26974 lines
886 KiB
Diff
26974 lines
886 KiB
Diff
diff -rupN binutils.orig/ld/NEWS binutils-2.41/ld/NEWS
|
||
--- binutils.orig/ld/NEWS 2024-05-13 13:03:48.141602288 +0100
|
||
+++ binutils-2.41/ld/NEWS 2024-05-13 13:04:43.757681506 +0100
|
||
@@ -1,5 +1,8 @@
|
||
-*- text -*-
|
||
|
||
+* Add --section-ordering-file <FILE> option to add extra mapping of input
|
||
+ sections to output sections.
|
||
+
|
||
* On RISC-V, add ld target option --[no-]check-uleb128. Should rebuild the
|
||
objects by binutils 2.42 and up if enabling the option and get warnings,
|
||
since the non-zero addend of SUB_ULEB128 shouldn't be generated from .uleb128
|
||
diff -rupN binutils.orig/ld/NEWS.orig binutils-2.41/ld/NEWS.orig
|
||
--- binutils.orig/ld/NEWS.orig 1970-01-01 01:00:00.000000000 +0100
|
||
+++ binutils-2.41/ld/NEWS.orig 2024-05-13 13:04:08.590633292 +0100
|
||
@@ -0,0 +1,991 @@
|
||
+-*- text -*-
|
||
+
|
||
+* On RISC-V, add ld target option --[no-]check-uleb128. Should rebuild the
|
||
+ objects by binutils 2.42 and up if enabling the option and get warnings,
|
||
+ since the non-zero addend of SUB_ULEB128 shouldn't be generated from .uleb128
|
||
+ directives.
|
||
+
|
||
+* Added --warn-execstack-objects to warn about executable stacks only when an
|
||
+ input object file requests one. Also added --error-execstack and
|
||
+ --error-rxw-segments options to convert warnings about executable stacks and
|
||
+ segments into errors.
|
||
+
|
||
+ Also added --enable-error-execstack=[yes|no] and
|
||
+ --enable-error-rwx-segments=[yes|no] configure options to set the default for
|
||
+ converting warnings into errors.
|
||
+
|
||
+Changes in 2.41:
|
||
+
|
||
+* The linker now accepts a command line option of --remap-inputs
|
||
+ <PATTERN>=<FILE> to relace any input file that matches <PATTERN> with
|
||
+ <FILE>. In addition the option --remap-inputs-file=<FILE> can be used to
|
||
+ specify a file containing any number of these remapping directives.
|
||
+
|
||
+* The linker command line option --print-map-locals can be used to include
|
||
+ local symbols in a linker map. (ELF targets only).
|
||
+
|
||
+* For most ELF based targets, if the --enable-linker-version option is used
|
||
+ then the version of the linker will be inserted as a string into the .comment
|
||
+ section.
|
||
+
|
||
+* The linker script syntax has a new command for output sections: ASCIZ "string"
|
||
+ This will insert a zero-terminated string at the current location.
|
||
+
|
||
+* Add command-line option, -z nosectionheader, to omit ELF section
|
||
+ header.
|
||
+
|
||
+Changes in 2.40:
|
||
+
|
||
+* The linker has a new command line option to suppress the generation of any
|
||
+ warning or error messages. This can be useful when there is a need to create
|
||
+ a known non-working binary. The option is -w or --no-warnings.
|
||
+
|
||
+* ld now supports zstd compressed debug sections. The new option
|
||
+ --compress-debug-sections=zstd compresses debug sections with zstd.
|
||
+
|
||
+* Add --enable-default-compressed-debug-sections-algorithm={zlib,zstd}
|
||
+ that selects the default compression algorithm
|
||
+ for --enable-compressed-debug-sections.
|
||
+
|
||
+* Remove support for -z bndplt (MPX prefix instructions).
|
||
+
|
||
+Changes in 2.39:
|
||
+
|
||
+* The ELF linker will now generate a warning message if the stack is made
|
||
+ executable. By default this warning is not issued if the user has
|
||
+ specifically requested an executable stack via the "-z execstack"
|
||
+ command line option, but the warning can be forced via the new
|
||
+ "--warn-execstack" option. Alternatively all warnings about creating
|
||
+ an executable stack can be suppressed via the "--no-warn-execstack"
|
||
+ option.
|
||
+
|
||
+ In addition the ELF linker will also warn if it creates a memory resident
|
||
+ segment with all three of the Read, Write and eXecute permissions set, or
|
||
+ if it creates a thread local data segment with the eXecute permission set.
|
||
+ These warnings can be disabled via --no-warn-rwx-segments option and
|
||
+ re-enabled via the --warn-rwx-segments option.
|
||
+
|
||
+ New configure options can also control these new features:
|
||
+
|
||
+ --enable-warn-execstack=no
|
||
+ will disable the warnings about creating an executable stack.
|
||
+
|
||
+ --enable-warn-execstack=yes
|
||
+ will make --warn-execstack enabled by default.
|
||
+
|
||
+ --enable-warn-rwx-segments=no
|
||
+ will make --no-warn-rwx-segments enabled by default.
|
||
+
|
||
+ --enable-default-execstack=no
|
||
+ will stop the creation of an executable stack simply because an input file
|
||
+ is missing a .note.GNU-stack section, even on architectures where this
|
||
+ behaviour is the default.
|
||
+
|
||
+* TYPE=<type> is now supported in an output section description to set the
|
||
+ section type value.
|
||
+
|
||
+* Remove (rudimentary) support for the x86-64 sub-architectures Intel L1OM and
|
||
+ Intel K1OM.
|
||
+
|
||
+* The ELF linker now supports a new --package-metadata option that allows
|
||
+ embedding a JSON payload in accordance to the Package Metadata specification.
|
||
+ If support for libjansson is enabled at build time, the linker will use it to
|
||
+ validate the input. This can be enabled with --enable-jansson.
|
||
+ For more details, see: https://systemd.io/ELF_PACKAGE_METADATA/
|
||
+
|
||
+Changes in 2.38:
|
||
+
|
||
+* Add -z pack-relative-relocs/-z no pack-relative-relocs to x86 ELF
|
||
+ linker to pack relative relocations in the DT_RELR section.
|
||
+
|
||
+* Add support for the LoongArch architecture.
|
||
+
|
||
+* Add -z indirect-extern-access/-z noindirect-extern-access to x86 ELF
|
||
+ linker to control canonical function pointers and copy relocation.
|
||
+
|
||
+* Add --max-cache-size=SIZE to set the the maximum cache size to SIZE
|
||
+ bytes.
|
||
+
|
||
+Changes in 2.37:
|
||
+
|
||
+* arm-symbianelf support removed.
|
||
+
|
||
+* Add -z report-relative-reloc to x86 ELF linker to report dynamic
|
||
+ relative relocations.
|
||
+
|
||
+* Add -z start-stop-gc to disable special treatment of __start_*/__stop_*
|
||
+ references when --gc-sections.
|
||
+
|
||
+* Add -Bno-symbolic to cancel -Bsymbolic and -Bsymbolic-functions.
|
||
+
|
||
+Changes in 2.36:
|
||
+
|
||
+* Add libdep plugin, for linking dependencies of static libraries that
|
||
+ were recorded by ar in the __.LIBDEP archive member.
|
||
+
|
||
+* Add --error-handling-script=<NAME> command line option to allow a helper
|
||
+ script to be invoked when an undefined symbol or a missing library is
|
||
+ encountered. This option can be suppressed via the configure time
|
||
+ switch: --enable-error-handling-script=no.
|
||
+
|
||
+* Add -z lam-u48 to x86-64 ELF linker to generate LAM_U48 property.
|
||
+
|
||
+* Add -z lam-u57 to x86-64 ELF linker to enerate LAM_U57 property.
|
||
+
|
||
+* Add -z lam-u48-report=[none|warning|error] to report missing LAM_U48
|
||
+ property.
|
||
+
|
||
+* Add -z lam-u57-report=[none|warning|error] to report missing LAM_U57
|
||
+ property.
|
||
+
|
||
+* Add -z lam-report=[none|warning|error] to report missing LAM_U48 and
|
||
+ LAM_U57 properties.
|
||
+
|
||
+* Add -z x86-64-{baseline|v[234]} to the x86 ELF linker to mark
|
||
+ x86-64-{baseline|v[234]} ISA level as needed.
|
||
+
|
||
+* Add -z unique-symbol to avoid duplicated local symbol names.
|
||
+
|
||
+* The creation of PE format DLLs now defaults to using a more secure set of DLL
|
||
+ characteristics.
|
||
+
|
||
+* The linker now deduplicates the types in .ctf sections. The new
|
||
+ command-line option --ctf-share-types describes how to do this:
|
||
+ its default value, share-unconflicted, produces the most compact
|
||
+ output.
|
||
+
|
||
+* The linker now omits the "variable section" from .ctf sections by
|
||
+ default, saving space. This is almost certainly what you want
|
||
+ unless you are working on a project that has its own analogue
|
||
+ of symbol tables that are not reflected in the ELF symtabs.
|
||
+
|
||
+* Add support for the SHF_GNU_RETAIN ELF section flag.
|
||
+ This flag specifies that the section should not be garbage collected by the
|
||
+ linker.
|
||
+
|
||
+Changes in 2.35:
|
||
+
|
||
+* X86 NaCl target support is removed.
|
||
+
|
||
+* Add ELF linker command-line options, --export-dynamic-symbol and
|
||
+ --export-dynamic-symbol-list, to make symbols dynamic.
|
||
+
|
||
+* Add a configure option, --enable-textrel-check=[no|yes|warning|error],
|
||
+ to decide what ELF linker should do by default with DT_TEXTREL in an
|
||
+ executable or shared library. Default to yes for Linux/x86 targets.
|
||
+
|
||
+* The -Map=<filename> command line option has been extended so that if
|
||
+ <filename> is a directory then <filename>/<output-filename>.map will be
|
||
+ created.
|
||
+
|
||
+* Add a command-line option for ELF linker, --warn-textrel, to warn that
|
||
+ DT_TEXTREL is set in a position-independent executable or shared object.
|
||
+
|
||
+* Add command-line options --enable-non-contiguous-regions and
|
||
+ --enable-non-contiguous-regions-warnings.
|
||
+
|
||
+* Add command-line option --imagic for the pdp11-aout target to output format
|
||
+ IMAGIC (0411) for separate instruction and data spaces, and change the
|
||
+ default format option for pdp11-aout to be --omagic.
|
||
+
|
||
+* Relative pathnames in INPUT() and GROUP() directives in linker scripts are
|
||
+ searched relative to the directory of the linker script before other search
|
||
+ paths.
|
||
+
|
||
+* Add ELF linker command-line option `-z start-stop-visibility=...' to control
|
||
+ the visibility of synthetic `__start_SECNAME` and `__stop_SECNAME` symbols.
|
||
+
|
||
+* Add command-line option --dependency-file to write a Make-style dependency
|
||
+ file listing the input files consulted by the linker, like the files written
|
||
+ by the compiler's -M -MP options.
|
||
+
|
||
+Changes in 2.34:
|
||
+
|
||
+* The ld check for "PHDR segment not covered by LOAD segment" is more
|
||
+ effective, catching cases that were wrongly allowed by previous versions of
|
||
+ ld. If you see this error it is likely you are linking with a bad linker
|
||
+ script or the binary you are building is not intended to be loaded by a
|
||
+ dynamic loader. In the latter case --no-dynamic-linker is appropriate.
|
||
+
|
||
+* cr16c support removed.
|
||
+
|
||
+* Add support for z80-elf.
|
||
+
|
||
+* Add support for relocation of each byte or word of multibyte value to Z80
|
||
+ targets.
|
||
+
|
||
+* Add support for Zilog eZ80 (both ADL and Z80 mode) and Zilog Z180 CPUs.
|
||
+
|
||
+Changes in 2.33:
|
||
+
|
||
+* Add command-line option --no-print-map-discarded.
|
||
+
|
||
+* The Cortex-A53 Erratum 843419 workaround now supports a choice of which
|
||
+ workaround to use. The option --fix-cortex-a53-843419 now takes an
|
||
+ optional argument --fix-cortex-a53-843419[=full|adr|adrp] which can be
|
||
+ used to force a particular workaround to be used. See --help for AArch64
|
||
+ for more details.
|
||
+
|
||
+* Add target handlers for AArch64 for ELF GNU program properties.
|
||
+
|
||
+* Add support for GNU_PROPERTY_AARCH64_FEATURE_1_BTI in ELF GNU program
|
||
+ properties in the AArch64 ELF linker.
|
||
+
|
||
+* Add support for GNU_PROPERTY_AARCH64_FEATURE_1_PAC in ELF GNU program
|
||
+ properties in the AArch64 ELF linker.
|
||
+
|
||
+* Add -z force-bti for AArch64 to enable GNU_PROPERTY_AARCH64_FEATURE_1_BTI
|
||
+ on output while warning about missing GNU_PROPERTY_AARCH64_FEATURE_1_BTI
|
||
+ on inputs and use PLTs protected with BTI.
|
||
+
|
||
+* Add -z pac-plt for AArch64 to pick PAC enabled PLTs.
|
||
+
|
||
+Changes in 2.32:
|
||
+
|
||
+* Report property change in linker map file when merging GNU properties.
|
||
+
|
||
+* Add support for the C-SKY processor series.
|
||
+
|
||
+* -t now doesn't report members within archives, unless -t is given twice.
|
||
+ A single -t is now more useful when generating a list of files that should be
|
||
+ packaged for a linker bug report. For example:
|
||
+ gcc hello.c -save-temps -Wl,-t | xargs realpath | sort | uniq > files
|
||
+ tar cJf test.tar.xz `cat files`
|
||
+
|
||
+Changes in 2.31:
|
||
+
|
||
+* Speed up direct linking with DLLs for Cygwin and Mingw targets.
|
||
+
|
||
+* Add a configure option --enable-separate-code to decide whether
|
||
+ -z separate-code should be enabled in ELF linker by default. Default
|
||
+ to yes for Linux/x86 targets. Note that -z separate-code can increase
|
||
+ disk and memory size.
|
||
+
|
||
+Changes in 2.30:
|
||
+
|
||
+* Add -z separate-code to generate separate code PT_LOAD segment.
|
||
+
|
||
+* Add "-z undefs" command-line option as the inverse of the "-z defs" option.
|
||
+
|
||
+* Add -z globalaudit command-line option to force audit libraries to be run
|
||
+ for every dynamic object loaded by an executable - provided that the loader
|
||
+ supports this functionality.
|
||
+
|
||
+* Tighten linker script grammar around file name specifiers to prevent the use
|
||
+ of SORT_BY_ALIGNMENT and SORT_BY_INIT_PRIORITY on filenames. These would
|
||
+ previously be accepted but had no effect.
|
||
+
|
||
+* The EXCLUDE_FILE directive can now be placed within any SORT_* directive
|
||
+ within input section lists.
|
||
+
|
||
+Changes in 2.29:
|
||
+
|
||
+* Support for -z shstk in the x86 ELF linker to generate
|
||
+ GNU_PROPERTY_X86_FEATURE_1_SHSTK in ELF GNU program properties.
|
||
+
|
||
+* Add support for GNU_PROPERTY_X86_FEATURE_1_SHSTK in ELF GNU program
|
||
+ properties in the x86 ELF linker.
|
||
+
|
||
+* Add support for GNU_PROPERTY_X86_FEATURE_1_IBT in ELF GNU program
|
||
+ properties in the x86 ELF linker.
|
||
+
|
||
+* Support for -z ibtplt in the x86 ELF linker to generate IBT-enabled
|
||
+ PLT.
|
||
+
|
||
+* Support for -z ibt in the x86 ELF linker to generate IBT-enabled
|
||
+ PLT as well as GNU_PROPERTY_X86_FEATURE_1_IBT in ELF GNU program
|
||
+ properties.
|
||
+
|
||
+* Add support for ELF SHF_GNU_MBIND and PT_GNU_MBIND_XXX.
|
||
+
|
||
+* Add support for ELF GNU program properties.
|
||
+
|
||
+* Add support for the Texas Instruments PRU processor.
|
||
+
|
||
+* When configuring for arc*-*-linux* targets the default linker emulation will
|
||
+ change if --with-cpu=nps400 is used at configure time.
|
||
+
|
||
+* Improve assignment of LMAs to orphan sections in some edge cases where a
|
||
+ mixture of both AT>LMA_REGION and AT(LMA) are used.
|
||
+
|
||
+* Orphan sections placed after an empty section that has an AT(LMA) will now
|
||
+ take an load memory address starting from LMA.
|
||
+
|
||
+* Section groups can now be resolved (the group deleted and the group members
|
||
+ placed like normal sections) at partial link time either using the new linker
|
||
+ option --force-group-allocation or by placing FORCE_GROUP_ALLOCATION into the
|
||
+ linker script.
|
||
+
|
||
+Changes in 2.28:
|
||
+
|
||
+* The EXCLUDE_FILE linker script construct can now be applied outside of the
|
||
+ section list in order for the exclusions to apply over all input sections in
|
||
+ the list.
|
||
+
|
||
+* Add support for the RISC-V architecture.
|
||
+
|
||
+* The command-line option --no-eh-frame-hdr can now be used in ELF based
|
||
+ linkers to disable the automatic generation of .eh_frame_hdr sections.
|
||
+
|
||
+* Add --in-implib=<infile> to the ARM linker to enable specifying a set of
|
||
+ Secure Gateway veneers that must exist in the output import library specified
|
||
+ by --out-implib=<outfile> and the address they must have. As such,
|
||
+ --in-implib is only supported in combination with --cmse-implib.
|
||
+
|
||
+* Extended the --out-implib=<file> option, previously restricted to x86 PE
|
||
+ targets, to any ELF based target. This allows the generation of an import
|
||
+ library for an ELF executable, which can then be used by another application
|
||
+ to link against the executable.
|
||
+
|
||
+Changes in 2.27:
|
||
+
|
||
+* Add a configure option --enable-relro to decide whether -z relro should
|
||
+ be enabled in ELF linker by default. Default to yes for all Linux
|
||
+ targets except FRV, HPPA, IA64 and MIPS. Note that -z relro can increase
|
||
+ disk and memory size.
|
||
+
|
||
+* Support for -z noreloc-overflow in the x86-64 ELF linker to disable
|
||
+ relocation overflow check.
|
||
+
|
||
+* Add -z common/-z nocommon options for ELF targets to control whether to
|
||
+ convert common symbols to the STT_COMMON type during a relocatable link.
|
||
+
|
||
+* Support for -z nodynamic-undefined-weak in the x86 ELF linker, which
|
||
+ avoids dynamic relocations against undefined weak symbols in executable.
|
||
+
|
||
+* The NOCROSSREFSTO command was added to the linker script language.
|
||
+
|
||
+* Add --no-apply-dynamic-relocs to the AArch64 linker to do not apply link-time
|
||
+ values for dynamic relocations.
|
||
+
|
||
+Changes in 2.26:
|
||
+
|
||
+* Add --fix-stm32l4xx-629360 to the ARM linker to enable a link-time
|
||
+ workaround for a bug in the bus matrix / memory controller for some of
|
||
+ the STM32 Cortex-M4 based products (STM32L4xx)
|
||
+
|
||
+* Add a configure option --enable-compressed-debug-sections={all,ld} to
|
||
+ decide whether DWARF debug sections should be compressed by default.
|
||
+
|
||
+* Add support for the ARC EM/HS, and ARC600/700 architectures.
|
||
+
|
||
+* Experimental support for linker garbage collection (--gc-sections)
|
||
+ has been enabled for COFF and PE based targets.
|
||
+
|
||
+* New command-line option for ELF targets to compress DWARF debug
|
||
+ sections, --compress-debug-sections=[none|zlib|zlib-gnu|zlib-gabi].
|
||
+
|
||
+* New command-line option, --orphan-handling=[place|warn|error|discard], to
|
||
+ adjust how orphan sections are handled. The default is 'place' which gives
|
||
+ the current behaviour, 'warn' and 'error' issue a warning or error
|
||
+ respectively when orphan sections are found, and 'discard' will discard all
|
||
+ orphan sections.
|
||
+
|
||
+* Add support for LLVM plugin.
|
||
+
|
||
+* Add --print-memory-usage option to report memory blocks usage.
|
||
+
|
||
+* Add --require-defined option, it's like --undefined except the new symbol
|
||
+ must be defined by the end of the link.
|
||
+
|
||
+Changes in 2.25:
|
||
+
|
||
+* PE binaries now once again contain real timestamps by default. To disable
|
||
+ the inclusion of a timestamp in a PE binary, use the --no-insert-timestamp
|
||
+ command-line option.
|
||
+
|
||
+* Replace support for openrisc and or32 with support for or1k.
|
||
+
|
||
+* Add support for the --build-id command-line option to COFF based targets.
|
||
+
|
||
+* x86/x86_64 pe-coff now supports the --build-id option.
|
||
+
|
||
+* Add support for the Andes NDS32.
|
||
+
|
||
+Changes in 2.24:
|
||
+
|
||
+* Add LOG2CEIL() builtin function to the linker script language
|
||
+
|
||
+* Add support for the Texas Instruments MSP430X processor.
|
||
+
|
||
+* Add support for Altera Nios II.
|
||
+
|
||
+* Add support for the V850E3V5 architecture.
|
||
+
|
||
+* Add support for the Imagination Technologies Meta processor.
|
||
+
|
||
+* --enable-new-dtags no longer generates old dtags in addition to new dtags.
|
||
+
|
||
+* Remove linker support for MIPS ECOFF targets.
|
||
+
|
||
+* Add ALIGN_WITH_INPUT to the linker script language to force the alignment of
|
||
+ an output section to use the maximum alignment of all its input sections.
|
||
+
|
||
+Changes in 2.23:
|
||
+
|
||
+* Enable compressed debug section feature for x86/x86_64 pe-coff.
|
||
+
|
||
+* Add support for the 64-bit ARM architecture: AArch64.
|
||
+
|
||
+* Added SORT_NONE to the linker script language to disable section sorting.
|
||
+
|
||
+* Add a linker-provided symbol when producing ELF output, '__ehdr_start'
|
||
+ to point to the ELF file header (and nearby program headers) in the
|
||
+ program's memory image.
|
||
+
|
||
+* Add support for S12X processor.
|
||
+
|
||
+* Add support for the VLE extension to the PowerPC architecture.
|
||
+
|
||
+* Add support for the Freescale XGATE architecture.
|
||
+
|
||
+* Add option -f FILE on AIX (for response file).
|
||
+
|
||
+* Add support for the Renesas RL78 architecture.
|
||
+
|
||
+* Add support for the Adapteva EPIPHANY architecture.
|
||
+
|
||
+Changes in 2.22:
|
||
+
|
||
+* --copy-dt-needed-entries is no longer enabled by default. Instead
|
||
+ --no-copy-dt-needed-entries is the default.
|
||
+
|
||
+* INPUT_SECTION_FLAGS has been added to the linker script language
|
||
+ to allow selection of input sections by section header section flags.
|
||
+
|
||
+* Add support for the Tilera TILEPro and TILE-Gx architectures.
|
||
+
|
||
+* Added SORT_BY_INIT_PRIORITY to the linker script language to permit
|
||
+ sorting sections by numerical value of the GCC init_priority attribute
|
||
+ encoded in the section name.
|
||
+
|
||
+Changes in 2.21:
|
||
+
|
||
+* Linker script expression evaluation is somewhat more sane. This may
|
||
+ break scripts that depend on quirks of the old expression evaluation.
|
||
+
|
||
+* Turn off underscoring for x86_64 PE+-COFF targets. For old behavior the
|
||
+ option --enable-leading-mingw64-underscores can be used on configure of
|
||
+ bfd.
|
||
+
|
||
+* Add support for the TMS320C6000 (TI C6X) processor family.
|
||
+
|
||
+* --add-needed renamed to --copy-dt-needed-entries in order to avoid confusion
|
||
+ with --as-needed option.
|
||
+
|
||
+* Extend .def file syntax by '== <ID>' for imports and exports. This allows
|
||
+ to alias the import/export table name written in PE image.
|
||
+
|
||
+* Add --exclude-all-symbols option to PE based linkers. This prevents all
|
||
+ symbols from automatically being exported.
|
||
+
|
||
+* Add support for the Renesas RX processor.
|
||
+
|
||
+* Add support for alpha-vms target.
|
||
+
|
||
+Changes in 2.20:
|
||
+
|
||
+* GNU/Linux targets now support the STB_GNU_UNIQUE symbol binding. This is a
|
||
+ GNU extension to the standard set of ELF symbol bindings. The binding will
|
||
+ be passed on to the dynamic linker which will make sure that in the entire
|
||
+ process there is just one symbol with the given name and type in use.
|
||
+
|
||
+* PE targets now support a GNU extension to allow the alignment of common
|
||
+ common symbols to be specified. This support uses custom options in
|
||
+ the .drectve section, which will be disregarded by the native tools.
|
||
+
|
||
+* PE targets now add primitive support for ELF version scripts; symbols
|
||
+ are not versioned, but the local and global symbol visibility directives
|
||
+ are respected when filtering symbols in auto-export mode.
|
||
+
|
||
+* New option --no-export-dynamic to undo the effect of the -E and
|
||
+ --export-dynamic options.
|
||
+
|
||
+* ELF: --warn-alternate-em option to warn if an object has alternate
|
||
+ ELF machine code.
|
||
+
|
||
+* New script function REGION_ALIAS to add alias names to memory regions.
|
||
+
|
||
+* PE targets no longer make use of the long section names PE extension to
|
||
+ the COFF format when generating executable images, by default. The old
|
||
+ (slightly non-conformant) behaviour can still be invoked by using the
|
||
+ new '--enable-long-section-names' command-line option. It is also enabled
|
||
+ automatically in the presence of un-stripped debug information, as GDB
|
||
+ needs to be able to find the debug info sections by their full names.
|
||
+
|
||
+* For GNU/Linux systems the linker will now avoid processing any relocations
|
||
+ made against symbols of the STT_GNU_IFUNC type and instead emit them into
|
||
+ the resulting binary for processing by the loader.
|
||
+
|
||
+* --as-needed now links in a dynamic library if it satisfies undefined
|
||
+ symbols in regular objects, or in other dynamic libraries. In the
|
||
+ latter case the library is not linked if it is found in a DT_NEEDED
|
||
+ entry of one of the libraries already linked.
|
||
+
|
||
+* Add a new command-line option, -Ttext-segment ADDR, for ELF targets
|
||
+ to set the address of the first byte of the text segment.
|
||
+
|
||
+* Add support for Sunplus score architecture.
|
||
+
|
||
+* Add new option --use-nul-prefixed-import-tables to ld for PE targets to
|
||
+ allow fallback to old import table generation with null element prefix.
|
||
+
|
||
+* Windows PE systems now support a new --exclude-modules-for-implib option,
|
||
+ allowing users to partition object files and archive members between a DLL
|
||
+ and its associated import library as they are generated during linking.
|
||
+
|
||
+* Add support for Lattice Mico32 (lm32) architecture.
|
||
+
|
||
+* Add CR16 ELF --embedded-relocs (used to embedded relocations into binaries
|
||
+ for Embedded-PIC code) option.
|
||
+
|
||
+* Add to the PE/PE+ targets the support of two different kinds of
|
||
+ pseudo-relocations. They can be selected by the switches
|
||
+ --enable-runtime-pseudo-reloc-v1 and --enable-runtime-pseudo-reloc-v2.
|
||
+ For the switch --enable-runtime-pseudo-reloc it uses for 32-bit
|
||
+ runtime pseudo relocation version one, for 64-bit the version two.
|
||
+
|
||
+Changes in 2.19:
|
||
+
|
||
+* Linker scripts support a new INSERT command that makes it easier to
|
||
+ augment the default script.
|
||
+
|
||
+* Linker script input section filespecs may now specify a file within an
|
||
+ archive by writing "archive:file".
|
||
+
|
||
+* The --sort-common switch now has an optional argument which specifies the
|
||
+ direction of sorting.
|
||
+
|
||
+* The M68K linker now supports multiple GOT generation schemes controlled via
|
||
+ the --got=<type> command-line option.
|
||
+
|
||
+* The ARM EABI linker will now generate stubs for function calls to symbols
|
||
+ that are too far away. The placement of the stubs is controlled by a new
|
||
+ linker command-line option: --stub-group-size=N.
|
||
+
|
||
+Changes in 2.18:
|
||
+
|
||
+* Linker sources now released under version 3 of the GNU General Public
|
||
+ License.
|
||
+
|
||
+* ELF: New --build-id option to generate a unique per-binary identifier
|
||
+ embedded in a note section.
|
||
+
|
||
+* Added support for National Semicondutor CompactRISC (ie CR16) target.
|
||
+
|
||
+* -l:foo now searches the library path for a filename called foo,
|
||
+ without converting it to libfoo.a or libfoo.so.
|
||
+
|
||
+* Add a new command-line option '--default-script=FILE' or '-dT FILE'
|
||
+ which specifies a replacement for the built in, default linker
|
||
+ script.
|
||
+
|
||
+* ELF: Add -Bsymbolic-functions, --dynamic-list-cpp-new, which puts C++
|
||
+ operator new and delete on the dynamic list, and --dynamic-list-data,
|
||
+ builtin list for --dynamic-list, which puts global data symbols on the
|
||
+ dynamic list.
|
||
+
|
||
+* Add support for x86_64 PE+ target.
|
||
+
|
||
+* Add support for Score target.
|
||
+
|
||
+* ELF: Add --dynamic-list option to specify a list of global symbols
|
||
+ whose references shouldn't be bound to the definition within the
|
||
+ shared library, or a list of symbols which should be added to the
|
||
+ symbol table in the executable.
|
||
+
|
||
+* The default output section LMA has changed for allocatable sections from
|
||
+ being equal to VMA, to keeping the difference between LMA and VMA the same as
|
||
+ the previous output section in the same region. This is a more useful
|
||
+ default when using overlays and other cases where you specify an LMA
|
||
+ differing from the VMA for some sections.
|
||
+
|
||
+* New switch: --print-gc-sections to list any sections removed by garabge
|
||
+ collection.
|
||
+
|
||
+* ARM: Added --vfp11-denorm-fix option to work around an erratum in current
|
||
+ VFP11 coprocessors.
|
||
+
|
||
+Changes in 2.17:
|
||
+
|
||
+* Support for the Infineon XC16X has been added by KPIT Cummins Infosystems.
|
||
+
|
||
+* Modify the Linux linker search order to better match ld.so search order.
|
||
+ Look for DT_NEEDED libraries in paths specified by ld.so.conf before
|
||
+ searching the default directories, rather than vice versa.
|
||
+ Use $prefix/etc/ld.so.conf if it exists, otherwise /etc/ld.so.conf.
|
||
+
|
||
+* PE-COFF: Forward exports from DLL's can now be specified in .def files
|
||
+ passed directly to ld.
|
||
+
|
||
+* Support for the Z80 processor family has been added.
|
||
+
|
||
+* Add support for the "@<file>" syntax to the command line, so that extra
|
||
+ switches can be read from <file>.
|
||
+
|
||
+Changes in 2.16:
|
||
+
|
||
+* Support for the R_ARM_V4BX relocation as defined in the ARM AAELF
|
||
+ specification has been added via the --fix-v4bx command-line option.
|
||
+
|
||
+* New linker script construct AS_NEEDED(), which sets the --as-needed flag
|
||
+ for input files listed inside of it.
|
||
+
|
||
+* A new command-line option, --sysroot, can be used to override the
|
||
+ default sysroot location. It only applies to toolchains that were
|
||
+ configured using --with-sysroot.
|
||
+
|
||
+* New linker script functions: ORIGIN() and LENGTH() which return information
|
||
+ about a specified memory region.
|
||
+
|
||
+* Port to MAXQ processor contributed by HCL Tech.
|
||
+
|
||
+* Added SEGMENT_START to the linker script language to permit the user to
|
||
+ override the base address for a segment from the command-line.
|
||
+
|
||
+* ELF: --warn-shared-textrel option to warn if adding a DT_TEXTREL to a shared
|
||
+ object.
|
||
+
|
||
+* Added SORT_BY_NAME and SORT_BY_ALIGNMENT to the linker script
|
||
+ language to permit sorting sections by section name or section
|
||
+ maximum alignment.
|
||
+
|
||
+* Added a new linker command-line switch, --sort-section name|alignment,
|
||
+ to sort sections by section name or maximum alignment.
|
||
+
|
||
+* ELF: --add-needed/--no-add-needed options to control if a DT_NEEDED tag
|
||
+ should be added when a shared library comes from DT_NEEDED tags.
|
||
+
|
||
+* Support for the crx-elf target added.
|
||
+
|
||
+* Support for the sh-symbianelf target added.
|
||
+
|
||
+* A new linker command-line switch has been added which allows the hash table
|
||
+ size to be set to a suitable prime value near to its argument. This switch
|
||
+ is --hash-size=<NUMBER>. Also if the switch --reduce-memory-overheads is
|
||
+ used, and --hash-size has not been used, then the default value will be set
|
||
+ to 1021.
|
||
+
|
||
+* Linker map files are now generated with an O(N) algorithm for finding symbols
|
||
+ that are defined in each section. This uses about 40% more memory for
|
||
+ symbols than the old O(N^2) algorithm. You can use the new
|
||
+ --reduce-memory-overheads option to select the old algorithm; this option
|
||
+ might also be used in the future to select similar tradeoffs.
|
||
+
|
||
+Changes in 2.15:
|
||
+
|
||
+* ELF: --as-needed/--no-as-needed options to control if a DT_NEEDED tag should
|
||
+ be added only when a shared library is referenced.
|
||
+
|
||
+* PE: --large-address-aware option to indicate executables support virtual
|
||
+ addresses greater than 2 gigabytes.
|
||
+
|
||
+* DWARF 2 support for i386pe added.
|
||
+
|
||
+* The linker script operator DEFINED() will now yield 1 only for a symbol that
|
||
+ is defined before the statement where DEFINED is used.
|
||
+
|
||
+* The MIPS --embedded-relocs (used to embed relocations into binaries for
|
||
+ Embedded-PIC code) is deprecated and will be removed in a future release.
|
||
+
|
||
+* cr16c support added by NSC.
|
||
+
|
||
+* m32r Linux (ELF) support added by Renesas.
|
||
+
|
||
+* Improved linker's handling of unresolved symbols. The switch
|
||
+ --unresolved-symbols=<method> has been added to tell the linker when it
|
||
+ should report them and the switch --warn-unresolved-symbols has been added to
|
||
+ make reports be issued as warning messages rather than errors.
|
||
+
|
||
+Changes in 2.14:
|
||
+
|
||
+* Added support for Xtensa architecture.
|
||
+
|
||
+* Added --with-sysroot configure switch to specify a target system root, for
|
||
+ linking against a target filesystem image.
|
||
+
|
||
+* Added --accept-unknown-linker-format to restore old linker behaviour (pre
|
||
+ 2.14) of silently accepting and linking in any files in an unknown binary
|
||
+ file format.
|
||
+
|
||
+* Added --no-omagic to undo the effects of the -N option.
|
||
+
|
||
+* Support for Texas Instruments TMS320C4x and TMS320C3x series of
|
||
+ DSP's contributed by Michael Hayes and Svein E. Seldal.
|
||
+
|
||
+* Added --with-lib-path configure switch to specify default value for
|
||
+ LIB_PATH.
|
||
+
|
||
+* ARM port to QNX operating system added by Graeme Peterson.
|
||
+
|
||
+* IP2K support added by Denis Chertykov.
|
||
+
|
||
+Changes in 2.13:
|
||
+
|
||
+* Support for the Fujitsu FRV architecture added by Red Hat. Models for FR400
|
||
+ and FR500 included.
|
||
+
|
||
+Changes in version 2.13:
|
||
+
|
||
+* DEC VAX ELF support, by Matt Thomas.
|
||
+
|
||
+Changes in version 2.12:
|
||
+
|
||
+* Support for Don Knuth's MMIX, by Hans-Peter Nilsson.
|
||
+
|
||
+* Support for the OpenRISC 32-bit embedded processor by OpenCores.
|
||
+
|
||
+* Support for -z nocopyreloc in the x86 ELF linker, which disables
|
||
+ production of copy relocs. Warning: using this option may result in
|
||
+ non-sharable applications.
|
||
+
|
||
+* Support for -z combreloc in the ELF linker, which puts dynamic
|
||
+ relocations against the same symbol together, so that dynamic linker
|
||
+ can use an one-entry symbol lookup cache.
|
||
+
|
||
+* Support for ELF SHF_MERGE section merging, by Jakub Jelinek.
|
||
+
|
||
+Changes in version 2.11:
|
||
+
|
||
+* Support for AMD x86-64 architecture, by Jan Hubicka, SuSE Labs.
|
||
+
|
||
+* Support added for eliminating duplicate DWARF2 debug information by
|
||
+ having the compiler generate the information in sections called
|
||
+ .gnu.linkonce.wi.XXXX where XXXX is a checksum for the contents. The
|
||
+ linker then merges these sections together into the normal .debug_info
|
||
+ section.
|
||
+
|
||
+* The native ELF linker now searches the directories in DT_RUNPATH or
|
||
+ DT_RPATH of a shared library for shared libraries needed by it.
|
||
+
|
||
+* TI C54x support, by Timothy Wall.
|
||
+
|
||
+* Added command-line switch --section-start to set the start address of any
|
||
+ specified section.
|
||
+
|
||
+* Added ability to emit full relocation information in linked executables,
|
||
+ enabled by --emit-relocs. Some post-linkage optimization tools need
|
||
+ this information in order to be able to correctly identify and perform
|
||
+ symbol relative addressing in the event of changes in section contents
|
||
+ (instructions being added or deleted, extending data sections, etc.)
|
||
+
|
||
+* Support for i860, by Jason Eckhardt (preliminary, alpha quality).
|
||
+
|
||
+* Support for CRIS (Axis Communications ETRAX series).
|
||
+
|
||
+* Support for PDP-11 and 2.11BSD a.out format, by Lars Brinkhoff.
|
||
+
|
||
+Changes in version 2.10:
|
||
+
|
||
+* Added AT> to the linker script language to allow load-time allocation of
|
||
+ sections into regions.
|
||
+
|
||
+* Added garbage collection of unused sections, enabled by --gc-sections.
|
||
+ It does require a bit of backend support; currently implemented are
|
||
+ arm-elf, avr-elf, d10v-elf, fr30-elf, i386-elf, m32r-elf, m68k-elf,
|
||
+ mcore-elf, mips-elf, mn10300-elf, ppc-elf, sh-elf, sparc-elf, and v850-elf.
|
||
+ Others will ignore the option.
|
||
+
|
||
+* Added SORT to the linker script language to permit sorting sections by file
|
||
+ name or section name.
|
||
+
|
||
+* Added EXTERN to the linker script language as an equivalent to the -u
|
||
+ command-line option.
|
||
+
|
||
+* Added ASSERT to the linker script language.
|
||
+
|
||
+* Added EXCLUDE_FILE to the linker script language for further control over
|
||
+ wildcard file names.
|
||
+
|
||
+* Added -O option to optimize linker output (as of this writing, this only
|
||
+ affects ELF shared library generation).
|
||
+
|
||
+* The -e option now accepts a number as well as a symbol name.
|
||
+
|
||
+* Added --no-undefined option to disallow undefined symbols when creating a
|
||
+ shared library.
|
||
+
|
||
+* The linker now issues a warning, not an error, for an undefined symbol when
|
||
+ using -Bsymbolic; use the new --no-undefined option to get the old
|
||
+ behaviour.
|
||
+
|
||
+* Added --demangle and --no-demangle options.
|
||
+
|
||
+Changes in version 2.9:
|
||
+
|
||
+* Added SQUAD to the linker script language.
|
||
+
|
||
+* New option --no-warn-mismatch.
|
||
+
|
||
+* The MEMORY command now parses the attributes to determine where sections that
|
||
+ are not placed in a specific memory region are placed.
|
||
+
|
||
+Changes in version 2.8:
|
||
+
|
||
+* Linker scripts may now contain shell wildcard characters for file and section
|
||
+ names.
|
||
+
|
||
+* The linker now supports symbol versions in ELF.
|
||
+
|
||
+* The NOCROSSREFS command was added to the linker script language.
|
||
+
|
||
+* The LOADADDR expression was added to the linker script language.
|
||
+
|
||
+* MAX and MIN functions were added to the linker script language.
|
||
+
|
||
+* The OVERLAY construct was added to the linker script language.
|
||
+
|
||
+* New option --warn-section-align to warn when the address of an output section
|
||
+ changes due to alignment of an input section.
|
||
+
|
||
+* New options --filter/-F and --auxiliary/-f.
|
||
+
|
||
+Changes in version 2.7:
|
||
+
|
||
+* New option --cref to print out a cross reference table.
|
||
+
|
||
+* New option --wrap SYMBOL.
|
||
+
|
||
+* New option --no-whole-archive, to turn off the effect of --whole-archive.
|
||
+
|
||
+* Input sections assigned to the output section /DISCARD/ in the linker script
|
||
+ are not included in the output file.
|
||
+
|
||
+* The SunOS and ELF linkers now merge stabs debugging information which uses
|
||
+ the N_BINCL and N_EINCL stab types. This reduces the amount of debugging
|
||
+ information generated.
|
||
+
|
||
+Changes in version 2.6:
|
||
+
|
||
+* When an ELF section name is representable as a C identifier (this is not true
|
||
+of most ELF section names), the linker will automatically define symbols
|
||
+__start_SECNAME and __stop_SECNAME, where SECNAME is the section name, at the
|
||
+beginning and the end of the section. This is used by glibc.
|
||
+
|
||
+ Addendum: Current versions of the linker (at least for version 2.18 onwards
|
||
+and possibly much earlier as well) place two restrictions on this feature: The
|
||
+symbols are only implemented for orphaned sections, not for explicitly placed
|
||
+sections and they are PROVIDEd rather than being defined.
|
||
+
|
||
+* When an ELF section named .gnu.warning is encountered in an input file, the
|
||
+contents of the section are displayed as an error message, and the section is
|
||
+not copied into the output file. This is used by glibc.
|
||
+
|
||
+* When an ELF section named .gnu.warning.SYMBOL is encountered in an input
|
||
+file, and the symbol SYMBOL is referenced by some object file, the contents of
|
||
+the section are displayed as an error message. The section is not copied into
|
||
+the output file, unless doing a relocatable or shared link. This is used by
|
||
+glibc.
|
||
+
|
||
+* New options -split-by-reloc and -split-by-file.
|
||
+
|
||
+* The linker now supports linking PIC compiled code on SPARC SunOS. It can
|
||
+also create SPARC SunOS shared libraries, and, like the native SunOS linker,
|
||
+will do so whenever there is an undefined symbol in the link and neither the -e
|
||
+nor the -r option was used.
|
||
+
|
||
+* The -rpath option may be used on SunOS to set the list of directories to be
|
||
+searched at run time. This overrides the default of building the list from the
|
||
+-L options.
|
||
+
|
||
+* The COFF linker now combines debugging information for structs, unions, and
|
||
+enums, so that even if the same type is defined in multiple input files it will
|
||
+only be defined once in the output file. The --traditional-format switch will
|
||
+prevent this optimization.
|
||
+
|
||
+Changes in version 2.5:
|
||
+
|
||
+* The linker now supports linking against SunOS shared libraries. It still can
|
||
+not link SunOS PIC (Position Independent Code) files, so it can not be used to
|
||
+generate shared libraries.
|
||
+
|
||
+* The linker now supports linking against ELF shared libraries for the i386
|
||
+(UnixWare) and SPARC (Solaris). It can also link ELF PIC files, and can be
|
||
+used to generate shared libraries. Shared library generation is not well
|
||
+tested; please report any problems encountered. The linker is now enabled for
|
||
+Solaris again.
|
||
+
|
||
+* Eric Youngdale has contributed Linux support code, including linking against
|
||
+Linux a.out shared libraries. The linker produces Linux QMAGIC binaries.
|
||
+
|
||
+* The ELF backend has been converted to the new linker code. To use the new
|
||
+ELF linker, each particular target requires a relocation function. So far,
|
||
+this function has been written for i386 (UnixWare), SPARC (Solaris) MIPS (Irix
|
||
+5), and HPPA ELF targets.
|
||
+
|
||
+* The -( (--start-group) and -) (--end-group) options have been added to
|
||
+support searching a group of archives as though they were a single archive.
|
||
+This can also be used in a linker script, as GROUP ( files ).
|
||
+
|
||
+* When a file is named on the command line, and the linker does not recognize
|
||
+it as an object file, the linker will now treat the file as a linker script
|
||
+file. A linker script named in this way augments, but does not replace, the
|
||
+default linker script.
|
||
+
|
||
+* The -warn-once option was added. It causes the linker to only warn once per
|
||
+undefined symbol, rather than once per reference.
|
||
+
|
||
+* The COFF backend has been converted to the new linker code. As with ELF, to
|
||
+use the new linker, each particular target requires a relocation function. So
|
||
+far, this function has been written for the i386, m68k, a29k and SH targets.
|
||
+
|
||
+* The -V flag was made a synonym for -v, for SVR4 compatibility. The old -V
|
||
+behaviour is available via --verbose.
|
||
+
|
||
+Changes in version 2.4:
|
||
+
|
||
+* New linker code, by Steve Chamberlain and Ian Taylor. For a.out and ecoff
|
||
+ formats (so far), this should result in considerable savings in time
|
||
+ and memory used while linking; slightly poorer performance than
|
||
+ before for formats not converted yet.
|
||
+
|
||
+* Command-line parsing is no longer done with flex. This means
|
||
+ oddball characters in filenames won't get treated as argument
|
||
+ separators.
|
||
+
|
||
+* HP-PA ELF support, by Jeff Law. (No SOM support yet.)
|
||
+
|
||
+* Mach i386 support, by David Mackenzie.
|
||
+
|
||
+* Irix 4 shared libraries are now supported (Irix 5 uses ELF, and ELF shared
|
||
+ libraries are not yet supported).
|
||
+
|
||
+* COFF shared libraries (as on SCO) should work as well.
|
||
+
|
||
+* The linker is disabled for Solaris. (Actually, it was in 2.3 also, I just
|
||
+ forgot to note it.) Some of their C library routines don't work when
|
||
+ statically linked, and the GNU linker doesn't support dynamic linking yet.
|
||
+
|
||
+Changes in version 2.3:
|
||
+
|
||
+* Weak symbols are now supported.
|
||
+
|
||
+* ELF support has been added. The linker has been bootstrapped on
|
||
+ UnixWare and Solaris.
|
||
+
|
||
+* Alpha OSF/1 support has been added (non dynamic linking only).
|
||
+
|
||
+Changes in version 2.2:
|
||
+
|
||
+* The `bfd' library has been updated to reduce a.out-format string
|
||
+ table size. The effect of this is that files linked from many input
|
||
+ files with duplicate symbols (`-g' debugging records, or identical
|
||
+ static symbols) should be much smaller.
|
||
+
|
||
+Changes in version 2.1:
|
||
+
|
||
+* The ld -ySYMBOL flag (to trace references to SYMBOL) is now implemented.
|
||
+
|
||
+* There is now support for writing ECOFF files, so ld and the
|
||
+ other utilities should work on Risc/Ultrix and Irix.
|
||
+
|
||
+
|
||
+Copyright (C) 2012-2023 Free Software Foundation, Inc.
|
||
+
|
||
+Copying and distribution of this file, with or without modification,
|
||
+are permitted in any medium without royalty provided the copyright
|
||
+notice and this notice are preserved.
|
||
+
|
||
+Local variables:
|
||
+fill-column: 79
|
||
+End:
|
||
diff -rupN binutils.orig/ld/NEWS.rej binutils-2.41/ld/NEWS.rej
|
||
--- binutils.orig/ld/NEWS.rej 1970-01-01 01:00:00.000000000 +0100
|
||
+++ binutils-2.41/ld/NEWS.rej 2024-05-13 13:04:08.590633292 +0100
|
||
@@ -0,0 +1,11 @@
|
||
+--- ld/NEWS
|
||
++++ ld/NEWS
|
||
+@@ -1,5 +1,8 @@
|
||
+ -*- text -*-
|
||
+
|
||
++* Add --section-ordering-file <FILE> option to add extra mapping of input
|
||
++ sections to output sections.
|
||
++
|
||
+ * Add -plugin-save-temps to store plugin intermediate files permanently.
|
||
+
|
||
+ Changes in 2.42:
|
||
diff -rupN binutils.orig/ld/ld.h binutils-2.41/ld/ld.h
|
||
--- binutils.orig/ld/ld.h 2024-05-13 13:03:47.798601768 +0100
|
||
+++ binutils-2.41/ld/ld.h 2024-05-13 13:04:08.591633294 +0100
|
||
@@ -193,6 +193,9 @@ typedef struct
|
||
|
||
/* Default linker script. */
|
||
char *default_script;
|
||
+
|
||
+ /* Linker script fragment provided by the --section-order command line option. */
|
||
+ char *section_ordering_file;
|
||
} args_type;
|
||
|
||
extern args_type command_line;
|
||
@@ -319,6 +322,7 @@ extern ld_config_type config;
|
||
|
||
extern FILE * saved_script_handle;
|
||
extern bool force_make_executable;
|
||
+extern bool in_section_ordering;
|
||
|
||
extern int yyparse (void);
|
||
extern void add_cref (const char *, bfd *, asection *, bfd_vma);
|
||
diff -rupN binutils.orig/ld/ld.h.orig binutils-2.41/ld/ld.h.orig
|
||
--- binutils.orig/ld/ld.h.orig 1970-01-01 01:00:00.000000000 +0100
|
||
+++ binutils-2.41/ld/ld.h.orig 2023-07-03 00:00:00.000000000 +0100
|
||
@@ -0,0 +1,338 @@
|
||
+/* ld.h -- general linker header file
|
||
+ Copyright (C) 1991-2023 Free Software Foundation, Inc.
|
||
+
|
||
+ This file is part of the GNU Binutils.
|
||
+
|
||
+ This program is free software; you can redistribute it and/or modify
|
||
+ it under the terms of the GNU General Public License as published by
|
||
+ the Free Software Foundation; either version 3 of the License, or
|
||
+ (at your option) any later version.
|
||
+
|
||
+ This program is distributed in the hope that it will be useful,
|
||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
+ GNU General Public License for more details.
|
||
+
|
||
+ You should have received a copy of the GNU General Public License
|
||
+ along with this program; if not, write to the Free Software
|
||
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
|
||
+ MA 02110-1301, USA. */
|
||
+
|
||
+#ifndef LD_H
|
||
+#define LD_H
|
||
+
|
||
+#ifndef SEEK_CUR
|
||
+#define SEEK_CUR 1
|
||
+#endif
|
||
+#ifndef SEEK_END
|
||
+#define SEEK_END 2
|
||
+#endif
|
||
+
|
||
+#ifndef ENABLE_NLS
|
||
+ /* The Solaris version of locale.h always includes libintl.h. If we have
|
||
+ been configured with --disable-nls then ENABLE_NLS will not be defined
|
||
+ and the dummy definitions of bindtextdomain (et al) below will conflict
|
||
+ with the defintions in libintl.h. So we define these values to prevent
|
||
+ the bogus inclusion of libintl.h. */
|
||
+# define _LIBINTL_H
|
||
+# define _LIBGETTEXT_H
|
||
+#endif
|
||
+#include <locale.h>
|
||
+
|
||
+#ifdef ENABLE_NLS
|
||
+# include <libintl.h>
|
||
+# define _(String) gettext (String)
|
||
+# ifdef gettext_noop
|
||
+# define N_(String) gettext_noop (String)
|
||
+# else
|
||
+# define N_(String) (String)
|
||
+# endif
|
||
+#else
|
||
+# define gettext(Msgid) (Msgid)
|
||
+# define dgettext(Domainname, Msgid) (Msgid)
|
||
+# define dcgettext(Domainname, Msgid, Category) (Msgid)
|
||
+# define ngettext(Msgid1, Msgid2, n) \
|
||
+ (n == 1 ? Msgid1 : Msgid2)
|
||
+# define dngettext(Domainname, Msgid1, Msgid2, n) \
|
||
+ (n == 1 ? Msgid1 : Msgid2)
|
||
+# define dcngettext(Domainname, Msgid1, Msgid2, n, Category) \
|
||
+ (n == 1 ? Msgid1 : Msgid2)
|
||
+# define textdomain(Domainname) do {} while (0)
|
||
+# define bindtextdomain(Domainname, Dirname) do {} while (0)
|
||
+# define _(String) (String)
|
||
+# define N_(String) (String)
|
||
+#endif
|
||
+
|
||
+/* Look in this environment name for the linker to pretend to be */
|
||
+#define EMULATION_ENVIRON "LDEMULATION"
|
||
+/* If in there look for the strings: */
|
||
+
|
||
+/* Look in this variable for a target format */
|
||
+#define TARGET_ENVIRON "GNUTARGET"
|
||
+
|
||
+/* Input sections which are put in a section of this name are actually
|
||
+ discarded. */
|
||
+#define DISCARD_SECTION_NAME "/DISCARD/"
|
||
+
|
||
+/* A file name list. */
|
||
+typedef struct name_list
|
||
+{
|
||
+ const char *name;
|
||
+ struct name_list *next;
|
||
+}
|
||
+name_list;
|
||
+
|
||
+typedef enum {sort_none, sort_ascending, sort_descending} sort_order;
|
||
+
|
||
+/* A wildcard specification. */
|
||
+
|
||
+typedef enum
|
||
+{
|
||
+ none, by_name, by_alignment, by_name_alignment, by_alignment_name,
|
||
+ by_none, by_init_priority
|
||
+} sort_type;
|
||
+
|
||
+extern sort_type sort_section;
|
||
+
|
||
+struct wildcard_spec
|
||
+{
|
||
+ const char *name;
|
||
+ struct name_list *exclude_name_list;
|
||
+ struct flag_info *section_flag_list;
|
||
+ size_t namelen, prefixlen, suffixlen;
|
||
+ sort_type sorted;
|
||
+};
|
||
+
|
||
+struct wildcard_list
|
||
+{
|
||
+ struct wildcard_list *next;
|
||
+ struct wildcard_spec spec;
|
||
+};
|
||
+
|
||
+#define BYTE_SIZE (1)
|
||
+#define SHORT_SIZE (2)
|
||
+#define LONG_SIZE (4)
|
||
+#define QUAD_SIZE (8)
|
||
+
|
||
+enum endian_enum { ENDIAN_UNSET = 0, ENDIAN_BIG, ENDIAN_LITTLE };
|
||
+
|
||
+typedef struct
|
||
+{
|
||
+ /* 1 => assign space to common symbols even if `relocatable_output'. */
|
||
+ bool force_common_definition;
|
||
+
|
||
+ /* If TRUE, build MIPS embedded PIC relocation tables in the output
|
||
+ file. */
|
||
+ bool embedded_relocs;
|
||
+
|
||
+ /* If TRUE, force generation of a file with a .exe file. */
|
||
+ bool force_exe_suffix;
|
||
+
|
||
+ /* If TRUE, generate a cross reference report. */
|
||
+ bool cref;
|
||
+
|
||
+ /* If TRUE (which is the default), warn about mismatched input
|
||
+ files. */
|
||
+ bool warn_mismatch;
|
||
+
|
||
+ /* Warn on attempting to open an incompatible library during a library
|
||
+ search. */
|
||
+ bool warn_search_mismatch;
|
||
+
|
||
+ /* If non-zero check section addresses, once computed,
|
||
+ for overlaps. Relocatable links only check when this is > 0. */
|
||
+ signed char check_section_addresses;
|
||
+
|
||
+ /* If TRUE allow the linking of input files in an unknown architecture
|
||
+ assuming that the user knows what they are doing. This was the old
|
||
+ behaviour of the linker. The new default behaviour is to reject such
|
||
+ input files. */
|
||
+ bool accept_unknown_input_arch;
|
||
+
|
||
+ /* Name of the import library to generate. */
|
||
+ char *out_implib_filename;
|
||
+
|
||
+ /* If TRUE we'll just print the default output on stdout. */
|
||
+ bool print_output_format;
|
||
+
|
||
+ /* If set, display the target memory usage (per memory region). */
|
||
+ bool print_memory_usage;
|
||
+
|
||
+ /* Should we force section groups to be resolved? Controlled with
|
||
+ --force-group-allocation on the command line or FORCE_GROUP_ALLOCATION
|
||
+ in the linker script. */
|
||
+ bool force_group_allocation;
|
||
+
|
||
+ /* Big or little endian as set on command line. */
|
||
+ enum endian_enum endian;
|
||
+
|
||
+ /* Name of runtime interpreter to invoke. */
|
||
+ char *interpreter;
|
||
+
|
||
+ /* Name to give runtime library from the -soname argument. */
|
||
+ char *soname;
|
||
+
|
||
+ /* Runtime library search path from the -rpath argument. */
|
||
+ char *rpath;
|
||
+
|
||
+ /* Link time runtime library search path from the -rpath-link
|
||
+ argument. */
|
||
+ char *rpath_link;
|
||
+
|
||
+ /* Name of shared object whose symbol table should be filtered with
|
||
+ this shared object. From the --filter option. */
|
||
+ char *filter_shlib;
|
||
+
|
||
+ /* Name of shared object for whose symbol table this shared object
|
||
+ is an auxiliary filter. From the --auxiliary option. */
|
||
+ char **auxiliary_filters;
|
||
+
|
||
+ /* A version symbol to be applied to the symbol names found in the
|
||
+ .exports sections. */
|
||
+ char *version_exports_section;
|
||
+
|
||
+ /* Default linker script. */
|
||
+ char *default_script;
|
||
+} args_type;
|
||
+
|
||
+extern args_type command_line;
|
||
+
|
||
+typedef int token_code_type;
|
||
+
|
||
+/* Different ways we can handle orphan sections. */
|
||
+
|
||
+enum orphan_handling_enum
|
||
+{
|
||
+ /* The classic strategy, find a suitable section to place the orphan
|
||
+ into. */
|
||
+ orphan_handling_place = 0,
|
||
+
|
||
+ /* Discard any orphan sections as though they were assign to the section
|
||
+ /DISCARD/. */
|
||
+ orphan_handling_discard,
|
||
+
|
||
+ /* Find somewhere to place the orphan section, as with
|
||
+ ORPHAN_HANDLING_PLACE, but also issue a warning. */
|
||
+ orphan_handling_warn,
|
||
+
|
||
+ /* Issue a fatal error if any orphan sections are found. */
|
||
+ orphan_handling_error,
|
||
+};
|
||
+
|
||
+typedef struct
|
||
+{
|
||
+ bool magic_demand_paged;
|
||
+ bool make_executable;
|
||
+
|
||
+ /* If TRUE, -shared is supported. */
|
||
+ /* ??? A better way to do this is perhaps to define this in the
|
||
+ ld_emulation_xfer_struct since this is really a target dependent
|
||
+ parameter. */
|
||
+ bool has_shared;
|
||
+
|
||
+ /* If TRUE, build constructors. */
|
||
+ bool build_constructors;
|
||
+
|
||
+ /* If TRUE, warn about any constructors. */
|
||
+ bool warn_constructors;
|
||
+
|
||
+ /* If TRUE, warn about merging common symbols with others. */
|
||
+ bool warn_common;
|
||
+
|
||
+ /* If TRUE, only warn once about a particular undefined symbol. */
|
||
+ bool warn_once;
|
||
+
|
||
+ /* How should we deal with orphan sections. */
|
||
+ enum orphan_handling_enum orphan_handling;
|
||
+
|
||
+ /* If TRUE, warn if multiple global-pointers are needed (Alpha
|
||
+ only). */
|
||
+ bool warn_multiple_gp;
|
||
+
|
||
+ /* If TRUE, warn if the starting address of an output section
|
||
+ changes due to the alignment of an input section. */
|
||
+ bool warn_section_align;
|
||
+
|
||
+ /* If TRUE, warning messages are fatal. */
|
||
+ bool fatal_warnings;
|
||
+
|
||
+ /* If TRUE, warning and error messages are ignored. */
|
||
+ bool no_warnings;
|
||
+
|
||
+ sort_order sort_common;
|
||
+
|
||
+ bool text_read_only;
|
||
+
|
||
+ bool stats;
|
||
+
|
||
+ /* If set, orphan input sections will be mapped to separate output
|
||
+ sections. */
|
||
+ bool unique_orphan_sections;
|
||
+
|
||
+ /* If set, only search library directories explicitly selected
|
||
+ on the command line. */
|
||
+ bool only_cmd_line_lib_dirs;
|
||
+
|
||
+ /* If set, numbers and absolute symbols are simply treated as
|
||
+ numbers everywhere. */
|
||
+ bool sane_expr;
|
||
+
|
||
+ /* If set, code and non-code sections should never be in one segment. */
|
||
+ bool separate_code;
|
||
+
|
||
+ /* If set, generation of ELF section header should be suppressed. */
|
||
+ bool no_section_header;
|
||
+
|
||
+ /* The rpath separation character. Usually ':'. */
|
||
+ char rpath_separator;
|
||
+
|
||
+ char *map_filename;
|
||
+ FILE *map_file;
|
||
+
|
||
+ char *dependency_file;
|
||
+
|
||
+ unsigned int split_by_reloc;
|
||
+ bfd_size_type split_by_file;
|
||
+
|
||
+ /* The size of the hash table to use. */
|
||
+ unsigned long hash_table_size;
|
||
+
|
||
+ /* If set, print discarded sections in map file output. */
|
||
+ bool print_map_discarded;
|
||
+
|
||
+ /* If set, print local symbols in map file output. */
|
||
+ bool print_map_locals;
|
||
+
|
||
+ /* If set, emit the names and types of statically-linked variables
|
||
+ into the CTF. */
|
||
+ bool ctf_variables;
|
||
+
|
||
+ /* If set, share only duplicated types in CTF, rather than sharing
|
||
+ all types that are not in conflict. */
|
||
+ bool ctf_share_duplicated;
|
||
+
|
||
+ /* Compress DWARF debug sections. */
|
||
+ enum compressed_debug_section_type compress_debug;
|
||
+} ld_config_type;
|
||
+
|
||
+extern ld_config_type config;
|
||
+
|
||
+extern FILE * saved_script_handle;
|
||
+extern bool force_make_executable;
|
||
+
|
||
+extern int yyparse (void);
|
||
+extern void add_cref (const char *, bfd *, asection *, bfd_vma);
|
||
+extern bool handle_asneeded_cref (bfd *, enum notice_asneeded_action);
|
||
+extern void output_cref (FILE *);
|
||
+extern void check_nocrossrefs (void);
|
||
+extern void ld_abort (const char *, int, const char *) ATTRIBUTE_NORETURN;
|
||
+
|
||
+/* If gcc >= 2.6, we can give a function name, too. */
|
||
+#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 6)
|
||
+#define __PRETTY_FUNCTION__ NULL
|
||
+#endif
|
||
+
|
||
+#undef abort
|
||
+#define abort() ld_abort (__FILE__, __LINE__, __PRETTY_FUNCTION__)
|
||
+
|
||
+#endif
|
||
diff -rupN binutils.orig/ld/ld.texi binutils-2.41/ld/ld.texi
|
||
--- binutils.orig/ld/ld.texi 2024-05-13 13:03:48.141602288 +0100
|
||
+++ binutils-2.41/ld/ld.texi 2024-05-13 13:04:08.594633298 +0100
|
||
@@ -301,6 +301,7 @@ and the script command language. If @em
|
||
are specified, the linker does not produce any output, and issues the
|
||
message @samp{No input files}.
|
||
|
||
+@anchor{unrecognised-input-files}
|
||
If the linker cannot recognize the format of an object file, it will
|
||
assume that it is a linker script. A script specified in this way
|
||
augments the main linker script used for the link (either the default
|
||
@@ -1146,18 +1147,32 @@ a linker bug report.
|
||
@itemx --script=@var{scriptfile}
|
||
Use @var{scriptfile} as the linker script. This script replaces
|
||
@command{ld}'s default linker script (rather than adding to it),
|
||
-unless the script contains @code{INSERT}, so
|
||
-@var{commandfile} must specify everything necessary to describe the
|
||
-output file. @xref{Scripts}. If @var{scriptfile} does not exist in
|
||
-the current directory, @code{ld} looks for it in the directories
|
||
-specified by any preceding @samp{-L} options. Multiple @samp{-T}
|
||
-options accumulate.
|
||
+unless the script contains @code{INSERT}, so @var{commandfile} must
|
||
+specify everything necessary to describe the output file.
|
||
+@xref{Scripts}.
|
||
+
|
||
+If @var{scriptfile} does not exist in the current directory, @code{ld}
|
||
+looks for it in the directories specified by any preceding @samp{-L}
|
||
+options.
|
||
+
|
||
+Command line options that appear before the @option{-T} option can
|
||
+affect the script, but command line options that appear after it do
|
||
+not.
|
||
+
|
||
+Multiple @samp{-T} options will accumulate if they are augmenting the
|
||
+current script, otherwise the last, non-augmenting, @option{-T} option
|
||
+will be used.
|
||
+
|
||
+There are other ways of specifying linker scripts. See
|
||
+@xref{--default-script}, @xref{--section-ordering-file} and
|
||
+@xref{unrecognised-input-files}.
|
||
|
||
@kindex -dT @var{script}
|
||
@kindex --default-script=@var{script}
|
||
@cindex script files
|
||
@item -dT @var{scriptfile}
|
||
@itemx --default-script=@var{scriptfile}
|
||
+@anchor{--default-script}
|
||
Use @var{scriptfile} as the default linker script. @xref{Scripts}.
|
||
|
||
This option is similar to the @option{--script} option except that
|
||
@@ -2487,6 +2502,51 @@ warning and continue with the link.
|
||
|
||
@end ifset
|
||
|
||
+@kindex --section-ordering-file
|
||
+@item --section-ordering-file=@var{script}
|
||
+@anchor{--section-ordering-file}
|
||
+This option is used to augment the current linker script with
|
||
+additional mapping of input sections to output sections. This file
|
||
+must use the same syntax for @code{SECTIONS} as is used in normal
|
||
+linker scripts, but it should not do anything other than place input
|
||
+sections into output sections. @pxref{SECTIONS}
|
||
+
|
||
+A second constraint on the section ordering script is that it can only
|
||
+reference output sections that are already defined by whichever linker
|
||
+script is currently in use. (Ie the default linker script or a script
|
||
+specified on the command line). The benefit of the section ordering
|
||
+script however is that the input sections are mapped to the start of
|
||
+the output sections, so that they can ensure the ordering of sections
|
||
+in the output section. For example, imagine that the default linker
|
||
+script looks like this:
|
||
+
|
||
+@smallexample
|
||
+SECTIONS @{
|
||
+ .text : @{ *(.text.hot) ; *(.text .text.*) @}
|
||
+ .data : @{ *(.data.big) ; *(.data .data.*) @}
|
||
+ @}
|
||
+@end smallexample
|
||
+
|
||
+Then if a section ordering file like this is used:
|
||
+
|
||
+@smallexample
|
||
+ .text : @{ *(.text.first) ; *(.text.z*) @}
|
||
+ .data : @{ foo.o(.data.first) ; *(.data.small) @}
|
||
+@end smallexample
|
||
+
|
||
+This would be equivalent to a linker script like this:
|
||
+
|
||
+@smallexample
|
||
+SECTIONS @{
|
||
+ .text : @{ *(.text.first) ; *(.text.z*) ; *(.text.hot) ; *(.text .text.*) @}
|
||
+ .data : @{ foo.o(.data.first) ; *(.data.small) ; *(.data.big) ; *(.data .data.*) @}
|
||
+ @}
|
||
+@end smallexample
|
||
+
|
||
+The advantage of the section ordering file is that it can be used to
|
||
+order those sections that matter to the user without having to worry
|
||
+about any other sections, or memory regions, or anything else.
|
||
+
|
||
@kindex -shared
|
||
@kindex -Bshareable
|
||
@item -shared
|
||
diff -rupN binutils.orig/ld/ld.texi.orig binutils-2.41/ld/ld.texi.orig
|
||
--- binutils.orig/ld/ld.texi.orig 1970-01-01 01:00:00.000000000 +0100
|
||
+++ binutils-2.41/ld/ld.texi.orig 2024-05-13 13:03:26.615569650 +0100
|
||
@@ -0,0 +1,9639 @@
|
||
+\input texinfo
|
||
+@setfilename ld.info
|
||
+@c Copyright (C) 1991-2023 Free Software Foundation, Inc.
|
||
+@syncodeindex ky cp
|
||
+@c man begin INCLUDE
|
||
+@include configdoc.texi
|
||
+@c (configdoc.texi is generated by the Makefile)
|
||
+@include bfdver.texi
|
||
+@c man end
|
||
+
|
||
+@c @smallbook
|
||
+
|
||
+@macro gcctabopt{body}
|
||
+@code{\body\}
|
||
+@end macro
|
||
+
|
||
+@c man begin NAME
|
||
+@ifset man
|
||
+@c Configure for the generation of man pages
|
||
+@set UsesEnvVars
|
||
+@set GENERIC
|
||
+@set ARM
|
||
+@set C6X
|
||
+@set CSKY
|
||
+@set H8300
|
||
+@set HPPA
|
||
+@set M68HC11
|
||
+@set M68K
|
||
+@set MIPS
|
||
+@set MMIX
|
||
+@set MSP430
|
||
+@set NDS32
|
||
+@set NIOSII
|
||
+@set PDP11
|
||
+@set POWERPC
|
||
+@set POWERPC64
|
||
+@set Renesas
|
||
+@set S/390
|
||
+@set SPU
|
||
+@set TICOFF
|
||
+@set WIN32
|
||
+@set XTENSA
|
||
+@end ifset
|
||
+@c man end
|
||
+
|
||
+@ifnottex
|
||
+@dircategory Software development
|
||
+@direntry
|
||
+* Ld: (ld). The GNU linker.
|
||
+@end direntry
|
||
+@end ifnottex
|
||
+
|
||
+@copying
|
||
+This file documents the @sc{gnu} linker LD
|
||
+@ifset VERSION_PACKAGE
|
||
+@value{VERSION_PACKAGE}
|
||
+@end ifset
|
||
+version @value{VERSION}.
|
||
+
|
||
+Copyright @copyright{} 1991-2023 Free Software Foundation, Inc.
|
||
+
|
||
+Permission is granted to copy, distribute and/or modify this document
|
||
+under the terms of the GNU Free Documentation License, Version 1.3
|
||
+or any later version published by the Free Software Foundation;
|
||
+with no Invariant Sections, with no Front-Cover Texts, and with no
|
||
+Back-Cover Texts. A copy of the license is included in the
|
||
+section entitled ``GNU Free Documentation License''.
|
||
+@end copying
|
||
+@iftex
|
||
+@finalout
|
||
+@setchapternewpage odd
|
||
+@settitle The GNU linker
|
||
+@titlepage
|
||
+@title The GNU linker
|
||
+@sp 1
|
||
+@subtitle @code{ld}
|
||
+@ifset VERSION_PACKAGE
|
||
+@subtitle @value{VERSION_PACKAGE}
|
||
+@end ifset
|
||
+@subtitle Version @value{VERSION}
|
||
+@author Steve Chamberlain
|
||
+@author Ian Lance Taylor
|
||
+@page
|
||
+
|
||
+@tex
|
||
+{\parskip=0pt
|
||
+\hfill Red Hat Inc\par
|
||
+\hfill nickc\@redhat.com, doc\@redhat.com\par
|
||
+\hfill {\it The GNU linker}\par
|
||
+\hfill Edited by Jeffrey Osier (jeffrey\@cygnus.com)\par
|
||
+}
|
||
+\global\parindent=0pt % Steve likes it this way.
|
||
+@end tex
|
||
+
|
||
+@vskip 0pt plus 1filll
|
||
+@c man begin COPYRIGHT
|
||
+Copyright @copyright{} 1991-2023 Free Software Foundation, Inc.
|
||
+
|
||
+Permission is granted to copy, distribute and/or modify this document
|
||
+under the terms of the GNU Free Documentation License, Version 1.3
|
||
+or any later version published by the Free Software Foundation;
|
||
+with no Invariant Sections, with no Front-Cover Texts, and with no
|
||
+Back-Cover Texts. A copy of the license is included in the
|
||
+section entitled ``GNU Free Documentation License''.
|
||
+@c man end
|
||
+
|
||
+@end titlepage
|
||
+@end iftex
|
||
+@contents
|
||
+@c FIXME: Talk about importance of *order* of args, cmds to linker!
|
||
+
|
||
+@ifnottex
|
||
+@node Top
|
||
+@top LD
|
||
+This file documents the @sc{gnu} linker ld
|
||
+@ifset VERSION_PACKAGE
|
||
+@value{VERSION_PACKAGE}
|
||
+@end ifset
|
||
+version @value{VERSION}.
|
||
+
|
||
+This document is distributed under the terms of the GNU Free
|
||
+Documentation License version 1.3. A copy of the license is included
|
||
+in the section entitled ``GNU Free Documentation License''.
|
||
+
|
||
+@menu
|
||
+* Overview:: Overview
|
||
+* Invocation:: Invocation
|
||
+* Scripts:: Linker Scripts
|
||
+* Plugins:: Linker Plugins
|
||
+@ifset GENERIC
|
||
+* Machine Dependent:: Machine Dependent Features
|
||
+@end ifset
|
||
+@ifclear GENERIC
|
||
+@ifset H8300
|
||
+* H8/300:: ld and the H8/300
|
||
+@end ifset
|
||
+@ifset Renesas
|
||
+* Renesas:: ld and other Renesas micros
|
||
+@end ifset
|
||
+@ifset ARM
|
||
+* ARM:: ld and the ARM family
|
||
+@end ifset
|
||
+@ifset M68HC11
|
||
+* M68HC11/68HC12:: ld and the Motorola 68HC11 and 68HC12 families
|
||
+@end ifset
|
||
+@ifset HPPA
|
||
+* HPPA ELF32:: ld and HPPA 32-bit ELF
|
||
+@end ifset
|
||
+@ifset M68K
|
||
+* M68K:: ld and Motorola 68K family
|
||
+@end ifset
|
||
+@ifset MIPS
|
||
+* MIPS:: ld and MIPS family
|
||
+@end ifset
|
||
+@ifset POWERPC
|
||
+* PowerPC ELF32:: ld and PowerPC 32-bit ELF Support
|
||
+@end ifset
|
||
+@ifset POWERPC64
|
||
+* PowerPC64 ELF64:: ld and PowerPC64 64-bit ELF Support
|
||
+@end ifset
|
||
+@ifset S/390
|
||
+* S/390 ELF:: ld and S/390 ELF Support
|
||
+@end ifset
|
||
+@ifset SPU
|
||
+* SPU ELF:: ld and SPU ELF Support
|
||
+@end ifset
|
||
+@ifset TICOFF
|
||
+* TI COFF:: ld and the TI COFF
|
||
+@end ifset
|
||
+@ifset WIN32
|
||
+* Win32:: ld and WIN32 (cygwin/mingw)
|
||
+@end ifset
|
||
+@ifset XTENSA
|
||
+* Xtensa:: ld and Xtensa Processors
|
||
+@end ifset
|
||
+@end ifclear
|
||
+@ifclear SingleFormat
|
||
+* BFD:: BFD
|
||
+@end ifclear
|
||
+@c Following blank line required for remaining bug in makeinfo conds/menus
|
||
+
|
||
+* Reporting Bugs:: Reporting Bugs
|
||
+* MRI:: MRI Compatible Script Files
|
||
+* GNU Free Documentation License:: GNU Free Documentation License
|
||
+* LD Index:: LD Index
|
||
+@end menu
|
||
+@end ifnottex
|
||
+
|
||
+@node Overview
|
||
+@chapter Overview
|
||
+
|
||
+@cindex @sc{gnu} linker
|
||
+@cindex what is this?
|
||
+
|
||
+@ifset man
|
||
+@c man begin SYNOPSIS
|
||
+ld [@b{options}] @var{objfile} @dots{}
|
||
+@c man end
|
||
+
|
||
+@c man begin SEEALSO
|
||
+ar(1), nm(1), objcopy(1), objdump(1), readelf(1) and
|
||
+the Info entries for @file{binutils} and
|
||
+@file{ld}.
|
||
+@c man end
|
||
+@end ifset
|
||
+
|
||
+@c man begin DESCRIPTION
|
||
+
|
||
+@command{ld} combines a number of object and archive files, relocates
|
||
+their data and ties up symbol references. Usually the last step in
|
||
+compiling a program is to run @command{ld}.
|
||
+
|
||
+@command{ld} accepts Linker Command Language files written in
|
||
+a superset of AT&T's Link Editor Command Language syntax,
|
||
+to provide explicit and total control over the linking process.
|
||
+
|
||
+@ifset man
|
||
+@c For the man only
|
||
+This man page does not describe the command language; see the
|
||
+@command{ld} entry in @code{info} for full details on the command
|
||
+language and on other aspects of the GNU linker.
|
||
+@end ifset
|
||
+
|
||
+@ifclear SingleFormat
|
||
+This version of @command{ld} uses the general purpose BFD libraries
|
||
+to operate on object files. This allows @command{ld} to read, combine, and
|
||
+write object files in many different formats---for example, COFF or
|
||
+@code{a.out}. Different formats may be linked together to produce any
|
||
+available kind of object file. @xref{BFD}, for more information.
|
||
+@end ifclear
|
||
+
|
||
+Aside from its flexibility, the @sc{gnu} linker is more helpful than other
|
||
+linkers in providing diagnostic information. Many linkers abandon
|
||
+execution immediately upon encountering an error; whenever possible,
|
||
+@command{ld} continues executing, allowing you to identify other errors
|
||
+(or, in some cases, to get an output file in spite of the error).
|
||
+
|
||
+@c man end
|
||
+
|
||
+@node Invocation
|
||
+@chapter Invocation
|
||
+
|
||
+@c man begin DESCRIPTION
|
||
+
|
||
+The @sc{gnu} linker @command{ld} is meant to cover a broad range of situations,
|
||
+and to be as compatible as possible with other linkers. As a result,
|
||
+you have many choices to control its behavior.
|
||
+
|
||
+@c man end
|
||
+
|
||
+@ifset UsesEnvVars
|
||
+@menu
|
||
+* Options:: Command-line Options
|
||
+* Environment:: Environment Variables
|
||
+@end menu
|
||
+
|
||
+@node Options
|
||
+@section Command-line Options
|
||
+@end ifset
|
||
+
|
||
+@cindex command line
|
||
+@cindex options
|
||
+
|
||
+@c man begin OPTIONS
|
||
+
|
||
+The linker supports a plethora of command-line options, but in actual
|
||
+practice few of them are used in any particular context.
|
||
+@cindex standard Unix system
|
||
+For instance, a frequent use of @command{ld} is to link standard Unix
|
||
+object files on a standard, supported Unix system. On such a system, to
|
||
+link a file @code{hello.o}:
|
||
+
|
||
+@smallexample
|
||
+ld -o @var{output} /lib/crt0.o hello.o -lc
|
||
+@end smallexample
|
||
+
|
||
+This tells @command{ld} to produce a file called @var{output} as the
|
||
+result of linking the file @code{/lib/crt0.o} with @code{hello.o} and
|
||
+the library @code{libc.a}, which will come from the standard search
|
||
+directories. (See the discussion of the @samp{-l} option below.)
|
||
+
|
||
+Some of the command-line options to @command{ld} may be specified at any
|
||
+point in the command line. However, options which refer to files, such
|
||
+as @samp{-l} or @samp{-T}, cause the file to be read at the point at
|
||
+which the option appears in the command line, relative to the object
|
||
+files and other file options. Repeating non-file options with a
|
||
+different argument will either have no further effect, or override prior
|
||
+occurrences (those further to the left on the command line) of that
|
||
+option. Options which may be meaningfully specified more than once are
|
||
+noted in the descriptions below.
|
||
+
|
||
+@cindex object files
|
||
+Non-option arguments are object files or archives which are to be linked
|
||
+together. They may follow, precede, or be mixed in with command-line
|
||
+options, except that an object file argument may not be placed between
|
||
+an option and its argument.
|
||
+
|
||
+Usually the linker is invoked with at least one object file, but you can
|
||
+specify other forms of binary input files using @samp{-l}, @samp{-R},
|
||
+and the script command language. If @emph{no} binary input files at all
|
||
+are specified, the linker does not produce any output, and issues the
|
||
+message @samp{No input files}.
|
||
+
|
||
+If the linker cannot recognize the format of an object file, it will
|
||
+assume that it is a linker script. A script specified in this way
|
||
+augments the main linker script used for the link (either the default
|
||
+linker script or the one specified by using @samp{-T}). This feature
|
||
+permits the linker to link against a file which appears to be an object
|
||
+or an archive, but actually merely defines some symbol values, or uses
|
||
+@code{INPUT} or @code{GROUP} to load other objects. Specifying a
|
||
+script in this way merely augments the main linker script, with the
|
||
+extra commands placed after the main script; use the @samp{-T} option
|
||
+to replace the default linker script entirely, but note the effect of
|
||
+the @code{INSERT} command. @xref{Scripts}.
|
||
+
|
||
+For options whose names are a single letter,
|
||
+option arguments must either follow the option letter without intervening
|
||
+whitespace, or be given as separate arguments immediately following the
|
||
+option that requires them.
|
||
+
|
||
+For options whose names are multiple letters, either one dash or two can
|
||
+precede the option name; for example, @samp{-trace-symbol} and
|
||
+@samp{--trace-symbol} are equivalent. Note---there is one exception to
|
||
+this rule. Multiple letter options that start with a lower case 'o' can
|
||
+only be preceded by two dashes. This is to reduce confusion with the
|
||
+@samp{-o} option. So for example @samp{-omagic} sets the output file
|
||
+name to @samp{magic} whereas @samp{--omagic} sets the NMAGIC flag on the
|
||
+output.
|
||
+
|
||
+Arguments to multiple-letter options must either be separated from the
|
||
+option name by an equals sign, or be given as separate arguments
|
||
+immediately following the option that requires them. For example,
|
||
+@samp{--trace-symbol foo} and @samp{--trace-symbol=foo} are equivalent.
|
||
+Unique abbreviations of the names of multiple-letter options are
|
||
+accepted.
|
||
+
|
||
+Note---if the linker is being invoked indirectly, via a compiler driver
|
||
+(e.g. @samp{gcc}) then all the linker command-line options should be
|
||
+prefixed by @samp{-Wl,} (or whatever is appropriate for the particular
|
||
+compiler driver) like this:
|
||
+
|
||
+@smallexample
|
||
+ gcc -Wl,--start-group foo.o bar.o -Wl,--end-group
|
||
+@end smallexample
|
||
+
|
||
+This is important, because otherwise the compiler driver program may
|
||
+silently drop the linker options, resulting in a bad link. Confusion
|
||
+may also arise when passing options that require values through a
|
||
+driver, as the use of a space between option and argument acts as
|
||
+a separator, and causes the driver to pass only the option to the linker
|
||
+and the argument to the compiler. In this case, it is simplest to use
|
||
+the joined forms of both single- and multiple-letter options, such as:
|
||
+
|
||
+@smallexample
|
||
+ gcc foo.o bar.o -Wl,-eENTRY -Wl,-Map=a.map
|
||
+@end smallexample
|
||
+
|
||
+Here is a table of the generic command-line switches accepted by the GNU
|
||
+linker:
|
||
+
|
||
+@table @gcctabopt
|
||
+@include at-file.texi
|
||
+
|
||
+@kindex -a @var{keyword}
|
||
+@item -a @var{keyword}
|
||
+This option is supported for HP/UX compatibility. The @var{keyword}
|
||
+argument must be one of the strings @samp{archive}, @samp{shared}, or
|
||
+@samp{default}. @samp{-aarchive} is functionally equivalent to
|
||
+@samp{-Bstatic}, and the other two keywords are functionally equivalent
|
||
+to @samp{-Bdynamic}. This option may be used any number of times.
|
||
+
|
||
+@kindex --audit @var{AUDITLIB}
|
||
+@item --audit @var{AUDITLIB}
|
||
+Adds @var{AUDITLIB} to the @code{DT_AUDIT} entry of the dynamic section.
|
||
+@var{AUDITLIB} is not checked for existence, nor will it use the DT_SONAME
|
||
+specified in the library. If specified multiple times @code{DT_AUDIT}
|
||
+will contain a colon separated list of audit interfaces to use. If the linker
|
||
+finds an object with an audit entry while searching for shared libraries,
|
||
+it will add a corresponding @code{DT_DEPAUDIT} entry in the output file.
|
||
+This option is only meaningful on ELF platforms supporting the rtld-audit
|
||
+interface.
|
||
+
|
||
+@ifclear SingleFormat
|
||
+@cindex binary input format
|
||
+@kindex -b @var{format}
|
||
+@kindex --format=@var{format}
|
||
+@cindex input format
|
||
+@cindex input format
|
||
+@item -b @var{input-format}
|
||
+@itemx --format=@var{input-format}
|
||
+@command{ld} may be configured to support more than one kind of object
|
||
+file. If your @command{ld} is configured this way, you can use the
|
||
+@samp{-b} option to specify the binary format for input object files
|
||
+that follow this option on the command line. Even when @command{ld} is
|
||
+configured to support alternative object formats, you don't usually need
|
||
+to specify this, as @command{ld} should be configured to expect as a
|
||
+default input format the most usual format on each machine.
|
||
+@var{input-format} is a text string, the name of a particular format
|
||
+supported by the BFD libraries. (You can list the available binary
|
||
+formats with @samp{objdump -i}.)
|
||
+@xref{BFD}.
|
||
+
|
||
+You may want to use this option if you are linking files with an unusual
|
||
+binary format. You can also use @samp{-b} to switch formats explicitly (when
|
||
+linking object files of different formats), by including
|
||
+@samp{-b @var{input-format}} before each group of object files in a
|
||
+particular format.
|
||
+
|
||
+The default format is taken from the environment variable
|
||
+@code{GNUTARGET}.
|
||
+@ifset UsesEnvVars
|
||
+@xref{Environment}.
|
||
+@end ifset
|
||
+You can also define the input format from a script, using the command
|
||
+@code{TARGET};
|
||
+@ifclear man
|
||
+see @ref{Format Commands}.
|
||
+@end ifclear
|
||
+@end ifclear
|
||
+
|
||
+@kindex -c @var{MRI-cmdfile}
|
||
+@kindex --mri-script=@var{MRI-cmdfile}
|
||
+@cindex compatibility, MRI
|
||
+@item -c @var{MRI-commandfile}
|
||
+@itemx --mri-script=@var{MRI-commandfile}
|
||
+For compatibility with linkers produced by MRI, @command{ld} accepts script
|
||
+files written in an alternate, restricted command language, described in
|
||
+@ifclear man
|
||
+@ref{MRI,,MRI Compatible Script Files}.
|
||
+@end ifclear
|
||
+@ifset man
|
||
+the MRI Compatible Script Files section of GNU ld documentation.
|
||
+@end ifset
|
||
+Introduce MRI script files with
|
||
+the option @samp{-c}; use the @samp{-T} option to run linker
|
||
+scripts written in the general-purpose @command{ld} scripting language.
|
||
+If @var{MRI-cmdfile} does not exist, @command{ld} looks for it in the directories
|
||
+specified by any @samp{-L} options.
|
||
+
|
||
+@cindex common allocation
|
||
+@kindex -d
|
||
+@kindex -dc
|
||
+@kindex -dp
|
||
+@item -d
|
||
+@itemx -dc
|
||
+@itemx -dp
|
||
+These three options are equivalent; multiple forms are supported for
|
||
+compatibility with other linkers. They assign space to common symbols
|
||
+even if a relocatable output file is specified (with @samp{-r}). The
|
||
+script command @code{FORCE_COMMON_ALLOCATION} has the same effect.
|
||
+@xref{Miscellaneous Commands}.
|
||
+
|
||
+@kindex --depaudit @var{AUDITLIB}
|
||
+@kindex -P @var{AUDITLIB}
|
||
+@item --depaudit @var{AUDITLIB}
|
||
+@itemx -P @var{AUDITLIB}
|
||
+Adds @var{AUDITLIB} to the @code{DT_DEPAUDIT} entry of the dynamic section.
|
||
+@var{AUDITLIB} is not checked for existence, nor will it use the DT_SONAME
|
||
+specified in the library. If specified multiple times @code{DT_DEPAUDIT}
|
||
+will contain a colon separated list of audit interfaces to use. This
|
||
+option is only meaningful on ELF platforms supporting the rtld-audit interface.
|
||
+The -P option is provided for Solaris compatibility.
|
||
+
|
||
+@kindex --enable-linker-version
|
||
+@item --enable-linker-version
|
||
+Enables the @code{LINKER_VERSION} linker script directive, described
|
||
+in @ref{Output Section Data}. If this directive is used in a linker
|
||
+script and this option has been enabled then a string containing the
|
||
+linker version will be inserted at the current point.
|
||
+
|
||
+Note - this location of this option on the linker command line is
|
||
+significant. It will only affect linker scripts that come after it on
|
||
+the command line, or which are built into the linker.
|
||
+
|
||
+@kindex --disable-linker-version
|
||
+@item --disable-linker-version
|
||
+Disables the @code{LINKER_VERSION} linker script directive, so that it
|
||
+does not insert a version string. This is the default.
|
||
+
|
||
+@kindex --enable-non-contiguous-regions
|
||
+@item --enable-non-contiguous-regions
|
||
+This option avoids generating an error if an input section does not
|
||
+fit a matching output section. The linker tries to allocate the input
|
||
+section to subseque nt matching output sections, and generates an
|
||
+error only if no output section is large enough. This is useful when
|
||
+several non-contiguous memory regions are available and the input
|
||
+section does not require a particular one. The order in which input
|
||
+sections are evaluated does not change, for instance:
|
||
+
|
||
+@smallexample
|
||
+ MEMORY @{
|
||
+ MEM1 (rwx) : ORIGIN = 0x1000, LENGTH = 0x14
|
||
+ MEM2 (rwx) : ORIGIN = 0x1000, LENGTH = 0x40
|
||
+ MEM3 (rwx) : ORIGIN = 0x2000, LENGTH = 0x40
|
||
+ @}
|
||
+ SECTIONS @{
|
||
+ mem1 : @{ *(.data.*); @} > MEM1
|
||
+ mem2 : @{ *(.data.*); @} > MEM2
|
||
+ mem3 : @{ *(.data.*); @} > MEM3
|
||
+ @}
|
||
+
|
||
+ with input sections:
|
||
+ .data.1: size 8
|
||
+ .data.2: size 0x10
|
||
+ .data.3: size 4
|
||
+
|
||
+ results in .data.1 affected to mem1, and .data.2 and .data.3
|
||
+ affected to mem2, even though .data.3 would fit in mem3.
|
||
+@end smallexample
|
||
+
|
||
+This option is incompatible with INSERT statements because it changes
|
||
+the way input sections are mapped to output sections.
|
||
+
|
||
+@kindex --enable-non-contiguous-regions-warnings
|
||
+@item --enable-non-contiguous-regions-warnings
|
||
+This option enables warnings when
|
||
+@code{--enable-non-contiguous-regions} allows possibly unexpected
|
||
+matches in sections mapping, potentially leading to silently
|
||
+discarding a section instead of failing because it does not fit any
|
||
+output region.
|
||
+
|
||
+@cindex entry point, from command line
|
||
+@kindex -e @var{entry}
|
||
+@kindex --entry=@var{entry}
|
||
+@item -e @var{entry}
|
||
+@itemx --entry=@var{entry}
|
||
+Use @var{entry} as the explicit symbol for beginning execution of your
|
||
+program, rather than the default entry point. If there is no symbol
|
||
+named @var{entry}, the linker will try to parse @var{entry} as a number,
|
||
+and use that as the entry address (the number will be interpreted in
|
||
+base 10; you may use a leading @samp{0x} for base 16, or a leading
|
||
+@samp{0} for base 8). @xref{Entry Point}, for a discussion of defaults
|
||
+and other ways of specifying the entry point.
|
||
+
|
||
+@kindex --exclude-libs
|
||
+@item --exclude-libs @var{lib},@var{lib},...
|
||
+Specifies a list of archive libraries from which symbols should not be automatically
|
||
+exported. The library names may be delimited by commas or colons. Specifying
|
||
+@code{--exclude-libs ALL} excludes symbols in all archive libraries from
|
||
+automatic export. This option is available only for the i386 PE targeted
|
||
+port of the linker and for ELF targeted ports. For i386 PE, symbols
|
||
+explicitly listed in a .def file are still exported, regardless of this
|
||
+option. For ELF targeted ports, symbols affected by this option will
|
||
+be treated as hidden.
|
||
+
|
||
+@kindex --exclude-modules-for-implib
|
||
+@item --exclude-modules-for-implib @var{module},@var{module},...
|
||
+Specifies a list of object files or archive members, from which symbols
|
||
+should not be automatically exported, but which should be copied wholesale
|
||
+into the import library being generated during the link. The module names
|
||
+may be delimited by commas or colons, and must match exactly the filenames
|
||
+used by @command{ld} to open the files; for archive members, this is simply
|
||
+the member name, but for object files the name listed must include and
|
||
+match precisely any path used to specify the input file on the linker's
|
||
+command-line. This option is available only for the i386 PE targeted port
|
||
+of the linker. Symbols explicitly listed in a .def file are still exported,
|
||
+regardless of this option.
|
||
+
|
||
+@cindex dynamic symbol table
|
||
+@kindex -E
|
||
+@kindex --export-dynamic
|
||
+@kindex --no-export-dynamic
|
||
+@item -E
|
||
+@itemx --export-dynamic
|
||
+@itemx --no-export-dynamic
|
||
+When creating a dynamically linked executable, using the @option{-E}
|
||
+option or the @option{--export-dynamic} option causes the linker to add
|
||
+all symbols to the dynamic symbol table. The dynamic symbol table is the
|
||
+set of symbols which are visible from dynamic objects at run time.
|
||
+
|
||
+If you do not use either of these options (or use the
|
||
+@option{--no-export-dynamic} option to restore the default behavior), the
|
||
+dynamic symbol table will normally contain only those symbols which are
|
||
+referenced by some dynamic object mentioned in the link.
|
||
+
|
||
+If you use @code{dlopen} to load a dynamic object which needs to refer
|
||
+back to the symbols defined by the program, rather than some other
|
||
+dynamic object, then you will probably need to use this option when
|
||
+linking the program itself.
|
||
+
|
||
+You can also use the dynamic list to control what symbols should
|
||
+be added to the dynamic symbol table if the output format supports it.
|
||
+See the description of @samp{--dynamic-list}.
|
||
+
|
||
+Note that this option is specific to ELF targeted ports. PE targets
|
||
+support a similar function to export all symbols from a DLL or EXE; see
|
||
+the description of @samp{--export-all-symbols} below.
|
||
+
|
||
+@kindex --export-dynamic-symbol=@var{glob}
|
||
+@cindex export dynamic symbol
|
||
+@item --export-dynamic-symbol=@var{glob}
|
||
+When creating a dynamically linked executable, symbols matching
|
||
+@var{glob} will be added to the dynamic symbol table. When creating a
|
||
+shared library, references to symbols matching @var{glob} will not be
|
||
+bound to the definitions within the shared library. This option is a
|
||
+no-op when creating a shared library and @samp{-Bsymbolic} or
|
||
+@samp{--dynamic-list} are not specified. This option is only meaningful
|
||
+on ELF platforms which support shared libraries.
|
||
+
|
||
+@kindex --export-dynamic-symbol-list=@var{file}
|
||
+@cindex export dynamic symbol list
|
||
+@item --export-dynamic-symbol-list=@var{file}
|
||
+Specify a @samp{--export-dynamic-symbol} for each pattern in the file.
|
||
+The format of the file is the same as the version node without
|
||
+scope and node name. See @ref{VERSION} for more information.
|
||
+
|
||
+@ifclear SingleFormat
|
||
+@cindex big-endian objects
|
||
+@cindex endianness
|
||
+@kindex -EB
|
||
+@item -EB
|
||
+Link big-endian objects. This affects the default output format.
|
||
+
|
||
+@cindex little-endian objects
|
||
+@kindex -EL
|
||
+@item -EL
|
||
+Link little-endian objects. This affects the default output format.
|
||
+@end ifclear
|
||
+
|
||
+@kindex -f @var{name}
|
||
+@kindex --auxiliary=@var{name}
|
||
+@item -f @var{name}
|
||
+@itemx --auxiliary=@var{name}
|
||
+When creating an ELF shared object, set the internal DT_AUXILIARY field
|
||
+to the specified name. This tells the dynamic linker that the symbol
|
||
+table of the shared object should be used as an auxiliary filter on the
|
||
+symbol table of the shared object @var{name}.
|
||
+
|
||
+If you later link a program against this filter object, then, when you
|
||
+run the program, the dynamic linker will see the DT_AUXILIARY field. If
|
||
+the dynamic linker resolves any symbols from the filter object, it will
|
||
+first check whether there is a definition in the shared object
|
||
+@var{name}. If there is one, it will be used instead of the definition
|
||
+in the filter object. The shared object @var{name} need not exist.
|
||
+Thus the shared object @var{name} may be used to provide an alternative
|
||
+implementation of certain functions, perhaps for debugging or for
|
||
+machine-specific performance.
|
||
+
|
||
+This option may be specified more than once. The DT_AUXILIARY entries
|
||
+will be created in the order in which they appear on the command line.
|
||
+
|
||
+@kindex -F @var{name}
|
||
+@kindex --filter=@var{name}
|
||
+@item -F @var{name}
|
||
+@itemx --filter=@var{name}
|
||
+When creating an ELF shared object, set the internal DT_FILTER field to
|
||
+the specified name. This tells the dynamic linker that the symbol table
|
||
+of the shared object which is being created should be used as a filter
|
||
+on the symbol table of the shared object @var{name}.
|
||
+
|
||
+If you later link a program against this filter object, then, when you
|
||
+run the program, the dynamic linker will see the DT_FILTER field. The
|
||
+dynamic linker will resolve symbols according to the symbol table of the
|
||
+filter object as usual, but it will actually link to the definitions
|
||
+found in the shared object @var{name}. Thus the filter object can be
|
||
+used to select a subset of the symbols provided by the object
|
||
+@var{name}.
|
||
+
|
||
+Some older linkers used the @option{-F} option throughout a compilation
|
||
+toolchain for specifying object-file format for both input and output
|
||
+object files.
|
||
+@ifclear SingleFormat
|
||
+The @sc{gnu} linker uses other mechanisms for this purpose: the
|
||
+@option{-b}, @option{--format}, @option{--oformat} options, the
|
||
+@code{TARGET} command in linker scripts, and the @code{GNUTARGET}
|
||
+environment variable.
|
||
+@end ifclear
|
||
+The @sc{gnu} linker will ignore the @option{-F} option when not
|
||
+creating an ELF shared object.
|
||
+
|
||
+@cindex finalization function
|
||
+@kindex -fini=@var{name}
|
||
+@item -fini=@var{name}
|
||
+When creating an ELF executable or shared object, call NAME when the
|
||
+executable or shared object is unloaded, by setting DT_FINI to the
|
||
+address of the function. By default, the linker uses @code{_fini} as
|
||
+the function to call.
|
||
+
|
||
+@kindex -g
|
||
+@item -g
|
||
+Ignored. Provided for compatibility with other tools.
|
||
+
|
||
+@kindex -G @var{value}
|
||
+@kindex --gpsize=@var{value}
|
||
+@cindex object size
|
||
+@item -G @var{value}
|
||
+@itemx --gpsize=@var{value}
|
||
+Set the maximum size of objects to be optimized using the GP register to
|
||
+@var{size}. This is only meaningful for object file formats such as
|
||
+MIPS ELF that support putting large and small objects into different
|
||
+sections. This is ignored for other object file formats.
|
||
+
|
||
+@cindex runtime library name
|
||
+@kindex -h @var{name}
|
||
+@kindex -soname=@var{name}
|
||
+@item -h @var{name}
|
||
+@itemx -soname=@var{name}
|
||
+When creating an ELF shared object, set the internal DT_SONAME field to
|
||
+the specified name. When an executable is linked with a shared object
|
||
+which has a DT_SONAME field, then when the executable is run the dynamic
|
||
+linker will attempt to load the shared object specified by the DT_SONAME
|
||
+field rather than using the file name given to the linker.
|
||
+
|
||
+@kindex -i
|
||
+@cindex incremental link
|
||
+@item -i
|
||
+Perform an incremental link (same as option @samp{-r}).
|
||
+
|
||
+@cindex initialization function
|
||
+@kindex -init=@var{name}
|
||
+@item -init=@var{name}
|
||
+When creating an ELF executable or shared object, call NAME when the
|
||
+executable or shared object is loaded, by setting DT_INIT to the address
|
||
+of the function. By default, the linker uses @code{_init} as the
|
||
+function to call.
|
||
+
|
||
+@cindex archive files, from cmd line
|
||
+@kindex -l @var{namespec}
|
||
+@kindex --library=@var{namespec}
|
||
+@item -l @var{namespec}
|
||
+@itemx --library=@var{namespec}
|
||
+Add the archive or object file specified by @var{namespec} to the
|
||
+list of files to link. This option may be used any number of times.
|
||
+If @var{namespec} is of the form @file{:@var{filename}}, @command{ld}
|
||
+will search the library path for a file called @var{filename}, otherwise it
|
||
+will search the library path for a file called @file{lib@var{namespec}.a}.
|
||
+
|
||
+On systems which support shared libraries, @command{ld} may also search for
|
||
+files other than @file{lib@var{namespec}.a}. Specifically, on ELF
|
||
+and SunOS systems, @command{ld} will search a directory for a library
|
||
+called @file{lib@var{namespec}.so} before searching for one called
|
||
+@file{lib@var{namespec}.a}. (By convention, a @code{.so} extension
|
||
+indicates a shared library.) Note that this behavior does not apply
|
||
+to @file{:@var{filename}}, which always specifies a file called
|
||
+@var{filename}.
|
||
+
|
||
+The linker will search an archive only once, at the location where it is
|
||
+specified on the command line. If the archive defines a symbol which
|
||
+was undefined in some object which appeared before the archive on the
|
||
+command line, the linker will include the appropriate file(s) from the
|
||
+archive. However, an undefined symbol in an object appearing later on
|
||
+the command line will not cause the linker to search the archive again.
|
||
+
|
||
+See the @option{-(} option for a way to force the linker to search
|
||
+archives multiple times.
|
||
+
|
||
+You may list the same archive multiple times on the command line.
|
||
+
|
||
+@ifset GENERIC
|
||
+This type of archive searching is standard for Unix linkers. However,
|
||
+if you are using @command{ld} on AIX, note that it is different from the
|
||
+behaviour of the AIX linker.
|
||
+@end ifset
|
||
+
|
||
+@cindex search directory, from cmd line
|
||
+@kindex -L @var{dir}
|
||
+@kindex --library-path=@var{dir}
|
||
+@item -L @var{searchdir}
|
||
+@itemx --library-path=@var{searchdir}
|
||
+Add path @var{searchdir} to the list of paths that @command{ld} will search
|
||
+for archive libraries and @command{ld} control scripts. You may use this
|
||
+option any number of times. The directories are searched in the order
|
||
+in which they are specified on the command line. Directories specified
|
||
+on the command line are searched before the default directories. All
|
||
+@option{-L} options apply to all @option{-l} options, regardless of the
|
||
+order in which the options appear. @option{-L} options do not affect
|
||
+how @command{ld} searches for a linker script unless @option{-T}
|
||
+option is specified.
|
||
+
|
||
+If @var{searchdir} begins with @code{=} or @code{$SYSROOT}, then this
|
||
+prefix will be replaced by the @dfn{sysroot prefix}, controlled by the
|
||
+@samp{--sysroot} option, or specified when the linker is configured.
|
||
+
|
||
+@ifset UsesEnvVars
|
||
+The default set of paths searched (without being specified with
|
||
+@samp{-L}) depends on which emulation mode @command{ld} is using, and in
|
||
+some cases also on how it was configured. @xref{Environment}.
|
||
+@end ifset
|
||
+
|
||
+The paths can also be specified in a link script with the
|
||
+@code{SEARCH_DIR} command. Directories specified this way are searched
|
||
+at the point in which the linker script appears in the command line.
|
||
+
|
||
+@cindex emulation
|
||
+@kindex -m @var{emulation}
|
||
+@item -m @var{emulation}
|
||
+Emulate the @var{emulation} linker. You can list the available
|
||
+emulations with the @samp{--verbose} or @samp{-V} options.
|
||
+
|
||
+If the @samp{-m} option is not used, the emulation is taken from the
|
||
+@code{LDEMULATION} environment variable, if that is defined.
|
||
+
|
||
+Otherwise, the default emulation depends upon how the linker was
|
||
+configured.
|
||
+
|
||
+@cindex remapping inputs
|
||
+@kindex --remap-inputs=@file{pattern}=@file{filename}
|
||
+@kindex --remap-inputs-file=@file{file}
|
||
+@item --remap-inputs=@file{pattern}=@file{filename}
|
||
+@itemx --remap-inputs-file=@file{file}
|
||
+These options allow the names of input files to be changed before the
|
||
+linker attempts to open them. The option
|
||
+@option{--remap-inputs=foo.o=bar.o} will cause any attempt to load a
|
||
+file called @file{foo.o} to instead try to load a file called
|
||
+@file{bar.o}. Wildcard patterns are permitted in the first filename,
|
||
+so @option{--remap-inputs=foo*.o=bar.o} will rename any input file that
|
||
+matches @file{foo*.o} to @file{bar.o}.
|
||
+
|
||
+An alternative form of the option
|
||
+@option{--remap-inputs-file=filename} allows the remappings to be read
|
||
+from a file. Each line in the file can contain a single remapping.
|
||
+Blank lines are ignored. Anything from a hash character (@samp{#}) to
|
||
+the end of a line is considered to be a comment and is also ignored.
|
||
+The mapping pattern can be separated from the filename by whitespace
|
||
+or an equals (@samp{=}) character.
|
||
+
|
||
+The options can be specified multiple times. Their contents
|
||
+accumulate. The remappings will be processed in the order in which
|
||
+they occur on the command line, and if they come from a file, in the
|
||
+order in which they occur in the file. If a match is made, no further
|
||
+checking for that filename will be performed.
|
||
+
|
||
+If the replacement filename is @file{/dev/null} or just @file{NUL}
|
||
+then the remapping will actually cause the input file to be ignored.
|
||
+This can be a convenient way to experiment with removing input files
|
||
+from a complicated build environment.
|
||
+
|
||
+Note that this option is position dependent and only affects filenames
|
||
+that come after it on the command line. Thus:
|
||
+
|
||
+@smallexample
|
||
+ ld foo.o --remap-inputs=foo.o=bar.o
|
||
+@end smallexample
|
||
+
|
||
+Will have no effect, whereas:
|
||
+
|
||
+@smallexample
|
||
+ ld --remap-inputs=foo.o=bar.o foo.o
|
||
+@end smallexample
|
||
+
|
||
+Will rename the input file @file{foo.o} to @file{bar.o}.
|
||
+
|
||
+Note - these options also affect files referenced by @emph{INPUT}
|
||
+statements in linker scripts. But since linker scripts are processed
|
||
+after the entire command line is read, the position of the remap
|
||
+options on the command line is not significant.
|
||
+
|
||
+If the @option{verbose} option is enabled then any mappings that match
|
||
+will be reported, although again the @option{verbose} option needs to
|
||
+be enabled on the command line @emph{before} the remaped filenames
|
||
+appear.
|
||
+
|
||
+If the @option{-Map} or @option{--print-map} options are enabled then
|
||
+the remapping list will be included in the map output.
|
||
+
|
||
+@cindex link map
|
||
+@kindex -M
|
||
+@kindex --print-map
|
||
+@item -M
|
||
+@itemx --print-map
|
||
+Print a link map to the standard output. A link map provides
|
||
+information about the link, including the following:
|
||
+
|
||
+@itemize @bullet
|
||
+@item
|
||
+Where object files are mapped into memory.
|
||
+@item
|
||
+How common symbols are allocated.
|
||
+@item
|
||
+All archive members included in the link, with a mention of the symbol
|
||
+which caused the archive member to be brought in.
|
||
+@item
|
||
+The values assigned to symbols.
|
||
+
|
||
+Note - symbols whose values are computed by an expression which
|
||
+involves a reference to a previous value of the same symbol may not
|
||
+have correct result displayed in the link map. This is because the
|
||
+linker discards intermediate results and only retains the final value
|
||
+of an expression. Under such circumstances the linker will display
|
||
+the final value enclosed by square brackets. Thus for example a
|
||
+linker script containing:
|
||
+
|
||
+@smallexample
|
||
+ foo = 1
|
||
+ foo = foo * 4
|
||
+ foo = foo + 8
|
||
+@end smallexample
|
||
+
|
||
+will produce the following output in the link map if the @option{-M}
|
||
+option is used:
|
||
+
|
||
+@smallexample
|
||
+ 0x00000001 foo = 0x1
|
||
+ [0x0000000c] foo = (foo * 0x4)
|
||
+ [0x0000000c] foo = (foo + 0x8)
|
||
+@end smallexample
|
||
+
|
||
+See @ref{Expressions} for more information about expressions in linker
|
||
+scripts.
|
||
+
|
||
+@item
|
||
+How GNU properties are merged.
|
||
+
|
||
+When the linker merges input .note.gnu.property sections into one output
|
||
+.note.gnu.property section, some properties are removed or updated.
|
||
+These actions are reported in the link map. For example:
|
||
+
|
||
+@smallexample
|
||
+Removed property 0xc0000002 to merge foo.o (0x1) and bar.o (not found)
|
||
+@end smallexample
|
||
+
|
||
+This indicates that property 0xc0000002 is removed from output when
|
||
+merging properties in @file{foo.o}, whose property 0xc0000002 value
|
||
+is 0x1, and @file{bar.o}, which doesn't have property 0xc0000002.
|
||
+
|
||
+@smallexample
|
||
+Updated property 0xc0010001 (0x1) to merge foo.o (0x1) and bar.o (0x1)
|
||
+@end smallexample
|
||
+
|
||
+This indicates that property 0xc0010001 value is updated to 0x1 in output
|
||
+when merging properties in @file{foo.o}, whose 0xc0010001 property value
|
||
+is 0x1, and @file{bar.o}, whose 0xc0010001 property value is 0x1.
|
||
+@end itemize
|
||
+
|
||
+@cindex link map discarded
|
||
+@kindex --print-map-discarded
|
||
+@kindex --no-print-map-discarded
|
||
+@item --print-map-discarded
|
||
+@itemx --no-print-map-discarded
|
||
+Print (or do not print) the list of discarded and garbage collected sections
|
||
+in the link map. Enabled by default.
|
||
+
|
||
+@kindex --print-map-locals
|
||
+@kindex --no-print-map-locals
|
||
+@item --print-map-locals
|
||
+@itemx --no-print-map-locals
|
||
+Print (or do not print) local symbols in the link map. Local symbols
|
||
+will have the text @samp{(local)} printed before their name, and will
|
||
+be listed after all of the global symbols in a given section.
|
||
+Temporary local symbols (typically those that start with @samp{.L})
|
||
+will not be included in the output. Disabled by default.
|
||
+
|
||
+@kindex -n
|
||
+@cindex read-only text
|
||
+@cindex NMAGIC
|
||
+@kindex --nmagic
|
||
+@item -n
|
||
+@itemx --nmagic
|
||
+Turn off page alignment of sections, and disable linking against shared
|
||
+libraries. If the output format supports Unix style magic numbers,
|
||
+mark the output as @code{NMAGIC}.
|
||
+
|
||
+@kindex -N
|
||
+@kindex --omagic
|
||
+@cindex read/write from cmd line
|
||
+@cindex OMAGIC
|
||
+@item -N
|
||
+@itemx --omagic
|
||
+Set the text and data sections to be readable and writable. Also, do
|
||
+not page-align the data segment, and disable linking against shared
|
||
+libraries. If the output format supports Unix style magic numbers,
|
||
+mark the output as @code{OMAGIC}. Note: Although a writable text section
|
||
+is allowed for PE-COFF targets, it does not conform to the format
|
||
+specification published by Microsoft.
|
||
+
|
||
+@kindex --no-omagic
|
||
+@cindex OMAGIC
|
||
+@item --no-omagic
|
||
+This option negates most of the effects of the @option{-N} option. It
|
||
+sets the text section to be read-only, and forces the data segment to
|
||
+be page-aligned. Note - this option does not enable linking against
|
||
+shared libraries. Use @option{-Bdynamic} for this.
|
||
+
|
||
+@kindex -o @var{output}
|
||
+@kindex --output=@var{output}
|
||
+@cindex naming the output file
|
||
+@item -o @var{output}
|
||
+@itemx --output=@var{output}
|
||
+Use @var{output} as the name for the program produced by @command{ld}; if this
|
||
+option is not specified, the name @file{a.out} is used by default. The
|
||
+script command @code{OUTPUT} can also specify the output file name.
|
||
+
|
||
+@kindex --dependency-file=@var{depfile}
|
||
+@cindex dependency file
|
||
+@item --dependency-file=@var{depfile}
|
||
+Write a @dfn{dependency file} to @var{depfile}. This file contains a rule
|
||
+suitable for @code{make} describing the output file and all the input files
|
||
+that were read to produce it. The output is similar to the compiler's
|
||
+output with @samp{-M -MP} (@pxref{Preprocessor Options,, Options
|
||
+Controlling the Preprocessor, gcc.info, Using the GNU Compiler
|
||
+Collection}). Note that there is no option like the compiler's @samp{-MM},
|
||
+to exclude ``system files'' (which is not a well-specified concept in the
|
||
+linker, unlike ``system headers'' in the compiler). So the output from
|
||
+@samp{--dependency-file} is always specific to the exact state of the
|
||
+installation where it was produced, and should not be copied into
|
||
+distributed makefiles without careful editing.
|
||
+
|
||
+@kindex -O @var{level}
|
||
+@cindex generating optimized output
|
||
+@item -O @var{level}
|
||
+If @var{level} is a numeric values greater than zero @command{ld} optimizes
|
||
+the output. This might take significantly longer and therefore probably
|
||
+should only be enabled for the final binary. At the moment this
|
||
+option only affects ELF shared library generation. Future releases of
|
||
+the linker may make more use of this option. Also currently there is
|
||
+no difference in the linker's behaviour for different non-zero values
|
||
+of this option. Again this may change with future releases.
|
||
+
|
||
+@kindex -plugin @var{name}
|
||
+@item -plugin @var{name}
|
||
+Involve a plugin in the linking process. The @var{name} parameter is
|
||
+the absolute filename of the plugin. Usually this parameter is
|
||
+automatically added by the complier, when using link time
|
||
+optimization, but users can also add their own plugins if they so
|
||
+wish.
|
||
+
|
||
+Note that the location of the compiler originated plugins is different
|
||
+from the place where the @command{ar}, @command{nm} and
|
||
+@command{ranlib} programs search for their plugins. In order for
|
||
+those commands to make use of a compiler based plugin it must first be
|
||
+copied into the @file{$@{libdir@}/bfd-plugins} directory. All gcc
|
||
+based linker plugins are backward compatible, so it is sufficient to
|
||
+just copy in the newest one.
|
||
+
|
||
+@kindex --push-state
|
||
+@cindex push state governing input file handling
|
||
+@item --push-state
|
||
+The @option{--push-state} allows one to preserve the current state of the
|
||
+flags which govern the input file handling so that they can all be
|
||
+restored with one corresponding @option{--pop-state} option.
|
||
+
|
||
+The option which are covered are: @option{-Bdynamic}, @option{-Bstatic},
|
||
+@option{-dn}, @option{-dy}, @option{-call_shared}, @option{-non_shared},
|
||
+@option{-static}, @option{-N}, @option{-n}, @option{--whole-archive},
|
||
+@option{--no-whole-archive}, @option{-r}, @option{-Ur},
|
||
+@option{--copy-dt-needed-entries}, @option{--no-copy-dt-needed-entries},
|
||
+@option{--as-needed}, @option{--no-as-needed}, and @option{-a}.
|
||
+
|
||
+One target for this option are specifications for @file{pkg-config}. When
|
||
+used with the @option{--libs} option all possibly needed libraries are
|
||
+listed and then possibly linked with all the time. It is better to return
|
||
+something as follows:
|
||
+
|
||
+@smallexample
|
||
+-Wl,--push-state,--as-needed -libone -libtwo -Wl,--pop-state
|
||
+@end smallexample
|
||
+
|
||
+@kindex --pop-state
|
||
+@cindex pop state governing input file handling
|
||
+@item --pop-state
|
||
+Undoes the effect of --push-state, restores the previous values of the
|
||
+flags governing input file handling.
|
||
+
|
||
+@kindex -q
|
||
+@kindex --emit-relocs
|
||
+@cindex retain relocations in final executable
|
||
+@item -q
|
||
+@itemx --emit-relocs
|
||
+Leave relocation sections and contents in fully linked executables.
|
||
+Post link analysis and optimization tools may need this information in
|
||
+order to perform correct modifications of executables. This results
|
||
+in larger executables.
|
||
+
|
||
+This option is currently only supported on ELF platforms.
|
||
+
|
||
+@kindex --force-dynamic
|
||
+@cindex forcing the creation of dynamic sections
|
||
+@item --force-dynamic
|
||
+Force the output file to have dynamic sections. This option is specific
|
||
+to VxWorks targets.
|
||
+
|
||
+@cindex partial link
|
||
+@cindex relocatable output
|
||
+@kindex -r
|
||
+@kindex --relocatable
|
||
+@item -r
|
||
+@itemx --relocatable
|
||
+Generate relocatable output---i.e., generate an output file that can in
|
||
+turn serve as input to @command{ld}. This is often called @dfn{partial
|
||
+linking}. As a side effect, in environments that support standard Unix
|
||
+magic numbers, this option also sets the output file's magic number to
|
||
+@code{OMAGIC}.
|
||
+@c ; see @option{-N}.
|
||
+If this option is not specified, an absolute file is produced. When
|
||
+linking C++ programs, this option @emph{will not} resolve references to
|
||
+constructors; to do that, use @samp{-Ur}.
|
||
+
|
||
+When an input file does not have the same format as the output file,
|
||
+partial linking is only supported if that input file does not contain any
|
||
+relocations. Different output formats can have further restrictions; for
|
||
+example some @code{a.out}-based formats do not support partial linking
|
||
+with input files in other formats at all.
|
||
+
|
||
+This option does the same thing as @samp{-i}.
|
||
+
|
||
+@kindex -R @var{file}
|
||
+@kindex --just-symbols=@var{file}
|
||
+@cindex symbol-only input
|
||
+@item -R @var{filename}
|
||
+@itemx --just-symbols=@var{filename}
|
||
+Read symbol names and their addresses from @var{filename}, but do not
|
||
+relocate it or include it in the output. This allows your output file
|
||
+to refer symbolically to absolute locations of memory defined in other
|
||
+programs. You may use this option more than once.
|
||
+
|
||
+For compatibility with other ELF linkers, if the @option{-R} option is
|
||
+followed by a directory name, rather than a file name, it is treated as
|
||
+the @option{-rpath} option.
|
||
+
|
||
+@kindex -s
|
||
+@kindex --strip-all
|
||
+@cindex strip all symbols
|
||
+@item -s
|
||
+@itemx --strip-all
|
||
+Omit all symbol information from the output file.
|
||
+
|
||
+@kindex -S
|
||
+@kindex --strip-debug
|
||
+@cindex strip debugger symbols
|
||
+@item -S
|
||
+@itemx --strip-debug
|
||
+Omit debugger symbol information (but not all symbols) from the output file.
|
||
+
|
||
+@kindex --strip-discarded
|
||
+@kindex --no-strip-discarded
|
||
+@item --strip-discarded
|
||
+@itemx --no-strip-discarded
|
||
+Omit (or do not omit) global symbols defined in discarded sections.
|
||
+Enabled by default.
|
||
+
|
||
+@kindex -t
|
||
+@kindex --trace
|
||
+@cindex input files, displaying
|
||
+@item -t
|
||
+@itemx --trace
|
||
+Print the names of the input files as @command{ld} processes them. If
|
||
+@samp{-t} is given twice then members within archives are also printed.
|
||
+@samp{-t} output is useful to generate a list of all the object files
|
||
+and scripts involved in linking, for example, when packaging files for
|
||
+a linker bug report.
|
||
+
|
||
+@kindex -T @var{script}
|
||
+@kindex --script=@var{script}
|
||
+@cindex script files
|
||
+@item -T @var{scriptfile}
|
||
+@itemx --script=@var{scriptfile}
|
||
+Use @var{scriptfile} as the linker script. This script replaces
|
||
+@command{ld}'s default linker script (rather than adding to it),
|
||
+unless the script contains @code{INSERT}, so
|
||
+@var{commandfile} must specify everything necessary to describe the
|
||
+output file. @xref{Scripts}. If @var{scriptfile} does not exist in
|
||
+the current directory, @code{ld} looks for it in the directories
|
||
+specified by any preceding @samp{-L} options. Multiple @samp{-T}
|
||
+options accumulate.
|
||
+
|
||
+@kindex -dT @var{script}
|
||
+@kindex --default-script=@var{script}
|
||
+@cindex script files
|
||
+@item -dT @var{scriptfile}
|
||
+@itemx --default-script=@var{scriptfile}
|
||
+Use @var{scriptfile} as the default linker script. @xref{Scripts}.
|
||
+
|
||
+This option is similar to the @option{--script} option except that
|
||
+processing of the script is delayed until after the rest of the
|
||
+command line has been processed. This allows options placed after the
|
||
+@option{--default-script} option on the command line to affect the
|
||
+behaviour of the linker script, which can be important when the linker
|
||
+command line cannot be directly controlled by the user. (eg because
|
||
+the command line is being constructed by another tool, such as
|
||
+@samp{gcc}).
|
||
+
|
||
+@kindex -u @var{symbol}
|
||
+@kindex --undefined=@var{symbol}
|
||
+@cindex undefined symbol
|
||
+@item -u @var{symbol}
|
||
+@itemx --undefined=@var{symbol}
|
||
+Force @var{symbol} to be entered in the output file as an undefined
|
||
+symbol. Doing this may, for example, trigger linking of additional
|
||
+modules from standard libraries. @samp{-u} may be repeated with
|
||
+different option arguments to enter additional undefined symbols. This
|
||
+option is equivalent to the @code{EXTERN} linker script command.
|
||
+
|
||
+If this option is being used to force additional modules to be pulled
|
||
+into the link, and if it is an error for the symbol to remain
|
||
+undefined, then the option @option{--require-defined} should be used
|
||
+instead.
|
||
+
|
||
+@kindex --require-defined=@var{symbol}
|
||
+@cindex symbols, require defined
|
||
+@cindex defined symbol
|
||
+@item --require-defined=@var{symbol}
|
||
+Require that @var{symbol} is defined in the output file. This option
|
||
+is the same as option @option{--undefined} except that if @var{symbol}
|
||
+is not defined in the output file then the linker will issue an error
|
||
+and exit. The same effect can be achieved in a linker script by using
|
||
+@code{EXTERN}, @code{ASSERT} and @code{DEFINED} together. This option
|
||
+can be used multiple times to require additional symbols.
|
||
+
|
||
+@kindex -Ur
|
||
+@cindex constructors
|
||
+@item -Ur
|
||
+
|
||
+For programs that do not use constructors or destructors, or for ELF
|
||
+based systems this option is equivalent to @option{-r}: it generates
|
||
+relocatable output---i.e., an output file that can in turn serve as
|
||
+input to @command{ld}. For other binaries however the @option{-Ur}
|
||
+option is similar to @option{-r} but it also resolves references to
|
||
+constructors and destructors.
|
||
+
|
||
+For those systems where @option{-r} and @option{-Ur} behave
|
||
+differently, it does not work to use @option{-Ur} on files that were
|
||
+themselves linked with @option{-Ur}; once the constructor table has
|
||
+been built, it cannot be added to. Use @option{-Ur} only for the last
|
||
+partial link, and @option{-r} for the others.
|
||
+
|
||
+@kindex --orphan-handling=@var{MODE}
|
||
+@cindex orphan sections
|
||
+@cindex sections, orphan
|
||
+@item --orphan-handling=@var{MODE}
|
||
+Control how orphan sections are handled. An orphan section is one not
|
||
+specifically mentioned in a linker script. @xref{Orphan Sections}.
|
||
+
|
||
+@var{MODE} can have any of the following values:
|
||
+
|
||
+@table @code
|
||
+@item place
|
||
+Orphan sections are placed into a suitable output section following
|
||
+the strategy described in @ref{Orphan Sections}. The option
|
||
+@samp{--unique} also affects how sections are placed.
|
||
+
|
||
+@item discard
|
||
+All orphan sections are discarded, by placing them in the
|
||
+@samp{/DISCARD/} section (@pxref{Output Section Discarding}).
|
||
+
|
||
+@item warn
|
||
+The linker will place the orphan section as for @code{place} and also
|
||
+issue a warning.
|
||
+
|
||
+@item error
|
||
+The linker will exit with an error if any orphan section is found.
|
||
+@end table
|
||
+
|
||
+The default if @samp{--orphan-handling} is not given is @code{place}.
|
||
+
|
||
+@kindex --unique[=@var{SECTION}]
|
||
+@item --unique[=@var{SECTION}]
|
||
+Creates a separate output section for every input section matching
|
||
+@var{SECTION}, or if the optional wildcard @var{SECTION} argument is
|
||
+missing, for every orphan input section. An orphan section is one not
|
||
+specifically mentioned in a linker script. You may use this option
|
||
+multiple times on the command line; It prevents the normal merging of
|
||
+input sections with the same name, overriding output section assignments
|
||
+in a linker script.
|
||
+
|
||
+@kindex -v
|
||
+@kindex -V
|
||
+@kindex --version
|
||
+@cindex version
|
||
+@item -v
|
||
+@itemx --version
|
||
+@itemx -V
|
||
+Display the version number for @command{ld}. The @option{-V} option also
|
||
+lists the supported emulations. See also the description of the
|
||
+@option{--enable-linker-version} in @ref{Options,,Command-line Options}
|
||
+which can be used to insert the linker version string into a binary.
|
||
+
|
||
+@kindex -x
|
||
+@kindex --discard-all
|
||
+@cindex deleting local symbols
|
||
+@item -x
|
||
+@itemx --discard-all
|
||
+Delete all local symbols.
|
||
+
|
||
+@kindex -X
|
||
+@kindex --discard-locals
|
||
+@cindex local symbols, deleting
|
||
+@item -X
|
||
+@itemx --discard-locals
|
||
+Delete all temporary local symbols. (These symbols start with
|
||
+system-specific local label prefixes, typically @samp{.L} for ELF systems
|
||
+or @samp{L} for traditional a.out systems.)
|
||
+
|
||
+@kindex -y @var{symbol}
|
||
+@kindex --trace-symbol=@var{symbol}
|
||
+@cindex symbol tracing
|
||
+@item -y @var{symbol}
|
||
+@itemx --trace-symbol=@var{symbol}
|
||
+Print the name of each linked file in which @var{symbol} appears. This
|
||
+option may be given any number of times. On many systems it is necessary
|
||
+to prepend an underscore.
|
||
+
|
||
+This option is useful when you have an undefined symbol in your link but
|
||
+don't know where the reference is coming from.
|
||
+
|
||
+@kindex -Y @var{path}
|
||
+@item -Y @var{path}
|
||
+Add @var{path} to the default library search path. This option exists
|
||
+for Solaris compatibility.
|
||
+
|
||
+@kindex -z @var{keyword}
|
||
+@item -z @var{keyword}
|
||
+The recognized keywords are:
|
||
+@table @samp
|
||
+
|
||
+@item call-nop=prefix-addr
|
||
+@itemx call-nop=suffix-nop
|
||
+@itemx call-nop=prefix-@var{byte}
|
||
+@itemx call-nop=suffix-@var{byte}
|
||
+Specify the 1-byte @code{NOP} padding when transforming indirect call
|
||
+to a locally defined function, foo, via its GOT slot.
|
||
+@option{call-nop=prefix-addr} generates @code{0x67 call foo}.
|
||
+@option{call-nop=suffix-nop} generates @code{call foo 0x90}.
|
||
+@option{call-nop=prefix-@var{byte}} generates @code{@var{byte} call foo}.
|
||
+@option{call-nop=suffix-@var{byte}} generates @code{call foo @var{byte}}.
|
||
+Supported for i386 and x86_64.
|
||
+
|
||
+@item cet-report=none
|
||
+@itemx cet-report=warning
|
||
+@itemx cet-report=error
|
||
+Specify how to report the missing GNU_PROPERTY_X86_FEATURE_1_IBT and
|
||
+GNU_PROPERTY_X86_FEATURE_1_SHSTK properties in input .note.gnu.property
|
||
+section. @option{cet-report=none}, which is the default, will make the
|
||
+linker not report missing properties in input files.
|
||
+@option{cet-report=warning} will make the linker issue a warning for
|
||
+missing properties in input files. @option{cet-report=error} will make
|
||
+the linker issue an error for missing properties in input files.
|
||
+Note that @option{ibt} will turn off the missing
|
||
+GNU_PROPERTY_X86_FEATURE_1_IBT property report and @option{shstk} will
|
||
+turn off the missing GNU_PROPERTY_X86_FEATURE_1_SHSTK property report.
|
||
+Supported for Linux/i386 and Linux/x86_64.
|
||
+
|
||
+@item combreloc
|
||
+@itemx nocombreloc
|
||
+Combine multiple dynamic relocation sections and sort to improve
|
||
+dynamic symbol lookup caching. Do not do this if @samp{nocombreloc}.
|
||
+
|
||
+@item common
|
||
+@itemx nocommon
|
||
+Generate common symbols with STT_COMMON type during a relocatable
|
||
+link. Use STT_OBJECT type if @samp{nocommon}.
|
||
+
|
||
+@item common-page-size=@var{value}
|
||
+Set the page size most commonly used to @var{value}. Memory image
|
||
+layout will be optimized to minimize memory pages if the system is
|
||
+using pages of this size.
|
||
+
|
||
+@item defs
|
||
+Report unresolved symbol references from regular object files. This
|
||
+is done even if the linker is creating a non-symbolic shared library.
|
||
+This option is the inverse of @samp{-z undefs}.
|
||
+
|
||
+@item dynamic-undefined-weak
|
||
+@itemx nodynamic-undefined-weak
|
||
+Make undefined weak symbols dynamic when building a dynamic object,
|
||
+if they are referenced from a regular object file and not forced local
|
||
+by symbol visibility or versioning. Do not make them dynamic if
|
||
+@samp{nodynamic-undefined-weak}. If neither option is given, a target
|
||
+may default to either option being in force, or make some other
|
||
+selection of undefined weak symbols dynamic. Not all targets support
|
||
+these options.
|
||
+
|
||
+@item execstack
|
||
+Marks the object as requiring executable stack.
|
||
+
|
||
+@item global
|
||
+This option is only meaningful when building a shared object. It makes
|
||
+the symbols defined by this shared object available for symbol resolution
|
||
+of subsequently loaded libraries.
|
||
+
|
||
+@item globalaudit
|
||
+This option is only meaningful when building a dynamic executable.
|
||
+This option marks the executable as requiring global auditing by
|
||
+setting the @code{DF_1_GLOBAUDIT} bit in the @code{DT_FLAGS_1} dynamic
|
||
+tag. Global auditing requires that any auditing library defined via
|
||
+the @option{--depaudit} or @option{-P} command-line options be run for
|
||
+all dynamic objects loaded by the application.
|
||
+
|
||
+@item ibtplt
|
||
+Generate Intel Indirect Branch Tracking (IBT) enabled PLT entries.
|
||
+Supported for Linux/i386 and Linux/x86_64.
|
||
+
|
||
+@item ibt
|
||
+Generate GNU_PROPERTY_X86_FEATURE_1_IBT in .note.gnu.property section
|
||
+to indicate compatibility with IBT. This also implies @option{ibtplt}.
|
||
+Supported for Linux/i386 and Linux/x86_64.
|
||
+
|
||
+@item indirect-extern-access
|
||
+@itemx noindirect-extern-access
|
||
+Generate GNU_PROPERTY_1_NEEDED_INDIRECT_EXTERN_ACCESS in
|
||
+.note.gnu.property section to indicate that object file requires
|
||
+canonical function pointers and cannot be used with copy relocation.
|
||
+This option also implies @option{noextern-protected-data} and
|
||
+@option{nocopyreloc}. Supported for i386 and x86-64.
|
||
+
|
||
+@option{noindirect-extern-access} removes
|
||
+GNU_PROPERTY_1_NEEDED_INDIRECT_EXTERN_ACCESS from .note.gnu.property
|
||
+section.
|
||
+
|
||
+@item initfirst
|
||
+This option is only meaningful when building a shared object.
|
||
+It marks the object so that its runtime initialization will occur
|
||
+before the runtime initialization of any other objects brought into
|
||
+the process at the same time. Similarly the runtime finalization of
|
||
+the object will occur after the runtime finalization of any other
|
||
+objects.
|
||
+
|
||
+@item interpose
|
||
+Specify that the dynamic loader should modify its symbol search order
|
||
+so that symbols in this shared library interpose all other shared
|
||
+libraries not so marked.
|
||
+
|
||
+@item unique
|
||
+@itemx nounique
|
||
+When generating a shared library or other dynamically loadable ELF
|
||
+object mark it as one that should (by default) only ever be loaded once,
|
||
+and only in the main namespace (when using @code{dlmopen}). This is
|
||
+primarily used to mark fundamental libraries such as libc, libpthread et
|
||
+al which do not usually function correctly unless they are the sole instances
|
||
+of themselves. This behaviour can be overridden by the @code{dlmopen} caller
|
||
+and does not apply to certain loading mechanisms (such as audit libraries).
|
||
+
|
||
+@item lam-u48
|
||
+Generate GNU_PROPERTY_X86_FEATURE_1_LAM_U48 in .note.gnu.property section
|
||
+to indicate compatibility with Intel LAM_U48. Supported for Linux/x86_64.
|
||
+
|
||
+@item lam-u57
|
||
+Generate GNU_PROPERTY_X86_FEATURE_1_LAM_U57 in .note.gnu.property section
|
||
+to indicate compatibility with Intel LAM_U57. Supported for Linux/x86_64.
|
||
+
|
||
+@item lam-u48-report=none
|
||
+@itemx lam-u48-report=warning
|
||
+@itemx lam-u48-report=error
|
||
+Specify how to report the missing GNU_PROPERTY_X86_FEATURE_1_LAM_U48
|
||
+property in input .note.gnu.property section.
|
||
+@option{lam-u48-report=none}, which is the default, will make the
|
||
+linker not report missing properties in input files.
|
||
+@option{lam-u48-report=warning} will make the linker issue a warning for
|
||
+missing properties in input files. @option{lam-u48-report=error} will
|
||
+make the linker issue an error for missing properties in input files.
|
||
+Supported for Linux/x86_64.
|
||
+
|
||
+@item lam-u57-report=none
|
||
+@itemx lam-u57-report=warning
|
||
+@itemx lam-u57-report=error
|
||
+Specify how to report the missing GNU_PROPERTY_X86_FEATURE_1_LAM_U57
|
||
+property in input .note.gnu.property section.
|
||
+@option{lam-u57-report=none}, which is the default, will make the
|
||
+linker not report missing properties in input files.
|
||
+@option{lam-u57-report=warning} will make the linker issue a warning for
|
||
+missing properties in input files. @option{lam-u57-report=error} will
|
||
+make the linker issue an error for missing properties in input files.
|
||
+Supported for Linux/x86_64.
|
||
+
|
||
+@item lam-report=none
|
||
+@itemx lam-report=warning
|
||
+@itemx lam-report=error
|
||
+Specify how to report the missing GNU_PROPERTY_X86_FEATURE_1_LAM_U48 and
|
||
+GNU_PROPERTY_X86_FEATURE_1_LAM_U57 properties in input .note.gnu.property
|
||
+section. @option{lam-report=none}, which is the default, will make the
|
||
+linker not report missing properties in input files.
|
||
+@option{lam-report=warning} will make the linker issue a warning for
|
||
+missing properties in input files. @option{lam-report=error} will make
|
||
+the linker issue an error for missing properties in input files.
|
||
+Supported for Linux/x86_64.
|
||
+
|
||
+@item lazy
|
||
+When generating an executable or shared library, mark it to tell the
|
||
+dynamic linker to defer function call resolution to the point when
|
||
+the function is called (lazy binding), rather than at load time.
|
||
+Lazy binding is the default.
|
||
+
|
||
+@item loadfltr
|
||
+Specify that the object's filters be processed immediately at runtime.
|
||
+
|
||
+@item max-page-size=@var{value}
|
||
+Set the maximum memory page size supported to @var{value}.
|
||
+
|
||
+@item muldefs
|
||
+Allow multiple definitions.
|
||
+
|
||
+@item nocopyreloc
|
||
+Disable linker generated .dynbss variables used in place of variables
|
||
+defined in shared libraries. May result in dynamic text relocations.
|
||
+
|
||
+@item nodefaultlib
|
||
+Specify that the dynamic loader search for dependencies of this object
|
||
+should ignore any default library search paths.
|
||
+
|
||
+@item nodelete
|
||
+Specify that the object shouldn't be unloaded at runtime.
|
||
+
|
||
+@item nodlopen
|
||
+Specify that the object is not available to @code{dlopen}.
|
||
+
|
||
+@item nodump
|
||
+Specify that the object can not be dumped by @code{dldump}.
|
||
+
|
||
+@item noexecstack
|
||
+Marks the object as not requiring executable stack.
|
||
+
|
||
+@item noextern-protected-data
|
||
+Don't treat protected data symbols as external when building a shared
|
||
+library. This option overrides the linker backend default. It can be
|
||
+used to work around incorrect relocations against protected data symbols
|
||
+generated by compiler. Updates on protected data symbols by another
|
||
+module aren't visible to the resulting shared library. Supported for
|
||
+i386 and x86-64.
|
||
+
|
||
+@item noreloc-overflow
|
||
+Disable relocation overflow check. This can be used to disable
|
||
+relocation overflow check if there will be no dynamic relocation
|
||
+overflow at run-time. Supported for x86_64.
|
||
+
|
||
+@item now
|
||
+When generating an executable or shared library, mark it to tell the
|
||
+dynamic linker to resolve all symbols when the program is started, or
|
||
+when the shared library is loaded by dlopen, instead of deferring
|
||
+function call resolution to the point when the function is first
|
||
+called.
|
||
+
|
||
+@item origin
|
||
+Specify that the object requires @samp{$ORIGIN} handling in paths.
|
||
+
|
||
+@item pack-relative-relocs
|
||
+@itemx nopack-relative-relocs
|
||
+Generate compact relative relocation in position-independent executable
|
||
+and shared library. It adds @code{DT_RELR}, @code{DT_RELRSZ} and
|
||
+@code{DT_RELRENT} entries to the dynamic section. It is ignored when
|
||
+building position-dependent executable and relocatable output.
|
||
+@option{nopack-relative-relocs} is the default, which disables compact
|
||
+relative relocation. When linked against the GNU C Library, a
|
||
+GLIBC_ABI_DT_RELR symbol version dependency on the shared C Library is
|
||
+added to the output. Supported for i386 and x86-64.
|
||
+
|
||
+@item relro
|
||
+@itemx norelro
|
||
+Create an ELF @code{PT_GNU_RELRO} segment header in the object. This
|
||
+specifies a memory segment that should be made read-only after
|
||
+relocation, if supported. Specifying @samp{common-page-size} smaller
|
||
+than the system page size will render this protection ineffective.
|
||
+Don't create an ELF @code{PT_GNU_RELRO} segment if @samp{norelro}.
|
||
+
|
||
+@item report-relative-reloc
|
||
+Report dynamic relative relocations generated by linker. Supported for
|
||
+Linux/i386 and Linux/x86_64.
|
||
+
|
||
+@item sectionheader
|
||
+@itemx nosectionheader
|
||
+Generate section header. Don't generate section header if
|
||
+@samp{nosectionheader} is used. @option{sectionheader} is the default.
|
||
+
|
||
+@item separate-code
|
||
+@itemx noseparate-code
|
||
+Create separate code @code{PT_LOAD} segment header in the object. This
|
||
+specifies a memory segment that should contain only instructions and must
|
||
+be in wholly disjoint pages from any other data. Don't create separate
|
||
+code @code{PT_LOAD} segment if @samp{noseparate-code} is used.
|
||
+
|
||
+@item shstk
|
||
+Generate GNU_PROPERTY_X86_FEATURE_1_SHSTK in .note.gnu.property section
|
||
+to indicate compatibility with Intel Shadow Stack. Supported for
|
||
+Linux/i386 and Linux/x86_64.
|
||
+
|
||
+@item stack-size=@var{value}
|
||
+Specify a stack size for an ELF @code{PT_GNU_STACK} segment.
|
||
+Specifying zero will override any default non-zero sized
|
||
+@code{PT_GNU_STACK} segment creation.
|
||
+
|
||
+@item start-stop-gc
|
||
+@itemx nostart-stop-gc
|
||
+@cindex start-stop-gc
|
||
+When @samp{--gc-sections} is in effect, a reference from a retained
|
||
+section to @code{__start_SECNAME} or @code{__stop_SECNAME} causes all
|
||
+input sections named @code{SECNAME} to also be retained, if
|
||
+@code{SECNAME} is representable as a C identifier and either
|
||
+@code{__start_SECNAME} or @code{__stop_SECNAME} is synthesized by the
|
||
+linker. @samp{-z start-stop-gc} disables this effect, allowing
|
||
+sections to be garbage collected as if the special synthesized symbols
|
||
+were not defined. @samp{-z start-stop-gc} has no effect on a
|
||
+definition of @code{__start_SECNAME} or @code{__stop_SECNAME} in an
|
||
+object file or linker script. Such a definition will prevent the
|
||
+linker providing a synthesized @code{__start_SECNAME} or
|
||
+@code{__stop_SECNAME} respectively, and therefore the special
|
||
+treatment by garbage collection for those references.
|
||
+
|
||
+@item start-stop-visibility=@var{value}
|
||
+@cindex visibility
|
||
+@cindex ELF symbol visibility
|
||
+Specify the ELF symbol visibility for synthesized
|
||
+@code{__start_SECNAME} and @code{__stop_SECNAME} symbols (@pxref{Input
|
||
+Section Example}). @var{value} must be exactly @samp{default},
|
||
+@samp{internal}, @samp{hidden}, or @samp{protected}. If no @samp{-z
|
||
+start-stop-visibility} option is given, @samp{protected} is used for
|
||
+compatibility with historical practice. However, it's highly
|
||
+recommended to use @samp{-z start-stop-visibility=hidden} in new
|
||
+programs and shared libraries so that these symbols are not exported
|
||
+between shared objects, which is not usually what's intended.
|
||
+
|
||
+@item text
|
||
+@itemx notext
|
||
+@itemx textoff
|
||
+Report an error if DT_TEXTREL is set, i.e., if the position-independent
|
||
+or shared object has dynamic relocations in read-only sections. Don't
|
||
+report an error if @samp{notext} or @samp{textoff}.
|
||
+
|
||
+@item undefs
|
||
+Do not report unresolved symbol references from regular object files,
|
||
+either when creating an executable, or when creating a shared library.
|
||
+This option is the inverse of @samp{-z defs}.
|
||
+
|
||
+@item unique-symbol
|
||
+@itemx nounique-symbol
|
||
+Avoid duplicated local symbol names in the symbol string table. Append
|
||
+".@code{number}" to duplicated local symbol names if @samp{unique-symbol}
|
||
+is used. @option{nounique-symbol} is the default.
|
||
+
|
||
+@item x86-64-baseline
|
||
+@item x86-64-v2
|
||
+@item x86-64-v3
|
||
+@itemx x86-64-v4
|
||
+Specify the x86-64 ISA level needed in .note.gnu.property section.
|
||
+@option{x86-64-baseline} generates @code{GNU_PROPERTY_X86_ISA_1_BASELINE}.
|
||
+@option{x86-64-v2} generates @code{GNU_PROPERTY_X86_ISA_1_V2}.
|
||
+@option{x86-64-v3} generates @code{GNU_PROPERTY_X86_ISA_1_V3}.
|
||
+@option{x86-64-v4} generates @code{GNU_PROPERTY_X86_ISA_1_V4}.
|
||
+Supported for Linux/i386 and Linux/x86_64.
|
||
+
|
||
+@end table
|
||
+
|
||
+Other keywords are ignored for Solaris compatibility.
|
||
+
|
||
+@kindex -(
|
||
+@cindex groups of archives
|
||
+@item -( @var{archives} -)
|
||
+@itemx --start-group @var{archives} --end-group
|
||
+The @var{archives} should be a list of archive files. They may be
|
||
+either explicit file names, or @samp{-l} options.
|
||
+
|
||
+The specified archives are searched repeatedly until no new undefined
|
||
+references are created. Normally, an archive is searched only once in
|
||
+the order that it is specified on the command line. If a symbol in that
|
||
+archive is needed to resolve an undefined symbol referred to by an
|
||
+object in an archive that appears later on the command line, the linker
|
||
+would not be able to resolve that reference. By grouping the archives,
|
||
+they will all be searched repeatedly until all possible references are
|
||
+resolved.
|
||
+
|
||
+Using this option has a significant performance cost. It is best to use
|
||
+it only when there are unavoidable circular references between two or
|
||
+more archives.
|
||
+
|
||
+@kindex --accept-unknown-input-arch
|
||
+@kindex --no-accept-unknown-input-arch
|
||
+@item --accept-unknown-input-arch
|
||
+@itemx --no-accept-unknown-input-arch
|
||
+Tells the linker to accept input files whose architecture cannot be
|
||
+recognised. The assumption is that the user knows what they are doing
|
||
+and deliberately wants to link in these unknown input files. This was
|
||
+the default behaviour of the linker, before release 2.14. The default
|
||
+behaviour from release 2.14 onwards is to reject such input files, and
|
||
+so the @samp{--accept-unknown-input-arch} option has been added to
|
||
+restore the old behaviour.
|
||
+
|
||
+@kindex --as-needed
|
||
+@kindex --no-as-needed
|
||
+@item --as-needed
|
||
+@itemx --no-as-needed
|
||
+This option affects ELF DT_NEEDED tags for dynamic libraries mentioned
|
||
+on the command line after the @option{--as-needed} option. Normally
|
||
+the linker will add a DT_NEEDED tag for each dynamic library mentioned
|
||
+on the command line, regardless of whether the library is actually
|
||
+needed or not. @option{--as-needed} causes a DT_NEEDED tag to only be
|
||
+emitted for a library that @emph{at that point in the link} satisfies a
|
||
+non-weak undefined symbol reference from a regular object file or, if
|
||
+the library is not found in the DT_NEEDED lists of other needed libraries, a
|
||
+non-weak undefined symbol reference from another needed dynamic library.
|
||
+Object files or libraries appearing on the command line @emph{after}
|
||
+the library in question do not affect whether the library is seen as
|
||
+needed. This is similar to the rules for extraction of object files
|
||
+from archives. @option{--no-as-needed} restores the default behaviour.
|
||
+
|
||
+Note: On Linux based systems the @option{--as-needed} option also has
|
||
+an affect on the behaviour of the @option{--rpath} and
|
||
+@option{--rpath-link} options. See the description of
|
||
+@option{--rpath-link} for more details.
|
||
+
|
||
+@kindex --add-needed
|
||
+@kindex --no-add-needed
|
||
+@item --add-needed
|
||
+@itemx --no-add-needed
|
||
+These two options have been deprecated because of the similarity of
|
||
+their names to the @option{--as-needed} and @option{--no-as-needed}
|
||
+options. They have been replaced by @option{--copy-dt-needed-entries}
|
||
+and @option{--no-copy-dt-needed-entries}.
|
||
+
|
||
+@kindex -assert @var{keyword}
|
||
+@item -assert @var{keyword}
|
||
+This option is ignored for SunOS compatibility.
|
||
+
|
||
+@kindex -Bdynamic
|
||
+@kindex -dy
|
||
+@kindex -call_shared
|
||
+@item -Bdynamic
|
||
+@itemx -dy
|
||
+@itemx -call_shared
|
||
+Link against dynamic libraries. This is only meaningful on platforms
|
||
+for which shared libraries are supported. This option is normally the
|
||
+default on such platforms. The different variants of this option are
|
||
+for compatibility with various systems. You may use this option
|
||
+multiple times on the command line: it affects library searching for
|
||
+@option{-l} options which follow it.
|
||
+
|
||
+@kindex -Bgroup
|
||
+@item -Bgroup
|
||
+Set the @code{DF_1_GROUP} flag in the @code{DT_FLAGS_1} entry in the dynamic
|
||
+section. This causes the runtime linker to handle lookups in this
|
||
+object and its dependencies to be performed only inside the group.
|
||
+@option{--unresolved-symbols=report-all} is implied. This option is
|
||
+only meaningful on ELF platforms which support shared libraries.
|
||
+
|
||
+@kindex -Bstatic
|
||
+@kindex -dn
|
||
+@kindex -non_shared
|
||
+@kindex -static
|
||
+@item -Bstatic
|
||
+@itemx -dn
|
||
+@itemx -non_shared
|
||
+@itemx -static
|
||
+Do not link against shared libraries. This is only meaningful on
|
||
+platforms for which shared libraries are supported. The different
|
||
+variants of this option are for compatibility with various systems. You
|
||
+may use this option multiple times on the command line: it affects
|
||
+library searching for @option{-l} options which follow it. This
|
||
+option also implies @option{--unresolved-symbols=report-all}. This
|
||
+option can be used with @option{-shared}. Doing so means that a
|
||
+shared library is being created but that all of the library's external
|
||
+references must be resolved by pulling in entries from static
|
||
+libraries.
|
||
+
|
||
+@kindex -Bsymbolic
|
||
+@item -Bsymbolic
|
||
+When creating a shared library, bind references to global symbols to the
|
||
+definition within the shared library, if any. Normally, it is possible
|
||
+for a program linked against a shared library to override the definition
|
||
+within the shared library. This option is only meaningful on ELF
|
||
+platforms which support shared libraries.
|
||
+
|
||
+@kindex -Bsymbolic-functions
|
||
+@item -Bsymbolic-functions
|
||
+When creating a shared library, bind references to global function
|
||
+symbols to the definition within the shared library, if any.
|
||
+This option is only meaningful on ELF platforms which support shared
|
||
+libraries.
|
||
+
|
||
+@kindex -Bno-symbolic
|
||
+@item -Bno-symbolic
|
||
+This option can cancel previously specified @samp{-Bsymbolic} and
|
||
+@samp{-Bsymbolic-functions}.
|
||
+
|
||
+@kindex --dynamic-list=@var{dynamic-list-file}
|
||
+@item --dynamic-list=@var{dynamic-list-file}
|
||
+Specify the name of a dynamic list file to the linker. This is
|
||
+typically used when creating shared libraries to specify a list of
|
||
+global symbols whose references shouldn't be bound to the definition
|
||
+within the shared library, or creating dynamically linked executables
|
||
+to specify a list of symbols which should be added to the symbol table
|
||
+in the executable. This option is only meaningful on ELF platforms
|
||
+which support shared libraries.
|
||
+
|
||
+The format of the dynamic list is the same as the version node without
|
||
+scope and node name. See @ref{VERSION} for more information.
|
||
+
|
||
+@kindex --dynamic-list-data
|
||
+@item --dynamic-list-data
|
||
+Include all global data symbols to the dynamic list.
|
||
+
|
||
+@kindex --dynamic-list-cpp-new
|
||
+@item --dynamic-list-cpp-new
|
||
+Provide the builtin dynamic list for C++ operator new and delete. It
|
||
+is mainly useful for building shared libstdc++.
|
||
+
|
||
+@kindex --dynamic-list-cpp-typeinfo
|
||
+@item --dynamic-list-cpp-typeinfo
|
||
+Provide the builtin dynamic list for C++ runtime type identification.
|
||
+
|
||
+@kindex --check-sections
|
||
+@kindex --no-check-sections
|
||
+@item --check-sections
|
||
+@itemx --no-check-sections
|
||
+Asks the linker @emph{not} to check section addresses after they have
|
||
+been assigned to see if there are any overlaps. Normally the linker will
|
||
+perform this check, and if it finds any overlaps it will produce
|
||
+suitable error messages. The linker does know about, and does make
|
||
+allowances for sections in overlays. The default behaviour can be
|
||
+restored by using the command-line switch @option{--check-sections}.
|
||
+Section overlap is not usually checked for relocatable links. You can
|
||
+force checking in that case by using the @option{--check-sections}
|
||
+option.
|
||
+
|
||
+@kindex --copy-dt-needed-entries
|
||
+@kindex --no-copy-dt-needed-entries
|
||
+@item --copy-dt-needed-entries
|
||
+@itemx --no-copy-dt-needed-entries
|
||
+This option affects the treatment of dynamic libraries referred to
|
||
+by DT_NEEDED tags @emph{inside} ELF dynamic libraries mentioned on the
|
||
+command line. Normally the linker won't add a DT_NEEDED tag to the
|
||
+output binary for each library mentioned in a DT_NEEDED tag in an
|
||
+input dynamic library. With @option{--copy-dt-needed-entries}
|
||
+specified on the command line however any dynamic libraries that
|
||
+follow it will have their DT_NEEDED entries added. The default
|
||
+behaviour can be restored with @option{--no-copy-dt-needed-entries}.
|
||
+
|
||
+This option also has an effect on the resolution of symbols in dynamic
|
||
+libraries. With @option{--copy-dt-needed-entries} dynamic libraries
|
||
+mentioned on the command line will be recursively searched, following
|
||
+their DT_NEEDED tags to other libraries, in order to resolve symbols
|
||
+required by the output binary. With the default setting however
|
||
+the searching of dynamic libraries that follow it will stop with the
|
||
+dynamic library itself. No DT_NEEDED links will be traversed to resolve
|
||
+symbols.
|
||
+
|
||
+@cindex cross reference table
|
||
+@kindex --cref
|
||
+@item --cref
|
||
+Output a cross reference table. If a linker map file is being
|
||
+generated, the cross reference table is printed to the map file.
|
||
+Otherwise, it is printed on the standard output.
|
||
+
|
||
+The format of the table is intentionally simple, so that it may be
|
||
+easily processed by a script if necessary. The symbols are printed out,
|
||
+sorted by name. For each symbol, a list of file names is given. If the
|
||
+symbol is defined, the first file listed is the location of the
|
||
+definition. If the symbol is defined as a common value then any files
|
||
+where this happens appear next. Finally any files that reference the
|
||
+symbol are listed.
|
||
+
|
||
+@cindex ctf variables
|
||
+@kindex --ctf-variables
|
||
+@kindex --no-ctf-variables
|
||
+@item --ctf-variables
|
||
+@item --no-ctf-variables
|
||
+The CTF debuginfo format supports a section which encodes the names and
|
||
+types of variables found in the program which do not appear in any symbol
|
||
+table. These variables clearly cannot be looked up by address by
|
||
+conventional debuggers, so the space used for their types and names is
|
||
+usually wasted: the types are usually small but the names are often not.
|
||
+@option{--ctf-variables} causes the generation of such a section.
|
||
+The default behaviour can be restored with @option{--no-ctf-variables}.
|
||
+
|
||
+@cindex ctf type sharing
|
||
+@kindex --ctf-share-types
|
||
+@item --ctf-share-types=@var{method}
|
||
+Adjust the method used to share types between translation units in CTF.
|
||
+
|
||
+@table @samp
|
||
+@item share-unconflicted
|
||
+Put all types that do not have ambiguous definitions into the shared dictionary,
|
||
+where debuggers can easily access them, even if they only occur in one
|
||
+translation unit. This is the default.
|
||
+
|
||
+@item share-duplicated
|
||
+Put only types that occur in multiple translation units into the shared
|
||
+dictionary: types with only one definition go into per-translation-unit
|
||
+dictionaries. Types with ambiguous definitions in multiple translation units
|
||
+always go into per-translation-unit dictionaries. This tends to make the CTF
|
||
+larger, but may reduce the amount of CTF in the shared dictionary. For very
|
||
+large projects this may speed up opening the CTF and save memory in the CTF
|
||
+consumer at runtime.
|
||
+@end table
|
||
+
|
||
+@cindex common allocation
|
||
+@kindex --no-define-common
|
||
+@item --no-define-common
|
||
+This option inhibits the assignment of addresses to common symbols.
|
||
+The script command @code{INHIBIT_COMMON_ALLOCATION} has the same effect.
|
||
+@xref{Miscellaneous Commands}.
|
||
+
|
||
+The @samp{--no-define-common} option allows decoupling
|
||
+the decision to assign addresses to Common symbols from the choice
|
||
+of the output file type; otherwise a non-Relocatable output type
|
||
+forces assigning addresses to Common symbols.
|
||
+Using @samp{--no-define-common} allows Common symbols that are referenced
|
||
+from a shared library to be assigned addresses only in the main program.
|
||
+This eliminates the unused duplicate space in the shared library,
|
||
+and also prevents any possible confusion over resolving to the wrong
|
||
+duplicate when there are many dynamic modules with specialized search
|
||
+paths for runtime symbol resolution.
|
||
+
|
||
+@cindex group allocation in linker script
|
||
+@cindex section groups
|
||
+@cindex COMDAT
|
||
+@kindex --force-group-allocation
|
||
+@item --force-group-allocation
|
||
+This option causes the linker to place section group members like
|
||
+normal input sections, and to delete the section groups. This is the
|
||
+default behaviour for a final link but this option can be used to
|
||
+change the behaviour of a relocatable link (@samp{-r}). The script
|
||
+command @code{FORCE_GROUP_ALLOCATION} has the same
|
||
+effect. @xref{Miscellaneous Commands}.
|
||
+
|
||
+@cindex symbols, from command line
|
||
+@kindex --defsym=@var{symbol}=@var{exp}
|
||
+@item --defsym=@var{symbol}=@var{expression}
|
||
+Create a global symbol in the output file, containing the absolute
|
||
+address given by @var{expression}. You may use this option as many
|
||
+times as necessary to define multiple symbols in the command line. A
|
||
+limited form of arithmetic is supported for the @var{expression} in this
|
||
+context: you may give a hexadecimal constant or the name of an existing
|
||
+symbol, or use @code{+} and @code{-} to add or subtract hexadecimal
|
||
+constants or symbols. If you need more elaborate expressions, consider
|
||
+using the linker command language from a script (@pxref{Assignments}).
|
||
+@emph{Note:} there should be no white space between @var{symbol}, the
|
||
+equals sign (``@key{=}''), and @var{expression}.
|
||
+
|
||
+The linker processes @samp{--defsym} arguments and @samp{-T} arguments
|
||
+in order, placing @samp{--defsym} before @samp{-T} will define the
|
||
+symbol before the linker script from @samp{-T} is processed, while
|
||
+placing @samp{--defsym} after @samp{-T} will define the symbol after
|
||
+the linker script has been processed. This difference has
|
||
+consequences for expressions within the linker script that use the
|
||
+@samp{--defsym} symbols, which order is correct will depend on what
|
||
+you are trying to achieve.
|
||
+
|
||
+@cindex demangling, from command line
|
||
+@kindex --demangle[=@var{style}]
|
||
+@kindex --no-demangle
|
||
+@item --demangle[=@var{style}]
|
||
+@itemx --no-demangle
|
||
+These options control whether to demangle symbol names in error messages
|
||
+and other output. When the linker is told to demangle, it tries to
|
||
+present symbol names in a readable fashion: it strips leading
|
||
+underscores if they are used by the object file format, and converts C++
|
||
+mangled symbol names into user readable names. Different compilers have
|
||
+different mangling styles. The optional demangling style argument can be used
|
||
+to choose an appropriate demangling style for your compiler. The linker will
|
||
+demangle by default unless the environment variable @samp{COLLECT_NO_DEMANGLE}
|
||
+is set. These options may be used to override the default.
|
||
+
|
||
+@cindex dynamic linker, from command line
|
||
+@kindex -I@var{file}
|
||
+@kindex --dynamic-linker=@var{file}
|
||
+@item -I@var{file}
|
||
+@itemx --dynamic-linker=@var{file}
|
||
+Set the name of the dynamic linker. This is only meaningful when
|
||
+generating dynamically linked ELF executables. The default dynamic
|
||
+linker is normally correct; don't use this unless you know what you are
|
||
+doing.
|
||
+
|
||
+@kindex --no-dynamic-linker
|
||
+@item --no-dynamic-linker
|
||
+When producing an executable file, omit the request for a dynamic
|
||
+linker to be used at load-time. This is only meaningful for ELF
|
||
+executables that contain dynamic relocations, and usually requires
|
||
+entry point code that is capable of processing these relocations.
|
||
+
|
||
+@kindex --embedded-relocs
|
||
+@item --embedded-relocs
|
||
+This option is similar to the @option{--emit-relocs} option except
|
||
+that the relocs are stored in a target-specific section. This option
|
||
+is only supported by the @samp{BFIN}, @samp{CR16} and @emph{M68K}
|
||
+targets.
|
||
+
|
||
+@kindex --disable-multiple-abs-defs
|
||
+@item --disable-multiple-abs-defs
|
||
+Do not allow multiple definitions with symbols included
|
||
+in filename invoked by -R or --just-symbols
|
||
+
|
||
+@kindex --fatal-warnings
|
||
+@kindex --no-fatal-warnings
|
||
+@item --fatal-warnings
|
||
+@itemx --no-fatal-warnings
|
||
+Treat all warnings as errors. The default behaviour can be restored
|
||
+with the option @option{--no-fatal-warnings}.
|
||
+
|
||
+@kindex -w
|
||
+@kindex --no-warnings
|
||
+@item -w
|
||
+@itemx --no-warnings
|
||
+Do not display any warning or error messages. This overrides
|
||
+@option{--fatal-warnings} if it has been enabled. This option can be
|
||
+used when it is known that the output binary will not work, but there
|
||
+is still a need to create it.
|
||
+
|
||
+@kindex --force-exe-suffix
|
||
+@item --force-exe-suffix
|
||
+Make sure that an output file has a .exe suffix.
|
||
+
|
||
+If a successfully built fully linked output file does not have a
|
||
+@code{.exe} or @code{.dll} suffix, this option forces the linker to copy
|
||
+the output file to one of the same name with a @code{.exe} suffix. This
|
||
+option is useful when using unmodified Unix makefiles on a Microsoft
|
||
+Windows host, since some versions of Windows won't run an image unless
|
||
+it ends in a @code{.exe} suffix.
|
||
+
|
||
+@kindex --gc-sections
|
||
+@kindex --no-gc-sections
|
||
+@cindex garbage collection
|
||
+@item --gc-sections
|
||
+@itemx --no-gc-sections
|
||
+Enable garbage collection of unused input sections. It is ignored on
|
||
+targets that do not support this option. The default behaviour (of not
|
||
+performing this garbage collection) can be restored by specifying
|
||
+@samp{--no-gc-sections} on the command line. Note that garbage
|
||
+collection for COFF and PE format targets is supported, but the
|
||
+implementation is currently considered to be experimental.
|
||
+
|
||
+@samp{--gc-sections} decides which input sections are used by
|
||
+examining symbols and relocations. The section containing the entry
|
||
+symbol and all sections containing symbols undefined on the
|
||
+command-line will be kept, as will sections containing symbols
|
||
+referenced by dynamic objects. Note that when building shared
|
||
+libraries, the linker must assume that any visible symbol is
|
||
+referenced. Once this initial set of sections has been determined,
|
||
+the linker recursively marks as used any section referenced by their
|
||
+relocations. See @samp{--entry}, @samp{--undefined}, and
|
||
+@samp{--gc-keep-exported}.
|
||
+
|
||
+This option can be set when doing a partial link (enabled with option
|
||
+@samp{-r}). In this case the root of symbols kept must be explicitly
|
||
+specified either by one of the options @samp{--entry},
|
||
+@samp{--undefined}, or @samp{--gc-keep-exported} or by a @code{ENTRY}
|
||
+command in the linker script.
|
||
+
|
||
+As a GNU extension, ELF input sections marked with the
|
||
+@code{SHF_GNU_RETAIN} flag will not be garbage collected.
|
||
+
|
||
+@kindex --print-gc-sections
|
||
+@kindex --no-print-gc-sections
|
||
+@cindex garbage collection
|
||
+@item --print-gc-sections
|
||
+@itemx --no-print-gc-sections
|
||
+List all sections removed by garbage collection. The listing is
|
||
+printed on stderr. This option is only effective if garbage
|
||
+collection has been enabled via the @samp{--gc-sections}) option. The
|
||
+default behaviour (of not listing the sections that are removed) can
|
||
+be restored by specifying @samp{--no-print-gc-sections} on the command
|
||
+line.
|
||
+
|
||
+@kindex --gc-keep-exported
|
||
+@cindex garbage collection
|
||
+@item --gc-keep-exported
|
||
+When @samp{--gc-sections} is enabled, this option prevents garbage
|
||
+collection of unused input sections that contain global symbols having
|
||
+default or protected visibility. This option is intended to be used for
|
||
+executables where unreferenced sections would otherwise be garbage
|
||
+collected regardless of the external visibility of contained symbols.
|
||
+Note that this option has no effect when linking shared objects since
|
||
+it is already the default behaviour. This option is only supported for
|
||
+ELF format targets.
|
||
+
|
||
+@kindex --print-output-format
|
||
+@cindex output format
|
||
+@item --print-output-format
|
||
+Print the name of the default output format (perhaps influenced by
|
||
+other command-line options). This is the string that would appear
|
||
+in an @code{OUTPUT_FORMAT} linker script command (@pxref{File Commands}).
|
||
+
|
||
+@kindex --print-memory-usage
|
||
+@cindex memory usage
|
||
+@item --print-memory-usage
|
||
+Print used size, total size and used size of memory regions created with
|
||
+the @ref{MEMORY} command. This is useful on embedded targets to have a
|
||
+quick view of amount of free memory. The format of the output has one
|
||
+headline and one line per region. It is both human readable and easily
|
||
+parsable by tools. Here is an example of an output:
|
||
+
|
||
+@smallexample
|
||
+Memory region Used Size Region Size %age Used
|
||
+ ROM: 256 KB 1 MB 25.00%
|
||
+ RAM: 32 B 2 GB 0.00%
|
||
+@end smallexample
|
||
+
|
||
+@cindex help
|
||
+@cindex usage
|
||
+@kindex --help
|
||
+@item --help
|
||
+Print a summary of the command-line options on the standard output and exit.
|
||
+
|
||
+@kindex --target-help
|
||
+@item --target-help
|
||
+Print a summary of all target-specific options on the standard output and exit.
|
||
+
|
||
+@kindex -Map=@var{mapfile}
|
||
+@item -Map=@var{mapfile}
|
||
+Print a link map to the file @var{mapfile}. See the description of the
|
||
+@option{-M} option, above. If @var{mapfile} is just the character
|
||
+@code{-} then the map will be written to stdout.
|
||
+
|
||
+Specifying a directory as @var{mapfile} causes the linker map to be
|
||
+written as a file inside the directory. Normally name of the file
|
||
+inside the directory is computed as the basename of the @var{output}
|
||
+file with @code{.map} appended. If however the special character
|
||
+@code{%} is used then this will be replaced by the full path of the
|
||
+output file. Additionally if there are any characters after the
|
||
+@var{%} symbol then @code{.map} will no longer be appended.
|
||
+
|
||
+@smallexample
|
||
+ -o foo.exe -Map=bar [Creates ./bar]
|
||
+ -o ../dir/foo.exe -Map=bar [Creates ./bar]
|
||
+ -o foo.exe -Map=../dir [Creates ../dir/foo.exe.map]
|
||
+ -o ../dir2/foo.exe -Map=../dir [Creates ../dir/foo.exe.map]
|
||
+ -o foo.exe -Map=% [Creates ./foo.exe.map]
|
||
+ -o ../dir/foo.exe -Map=% [Creates ../dir/foo.exe.map]
|
||
+ -o foo.exe -Map=%.bar [Creates ./foo.exe.bar]
|
||
+ -o ../dir/foo.exe -Map=%.bar [Creates ../dir/foo.exe.bar]
|
||
+ -o ../dir2/foo.exe -Map=../dir/% [Creates ../dir/../dir2/foo.exe.map]
|
||
+ -o ../dir2/foo.exe -Map=../dir/%.bar [Creates ../dir/../dir2/foo.exe.bar]
|
||
+@end smallexample
|
||
+
|
||
+It is an error to specify more than one @code{%} character.
|
||
+
|
||
+If the map file already exists then it will be overwritten by this
|
||
+operation.
|
||
+
|
||
+@cindex memory usage
|
||
+@kindex --no-keep-memory
|
||
+@item --no-keep-memory
|
||
+@command{ld} normally optimizes for speed over memory usage by caching the
|
||
+symbol tables of input files in memory. This option tells @command{ld} to
|
||
+instead optimize for memory usage, by rereading the symbol tables as
|
||
+necessary. This may be required if @command{ld} runs out of memory space
|
||
+while linking a large executable.
|
||
+
|
||
+@kindex --no-undefined
|
||
+@kindex -z defs
|
||
+@kindex -z undefs
|
||
+@item --no-undefined
|
||
+@itemx -z defs
|
||
+Report unresolved symbol references from regular object files. This
|
||
+is done even if the linker is creating a non-symbolic shared library.
|
||
+The switch @option{--[no-]allow-shlib-undefined} controls the
|
||
+behaviour for reporting unresolved references found in shared
|
||
+libraries being linked in.
|
||
+
|
||
+The effects of this option can be reverted by using @code{-z undefs}.
|
||
+
|
||
+@kindex --allow-multiple-definition
|
||
+@kindex -z muldefs
|
||
+@item --allow-multiple-definition
|
||
+@itemx -z muldefs
|
||
+Normally when a symbol is defined multiple times, the linker will
|
||
+report a fatal error. These options allow multiple definitions and the
|
||
+first definition will be used.
|
||
+
|
||
+@kindex --allow-shlib-undefined
|
||
+@kindex --no-allow-shlib-undefined
|
||
+@item --allow-shlib-undefined
|
||
+@itemx --no-allow-shlib-undefined
|
||
+Allows or disallows undefined symbols in shared libraries.
|
||
+This switch is similar to @option{--no-undefined} except that it
|
||
+determines the behaviour when the undefined symbols are in a
|
||
+shared library rather than a regular object file. It does not affect
|
||
+how undefined symbols in regular object files are handled.
|
||
+
|
||
+The default behaviour is to report errors for any undefined symbols
|
||
+referenced in shared libraries if the linker is being used to create
|
||
+an executable, but to allow them if the linker is being used to create
|
||
+a shared library.
|
||
+
|
||
+The reasons for allowing undefined symbol references in shared
|
||
+libraries specified at link time are that:
|
||
+
|
||
+@itemize @bullet
|
||
+@item
|
||
+A shared library specified at link time may not be the same as the one
|
||
+that is available at load time, so the symbol might actually be
|
||
+resolvable at load time.
|
||
+@item
|
||
+There are some operating systems, eg BeOS and HPPA, where undefined
|
||
+symbols in shared libraries are normal.
|
||
+
|
||
+The BeOS kernel for example patches shared libraries at load time to
|
||
+select whichever function is most appropriate for the current
|
||
+architecture. This is used, for example, to dynamically select an
|
||
+appropriate memset function.
|
||
+@end itemize
|
||
+
|
||
+@kindex --error-handling-script=@var{scriptname}
|
||
+@item --error-handling-script=@var{scriptname}
|
||
+If this option is provided then the linker will invoke
|
||
+@var{scriptname} whenever an error is encountered. Currently however
|
||
+only two kinds of error are supported: missing symbols and missing
|
||
+libraries. Two arguments will be passed to script: the keyword
|
||
+``undefined-symbol'' or `missing-lib'' and the @var{name} of the
|
||
+undefined symbol or missing library. The intention is that the script
|
||
+will provide suggestions to the user as to where the symbol or library
|
||
+might be found. After the script has finished then the normal linker
|
||
+error message will be displayed.
|
||
+
|
||
+The availability of this option is controlled by a configure time
|
||
+switch, so it may not be present in specific implementations.
|
||
+
|
||
+@kindex --no-undefined-version
|
||
+@item --no-undefined-version
|
||
+Normally when a symbol has an undefined version, the linker will ignore
|
||
+it. This option disallows symbols with undefined version and a fatal error
|
||
+will be issued instead.
|
||
+
|
||
+@kindex --default-symver
|
||
+@item --default-symver
|
||
+Create and use a default symbol version (the soname) for unversioned
|
||
+exported symbols.
|
||
+
|
||
+@kindex --default-imported-symver
|
||
+@item --default-imported-symver
|
||
+Create and use a default symbol version (the soname) for unversioned
|
||
+imported symbols.
|
||
+
|
||
+@kindex --no-warn-mismatch
|
||
+@item --no-warn-mismatch
|
||
+Normally @command{ld} will give an error if you try to link together input
|
||
+files that are mismatched for some reason, perhaps because they have
|
||
+been compiled for different processors or for different endiannesses.
|
||
+This option tells @command{ld} that it should silently permit such possible
|
||
+errors. This option should only be used with care, in cases when you
|
||
+have taken some special action that ensures that the linker errors are
|
||
+inappropriate.
|
||
+
|
||
+@kindex --no-warn-search-mismatch
|
||
+@item --no-warn-search-mismatch
|
||
+Normally @command{ld} will give a warning if it finds an incompatible
|
||
+library during a library search. This option silences the warning.
|
||
+
|
||
+@kindex --no-whole-archive
|
||
+@item --no-whole-archive
|
||
+Turn off the effect of the @option{--whole-archive} option for subsequent
|
||
+archive files.
|
||
+
|
||
+@cindex output file after errors
|
||
+@kindex --noinhibit-exec
|
||
+@item --noinhibit-exec
|
||
+Retain the executable output file whenever it is still usable.
|
||
+Normally, the linker will not produce an output file if it encounters
|
||
+errors during the link process; it exits without writing an output file
|
||
+when it issues any error whatsoever.
|
||
+
|
||
+@kindex -nostdlib
|
||
+@item -nostdlib
|
||
+Only search library directories explicitly specified on the
|
||
+command line. Library directories specified in linker scripts
|
||
+(including linker scripts specified on the command line) are ignored.
|
||
+
|
||
+@ifclear SingleFormat
|
||
+@kindex --oformat=@var{output-format}
|
||
+@item --oformat=@var{output-format}
|
||
+@command{ld} may be configured to support more than one kind of object
|
||
+file. If your @command{ld} is configured this way, you can use the
|
||
+@samp{--oformat} option to specify the binary format for the output
|
||
+object file. Even when @command{ld} is configured to support alternative
|
||
+object formats, you don't usually need to specify this, as @command{ld}
|
||
+should be configured to produce as a default output format the most
|
||
+usual format on each machine. @var{output-format} is a text string, the
|
||
+name of a particular format supported by the BFD libraries. (You can
|
||
+list the available binary formats with @samp{objdump -i}.) The script
|
||
+command @code{OUTPUT_FORMAT} can also specify the output format, but
|
||
+this option overrides it. @xref{BFD}.
|
||
+@end ifclear
|
||
+
|
||
+@kindex --out-implib
|
||
+@item --out-implib @var{file}
|
||
+Create an import library in @var{file} corresponding to the executable
|
||
+the linker is generating (eg. a DLL or ELF program). This import
|
||
+library (which should be called @code{*.dll.a} or @code{*.a} for DLLs)
|
||
+may be used to link clients against the generated executable; this
|
||
+behaviour makes it possible to skip a separate import library creation
|
||
+step (eg. @code{dlltool} for DLLs). This option is only available for
|
||
+the i386 PE and ELF targetted ports of the linker.
|
||
+
|
||
+@kindex -pie
|
||
+@kindex --pic-executable
|
||
+@item -pie
|
||
+@itemx --pic-executable
|
||
+@cindex position independent executables
|
||
+Create a position independent executable. This is currently only supported on
|
||
+ELF platforms. Position independent executables are similar to shared
|
||
+libraries in that they are relocated by the dynamic linker to the virtual
|
||
+address the OS chooses for them (which can vary between invocations). Like
|
||
+normal dynamically linked executables they can be executed and symbols
|
||
+defined in the executable cannot be overridden by shared libraries.
|
||
+
|
||
+@kindex -no-pie
|
||
+@item -no-pie
|
||
+@cindex position dependent executables
|
||
+Create a position dependent executable. This is the default.
|
||
+
|
||
+@kindex -qmagic
|
||
+@item -qmagic
|
||
+This option is ignored for Linux compatibility.
|
||
+
|
||
+@kindex -Qy
|
||
+@item -Qy
|
||
+This option is ignored for SVR4 compatibility.
|
||
+
|
||
+@kindex --relax
|
||
+@cindex synthesizing linker
|
||
+@cindex relaxing addressing modes
|
||
+@cindex --no-relax
|
||
+@item --relax
|
||
+@itemx --no-relax
|
||
+An option with machine dependent effects.
|
||
+@ifset GENERIC
|
||
+This option is only supported on a few targets.
|
||
+@end ifset
|
||
+@ifset H8300
|
||
+@xref{H8/300,,@command{ld} and the H8/300}.
|
||
+@end ifset
|
||
+@ifset XTENSA
|
||
+@xref{Xtensa,, @command{ld} and Xtensa Processors}.
|
||
+@end ifset
|
||
+@ifset M68HC11
|
||
+@xref{M68HC11/68HC12,,@command{ld} and the 68HC11 and 68HC12}.
|
||
+@end ifset
|
||
+@ifset NIOSII
|
||
+@xref{Nios II,,@command{ld} and the Altera Nios II}.
|
||
+@end ifset
|
||
+@ifset POWERPC
|
||
+@xref{PowerPC ELF32,,@command{ld} and PowerPC 32-bit ELF Support}.
|
||
+@end ifset
|
||
+
|
||
+On some platforms the @option{--relax} option performs target specific,
|
||
+global optimizations that become possible when the linker resolves
|
||
+addressing in the program, such as relaxing address modes,
|
||
+synthesizing new instructions, selecting shorter version of current
|
||
+instructions, and combining constant values.
|
||
+
|
||
+On some platforms these link time global optimizations may make symbolic
|
||
+debugging of the resulting executable impossible.
|
||
+@ifset GENERIC
|
||
+This is known to be the case for the Matsushita MN10200 and MN10300
|
||
+family of processors.
|
||
+@end ifset
|
||
+
|
||
+On platforms where the feature is supported, the option
|
||
+@option{--no-relax} will disable it.
|
||
+
|
||
+On platforms where the feature is not supported, both @option{--relax}
|
||
+and @option{--no-relax} are accepted, but ignored.
|
||
+
|
||
+@cindex retaining specified symbols
|
||
+@cindex stripping all but some symbols
|
||
+@cindex symbols, retaining selectively
|
||
+@kindex --retain-symbols-file=@var{filename}
|
||
+@item --retain-symbols-file=@var{filename}
|
||
+Retain @emph{only} the symbols listed in the file @var{filename},
|
||
+discarding all others. @var{filename} is simply a flat file, with one
|
||
+symbol name per line. This option is especially useful in environments
|
||
+@ifset GENERIC
|
||
+(such as VxWorks)
|
||
+@end ifset
|
||
+where a large global symbol table is accumulated gradually, to conserve
|
||
+run-time memory.
|
||
+
|
||
+@samp{--retain-symbols-file} does @emph{not} discard undefined symbols,
|
||
+or symbols needed for relocations.
|
||
+
|
||
+You may only specify @samp{--retain-symbols-file} once in the command
|
||
+line. It overrides @samp{-s} and @samp{-S}.
|
||
+
|
||
+@ifset GENERIC
|
||
+@item -rpath=@var{dir}
|
||
+@cindex runtime library search path
|
||
+@kindex -rpath=@var{dir}
|
||
+Add a directory to the runtime library search path. This is used when
|
||
+linking an ELF executable with shared objects. All @option{-rpath}
|
||
+arguments are concatenated and passed to the runtime linker, which uses
|
||
+them to locate shared objects at runtime.
|
||
+
|
||
+The @option{-rpath} option is also used when locating shared objects which
|
||
+are needed by shared objects explicitly included in the link; see the
|
||
+description of the @option{-rpath-link} option. Searching @option{-rpath}
|
||
+in this way is only supported by native linkers and cross linkers which
|
||
+have been configured with the @option{--with-sysroot} option.
|
||
+
|
||
+If @option{-rpath} is not used when linking an ELF executable, the
|
||
+contents of the environment variable @code{LD_RUN_PATH} will be used if it
|
||
+is defined.
|
||
+
|
||
+The @option{-rpath} option may also be used on SunOS. By default, on
|
||
+SunOS, the linker will form a runtime search path out of all the
|
||
+@option{-L} options it is given. If a @option{-rpath} option is used, the
|
||
+runtime search path will be formed exclusively using the @option{-rpath}
|
||
+options, ignoring the @option{-L} options. This can be useful when using
|
||
+gcc, which adds many @option{-L} options which may be on NFS mounted
|
||
+file systems.
|
||
+
|
||
+For compatibility with other ELF linkers, if the @option{-R} option is
|
||
+followed by a directory name, rather than a file name, it is treated as
|
||
+the @option{-rpath} option.
|
||
+@end ifset
|
||
+
|
||
+@ifset GENERIC
|
||
+@cindex link-time runtime library search path
|
||
+@kindex -rpath-link=@var{dir}
|
||
+@item -rpath-link=@var{dir}
|
||
+When using ELF or SunOS, one shared library may require another. This
|
||
+happens when an @code{ld -shared} link includes a shared library as one
|
||
+of the input files.
|
||
+
|
||
+When the linker encounters such a dependency when doing a non-shared,
|
||
+non-relocatable link, it will automatically try to locate the required
|
||
+shared library and include it in the link, if it is not included
|
||
+explicitly. In such a case, the @option{-rpath-link} option
|
||
+specifies the first set of directories to search. The
|
||
+@option{-rpath-link} option may specify a sequence of directory names
|
||
+either by specifying a list of names separated by colons, or by
|
||
+appearing multiple times.
|
||
+
|
||
+The tokens @var{$ORIGIN} and @var{$LIB} can appear in these search
|
||
+directories. They will be replaced by the full path to the directory
|
||
+containing the program or shared object in the case of @var{$ORIGIN}
|
||
+and either @samp{lib} - for 32-bit binaries - or @samp{lib64} - for
|
||
+64-bit binaries - in the case of @var{$LIB}.
|
||
+
|
||
+The alternative form of these tokens - @var{$@{ORIGIN@}} and
|
||
+@var{$@{LIB@}} can also be used. The token @var{$PLATFORM} is not
|
||
+supported.
|
||
+
|
||
+This option should be used with caution as it overrides the search path
|
||
+that may have been hard compiled into a shared library. In such a case it
|
||
+is possible to use unintentionally a different search path than the
|
||
+runtime linker would do.
|
||
+
|
||
+The linker uses the following search paths to locate required shared
|
||
+libraries:
|
||
+
|
||
+@enumerate
|
||
+@item
|
||
+Any directories specified by @option{-rpath-link} options.
|
||
+@item
|
||
+Any directories specified by @option{-rpath} options. The difference
|
||
+between @option{-rpath} and @option{-rpath-link} is that directories
|
||
+specified by @option{-rpath} options are included in the executable and
|
||
+used at runtime, whereas the @option{-rpath-link} option is only effective
|
||
+at link time. Searching @option{-rpath} in this way is only supported
|
||
+by native linkers and cross linkers which have been configured with
|
||
+the @option{--with-sysroot} option.
|
||
+@item
|
||
+On an ELF system, for native linkers, if the @option{-rpath} and
|
||
+@option{-rpath-link} options were not used, search the contents of the
|
||
+environment variable @code{LD_RUN_PATH}.
|
||
+@item
|
||
+On SunOS, if the @option{-rpath} option was not used, search any
|
||
+directories specified using @option{-L} options.
|
||
+@item
|
||
+For a native linker, search the contents of the environment
|
||
+variable @code{LD_LIBRARY_PATH}.
|
||
+@item
|
||
+For a native ELF linker, the directories in @code{DT_RUNPATH} or
|
||
+@code{DT_RPATH} of a shared library are searched for shared
|
||
+libraries needed by it. The @code{DT_RPATH} entries are ignored if
|
||
+@code{DT_RUNPATH} entries exist.
|
||
+@item
|
||
+For a linker for a Linux system, if the file @file{/etc/ld.so.conf}
|
||
+exists, the list of directories found in that file. Note: the path
|
||
+to this file is prefixed with the @code{sysroot} value, if that is
|
||
+defined, and then any @code{prefix} string if the linker was
|
||
+configured with the @command{--prefix=<path>} option.
|
||
+@item
|
||
+For a native linker on a FreeBSD system, any directories specified by
|
||
+the @code{_PATH_ELF_HINTS} macro defined in the @file{elf-hints.h}
|
||
+header file.
|
||
+@item
|
||
+Any directories specified by a @code{SEARCH_DIR} command in a
|
||
+linker script given on the command line, including scripts specified
|
||
+by @option{-T} (but not @option{-dT}).
|
||
+@item
|
||
+The default directories, normally @file{/lib} and @file{/usr/lib}.
|
||
+@item
|
||
+Any directories specified by a plugin LDPT_SET_EXTRA_LIBRARY_PATH.
|
||
+@item
|
||
+Any directories specified by a @code{SEARCH_DIR} command in a default
|
||
+linker script.
|
||
+@end enumerate
|
||
+
|
||
+Note however on Linux based systems there is an additional caveat: If
|
||
+the @option{--as-needed} option is active @emph{and} a shared library
|
||
+is located which would normally satisfy the search @emph{and} this
|
||
+library does not have DT_NEEDED tag for @file{libc.so}
|
||
+@emph{and} there is a shared library later on in the set of search
|
||
+directories which also satisfies the search @emph{and}
|
||
+this second shared library does have a DT_NEEDED tag for
|
||
+@file{libc.so} @emph{then} the second library will be selected instead
|
||
+of the first.
|
||
+
|
||
+If the required shared library is not found, the linker will issue a
|
||
+warning and continue with the link.
|
||
+
|
||
+@end ifset
|
||
+
|
||
+@kindex -shared
|
||
+@kindex -Bshareable
|
||
+@item -shared
|
||
+@itemx -Bshareable
|
||
+@cindex shared libraries
|
||
+Create a shared library. This is currently only supported on ELF, XCOFF
|
||
+and SunOS platforms. On SunOS, the linker will automatically create a
|
||
+shared library if the @option{-e} option is not used and there are
|
||
+undefined symbols in the link.
|
||
+
|
||
+@kindex --sort-common
|
||
+@item --sort-common
|
||
+@itemx --sort-common=ascending
|
||
+@itemx --sort-common=descending
|
||
+This option tells @command{ld} to sort the common symbols by alignment in
|
||
+ascending or descending order when it places them in the appropriate output
|
||
+sections. The symbol alignments considered are sixteen-byte or larger,
|
||
+eight-byte, four-byte, two-byte, and one-byte. This is to prevent gaps
|
||
+between symbols due to alignment constraints. If no sorting order is
|
||
+specified, then descending order is assumed.
|
||
+
|
||
+@kindex --sort-section=name
|
||
+@item --sort-section=name
|
||
+This option will apply @code{SORT_BY_NAME} to all wildcard section
|
||
+patterns in the linker script.
|
||
+
|
||
+@kindex --sort-section=alignment
|
||
+@item --sort-section=alignment
|
||
+This option will apply @code{SORT_BY_ALIGNMENT} to all wildcard section
|
||
+patterns in the linker script.
|
||
+
|
||
+@kindex --spare-dynamic-tags
|
||
+@item --spare-dynamic-tags=@var{count}
|
||
+This option specifies the number of empty slots to leave in the
|
||
+.dynamic section of ELF shared objects. Empty slots may be needed by
|
||
+post processing tools, such as the prelinker. The default is 5.
|
||
+
|
||
+@kindex --split-by-file
|
||
+@item --split-by-file[=@var{size}]
|
||
+Similar to @option{--split-by-reloc} but creates a new output section for
|
||
+each input file when @var{size} is reached. @var{size} defaults to a
|
||
+size of 1 if not given.
|
||
+
|
||
+@kindex --split-by-reloc
|
||
+@item --split-by-reloc[=@var{count}]
|
||
+Tries to creates extra sections in the output file so that no single
|
||
+output section in the file contains more than @var{count} relocations.
|
||
+This is useful when generating huge relocatable files for downloading into
|
||
+certain real time kernels with the COFF object file format; since COFF
|
||
+cannot represent more than 65535 relocations in a single section. Note
|
||
+that this will fail to work with object file formats which do not
|
||
+support arbitrary sections. The linker will not split up individual
|
||
+input sections for redistribution, so if a single input section contains
|
||
+more than @var{count} relocations one output section will contain that
|
||
+many relocations. @var{count} defaults to a value of 32768.
|
||
+
|
||
+@kindex --stats
|
||
+@item --stats
|
||
+Compute and display statistics about the operation of the linker, such
|
||
+as execution time and memory usage.
|
||
+
|
||
+@kindex --sysroot=@var{directory}
|
||
+@item --sysroot=@var{directory}
|
||
+Use @var{directory} as the location of the sysroot, overriding the
|
||
+configure-time default. This option is only supported by linkers
|
||
+that were configured using @option{--with-sysroot}.
|
||
+
|
||
+@kindex --task-link
|
||
+@item --task-link
|
||
+This is used by COFF/PE based targets to create a task-linked object
|
||
+file where all of the global symbols have been converted to statics.
|
||
+
|
||
+@kindex --traditional-format
|
||
+@cindex traditional format
|
||
+@item --traditional-format
|
||
+For some targets, the output of @command{ld} is different in some ways from
|
||
+the output of some existing linker. This switch requests @command{ld} to
|
||
+use the traditional format instead.
|
||
+
|
||
+@cindex dbx
|
||
+For example, on SunOS, @command{ld} combines duplicate entries in the
|
||
+symbol string table. This can reduce the size of an output file with
|
||
+full debugging information by over 30 percent. Unfortunately, the SunOS
|
||
+@code{dbx} program can not read the resulting program (@code{gdb} has no
|
||
+trouble). The @samp{--traditional-format} switch tells @command{ld} to not
|
||
+combine duplicate entries.
|
||
+
|
||
+@kindex --section-start=@var{sectionname}=@var{org}
|
||
+@item --section-start=@var{sectionname}=@var{org}
|
||
+Locate a section in the output file at the absolute
|
||
+address given by @var{org}. You may use this option as many
|
||
+times as necessary to locate multiple sections in the command
|
||
+line.
|
||
+@var{org} must be a single hexadecimal integer;
|
||
+for compatibility with other linkers, you may omit the leading
|
||
+@samp{0x} usually associated with hexadecimal values. @emph{Note:} there
|
||
+should be no white space between @var{sectionname}, the equals
|
||
+sign (``@key{=}''), and @var{org}.
|
||
+
|
||
+@kindex -Tbss=@var{org}
|
||
+@kindex -Tdata=@var{org}
|
||
+@kindex -Ttext=@var{org}
|
||
+@cindex segment origins, cmd line
|
||
+@item -Tbss=@var{org}
|
||
+@itemx -Tdata=@var{org}
|
||
+@itemx -Ttext=@var{org}
|
||
+Same as @option{--section-start}, with @code{.bss}, @code{.data} or
|
||
+@code{.text} as the @var{sectionname}.
|
||
+
|
||
+@kindex -Ttext-segment=@var{org}
|
||
+@item -Ttext-segment=@var{org}
|
||
+@cindex text segment origin, cmd line
|
||
+When creating an ELF executable, it will set the address of the first
|
||
+byte of the text segment.
|
||
+
|
||
+@kindex -Trodata-segment=@var{org}
|
||
+@item -Trodata-segment=@var{org}
|
||
+@cindex rodata segment origin, cmd line
|
||
+When creating an ELF executable or shared object for a target where
|
||
+the read-only data is in its own segment separate from the executable
|
||
+text, it will set the address of the first byte of the read-only data segment.
|
||
+
|
||
+@kindex -Tldata-segment=@var{org}
|
||
+@item -Tldata-segment=@var{org}
|
||
+@cindex ldata segment origin, cmd line
|
||
+When creating an ELF executable or shared object for x86-64 medium memory
|
||
+model, it will set the address of the first byte of the ldata segment.
|
||
+
|
||
+@kindex --unresolved-symbols
|
||
+@item --unresolved-symbols=@var{method}
|
||
+Determine how to handle unresolved symbols. There are four possible
|
||
+values for @samp{method}:
|
||
+
|
||
+@table @samp
|
||
+@item ignore-all
|
||
+Do not report any unresolved symbols.
|
||
+
|
||
+@item report-all
|
||
+Report all unresolved symbols. This is the default.
|
||
+
|
||
+@item ignore-in-object-files
|
||
+Report unresolved symbols that are contained in shared libraries, but
|
||
+ignore them if they come from regular object files.
|
||
+
|
||
+@item ignore-in-shared-libs
|
||
+Report unresolved symbols that come from regular object files, but
|
||
+ignore them if they come from shared libraries. This can be useful
|
||
+when creating a dynamic binary and it is known that all the shared
|
||
+libraries that it should be referencing are included on the linker's
|
||
+command line.
|
||
+@end table
|
||
+
|
||
+The behaviour for shared libraries on their own can also be controlled
|
||
+by the @option{--[no-]allow-shlib-undefined} option.
|
||
+
|
||
+Normally the linker will generate an error message for each reported
|
||
+unresolved symbol but the option @option{--warn-unresolved-symbols}
|
||
+can change this to a warning.
|
||
+
|
||
+@kindex --verbose[=@var{NUMBER}]
|
||
+@cindex verbose[=@var{NUMBER}]
|
||
+@item --dll-verbose
|
||
+@itemx --verbose[=@var{NUMBER}]
|
||
+Display the version number for @command{ld} and list the linker emulations
|
||
+supported. Display which input files can and cannot be opened. Display
|
||
+the linker script being used by the linker. If the optional @var{NUMBER}
|
||
+argument > 1, plugin symbol status will also be displayed.
|
||
+
|
||
+@kindex --version-script=@var{version-scriptfile}
|
||
+@cindex version script, symbol versions
|
||
+@item --version-script=@var{version-scriptfile}
|
||
+Specify the name of a version script to the linker. This is typically
|
||
+used when creating shared libraries to specify additional information
|
||
+about the version hierarchy for the library being created. This option
|
||
+is only fully supported on ELF platforms which support shared libraries;
|
||
+see @ref{VERSION}. It is partially supported on PE platforms, which can
|
||
+use version scripts to filter symbol visibility in auto-export mode: any
|
||
+symbols marked @samp{local} in the version script will not be exported.
|
||
+@xref{WIN32}.
|
||
+
|
||
+@kindex --warn-common
|
||
+@cindex warnings, on combining symbols
|
||
+@cindex combining symbols, warnings on
|
||
+@item --warn-common
|
||
+Warn when a common symbol is combined with another common symbol or with
|
||
+a symbol definition. Unix linkers allow this somewhat sloppy practice,
|
||
+but linkers on some other operating systems do not. This option allows
|
||
+you to find potential problems from combining global symbols.
|
||
+Unfortunately, some C libraries use this practice, so you may get some
|
||
+warnings about symbols in the libraries as well as in your programs.
|
||
+
|
||
+There are three kinds of global symbols, illustrated here by C examples:
|
||
+
|
||
+@table @samp
|
||
+@item int i = 1;
|
||
+A definition, which goes in the initialized data section of the output
|
||
+file.
|
||
+
|
||
+@item extern int i;
|
||
+An undefined reference, which does not allocate space.
|
||
+There must be either a definition or a common symbol for the
|
||
+variable somewhere.
|
||
+
|
||
+@item int i;
|
||
+A common symbol. If there are only (one or more) common symbols for a
|
||
+variable, it goes in the uninitialized data area of the output file.
|
||
+The linker merges multiple common symbols for the same variable into a
|
||
+single symbol. If they are of different sizes, it picks the largest
|
||
+size. The linker turns a common symbol into a declaration, if there is
|
||
+a definition of the same variable.
|
||
+@end table
|
||
+
|
||
+The @samp{--warn-common} option can produce five kinds of warnings.
|
||
+Each warning consists of a pair of lines: the first describes the symbol
|
||
+just encountered, and the second describes the previous symbol
|
||
+encountered with the same name. One or both of the two symbols will be
|
||
+a common symbol.
|
||
+
|
||
+@enumerate
|
||
+@item
|
||
+Turning a common symbol into a reference, because there is already a
|
||
+definition for the symbol.
|
||
+@smallexample
|
||
+@var{file}(@var{section}): warning: common of `@var{symbol}'
|
||
+ overridden by definition
|
||
+@var{file}(@var{section}): warning: defined here
|
||
+@end smallexample
|
||
+
|
||
+@item
|
||
+Turning a common symbol into a reference, because a later definition for
|
||
+the symbol is encountered. This is the same as the previous case,
|
||
+except that the symbols are encountered in a different order.
|
||
+@smallexample
|
||
+@var{file}(@var{section}): warning: definition of `@var{symbol}'
|
||
+ overriding common
|
||
+@var{file}(@var{section}): warning: common is here
|
||
+@end smallexample
|
||
+
|
||
+@item
|
||
+Merging a common symbol with a previous same-sized common symbol.
|
||
+@smallexample
|
||
+@var{file}(@var{section}): warning: multiple common
|
||
+ of `@var{symbol}'
|
||
+@var{file}(@var{section}): warning: previous common is here
|
||
+@end smallexample
|
||
+
|
||
+@item
|
||
+Merging a common symbol with a previous larger common symbol.
|
||
+@smallexample
|
||
+@var{file}(@var{section}): warning: common of `@var{symbol}'
|
||
+ overridden by larger common
|
||
+@var{file}(@var{section}): warning: larger common is here
|
||
+@end smallexample
|
||
+
|
||
+@item
|
||
+Merging a common symbol with a previous smaller common symbol. This is
|
||
+the same as the previous case, except that the symbols are
|
||
+encountered in a different order.
|
||
+@smallexample
|
||
+@var{file}(@var{section}): warning: common of `@var{symbol}'
|
||
+ overriding smaller common
|
||
+@var{file}(@var{section}): warning: smaller common is here
|
||
+@end smallexample
|
||
+@end enumerate
|
||
+
|
||
+@kindex --warn-constructors
|
||
+@item --warn-constructors
|
||
+Warn if any global constructors are used. This is only useful for a few
|
||
+object file formats. For formats like COFF or ELF, the linker can not
|
||
+detect the use of global constructors.
|
||
+
|
||
+@kindex --warn-execstack
|
||
+@cindex warnings, on executable stack
|
||
+@cindex executable stack, warnings on
|
||
+@item --warn-execstack
|
||
+@itemx --warn-execstack-objects
|
||
+@itemx --no-warn-execstack
|
||
+On ELF platforms the linker may generate warning messages if it is
|
||
+asked to create an output file that contains an executable stack.
|
||
+There are three possible states:
|
||
+@enumerate
|
||
+@item
|
||
+Do not generate any warnings.
|
||
+@item
|
||
+Always generate warnings, even if the executable stack is requested
|
||
+via the @option{-z execstack} command line option.
|
||
+@item
|
||
+Only generate a warning if an object file requests an executable
|
||
+stack, but not if the @option{-z execstack} option is used.
|
||
+@end enumerate
|
||
+
|
||
+The default state depends upon how the linker was configured when it
|
||
+was built. The @option{--no-warn-execstack} option always puts the
|
||
+linker into the no-warnings state. The @option{--warn-execstack}
|
||
+option puts the linker into the warn-always state. The
|
||
+@option{--warn-execstack-objects} option puts the linker into the
|
||
+warn-for-object-files-only state.
|
||
+
|
||
+Note: ELF format input files can specify that they need an executable
|
||
+stack by having a @var{.note.GNU-stack} section with the executable
|
||
+bit set in its section flags. They can specify that they do not need
|
||
+an executable stack by having the same section, but without the
|
||
+executable flag bit set. If an input file does not have a
|
||
+@var{.note.GNU-stack} section then the default behaviour is target
|
||
+specific. For some targets, then absence of such a section implies
|
||
+that an executable stack @emph{is} required. This is often a problem
|
||
+for hand crafted assembler files.
|
||
+
|
||
+@kindex --error-execstack
|
||
+@item --error-execstack
|
||
+@itemx --no-error-execstack
|
||
+If the linker is going to generate a warning message about an
|
||
+executable stack then the @option{--error-execstack} option will
|
||
+instead change that warning into an error. Note - this option does
|
||
+not change the linker's execstack warning generation state. Use
|
||
+@option{--warn-execstack} or @option{--warn-execstack-objects} to set
|
||
+a specific warning state.
|
||
+
|
||
+The @option{--no-error-execstack} option will restore the default
|
||
+behaviour of generating warning messages.
|
||
+
|
||
+@kindex --warn-multiple-gp
|
||
+@item --warn-multiple-gp
|
||
+Warn if multiple global pointer values are required in the output file.
|
||
+This is only meaningful for certain processors, such as the Alpha.
|
||
+Specifically, some processors put large-valued constants in a special
|
||
+section. A special register (the global pointer) points into the middle
|
||
+of this section, so that constants can be loaded efficiently via a
|
||
+base-register relative addressing mode. Since the offset in
|
||
+base-register relative mode is fixed and relatively small (e.g., 16
|
||
+bits), this limits the maximum size of the constant pool. Thus, in
|
||
+large programs, it is often necessary to use multiple global pointer
|
||
+values in order to be able to address all possible constants. This
|
||
+option causes a warning to be issued whenever this case occurs.
|
||
+
|
||
+@kindex --warn-once
|
||
+@cindex warnings, on undefined symbols
|
||
+@cindex undefined symbols, warnings on
|
||
+@item --warn-once
|
||
+Only warn once for each undefined symbol, rather than once per module
|
||
+which refers to it.
|
||
+
|
||
+@kindex --warn-rwx-segments
|
||
+@cindex warnings, on writeable and exectuable segments
|
||
+@cindex executable segments, warnings on
|
||
+@item --warn-rwx-segments
|
||
+@itemx --no-warn-rwx-segments
|
||
+Warn if the linker creates a loadable, non-zero sized segment that has
|
||
+all three of the read, write and execute permission flags set. Such a
|
||
+segment represents a potential security vulnerability. In addition
|
||
+warnings will be generated if a thread local storage segment is
|
||
+created with the execute permission flag set, regardless of whether or
|
||
+not it has the read and/or write flags set.
|
||
+
|
||
+These warnings are enabled by default. They can be disabled via the
|
||
+@option{--no-warn-rwx-segments} option and re-enabled via the
|
||
+@option{--warn-rwx-segments} option.
|
||
+
|
||
+@kindex --error-rwx-segments
|
||
+@item --error-rwx-segments
|
||
+@itemx --no-error-rwx-segments
|
||
+If the linker is going to generate a warning message about an
|
||
+executable, writeable segment, or an executable TLS segment, then the
|
||
+@option{--error-rwx-segments} option will turn this warning into an
|
||
+error instead. The @option{--no-error-rwx-segments} option will
|
||
+restore the default behaviour of just generating a warning message.
|
||
+
|
||
+Note - the @option{--error-rwx-segments} option does not by itself
|
||
+turn on warnings about these segments. These warnings are either
|
||
+enabled by default, if the linker was configured that way, or via the
|
||
+@option{--warn-rwx-segments} command line option.
|
||
+
|
||
+@kindex --warn-section-align
|
||
+@cindex warnings, on section alignment
|
||
+@cindex section alignment, warnings on
|
||
+@item --warn-section-align
|
||
+Warn if the address of an output section is changed because of
|
||
+alignment. Typically, the alignment will be set by an input section.
|
||
+The address will only be changed if it not explicitly specified; that
|
||
+is, if the @code{SECTIONS} command does not specify a start address for
|
||
+the section (@pxref{SECTIONS}).
|
||
+
|
||
+@kindex --warn-textrel
|
||
+@item --warn-textrel
|
||
+Warn if the linker adds DT_TEXTREL to a position-independent executable
|
||
+or shared object.
|
||
+
|
||
+@kindex --warn-alternate-em
|
||
+@item --warn-alternate-em
|
||
+Warn if an object has alternate ELF machine code.
|
||
+
|
||
+@kindex --warn-unresolved-symbols
|
||
+@item --warn-unresolved-symbols
|
||
+If the linker is going to report an unresolved symbol (see the option
|
||
+@option{--unresolved-symbols}) it will normally generate an error.
|
||
+This option makes it generate a warning instead.
|
||
+
|
||
+@kindex --error-unresolved-symbols
|
||
+@item --error-unresolved-symbols
|
||
+This restores the linker's default behaviour of generating errors when
|
||
+it is reporting unresolved symbols.
|
||
+
|
||
+@kindex --whole-archive
|
||
+@cindex including an entire archive
|
||
+@item --whole-archive
|
||
+For each archive mentioned on the command line after the
|
||
+@option{--whole-archive} option, include every object file in the archive
|
||
+in the link, rather than searching the archive for the required object
|
||
+files. This is normally used to turn an archive file into a shared
|
||
+library, forcing every object to be included in the resulting shared
|
||
+library. This option may be used more than once.
|
||
+
|
||
+Two notes when using this option from gcc: First, gcc doesn't know
|
||
+about this option, so you have to use @option{-Wl,-whole-archive}.
|
||
+Second, don't forget to use @option{-Wl,-no-whole-archive} after your
|
||
+list of archives, because gcc will add its own list of archives to
|
||
+your link and you may not want this flag to affect those as well.
|
||
+
|
||
+@kindex --wrap=@var{symbol}
|
||
+@item --wrap=@var{symbol}
|
||
+Use a wrapper function for @var{symbol}. Any undefined reference to
|
||
+@var{symbol} will be resolved to @code{__wrap_@var{symbol}}. Any
|
||
+undefined reference to @code{__real_@var{symbol}} will be resolved to
|
||
+@var{symbol}.
|
||
+
|
||
+This can be used to provide a wrapper for a system function. The
|
||
+wrapper function should be called @code{__wrap_@var{symbol}}. If it
|
||
+wishes to call the system function, it should call
|
||
+@code{__real_@var{symbol}}.
|
||
+
|
||
+Here is a trivial example:
|
||
+
|
||
+@smallexample
|
||
+void *
|
||
+__wrap_malloc (size_t c)
|
||
+@{
|
||
+ printf ("malloc called with %zu\n", c);
|
||
+ return __real_malloc (c);
|
||
+@}
|
||
+@end smallexample
|
||
+
|
||
+If you link other code with this file using @option{--wrap malloc}, then
|
||
+all calls to @code{malloc} will call the function @code{__wrap_malloc}
|
||
+instead. The call to @code{__real_malloc} in @code{__wrap_malloc} will
|
||
+call the real @code{malloc} function.
|
||
+
|
||
+You may wish to provide a @code{__real_malloc} function as well, so that
|
||
+links without the @option{--wrap} option will succeed. If you do this,
|
||
+you should not put the definition of @code{__real_malloc} in the same
|
||
+file as @code{__wrap_malloc}; if you do, the assembler may resolve the
|
||
+call before the linker has a chance to wrap it to @code{malloc}.
|
||
+
|
||
+Only undefined references are replaced by the linker. So, translation unit
|
||
+internal references to @var{symbol} are not resolved to
|
||
+@code{__wrap_@var{symbol}}. In the next example, the call to @code{f} in
|
||
+@code{g} is not resolved to @code{__wrap_f}.
|
||
+
|
||
+@smallexample
|
||
+int
|
||
+f (void)
|
||
+@{
|
||
+ return 123;
|
||
+@}
|
||
+
|
||
+int
|
||
+g (void)
|
||
+@{
|
||
+ return f();
|
||
+@}
|
||
+@end smallexample
|
||
+
|
||
+@kindex --eh-frame-hdr
|
||
+@kindex --no-eh-frame-hdr
|
||
+@item --eh-frame-hdr
|
||
+@itemx --no-eh-frame-hdr
|
||
+Request (@option{--eh-frame-hdr}) or suppress
|
||
+(@option{--no-eh-frame-hdr}) the creation of @code{.eh_frame_hdr}
|
||
+section and ELF @code{PT_GNU_EH_FRAME} segment header.
|
||
+
|
||
+@kindex --ld-generated-unwind-info
|
||
+@item --no-ld-generated-unwind-info
|
||
+Request creation of @code{.eh_frame} unwind info for linker
|
||
+generated code sections like PLT. This option is on by default
|
||
+if linker generated unwind info is supported. This option also
|
||
+controls the generation of @code{.sframe} stack trace info for linker
|
||
+generated code sections like PLT.
|
||
+
|
||
+@kindex --enable-new-dtags
|
||
+@kindex --disable-new-dtags
|
||
+@item --enable-new-dtags
|
||
+@itemx --disable-new-dtags
|
||
+This linker can create the new dynamic tags in ELF. But the older ELF
|
||
+systems may not understand them. If you specify
|
||
+@option{--enable-new-dtags}, the new dynamic tags will be created as needed
|
||
+and older dynamic tags will be omitted.
|
||
+If you specify @option{--disable-new-dtags}, no new dynamic tags will be
|
||
+created. By default, the new dynamic tags are created. Note that
|
||
+those options are only available for ELF systems.
|
||
+
|
||
+@kindex --hash-size=@var{number}
|
||
+@item --hash-size=@var{number}
|
||
+Set the default size of the linker's hash tables to a prime number
|
||
+close to @var{number}. Increasing this value can reduce the length of
|
||
+time it takes the linker to perform its tasks, at the expense of
|
||
+increasing the linker's memory requirements. Similarly reducing this
|
||
+value can reduce the memory requirements at the expense of speed.
|
||
+
|
||
+@kindex --hash-style=@var{style}
|
||
+@item --hash-style=@var{style}
|
||
+Set the type of linker's hash table(s). @var{style} can be either
|
||
+@code{sysv} for classic ELF @code{.hash} section, @code{gnu} for
|
||
+new style GNU @code{.gnu.hash} section or @code{both} for both
|
||
+the classic ELF @code{.hash} and new style GNU @code{.gnu.hash}
|
||
+hash tables. The default depends upon how the linker was configured,
|
||
+but for most Linux based systems it will be @code{both}.
|
||
+
|
||
+@kindex --compress-debug-sections=none
|
||
+@kindex --compress-debug-sections=zlib
|
||
+@kindex --compress-debug-sections=zlib-gnu
|
||
+@kindex --compress-debug-sections=zlib-gabi
|
||
+@kindex --compress-debug-sections=zstd
|
||
+@item --compress-debug-sections=none
|
||
+@itemx --compress-debug-sections=zlib
|
||
+@itemx --compress-debug-sections=zlib-gnu
|
||
+@itemx --compress-debug-sections=zlib-gabi
|
||
+@itemx --compress-debug-sections=zstd
|
||
+On ELF platforms, these options control how DWARF debug sections are
|
||
+compressed using zlib.
|
||
+
|
||
+@option{--compress-debug-sections=none} doesn't compress DWARF debug
|
||
+sections. @option{--compress-debug-sections=zlib-gnu} compresses
|
||
+DWARF debug sections and renames them to begin with @samp{.zdebug}
|
||
+instead of @samp{.debug}. @option{--compress-debug-sections=zlib-gabi}
|
||
+also compresses DWARF debug sections, but rather than renaming them it
|
||
+sets the SHF_COMPRESSED flag in the sections' headers.
|
||
+
|
||
+The @option{--compress-debug-sections=zlib} option is an alias for
|
||
+@option{--compress-debug-sections=zlib-gabi}.
|
||
+
|
||
+@option{--compress-debug-sections=zstd} compresses DWARF debug sections using
|
||
+zstd.
|
||
+
|
||
+Note that this option overrides any compression in input debug
|
||
+sections, so if a binary is linked with @option{--compress-debug-sections=none}
|
||
+for example, then any compressed debug sections in input files will be
|
||
+uncompressed before they are copied into the output binary.
|
||
+
|
||
+The default compression behaviour varies depending upon the target
|
||
+involved and the configure options used to build the toolchain. The
|
||
+default can be determined by examining the output from the linker's
|
||
+@option{--help} option.
|
||
+
|
||
+@kindex --reduce-memory-overheads
|
||
+@item --reduce-memory-overheads
|
||
+This option reduces memory requirements at ld runtime, at the expense of
|
||
+linking speed. This was introduced to select the old O(n^2) algorithm
|
||
+for link map file generation, rather than the new O(n) algorithm which uses
|
||
+about 40% more memory for symbol storage.
|
||
+
|
||
+Another effect of the switch is to set the default hash table size to
|
||
+1021, which again saves memory at the cost of lengthening the linker's
|
||
+run time. This is not done however if the @option{--hash-size} switch
|
||
+has been used.
|
||
+
|
||
+The @option{--reduce-memory-overheads} switch may be also be used to
|
||
+enable other tradeoffs in future versions of the linker.
|
||
+
|
||
+@kindex --max-cache-size=@var{size}
|
||
+@item --max-cache-size=@var{size}
|
||
+@command{ld} normally caches the relocation information and symbol tables
|
||
+of input files in memory with the unlimited size. This option sets the
|
||
+maximum cache size to @var{size}.
|
||
+
|
||
+@kindex --build-id
|
||
+@kindex --build-id=@var{style}
|
||
+@item --build-id
|
||
+@itemx --build-id=@var{style}
|
||
+Request the creation of a @code{.note.gnu.build-id} ELF note section
|
||
+or a @code{.buildid} COFF section. The contents of the note are
|
||
+unique bits identifying this linked file. @var{style} can be
|
||
+@code{uuid} to use 128 random bits, @code{sha1} to use a 160-bit
|
||
+@sc{SHA1} hash on the normative parts of the output contents,
|
||
+@code{md5} to use a 128-bit @sc{MD5} hash on the normative parts of
|
||
+the output contents, or @code{0x@var{hexstring}} to use a chosen bit
|
||
+string specified as an even number of hexadecimal digits (@code{-} and
|
||
+@code{:} characters between digit pairs are ignored). If @var{style}
|
||
+is omitted, @code{sha1} is used.
|
||
+
|
||
+The @code{md5} and @code{sha1} styles produces an identifier
|
||
+that is always the same in an identical output file, but will be
|
||
+unique among all nonidentical output files. It is not intended
|
||
+to be compared as a checksum for the file's contents. A linked
|
||
+file may be changed later by other tools, but the build ID bit
|
||
+string identifying the original linked file does not change.
|
||
+
|
||
+Passing @code{none} for @var{style} disables the setting from any
|
||
+@code{--build-id} options earlier on the command line.
|
||
+
|
||
+@kindex --package-metadata=@var{JSON}
|
||
+@item --package-metadata=@var{JSON}
|
||
+Request the creation of a @code{.note.package} ELF note section. The
|
||
+contents of the note are in JSON format, as per the package metadata
|
||
+specification. For more information see:
|
||
+https://systemd.io/ELF_PACKAGE_METADATA/
|
||
+If the JSON argument is missing/empty then this will disable the
|
||
+creation of the metadata note, if one had been enabled by an earlier
|
||
+occurrence of the --package-metdata option.
|
||
+If the linker has been built with libjansson, then the JSON string
|
||
+will be validated.
|
||
+@end table
|
||
+
|
||
+@c man end
|
||
+
|
||
+@subsection Options Specific to i386 PE Targets
|
||
+
|
||
+@c man begin OPTIONS
|
||
+
|
||
+The i386 PE linker supports the @option{-shared} option, which causes
|
||
+the output to be a dynamically linked library (DLL) instead of a
|
||
+normal executable. You should name the output @code{*.dll} when you
|
||
+use this option. In addition, the linker fully supports the standard
|
||
+@code{*.def} files, which may be specified on the linker command line
|
||
+like an object file (in fact, it should precede archives it exports
|
||
+symbols from, to ensure that they get linked in, just like a normal
|
||
+object file).
|
||
+
|
||
+In addition to the options common to all targets, the i386 PE linker
|
||
+support additional command-line options that are specific to the i386
|
||
+PE target. Options that take values may be separated from their
|
||
+values by either a space or an equals sign.
|
||
+
|
||
+@table @gcctabopt
|
||
+
|
||
+@kindex --add-stdcall-alias
|
||
+@item --add-stdcall-alias
|
||
+If given, symbols with a stdcall suffix (@@@var{nn}) will be exported
|
||
+as-is and also with the suffix stripped.
|
||
+[This option is specific to the i386 PE targeted port of the linker]
|
||
+
|
||
+@kindex --base-file
|
||
+@item --base-file @var{file}
|
||
+Use @var{file} as the name of a file in which to save the base
|
||
+addresses of all the relocations needed for generating DLLs with
|
||
+@file{dlltool}.
|
||
+[This is an i386 PE specific option]
|
||
+
|
||
+@kindex --dll
|
||
+@item --dll
|
||
+Create a DLL instead of a regular executable. You may also use
|
||
+@option{-shared} or specify a @code{LIBRARY} in a given @code{.def}
|
||
+file.
|
||
+[This option is specific to the i386 PE targeted port of the linker]
|
||
+
|
||
+@kindex --enable-long-section-names
|
||
+@kindex --disable-long-section-names
|
||
+@item --enable-long-section-names
|
||
+@itemx --disable-long-section-names
|
||
+The PE variants of the COFF object format add an extension that permits
|
||
+the use of section names longer than eight characters, the normal limit
|
||
+for COFF. By default, these names are only allowed in object files, as
|
||
+fully-linked executable images do not carry the COFF string table required
|
||
+to support the longer names. As a GNU extension, it is possible to
|
||
+allow their use in executable images as well, or to (probably pointlessly!)
|
||
+disallow it in object files, by using these two options. Executable images
|
||
+generated with these long section names are slightly non-standard, carrying
|
||
+as they do a string table, and may generate confusing output when examined
|
||
+with non-GNU PE-aware tools, such as file viewers and dumpers. However,
|
||
+GDB relies on the use of PE long section names to find Dwarf-2 debug
|
||
+information sections in an executable image at runtime, and so if neither
|
||
+option is specified on the command-line, @command{ld} will enable long
|
||
+section names, overriding the default and technically correct behaviour,
|
||
+when it finds the presence of debug information while linking an executable
|
||
+image and not stripping symbols.
|
||
+[This option is valid for all PE targeted ports of the linker]
|
||
+
|
||
+@kindex --enable-stdcall-fixup
|
||
+@kindex --disable-stdcall-fixup
|
||
+@item --enable-stdcall-fixup
|
||
+@itemx --disable-stdcall-fixup
|
||
+If the link finds a symbol that it cannot resolve, it will attempt to
|
||
+do ``fuzzy linking'' by looking for another defined symbol that differs
|
||
+only in the format of the symbol name (cdecl vs stdcall) and will
|
||
+resolve that symbol by linking to the match. For example, the
|
||
+undefined symbol @code{_foo} might be linked to the function
|
||
+@code{_foo@@12}, or the undefined symbol @code{_bar@@16} might be linked
|
||
+to the function @code{_bar}. When the linker does this, it prints a
|
||
+warning, since it normally should have failed to link, but sometimes
|
||
+import libraries generated from third-party dlls may need this feature
|
||
+to be usable. If you specify @option{--enable-stdcall-fixup}, this
|
||
+feature is fully enabled and warnings are not printed. If you specify
|
||
+@option{--disable-stdcall-fixup}, this feature is disabled and such
|
||
+mismatches are considered to be errors.
|
||
+[This option is specific to the i386 PE targeted port of the linker]
|
||
+
|
||
+@kindex --leading-underscore
|
||
+@kindex --no-leading-underscore
|
||
+@item --leading-underscore
|
||
+@itemx --no-leading-underscore
|
||
+For most targets default symbol-prefix is an underscore and is defined
|
||
+in target's description. By this option it is possible to
|
||
+disable/enable the default underscore symbol-prefix.
|
||
+
|
||
+@cindex DLLs, creating
|
||
+@kindex --export-all-symbols
|
||
+@item --export-all-symbols
|
||
+If given, all global symbols in the objects used to build a DLL will
|
||
+be exported by the DLL. Note that this is the default if there
|
||
+otherwise wouldn't be any exported symbols. When symbols are
|
||
+explicitly exported via DEF files or implicitly exported via function
|
||
+attributes, the default is to not export anything else unless this
|
||
+option is given. Note that the symbols @code{DllMain@@12},
|
||
+@code{DllEntryPoint@@0}, @code{DllMainCRTStartup@@12}, and
|
||
+@code{impure_ptr} will not be automatically
|
||
+exported. Also, symbols imported from other DLLs will not be
|
||
+re-exported, nor will symbols specifying the DLL's internal layout
|
||
+such as those beginning with @code{_head_} or ending with
|
||
+@code{_iname}. In addition, no symbols from @code{libgcc},
|
||
+@code{libstd++}, @code{libmingw32}, or @code{crtX.o} will be exported.
|
||
+Symbols whose names begin with @code{__rtti_} or @code{__builtin_} will
|
||
+not be exported, to help with C++ DLLs. Finally, there is an
|
||
+extensive list of cygwin-private symbols that are not exported
|
||
+(obviously, this applies on when building DLLs for cygwin targets).
|
||
+These cygwin-excludes are: @code{_cygwin_dll_entry@@12},
|
||
+@code{_cygwin_crt0_common@@8}, @code{_cygwin_noncygwin_dll_entry@@12},
|
||
+@code{_fmode}, @code{_impure_ptr}, @code{cygwin_attach_dll},
|
||
+@code{cygwin_premain0}, @code{cygwin_premain1}, @code{cygwin_premain2},
|
||
+@code{cygwin_premain3}, and @code{environ}.
|
||
+[This option is specific to the i386 PE targeted port of the linker]
|
||
+
|
||
+@kindex --exclude-symbols
|
||
+@item --exclude-symbols @var{symbol},@var{symbol},...
|
||
+Specifies a list of symbols which should not be automatically
|
||
+exported. The symbol names may be delimited by commas or colons.
|
||
+[This option is specific to the i386 PE targeted port of the linker]
|
||
+
|
||
+@kindex --exclude-all-symbols
|
||
+@item --exclude-all-symbols
|
||
+Specifies no symbols should be automatically exported.
|
||
+[This option is specific to the i386 PE targeted port of the linker]
|
||
+
|
||
+@kindex --file-alignment
|
||
+@item --file-alignment
|
||
+Specify the file alignment. Sections in the file will always begin at
|
||
+file offsets which are multiples of this number. This defaults to
|
||
+512.
|
||
+[This option is specific to the i386 PE targeted port of the linker]
|
||
+
|
||
+@cindex heap size
|
||
+@kindex --heap
|
||
+@item --heap @var{reserve}
|
||
+@itemx --heap @var{reserve},@var{commit}
|
||
+Specify the number of bytes of memory to reserve (and optionally commit)
|
||
+to be used as heap for this program. The default is 1MB reserved, 4K
|
||
+committed.
|
||
+[This option is specific to the i386 PE targeted port of the linker]
|
||
+
|
||
+@cindex image base
|
||
+@kindex --image-base
|
||
+@item --image-base @var{value}
|
||
+Use @var{value} as the base address of your program or dll. This is
|
||
+the lowest memory location that will be used when your program or dll
|
||
+is loaded. To reduce the need to relocate and improve performance of
|
||
+your dlls, each should have a unique base address and not overlap any
|
||
+other dlls. The default is 0x400000 for executables, and 0x10000000
|
||
+for dlls.
|
||
+[This option is specific to the i386 PE targeted port of the linker]
|
||
+
|
||
+@kindex --kill-at
|
||
+@item --kill-at
|
||
+If given, the stdcall suffixes (@@@var{nn}) will be stripped from
|
||
+symbols before they are exported.
|
||
+[This option is specific to the i386 PE targeted port of the linker]
|
||
+
|
||
+@kindex --large-address-aware
|
||
+@item --large-address-aware
|
||
+If given, the appropriate bit in the ``Characteristics'' field of the COFF
|
||
+header is set to indicate that this executable supports virtual addresses
|
||
+greater than 2 gigabytes. This should be used in conjunction with the /3GB
|
||
+or /USERVA=@var{value} megabytes switch in the ``[operating systems]''
|
||
+section of the BOOT.INI. Otherwise, this bit has no effect.
|
||
+[This option is specific to PE targeted ports of the linker]
|
||
+
|
||
+@kindex --disable-large-address-aware
|
||
+@item --disable-large-address-aware
|
||
+Reverts the effect of a previous @samp{--large-address-aware} option.
|
||
+This is useful if @samp{--large-address-aware} is always set by the compiler
|
||
+driver (e.g. Cygwin gcc) and the executable does not support virtual
|
||
+addresses greater than 2 gigabytes.
|
||
+[This option is specific to PE targeted ports of the linker]
|
||
+
|
||
+@kindex --major-image-version
|
||
+@item --major-image-version @var{value}
|
||
+Sets the major number of the ``image version''. Defaults to 1.
|
||
+[This option is specific to the i386 PE targeted port of the linker]
|
||
+
|
||
+@kindex --major-os-version
|
||
+@item --major-os-version @var{value}
|
||
+Sets the major number of the ``os version''. Defaults to 4.
|
||
+[This option is specific to the i386 PE targeted port of the linker]
|
||
+
|
||
+@kindex --major-subsystem-version
|
||
+@item --major-subsystem-version @var{value}
|
||
+Sets the major number of the ``subsystem version''. Defaults to 4.
|
||
+[This option is specific to the i386 PE targeted port of the linker]
|
||
+
|
||
+@kindex --minor-image-version
|
||
+@item --minor-image-version @var{value}
|
||
+Sets the minor number of the ``image version''. Defaults to 0.
|
||
+[This option is specific to the i386 PE targeted port of the linker]
|
||
+
|
||
+@kindex --minor-os-version
|
||
+@item --minor-os-version @var{value}
|
||
+Sets the minor number of the ``os version''. Defaults to 0.
|
||
+[This option is specific to the i386 PE targeted port of the linker]
|
||
+
|
||
+@kindex --minor-subsystem-version
|
||
+@item --minor-subsystem-version @var{value}
|
||
+Sets the minor number of the ``subsystem version''. Defaults to 0.
|
||
+[This option is specific to the i386 PE targeted port of the linker]
|
||
+
|
||
+@cindex DEF files, creating
|
||
+@cindex DLLs, creating
|
||
+@kindex --output-def
|
||
+@item --output-def @var{file}
|
||
+The linker will create the file @var{file} which will contain a DEF
|
||
+file corresponding to the DLL the linker is generating. This DEF file
|
||
+(which should be called @code{*.def}) may be used to create an import
|
||
+library with @code{dlltool} or may be used as a reference to
|
||
+automatically or implicitly exported symbols.
|
||
+[This option is specific to the i386 PE targeted port of the linker]
|
||
+
|
||
+@cindex DLLs, creating
|
||
+@kindex --enable-auto-image-base
|
||
+@item --enable-auto-image-base
|
||
+@itemx --enable-auto-image-base=@var{value}
|
||
+Automatically choose the image base for DLLs, optionally starting with base
|
||
+@var{value}, unless one is specified using the @code{--image-base} argument.
|
||
+By using a hash generated from the dllname to create unique image bases
|
||
+for each DLL, in-memory collisions and relocations which can delay program
|
||
+execution are avoided.
|
||
+[This option is specific to the i386 PE targeted port of the linker]
|
||
+
|
||
+@kindex --disable-auto-image-base
|
||
+@item --disable-auto-image-base
|
||
+Do not automatically generate a unique image base. If there is no
|
||
+user-specified image base (@code{--image-base}) then use the platform
|
||
+default.
|
||
+[This option is specific to the i386 PE targeted port of the linker]
|
||
+
|
||
+@cindex DLLs, linking to
|
||
+@kindex --dll-search-prefix
|
||
+@item --dll-search-prefix @var{string}
|
||
+When linking dynamically to a dll without an import library,
|
||
+search for @code{<string><basename>.dll} in preference to
|
||
+@code{lib<basename>.dll}. This behaviour allows easy distinction
|
||
+between DLLs built for the various "subplatforms": native, cygwin,
|
||
+uwin, pw, etc. For instance, cygwin DLLs typically use
|
||
+@code{--dll-search-prefix=cyg}.
|
||
+[This option is specific to the i386 PE targeted port of the linker]
|
||
+
|
||
+@kindex --enable-auto-import
|
||
+@item --enable-auto-import
|
||
+Do sophisticated linking of @code{_symbol} to @code{__imp__symbol} for
|
||
+DATA imports from DLLs, thus making it possible to bypass the dllimport
|
||
+mechanism on the user side and to reference unmangled symbol names.
|
||
+[This option is specific to the i386 PE targeted port of the linker]
|
||
+
|
||
+The following remarks pertain to the original implementation of the
|
||
+feature and are obsolete nowadays for Cygwin and MinGW targets.
|
||
+
|
||
+Note: Use of the 'auto-import' extension will cause the text section
|
||
+of the image file to be made writable. This does not conform to the
|
||
+PE-COFF format specification published by Microsoft.
|
||
+
|
||
+Note - use of the 'auto-import' extension will also cause read only
|
||
+data which would normally be placed into the .rdata section to be
|
||
+placed into the .data section instead. This is in order to work
|
||
+around a problem with consts that is described here:
|
||
+http://www.cygwin.com/ml/cygwin/2004-09/msg01101.html
|
||
+
|
||
+Using 'auto-import' generally will 'just work' -- but sometimes you may
|
||
+see this message:
|
||
+
|
||
+"variable '<var>' can't be auto-imported. Please read the
|
||
+documentation for ld's @code{--enable-auto-import} for details."
|
||
+
|
||
+This message occurs when some (sub)expression accesses an address
|
||
+ultimately given by the sum of two constants (Win32 import tables only
|
||
+allow one). Instances where this may occur include accesses to member
|
||
+fields of struct variables imported from a DLL, as well as using a
|
||
+constant index into an array variable imported from a DLL. Any
|
||
+multiword variable (arrays, structs, long long, etc) may trigger
|
||
+this error condition. However, regardless of the exact data type
|
||
+of the offending exported variable, ld will always detect it, issue
|
||
+the warning, and exit.
|
||
+
|
||
+There are several ways to address this difficulty, regardless of the
|
||
+data type of the exported variable:
|
||
+
|
||
+One way is to use --enable-runtime-pseudo-reloc switch. This leaves the task
|
||
+of adjusting references in your client code for runtime environment, so
|
||
+this method works only when runtime environment supports this feature.
|
||
+
|
||
+A second solution is to force one of the 'constants' to be a variable --
|
||
+that is, unknown and un-optimizable at compile time. For arrays,
|
||
+there are two possibilities: a) make the indexee (the array's address)
|
||
+a variable, or b) make the 'constant' index a variable. Thus:
|
||
+
|
||
+@example
|
||
+extern type extern_array[];
|
||
+extern_array[1] -->
|
||
+ @{ volatile type *t=extern_array; t[1] @}
|
||
+@end example
|
||
+
|
||
+or
|
||
+
|
||
+@example
|
||
+extern type extern_array[];
|
||
+extern_array[1] -->
|
||
+ @{ volatile int t=1; extern_array[t] @}
|
||
+@end example
|
||
+
|
||
+For structs (and most other multiword data types) the only option
|
||
+is to make the struct itself (or the long long, or the ...) variable:
|
||
+
|
||
+@example
|
||
+extern struct s extern_struct;
|
||
+extern_struct.field -->
|
||
+ @{ volatile struct s *t=&extern_struct; t->field @}
|
||
+@end example
|
||
+
|
||
+or
|
||
+
|
||
+@example
|
||
+extern long long extern_ll;
|
||
+extern_ll -->
|
||
+ @{ volatile long long * local_ll=&extern_ll; *local_ll @}
|
||
+@end example
|
||
+
|
||
+A third method of dealing with this difficulty is to abandon
|
||
+'auto-import' for the offending symbol and mark it with
|
||
+@code{__declspec(dllimport)}. However, in practice that
|
||
+requires using compile-time #defines to indicate whether you are
|
||
+building a DLL, building client code that will link to the DLL, or
|
||
+merely building/linking to a static library. In making the choice
|
||
+between the various methods of resolving the 'direct address with
|
||
+constant offset' problem, you should consider typical real-world usage:
|
||
+
|
||
+Original:
|
||
+@example
|
||
+--foo.h
|
||
+extern int arr[];
|
||
+--foo.c
|
||
+#include "foo.h"
|
||
+void main(int argc, char **argv)@{
|
||
+ printf("%d\n",arr[1]);
|
||
+@}
|
||
+@end example
|
||
+
|
||
+Solution 1:
|
||
+@example
|
||
+--foo.h
|
||
+extern int arr[];
|
||
+--foo.c
|
||
+#include "foo.h"
|
||
+void main(int argc, char **argv)@{
|
||
+ /* This workaround is for win32 and cygwin; do not "optimize" */
|
||
+ volatile int *parr = arr;
|
||
+ printf("%d\n",parr[1]);
|
||
+@}
|
||
+@end example
|
||
+
|
||
+Solution 2:
|
||
+@example
|
||
+--foo.h
|
||
+/* Note: auto-export is assumed (no __declspec(dllexport)) */
|
||
+#if (defined(_WIN32) || defined(__CYGWIN__)) && \
|
||
+ !(defined(FOO_BUILD_DLL) || defined(FOO_STATIC))
|
||
+#define FOO_IMPORT __declspec(dllimport)
|
||
+#else
|
||
+#define FOO_IMPORT
|
||
+#endif
|
||
+extern FOO_IMPORT int arr[];
|
||
+--foo.c
|
||
+#include "foo.h"
|
||
+void main(int argc, char **argv)@{
|
||
+ printf("%d\n",arr[1]);
|
||
+@}
|
||
+@end example
|
||
+
|
||
+A fourth way to avoid this problem is to re-code your
|
||
+library to use a functional interface rather than a data interface
|
||
+for the offending variables (e.g. set_foo() and get_foo() accessor
|
||
+functions).
|
||
+
|
||
+@kindex --disable-auto-import
|
||
+@item --disable-auto-import
|
||
+Do not attempt to do sophisticated linking of @code{_symbol} to
|
||
+@code{__imp__symbol} for DATA imports from DLLs.
|
||
+[This option is specific to the i386 PE targeted port of the linker]
|
||
+
|
||
+@kindex --enable-runtime-pseudo-reloc
|
||
+@item --enable-runtime-pseudo-reloc
|
||
+If your code contains expressions described in --enable-auto-import section,
|
||
+that is, DATA imports from DLL with non-zero offset, this switch will create
|
||
+a vector of 'runtime pseudo relocations' which can be used by runtime
|
||
+environment to adjust references to such data in your client code.
|
||
+[This option is specific to the i386 PE targeted port of the linker]
|
||
+
|
||
+@kindex --disable-runtime-pseudo-reloc
|
||
+@item --disable-runtime-pseudo-reloc
|
||
+Do not create pseudo relocations for non-zero offset DATA imports from DLLs.
|
||
+[This option is specific to the i386 PE targeted port of the linker]
|
||
+
|
||
+@kindex --enable-extra-pe-debug
|
||
+@item --enable-extra-pe-debug
|
||
+Show additional debug info related to auto-import symbol thunking.
|
||
+[This option is specific to the i386 PE targeted port of the linker]
|
||
+
|
||
+@kindex --section-alignment
|
||
+@item --section-alignment
|
||
+Sets the section alignment. Sections in memory will always begin at
|
||
+addresses which are a multiple of this number. Defaults to 0x1000.
|
||
+[This option is specific to the i386 PE targeted port of the linker]
|
||
+
|
||
+@cindex stack size
|
||
+@kindex --stack
|
||
+@item --stack @var{reserve}
|
||
+@itemx --stack @var{reserve},@var{commit}
|
||
+Specify the number of bytes of memory to reserve (and optionally commit)
|
||
+to be used as stack for this program. The default is 2MB reserved, 4K
|
||
+committed.
|
||
+[This option is specific to the i386 PE targeted port of the linker]
|
||
+
|
||
+@kindex --subsystem
|
||
+@item --subsystem @var{which}
|
||
+@itemx --subsystem @var{which}:@var{major}
|
||
+@itemx --subsystem @var{which}:@var{major}.@var{minor}
|
||
+Specifies the subsystem under which your program will execute. The
|
||
+legal values for @var{which} are @code{native}, @code{windows},
|
||
+@code{console}, @code{posix}, and @code{xbox}. You may optionally set
|
||
+the subsystem version also. Numeric values are also accepted for
|
||
+@var{which}.
|
||
+[This option is specific to the i386 PE targeted port of the linker]
|
||
+
|
||
+The following options set flags in the @code{DllCharacteristics} field
|
||
+of the PE file header:
|
||
+[These options are specific to PE targeted ports of the linker]
|
||
+
|
||
+@kindex --high-entropy-va
|
||
+@item --high-entropy-va
|
||
+@itemx --disable-high-entropy-va
|
||
+Image is compatible with 64-bit address space layout randomization
|
||
+(ASLR). This option is enabled by default for 64-bit PE images.
|
||
+
|
||
+This option also implies @option{--dynamicbase} and
|
||
+@option{--enable-reloc-section}.
|
||
+
|
||
+@kindex --dynamicbase
|
||
+@item --dynamicbase
|
||
+@itemx --disable-dynamicbase
|
||
+The image base address may be relocated using address space layout
|
||
+randomization (ASLR). This feature was introduced with MS Windows
|
||
+Vista for i386 PE targets. This option is enabled by default but
|
||
+can be disabled via the @option{--disable-dynamicbase} option.
|
||
+This option also implies @option{--enable-reloc-section}.
|
||
+
|
||
+@kindex --forceinteg
|
||
+@item --forceinteg
|
||
+@itemx --disable-forceinteg
|
||
+Code integrity checks are enforced. This option is disabled by
|
||
+default.
|
||
+
|
||
+@kindex --nxcompat
|
||
+@item --nxcompat
|
||
+@item --disable-nxcompat
|
||
+The image is compatible with the Data Execution Prevention.
|
||
+This feature was introduced with MS Windows XP SP2 for i386 PE
|
||
+targets. The option is enabled by default.
|
||
+
|
||
+@kindex --no-isolation
|
||
+@item --no-isolation
|
||
+@itemx --disable-no-isolation
|
||
+Although the image understands isolation, do not isolate the image.
|
||
+This option is disabled by default.
|
||
+
|
||
+@kindex --no-seh
|
||
+@item --no-seh
|
||
+@itemx --disable-no-seh
|
||
+The image does not use SEH. No SE handler may be called from
|
||
+this image. This option is disabled by default.
|
||
+
|
||
+@kindex --no-bind
|
||
+@item --no-bind
|
||
+@itemx --disable-no-bind
|
||
+Do not bind this image. This option is disabled by default.
|
||
+
|
||
+@kindex --wdmdriver
|
||
+@item --wdmdriver
|
||
+@itemx --disable-wdmdriver
|
||
+The driver uses the MS Windows Driver Model. This option is disabled
|
||
+by default.
|
||
+
|
||
+@kindex --tsaware
|
||
+@item --tsaware
|
||
+@itemx --disable-tsaware
|
||
+The image is Terminal Server aware. This option is disabled by
|
||
+default.
|
||
+
|
||
+@kindex --insert-timestamp
|
||
+@item --insert-timestamp
|
||
+@itemx --no-insert-timestamp
|
||
+Insert a real timestamp into the image. This is the default behaviour
|
||
+as it matches legacy code and it means that the image will work with
|
||
+other, proprietary tools. The problem with this default is that it
|
||
+will result in slightly different images being produced each time the
|
||
+same sources are linked. The option @option{--no-insert-timestamp}
|
||
+can be used to insert a zero value for the timestamp, this ensuring
|
||
+that binaries produced from identical sources will compare
|
||
+identically.
|
||
+
|
||
+@kindex --enable-reloc-section
|
||
+@item --enable-reloc-section
|
||
+@itemx --disable-reloc-section
|
||
+Create the base relocation table, which is necessary if the image
|
||
+is loaded at a different image base than specified in the PE header.
|
||
+This option is enabled by default.
|
||
+@end table
|
||
+
|
||
+@c man end
|
||
+
|
||
+@ifset C6X
|
||
+@subsection Options specific to C6X uClinux targets
|
||
+
|
||
+@c man begin OPTIONS
|
||
+
|
||
+The C6X uClinux target uses a binary format called DSBT to support shared
|
||
+libraries. Each shared library in the system needs to have a unique index;
|
||
+all executables use an index of 0.
|
||
+
|
||
+@table @gcctabopt
|
||
+
|
||
+@kindex --dsbt-size
|
||
+@item --dsbt-size @var{size}
|
||
+This option sets the number of entries in the DSBT of the current executable
|
||
+or shared library to @var{size}. The default is to create a table with 64
|
||
+entries.
|
||
+
|
||
+@kindex --dsbt-index
|
||
+@item --dsbt-index @var{index}
|
||
+This option sets the DSBT index of the current executable or shared library
|
||
+to @var{index}. The default is 0, which is appropriate for generating
|
||
+executables. If a shared library is generated with a DSBT index of 0, the
|
||
+@code{R_C6000_DSBT_INDEX} relocs are copied into the output file.
|
||
+
|
||
+@kindex --no-merge-exidx-entries
|
||
+The @samp{--no-merge-exidx-entries} switch disables the merging of adjacent
|
||
+exidx entries in frame unwind info.
|
||
+
|
||
+@end table
|
||
+
|
||
+@c man end
|
||
+@end ifset
|
||
+
|
||
+@ifset CSKY
|
||
+@subsection Options specific to C-SKY targets
|
||
+
|
||
+@c man begin OPTIONS
|
||
+
|
||
+@table @gcctabopt
|
||
+
|
||
+@kindex --branch-stub on C-SKY
|
||
+@item --branch-stub
|
||
+This option enables linker branch relaxation by inserting branch stub
|
||
+sections when needed to extend the range of branches. This option is
|
||
+usually not required since C-SKY supports branch and call instructions that
|
||
+can access the full memory range and branch relaxation is normally handled by
|
||
+the compiler or assembler.
|
||
+
|
||
+@kindex --stub-group-size on C-SKY
|
||
+@item --stub-group-size=@var{N}
|
||
+This option allows finer control of linker branch stub creation.
|
||
+It sets the maximum size of a group of input sections that can
|
||
+be handled by one stub section. A negative value of @var{N} locates
|
||
+stub sections after their branches, while a positive value allows stub
|
||
+sections to appear either before or after the branches. Values of
|
||
+@samp{1} or @samp{-1} indicate that the
|
||
+linker should choose suitable defaults.
|
||
+
|
||
+@end table
|
||
+
|
||
+@c man end
|
||
+@end ifset
|
||
+
|
||
+@ifset M68HC11
|
||
+@subsection Options specific to Motorola 68HC11 and 68HC12 targets
|
||
+
|
||
+@c man begin OPTIONS
|
||
+
|
||
+The 68HC11 and 68HC12 linkers support specific options to control the
|
||
+memory bank switching mapping and trampoline code generation.
|
||
+
|
||
+@table @gcctabopt
|
||
+
|
||
+@kindex --no-trampoline
|
||
+@item --no-trampoline
|
||
+This option disables the generation of trampoline. By default a trampoline
|
||
+is generated for each far function which is called using a @code{jsr}
|
||
+instruction (this happens when a pointer to a far function is taken).
|
||
+
|
||
+@kindex --bank-window
|
||
+@item --bank-window @var{name}
|
||
+This option indicates to the linker the name of the memory region in
|
||
+the @samp{MEMORY} specification that describes the memory bank window.
|
||
+The definition of such region is then used by the linker to compute
|
||
+paging and addresses within the memory window.
|
||
+
|
||
+@end table
|
||
+
|
||
+@c man end
|
||
+@end ifset
|
||
+
|
||
+@ifset M68K
|
||
+@subsection Options specific to Motorola 68K target
|
||
+
|
||
+@c man begin OPTIONS
|
||
+
|
||
+The following options are supported to control handling of GOT generation
|
||
+when linking for 68K targets.
|
||
+
|
||
+@table @gcctabopt
|
||
+
|
||
+@kindex --got
|
||
+@item --got=@var{type}
|
||
+This option tells the linker which GOT generation scheme to use.
|
||
+@var{type} should be one of @samp{single}, @samp{negative},
|
||
+@samp{multigot} or @samp{target}. For more information refer to the
|
||
+Info entry for @file{ld}.
|
||
+
|
||
+@end table
|
||
+
|
||
+@c man end
|
||
+@end ifset
|
||
+
|
||
+@ifset MIPS
|
||
+@subsection Options specific to MIPS targets
|
||
+
|
||
+@c man begin OPTIONS
|
||
+
|
||
+The following options are supported to control microMIPS instruction
|
||
+generation and branch relocation checks for ISA mode transitions when
|
||
+linking for MIPS targets.
|
||
+
|
||
+@table @gcctabopt
|
||
+
|
||
+@kindex --insn32
|
||
+@item --insn32
|
||
+@kindex --no-insn32
|
||
+@itemx --no-insn32
|
||
+These options control the choice of microMIPS instructions used in code
|
||
+generated by the linker, such as that in the PLT or lazy binding stubs,
|
||
+or in relaxation. If @samp{--insn32} is used, then the linker only uses
|
||
+32-bit instruction encodings. By default or if @samp{--no-insn32} is
|
||
+used, all instruction encodings are used, including 16-bit ones where
|
||
+possible.
|
||
+
|
||
+@kindex --ignore-branch-isa
|
||
+@item --ignore-branch-isa
|
||
+@kindex --no-ignore-branch-isa
|
||
+@itemx --no-ignore-branch-isa
|
||
+These options control branch relocation checks for invalid ISA mode
|
||
+transitions. If @samp{--ignore-branch-isa} is used, then the linker
|
||
+accepts any branch relocations and any ISA mode transition required
|
||
+is lost in relocation calculation, except for some cases of @code{BAL}
|
||
+instructions which meet relaxation conditions and are converted to
|
||
+equivalent @code{JALX} instructions as the associated relocation is
|
||
+calculated. By default or if @samp{--no-ignore-branch-isa} is used
|
||
+a check is made causing the loss of an ISA mode transition to produce
|
||
+an error.
|
||
+
|
||
+@kindex --compact-branches
|
||
+@item --compact-branches
|
||
+@kindex --no-compact-branches
|
||
+@itemx --no-compact-branches
|
||
+These options control the generation of compact instructions by the linker
|
||
+in the PLT entries for MIPS R6.
|
||
+
|
||
+@end table
|
||
+
|
||
+@c man end
|
||
+@end ifset
|
||
+
|
||
+
|
||
+@ifset PDP11
|
||
+@subsection Options specific to PDP11 targets
|
||
+
|
||
+@c man begin OPTIONS
|
||
+
|
||
+For the pdp11-aout target, three variants of the output format can be
|
||
+produced as selected by the following options. The default variant
|
||
+for pdp11-aout is the @samp{--omagic} option, whereas for other
|
||
+targets @samp{--nmagic} is the default. The @samp{--imagic} option is
|
||
+defined only for the pdp11-aout target, while the others are described
|
||
+here as they apply to the pdp11-aout target.
|
||
+
|
||
+@table @gcctabopt
|
||
+
|
||
+@kindex -N
|
||
+@item -N
|
||
+@kindex --omagic
|
||
+@itemx --omagic
|
||
+
|
||
+Mark the output as @code{OMAGIC} (0407) in the @file{a.out} header to
|
||
+indicate that the text segment is not to be write-protected and
|
||
+shared. Since the text and data sections are both readable and
|
||
+writable, the data section is allocated immediately contiguous after
|
||
+the text segment. This is the oldest format for PDP11 executable
|
||
+programs and is the default for @command{ld} on PDP11 Unix systems
|
||
+from the beginning through 2.11BSD.
|
||
+
|
||
+@kindex -n
|
||
+@item -n
|
||
+@kindex --nmagic
|
||
+@itemx --nmagic
|
||
+
|
||
+Mark the output as @code{NMAGIC} (0410) in the @file{a.out} header to
|
||
+indicate that when the output file is executed, the text portion will
|
||
+be read-only and shareable among all processes executing the same
|
||
+file. This involves moving the data areas up to the first possible 8K
|
||
+byte page boundary following the end of the text. This option creates
|
||
+a @emph{pure executable} format.
|
||
+
|
||
+@kindex -z
|
||
+@item -z
|
||
+@kindex --imagic
|
||
+@itemx --imagic
|
||
+
|
||
+Mark the output as @code{IMAGIC} (0411) in the @file{a.out} header to
|
||
+indicate that when the output file is executed, the program text and
|
||
+data areas will be loaded into separate address spaces using the split
|
||
+instruction and data space feature of the memory management unit in
|
||
+larger models of the PDP11. This doubles the address space available
|
||
+to the program. The text segment is again pure, write-protected, and
|
||
+shareable. The only difference in the output format between this
|
||
+option and the others, besides the magic number, is that both the text
|
||
+and data sections start at location 0. The @samp{-z} option selected
|
||
+this format in 2.11BSD. This option creates a @emph{separate
|
||
+executable} format.
|
||
+
|
||
+@kindex --no-omagic
|
||
+@item --no-omagic
|
||
+
|
||
+Equivalent to @samp{--nmagic} for pdp11-aout.
|
||
+
|
||
+@end table
|
||
+
|
||
+@c man end
|
||
+@end ifset
|
||
+
|
||
+@ifset UsesEnvVars
|
||
+@node Environment
|
||
+@section Environment Variables
|
||
+
|
||
+@c man begin ENVIRONMENT
|
||
+
|
||
+You can change the behaviour of @command{ld} with the environment variables
|
||
+@ifclear SingleFormat
|
||
+@code{GNUTARGET},
|
||
+@end ifclear
|
||
+@code{LDEMULATION} and @code{COLLECT_NO_DEMANGLE}.
|
||
+
|
||
+@ifclear SingleFormat
|
||
+@kindex GNUTARGET
|
||
+@cindex default input format
|
||
+@code{GNUTARGET} determines the input-file object format if you don't
|
||
+use @samp{-b} (or its synonym @samp{--format}). Its value should be one
|
||
+of the BFD names for an input format (@pxref{BFD}). If there is no
|
||
+@code{GNUTARGET} in the environment, @command{ld} uses the natural format
|
||
+of the target. If @code{GNUTARGET} is set to @code{default} then BFD
|
||
+attempts to discover the input format by examining binary input files;
|
||
+this method often succeeds, but there are potential ambiguities, since
|
||
+there is no method of ensuring that the magic number used to specify
|
||
+object-file formats is unique. However, the configuration procedure for
|
||
+BFD on each system places the conventional format for that system first
|
||
+in the search-list, so ambiguities are resolved in favor of convention.
|
||
+@end ifclear
|
||
+
|
||
+@kindex LDEMULATION
|
||
+@cindex default emulation
|
||
+@cindex emulation, default
|
||
+@code{LDEMULATION} determines the default emulation if you don't use the
|
||
+@samp{-m} option. The emulation can affect various aspects of linker
|
||
+behaviour, particularly the default linker script. You can list the
|
||
+available emulations with the @samp{--verbose} or @samp{-V} options. If
|
||
+the @samp{-m} option is not used, and the @code{LDEMULATION} environment
|
||
+variable is not defined, the default emulation depends upon how the
|
||
+linker was configured.
|
||
+
|
||
+@kindex COLLECT_NO_DEMANGLE
|
||
+@cindex demangling, default
|
||
+Normally, the linker will default to demangling symbols. However, if
|
||
+@code{COLLECT_NO_DEMANGLE} is set in the environment, then it will
|
||
+default to not demangling symbols. This environment variable is used in
|
||
+a similar fashion by the @code{gcc} linker wrapper program. The default
|
||
+may be overridden by the @samp{--demangle} and @samp{--no-demangle}
|
||
+options.
|
||
+
|
||
+@c man end
|
||
+@end ifset
|
||
+
|
||
+@node Scripts
|
||
+@chapter Linker Scripts
|
||
+
|
||
+@cindex scripts
|
||
+@cindex linker scripts
|
||
+@cindex command files
|
||
+Every link is controlled by a @dfn{linker script}. This script is
|
||
+written in the linker command language.
|
||
+
|
||
+The main purpose of the linker script is to describe how the sections in
|
||
+the input files should be mapped into the output file, and to control
|
||
+the memory layout of the output file. Most linker scripts do nothing
|
||
+more than this. However, when necessary, the linker script can also
|
||
+direct the linker to perform many other operations, using the commands
|
||
+described below.
|
||
+
|
||
+The linker always uses a linker script. If you do not supply one
|
||
+yourself, the linker will use a default script that is compiled into the
|
||
+linker executable. You can use the @samp{--verbose} command-line option
|
||
+to display the default linker script. Certain command-line options,
|
||
+such as @samp{-r} or @samp{-N}, will affect the default linker script.
|
||
+
|
||
+You may supply your own linker script by using the @samp{-T} command
|
||
+line option. When you do this, your linker script will replace the
|
||
+default linker script.
|
||
+
|
||
+You may also use linker scripts implicitly by naming them as input files
|
||
+to the linker, as though they were files to be linked. @xref{Implicit
|
||
+Linker Scripts}.
|
||
+
|
||
+@menu
|
||
+* Basic Script Concepts:: Basic Linker Script Concepts
|
||
+* Script Format:: Linker Script Format
|
||
+* Simple Example:: Simple Linker Script Example
|
||
+* Simple Commands:: Simple Linker Script Commands
|
||
+* Assignments:: Assigning Values to Symbols
|
||
+* SECTIONS:: SECTIONS Command
|
||
+* MEMORY:: MEMORY Command
|
||
+* PHDRS:: PHDRS Command
|
||
+* VERSION:: VERSION Command
|
||
+* Expressions:: Expressions in Linker Scripts
|
||
+* Implicit Linker Scripts:: Implicit Linker Scripts
|
||
+@end menu
|
||
+
|
||
+@node Basic Script Concepts
|
||
+@section Basic Linker Script Concepts
|
||
+@cindex linker script concepts
|
||
+We need to define some basic concepts and vocabulary in order to
|
||
+describe the linker script language.
|
||
+
|
||
+The linker combines input files into a single output file. The output
|
||
+file and each input file are in a special data format known as an
|
||
+@dfn{object file format}. Each file is called an @dfn{object file}.
|
||
+The output file is often called an @dfn{executable}, but for our
|
||
+purposes we will also call it an object file. Each object file has,
|
||
+among other things, a list of @dfn{sections}. We sometimes refer to a
|
||
+section in an input file as an @dfn{input section}; similarly, a section
|
||
+in the output file is an @dfn{output section}.
|
||
+
|
||
+Each section in an object file has a name and a size. Most sections
|
||
+also have an associated block of data, known as the @dfn{section
|
||
+contents}. A section may be marked as @dfn{loadable}, which means that
|
||
+the contents should be loaded into memory when the output file is run.
|
||
+A section with no contents may be @dfn{allocatable}, which means that an
|
||
+area in memory should be set aside, but nothing in particular should be
|
||
+loaded there (in some cases this memory must be zeroed out). A section
|
||
+which is neither loadable nor allocatable typically contains some sort
|
||
+of debugging information.
|
||
+
|
||
+Every loadable or allocatable output section has two addresses. The
|
||
+first is the @dfn{VMA}, or virtual memory address. This is the address
|
||
+the section will have when the output file is run. The second is the
|
||
+@dfn{LMA}, or load memory address. This is the address at which the
|
||
+section will be loaded. In most cases the two addresses will be the
|
||
+same. An example of when they might be different is when a data section
|
||
+is loaded into ROM, and then copied into RAM when the program starts up
|
||
+(this technique is often used to initialize global variables in a ROM
|
||
+based system). In this case the ROM address would be the LMA, and the
|
||
+RAM address would be the VMA.
|
||
+
|
||
+You can see the sections in an object file by using the @code{objdump}
|
||
+program with the @samp{-h} option.
|
||
+
|
||
+Every object file also has a list of @dfn{symbols}, known as the
|
||
+@dfn{symbol table}. A symbol may be defined or undefined. Each symbol
|
||
+has a name, and each defined symbol has an address, among other
|
||
+information. If you compile a C or C++ program into an object file, you
|
||
+will get a defined symbol for every defined function and global or
|
||
+static variable. Every undefined function or global variable which is
|
||
+referenced in the input file will become an undefined symbol.
|
||
+
|
||
+You can see the symbols in an object file by using the @code{nm}
|
||
+program, or by using the @code{objdump} program with the @samp{-t}
|
||
+option.
|
||
+
|
||
+@node Script Format
|
||
+@section Linker Script Format
|
||
+@cindex linker script format
|
||
+Linker scripts are text files.
|
||
+
|
||
+You write a linker script as a series of commands. Each command is
|
||
+either a keyword, possibly followed by arguments, or an assignment to a
|
||
+symbol. You may separate commands using semicolons. Whitespace is
|
||
+generally ignored.
|
||
+
|
||
+Strings such as file or format names can normally be entered directly.
|
||
+If the file name contains a character such as a comma which would
|
||
+otherwise serve to separate file names, you may put the file name in
|
||
+double quotes. There is no way to use a double quote character in a
|
||
+file name.
|
||
+
|
||
+You may include comments in linker scripts just as in C, delimited by
|
||
+@samp{/*} and @samp{*/}. As in C, comments are syntactically equivalent
|
||
+to whitespace.
|
||
+
|
||
+@node Simple Example
|
||
+@section Simple Linker Script Example
|
||
+@cindex linker script example
|
||
+@cindex example of linker script
|
||
+Many linker scripts are fairly simple.
|
||
+
|
||
+The simplest possible linker script has just one command:
|
||
+@samp{SECTIONS}. You use the @samp{SECTIONS} command to describe the
|
||
+memory layout of the output file.
|
||
+
|
||
+The @samp{SECTIONS} command is a powerful command. Here we will
|
||
+describe a simple use of it. Let's assume your program consists only of
|
||
+code, initialized data, and uninitialized data. These will be in the
|
||
+@samp{.text}, @samp{.data}, and @samp{.bss} sections, respectively.
|
||
+Let's assume further that these are the only sections which appear in
|
||
+your input files.
|
||
+
|
||
+For this example, let's say that the code should be loaded at address
|
||
+0x10000, and that the data should start at address 0x8000000. Here is a
|
||
+linker script which will do that:
|
||
+@smallexample
|
||
+SECTIONS
|
||
+@{
|
||
+ . = 0x10000;
|
||
+ .text : @{ *(.text) @}
|
||
+ . = 0x8000000;
|
||
+ .data : @{ *(.data) @}
|
||
+ .bss : @{ *(.bss) @}
|
||
+@}
|
||
+@end smallexample
|
||
+
|
||
+You write the @samp{SECTIONS} command as the keyword @samp{SECTIONS},
|
||
+followed by a series of symbol assignments and output section
|
||
+descriptions enclosed in curly braces.
|
||
+
|
||
+The first line inside the @samp{SECTIONS} command of the above example
|
||
+sets the value of the special symbol @samp{.}, which is the location
|
||
+counter. If you do not specify the address of an output section in some
|
||
+other way (other ways are described later), the address is set from the
|
||
+current value of the location counter. The location counter is then
|
||
+incremented by the size of the output section. At the start of the
|
||
+@samp{SECTIONS} command, the location counter has the value @samp{0}.
|
||
+
|
||
+The second line defines an output section, @samp{.text}. The colon is
|
||
+required syntax which may be ignored for now. Within the curly braces
|
||
+after the output section name, you list the names of the input sections
|
||
+which should be placed into this output section. The @samp{*} is a
|
||
+wildcard which matches any file name. The expression @samp{*(.text)}
|
||
+means all @samp{.text} input sections in all input files.
|
||
+
|
||
+Since the location counter is @samp{0x10000} when the output section
|
||
+@samp{.text} is defined, the linker will set the address of the
|
||
+@samp{.text} section in the output file to be @samp{0x10000}.
|
||
+
|
||
+The remaining lines define the @samp{.data} and @samp{.bss} sections in
|
||
+the output file. The linker will place the @samp{.data} output section
|
||
+at address @samp{0x8000000}. After the linker places the @samp{.data}
|
||
+output section, the value of the location counter will be
|
||
+@samp{0x8000000} plus the size of the @samp{.data} output section. The
|
||
+effect is that the linker will place the @samp{.bss} output section
|
||
+immediately after the @samp{.data} output section in memory.
|
||
+
|
||
+The linker will ensure that each output section has the required
|
||
+alignment, by increasing the location counter if necessary. In this
|
||
+example, the specified addresses for the @samp{.text} and @samp{.data}
|
||
+sections will probably satisfy any alignment constraints, but the linker
|
||
+may have to create a small gap between the @samp{.data} and @samp{.bss}
|
||
+sections.
|
||
+
|
||
+That's it! That's a simple and complete linker script.
|
||
+
|
||
+@node Simple Commands
|
||
+@section Simple Linker Script Commands
|
||
+@cindex linker script simple commands
|
||
+In this section we describe the simple linker script commands.
|
||
+
|
||
+@menu
|
||
+* Entry Point:: Setting the entry point
|
||
+* File Commands:: Commands dealing with files
|
||
+@ifclear SingleFormat
|
||
+* Format Commands:: Commands dealing with object file formats
|
||
+@end ifclear
|
||
+
|
||
+* REGION_ALIAS:: Assign alias names to memory regions
|
||
+* Miscellaneous Commands:: Other linker script commands
|
||
+@end menu
|
||
+
|
||
+@node Entry Point
|
||
+@subsection Setting the Entry Point
|
||
+@kindex ENTRY(@var{symbol})
|
||
+@cindex start of execution
|
||
+@cindex first instruction
|
||
+@cindex entry point
|
||
+The first instruction to execute in a program is called the @dfn{entry
|
||
+point}. You can use the @code{ENTRY} linker script command to set the
|
||
+entry point. The argument is a symbol name:
|
||
+@smallexample
|
||
+ENTRY(@var{symbol})
|
||
+@end smallexample
|
||
+
|
||
+There are several ways to set the entry point. The linker will set the
|
||
+entry point by trying each of the following methods in order, and
|
||
+stopping when one of them succeeds:
|
||
+@itemize @bullet
|
||
+@item
|
||
+the @samp{-e} @var{entry} command-line option;
|
||
+@item
|
||
+the @code{ENTRY(@var{symbol})} command in a linker script;
|
||
+@item
|
||
+the value of a target-specific symbol, if it is defined; For many
|
||
+targets this is @code{start}, but PE- and BeOS-based systems for example
|
||
+check a list of possible entry symbols, matching the first one found.
|
||
+@item
|
||
+the address of the first byte of the code section, if present and an
|
||
+executable is being created - the code section is usually
|
||
+@samp{.text}, but can be something else;
|
||
+@item
|
||
+The address @code{0}.
|
||
+@end itemize
|
||
+
|
||
+@node File Commands
|
||
+@subsection Commands Dealing with Files
|
||
+@cindex linker script file commands
|
||
+Several linker script commands deal with files.
|
||
+
|
||
+@table @code
|
||
+@item INCLUDE @var{filename}
|
||
+@kindex INCLUDE @var{filename}
|
||
+@cindex including a linker script
|
||
+Include the linker script @var{filename} at this point. The file will
|
||
+be searched for in the current directory, and in any directory specified
|
||
+with the @option{-L} option. You can nest calls to @code{INCLUDE} up to
|
||
+10 levels deep.
|
||
+
|
||
+You can place @code{INCLUDE} directives at the top level, in @code{MEMORY} or
|
||
+@code{SECTIONS} commands, or in output section descriptions.
|
||
+
|
||
+@item INPUT(@var{file}, @var{file}, @dots{})
|
||
+@itemx INPUT(@var{file} @var{file} @dots{})
|
||
+@kindex INPUT(@var{files})
|
||
+@cindex input files in linker scripts
|
||
+@cindex input object files in linker scripts
|
||
+@cindex linker script input object files
|
||
+The @code{INPUT} command directs the linker to include the named files
|
||
+in the link, as though they were named on the command line.
|
||
+
|
||
+For example, if you always want to include @file{subr.o} any time you do
|
||
+a link, but you can't be bothered to put it on every link command line,
|
||
+then you can put @samp{INPUT (subr.o)} in your linker script.
|
||
+
|
||
+In fact, if you like, you can list all of your input files in the linker
|
||
+script, and then invoke the linker with nothing but a @samp{-T} option.
|
||
+
|
||
+In case a @dfn{sysroot prefix} is configured, and the filename starts
|
||
+with the @samp{/} character, and the script being processed was
|
||
+located inside the @dfn{sysroot prefix}, the filename will be looked
|
||
+for in the @dfn{sysroot prefix}. The @dfn{sysroot prefix} can also be forced by specifying
|
||
+@code{=} as the first character in the filename path, or prefixing the
|
||
+filename path with @code{$SYSROOT}. See also the description of
|
||
+@samp{-L} in @ref{Options,,Command-line Options}.
|
||
+
|
||
+If a @dfn{sysroot prefix} is not used then the linker will try to open
|
||
+the file in the directory containing the linker script. If it is not
|
||
+found the linker will then search the current directory. If it is still
|
||
+not found the linker will search through the archive library search
|
||
+path.
|
||
+
|
||
+If you use @samp{INPUT (-l@var{file})}, @command{ld} will transform the
|
||
+name to @code{lib@var{file}.a}, as with the command-line argument
|
||
+@samp{-l}.
|
||
+
|
||
+When you use the @code{INPUT} command in an implicit linker script, the
|
||
+files will be included in the link at the point at which the linker
|
||
+script file is included. This can affect archive searching.
|
||
+
|
||
+@item GROUP(@var{file}, @var{file}, @dots{})
|
||
+@itemx GROUP(@var{file} @var{file} @dots{})
|
||
+@kindex GROUP(@var{files})
|
||
+@cindex grouping input files
|
||
+The @code{GROUP} command is like @code{INPUT}, except that the named
|
||
+files should all be archives, and they are searched repeatedly until no
|
||
+new undefined references are created. See the description of @samp{-(}
|
||
+in @ref{Options,,Command-line Options}.
|
||
+
|
||
+@item AS_NEEDED(@var{file}, @var{file}, @dots{})
|
||
+@itemx AS_NEEDED(@var{file} @var{file} @dots{})
|
||
+@kindex AS_NEEDED(@var{files})
|
||
+This construct can appear only inside of the @code{INPUT} or @code{GROUP}
|
||
+commands, among other filenames. The files listed will be handled
|
||
+as if they appear directly in the @code{INPUT} or @code{GROUP} commands,
|
||
+with the exception of ELF shared libraries, that will be added only
|
||
+when they are actually needed. This construct essentially enables
|
||
+@option{--as-needed} option for all the files listed inside of it
|
||
+and restores previous @option{--as-needed} resp. @option{--no-as-needed}
|
||
+setting afterwards.
|
||
+
|
||
+@item OUTPUT(@var{filename})
|
||
+@kindex OUTPUT(@var{filename})
|
||
+@cindex output file name in linker script
|
||
+The @code{OUTPUT} command names the output file. Using
|
||
+@code{OUTPUT(@var{filename})} in the linker script is exactly like using
|
||
+@samp{-o @var{filename}} on the command line (@pxref{Options,,Command
|
||
+Line Options}). If both are used, the command-line option takes
|
||
+precedence.
|
||
+
|
||
+You can use the @code{OUTPUT} command to define a default name for the
|
||
+output file other than the usual default of @file{a.out}.
|
||
+
|
||
+@item SEARCH_DIR(@var{path})
|
||
+@kindex SEARCH_DIR(@var{path})
|
||
+@cindex library search path in linker script
|
||
+@cindex archive search path in linker script
|
||
+@cindex search path in linker script
|
||
+The @code{SEARCH_DIR} command adds @var{path} to the list of paths where
|
||
+@command{ld} looks for archive libraries. Using
|
||
+@code{SEARCH_DIR(@var{path})} is exactly like using @samp{-L @var{path}}
|
||
+on the command line (@pxref{Options,,Command-line Options}). If both
|
||
+are used, then the linker will search both paths. Paths specified using
|
||
+the command-line option are searched first.
|
||
+
|
||
+@item STARTUP(@var{filename})
|
||
+@kindex STARTUP(@var{filename})
|
||
+@cindex first input file
|
||
+The @code{STARTUP} command is just like the @code{INPUT} command, except
|
||
+that @var{filename} will become the first input file to be linked, as
|
||
+though it were specified first on the command line. This may be useful
|
||
+when using a system in which the entry point is always the start of the
|
||
+first file.
|
||
+@end table
|
||
+
|
||
+@ifclear SingleFormat
|
||
+@node Format Commands
|
||
+@subsection Commands Dealing with Object File Formats
|
||
+A couple of linker script commands deal with object file formats.
|
||
+
|
||
+@table @code
|
||
+@item OUTPUT_FORMAT(@var{bfdname})
|
||
+@itemx OUTPUT_FORMAT(@var{default}, @var{big}, @var{little})
|
||
+@kindex OUTPUT_FORMAT(@var{bfdname})
|
||
+@cindex output file format in linker script
|
||
+The @code{OUTPUT_FORMAT} command names the BFD format to use for the
|
||
+output file (@pxref{BFD}). Using @code{OUTPUT_FORMAT(@var{bfdname})} is
|
||
+exactly like using @samp{--oformat @var{bfdname}} on the command line
|
||
+(@pxref{Options,,Command-line Options}). If both are used, the command
|
||
+line option takes precedence.
|
||
+
|
||
+You can use @code{OUTPUT_FORMAT} with three arguments to use different
|
||
+formats based on the @samp{-EB} and @samp{-EL} command-line options.
|
||
+This permits the linker script to set the output format based on the
|
||
+desired endianness.
|
||
+
|
||
+If neither @samp{-EB} nor @samp{-EL} are used, then the output format
|
||
+will be the first argument, @var{default}. If @samp{-EB} is used, the
|
||
+output format will be the second argument, @var{big}. If @samp{-EL} is
|
||
+used, the output format will be the third argument, @var{little}.
|
||
+
|
||
+For example, the default linker script for the MIPS ELF target uses this
|
||
+command:
|
||
+@smallexample
|
||
+OUTPUT_FORMAT(elf32-bigmips, elf32-bigmips, elf32-littlemips)
|
||
+@end smallexample
|
||
+This says that the default format for the output file is
|
||
+@samp{elf32-bigmips}, but if the user uses the @samp{-EL} command-line
|
||
+option, the output file will be created in the @samp{elf32-littlemips}
|
||
+format.
|
||
+
|
||
+@item TARGET(@var{bfdname})
|
||
+@kindex TARGET(@var{bfdname})
|
||
+@cindex input file format in linker script
|
||
+The @code{TARGET} command names the BFD format to use when reading input
|
||
+files. It affects subsequent @code{INPUT} and @code{GROUP} commands.
|
||
+This command is like using @samp{-b @var{bfdname}} on the command line
|
||
+(@pxref{Options,,Command-line Options}). If the @code{TARGET} command
|
||
+is used but @code{OUTPUT_FORMAT} is not, then the last @code{TARGET}
|
||
+command is also used to set the format for the output file. @xref{BFD}.
|
||
+@end table
|
||
+@end ifclear
|
||
+
|
||
+@node REGION_ALIAS
|
||
+@subsection Assign alias names to memory regions
|
||
+@kindex REGION_ALIAS(@var{alias}, @var{region})
|
||
+@cindex region alias
|
||
+@cindex region names
|
||
+
|
||
+Alias names can be added to existing memory regions created with the
|
||
+@ref{MEMORY} command. Each name corresponds to at most one memory region.
|
||
+
|
||
+@smallexample
|
||
+REGION_ALIAS(@var{alias}, @var{region})
|
||
+@end smallexample
|
||
+
|
||
+The @code{REGION_ALIAS} function creates an alias name @var{alias} for the
|
||
+memory region @var{region}. This allows a flexible mapping of output sections
|
||
+to memory regions. An example follows.
|
||
+
|
||
+Suppose we have an application for embedded systems which come with various
|
||
+memory storage devices. All have a general purpose, volatile memory @code{RAM}
|
||
+that allows code execution or data storage. Some may have a read-only,
|
||
+non-volatile memory @code{ROM} that allows code execution and read-only data
|
||
+access. The last variant is a read-only, non-volatile memory @code{ROM2} with
|
||
+read-only data access and no code execution capability. We have four output
|
||
+sections:
|
||
+
|
||
+@itemize @bullet
|
||
+@item
|
||
+@code{.text} program code;
|
||
+@item
|
||
+@code{.rodata} read-only data;
|
||
+@item
|
||
+@code{.data} read-write initialized data;
|
||
+@item
|
||
+@code{.bss} read-write zero initialized data.
|
||
+@end itemize
|
||
+
|
||
+The goal is to provide a linker command file that contains a system independent
|
||
+part defining the output sections and a system dependent part mapping the
|
||
+output sections to the memory regions available on the system. Our embedded
|
||
+systems come with three different memory setups @code{A}, @code{B} and
|
||
+@code{C}:
|
||
+@multitable @columnfractions .25 .25 .25 .25
|
||
+@item Section @tab Variant A @tab Variant B @tab Variant C
|
||
+@item .text @tab RAM @tab ROM @tab ROM
|
||
+@item .rodata @tab RAM @tab ROM @tab ROM2
|
||
+@item .data @tab RAM @tab RAM/ROM @tab RAM/ROM2
|
||
+@item .bss @tab RAM @tab RAM @tab RAM
|
||
+@end multitable
|
||
+The notation @code{RAM/ROM} or @code{RAM/ROM2} means that this section is
|
||
+loaded into region @code{ROM} or @code{ROM2} respectively. Please note that
|
||
+the load address of the @code{.data} section starts in all three variants at
|
||
+the end of the @code{.rodata} section.
|
||
+
|
||
+The base linker script that deals with the output sections follows. It
|
||
+includes the system dependent @code{linkcmds.memory} file that describes the
|
||
+memory layout:
|
||
+@smallexample
|
||
+INCLUDE linkcmds.memory
|
||
+
|
||
+SECTIONS
|
||
+ @{
|
||
+ .text :
|
||
+ @{
|
||
+ *(.text)
|
||
+ @} > REGION_TEXT
|
||
+ .rodata :
|
||
+ @{
|
||
+ *(.rodata)
|
||
+ rodata_end = .;
|
||
+ @} > REGION_RODATA
|
||
+ .data : AT (rodata_end)
|
||
+ @{
|
||
+ data_start = .;
|
||
+ *(.data)
|
||
+ @} > REGION_DATA
|
||
+ data_size = SIZEOF(.data);
|
||
+ data_load_start = LOADADDR(.data);
|
||
+ .bss :
|
||
+ @{
|
||
+ *(.bss)
|
||
+ @} > REGION_BSS
|
||
+ @}
|
||
+@end smallexample
|
||
+
|
||
+Now we need three different @code{linkcmds.memory} files to define memory
|
||
+regions and alias names. The content of @code{linkcmds.memory} for the three
|
||
+variants @code{A}, @code{B} and @code{C}:
|
||
+@table @code
|
||
+@item A
|
||
+Here everything goes into the @code{RAM}.
|
||
+@smallexample
|
||
+MEMORY
|
||
+ @{
|
||
+ RAM : ORIGIN = 0, LENGTH = 4M
|
||
+ @}
|
||
+
|
||
+REGION_ALIAS("REGION_TEXT", RAM);
|
||
+REGION_ALIAS("REGION_RODATA", RAM);
|
||
+REGION_ALIAS("REGION_DATA", RAM);
|
||
+REGION_ALIAS("REGION_BSS", RAM);
|
||
+@end smallexample
|
||
+@item B
|
||
+Program code and read-only data go into the @code{ROM}. Read-write data goes
|
||
+into the @code{RAM}. An image of the initialized data is loaded into the
|
||
+@code{ROM} and will be copied during system start into the @code{RAM}.
|
||
+@smallexample
|
||
+MEMORY
|
||
+ @{
|
||
+ ROM : ORIGIN = 0, LENGTH = 3M
|
||
+ RAM : ORIGIN = 0x10000000, LENGTH = 1M
|
||
+ @}
|
||
+
|
||
+REGION_ALIAS("REGION_TEXT", ROM);
|
||
+REGION_ALIAS("REGION_RODATA", ROM);
|
||
+REGION_ALIAS("REGION_DATA", RAM);
|
||
+REGION_ALIAS("REGION_BSS", RAM);
|
||
+@end smallexample
|
||
+@item C
|
||
+Program code goes into the @code{ROM}. Read-only data goes into the
|
||
+@code{ROM2}. Read-write data goes into the @code{RAM}. An image of the
|
||
+initialized data is loaded into the @code{ROM2} and will be copied during
|
||
+system start into the @code{RAM}.
|
||
+@smallexample
|
||
+MEMORY
|
||
+ @{
|
||
+ ROM : ORIGIN = 0, LENGTH = 2M
|
||
+ ROM2 : ORIGIN = 0x10000000, LENGTH = 1M
|
||
+ RAM : ORIGIN = 0x20000000, LENGTH = 1M
|
||
+ @}
|
||
+
|
||
+REGION_ALIAS("REGION_TEXT", ROM);
|
||
+REGION_ALIAS("REGION_RODATA", ROM2);
|
||
+REGION_ALIAS("REGION_DATA", RAM);
|
||
+REGION_ALIAS("REGION_BSS", RAM);
|
||
+@end smallexample
|
||
+@end table
|
||
+
|
||
+It is possible to write a common system initialization routine to copy the
|
||
+@code{.data} section from @code{ROM} or @code{ROM2} into the @code{RAM} if
|
||
+necessary:
|
||
+@smallexample
|
||
+#include <string.h>
|
||
+
|
||
+extern char data_start [];
|
||
+extern char data_size [];
|
||
+extern char data_load_start [];
|
||
+
|
||
+void copy_data(void)
|
||
+@{
|
||
+ if (data_start != data_load_start)
|
||
+ @{
|
||
+ memcpy(data_start, data_load_start, (size_t) data_size);
|
||
+ @}
|
||
+@}
|
||
+@end smallexample
|
||
+
|
||
+@node Miscellaneous Commands
|
||
+@subsection Other Linker Script Commands
|
||
+There are a few other linker scripts commands.
|
||
+
|
||
+@table @code
|
||
+@item ASSERT(@var{exp}, @var{message})
|
||
+@kindex ASSERT
|
||
+@cindex assertion in linker script
|
||
+Ensure that @var{exp} is non-zero. If it is zero, then exit the linker
|
||
+with an error code, and print @var{message}.
|
||
+
|
||
+Note that assertions are checked before the final stages of linking
|
||
+take place. This means that expressions involving symbols PROVIDEd
|
||
+inside section definitions will fail if the user has not set values
|
||
+for those symbols. The only exception to this rule is PROVIDEd
|
||
+symbols that just reference dot. Thus an assertion like this:
|
||
+
|
||
+@smallexample
|
||
+ .stack :
|
||
+ @{
|
||
+ PROVIDE (__stack = .);
|
||
+ PROVIDE (__stack_size = 0x100);
|
||
+ ASSERT ((__stack > (_end + __stack_size)), "Error: No room left for the stack");
|
||
+ @}
|
||
+@end smallexample
|
||
+
|
||
+will fail if @code{__stack_size} is not defined elsewhere. Symbols
|
||
+PROVIDEd outside of section definitions are evaluated earlier, so they
|
||
+can be used inside ASSERTions. Thus:
|
||
+
|
||
+@smallexample
|
||
+ PROVIDE (__stack_size = 0x100);
|
||
+ .stack :
|
||
+ @{
|
||
+ PROVIDE (__stack = .);
|
||
+ ASSERT ((__stack > (_end + __stack_size)), "Error: No room left for the stack");
|
||
+ @}
|
||
+@end smallexample
|
||
+
|
||
+will work.
|
||
+
|
||
+@item EXTERN(@var{symbol} @var{symbol} @dots{})
|
||
+@kindex EXTERN
|
||
+@cindex undefined symbol in linker script
|
||
+Force @var{symbol} to be entered in the output file as an undefined
|
||
+symbol. Doing this may, for example, trigger linking of additional
|
||
+modules from standard libraries. You may list several @var{symbol}s for
|
||
+each @code{EXTERN}, and you may use @code{EXTERN} multiple times. This
|
||
+command has the same effect as the @samp{-u} command-line option.
|
||
+
|
||
+@item FORCE_COMMON_ALLOCATION
|
||
+@kindex FORCE_COMMON_ALLOCATION
|
||
+@cindex common allocation in linker script
|
||
+This command has the same effect as the @samp{-d} command-line option:
|
||
+to make @command{ld} assign space to common symbols even if a relocatable
|
||
+output file is specified (@samp{-r}).
|
||
+
|
||
+@item INHIBIT_COMMON_ALLOCATION
|
||
+@kindex INHIBIT_COMMON_ALLOCATION
|
||
+@cindex common allocation in linker script
|
||
+This command has the same effect as the @samp{--no-define-common}
|
||
+command-line option: to make @code{ld} omit the assignment of addresses
|
||
+to common symbols even for a non-relocatable output file.
|
||
+
|
||
+@item FORCE_GROUP_ALLOCATION
|
||
+@kindex FORCE_GROUP_ALLOCATION
|
||
+@cindex group allocation in linker script
|
||
+@cindex section groups
|
||
+@cindex COMDAT
|
||
+This command has the same effect as the
|
||
+@samp{--force-group-allocation} command-line option: to make
|
||
+@command{ld} place section group members like normal input sections,
|
||
+and to delete the section groups even if a relocatable output file is
|
||
+specified (@samp{-r}).
|
||
+
|
||
+@item INSERT [ AFTER | BEFORE ] @var{output_section}
|
||
+@kindex INSERT
|
||
+@cindex insert user script into default script
|
||
+This command is typically used in a script specified by @samp{-T} to
|
||
+augment the default @code{SECTIONS} with, for example, overlays. It
|
||
+inserts all prior linker script statements after (or before)
|
||
+@var{output_section}, and also causes @samp{-T} to not override the
|
||
+default linker script. The exact insertion point is as for orphan
|
||
+sections. @xref{Location Counter}. The insertion happens after the
|
||
+linker has mapped input sections to output sections. Prior to the
|
||
+insertion, since @samp{-T} scripts are parsed before the default
|
||
+linker script, statements in the @samp{-T} script occur before the
|
||
+default linker script statements in the internal linker representation
|
||
+of the script. In particular, input section assignments will be made
|
||
+to @samp{-T} output sections before those in the default script. Here
|
||
+is an example of how a @samp{-T} script using @code{INSERT} might look:
|
||
+
|
||
+@smallexample
|
||
+SECTIONS
|
||
+@{
|
||
+ OVERLAY :
|
||
+ @{
|
||
+ .ov1 @{ ov1*(.text) @}
|
||
+ .ov2 @{ ov2*(.text) @}
|
||
+ @}
|
||
+@}
|
||
+INSERT AFTER .text;
|
||
+@end smallexample
|
||
+
|
||
+Note that when @samp{-T} is used twice, once to override the default
|
||
+script and once to augment that script using @code{INSERT} the order
|
||
+of parsing and section assignments apply as for the default script.
|
||
+The script with @code{INSERT} should be specified @emph{first} on the
|
||
+command line.
|
||
+
|
||
+@item NOCROSSREFS(@var{section} @var{section} @dots{})
|
||
+@kindex NOCROSSREFS(@var{sections})
|
||
+@cindex cross references
|
||
+This command may be used to tell @command{ld} to issue an error about any
|
||
+references among certain output sections.
|
||
+
|
||
+In certain types of programs, particularly on embedded systems when
|
||
+using overlays, when one section is loaded into memory, another section
|
||
+will not be. Any direct references between the two sections would be
|
||
+errors. For example, it would be an error if code in one section called
|
||
+a function defined in the other section.
|
||
+
|
||
+The @code{NOCROSSREFS} command takes a list of output section names. If
|
||
+@command{ld} detects any cross references between the sections, it reports
|
||
+an error and returns a non-zero exit status. Note that the
|
||
+@code{NOCROSSREFS} command uses output section names, not input section
|
||
+names.
|
||
+
|
||
+@item NOCROSSREFS_TO(@var{tosection} @var{fromsection} @dots{})
|
||
+@kindex NOCROSSREFS_TO(@var{tosection} @var{fromsections})
|
||
+@cindex cross references
|
||
+This command may be used to tell @command{ld} to issue an error about any
|
||
+references to one section from a list of other sections.
|
||
+
|
||
+The @code{NOCROSSREFS} command is useful when ensuring that two or more
|
||
+output sections are entirely independent but there are situations where
|
||
+a one-way dependency is needed. For example, in a multi-core application
|
||
+there may be shared code that can be called from each core but for safety
|
||
+must never call back.
|
||
+
|
||
+The @code{NOCROSSREFS_TO} command takes a list of output section names.
|
||
+The first section can not be referenced from any of the other sections.
|
||
+If @command{ld} detects any references to the first section from any of
|
||
+the other sections, it reports an error and returns a non-zero exit
|
||
+status. Note that the @code{NOCROSSREFS_TO} command uses output section
|
||
+names, not input section names.
|
||
+
|
||
+@ifclear SingleFormat
|
||
+@item OUTPUT_ARCH(@var{bfdarch})
|
||
+@kindex OUTPUT_ARCH(@var{bfdarch})
|
||
+@cindex machine architecture
|
||
+@cindex architecture
|
||
+Specify a particular output machine architecture. The argument is one
|
||
+of the names used by the BFD library (@pxref{BFD}). You can see the
|
||
+architecture of an object file by using the @code{objdump} program with
|
||
+the @samp{-f} option.
|
||
+@end ifclear
|
||
+
|
||
+@item LD_FEATURE(@var{string})
|
||
+@kindex LD_FEATURE(@var{string})
|
||
+This command may be used to modify @command{ld} behavior. If
|
||
+@var{string} is @code{"SANE_EXPR"} then absolute symbols and numbers
|
||
+in a script are simply treated as numbers everywhere.
|
||
+@xref{Expression Section}.
|
||
+@end table
|
||
+
|
||
+@node Assignments
|
||
+@section Assigning Values to Symbols
|
||
+@cindex assignment in scripts
|
||
+@cindex symbol definition, scripts
|
||
+@cindex variables, defining
|
||
+You may assign a value to a symbol in a linker script. This will define
|
||
+the symbol and place it into the symbol table with a global scope.
|
||
+
|
||
+@menu
|
||
+* Simple Assignments:: Simple Assignments
|
||
+* HIDDEN:: HIDDEN
|
||
+* PROVIDE:: PROVIDE
|
||
+* PROVIDE_HIDDEN:: PROVIDE_HIDDEN
|
||
+* Source Code Reference:: How to use a linker script defined symbol in source code
|
||
+@end menu
|
||
+
|
||
+@node Simple Assignments
|
||
+@subsection Simple Assignments
|
||
+
|
||
+You may assign to a symbol using any of the C assignment operators:
|
||
+
|
||
+@table @code
|
||
+@item @var{symbol} = @var{expression} ;
|
||
+@itemx @var{symbol} += @var{expression} ;
|
||
+@itemx @var{symbol} -= @var{expression} ;
|
||
+@itemx @var{symbol} *= @var{expression} ;
|
||
+@itemx @var{symbol} /= @var{expression} ;
|
||
+@itemx @var{symbol} <<= @var{expression} ;
|
||
+@itemx @var{symbol} >>= @var{expression} ;
|
||
+@itemx @var{symbol} &= @var{expression} ;
|
||
+@itemx @var{symbol} |= @var{expression} ;
|
||
+@end table
|
||
+
|
||
+The first case will define @var{symbol} to the value of
|
||
+@var{expression}. In the other cases, @var{symbol} must already be
|
||
+defined, and the value will be adjusted accordingly.
|
||
+
|
||
+The special symbol name @samp{.} indicates the location counter. You
|
||
+may only use this within a @code{SECTIONS} command. @xref{Location Counter}.
|
||
+
|
||
+The semicolon after @var{expression} is required.
|
||
+
|
||
+Expressions are defined below; see @ref{Expressions}.
|
||
+
|
||
+You may write symbol assignments as commands in their own right, or as
|
||
+statements within a @code{SECTIONS} command, or as part of an output
|
||
+section description in a @code{SECTIONS} command.
|
||
+
|
||
+The section of the symbol will be set from the section of the
|
||
+expression; for more information, see @ref{Expression Section}.
|
||
+
|
||
+Here is an example showing the three different places that symbol
|
||
+assignments may be used:
|
||
+
|
||
+@smallexample
|
||
+floating_point = 0;
|
||
+SECTIONS
|
||
+@{
|
||
+ .text :
|
||
+ @{
|
||
+ *(.text)
|
||
+ _etext = .;
|
||
+ @}
|
||
+ _bdata = (. + 3) & ~ 3;
|
||
+ .data : @{ *(.data) @}
|
||
+@}
|
||
+@end smallexample
|
||
+@noindent
|
||
+In this example, the symbol @samp{floating_point} will be defined as
|
||
+zero. The symbol @samp{_etext} will be defined as the address following
|
||
+the last @samp{.text} input section. The symbol @samp{_bdata} will be
|
||
+defined as the address following the @samp{.text} output section aligned
|
||
+upward to a 4 byte boundary.
|
||
+
|
||
+@node HIDDEN
|
||
+@subsection HIDDEN
|
||
+@cindex HIDDEN
|
||
+For ELF targeted ports, define a symbol that will be hidden and won't be
|
||
+exported. The syntax is @code{HIDDEN(@var{symbol} = @var{expression})}.
|
||
+
|
||
+Here is the example from @ref{Simple Assignments}, rewritten to use
|
||
+@code{HIDDEN}:
|
||
+
|
||
+@smallexample
|
||
+HIDDEN(floating_point = 0);
|
||
+SECTIONS
|
||
+@{
|
||
+ .text :
|
||
+ @{
|
||
+ *(.text)
|
||
+ HIDDEN(_etext = .);
|
||
+ @}
|
||
+ HIDDEN(_bdata = (. + 3) & ~ 3);
|
||
+ .data : @{ *(.data) @}
|
||
+@}
|
||
+@end smallexample
|
||
+@noindent
|
||
+In this case none of the three symbols will be visible outside this module.
|
||
+
|
||
+@node PROVIDE
|
||
+@subsection PROVIDE
|
||
+@cindex PROVIDE
|
||
+In some cases, it is desirable for a linker script to define a symbol
|
||
+only if it is referenced and is not defined by any object included in
|
||
+the link. For example, traditional linkers defined the symbol
|
||
+@samp{etext}. However, ANSI C requires that the user be able to use
|
||
+@samp{etext} as a function name without encountering an error. The
|
||
+@code{PROVIDE} keyword may be used to define a symbol, such as
|
||
+@samp{etext}, only if it is referenced but not defined. The syntax is
|
||
+@code{PROVIDE(@var{symbol} = @var{expression})}.
|
||
+
|
||
+Here is an example of using @code{PROVIDE} to define @samp{etext}:
|
||
+@smallexample
|
||
+SECTIONS
|
||
+@{
|
||
+ .text :
|
||
+ @{
|
||
+ *(.text)
|
||
+ _etext = .;
|
||
+ PROVIDE(etext = .);
|
||
+ @}
|
||
+@}
|
||
+@end smallexample
|
||
+
|
||
+In this example, if the program defines @samp{_etext} (with a leading
|
||
+underscore), the linker will give a multiple definition diagnostic. If,
|
||
+on the other hand, the program defines @samp{etext} (with no leading
|
||
+underscore), the linker will silently use the definition in the program.
|
||
+If the program references @samp{etext} but does not define it, the
|
||
+linker will use the definition in the linker script.
|
||
+
|
||
+Note - the @code{PROVIDE} directive considers a common symbol to be
|
||
+defined, even though such a symbol could be combined with the symbol
|
||
+that the @code{PROVIDE} would create. This is particularly important
|
||
+when considering constructor and destructor list symbols such as
|
||
+@samp{__CTOR_LIST__} as these are often defined as common symbols.
|
||
+
|
||
+@node PROVIDE_HIDDEN
|
||
+@subsection PROVIDE_HIDDEN
|
||
+@cindex PROVIDE_HIDDEN
|
||
+Similar to @code{PROVIDE}. For ELF targeted ports, the symbol will be
|
||
+hidden and won't be exported.
|
||
+
|
||
+@node Source Code Reference
|
||
+@subsection Source Code Reference
|
||
+
|
||
+Accessing a linker script defined variable from source code is not
|
||
+intuitive. In particular a linker script symbol is not equivalent to
|
||
+a variable declaration in a high level language, it is instead a
|
||
+symbol that does not have a value.
|
||
+
|
||
+Before going further, it is important to note that compilers often
|
||
+transform names in the source code into different names when they are
|
||
+stored in the symbol table. For example, Fortran compilers commonly
|
||
+prepend or append an underscore, and C++ performs extensive @samp{name
|
||
+mangling}. Therefore there might be a discrepancy between the name
|
||
+of a variable as it is used in source code and the name of the same
|
||
+variable as it is defined in a linker script. For example in C a
|
||
+linker script variable might be referred to as:
|
||
+
|
||
+@smallexample
|
||
+ extern int foo;
|
||
+@end smallexample
|
||
+
|
||
+But in the linker script it might be defined as:
|
||
+
|
||
+@smallexample
|
||
+ _foo = 1000;
|
||
+@end smallexample
|
||
+
|
||
+In the remaining examples however it is assumed that no name
|
||
+transformation has taken place.
|
||
+
|
||
+When a symbol is declared in a high level language such as C, two
|
||
+things happen. The first is that the compiler reserves enough space
|
||
+in the program's memory to hold the @emph{value} of the symbol. The
|
||
+second is that the compiler creates an entry in the program's symbol
|
||
+table which holds the symbol's @emph{address}. ie the symbol table
|
||
+contains the address of the block of memory holding the symbol's
|
||
+value. So for example the following C declaration, at file scope:
|
||
+
|
||
+@smallexample
|
||
+ int foo = 1000;
|
||
+@end smallexample
|
||
+
|
||
+creates an entry called @samp{foo} in the symbol table. This entry
|
||
+holds the address of an @samp{int} sized block of memory where the
|
||
+number 1000 is initially stored.
|
||
+
|
||
+When a program references a symbol the compiler generates code that
|
||
+first accesses the symbol table to find the address of the symbol's
|
||
+memory block and then code to read the value from that memory block.
|
||
+So:
|
||
+
|
||
+@smallexample
|
||
+ foo = 1;
|
||
+@end smallexample
|
||
+
|
||
+looks up the symbol @samp{foo} in the symbol table, gets the address
|
||
+associated with this symbol and then writes the value 1 into that
|
||
+address. Whereas:
|
||
+
|
||
+@smallexample
|
||
+ int * a = & foo;
|
||
+@end smallexample
|
||
+
|
||
+looks up the symbol @samp{foo} in the symbol table, gets its address
|
||
+and then copies this address into the block of memory associated with
|
||
+the variable @samp{a}.
|
||
+
|
||
+Linker scripts symbol declarations, by contrast, create an entry in
|
||
+the symbol table but do not assign any memory to them. Thus they are
|
||
+an address without a value. So for example the linker script definition:
|
||
+
|
||
+@smallexample
|
||
+ foo = 1000;
|
||
+@end smallexample
|
||
+
|
||
+creates an entry in the symbol table called @samp{foo} which holds
|
||
+the address of memory location 1000, but nothing special is stored at
|
||
+address 1000. This means that you cannot access the @emph{value} of a
|
||
+linker script defined symbol - it has no value - all you can do is
|
||
+access the @emph{address} of a linker script defined symbol.
|
||
+
|
||
+Hence when you are using a linker script defined symbol in source code
|
||
+you should always take the address of the symbol, and never attempt to
|
||
+use its value. For example suppose you want to copy the contents of a
|
||
+section of memory called .ROM into a section called .FLASH and the
|
||
+linker script contains these declarations:
|
||
+
|
||
+@smallexample
|
||
+@group
|
||
+ start_of_ROM = .ROM;
|
||
+ end_of_ROM = .ROM + sizeof (.ROM);
|
||
+ start_of_FLASH = .FLASH;
|
||
+@end group
|
||
+@end smallexample
|
||
+
|
||
+Then the C source code to perform the copy would be:
|
||
+
|
||
+@smallexample
|
||
+@group
|
||
+ extern char start_of_ROM, end_of_ROM, start_of_FLASH;
|
||
+
|
||
+ memcpy (& start_of_FLASH, & start_of_ROM, & end_of_ROM - & start_of_ROM);
|
||
+@end group
|
||
+@end smallexample
|
||
+
|
||
+Note the use of the @samp{&} operators. These are correct.
|
||
+Alternatively the symbols can be treated as the names of vectors or
|
||
+arrays and then the code will again work as expected:
|
||
+
|
||
+@smallexample
|
||
+@group
|
||
+ extern char start_of_ROM[], end_of_ROM[], start_of_FLASH[];
|
||
+
|
||
+ memcpy (start_of_FLASH, start_of_ROM, end_of_ROM - start_of_ROM);
|
||
+@end group
|
||
+@end smallexample
|
||
+
|
||
+Note how using this method does not require the use of @samp{&}
|
||
+operators.
|
||
+
|
||
+@node SECTIONS
|
||
+@section SECTIONS Command
|
||
+@kindex SECTIONS
|
||
+The @code{SECTIONS} command tells the linker how to map input sections
|
||
+into output sections, and how to place the output sections in memory.
|
||
+
|
||
+The format of the @code{SECTIONS} command is:
|
||
+@smallexample
|
||
+SECTIONS
|
||
+@{
|
||
+ @var{sections-command}
|
||
+ @var{sections-command}
|
||
+ @dots{}
|
||
+@}
|
||
+@end smallexample
|
||
+
|
||
+Each @var{sections-command} may of be one of the following:
|
||
+
|
||
+@itemize @bullet
|
||
+@item
|
||
+an @code{ENTRY} command (@pxref{Entry Point,,Entry command})
|
||
+@item
|
||
+a symbol assignment (@pxref{Assignments})
|
||
+@item
|
||
+an output section description
|
||
+@item
|
||
+an overlay description
|
||
+@end itemize
|
||
+
|
||
+The @code{ENTRY} command and symbol assignments are permitted inside the
|
||
+@code{SECTIONS} command for convenience in using the location counter in
|
||
+those commands. This can also make the linker script easier to
|
||
+understand because you can use those commands at meaningful points in
|
||
+the layout of the output file.
|
||
+
|
||
+Output section descriptions and overlay descriptions are described
|
||
+below.
|
||
+
|
||
+If you do not use a @code{SECTIONS} command in your linker script, the
|
||
+linker will place each input section into an identically named output
|
||
+section in the order that the sections are first encountered in the
|
||
+input files. If all input sections are present in the first file, for
|
||
+example, the order of sections in the output file will match the order
|
||
+in the first input file. The first section will be at address zero.
|
||
+
|
||
+@menu
|
||
+* Output Section Description:: Output section description
|
||
+* Output Section Name:: Output section name
|
||
+* Output Section Address:: Output section address
|
||
+* Input Section:: Input section description
|
||
+* Output Section Data:: Output section data
|
||
+* Output Section Keywords:: Output section keywords
|
||
+* Output Section Discarding:: Output section discarding
|
||
+* Output Section Attributes:: Output section attributes
|
||
+* Overlay Description:: Overlay description
|
||
+@end menu
|
||
+
|
||
+@node Output Section Description
|
||
+@subsection Output Section Description
|
||
+The full description of an output section looks like this:
|
||
+@smallexample
|
||
+@group
|
||
+@var{section} [@var{address}] [(@var{type})] :
|
||
+ [AT(@var{lma})]
|
||
+ [ALIGN(@var{section_align}) | ALIGN_WITH_INPUT]
|
||
+ [SUBALIGN(@var{subsection_align})]
|
||
+ [@var{constraint}]
|
||
+ @{
|
||
+ @var{output-section-command}
|
||
+ @var{output-section-command}
|
||
+ @dots{}
|
||
+ @} [>@var{region}] [AT>@var{lma_region}] [:@var{phdr} :@var{phdr} @dots{}] [=@var{fillexp}] [,]
|
||
+@end group
|
||
+@end smallexample
|
||
+
|
||
+Most output sections do not use most of the optional section attributes.
|
||
+
|
||
+The whitespace around @var{section} is required, so that the section
|
||
+name is unambiguous. The colon and the curly braces are also required.
|
||
+The comma at the end may be required if a @var{fillexp} is used and
|
||
+the next @var{sections-command} looks like a continuation of the expression.
|
||
+The line breaks and other white space are optional.
|
||
+
|
||
+Each @var{output-section-command} may be one of the following:
|
||
+
|
||
+@itemize @bullet
|
||
+@item
|
||
+a symbol assignment (@pxref{Assignments})
|
||
+@item
|
||
+an input section description (@pxref{Input Section})
|
||
+@item
|
||
+data values to include directly (@pxref{Output Section Data})
|
||
+@item
|
||
+a special output section keyword (@pxref{Output Section Keywords})
|
||
+@end itemize
|
||
+
|
||
+@node Output Section Name
|
||
+@subsection Output Section Name
|
||
+@cindex name, section
|
||
+@cindex section name
|
||
+The name of the output section is @var{section}. @var{section} must
|
||
+meet the constraints of your output format. In formats which only
|
||
+support a limited number of sections, such as @code{a.out}, the name
|
||
+must be one of the names supported by the format (@code{a.out}, for
|
||
+example, allows only @samp{.text}, @samp{.data} or @samp{.bss}). If the
|
||
+output format supports any number of sections, but with numbers and not
|
||
+names (as is the case for Oasys), the name should be supplied as a
|
||
+quoted numeric string. A section name may consist of any sequence of
|
||
+characters, but a name which contains any unusual characters such as
|
||
+commas must be quoted.
|
||
+
|
||
+The output section name @samp{/DISCARD/} is special; @ref{Output Section
|
||
+Discarding}.
|
||
+
|
||
+@node Output Section Address
|
||
+@subsection Output Section Address
|
||
+@cindex address, section
|
||
+@cindex section address
|
||
+The @var{address} is an expression for the VMA (the virtual memory
|
||
+address) of the output section. This address is optional, but if it
|
||
+is provided then the output address will be set exactly as specified.
|
||
+
|
||
+If the output address is not specified then one will be chosen for the
|
||
+section, based on the heuristic below. This address will be adjusted
|
||
+to fit the alignment requirement of the output section. The
|
||
+alignment requirement is the strictest alignment of any input section
|
||
+contained within the output section.
|
||
+
|
||
+The output section address heuristic is as follows:
|
||
+
|
||
+@itemize @bullet
|
||
+@item
|
||
+If an output memory @var{region} is set for the section then it
|
||
+is added to this region and its address will be the next free address
|
||
+in that region.
|
||
+
|
||
+@item
|
||
+If the MEMORY command has been used to create a list of memory
|
||
+regions then the first region which has attributes compatible with the
|
||
+section is selected to contain it. The section's output address will
|
||
+be the next free address in that region; @ref{MEMORY}.
|
||
+
|
||
+@item
|
||
+If no memory regions were specified, or none match the section then
|
||
+the output address will be based on the current value of the location
|
||
+counter.
|
||
+@end itemize
|
||
+
|
||
+@noindent
|
||
+For example:
|
||
+
|
||
+@smallexample
|
||
+.text . : @{ *(.text) @}
|
||
+@end smallexample
|
||
+
|
||
+@noindent
|
||
+and
|
||
+
|
||
+@smallexample
|
||
+.text : @{ *(.text) @}
|
||
+@end smallexample
|
||
+
|
||
+@noindent
|
||
+are subtly different. The first will set the address of the
|
||
+@samp{.text} output section to the current value of the location
|
||
+counter. The second will set it to the current value of the location
|
||
+counter aligned to the strictest alignment of any of the @samp{.text}
|
||
+input sections.
|
||
+
|
||
+The @var{address} may be an arbitrary expression; @ref{Expressions}.
|
||
+For example, if you want to align the section on a 0x10 byte boundary,
|
||
+so that the lowest four bits of the section address are zero, you could
|
||
+do something like this:
|
||
+@smallexample
|
||
+.text ALIGN(0x10) : @{ *(.text) @}
|
||
+@end smallexample
|
||
+@noindent
|
||
+This works because @code{ALIGN} returns the current location counter
|
||
+aligned upward to the specified value.
|
||
+
|
||
+Specifying @var{address} for a section will change the value of the
|
||
+location counter, provided that the section is non-empty. (Empty
|
||
+sections are ignored).
|
||
+
|
||
+@node Input Section
|
||
+@subsection Input Section Description
|
||
+@cindex input sections
|
||
+@cindex mapping input sections to output sections
|
||
+The most common output section command is an input section description.
|
||
+
|
||
+The input section description is the most basic linker script operation.
|
||
+You use output sections to tell the linker how to lay out your program
|
||
+in memory. You use input section descriptions to tell the linker how to
|
||
+map the input files into your memory layout.
|
||
+
|
||
+@menu
|
||
+* Input Section Basics:: Input section basics
|
||
+* Input Section Wildcards:: Input section wildcard patterns
|
||
+* Input Section Common:: Input section for common symbols
|
||
+* Input Section Keep:: Input section and garbage collection
|
||
+* Input Section Example:: Input section example
|
||
+@end menu
|
||
+
|
||
+@node Input Section Basics
|
||
+@subsubsection Input Section Basics
|
||
+@cindex input section basics
|
||
+An input section description consists of a file name optionally followed
|
||
+by a list of section names in parentheses.
|
||
+
|
||
+The file name and the section name may be wildcard patterns, which we
|
||
+describe further below (@pxref{Input Section Wildcards}).
|
||
+
|
||
+The most common input section description is to include all input
|
||
+sections with a particular name in the output section. For example, to
|
||
+include all input @samp{.text} sections, you would write:
|
||
+@smallexample
|
||
+*(.text)
|
||
+@end smallexample
|
||
+@noindent
|
||
+Here the @samp{*} is a wildcard which matches any file name. To exclude a list
|
||
+@cindex EXCLUDE_FILE
|
||
+of files from matching the file name wildcard, EXCLUDE_FILE may be used to
|
||
+match all files except the ones specified in the EXCLUDE_FILE list. For
|
||
+example:
|
||
+@smallexample
|
||
+EXCLUDE_FILE (*crtend.o *otherfile.o) *(.ctors)
|
||
+@end smallexample
|
||
+@noindent
|
||
+will cause all .ctors sections from all files except @file{crtend.o}
|
||
+and @file{otherfile.o} to be included. The EXCLUDE_FILE can also be
|
||
+placed inside the section list, for example:
|
||
+@smallexample
|
||
+*(EXCLUDE_FILE (*crtend.o *otherfile.o) .ctors)
|
||
+@end smallexample
|
||
+@noindent
|
||
+The result of this is identically to the previous example. Supporting
|
||
+two syntaxes for EXCLUDE_FILE is useful if the section list contains
|
||
+more than one section, as described below.
|
||
+
|
||
+There are two ways to include more than one section:
|
||
+@smallexample
|
||
+*(.text .rdata)
|
||
+*(.text) *(.rdata)
|
||
+@end smallexample
|
||
+@noindent
|
||
+The difference between these is the order in which the @samp{.text} and
|
||
+@samp{.rdata} input sections will appear in the output section. In the
|
||
+first example, they will be intermingled, appearing in the same order as
|
||
+they are found in the linker input. In the second example, all
|
||
+@samp{.text} input sections will appear first, followed by all
|
||
+@samp{.rdata} input sections.
|
||
+
|
||
+When using EXCLUDE_FILE with more than one section, if the exclusion
|
||
+is within the section list then the exclusion only applies to the
|
||
+immediately following section, for example:
|
||
+@smallexample
|
||
+*(EXCLUDE_FILE (*somefile.o) .text .rdata)
|
||
+@end smallexample
|
||
+@noindent
|
||
+will cause all @samp{.text} sections from all files except
|
||
+@file{somefile.o} to be included, while all @samp{.rdata} sections
|
||
+from all files, including @file{somefile.o}, will be included. To
|
||
+exclude the @samp{.rdata} sections from @file{somefile.o} the example
|
||
+could be modified to:
|
||
+@smallexample
|
||
+*(EXCLUDE_FILE (*somefile.o) .text EXCLUDE_FILE (*somefile.o) .rdata)
|
||
+@end smallexample
|
||
+@noindent
|
||
+Alternatively, placing the EXCLUDE_FILE outside of the section list,
|
||
+before the input file selection, will cause the exclusion to apply for
|
||
+all sections. Thus the previous example can be rewritten as:
|
||
+@smallexample
|
||
+EXCLUDE_FILE (*somefile.o) *(.text .rdata)
|
||
+@end smallexample
|
||
+
|
||
+You can specify a file name to include sections from a particular file.
|
||
+You would do this if one or more of your files contain special data that
|
||
+needs to be at a particular location in memory. For example:
|
||
+@smallexample
|
||
+data.o(.data)
|
||
+@end smallexample
|
||
+
|
||
+To refine the sections that are included based on the section flags
|
||
+of an input section, INPUT_SECTION_FLAGS may be used.
|
||
+
|
||
+Here is a simple example for using Section header flags for ELF sections:
|
||
+
|
||
+@smallexample
|
||
+@group
|
||
+SECTIONS @{
|
||
+ .text : @{ INPUT_SECTION_FLAGS (SHF_MERGE & SHF_STRINGS) *(.text) @}
|
||
+ .text2 : @{ INPUT_SECTION_FLAGS (!SHF_WRITE) *(.text) @}
|
||
+@}
|
||
+@end group
|
||
+@end smallexample
|
||
+
|
||
+In this example, the output section @samp{.text} will be comprised of any
|
||
+input section matching the name *(.text) whose section header flags
|
||
+@code{SHF_MERGE} and @code{SHF_STRINGS} are set. The output section
|
||
+@samp{.text2} will be comprised of any input section matching the name *(.text)
|
||
+whose section header flag @code{SHF_WRITE} is clear.
|
||
+
|
||
+You can also specify files within archives by writing a pattern
|
||
+matching the archive, a colon, then the pattern matching the file,
|
||
+with no whitespace around the colon.
|
||
+
|
||
+@table @samp
|
||
+@item archive:file
|
||
+matches file within archive
|
||
+@item archive:
|
||
+matches the whole archive
|
||
+@item :file
|
||
+matches file but not one in an archive
|
||
+@end table
|
||
+
|
||
+Either one or both of @samp{archive} and @samp{file} can contain shell
|
||
+wildcards. On DOS based file systems, the linker will assume that a
|
||
+single letter followed by a colon is a drive specifier, so
|
||
+@samp{c:myfile.o} is a simple file specification, not @samp{myfile.o}
|
||
+within an archive called @samp{c}. @samp{archive:file} filespecs may
|
||
+also be used within an @code{EXCLUDE_FILE} list, but may not appear in
|
||
+other linker script contexts. For instance, you cannot extract a file
|
||
+from an archive by using @samp{archive:file} in an @code{INPUT}
|
||
+command.
|
||
+
|
||
+If you use a file name without a list of sections, then all sections in
|
||
+the input file will be included in the output section. This is not
|
||
+commonly done, but it may by useful on occasion. For example:
|
||
+@smallexample
|
||
+data.o
|
||
+@end smallexample
|
||
+
|
||
+When you use a file name which is not an @samp{archive:file} specifier
|
||
+and does not contain any wild card
|
||
+characters, the linker will first see if you also specified the file
|
||
+name on the linker command line or in an @code{INPUT} command. If you
|
||
+did not, the linker will attempt to open the file as an input file, as
|
||
+though it appeared on the command line. Note that this differs from an
|
||
+@code{INPUT} command, because the linker will not search for the file in
|
||
+the archive search path.
|
||
+
|
||
+@node Input Section Wildcards
|
||
+@subsubsection Input Section Wildcard Patterns
|
||
+@cindex input section wildcards
|
||
+@cindex wildcard file name patterns
|
||
+@cindex file name wildcard patterns
|
||
+@cindex section name wildcard patterns
|
||
+In an input section description, either the file name or the section
|
||
+name or both may be wildcard patterns.
|
||
+
|
||
+The file name of @samp{*} seen in many examples is a simple wildcard
|
||
+pattern for the file name.
|
||
+
|
||
+The wildcard patterns are like those used by the Unix shell.
|
||
+
|
||
+@table @samp
|
||
+@item *
|
||
+matches any number of characters
|
||
+@item ?
|
||
+matches any single character
|
||
+@item [@var{chars}]
|
||
+matches a single instance of any of the @var{chars}; the @samp{-}
|
||
+character may be used to specify a range of characters, as in
|
||
+@samp{[a-z]} to match any lower case letter
|
||
+@item \
|
||
+quotes the following character
|
||
+@end table
|
||
+
|
||
+File name wildcard patterns only match files which are explicitly
|
||
+specified on the command line or in an @code{INPUT} command. The linker
|
||
+does not search directories to expand wildcards.
|
||
+
|
||
+If a file name matches more than one wildcard pattern, or if a file name
|
||
+appears explicitly and is also matched by a wildcard pattern, the linker
|
||
+will use the first match in the linker script. For example, this
|
||
+sequence of input section descriptions is probably in error, because the
|
||
+@file{data.o} rule will not be used:
|
||
+@smallexample
|
||
+.data : @{ *(.data) @}
|
||
+.data1 : @{ data.o(.data) @}
|
||
+@end smallexample
|
||
+
|
||
+@cindex SORT_BY_NAME
|
||
+Normally, the linker will place files and sections matched by wildcards
|
||
+in the order in which they are seen during the link. You can change
|
||
+this by using the @code{SORT_BY_NAME} keyword, which appears before a wildcard
|
||
+pattern in parentheses (e.g., @code{SORT_BY_NAME(.text*)}). When the
|
||
+@code{SORT_BY_NAME} keyword is used, the linker will sort the files or sections
|
||
+into ascending order by name before placing them in the output file.
|
||
+
|
||
+@cindex SORT_BY_ALIGNMENT
|
||
+@code{SORT_BY_ALIGNMENT} is similar to @code{SORT_BY_NAME}.
|
||
+@code{SORT_BY_ALIGNMENT} will sort sections into descending order of
|
||
+alignment before placing them in the output file. Placing larger
|
||
+alignments before smaller alignments can reduce the amount of padding
|
||
+needed.
|
||
+
|
||
+@cindex SORT_BY_INIT_PRIORITY
|
||
+@code{SORT_BY_INIT_PRIORITY} is also similar to @code{SORT_BY_NAME}.
|
||
+@code{SORT_BY_INIT_PRIORITY} will sort sections into ascending
|
||
+numerical order of the GCC init_priority attribute encoded in the
|
||
+section name before placing them in the output file. In
|
||
+@code{.init_array.NNNNN} and @code{.fini_array.NNNNN}, @code{NNNNN} is
|
||
+the init_priority. In @code{.ctors.NNNNN} and @code{.dtors.NNNNN},
|
||
+@code{NNNNN} is 65535 minus the init_priority.
|
||
+
|
||
+@cindex SORT
|
||
+@code{SORT} is an alias for @code{SORT_BY_NAME}.
|
||
+
|
||
+When there are nested section sorting commands in linker script, there
|
||
+can be at most 1 level of nesting for section sorting commands.
|
||
+
|
||
+@enumerate
|
||
+@item
|
||
+@code{SORT_BY_NAME} (@code{SORT_BY_ALIGNMENT} (wildcard section pattern)).
|
||
+It will sort the input sections by name first, then by alignment if two
|
||
+sections have the same name.
|
||
+@item
|
||
+@code{SORT_BY_ALIGNMENT} (@code{SORT_BY_NAME} (wildcard section pattern)).
|
||
+It will sort the input sections by alignment first, then by name if two
|
||
+sections have the same alignment.
|
||
+@item
|
||
+@code{SORT_BY_NAME} (@code{SORT_BY_NAME} (wildcard section pattern)) is
|
||
+treated the same as @code{SORT_BY_NAME} (wildcard section pattern).
|
||
+@item
|
||
+@code{SORT_BY_ALIGNMENT} (@code{SORT_BY_ALIGNMENT} (wildcard section pattern))
|
||
+is treated the same as @code{SORT_BY_ALIGNMENT} (wildcard section pattern).
|
||
+@item
|
||
+All other nested section sorting commands are invalid.
|
||
+@end enumerate
|
||
+
|
||
+When both command-line section sorting option and linker script
|
||
+section sorting command are used, section sorting command always
|
||
+takes precedence over the command-line option.
|
||
+
|
||
+If the section sorting command in linker script isn't nested, the
|
||
+command-line option will make the section sorting command to be
|
||
+treated as nested sorting command.
|
||
+
|
||
+@enumerate
|
||
+@item
|
||
+@code{SORT_BY_NAME} (wildcard section pattern ) with
|
||
+@option{--sort-sections alignment} is equivalent to
|
||
+@code{SORT_BY_NAME} (@code{SORT_BY_ALIGNMENT} (wildcard section pattern)).
|
||
+@item
|
||
+@code{SORT_BY_ALIGNMENT} (wildcard section pattern) with
|
||
+@option{--sort-section name} is equivalent to
|
||
+@code{SORT_BY_ALIGNMENT} (@code{SORT_BY_NAME} (wildcard section pattern)).
|
||
+@end enumerate
|
||
+
|
||
+If the section sorting command in linker script is nested, the
|
||
+command-line option will be ignored.
|
||
+
|
||
+@cindex SORT_NONE
|
||
+@code{SORT_NONE} disables section sorting by ignoring the command-line
|
||
+section sorting option.
|
||
+
|
||
+If you ever get confused about where input sections are going, use the
|
||
+@samp{-M} linker option to generate a map file. The map file shows
|
||
+precisely how input sections are mapped to output sections.
|
||
+
|
||
+This example shows how wildcard patterns might be used to partition
|
||
+files. This linker script directs the linker to place all @samp{.text}
|
||
+sections in @samp{.text} and all @samp{.bss} sections in @samp{.bss}.
|
||
+The linker will place the @samp{.data} section from all files beginning
|
||
+with an upper case character in @samp{.DATA}; for all other files, the
|
||
+linker will place the @samp{.data} section in @samp{.data}.
|
||
+@smallexample
|
||
+@group
|
||
+SECTIONS @{
|
||
+ .text : @{ *(.text) @}
|
||
+ .DATA : @{ [A-Z]*(.data) @}
|
||
+ .data : @{ *(.data) @}
|
||
+ .bss : @{ *(.bss) @}
|
||
+@}
|
||
+@end group
|
||
+@end smallexample
|
||
+
|
||
+@node Input Section Common
|
||
+@subsubsection Input Section for Common Symbols
|
||
+@cindex common symbol placement
|
||
+@cindex uninitialized data placement
|
||
+A special notation is needed for common symbols, because in many object
|
||
+file formats common symbols do not have a particular input section. The
|
||
+linker treats common symbols as though they are in an input section
|
||
+named @samp{COMMON}.
|
||
+
|
||
+You may use file names with the @samp{COMMON} section just as with any
|
||
+other input sections. You can use this to place common symbols from a
|
||
+particular input file in one section while common symbols from other
|
||
+input files are placed in another section.
|
||
+
|
||
+In most cases, common symbols in input files will be placed in the
|
||
+@samp{.bss} section in the output file. For example:
|
||
+@smallexample
|
||
+.bss @{ *(.bss) *(COMMON) @}
|
||
+@end smallexample
|
||
+
|
||
+@cindex scommon section
|
||
+@cindex small common symbols
|
||
+Some object file formats have more than one type of common symbol. For
|
||
+example, the MIPS ELF object file format distinguishes standard common
|
||
+symbols and small common symbols. In this case, the linker will use a
|
||
+different special section name for other types of common symbols. In
|
||
+the case of MIPS ELF, the linker uses @samp{COMMON} for standard common
|
||
+symbols and @samp{.scommon} for small common symbols. This permits you
|
||
+to map the different types of common symbols into memory at different
|
||
+locations.
|
||
+
|
||
+@cindex [COMMON]
|
||
+You will sometimes see @samp{[COMMON]} in old linker scripts. This
|
||
+notation is now considered obsolete. It is equivalent to
|
||
+@samp{*(COMMON)}.
|
||
+
|
||
+@node Input Section Keep
|
||
+@subsubsection Input Section and Garbage Collection
|
||
+@cindex KEEP
|
||
+@cindex garbage collection
|
||
+When link-time garbage collection is in use (@samp{--gc-sections}),
|
||
+it is often useful to mark sections that should not be eliminated.
|
||
+This is accomplished by surrounding an input section's wildcard entry
|
||
+with @code{KEEP()}, as in @code{KEEP(*(.init))} or
|
||
+@code{KEEP(SORT_BY_NAME(*)(.ctors))}.
|
||
+
|
||
+@node Input Section Example
|
||
+@subsubsection Input Section Example
|
||
+The following example is a complete linker script. It tells the linker
|
||
+to read all of the sections from file @file{all.o} and place them at the
|
||
+start of output section @samp{outputa} which starts at location
|
||
+@samp{0x10000}. All of section @samp{.input1} from file @file{foo.o}
|
||
+follows immediately, in the same output section. All of section
|
||
+@samp{.input2} from @file{foo.o} goes into output section
|
||
+@samp{outputb}, followed by section @samp{.input1} from @file{foo1.o}.
|
||
+All of the remaining @samp{.input1} and @samp{.input2} sections from any
|
||
+files are written to output section @samp{outputc}.
|
||
+
|
||
+@smallexample
|
||
+@group
|
||
+SECTIONS @{
|
||
+ outputa 0x10000 :
|
||
+ @{
|
||
+ all.o
|
||
+ foo.o (.input1)
|
||
+ @}
|
||
+@end group
|
||
+@group
|
||
+ outputb :
|
||
+ @{
|
||
+ foo.o (.input2)
|
||
+ foo1.o (.input1)
|
||
+ @}
|
||
+@end group
|
||
+@group
|
||
+ outputc :
|
||
+ @{
|
||
+ *(.input1)
|
||
+ *(.input2)
|
||
+ @}
|
||
+@}
|
||
+@end group
|
||
+@end smallexample
|
||
+
|
||
+If an output section's name is the same as the input section's name
|
||
+and is representable as a C identifier, then the linker will
|
||
+automatically @pxref{PROVIDE} two symbols: __start_SECNAME and
|
||
+__stop_SECNAME, where SECNAME is the name of the section. These
|
||
+indicate the start address and end address of the output section
|
||
+respectively. Note: most section names are not representable as
|
||
+C identifiers because they contain a @samp{.} character.
|
||
+
|
||
+@node Output Section Data
|
||
+@subsection Output Section Data
|
||
+@cindex data
|
||
+@cindex section data
|
||
+@cindex output section data
|
||
+@kindex ASCIZ ``@var{string}''
|
||
+@kindex BYTE(@var{expression})
|
||
+@kindex SHORT(@var{expression})
|
||
+@kindex LONG(@var{expression})
|
||
+@kindex QUAD(@var{expression})
|
||
+@kindex SQUAD(@var{expression})
|
||
+You can include explicit bytes of data in an output section by using
|
||
+@code{BYTE}, @code{SHORT}, @code{LONG}, @code{QUAD}, or @code{SQUAD} as
|
||
+an output section command. Each keyword is followed by an expression in
|
||
+parentheses providing the value to store (@pxref{Expressions}). The
|
||
+value of the expression is stored at the current value of the location
|
||
+counter.
|
||
+
|
||
+The @code{BYTE}, @code{SHORT}, @code{LONG}, and @code{QUAD} commands
|
||
+store one, two, four, and eight bytes (respectively). After storing the
|
||
+bytes, the location counter is incremented by the number of bytes
|
||
+stored.
|
||
+
|
||
+For example, this will store the byte 1 followed by the four byte value
|
||
+of the symbol @samp{addr}:
|
||
+@smallexample
|
||
+BYTE(1)
|
||
+LONG(addr)
|
||
+@end smallexample
|
||
+
|
||
+When using a 64 bit host or target, @code{QUAD} and @code{SQUAD} are the
|
||
+same; they both store an 8 byte, or 64 bit, value. When both host and
|
||
+target are 32 bits, an expression is computed as 32 bits. In this case
|
||
+@code{QUAD} stores a 32 bit value zero extended to 64 bits, and
|
||
+@code{SQUAD} stores a 32 bit value sign extended to 64 bits.
|
||
+
|
||
+If the object file format of the output file has an explicit endianness,
|
||
+which is the normal case, the value will be stored in that endianness.
|
||
+When the object file format does not have an explicit endianness, as is
|
||
+true of, for example, S-records, the value will be stored in the
|
||
+endianness of the first input object file.
|
||
+
|
||
+You can include a zero-terminated string in an output section by using
|
||
+@code{ASCIZ}. The keyword is followed by a string which is stored at
|
||
+the current value of the location counter adding a zero byte at the
|
||
+end. If the string includes spaces it must be enclosed in double
|
||
+quotes. The string may contain '\n', '\r', '\t' and octal numbers.
|
||
+Hex numbers are not supported.
|
||
+
|
||
+For example, this string of 16 characters will create a 17 byte area
|
||
+@smallexample
|
||
+ ASCIZ "This is 16 bytes"
|
||
+@end smallexample
|
||
+
|
||
+Note---these commands only work inside a section description and not
|
||
+between them, so the following will produce an error from the linker:
|
||
+@smallexample
|
||
+SECTIONS @{@ .text : @{@ *(.text) @}@ LONG(1) .data : @{@ *(.data) @}@ @}@
|
||
+@end smallexample
|
||
+whereas this will work:
|
||
+@smallexample
|
||
+SECTIONS @{@ .text : @{@ *(.text) ; LONG(1) @}@ .data : @{@ *(.data) @}@ @}@
|
||
+@end smallexample
|
||
+
|
||
+@kindex FILL(@var{expression})
|
||
+@cindex holes, filling
|
||
+@cindex unspecified memory
|
||
+You may use the @code{FILL} command to set the fill pattern for the
|
||
+current section. It is followed by an expression in parentheses. Any
|
||
+otherwise unspecified regions of memory within the section (for example,
|
||
+gaps left due to the required alignment of input sections) are filled
|
||
+with the value of the expression, repeated as
|
||
+necessary. A @code{FILL} statement covers memory locations after the
|
||
+point at which it occurs in the section definition; by including more
|
||
+than one @code{FILL} statement, you can have different fill patterns in
|
||
+different parts of an output section.
|
||
+
|
||
+This example shows how to fill unspecified regions of memory with the
|
||
+value @samp{0x90}:
|
||
+@smallexample
|
||
+FILL(0x90909090)
|
||
+@end smallexample
|
||
+
|
||
+The @code{FILL} command is similar to the @samp{=@var{fillexp}} output
|
||
+section attribute, but it only affects the
|
||
+part of the section following the @code{FILL} command, rather than the
|
||
+entire section. If both are used, the @code{FILL} command takes
|
||
+precedence. @xref{Output Section Fill}, for details on the fill
|
||
+expression.
|
||
+
|
||
+@kindex LINKER_VERSION
|
||
+@cindex LINKER_VERSION
|
||
+Inserts a string containing the version of the linker at the current
|
||
+point. Note - by default this directive is disabled and will do
|
||
+nothing. It only becomes active if the
|
||
+@option{--enable-linker-version} command line option is used.
|
||
+
|
||
+Built-in linker scripts for ELF based targets already include this
|
||
+directive in their @samp{.comment} section.
|
||
+
|
||
+@node Output Section Keywords
|
||
+@subsection Output Section Keywords
|
||
+There are a couple of keywords which can appear as output section
|
||
+commands.
|
||
+
|
||
+@table @code
|
||
+@kindex CREATE_OBJECT_SYMBOLS
|
||
+@cindex input filename symbols
|
||
+@cindex filename symbols
|
||
+@item CREATE_OBJECT_SYMBOLS
|
||
+The command tells the linker to create a symbol for each input file.
|
||
+The name of each symbol will be the name of the corresponding input
|
||
+file. The section of each symbol will be the output section in which
|
||
+the @code{CREATE_OBJECT_SYMBOLS} command appears.
|
||
+
|
||
+This is conventional for the a.out object file format. It is not
|
||
+normally used for any other object file format.
|
||
+
|
||
+@kindex CONSTRUCTORS
|
||
+@cindex C++ constructors, arranging in link
|
||
+@cindex constructors, arranging in link
|
||
+@item CONSTRUCTORS
|
||
+When linking using the a.out object file format, the linker uses an
|
||
+unusual set construct to support C++ global constructors and
|
||
+destructors. When linking object file formats which do not support
|
||
+arbitrary sections, such as ECOFF and XCOFF, the linker will
|
||
+automatically recognize C++ global constructors and destructors by name.
|
||
+For these object file formats, the @code{CONSTRUCTORS} command tells the
|
||
+linker to place constructor information in the output section where the
|
||
+@code{CONSTRUCTORS} command appears. The @code{CONSTRUCTORS} command is
|
||
+ignored for other object file formats.
|
||
+
|
||
+The symbol @w{@code{__CTOR_LIST__}} marks the start of the global
|
||
+constructors, and the symbol @w{@code{__CTOR_END__}} marks the end.
|
||
+Similarly, @w{@code{__DTOR_LIST__}} and @w{@code{__DTOR_END__}} mark
|
||
+the start and end of the global destructors. The
|
||
+first word in the list is the number of entries, followed by the address
|
||
+of each constructor or destructor, followed by a zero word. The
|
||
+compiler must arrange to actually run the code. For these object file
|
||
+formats @sc{gnu} C++ normally calls constructors from a subroutine
|
||
+@code{__main}; a call to @code{__main} is automatically inserted into
|
||
+the startup code for @code{main}. @sc{gnu} C++ normally runs
|
||
+destructors either by using @code{atexit}, or directly from the function
|
||
+@code{exit}.
|
||
+
|
||
+For object file formats such as @code{COFF} or @code{ELF} which support
|
||
+arbitrary section names, @sc{gnu} C++ will normally arrange to put the
|
||
+addresses of global constructors and destructors into the @code{.ctors}
|
||
+and @code{.dtors} sections. Placing the following sequence into your
|
||
+linker script will build the sort of table which the @sc{gnu} C++
|
||
+runtime code expects to see.
|
||
+
|
||
+@smallexample
|
||
+ __CTOR_LIST__ = .;
|
||
+ LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2)
|
||
+ *(.ctors)
|
||
+ LONG(0)
|
||
+ __CTOR_END__ = .;
|
||
+ __DTOR_LIST__ = .;
|
||
+ LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2)
|
||
+ *(.dtors)
|
||
+ LONG(0)
|
||
+ __DTOR_END__ = .;
|
||
+@end smallexample
|
||
+
|
||
+If you are using the @sc{gnu} C++ support for initialization priority,
|
||
+which provides some control over the order in which global constructors
|
||
+are run, you must sort the constructors at link time to ensure that they
|
||
+are executed in the correct order. When using the @code{CONSTRUCTORS}
|
||
+command, use @samp{SORT_BY_NAME(CONSTRUCTORS)} instead. When using the
|
||
+@code{.ctors} and @code{.dtors} sections, use @samp{*(SORT_BY_NAME(.ctors))} and
|
||
+@samp{*(SORT_BY_NAME(.dtors))} instead of just @samp{*(.ctors)} and
|
||
+@samp{*(.dtors)}.
|
||
+
|
||
+Normally the compiler and linker will handle these issues automatically,
|
||
+and you will not need to concern yourself with them. However, you may
|
||
+need to consider this if you are using C++ and writing your own linker
|
||
+scripts.
|
||
+
|
||
+@end table
|
||
+
|
||
+@node Output Section Discarding
|
||
+@subsection Output Section Discarding
|
||
+@cindex discarding sections
|
||
+@cindex sections, discarding
|
||
+@cindex removing sections
|
||
+The linker will not normally create output sections with no contents.
|
||
+This is for convenience when referring to input sections that may or
|
||
+may not be present in any of the input files. For example:
|
||
+@smallexample
|
||
+.foo : @{ *(.foo) @}
|
||
+@end smallexample
|
||
+@noindent
|
||
+will only create a @samp{.foo} section in the output file if there is a
|
||
+@samp{.foo} section in at least one input file, and if the input
|
||
+sections are not all empty. Other link script directives that allocate
|
||
+space in an output section will also create the output section. So
|
||
+too will assignments to dot even if the assignment does not create
|
||
+space, except for @samp{. = 0}, @samp{. = . + 0}, @samp{. = sym},
|
||
+@samp{. = . + sym} and @samp{. = ALIGN (. != 0, expr, 1)} when
|
||
+@samp{sym} is an absolute symbol of value 0 defined in the script.
|
||
+This allows you to force output of an empty section with @samp{. = .}.
|
||
+
|
||
+The linker will ignore address assignments (@pxref{Output Section Address})
|
||
+on discarded output sections, except when the linker script defines
|
||
+symbols in the output section. In that case the linker will obey
|
||
+the address assignments, possibly advancing dot even though the
|
||
+section is discarded.
|
||
+
|
||
+@cindex /DISCARD/
|
||
+The special output section name @samp{/DISCARD/} may be used to discard
|
||
+input sections. Any input sections which are assigned to an output
|
||
+section named @samp{/DISCARD/} are not included in the output file.
|
||
+
|
||
+This can be used to discard input sections marked with the ELF flag
|
||
+@code{SHF_GNU_RETAIN}, which would otherwise have been saved from linker
|
||
+garbage collection.
|
||
+
|
||
+Note, sections that match the @samp{/DISCARD/} output section will be
|
||
+discarded even if they are in an ELF section group which has other
|
||
+members which are not being discarded. This is deliberate.
|
||
+Discarding takes precedence over grouping.
|
||
+
|
||
+@node Output Section Attributes
|
||
+@subsection Output Section Attributes
|
||
+@cindex output section attributes
|
||
+We showed above that the full description of an output section looked
|
||
+like this:
|
||
+
|
||
+@smallexample
|
||
+@group
|
||
+@var{section} [@var{address}] [(@var{type})] :
|
||
+ [AT(@var{lma})]
|
||
+ [ALIGN(@var{section_align}) | ALIGN_WITH_INPUT]
|
||
+ [SUBALIGN(@var{subsection_align})]
|
||
+ [@var{constraint}]
|
||
+ @{
|
||
+ @var{output-section-command}
|
||
+ @var{output-section-command}
|
||
+ @dots{}
|
||
+ @} [>@var{region}] [AT>@var{lma_region}] [:@var{phdr} :@var{phdr} @dots{}] [=@var{fillexp}]
|
||
+@end group
|
||
+@end smallexample
|
||
+
|
||
+We've already described @var{section}, @var{address}, and
|
||
+@var{output-section-command}. In this section we will describe the
|
||
+remaining section attributes.
|
||
+
|
||
+@menu
|
||
+* Output Section Type:: Output section type
|
||
+* Output Section LMA:: Output section LMA
|
||
+* Forced Output Alignment:: Forced Output Alignment
|
||
+* Forced Input Alignment:: Forced Input Alignment
|
||
+* Output Section Constraint:: Output section constraint
|
||
+* Output Section Region:: Output section region
|
||
+* Output Section Phdr:: Output section phdr
|
||
+* Output Section Fill:: Output section fill
|
||
+@end menu
|
||
+
|
||
+@node Output Section Type
|
||
+@subsubsection Output Section Type
|
||
+Each output section may have a type. The type is a keyword in
|
||
+parentheses. The following types are defined:
|
||
+
|
||
+@table @code
|
||
+
|
||
+@item NOLOAD
|
||
+The section should be marked as not loadable, so that it will not be
|
||
+loaded into memory when the program is run.
|
||
+
|
||
+@item READONLY
|
||
+The section should be marked as read-only.
|
||
+
|
||
+@item DSECT
|
||
+@item COPY
|
||
+@item INFO
|
||
+@item OVERLAY
|
||
+These type names are supported for backward compatibility, and are
|
||
+rarely used. They all have the same effect: the section should be
|
||
+marked as not allocatable, so that no memory is allocated for the
|
||
+section when the program is run.
|
||
+
|
||
+@item TYPE = @var{type}
|
||
+Set the section type to the integer @var{type}. When generating an ELF
|
||
+output file, type names @code{SHT_PROGBITS}, @code{SHT_STRTAB},
|
||
+@code{SHT_NOTE}, @code{SHT_NOBITS}, @code{SHT_INIT_ARRAY},
|
||
+@code{SHT_FINI_ARRAY}, and @code{SHT_PREINIT_ARRAY} are also allowed
|
||
+for @var{type}. It is the user's responsibility to ensure that any
|
||
+special requirements of the section type are met.
|
||
+
|
||
+Note - the TYPE only is used if some or all of the contents of the
|
||
+section do not have an implicit type of their own. So for example:
|
||
+@smallexample
|
||
+ .foo . TYPE = SHT_PROGBITS @{ *(.bar) @}
|
||
+@end smallexample
|
||
+will set the type of section @samp{.foo} to the type of the section
|
||
+@samp{.bar} in the input files, which may not be the SHT_PROGBITS
|
||
+type. Whereas:
|
||
+@smallexample
|
||
+ .foo . TYPE = SHT_PROGBITS @{ BYTE(1) @}
|
||
+@end smallexample
|
||
+will set the type of @samp{.foo} to SHT_PROGBBITS. If it is necessary
|
||
+to override the type of incoming sections and force the output section
|
||
+type then an extra piece of untyped data will be needed:
|
||
+@smallexample
|
||
+ .foo . TYPE = SHT_PROGBITS @{ BYTE(1); *(.bar) @}
|
||
+@end smallexample
|
||
+
|
||
+@item READONLY ( TYPE = @var{type} )
|
||
+This form of the syntax combines the @var{READONLY} type with the
|
||
+type specified by @var{type}.
|
||
+
|
||
+@end table
|
||
+
|
||
+@kindex NOLOAD
|
||
+@cindex prevent unnecessary loading
|
||
+@cindex loading, preventing
|
||
+The linker normally sets the attributes of an output section based on
|
||
+the input sections which map into it. You can override this by using
|
||
+the section type. For example, in the script sample below, the
|
||
+@samp{ROM} section is addressed at memory location @samp{0} and does not
|
||
+need to be loaded when the program is run.
|
||
+@smallexample
|
||
+@group
|
||
+SECTIONS @{
|
||
+ ROM 0 (NOLOAD) : @{ @dots{} @}
|
||
+ @dots{}
|
||
+@}
|
||
+@end group
|
||
+@end smallexample
|
||
+
|
||
+@node Output Section LMA
|
||
+@subsubsection Output Section LMA
|
||
+@kindex AT>@var{lma_region}
|
||
+@kindex AT(@var{lma})
|
||
+@cindex load address
|
||
+@cindex section load address
|
||
+Every section has a virtual address (VMA) and a load address (LMA); see
|
||
+@ref{Basic Script Concepts}. The virtual address is specified by the
|
||
+@pxref{Output Section Address} described earlier. The load address is
|
||
+specified by the @code{AT} or @code{AT>} keywords. Specifying a load
|
||
+address is optional.
|
||
+
|
||
+The @code{AT} keyword takes an expression as an argument. This
|
||
+specifies the exact load address of the section. The @code{AT>} keyword
|
||
+takes the name of a memory region as an argument. @xref{MEMORY}. The
|
||
+load address of the section is set to the next free address in the
|
||
+region, aligned to the section's alignment requirements.
|
||
+
|
||
+If neither @code{AT} nor @code{AT>} is specified for an allocatable
|
||
+section, the linker will use the following heuristic to determine the
|
||
+load address:
|
||
+
|
||
+@itemize @bullet
|
||
+@item
|
||
+If the section has a specific VMA address, then this is used as
|
||
+the LMA address as well.
|
||
+
|
||
+@item
|
||
+If the section is not allocatable then its LMA is set to its VMA.
|
||
+
|
||
+@item
|
||
+Otherwise if a memory region can be found that is compatible
|
||
+with the current section, and this region contains at least one
|
||
+section, then the LMA is set so the difference between the
|
||
+VMA and LMA is the same as the difference between the VMA and LMA of
|
||
+the last section in the located region.
|
||
+
|
||
+@item
|
||
+If no memory regions have been declared then a default region
|
||
+that covers the entire address space is used in the previous step.
|
||
+
|
||
+@item
|
||
+If no suitable region could be found, or there was no previous
|
||
+section then the LMA is set equal to the VMA.
|
||
+@end itemize
|
||
+
|
||
+@cindex ROM initialized data
|
||
+@cindex initialized data in ROM
|
||
+This feature is designed to make it easy to build a ROM image. For
|
||
+example, the following linker script creates three output sections: one
|
||
+called @samp{.text}, which starts at @code{0x1000}, one called
|
||
+@samp{.mdata}, which is loaded at the end of the @samp{.text} section
|
||
+even though its VMA is @code{0x2000}, and one called @samp{.bss} to hold
|
||
+uninitialized data at address @code{0x3000}. The symbol @code{_data} is
|
||
+defined with the value @code{0x2000}, which shows that the location
|
||
+counter holds the VMA value, not the LMA value.
|
||
+
|
||
+@smallexample
|
||
+@group
|
||
+SECTIONS
|
||
+ @{
|
||
+ .text 0x1000 : @{ *(.text) _etext = . ; @}
|
||
+ .mdata 0x2000 :
|
||
+ AT ( ADDR (.text) + SIZEOF (.text) )
|
||
+ @{ _data = . ; *(.data); _edata = . ; @}
|
||
+ .bss 0x3000 :
|
||
+ @{ _bstart = . ; *(.bss) *(COMMON) ; _bend = . ;@}
|
||
+@}
|
||
+@end group
|
||
+@end smallexample
|
||
+
|
||
+The run-time initialization code for use with a program generated with
|
||
+this linker script would include something like the following, to copy
|
||
+the initialized data from the ROM image to its runtime address. Notice
|
||
+how this code takes advantage of the symbols defined by the linker
|
||
+script.
|
||
+
|
||
+@smallexample
|
||
+@group
|
||
+extern char _etext, _data, _edata, _bstart, _bend;
|
||
+char *src = &_etext;
|
||
+char *dst = &_data;
|
||
+
|
||
+/* ROM has data at end of text; copy it. */
|
||
+while (dst < &_edata)
|
||
+ *dst++ = *src++;
|
||
+
|
||
+/* Zero bss. */
|
||
+for (dst = &_bstart; dst< &_bend; dst++)
|
||
+ *dst = 0;
|
||
+@end group
|
||
+@end smallexample
|
||
+
|
||
+@node Forced Output Alignment
|
||
+@subsubsection Forced Output Alignment
|
||
+@kindex ALIGN(@var{section_align})
|
||
+@cindex forcing output section alignment
|
||
+@cindex output section alignment
|
||
+You can increase an output section's alignment by using ALIGN. As an
|
||
+alternative you can enforce that the difference between the VMA and LMA remains
|
||
+intact throughout this output section with the ALIGN_WITH_INPUT attribute.
|
||
+
|
||
+@node Forced Input Alignment
|
||
+@subsubsection Forced Input Alignment
|
||
+@kindex SUBALIGN(@var{subsection_align})
|
||
+@cindex forcing input section alignment
|
||
+@cindex input section alignment
|
||
+You can force input section alignment within an output section by using
|
||
+SUBALIGN. The value specified overrides any alignment given by input
|
||
+sections, whether larger or smaller.
|
||
+
|
||
+@node Output Section Constraint
|
||
+@subsubsection Output Section Constraint
|
||
+@kindex ONLY_IF_RO
|
||
+@kindex ONLY_IF_RW
|
||
+@cindex constraints on output sections
|
||
+You can specify that an output section should only be created if all
|
||
+of its input sections are read-only or all of its input sections are
|
||
+read-write by using the keyword @code{ONLY_IF_RO} and
|
||
+@code{ONLY_IF_RW} respectively.
|
||
+
|
||
+@node Output Section Region
|
||
+@subsubsection Output Section Region
|
||
+@kindex >@var{region}
|
||
+@cindex section, assigning to memory region
|
||
+@cindex memory regions and sections
|
||
+You can assign a section to a previously defined region of memory by
|
||
+using @samp{>@var{region}}. @xref{MEMORY}.
|
||
+
|
||
+Here is a simple example:
|
||
+@smallexample
|
||
+@group
|
||
+MEMORY @{ rom : ORIGIN = 0x1000, LENGTH = 0x1000 @}
|
||
+SECTIONS @{ ROM : @{ *(.text) @} >rom @}
|
||
+@end group
|
||
+@end smallexample
|
||
+
|
||
+@node Output Section Phdr
|
||
+@subsubsection Output Section Phdr
|
||
+@kindex :@var{phdr}
|
||
+@cindex section, assigning to program header
|
||
+@cindex program headers and sections
|
||
+You can assign a section to a previously defined program segment by
|
||
+using @samp{:@var{phdr}}. @xref{PHDRS}. If a section is assigned to
|
||
+one or more segments, then all subsequent allocated sections will be
|
||
+assigned to those segments as well, unless they use an explicitly
|
||
+@code{:@var{phdr}} modifier. You can use @code{:NONE} to tell the
|
||
+linker to not put the section in any segment at all.
|
||
+
|
||
+Here is a simple example:
|
||
+@smallexample
|
||
+@group
|
||
+PHDRS @{ text PT_LOAD ; @}
|
||
+SECTIONS @{ .text : @{ *(.text) @} :text @}
|
||
+@end group
|
||
+@end smallexample
|
||
+
|
||
+@node Output Section Fill
|
||
+@subsubsection Output Section Fill
|
||
+@kindex =@var{fillexp}
|
||
+@cindex section fill pattern
|
||
+@cindex fill pattern, entire section
|
||
+You can set the fill pattern for an entire section by using
|
||
+@samp{=@var{fillexp}}. @var{fillexp} is an expression
|
||
+(@pxref{Expressions}). Any otherwise unspecified regions of memory
|
||
+within the output section (for example, gaps left due to the required
|
||
+alignment of input sections) will be filled with the value, repeated as
|
||
+necessary. If the fill expression is a simple hex number, ie. a string
|
||
+of hex digit starting with @samp{0x} and without a trailing @samp{k} or @samp{M}, then
|
||
+an arbitrarily long sequence of hex digits can be used to specify the
|
||
+fill pattern; Leading zeros become part of the pattern too. For all
|
||
+other cases, including extra parentheses or a unary @code{+}, the fill
|
||
+pattern is the four least significant bytes of the value of the
|
||
+expression. In all cases, the number is big-endian.
|
||
+
|
||
+You can also change the fill value with a @code{FILL} command in the
|
||
+output section commands; (@pxref{Output Section Data}).
|
||
+
|
||
+Here is a simple example:
|
||
+@smallexample
|
||
+@group
|
||
+SECTIONS @{ .text : @{ *(.text) @} =0x90909090 @}
|
||
+@end group
|
||
+@end smallexample
|
||
+
|
||
+@node Overlay Description
|
||
+@subsection Overlay Description
|
||
+@kindex OVERLAY
|
||
+@cindex overlays
|
||
+An overlay description provides an easy way to describe sections which
|
||
+are to be loaded as part of a single memory image but are to be run at
|
||
+the same memory address. At run time, some sort of overlay manager will
|
||
+copy the overlaid sections in and out of the runtime memory address as
|
||
+required, perhaps by simply manipulating addressing bits. This approach
|
||
+can be useful, for example, when a certain region of memory is faster
|
||
+than another.
|
||
+
|
||
+Overlays are described using the @code{OVERLAY} command. The
|
||
+@code{OVERLAY} command is used within a @code{SECTIONS} command, like an
|
||
+output section description. The full syntax of the @code{OVERLAY}
|
||
+command is as follows:
|
||
+@smallexample
|
||
+@group
|
||
+OVERLAY [@var{start}] : [NOCROSSREFS] [AT ( @var{ldaddr} )]
|
||
+ @{
|
||
+ @var{secname1}
|
||
+ @{
|
||
+ @var{output-section-command}
|
||
+ @var{output-section-command}
|
||
+ @dots{}
|
||
+ @} [:@var{phdr}@dots{}] [=@var{fill}]
|
||
+ @var{secname2}
|
||
+ @{
|
||
+ @var{output-section-command}
|
||
+ @var{output-section-command}
|
||
+ @dots{}
|
||
+ @} [:@var{phdr}@dots{}] [=@var{fill}]
|
||
+ @dots{}
|
||
+ @} [>@var{region}] [:@var{phdr}@dots{}] [=@var{fill}] [,]
|
||
+@end group
|
||
+@end smallexample
|
||
+
|
||
+Everything is optional except @code{OVERLAY} (a keyword), and each
|
||
+section must have a name (@var{secname1} and @var{secname2} above). The
|
||
+section definitions within the @code{OVERLAY} construct are identical to
|
||
+those within the general @code{SECTIONS} construct (@pxref{SECTIONS}),
|
||
+except that no addresses and no memory regions may be defined for
|
||
+sections within an @code{OVERLAY}.
|
||
+
|
||
+The comma at the end may be required if a @var{fill} is used and
|
||
+the next @var{sections-command} looks like a continuation of the expression.
|
||
+
|
||
+The sections are all defined with the same starting address. The load
|
||
+addresses of the sections are arranged such that they are consecutive in
|
||
+memory starting at the load address used for the @code{OVERLAY} as a
|
||
+whole (as with normal section definitions, the load address is optional,
|
||
+and defaults to the start address; the start address is also optional,
|
||
+and defaults to the current value of the location counter).
|
||
+
|
||
+If the @code{NOCROSSREFS} keyword is used, and there are any
|
||
+references among the sections, the linker will report an error. Since
|
||
+the sections all run at the same address, it normally does not make
|
||
+sense for one section to refer directly to another.
|
||
+@xref{Miscellaneous Commands, NOCROSSREFS}.
|
||
+
|
||
+For each section within the @code{OVERLAY}, the linker automatically
|
||
+provides two symbols. The symbol @code{__load_start_@var{secname}} is
|
||
+defined as the starting load address of the section. The symbol
|
||
+@code{__load_stop_@var{secname}} is defined as the final load address of
|
||
+the section. Any characters within @var{secname} which are not legal
|
||
+within C identifiers are removed. C (or assembler) code may use these
|
||
+symbols to move the overlaid sections around as necessary.
|
||
+
|
||
+At the end of the overlay, the value of the location counter is set to
|
||
+the start address of the overlay plus the size of the largest section.
|
||
+
|
||
+Here is an example. Remember that this would appear inside a
|
||
+@code{SECTIONS} construct.
|
||
+@smallexample
|
||
+@group
|
||
+ OVERLAY 0x1000 : AT (0x4000)
|
||
+ @{
|
||
+ .text0 @{ o1/*.o(.text) @}
|
||
+ .text1 @{ o2/*.o(.text) @}
|
||
+ @}
|
||
+@end group
|
||
+@end smallexample
|
||
+@noindent
|
||
+This will define both @samp{.text0} and @samp{.text1} to start at
|
||
+address 0x1000. @samp{.text0} will be loaded at address 0x4000, and
|
||
+@samp{.text1} will be loaded immediately after @samp{.text0}. The
|
||
+following symbols will be defined if referenced: @code{__load_start_text0},
|
||
+@code{__load_stop_text0}, @code{__load_start_text1},
|
||
+@code{__load_stop_text1}.
|
||
+
|
||
+C code to copy overlay @code{.text1} into the overlay area might look
|
||
+like the following.
|
||
+
|
||
+@smallexample
|
||
+@group
|
||
+ extern char __load_start_text1, __load_stop_text1;
|
||
+ memcpy ((char *) 0x1000, &__load_start_text1,
|
||
+ &__load_stop_text1 - &__load_start_text1);
|
||
+@end group
|
||
+@end smallexample
|
||
+
|
||
+Note that the @code{OVERLAY} command is just syntactic sugar, since
|
||
+everything it does can be done using the more basic commands. The above
|
||
+example could have been written identically as follows.
|
||
+
|
||
+@smallexample
|
||
+@group
|
||
+ .text0 0x1000 : AT (0x4000) @{ o1/*.o(.text) @}
|
||
+ PROVIDE (__load_start_text0 = LOADADDR (.text0));
|
||
+ PROVIDE (__load_stop_text0 = LOADADDR (.text0) + SIZEOF (.text0));
|
||
+ .text1 0x1000 : AT (0x4000 + SIZEOF (.text0)) @{ o2/*.o(.text) @}
|
||
+ PROVIDE (__load_start_text1 = LOADADDR (.text1));
|
||
+ PROVIDE (__load_stop_text1 = LOADADDR (.text1) + SIZEOF (.text1));
|
||
+ . = 0x1000 + MAX (SIZEOF (.text0), SIZEOF (.text1));
|
||
+@end group
|
||
+@end smallexample
|
||
+
|
||
+@node MEMORY
|
||
+@section MEMORY Command
|
||
+@kindex MEMORY
|
||
+@cindex memory regions
|
||
+@cindex regions of memory
|
||
+@cindex allocating memory
|
||
+@cindex discontinuous memory
|
||
+The linker's default configuration permits allocation of all available
|
||
+memory. You can override this by using the @code{MEMORY} command.
|
||
+
|
||
+The @code{MEMORY} command describes the location and size of blocks of
|
||
+memory in the target. You can use it to describe which memory regions
|
||
+may be used by the linker, and which memory regions it must avoid. You
|
||
+can then assign sections to particular memory regions. The linker will
|
||
+set section addresses based on the memory regions, and will warn about
|
||
+regions that become too full. The linker will not shuffle sections
|
||
+around to fit into the available regions.
|
||
+
|
||
+A linker script may contain many uses of the @code{MEMORY} command,
|
||
+however, all memory blocks defined are treated as if they were
|
||
+specified inside a single @code{MEMORY} command. The syntax for
|
||
+@code{MEMORY} is:
|
||
+@smallexample
|
||
+@group
|
||
+MEMORY
|
||
+ @{
|
||
+ @var{name} [(@var{attr})] : ORIGIN = @var{origin}, LENGTH = @var{len}
|
||
+ @dots{}
|
||
+ @}
|
||
+@end group
|
||
+@end smallexample
|
||
+
|
||
+The @var{name} is a name used in the linker script to refer to the
|
||
+region. The region name has no meaning outside of the linker script.
|
||
+Region names are stored in a separate name space, and will not conflict
|
||
+with symbol names, file names, or section names. Each memory region
|
||
+must have a distinct name within the @code{MEMORY} command. However you can
|
||
+add later alias names to existing memory regions with the @ref{REGION_ALIAS}
|
||
+command.
|
||
+
|
||
+@cindex memory region attributes
|
||
+The @var{attr} string is an optional list of attributes that specify
|
||
+whether to use a particular memory region for an input section which is
|
||
+not explicitly mapped in the linker script. As described in
|
||
+@ref{SECTIONS}, if you do not specify an output section for some input
|
||
+section, the linker will create an output section with the same name as
|
||
+the input section. If you define region attributes, the linker will use
|
||
+them to select the memory region for the output section that it creates.
|
||
+
|
||
+The @var{attr} string must consist only of the following characters:
|
||
+@table @samp
|
||
+@item R
|
||
+Read-only section
|
||
+@item W
|
||
+Read/write section
|
||
+@item X
|
||
+Executable section
|
||
+@item A
|
||
+Allocatable section
|
||
+@item I
|
||
+Initialized section
|
||
+@item L
|
||
+Same as @samp{I}
|
||
+@item !
|
||
+Invert the sense of any of the attributes that follow
|
||
+@end table
|
||
+
|
||
+If an unmapped section matches any of the listed attributes other than
|
||
+@samp{!}, it will be placed in the memory region. The @samp{!}
|
||
+attribute reverses the test for the characters that follow, so that an
|
||
+unmapped section will be placed in the memory region only if it does
|
||
+not match any of the attributes listed afterwards. Thus an attribute
|
||
+string of @samp{RW!X} will match any unmapped section that has either
|
||
+or both of the @samp{R} and @samp{W} attributes, but only as long as
|
||
+the section does not also have the @samp{X} attribute.
|
||
+
|
||
+@kindex ORIGIN =
|
||
+@kindex o =
|
||
+@kindex org =
|
||
+The @var{origin} is an numerical expression for the start address of
|
||
+the memory region. The expression must evaluate to a constant and it
|
||
+cannot involve any symbols. The keyword @code{ORIGIN} may be
|
||
+abbreviated to @code{org} or @code{o} (but not, for example,
|
||
+@code{ORG}).
|
||
+
|
||
+@kindex LENGTH =
|
||
+@kindex len =
|
||
+@kindex l =
|
||
+The @var{len} is an expression for the size in bytes of the memory
|
||
+region. As with the @var{origin} expression, the expression must
|
||
+be numerical only and must evaluate to a constant. The keyword
|
||
+@code{LENGTH} may be abbreviated to @code{len} or @code{l}.
|
||
+
|
||
+In the following example, we specify that there are two memory regions
|
||
+available for allocation: one starting at @samp{0} for 256 kilobytes,
|
||
+and the other starting at @samp{0x40000000} for four megabytes. The
|
||
+linker will place into the @samp{rom} memory region every section which
|
||
+is not explicitly mapped into a memory region, and is either read-only
|
||
+or executable. The linker will place other sections which are not
|
||
+explicitly mapped into a memory region into the @samp{ram} memory
|
||
+region.
|
||
+
|
||
+@smallexample
|
||
+@group
|
||
+MEMORY
|
||
+ @{
|
||
+ rom (rx) : ORIGIN = 0, LENGTH = 256K
|
||
+ ram (!rx) : org = 0x40000000, l = 4M
|
||
+ @}
|
||
+@end group
|
||
+@end smallexample
|
||
+
|
||
+Once you define a memory region, you can direct the linker to place
|
||
+specific output sections into that memory region by using the
|
||
+@samp{>@var{region}} output section attribute. For example, if you have
|
||
+a memory region named @samp{mem}, you would use @samp{>mem} in the
|
||
+output section definition. @xref{Output Section Region}. If no address
|
||
+was specified for the output section, the linker will set the address to
|
||
+the next available address within the memory region. If the combined
|
||
+output sections directed to a memory region are too large for the
|
||
+region, the linker will issue an error message.
|
||
+
|
||
+It is possible to access the origin and length of a memory in an
|
||
+expression via the @code{ORIGIN(@var{memory})} and
|
||
+@code{LENGTH(@var{memory})} functions:
|
||
+
|
||
+@smallexample
|
||
+@group
|
||
+ _fstack = ORIGIN(ram) + LENGTH(ram) - 4;
|
||
+@end group
|
||
+@end smallexample
|
||
+
|
||
+@node PHDRS
|
||
+@section PHDRS Command
|
||
+@kindex PHDRS
|
||
+@cindex program headers
|
||
+@cindex ELF program headers
|
||
+@cindex program segments
|
||
+@cindex segments, ELF
|
||
+The ELF object file format uses @dfn{program headers}, also knows as
|
||
+@dfn{segments}. The program headers describe how the program should be
|
||
+loaded into memory. You can print them out by using the @code{objdump}
|
||
+program with the @samp{-p} option.
|
||
+
|
||
+When you run an ELF program on a native ELF system, the system loader
|
||
+reads the program headers in order to figure out how to load the
|
||
+program. This will only work if the program headers are set correctly.
|
||
+This manual does not describe the details of how the system loader
|
||
+interprets program headers; for more information, see the ELF ABI.
|
||
+
|
||
+The linker will create reasonable program headers by default. However,
|
||
+in some cases, you may need to specify the program headers more
|
||
+precisely. You may use the @code{PHDRS} command for this purpose. When
|
||
+the linker sees the @code{PHDRS} command in the linker script, it will
|
||
+not create any program headers other than the ones specified.
|
||
+
|
||
+The linker only pays attention to the @code{PHDRS} command when
|
||
+generating an ELF output file. In other cases, the linker will simply
|
||
+ignore @code{PHDRS}.
|
||
+
|
||
+This is the syntax of the @code{PHDRS} command. The words @code{PHDRS},
|
||
+@code{FILEHDR}, @code{AT}, and @code{FLAGS} are keywords.
|
||
+
|
||
+@smallexample
|
||
+@group
|
||
+PHDRS
|
||
+@{
|
||
+ @var{name} @var{type} [ FILEHDR ] [ PHDRS ] [ AT ( @var{address} ) ]
|
||
+ [ FLAGS ( @var{flags} ) ] ;
|
||
+@}
|
||
+@end group
|
||
+@end smallexample
|
||
+
|
||
+The @var{name} is used only for reference in the @code{SECTIONS} command
|
||
+of the linker script. It is not put into the output file. Program
|
||
+header names are stored in a separate name space, and will not conflict
|
||
+with symbol names, file names, or section names. Each program header
|
||
+must have a distinct name. The headers are processed in order and it
|
||
+is usual for them to map to sections in ascending load address order.
|
||
+
|
||
+Certain program header types describe segments of memory which the
|
||
+system loader will load from the file. In the linker script, you
|
||
+specify the contents of these segments by placing allocatable output
|
||
+sections in the segments. You use the @samp{:@var{phdr}} output section
|
||
+attribute to place a section in a particular segment. @xref{Output
|
||
+Section Phdr}.
|
||
+
|
||
+It is normal to put certain sections in more than one segment. This
|
||
+merely implies that one segment of memory contains another. You may
|
||
+repeat @samp{:@var{phdr}}, using it once for each segment which should
|
||
+contain the section.
|
||
+
|
||
+If you place a section in one or more segments using @samp{:@var{phdr}},
|
||
+then the linker will place all subsequent allocatable sections which do
|
||
+not specify @samp{:@var{phdr}} in the same segments. This is for
|
||
+convenience, since generally a whole set of contiguous sections will be
|
||
+placed in a single segment. You can use @code{:NONE} to override the
|
||
+default segment and tell the linker to not put the section in any
|
||
+segment at all.
|
||
+
|
||
+@kindex FILEHDR
|
||
+@kindex PHDRS
|
||
+You may use the @code{FILEHDR} and @code{PHDRS} keywords after
|
||
+the program header type to further describe the contents of the segment.
|
||
+The @code{FILEHDR} keyword means that the segment should include the ELF
|
||
+file header. The @code{PHDRS} keyword means that the segment should
|
||
+include the ELF program headers themselves. If applied to a loadable
|
||
+segment (@code{PT_LOAD}), all prior loadable segments must have one of
|
||
+these keywords.
|
||
+
|
||
+The @var{type} may be one of the following. The numbers indicate the
|
||
+value of the keyword.
|
||
+
|
||
+@table @asis
|
||
+@item @code{PT_NULL} (0)
|
||
+Indicates an unused program header.
|
||
+
|
||
+@item @code{PT_LOAD} (1)
|
||
+Indicates that this program header describes a segment to be loaded from
|
||
+the file.
|
||
+
|
||
+@item @code{PT_DYNAMIC} (2)
|
||
+Indicates a segment where dynamic linking information can be found.
|
||
+
|
||
+@item @code{PT_INTERP} (3)
|
||
+Indicates a segment where the name of the program interpreter may be
|
||
+found.
|
||
+
|
||
+@item @code{PT_NOTE} (4)
|
||
+Indicates a segment holding note information.
|
||
+
|
||
+@item @code{PT_SHLIB} (5)
|
||
+A reserved program header type, defined but not specified by the ELF
|
||
+ABI.
|
||
+
|
||
+@item @code{PT_PHDR} (6)
|
||
+Indicates a segment where the program headers may be found.
|
||
+
|
||
+@item @code{PT_TLS} (7)
|
||
+Indicates a segment containing thread local storage.
|
||
+
|
||
+@item @var{expression}
|
||
+An expression giving the numeric type of the program header. This may
|
||
+be used for types not defined above.
|
||
+@end table
|
||
+
|
||
+You can specify that a segment should be loaded at a particular address
|
||
+in memory by using an @code{AT} expression. This is identical to the
|
||
+@code{AT} command used as an output section attribute (@pxref{Output
|
||
+Section LMA}). The @code{AT} command for a program header overrides the
|
||
+output section attribute.
|
||
+
|
||
+The linker will normally set the segment flags based on the sections
|
||
+which comprise the segment. You may use the @code{FLAGS} keyword to
|
||
+explicitly specify the segment flags. The value of @var{flags} must be
|
||
+an integer. It is used to set the @code{p_flags} field of the program
|
||
+header.
|
||
+
|
||
+Here is an example of @code{PHDRS}. This shows a typical set of program
|
||
+headers used on a native ELF system.
|
||
+
|
||
+@example
|
||
+@group
|
||
+PHDRS
|
||
+@{
|
||
+ headers PT_PHDR PHDRS ;
|
||
+ interp PT_INTERP ;
|
||
+ text PT_LOAD FILEHDR PHDRS ;
|
||
+ data PT_LOAD ;
|
||
+ dynamic PT_DYNAMIC ;
|
||
+@}
|
||
+
|
||
+SECTIONS
|
||
+@{
|
||
+ . = SIZEOF_HEADERS;
|
||
+ .interp : @{ *(.interp) @} :text :interp
|
||
+ .text : @{ *(.text) @} :text
|
||
+ .rodata : @{ *(.rodata) @} /* defaults to :text */
|
||
+ @dots{}
|
||
+ . = . + 0x1000; /* move to a new page in memory */
|
||
+ .data : @{ *(.data) @} :data
|
||
+ .dynamic : @{ *(.dynamic) @} :data :dynamic
|
||
+ @dots{}
|
||
+@}
|
||
+@end group
|
||
+@end example
|
||
+
|
||
+@node VERSION
|
||
+@section VERSION Command
|
||
+@kindex VERSION @{script text@}
|
||
+@cindex symbol versions
|
||
+@cindex version script
|
||
+@cindex versions of symbols
|
||
+The linker supports symbol versions when using ELF. Symbol versions are
|
||
+only useful when using shared libraries. The dynamic linker can use
|
||
+symbol versions to select a specific version of a function when it runs
|
||
+a program that may have been linked against an earlier version of the
|
||
+shared library.
|
||
+
|
||
+You can include a version script directly in the main linker script, or
|
||
+you can supply the version script as an implicit linker script. You can
|
||
+also use the @samp{--version-script} linker option.
|
||
+
|
||
+The syntax of the @code{VERSION} command is simply
|
||
+@smallexample
|
||
+VERSION @{ version-script-commands @}
|
||
+@end smallexample
|
||
+
|
||
+The format of the version script commands is identical to that used by
|
||
+Sun's linker in Solaris 2.5. The version script defines a tree of
|
||
+version nodes. You specify the node names and interdependencies in the
|
||
+version script. You can specify which symbols are bound to which
|
||
+version nodes, and you can reduce a specified set of symbols to local
|
||
+scope so that they are not globally visible outside of the shared
|
||
+library.
|
||
+
|
||
+The easiest way to demonstrate the version script language is with a few
|
||
+examples.
|
||
+
|
||
+@smallexample
|
||
+VERS_1.1 @{
|
||
+ global:
|
||
+ foo1;
|
||
+ local:
|
||
+ old*;
|
||
+ original*;
|
||
+ new*;
|
||
+@};
|
||
+
|
||
+VERS_1.2 @{
|
||
+ foo2;
|
||
+@} VERS_1.1;
|
||
+
|
||
+VERS_2.0 @{
|
||
+ bar1; bar2;
|
||
+ extern "C++" @{
|
||
+ ns::*;
|
||
+ "f(int, double)";
|
||
+ @};
|
||
+@} VERS_1.2;
|
||
+@end smallexample
|
||
+
|
||
+This example version script defines three version nodes. The first
|
||
+version node defined is @samp{VERS_1.1}; it has no other dependencies.
|
||
+The script binds the symbol @samp{foo1} to @samp{VERS_1.1}. It reduces
|
||
+a number of symbols to local scope so that they are not visible outside
|
||
+of the shared library; this is done using wildcard patterns, so that any
|
||
+symbol whose name begins with @samp{old}, @samp{original}, or @samp{new}
|
||
+is matched. The wildcard patterns available are the same as those used
|
||
+in the shell when matching filenames (also known as ``globbing'').
|
||
+However, if you specify the symbol name inside double quotes, then the
|
||
+name is treated as literal, rather than as a glob pattern.
|
||
+
|
||
+Next, the version script defines node @samp{VERS_1.2}. This node
|
||
+depends upon @samp{VERS_1.1}. The script binds the symbol @samp{foo2}
|
||
+to the version node @samp{VERS_1.2}.
|
||
+
|
||
+Finally, the version script defines node @samp{VERS_2.0}. This node
|
||
+depends upon @samp{VERS_1.2}. The scripts binds the symbols @samp{bar1}
|
||
+and @samp{bar2} are bound to the version node @samp{VERS_2.0}.
|
||
+
|
||
+When the linker finds a symbol defined in a library which is not
|
||
+specifically bound to a version node, it will effectively bind it to an
|
||
+unspecified base version of the library. You can bind all otherwise
|
||
+unspecified symbols to a given version node by using @samp{global: *;}
|
||
+somewhere in the version script. Note that it's slightly crazy to use
|
||
+wildcards in a global spec except on the last version node. Global
|
||
+wildcards elsewhere run the risk of accidentally adding symbols to the
|
||
+set exported for an old version. That's wrong since older versions
|
||
+ought to have a fixed set of symbols.
|
||
+
|
||
+The names of the version nodes have no specific meaning other than what
|
||
+they might suggest to the person reading them. The @samp{2.0} version
|
||
+could just as well have appeared in between @samp{1.1} and @samp{1.2}.
|
||
+However, this would be a confusing way to write a version script.
|
||
+
|
||
+Node name can be omitted, provided it is the only version node
|
||
+in the version script. Such version script doesn't assign any versions to
|
||
+symbols, only selects which symbols will be globally visible out and which
|
||
+won't.
|
||
+
|
||
+@smallexample
|
||
+@{ global: foo; bar; local: *; @};
|
||
+@end smallexample
|
||
+
|
||
+When you link an application against a shared library that has versioned
|
||
+symbols, the application itself knows which version of each symbol it
|
||
+requires, and it also knows which version nodes it needs from each
|
||
+shared library it is linked against. Thus at runtime, the dynamic
|
||
+loader can make a quick check to make sure that the libraries you have
|
||
+linked against do in fact supply all of the version nodes that the
|
||
+application will need to resolve all of the dynamic symbols. In this
|
||
+way it is possible for the dynamic linker to know with certainty that
|
||
+all external symbols that it needs will be resolvable without having to
|
||
+search for each symbol reference.
|
||
+
|
||
+The symbol versioning is in effect a much more sophisticated way of
|
||
+doing minor version checking that SunOS does. The fundamental problem
|
||
+that is being addressed here is that typically references to external
|
||
+functions are bound on an as-needed basis, and are not all bound when
|
||
+the application starts up. If a shared library is out of date, a
|
||
+required interface may be missing; when the application tries to use
|
||
+that interface, it may suddenly and unexpectedly fail. With symbol
|
||
+versioning, the user will get a warning when they start their program if
|
||
+the libraries being used with the application are too old.
|
||
+
|
||
+There are several GNU extensions to Sun's versioning approach. The
|
||
+first of these is the ability to bind a symbol to a version node in the
|
||
+source file where the symbol is defined instead of in the versioning
|
||
+script. This was done mainly to reduce the burden on the library
|
||
+maintainer. You can do this by putting something like:
|
||
+@smallexample
|
||
+__asm__(".symver original_foo,foo@@VERS_1.1");
|
||
+@end smallexample
|
||
+@noindent
|
||
+in the C source file. This renames the function @samp{original_foo} to
|
||
+be an alias for @samp{foo} bound to the version node @samp{VERS_1.1}.
|
||
+The @samp{local:} directive can be used to prevent the symbol
|
||
+@samp{original_foo} from being exported. A @samp{.symver} directive
|
||
+takes precedence over a version script.
|
||
+
|
||
+The second GNU extension is to allow multiple versions of the same
|
||
+function to appear in a given shared library. In this way you can make
|
||
+an incompatible change to an interface without increasing the major
|
||
+version number of the shared library, while still allowing applications
|
||
+linked against the old interface to continue to function.
|
||
+
|
||
+To do this, you must use multiple @samp{.symver} directives in the
|
||
+source file. Here is an example:
|
||
+
|
||
+@smallexample
|
||
+__asm__(".symver original_foo,foo@@");
|
||
+__asm__(".symver old_foo,foo@@VERS_1.1");
|
||
+__asm__(".symver old_foo1,foo@@VERS_1.2");
|
||
+__asm__(".symver new_foo,foo@@@@VERS_2.0");
|
||
+@end smallexample
|
||
+
|
||
+In this example, @samp{foo@@} represents the symbol @samp{foo} bound to the
|
||
+unspecified base version of the symbol. The source file that contains this
|
||
+example would define 4 C functions: @samp{original_foo}, @samp{old_foo},
|
||
+@samp{old_foo1}, and @samp{new_foo}.
|
||
+
|
||
+When you have multiple definitions of a given symbol, there needs to be
|
||
+some way to specify a default version to which external references to
|
||
+this symbol will be bound. You can do this with the
|
||
+@samp{foo@@@@VERS_2.0} type of @samp{.symver} directive. You can only
|
||
+declare one version of a symbol as the default in this manner; otherwise
|
||
+you would effectively have multiple definitions of the same symbol.
|
||
+
|
||
+If you wish to bind a reference to a specific version of the symbol
|
||
+within the shared library, you can use the aliases of convenience
|
||
+(i.e., @samp{old_foo}), or you can use the @samp{.symver} directive to
|
||
+specifically bind to an external version of the function in question.
|
||
+
|
||
+You can also specify the language in the version script:
|
||
+
|
||
+@smallexample
|
||
+VERSION extern "lang" @{ version-script-commands @}
|
||
+@end smallexample
|
||
+
|
||
+The supported @samp{lang}s are @samp{C}, @samp{C++}, and @samp{Java}.
|
||
+The linker will iterate over the list of symbols at the link time and
|
||
+demangle them according to @samp{lang} before matching them to the
|
||
+patterns specified in @samp{version-script-commands}. The default
|
||
+@samp{lang} is @samp{C}.
|
||
+
|
||
+Demangled names may contains spaces and other special characters. As
|
||
+described above, you can use a glob pattern to match demangled names,
|
||
+or you can use a double-quoted string to match the string exactly. In
|
||
+the latter case, be aware that minor differences (such as differing
|
||
+whitespace) between the version script and the demangler output will
|
||
+cause a mismatch. As the exact string generated by the demangler
|
||
+might change in the future, even if the mangled name does not, you
|
||
+should check that all of your version directives are behaving as you
|
||
+expect when you upgrade.
|
||
+
|
||
+@node Expressions
|
||
+@section Expressions in Linker Scripts
|
||
+@cindex expressions
|
||
+@cindex arithmetic
|
||
+The syntax for expressions in the linker script language is identical to
|
||
+that of C expressions, except that whitespace is required in some
|
||
+places to resolve syntactic ambiguities. All expressions are
|
||
+evaluated as integers. All expressions are evaluated in the same
|
||
+size, which is 32 bits if both the host and target are 32 bits, and is
|
||
+otherwise 64 bits.
|
||
+
|
||
+You can use and set symbol values in expressions.
|
||
+
|
||
+The linker defines several special purpose builtin functions for use in
|
||
+expressions.
|
||
+
|
||
+@menu
|
||
+* Constants:: Constants
|
||
+* Symbolic Constants:: Symbolic constants
|
||
+* Symbols:: Symbol Names
|
||
+* Orphan Sections:: Orphan Sections
|
||
+* Location Counter:: The Location Counter
|
||
+* Operators:: Operators
|
||
+* Evaluation:: Evaluation
|
||
+* Expression Section:: The Section of an Expression
|
||
+* Builtin Functions:: Builtin Functions
|
||
+@end menu
|
||
+
|
||
+@node Constants
|
||
+@subsection Constants
|
||
+@cindex integer notation
|
||
+@cindex constants in linker scripts
|
||
+All constants are integers.
|
||
+
|
||
+As in C, the linker considers an integer beginning with @samp{0} to be
|
||
+octal, and an integer beginning with @samp{0x} or @samp{0X} to be
|
||
+hexadecimal. Alternatively the linker accepts suffixes of @samp{h} or
|
||
+@samp{H} for hexadecimal, @samp{o} or @samp{O} for octal, @samp{b} or
|
||
+@samp{B} for binary and @samp{d} or @samp{D} for decimal. Any integer
|
||
+value without a prefix or a suffix is considered to be decimal.
|
||
+
|
||
+@cindex scaled integers
|
||
+@cindex K and M integer suffixes
|
||
+@cindex M and K integer suffixes
|
||
+@cindex suffixes for integers
|
||
+@cindex integer suffixes
|
||
+In addition, you can use the suffixes @code{K} and @code{M} to scale a
|
||
+constant by
|
||
+@c TEXI2ROFF-KILL
|
||
+@ifnottex
|
||
+@c END TEXI2ROFF-KILL
|
||
+@code{1024} or @code{1024*1024}
|
||
+@c TEXI2ROFF-KILL
|
||
+@end ifnottex
|
||
+@tex
|
||
+${\rm 1024}$ or ${\rm 1024}^2$
|
||
+@end tex
|
||
+@c END TEXI2ROFF-KILL
|
||
+respectively. For example, the following
|
||
+all refer to the same quantity:
|
||
+
|
||
+@smallexample
|
||
+_fourk_1 = 4K;
|
||
+_fourk_2 = 4096;
|
||
+_fourk_3 = 0x1000;
|
||
+_fourk_4 = 10000o;
|
||
+@end smallexample
|
||
+
|
||
+Note - the @code{K} and @code{M} suffixes cannot be used in
|
||
+conjunction with the base suffixes mentioned above.
|
||
+
|
||
+@node Symbolic Constants
|
||
+@subsection Symbolic Constants
|
||
+@cindex symbolic constants
|
||
+@kindex CONSTANT
|
||
+It is possible to refer to target-specific constants via the use of
|
||
+the @code{CONSTANT(@var{name})} operator, where @var{name} is one of:
|
||
+
|
||
+@table @code
|
||
+@item MAXPAGESIZE
|
||
+@kindex MAXPAGESIZE
|
||
+The target's maximum page size.
|
||
+
|
||
+@item COMMONPAGESIZE
|
||
+@kindex COMMONPAGESIZE
|
||
+The target's default page size.
|
||
+@end table
|
||
+
|
||
+So for example:
|
||
+
|
||
+@smallexample
|
||
+ .text ALIGN (CONSTANT (MAXPAGESIZE)) : @{ *(.text) @}
|
||
+@end smallexample
|
||
+
|
||
+will create a text section aligned to the largest page boundary
|
||
+supported by the target.
|
||
+
|
||
+@node Symbols
|
||
+@subsection Symbol Names
|
||
+@cindex symbol names
|
||
+@cindex names
|
||
+@cindex quoted symbol names
|
||
+@kindex "
|
||
+Unless quoted, symbol names start with a letter, underscore, or period
|
||
+and may include letters, digits, underscores, periods, and hyphens.
|
||
+Unquoted symbol names must not conflict with any keywords. You can
|
||
+specify a symbol which contains odd characters or has the same name as a
|
||
+keyword by surrounding the symbol name in double quotes:
|
||
+@smallexample
|
||
+"SECTION" = 9;
|
||
+"with a space" = "also with a space" + 10;
|
||
+@end smallexample
|
||
+
|
||
+Since symbols can contain many non-alphabetic characters, it is safest
|
||
+to delimit symbols with spaces. For example, @samp{A-B} is one symbol,
|
||
+whereas @samp{A - B} is an expression involving subtraction.
|
||
+
|
||
+@node Orphan Sections
|
||
+@subsection Orphan Sections
|
||
+@cindex orphan
|
||
+Orphan sections are sections present in the input files which
|
||
+are not explicitly placed into the output file by the linker
|
||
+script. The linker will still copy these sections into the
|
||
+output file by either finding, or creating a suitable output section
|
||
+in which to place the orphaned input section.
|
||
+
|
||
+If the name of an orphaned input section exactly matches the name of
|
||
+an existing output section, then the orphaned input section will be
|
||
+placed at the end of that output section.
|
||
+
|
||
+If there is no output section with a matching name then new output
|
||
+sections will be created. Each new output section will have the same
|
||
+name as the orphan section placed within it. If there are multiple
|
||
+orphan sections with the same name, these will all be combined into
|
||
+one new output section.
|
||
+
|
||
+If new output sections are created to hold orphaned input sections,
|
||
+then the linker must decide where to place these new output sections
|
||
+in relation to existing output sections. On most modern targets, the
|
||
+linker attempts to place orphan sections after sections of the same
|
||
+attribute, such as code vs data, loadable vs non-loadable, etc. If no
|
||
+sections with matching attributes are found, or your target lacks this
|
||
+support, the orphan section is placed at the end of the file.
|
||
+
|
||
+The command-line options @samp{--orphan-handling} and @samp{--unique}
|
||
+(@pxref{Options,,Command-line Options}) can be used to control which
|
||
+output sections an orphan is placed in.
|
||
+
|
||
+@node Location Counter
|
||
+@subsection The Location Counter
|
||
+@kindex .
|
||
+@cindex dot
|
||
+@cindex location counter
|
||
+@cindex current output location
|
||
+The special linker variable @dfn{dot} @samp{.} always contains the
|
||
+current output location counter. Since the @code{.} always refers to a
|
||
+location in an output section, it may only appear in an expression
|
||
+within a @code{SECTIONS} command. The @code{.} symbol may appear
|
||
+anywhere that an ordinary symbol is allowed in an expression.
|
||
+
|
||
+@cindex holes
|
||
+Assigning a value to @code{.} will cause the location counter to be
|
||
+moved. This may be used to create holes in the output section. The
|
||
+location counter may not be moved backwards inside an output section,
|
||
+and may not be moved backwards outside of an output section if so
|
||
+doing creates areas with overlapping LMAs.
|
||
+
|
||
+@smallexample
|
||
+SECTIONS
|
||
+@{
|
||
+ output :
|
||
+ @{
|
||
+ file1(.text)
|
||
+ . = . + 1000;
|
||
+ file2(.text)
|
||
+ . += 1000;
|
||
+ file3(.text)
|
||
+ @} = 0x12345678;
|
||
+@}
|
||
+@end smallexample
|
||
+@noindent
|
||
+In the previous example, the @samp{.text} section from @file{file1} is
|
||
+located at the beginning of the output section @samp{output}. It is
|
||
+followed by a 1000 byte gap. Then the @samp{.text} section from
|
||
+@file{file2} appears, also with a 1000 byte gap following before the
|
||
+@samp{.text} section from @file{file3}. The notation @samp{= 0x12345678}
|
||
+specifies what data to write in the gaps (@pxref{Output Section Fill}).
|
||
+
|
||
+@cindex dot inside sections
|
||
+Note: @code{.} actually refers to the byte offset from the start of the
|
||
+current containing object. Normally this is the @code{SECTIONS}
|
||
+statement, whose start address is 0, hence @code{.} can be used as an
|
||
+absolute address. If @code{.} is used inside a section description
|
||
+however, it refers to the byte offset from the start of that section,
|
||
+not an absolute address. Thus in a script like this:
|
||
+
|
||
+@smallexample
|
||
+SECTIONS
|
||
+@{
|
||
+ . = 0x100
|
||
+ .text: @{
|
||
+ *(.text)
|
||
+ . = 0x200
|
||
+ @}
|
||
+ . = 0x500
|
||
+ .data: @{
|
||
+ *(.data)
|
||
+ . += 0x600
|
||
+ @}
|
||
+@}
|
||
+@end smallexample
|
||
+
|
||
+The @samp{.text} section will be assigned a starting address of 0x100
|
||
+and a size of exactly 0x200 bytes, even if there is not enough data in
|
||
+the @samp{.text} input sections to fill this area. (If there is too
|
||
+much data, an error will be produced because this would be an attempt to
|
||
+move @code{.} backwards). The @samp{.data} section will start at 0x500
|
||
+and it will have an extra 0x600 bytes worth of space after the end of
|
||
+the values from the @samp{.data} input sections and before the end of
|
||
+the @samp{.data} output section itself.
|
||
+
|
||
+@cindex dot outside sections
|
||
+Setting symbols to the value of the location counter outside of an
|
||
+output section statement can result in unexpected values if the linker
|
||
+needs to place orphan sections. For example, given the following:
|
||
+
|
||
+@smallexample
|
||
+SECTIONS
|
||
+@{
|
||
+ start_of_text = . ;
|
||
+ .text: @{ *(.text) @}
|
||
+ end_of_text = . ;
|
||
+
|
||
+ start_of_data = . ;
|
||
+ .data: @{ *(.data) @}
|
||
+ end_of_data = . ;
|
||
+@}
|
||
+@end smallexample
|
||
+
|
||
+If the linker needs to place some input section, e.g. @code{.rodata},
|
||
+not mentioned in the script, it might choose to place that section
|
||
+between @code{.text} and @code{.data}. You might think the linker
|
||
+should place @code{.rodata} on the blank line in the above script, but
|
||
+blank lines are of no particular significance to the linker. As well,
|
||
+the linker doesn't associate the above symbol names with their
|
||
+sections. Instead, it assumes that all assignments or other
|
||
+statements belong to the previous output section, except for the
|
||
+special case of an assignment to @code{.}. I.e., the linker will
|
||
+place the orphan @code{.rodata} section as if the script was written
|
||
+as follows:
|
||
+
|
||
+@smallexample
|
||
+SECTIONS
|
||
+@{
|
||
+ start_of_text = . ;
|
||
+ .text: @{ *(.text) @}
|
||
+ end_of_text = . ;
|
||
+
|
||
+ start_of_data = . ;
|
||
+ .rodata: @{ *(.rodata) @}
|
||
+ .data: @{ *(.data) @}
|
||
+ end_of_data = . ;
|
||
+@}
|
||
+@end smallexample
|
||
+
|
||
+This may or may not be the script author's intention for the value of
|
||
+@code{start_of_data}. One way to influence the orphan section
|
||
+placement is to assign the location counter to itself, as the linker
|
||
+assumes that an assignment to @code{.} is setting the start address of
|
||
+a following output section and thus should be grouped with that
|
||
+section. So you could write:
|
||
+
|
||
+@smallexample
|
||
+SECTIONS
|
||
+@{
|
||
+ start_of_text = . ;
|
||
+ .text: @{ *(.text) @}
|
||
+ end_of_text = . ;
|
||
+
|
||
+ . = . ;
|
||
+ start_of_data = . ;
|
||
+ .data: @{ *(.data) @}
|
||
+ end_of_data = . ;
|
||
+@}
|
||
+@end smallexample
|
||
+
|
||
+Now, the orphan @code{.rodata} section will be placed between
|
||
+@code{end_of_text} and @code{start_of_data}.
|
||
+
|
||
+@need 2000
|
||
+@node Operators
|
||
+@subsection Operators
|
||
+@cindex operators for arithmetic
|
||
+@cindex arithmetic operators
|
||
+@cindex precedence in expressions
|
||
+The linker recognizes the standard C set of arithmetic operators, with
|
||
+the standard bindings and precedence levels:
|
||
+@c TEXI2ROFF-KILL
|
||
+@ifnottex
|
||
+@c END TEXI2ROFF-KILL
|
||
+@smallexample
|
||
+precedence associativity Operators Notes
|
||
+(highest)
|
||
+1 left ! - ~ (1)
|
||
+2 left * / %
|
||
+3 left + -
|
||
+4 left >> <<
|
||
+5 left == != > < <= >=
|
||
+6 left &
|
||
+7 left |
|
||
+8 left &&
|
||
+9 left ||
|
||
+10 right ? :
|
||
+11 right &= += -= *= /= (2)
|
||
+(lowest)
|
||
+@end smallexample
|
||
+Notes:
|
||
+(1) Prefix operators
|
||
+(2) @xref{Assignments}.
|
||
+@c TEXI2ROFF-KILL
|
||
+@end ifnottex
|
||
+@tex
|
||
+\vskip \baselineskip
|
||
+%"lispnarrowing" is the extra indent used generally for smallexample
|
||
+\hskip\lispnarrowing\vbox{\offinterlineskip
|
||
+\hrule
|
||
+\halign
|
||
+{\vrule#&\strut\hfil\ #\ \hfil&\vrule#&\strut\hfil\ #\ \hfil&\vrule#&\strut\hfil\ {\tt #}\ \hfil&\vrule#\cr
|
||
+height2pt&\omit&&\omit&&\omit&\cr
|
||
+&Precedence&& Associativity &&{\rm Operators}&\cr
|
||
+height2pt&\omit&&\omit&&\omit&\cr
|
||
+\noalign{\hrule}
|
||
+height2pt&\omit&&\omit&&\omit&\cr
|
||
+&highest&&&&&\cr
|
||
+% '176 is tilde, '~' in tt font
|
||
+&1&&left&&\qquad- \char'176\ !\qquad\dag&\cr
|
||
+&2&&left&&* / \%&\cr
|
||
+&3&&left&&+ -&\cr
|
||
+&4&&left&&>> <<&\cr
|
||
+&5&&left&&== != > < <= >=&\cr
|
||
+&6&&left&&\&&\cr
|
||
+&7&&left&&|&\cr
|
||
+&8&&left&&{\&\&}&\cr
|
||
+&9&&left&&||&\cr
|
||
+&10&&right&&? :&\cr
|
||
+&11&&right&&\qquad\&= += -= *= /=\qquad\ddag&\cr
|
||
+&lowest&&&&&\cr
|
||
+height2pt&\omit&&\omit&&\omit&\cr}
|
||
+\hrule}
|
||
+@end tex
|
||
+@iftex
|
||
+{
|
||
+@obeylines@parskip=0pt@parindent=0pt
|
||
+@dag@quad Prefix operators.
|
||
+@ddag@quad @xref{Assignments}.
|
||
+}
|
||
+@end iftex
|
||
+@c END TEXI2ROFF-KILL
|
||
+
|
||
+@node Evaluation
|
||
+@subsection Evaluation
|
||
+@cindex lazy evaluation
|
||
+@cindex expression evaluation order
|
||
+The linker evaluates expressions lazily. It only computes the value of
|
||
+an expression when absolutely necessary.
|
||
+
|
||
+The linker needs some information, such as the value of the start
|
||
+address of the first section, and the origins and lengths of memory
|
||
+regions, in order to do any linking at all. These values are computed
|
||
+as soon as possible when the linker reads in the linker script.
|
||
+
|
||
+However, other values (such as symbol values) are not known or needed
|
||
+until after storage allocation. Such values are evaluated later, when
|
||
+other information (such as the sizes of output sections) is available
|
||
+for use in the symbol assignment expression.
|
||
+
|
||
+The sizes of sections cannot be known until after allocation, so
|
||
+assignments dependent upon these are not performed until after
|
||
+allocation.
|
||
+
|
||
+Some expressions, such as those depending upon the location counter
|
||
+@samp{.}, must be evaluated during section allocation.
|
||
+
|
||
+If the result of an expression is required, but the value is not
|
||
+available, then an error results. For example, a script like the
|
||
+following
|
||
+@smallexample
|
||
+@group
|
||
+SECTIONS
|
||
+ @{
|
||
+ .text 9+this_isnt_constant :
|
||
+ @{ *(.text) @}
|
||
+ @}
|
||
+@end group
|
||
+@end smallexample
|
||
+@noindent
|
||
+will cause the error message @samp{non constant expression for initial
|
||
+address}.
|
||
+
|
||
+@node Expression Section
|
||
+@subsection The Section of an Expression
|
||
+@cindex expression sections
|
||
+@cindex absolute expressions
|
||
+@cindex relative expressions
|
||
+@cindex absolute and relocatable symbols
|
||
+@cindex relocatable and absolute symbols
|
||
+@cindex symbols, relocatable and absolute
|
||
+Addresses and symbols may be section relative, or absolute. A section
|
||
+relative symbol is relocatable. If you request relocatable output
|
||
+using the @samp{-r} option, a further link operation may change the
|
||
+value of a section relative symbol. On the other hand, an absolute
|
||
+symbol will retain the same value throughout any further link
|
||
+operations.
|
||
+
|
||
+Some terms in linker expressions are addresses. This is true of
|
||
+section relative symbols and for builtin functions that return an
|
||
+address, such as @code{ADDR}, @code{LOADADDR}, @code{ORIGIN} and
|
||
+@code{SEGMENT_START}. Other terms are simply numbers, or are builtin
|
||
+functions that return a non-address value, such as @code{LENGTH}.
|
||
+One complication is that unless you set @code{LD_FEATURE ("SANE_EXPR")}
|
||
+(@pxref{Miscellaneous Commands}), numbers and absolute symbols are treated
|
||
+differently depending on their location, for compatibility with older
|
||
+versions of @code{ld}. Expressions appearing outside an output
|
||
+section definition treat all numbers as absolute addresses.
|
||
+Expressions appearing inside an output section definition treat
|
||
+absolute symbols as numbers. If @code{LD_FEATURE ("SANE_EXPR")} is
|
||
+given, then absolute symbols and numbers are simply treated as numbers
|
||
+everywhere.
|
||
+
|
||
+In the following simple example,
|
||
+
|
||
+@smallexample
|
||
+@group
|
||
+SECTIONS
|
||
+ @{
|
||
+ . = 0x100;
|
||
+ __executable_start = 0x100;
|
||
+ .data :
|
||
+ @{
|
||
+ . = 0x10;
|
||
+ __data_start = 0x10;
|
||
+ *(.data)
|
||
+ @}
|
||
+ @dots{}
|
||
+ @}
|
||
+@end group
|
||
+@end smallexample
|
||
+
|
||
+both @code{.} and @code{__executable_start} are set to the absolute
|
||
+address 0x100 in the first two assignments, then both @code{.} and
|
||
+@code{__data_start} are set to 0x10 relative to the @code{.data}
|
||
+section in the second two assignments.
|
||
+
|
||
+For expressions involving numbers, relative addresses and absolute
|
||
+addresses, ld follows these rules to evaluate terms:
|
||
+
|
||
+@itemize @bullet
|
||
+@item
|
||
+Unary operations on an absolute address or number, and binary
|
||
+operations on two absolute addresses or two numbers, or between one
|
||
+absolute address and a number, apply the operator to the value(s).
|
||
+@item
|
||
+Unary operations on a relative address, and binary operations on two
|
||
+relative addresses in the same section or between one relative address
|
||
+and a number, apply the operator to the offset part of the address(es).
|
||
+@item
|
||
+Other binary operations, that is, between two relative addresses not
|
||
+in the same section, or between a relative address and an absolute
|
||
+address, first convert any non-absolute term to an absolute address
|
||
+before applying the operator.
|
||
+@end itemize
|
||
+
|
||
+The result section of each sub-expression is as follows:
|
||
+
|
||
+@itemize @bullet
|
||
+@item
|
||
+An operation involving only numbers results in a number.
|
||
+@item
|
||
+The result of comparisons, @samp{&&} and @samp{||} is also a number.
|
||
+@item
|
||
+The result of other binary arithmetic and logical operations on two
|
||
+relative addresses in the same section or two absolute addresses
|
||
+(after above conversions) is also a number when
|
||
+@code{LD_FEATURE ("SANE_EXPR")} or inside an output section definition
|
||
+but an absolute address otherwise.
|
||
+@item
|
||
+The result of other operations on relative addresses or one
|
||
+relative address and a number, is a relative address in the same
|
||
+section as the relative operand(s).
|
||
+@item
|
||
+The result of other operations on absolute addresses (after above
|
||
+conversions) is an absolute address.
|
||
+@end itemize
|
||
+
|
||
+You can use the builtin function @code{ABSOLUTE} to force an expression
|
||
+to be absolute when it would otherwise be relative. For example, to
|
||
+create an absolute symbol set to the address of the end of the output
|
||
+section @samp{.data}:
|
||
+@smallexample
|
||
+SECTIONS
|
||
+ @{
|
||
+ .data : @{ *(.data) _edata = ABSOLUTE(.); @}
|
||
+ @}
|
||
+@end smallexample
|
||
+@noindent
|
||
+If @samp{ABSOLUTE} were not used, @samp{_edata} would be relative to the
|
||
+@samp{.data} section.
|
||
+
|
||
+Using @code{LOADADDR} also forces an expression absolute, since this
|
||
+particular builtin function returns an absolute address.
|
||
+
|
||
+@node Builtin Functions
|
||
+@subsection Builtin Functions
|
||
+@cindex functions in expressions
|
||
+The linker script language includes a number of builtin functions for
|
||
+use in linker script expressions.
|
||
+
|
||
+@table @code
|
||
+@item ABSOLUTE(@var{exp})
|
||
+@kindex ABSOLUTE(@var{exp})
|
||
+@cindex expression, absolute
|
||
+Return the absolute (non-relocatable, as opposed to non-negative) value
|
||
+of the expression @var{exp}. Primarily useful to assign an absolute
|
||
+value to a symbol within a section definition, where symbol values are
|
||
+normally section relative. @xref{Expression Section}.
|
||
+
|
||
+@item ADDR(@var{section})
|
||
+@kindex ADDR(@var{section})
|
||
+@cindex section address in expression
|
||
+Return the address (VMA) of the named @var{section}. Your
|
||
+script must previously have defined the location of that section. In
|
||
+the following example, @code{start_of_output_1}, @code{symbol_1} and
|
||
+@code{symbol_2} are assigned equivalent values, except that
|
||
+@code{symbol_1} will be relative to the @code{.output1} section while
|
||
+the other two will be absolute:
|
||
+@smallexample
|
||
+@group
|
||
+SECTIONS @{ @dots{}
|
||
+ .output1 :
|
||
+ @{
|
||
+ start_of_output_1 = ABSOLUTE(.);
|
||
+ @dots{}
|
||
+ @}
|
||
+ .output :
|
||
+ @{
|
||
+ symbol_1 = ADDR(.output1);
|
||
+ symbol_2 = start_of_output_1;
|
||
+ @}
|
||
+@dots{} @}
|
||
+@end group
|
||
+@end smallexample
|
||
+
|
||
+@item ALIGN(@var{align})
|
||
+@itemx ALIGN(@var{exp},@var{align})
|
||
+@kindex ALIGN(@var{align})
|
||
+@kindex ALIGN(@var{exp},@var{align})
|
||
+@cindex round up location counter
|
||
+@cindex align location counter
|
||
+@cindex round up expression
|
||
+@cindex align expression
|
||
+Return the location counter (@code{.}) or arbitrary expression aligned
|
||
+to the next @var{align} boundary. The single operand @code{ALIGN}
|
||
+doesn't change the value of the location counter---it just does
|
||
+arithmetic on it. The two operand @code{ALIGN} allows an arbitrary
|
||
+expression to be aligned upwards (@code{ALIGN(@var{align})} is
|
||
+equivalent to @code{ALIGN(ABSOLUTE(.), @var{align})}).
|
||
+
|
||
+Here is an example which aligns the output @code{.data} section to the
|
||
+next @code{0x2000} byte boundary after the preceding section and sets a
|
||
+variable within the section to the next @code{0x8000} boundary after the
|
||
+input sections:
|
||
+@smallexample
|
||
+@group
|
||
+SECTIONS @{ @dots{}
|
||
+ .data ALIGN(0x2000): @{
|
||
+ *(.data)
|
||
+ variable = ALIGN(0x8000);
|
||
+ @}
|
||
+@dots{} @}
|
||
+@end group
|
||
+@end smallexample
|
||
+@noindent
|
||
+The first use of @code{ALIGN} in this example specifies the location of
|
||
+a section because it is used as the optional @var{address} attribute of
|
||
+a section definition (@pxref{Output Section Address}). The second use
|
||
+of @code{ALIGN} is used to defines the value of a symbol.
|
||
+
|
||
+The builtin function @code{NEXT} is closely related to @code{ALIGN}.
|
||
+
|
||
+@item ALIGNOF(@var{section})
|
||
+@kindex ALIGNOF(@var{section})
|
||
+@cindex section alignment
|
||
+Return the alignment in bytes of the named @var{section}, if that section has
|
||
+been allocated. If the section has not been allocated when this is
|
||
+evaluated, the linker will report an error. In the following example,
|
||
+the alignment of the @code{.output} section is stored as the first
|
||
+value in that section.
|
||
+@smallexample
|
||
+@group
|
||
+SECTIONS@{ @dots{}
|
||
+ .output @{
|
||
+ LONG (ALIGNOF (.output))
|
||
+ @dots{}
|
||
+ @}
|
||
+@dots{} @}
|
||
+@end group
|
||
+@end smallexample
|
||
+
|
||
+@item BLOCK(@var{exp})
|
||
+@kindex BLOCK(@var{exp})
|
||
+This is a synonym for @code{ALIGN}, for compatibility with older linker
|
||
+scripts. It is most often seen when setting the address of an output
|
||
+section.
|
||
+
|
||
+@item DATA_SEGMENT_ALIGN(@var{maxpagesize}, @var{commonpagesize})
|
||
+@kindex DATA_SEGMENT_ALIGN(@var{maxpagesize}, @var{commonpagesize})
|
||
+This is equivalent to either
|
||
+@smallexample
|
||
+(ALIGN(@var{maxpagesize}) + (. & (@var{maxpagesize} - 1)))
|
||
+@end smallexample
|
||
+or
|
||
+@smallexample
|
||
+(ALIGN(@var{maxpagesize})
|
||
+ + ((. + @var{commonpagesize} - 1) & (@var{maxpagesize} - @var{commonpagesize})))
|
||
+@end smallexample
|
||
+@noindent
|
||
+depending on whether the latter uses fewer @var{commonpagesize} sized pages
|
||
+for the data segment (area between the result of this expression and
|
||
+@code{DATA_SEGMENT_END}) than the former or not.
|
||
+If the latter form is used, it means @var{commonpagesize} bytes of runtime
|
||
+memory will be saved at the expense of up to @var{commonpagesize} wasted
|
||
+bytes in the on-disk file.
|
||
+
|
||
+This expression can only be used directly in @code{SECTIONS} commands, not in
|
||
+any output section descriptions and only once in the linker script.
|
||
+@var{commonpagesize} should be less or equal to @var{maxpagesize} and should
|
||
+be the system page size the object wants to be optimized for while still
|
||
+running on system page sizes up to @var{maxpagesize}. Note however
|
||
+that @samp{-z relro} protection will not be effective if the system
|
||
+page size is larger than @var{commonpagesize}.
|
||
+
|
||
+@noindent
|
||
+Example:
|
||
+@smallexample
|
||
+ . = DATA_SEGMENT_ALIGN(0x10000, 0x2000);
|
||
+@end smallexample
|
||
+
|
||
+@item DATA_SEGMENT_END(@var{exp})
|
||
+@kindex DATA_SEGMENT_END(@var{exp})
|
||
+This defines the end of data segment for @code{DATA_SEGMENT_ALIGN}
|
||
+evaluation purposes.
|
||
+
|
||
+@smallexample
|
||
+ . = DATA_SEGMENT_END(.);
|
||
+@end smallexample
|
||
+
|
||
+@item DATA_SEGMENT_RELRO_END(@var{offset}, @var{exp})
|
||
+@kindex DATA_SEGMENT_RELRO_END(@var{offset}, @var{exp})
|
||
+This defines the end of the @code{PT_GNU_RELRO} segment when
|
||
+@samp{-z relro} option is used.
|
||
+When @samp{-z relro} option is not present, @code{DATA_SEGMENT_RELRO_END}
|
||
+does nothing, otherwise @code{DATA_SEGMENT_ALIGN} is padded so that
|
||
+@var{exp} + @var{offset} is aligned to the @var{commonpagesize}
|
||
+argument given to @code{DATA_SEGMENT_ALIGN}. If present in the linker
|
||
+script, it must be placed between @code{DATA_SEGMENT_ALIGN} and
|
||
+@code{DATA_SEGMENT_END}. Evaluates to the second argument plus any
|
||
+padding needed at the end of the @code{PT_GNU_RELRO} segment due to
|
||
+section alignment.
|
||
+
|
||
+@smallexample
|
||
+ . = DATA_SEGMENT_RELRO_END(24, .);
|
||
+@end smallexample
|
||
+
|
||
+@item DEFINED(@var{symbol})
|
||
+@kindex DEFINED(@var{symbol})
|
||
+@cindex symbol defaults
|
||
+Return 1 if @var{symbol} is in the linker global symbol table and is
|
||
+defined before the statement using DEFINED in the script, otherwise
|
||
+return 0. You can use this function to provide
|
||
+default values for symbols. For example, the following script fragment
|
||
+shows how to set a global symbol @samp{begin} to the first location in
|
||
+the @samp{.text} section---but if a symbol called @samp{begin} already
|
||
+existed, its value is preserved:
|
||
+
|
||
+@smallexample
|
||
+@group
|
||
+SECTIONS @{ @dots{}
|
||
+ .text : @{
|
||
+ begin = DEFINED(begin) ? begin : . ;
|
||
+ @dots{}
|
||
+ @}
|
||
+ @dots{}
|
||
+@}
|
||
+@end group
|
||
+@end smallexample
|
||
+
|
||
+@item LENGTH(@var{memory})
|
||
+@kindex LENGTH(@var{memory})
|
||
+Return the length of the memory region named @var{memory}.
|
||
+
|
||
+@item LOADADDR(@var{section})
|
||
+@kindex LOADADDR(@var{section})
|
||
+@cindex section load address in expression
|
||
+Return the absolute LMA of the named @var{section}. (@pxref{Output
|
||
+Section LMA}).
|
||
+
|
||
+@item LOG2CEIL(@var{exp})
|
||
+@kindex LOG2CEIL(@var{exp})
|
||
+Return the binary logarithm of @var{exp} rounded towards infinity.
|
||
+@code{LOG2CEIL(0)} returns 0.
|
||
+
|
||
+@kindex MAX
|
||
+@item MAX(@var{exp1}, @var{exp2})
|
||
+Returns the maximum of @var{exp1} and @var{exp2}.
|
||
+
|
||
+@kindex MIN
|
||
+@item MIN(@var{exp1}, @var{exp2})
|
||
+Returns the minimum of @var{exp1} and @var{exp2}.
|
||
+
|
||
+@item NEXT(@var{exp})
|
||
+@kindex NEXT(@var{exp})
|
||
+@cindex unallocated address, next
|
||
+Return the next unallocated address that is a multiple of @var{exp}.
|
||
+This function is closely related to @code{ALIGN(@var{exp})}; unless you
|
||
+use the @code{MEMORY} command to define discontinuous memory for the
|
||
+output file, the two functions are equivalent.
|
||
+
|
||
+@item ORIGIN(@var{memory})
|
||
+@kindex ORIGIN(@var{memory})
|
||
+Return the origin of the memory region named @var{memory}.
|
||
+
|
||
+@item SEGMENT_START(@var{segment}, @var{default})
|
||
+@kindex SEGMENT_START(@var{segment}, @var{default})
|
||
+Return the base address of the named @var{segment}. If an explicit
|
||
+value has already been given for this segment (with a command-line
|
||
+@samp{-T} option) then that value will be returned otherwise the value
|
||
+will be @var{default}. At present, the @samp{-T} command-line option
|
||
+can only be used to set the base address for the ``text'', ``data'', and
|
||
+``bss'' sections, but you can use @code{SEGMENT_START} with any segment
|
||
+name.
|
||
+
|
||
+@item SIZEOF(@var{section})
|
||
+@kindex SIZEOF(@var{section})
|
||
+@cindex section size
|
||
+Return the size in bytes of the named @var{section}, if that section has
|
||
+been allocated. If the section has not been allocated when this is
|
||
+evaluated, the linker will report an error. In the following example,
|
||
+@code{symbol_1} and @code{symbol_2} are assigned identical values:
|
||
+@smallexample
|
||
+@group
|
||
+SECTIONS@{ @dots{}
|
||
+ .output @{
|
||
+ .start = . ;
|
||
+ @dots{}
|
||
+ .end = . ;
|
||
+ @}
|
||
+ symbol_1 = .end - .start ;
|
||
+ symbol_2 = SIZEOF(.output);
|
||
+@dots{} @}
|
||
+@end group
|
||
+@end smallexample
|
||
+
|
||
+@item SIZEOF_HEADERS
|
||
+@kindex SIZEOF_HEADERS
|
||
+@cindex header size
|
||
+Return the size in bytes of the output file's headers. This is
|
||
+information which appears at the start of the output file. You can use
|
||
+this number when setting the start address of the first section, if you
|
||
+choose, to facilitate paging.
|
||
+
|
||
+@cindex not enough room for program headers
|
||
+@cindex program headers, not enough room
|
||
+When producing an ELF output file, if the linker script uses the
|
||
+@code{SIZEOF_HEADERS} builtin function, the linker must compute the
|
||
+number of program headers before it has determined all the section
|
||
+addresses and sizes. If the linker later discovers that it needs
|
||
+additional program headers, it will report an error @samp{not enough
|
||
+room for program headers}. To avoid this error, you must avoid using
|
||
+the @code{SIZEOF_HEADERS} function, or you must rework your linker
|
||
+script to avoid forcing the linker to use additional program headers, or
|
||
+you must define the program headers yourself using the @code{PHDRS}
|
||
+command (@pxref{PHDRS}).
|
||
+@end table
|
||
+
|
||
+@node Implicit Linker Scripts
|
||
+@section Implicit Linker Scripts
|
||
+@cindex implicit linker scripts
|
||
+If you specify a linker input file which the linker can not recognize as
|
||
+an object file or an archive file, it will try to read the file as a
|
||
+linker script. If the file can not be parsed as a linker script, the
|
||
+linker will report an error.
|
||
+
|
||
+An implicit linker script will not replace the default linker script.
|
||
+
|
||
+Typically an implicit linker script would contain only symbol
|
||
+assignments, or the @code{INPUT}, @code{GROUP}, or @code{VERSION}
|
||
+commands.
|
||
+
|
||
+Any input files read because of an implicit linker script will be read
|
||
+at the position in the command line where the implicit linker script was
|
||
+read. This can affect archive searching.
|
||
+
|
||
+@node Plugins
|
||
+@chapter Linker Plugins
|
||
+
|
||
+@cindex plugins
|
||
+@cindex linker plugins
|
||
+The linker can use dynamically loaded plugins to modify its behavior.
|
||
+For example, the link-time optimization feature that some compilers
|
||
+support is implemented with a linker plugin.
|
||
+
|
||
+Currently there is only one plugin shipped by default, but more may
|
||
+be added here later.
|
||
+
|
||
+Plugins are enabled via the use of the @option{-plugin @var{name}}
|
||
+command line option. @xref{Options}.
|
||
+
|
||
+@menu
|
||
+* libdep Plugin:: Static Library Dependencies Plugin
|
||
+@end menu
|
||
+
|
||
+@node libdep Plugin
|
||
+@section Static Library Dependencies Plugin
|
||
+@cindex static library dependencies
|
||
+Originally, static libraries were contained in an archive file consisting
|
||
+just of a collection of relocatable object files. Later they evolved to
|
||
+optionally include a symbol table, to assist in finding the needed objects
|
||
+within a library. There their evolution ended, and dynamic libraries
|
||
+rose to ascendance.
|
||
+
|
||
+One useful feature of dynamic libraries was that, more than just collecting
|
||
+multiple objects into a single file, they also included a list of their
|
||
+dependencies, such that one could specify just the name of a single dynamic
|
||
+library at link time, and all of its dependencies would be implicitly
|
||
+referenced as well. But static libraries lacked this feature, so if a
|
||
+link invocation was switched from using dynamic libraries to static
|
||
+libraries, the link command would usually fail unless it was rewritten to
|
||
+explicitly list the dependencies of the static library.
|
||
+
|
||
+The GNU @command{ar} utility now supports a @option{--record-libdeps} option
|
||
+to embed dependency lists into static libraries as well, and the @file{libdep}
|
||
+plugin may be used to read this dependency information at link time. The
|
||
+dependency information is stored as a single string, carrying @option{-l}
|
||
+and @option{-L} arguments as they would normally appear in a linker
|
||
+command line. As such, the information can be written with any text
|
||
+utility and stored into any archive, even if GNU @command{ar} is not
|
||
+being used to create the archive. The information is stored in an
|
||
+archive member named @samp{__.LIBDEP}.
|
||
+
|
||
+For example, given a library @file{libssl.a} that depends on another
|
||
+library @file{libcrypto.a} which may be found in @file{/usr/local/lib},
|
||
+the @samp{__.LIBDEP} member of @file{libssl.a} would contain
|
||
+
|
||
+@smallexample
|
||
+-L/usr/local/lib -lcrypto
|
||
+@end smallexample
|
||
+
|
||
+@ifset GENERIC
|
||
+@node Machine Dependent
|
||
+@chapter Machine Dependent Features
|
||
+
|
||
+@cindex machine dependencies
|
||
+@command{ld} has additional features on some platforms; the following
|
||
+sections describe them. Machines where @command{ld} has no additional
|
||
+functionality are not listed.
|
||
+
|
||
+@menu
|
||
+@ifset H8300
|
||
+* H8/300:: @command{ld} and the H8/300
|
||
+@end ifset
|
||
+@ifset M68HC11
|
||
+* M68HC11/68HC12:: @code{ld} and the Motorola 68HC11 and 68HC12 families
|
||
+@end ifset
|
||
+@ifset ARM
|
||
+* ARM:: @command{ld} and the ARM family
|
||
+@end ifset
|
||
+@ifset HPPA
|
||
+* HPPA ELF32:: @command{ld} and HPPA 32-bit ELF
|
||
+@end ifset
|
||
+@ifset M68K
|
||
+* M68K:: @command{ld} and the Motorola 68K family
|
||
+@end ifset
|
||
+@ifset MIPS
|
||
+* MIPS:: @command{ld} and the MIPS family
|
||
+@end ifset
|
||
+@ifset MMIX
|
||
+* MMIX:: @command{ld} and MMIX
|
||
+@end ifset
|
||
+@ifset MSP430
|
||
+* MSP430:: @command{ld} and MSP430
|
||
+@end ifset
|
||
+@ifset NDS32
|
||
+* NDS32:: @command{ld} and NDS32
|
||
+@end ifset
|
||
+@ifset NIOSII
|
||
+* Nios II:: @command{ld} and the Altera Nios II
|
||
+@end ifset
|
||
+@ifset POWERPC
|
||
+* PowerPC ELF32:: @command{ld} and PowerPC 32-bit ELF Support
|
||
+@end ifset
|
||
+@ifset POWERPC64
|
||
+* PowerPC64 ELF64:: @command{ld} and PowerPC64 64-bit ELF Support
|
||
+@end ifset
|
||
+@ifset S/390
|
||
+* S/390 ELF:: @command{ld} and S/390 ELF Support
|
||
+@end ifset
|
||
+@ifset SPU
|
||
+* SPU ELF:: @command{ld} and SPU ELF Support
|
||
+@end ifset
|
||
+@ifset TICOFF
|
||
+* TI COFF:: @command{ld} and TI COFF
|
||
+@end ifset
|
||
+@ifset WIN32
|
||
+* WIN32:: @command{ld} and WIN32 (cygwin/mingw)
|
||
+@end ifset
|
||
+@ifset XTENSA
|
||
+* Xtensa:: @command{ld} and Xtensa Processors
|
||
+@end ifset
|
||
+@end menu
|
||
+@end ifset
|
||
+
|
||
+@ifset H8300
|
||
+@ifclear GENERIC
|
||
+@raisesections
|
||
+@end ifclear
|
||
+
|
||
+@node H8/300
|
||
+@section @command{ld} and the H8/300
|
||
+
|
||
+@cindex H8/300 support
|
||
+For the H8/300, @command{ld} can perform these global optimizations when
|
||
+you specify the @samp{--relax} command-line option.
|
||
+
|
||
+@table @emph
|
||
+@cindex relaxing on H8/300
|
||
+@item relaxing address modes
|
||
+@command{ld} finds all @code{jsr} and @code{jmp} instructions whose
|
||
+targets are within eight bits, and turns them into eight-bit
|
||
+program-counter relative @code{bsr} and @code{bra} instructions,
|
||
+respectively.
|
||
+
|
||
+@cindex synthesizing on H8/300
|
||
+@item synthesizing instructions
|
||
+@c FIXME: specifically mov.b, or any mov instructions really? -> mov.b only, at least on H8, H8H, H8S
|
||
+@command{ld} finds all @code{mov.b} instructions which use the
|
||
+sixteen-bit absolute address form, but refer to the top
|
||
+page of memory, and changes them to use the eight-bit address form.
|
||
+(That is: the linker turns @samp{mov.b @code{@@}@var{aa}:16} into
|
||
+@samp{mov.b @code{@@}@var{aa}:8} whenever the address @var{aa} is in the
|
||
+top page of memory).
|
||
+
|
||
+@command{ld} finds all @code{mov} instructions which use the register
|
||
+indirect with 32-bit displacement addressing mode, but use a small
|
||
+displacement inside 16-bit displacement range, and changes them to use
|
||
+the 16-bit displacement form. (That is: the linker turns @samp{mov.b
|
||
+@code{@@}@var{d}:32,ERx} into @samp{mov.b @code{@@}@var{d}:16,ERx}
|
||
+whenever the displacement @var{d} is in the 16 bit signed integer
|
||
+range. Only implemented in ELF-format ld).
|
||
+
|
||
+@item bit manipulation instructions
|
||
+@command{ld} finds all bit manipulation instructions like @code{band, bclr,
|
||
+biand, bild, bior, bist, bixor, bld, bnot, bor, bset, bst, btst, bxor}
|
||
+which use 32 bit and 16 bit absolute address form, but refer to the top
|
||
+page of memory, and changes them to use the 8 bit address form.
|
||
+(That is: the linker turns @samp{bset #xx:3,@code{@@}@var{aa}:32} into
|
||
+@samp{bset #xx:3,@code{@@}@var{aa}:8} whenever the address @var{aa} is in
|
||
+the top page of memory).
|
||
+
|
||
+@item system control instructions
|
||
+@command{ld} finds all @code{ldc.w, stc.w} instructions which use the
|
||
+32 bit absolute address form, but refer to the top page of memory, and
|
||
+changes them to use 16 bit address form.
|
||
+(That is: the linker turns @samp{ldc.w @code{@@}@var{aa}:32,ccr} into
|
||
+@samp{ldc.w @code{@@}@var{aa}:16,ccr} whenever the address @var{aa} is in
|
||
+the top page of memory).
|
||
+@end table
|
||
+
|
||
+@ifclear GENERIC
|
||
+@lowersections
|
||
+@end ifclear
|
||
+@end ifset
|
||
+
|
||
+@ifclear GENERIC
|
||
+@ifset Renesas
|
||
+@c This stuff is pointless to say unless you're especially concerned
|
||
+@c with Renesas chips; don't enable it for generic case, please.
|
||
+@node Renesas
|
||
+@chapter @command{ld} and Other Renesas Chips
|
||
+
|
||
+@command{ld} also supports the Renesas (formerly Hitachi) H8/300H,
|
||
+H8/500, and SH chips. No special features, commands, or command-line
|
||
+options are required for these chips.
|
||
+@end ifset
|
||
+@end ifclear
|
||
+
|
||
+@ifset ARM
|
||
+@ifclear GENERIC
|
||
+@raisesections
|
||
+@end ifclear
|
||
+
|
||
+@ifset M68HC11
|
||
+@ifclear GENERIC
|
||
+@raisesections
|
||
+@end ifclear
|
||
+
|
||
+@node M68HC11/68HC12
|
||
+@section @command{ld} and the Motorola 68HC11 and 68HC12 families
|
||
+
|
||
+@cindex M68HC11 and 68HC12 support
|
||
+
|
||
+@subsection Linker Relaxation
|
||
+
|
||
+For the Motorola 68HC11, @command{ld} can perform these global
|
||
+optimizations when you specify the @samp{--relax} command-line option.
|
||
+
|
||
+@table @emph
|
||
+@cindex relaxing on M68HC11
|
||
+@item relaxing address modes
|
||
+@command{ld} finds all @code{jsr} and @code{jmp} instructions whose
|
||
+targets are within eight bits, and turns them into eight-bit
|
||
+program-counter relative @code{bsr} and @code{bra} instructions,
|
||
+respectively.
|
||
+
|
||
+@command{ld} also looks at all 16-bit extended addressing modes and
|
||
+transforms them in a direct addressing mode when the address is in
|
||
+page 0 (between 0 and 0x0ff).
|
||
+
|
||
+@item relaxing gcc instruction group
|
||
+When @command{gcc} is called with @option{-mrelax}, it can emit group
|
||
+of instructions that the linker can optimize to use a 68HC11 direct
|
||
+addressing mode. These instructions consists of @code{bclr} or
|
||
+@code{bset} instructions.
|
||
+
|
||
+@end table
|
||
+
|
||
+@subsection Trampoline Generation
|
||
+
|
||
+@cindex trampoline generation on M68HC11
|
||
+@cindex trampoline generation on M68HC12
|
||
+For 68HC11 and 68HC12, @command{ld} can generate trampoline code to
|
||
+call a far function using a normal @code{jsr} instruction. The linker
|
||
+will also change the relocation to some far function to use the
|
||
+trampoline address instead of the function address. This is typically the
|
||
+case when a pointer to a function is taken. The pointer will in fact
|
||
+point to the function trampoline.
|
||
+
|
||
+@ifclear GENERIC
|
||
+@lowersections
|
||
+@end ifclear
|
||
+@end ifset
|
||
+
|
||
+@node ARM
|
||
+@section @command{ld} and the ARM family
|
||
+
|
||
+@cindex ARM interworking support
|
||
+@kindex --support-old-code
|
||
+For the ARM, @command{ld} will generate code stubs to allow functions calls
|
||
+between ARM and Thumb code. These stubs only work with code that has
|
||
+been compiled and assembled with the @samp{-mthumb-interwork} command
|
||
+line option. If it is necessary to link with old ARM object files or
|
||
+libraries, which have not been compiled with the -mthumb-interwork
|
||
+option then the @samp{--support-old-code} command-line switch should be
|
||
+given to the linker. This will make it generate larger stub functions
|
||
+which will work with non-interworking aware ARM code. Note, however,
|
||
+the linker does not support generating stubs for function calls to
|
||
+non-interworking aware Thumb code.
|
||
+
|
||
+@cindex thumb entry point
|
||
+@cindex entry point, thumb
|
||
+@kindex --thumb-entry=@var{entry}
|
||
+The @samp{--thumb-entry} switch is a duplicate of the generic
|
||
+@samp{--entry} switch, in that it sets the program's starting address.
|
||
+But it also sets the bottom bit of the address, so that it can be
|
||
+branched to using a BX instruction, and the program will start
|
||
+executing in Thumb mode straight away.
|
||
+
|
||
+@cindex PE import table prefixing
|
||
+@kindex --use-nul-prefixed-import-tables
|
||
+The @samp{--use-nul-prefixed-import-tables} switch is specifying, that
|
||
+the import tables idata4 and idata5 have to be generated with a zero
|
||
+element prefix for import libraries. This is the old style to generate
|
||
+import tables. By default this option is turned off.
|
||
+
|
||
+@cindex BE8
|
||
+@kindex --be8
|
||
+The @samp{--be8} switch instructs @command{ld} to generate BE8 format
|
||
+executables. This option is only valid when linking big-endian
|
||
+objects - ie ones which have been assembled with the @option{-EB}
|
||
+option. The resulting image will contain big-endian data and
|
||
+little-endian code.
|
||
+
|
||
+@cindex TARGET1
|
||
+@kindex --target1-rel
|
||
+@kindex --target1-abs
|
||
+The @samp{R_ARM_TARGET1} relocation is typically used for entries in the
|
||
+@samp{.init_array} section. It is interpreted as either @samp{R_ARM_REL32}
|
||
+or @samp{R_ARM_ABS32}, depending on the target. The @samp{--target1-rel}
|
||
+and @samp{--target1-abs} switches override the default.
|
||
+
|
||
+@cindex TARGET2
|
||
+@kindex --target2=@var{type}
|
||
+The @samp{--target2=type} switch overrides the default definition of the
|
||
+@samp{R_ARM_TARGET2} relocation. Valid values for @samp{type}, their
|
||
+meanings, and target defaults are as follows:
|
||
+@table @samp
|
||
+@item rel
|
||
+@samp{R_ARM_REL32} (arm*-*-elf, arm*-*-eabi)
|
||
+@item abs
|
||
+@samp{R_ARM_ABS32}
|
||
+@item got-rel
|
||
+@samp{R_ARM_GOT_PREL} (arm*-*-linux, arm*-*-*bsd)
|
||
+@end table
|
||
+
|
||
+@cindex FIX_V4BX
|
||
+@kindex --fix-v4bx
|
||
+The @samp{R_ARM_V4BX} relocation (defined by the ARM AAELF
|
||
+specification) enables objects compiled for the ARMv4 architecture to be
|
||
+interworking-safe when linked with other objects compiled for ARMv4t, but
|
||
+also allows pure ARMv4 binaries to be built from the same ARMv4 objects.
|
||
+
|
||
+In the latter case, the switch @option{--fix-v4bx} must be passed to the
|
||
+linker, which causes v4t @code{BX rM} instructions to be rewritten as
|
||
+@code{MOV PC,rM}, since v4 processors do not have a @code{BX} instruction.
|
||
+
|
||
+In the former case, the switch should not be used, and @samp{R_ARM_V4BX}
|
||
+relocations are ignored.
|
||
+
|
||
+@cindex FIX_V4BX_INTERWORKING
|
||
+@kindex --fix-v4bx-interworking
|
||
+Replace @code{BX rM} instructions identified by @samp{R_ARM_V4BX}
|
||
+relocations with a branch to the following veneer:
|
||
+
|
||
+@smallexample
|
||
+TST rM, #1
|
||
+MOVEQ PC, rM
|
||
+BX Rn
|
||
+@end smallexample
|
||
+
|
||
+This allows generation of libraries/applications that work on ARMv4 cores
|
||
+and are still interworking safe. Note that the above veneer clobbers the
|
||
+condition flags, so may cause incorrect program behavior in rare cases.
|
||
+
|
||
+@cindex USE_BLX
|
||
+@kindex --use-blx
|
||
+The @samp{--use-blx} switch enables the linker to use ARM/Thumb
|
||
+BLX instructions (available on ARMv5t and above) in various
|
||
+situations. Currently it is used to perform calls via the PLT from Thumb
|
||
+code using BLX rather than using BX and a mode-switching stub before
|
||
+each PLT entry. This should lead to such calls executing slightly faster.
|
||
+
|
||
+@cindex VFP11_DENORM_FIX
|
||
+@kindex --vfp11-denorm-fix
|
||
+The @samp{--vfp11-denorm-fix} switch enables a link-time workaround for a
|
||
+bug in certain VFP11 coprocessor hardware, which sometimes allows
|
||
+instructions with denorm operands (which must be handled by support code)
|
||
+to have those operands overwritten by subsequent instructions before
|
||
+the support code can read the intended values.
|
||
+
|
||
+The bug may be avoided in scalar mode if you allow at least one
|
||
+intervening instruction between a VFP11 instruction which uses a register
|
||
+and another instruction which writes to the same register, or at least two
|
||
+intervening instructions if vector mode is in use. The bug only affects
|
||
+full-compliance floating-point mode: you do not need this workaround if
|
||
+you are using "runfast" mode. Please contact ARM for further details.
|
||
+
|
||
+If you know you are using buggy VFP11 hardware, you can
|
||
+enable this workaround by specifying the linker option
|
||
+@samp{--vfp-denorm-fix=scalar} if you are using the VFP11 scalar
|
||
+mode only, or @samp{--vfp-denorm-fix=vector} if you are using
|
||
+vector mode (the latter also works for scalar code). The default is
|
||
+@samp{--vfp-denorm-fix=none}.
|
||
+
|
||
+If the workaround is enabled, instructions are scanned for
|
||
+potentially-troublesome sequences, and a veneer is created for each
|
||
+such sequence which may trigger the erratum. The veneer consists of the
|
||
+first instruction of the sequence and a branch back to the subsequent
|
||
+instruction. The original instruction is then replaced with a branch to
|
||
+the veneer. The extra cycles required to call and return from the veneer
|
||
+are sufficient to avoid the erratum in both the scalar and vector cases.
|
||
+
|
||
+@cindex ARM1176 erratum workaround
|
||
+@kindex --fix-arm1176
|
||
+@kindex --no-fix-arm1176
|
||
+The @samp{--fix-arm1176} switch enables a link-time workaround for an erratum
|
||
+in certain ARM1176 processors. The workaround is enabled by default if you
|
||
+are targeting ARM v6 (excluding ARM v6T2) or earlier. It can be disabled
|
||
+unconditionally by specifying @samp{--no-fix-arm1176}.
|
||
+
|
||
+Further information is available in the ``ARM1176JZ-S and ARM1176JZF-S
|
||
+Programmer Advice Notice'' available on the ARM documentation website at:
|
||
+http://infocenter.arm.com/.
|
||
+
|
||
+@cindex STM32L4xx erratum workaround
|
||
+@kindex --fix-stm32l4xx-629360
|
||
+
|
||
+The @samp{--fix-stm32l4xx-629360} switch enables a link-time
|
||
+workaround for a bug in the bus matrix / memory controller for some of
|
||
+the STM32 Cortex-M4 based products (STM32L4xx). When accessing
|
||
+off-chip memory via the affected bus for bus reads of 9 words or more,
|
||
+the bus can generate corrupt data and/or abort. These are only
|
||
+core-initiated accesses (not DMA), and might affect any access:
|
||
+integer loads such as LDM, POP and floating-point loads such as VLDM,
|
||
+VPOP. Stores are not affected.
|
||
+
|
||
+The bug can be avoided by splitting memory accesses into the
|
||
+necessary chunks to keep bus reads below 8 words.
|
||
+
|
||
+The workaround is not enabled by default, this is equivalent to use
|
||
+@samp{--fix-stm32l4xx-629360=none}. If you know you are using buggy
|
||
+STM32L4xx hardware, you can enable the workaround by specifying the
|
||
+linker option @samp{--fix-stm32l4xx-629360}, or the equivalent
|
||
+@samp{--fix-stm32l4xx-629360=default}.
|
||
+
|
||
+If the workaround is enabled, instructions are scanned for
|
||
+potentially-troublesome sequences, and a veneer is created for each
|
||
+such sequence which may trigger the erratum. The veneer consists in a
|
||
+replacement sequence emulating the behaviour of the original one and a
|
||
+branch back to the subsequent instruction. The original instruction is
|
||
+then replaced with a branch to the veneer.
|
||
+
|
||
+The workaround does not always preserve the memory access order for
|
||
+the LDMDB instruction, when the instruction loads the PC.
|
||
+
|
||
+The workaround is not able to handle problematic instructions when
|
||
+they are in the middle of an IT block, since a branch is not allowed
|
||
+there. In that case, the linker reports a warning and no replacement
|
||
+occurs.
|
||
+
|
||
+The workaround is not able to replace problematic instructions with a
|
||
+PC-relative branch instruction if the @samp{.text} section is too
|
||
+large. In that case, when the branch that replaces the original code
|
||
+cannot be encoded, the linker reports a warning and no replacement
|
||
+occurs.
|
||
+
|
||
+@cindex NO_ENUM_SIZE_WARNING
|
||
+@kindex --no-enum-size-warning
|
||
+The @option{--no-enum-size-warning} switch prevents the linker from
|
||
+warning when linking object files that specify incompatible EABI
|
||
+enumeration size attributes. For example, with this switch enabled,
|
||
+linking of an object file using 32-bit enumeration values with another
|
||
+using enumeration values fitted into the smallest possible space will
|
||
+not be diagnosed.
|
||
+
|
||
+@cindex NO_WCHAR_SIZE_WARNING
|
||
+@kindex --no-wchar-size-warning
|
||
+The @option{--no-wchar-size-warning} switch prevents the linker from
|
||
+warning when linking object files that specify incompatible EABI
|
||
+@code{wchar_t} size attributes. For example, with this switch enabled,
|
||
+linking of an object file using 32-bit @code{wchar_t} values with another
|
||
+using 16-bit @code{wchar_t} values will not be diagnosed.
|
||
+
|
||
+@cindex PIC_VENEER
|
||
+@kindex --pic-veneer
|
||
+The @samp{--pic-veneer} switch makes the linker use PIC sequences for
|
||
+ARM/Thumb interworking veneers, even if the rest of the binary
|
||
+is not PIC. This avoids problems on uClinux targets where
|
||
+@samp{--emit-relocs} is used to generate relocatable binaries.
|
||
+
|
||
+@cindex STUB_GROUP_SIZE
|
||
+@kindex --stub-group-size=@var{N}
|
||
+The linker will automatically generate and insert small sequences of
|
||
+code into a linked ARM ELF executable whenever an attempt is made to
|
||
+perform a function call to a symbol that is too far away. The
|
||
+placement of these sequences of instructions - called stubs - is
|
||
+controlled by the command-line option @option{--stub-group-size=N}.
|
||
+The placement is important because a poor choice can create a need for
|
||
+duplicate stubs, increasing the code size. The linker will try to
|
||
+group stubs together in order to reduce interruptions to the flow of
|
||
+code, but it needs guidance as to how big these groups should be and
|
||
+where they should be placed.
|
||
+
|
||
+The value of @samp{N}, the parameter to the
|
||
+@option{--stub-group-size=} option controls where the stub groups are
|
||
+placed. If it is negative then all stubs are placed after the first
|
||
+branch that needs them. If it is positive then the stubs can be
|
||
+placed either before or after the branches that need them. If the
|
||
+value of @samp{N} is 1 (either +1 or -1) then the linker will choose
|
||
+exactly where to place groups of stubs, using its built in heuristics.
|
||
+A value of @samp{N} greater than 1 (or smaller than -1) tells the
|
||
+linker that a single group of stubs can service at most @samp{N} bytes
|
||
+from the input sections.
|
||
+
|
||
+The default, if @option{--stub-group-size=} is not specified, is
|
||
+@samp{N = +1}.
|
||
+
|
||
+Farcalls stubs insertion is fully supported for the ARM-EABI target
|
||
+only, because it relies on object files properties not present
|
||
+otherwise.
|
||
+
|
||
+@cindex Cortex-A8 erratum workaround
|
||
+@kindex --fix-cortex-a8
|
||
+@kindex --no-fix-cortex-a8
|
||
+The @samp{--fix-cortex-a8} switch enables a link-time workaround for an erratum in certain Cortex-A8 processors. The workaround is enabled by default if you are targeting the ARM v7-A architecture profile. It can be enabled otherwise by specifying @samp{--fix-cortex-a8}, or disabled unconditionally by specifying @samp{--no-fix-cortex-a8}.
|
||
+
|
||
+The erratum only affects Thumb-2 code. Please contact ARM for further details.
|
||
+
|
||
+@cindex Cortex-A53 erratum 835769 workaround
|
||
+@kindex --fix-cortex-a53-835769
|
||
+@kindex --no-fix-cortex-a53-835769
|
||
+The @samp{--fix-cortex-a53-835769} switch enables a link-time workaround for erratum 835769 present on certain early revisions of Cortex-A53 processors. The workaround is disabled by default. It can be enabled by specifying @samp{--fix-cortex-a53-835769}, or disabled unconditionally by specifying @samp{--no-fix-cortex-a53-835769}.
|
||
+
|
||
+Please contact ARM for further details.
|
||
+
|
||
+@kindex --merge-exidx-entries
|
||
+@kindex --no-merge-exidx-entries
|
||
+@cindex Merging exidx entries
|
||
+The @samp{--no-merge-exidx-entries} switch disables the merging of adjacent exidx entries in debuginfo.
|
||
+
|
||
+@kindex --long-plt
|
||
+@cindex 32-bit PLT entries
|
||
+The @samp{--long-plt} option enables the use of 16 byte PLT entries
|
||
+which support up to 4Gb of code. The default is to use 12 byte PLT
|
||
+entries which only support 512Mb of code.
|
||
+
|
||
+@kindex --no-apply-dynamic-relocs
|
||
+@cindex AArch64 rela addend
|
||
+The @samp{--no-apply-dynamic-relocs} option makes AArch64 linker do not apply
|
||
+link-time values for dynamic relocations.
|
||
+
|
||
+@cindex Placement of SG veneers
|
||
+All SG veneers are placed in the special output section @code{.gnu.sgstubs}.
|
||
+Its start address must be set, either with the command-line option
|
||
+@samp{--section-start} or in a linker script, to indicate where to place these
|
||
+veneers in memory.
|
||
+
|
||
+@kindex --cmse-implib
|
||
+@cindex Secure gateway import library
|
||
+The @samp{--cmse-implib} option requests that the import libraries
|
||
+specified by the @samp{--out-implib} and @samp{--in-implib} options are
|
||
+secure gateway import libraries, suitable for linking a non-secure
|
||
+executable against secure code as per ARMv8-M Security Extensions.
|
||
+
|
||
+@kindex --in-implib=@var{file}
|
||
+@cindex Input import library
|
||
+The @samp{--in-implib=file} specifies an input import library whose symbols
|
||
+must keep the same address in the executable being produced. A warning is
|
||
+given if no @samp{--out-implib} is given but new symbols have been introduced
|
||
+in the executable that should be listed in its import library. Otherwise, if
|
||
+@samp{--out-implib} is specified, the symbols are added to the output import
|
||
+library. A warning is also given if some symbols present in the input import
|
||
+library have disappeared from the executable. This option is only effective
|
||
+for Secure Gateway import libraries, ie. when @samp{--cmse-implib} is
|
||
+specified.
|
||
+
|
||
+@ifclear GENERIC
|
||
+@lowersections
|
||
+@end ifclear
|
||
+@end ifset
|
||
+
|
||
+@ifset HPPA
|
||
+@ifclear GENERIC
|
||
+@raisesections
|
||
+@end ifclear
|
||
+
|
||
+@node HPPA ELF32
|
||
+@section @command{ld} and HPPA 32-bit ELF Support
|
||
+@cindex HPPA multiple sub-space stubs
|
||
+@kindex --multi-subspace
|
||
+When generating a shared library, @command{ld} will by default generate
|
||
+import stubs suitable for use with a single sub-space application.
|
||
+The @samp{--multi-subspace} switch causes @command{ld} to generate export
|
||
+stubs, and different (larger) import stubs suitable for use with
|
||
+multiple sub-spaces.
|
||
+
|
||
+@cindex HPPA stub grouping
|
||
+@kindex --stub-group-size=@var{N}
|
||
+Long branch stubs and import/export stubs are placed by @command{ld} in
|
||
+stub sections located between groups of input sections.
|
||
+@samp{--stub-group-size} specifies the maximum size of a group of input
|
||
+sections handled by one stub section. Since branch offsets are signed,
|
||
+a stub section may serve two groups of input sections, one group before
|
||
+the stub section, and one group after it. However, when using
|
||
+conditional branches that require stubs, it may be better (for branch
|
||
+prediction) that stub sections only serve one group of input sections.
|
||
+A negative value for @samp{N} chooses this scheme, ensuring that
|
||
+branches to stubs always use a negative offset. Two special values of
|
||
+@samp{N} are recognized, @samp{1} and @samp{-1}. These both instruct
|
||
+@command{ld} to automatically size input section groups for the branch types
|
||
+detected, with the same behaviour regarding stub placement as other
|
||
+positive or negative values of @samp{N} respectively.
|
||
+
|
||
+Note that @samp{--stub-group-size} does not split input sections. A
|
||
+single input section larger than the group size specified will of course
|
||
+create a larger group (of one section). If input sections are too
|
||
+large, it may not be possible for a branch to reach its stub.
|
||
+
|
||
+@ifclear GENERIC
|
||
+@lowersections
|
||
+@end ifclear
|
||
+@end ifset
|
||
+
|
||
+@ifset M68K
|
||
+@ifclear GENERIC
|
||
+@raisesections
|
||
+@end ifclear
|
||
+
|
||
+@node M68K
|
||
+@section @command{ld} and the Motorola 68K family
|
||
+
|
||
+@cindex Motorola 68K GOT generation
|
||
+@kindex --got=@var{type}
|
||
+The @samp{--got=@var{type}} option lets you choose the GOT generation scheme.
|
||
+The choices are @samp{single}, @samp{negative}, @samp{multigot} and
|
||
+@samp{target}. When @samp{target} is selected the linker chooses
|
||
+the default GOT generation scheme for the current target.
|
||
+@samp{single} tells the linker to generate a single GOT with
|
||
+entries only at non-negative offsets.
|
||
+@samp{negative} instructs the linker to generate a single GOT with
|
||
+entries at both negative and positive offsets. Not all environments
|
||
+support such GOTs.
|
||
+@samp{multigot} allows the linker to generate several GOTs in the
|
||
+output file. All GOT references from a single input object
|
||
+file access the same GOT, but references from different input object
|
||
+files might access different GOTs. Not all environments support such GOTs.
|
||
+
|
||
+@ifclear GENERIC
|
||
+@lowersections
|
||
+@end ifclear
|
||
+@end ifset
|
||
+
|
||
+@ifset MIPS
|
||
+@ifclear GENERIC
|
||
+@raisesections
|
||
+@end ifclear
|
||
+
|
||
+@node MIPS
|
||
+@section @command{ld} and the MIPS family
|
||
+
|
||
+@cindex MIPS microMIPS instruction choice selection
|
||
+@kindex --insn32
|
||
+@kindex --no-insn32
|
||
+The @samp{--insn32} and @samp{--no-insn32} options control the choice of
|
||
+microMIPS instructions used in code generated by the linker, such as that
|
||
+in the PLT or lazy binding stubs, or in relaxation. If @samp{--insn32} is
|
||
+used, then the linker only uses 32-bit instruction encodings. By default
|
||
+or if @samp{--no-insn32} is used, all instruction encodings are used,
|
||
+including 16-bit ones where possible.
|
||
+
|
||
+@cindex MIPS branch relocation check control
|
||
+@kindex --ignore-branch-isa
|
||
+@kindex --no-ignore-branch-isa
|
||
+The @samp{--ignore-branch-isa} and @samp{--no-ignore-branch-isa} options
|
||
+control branch relocation checks for invalid ISA mode transitions. If
|
||
+@samp{--ignore-branch-isa} is used, then the linker accepts any branch
|
||
+relocations and any ISA mode transition required is lost in relocation
|
||
+calculation, except for some cases of @code{BAL} instructions which meet
|
||
+relaxation conditions and are converted to equivalent @code{JALX}
|
||
+instructions as the associated relocation is calculated. By default
|
||
+or if @samp{--no-ignore-branch-isa} is used a check is made causing
|
||
+the loss of an ISA mode transition to produce an error.
|
||
+
|
||
+@ifclear GENERIC
|
||
+@lowersections
|
||
+@end ifclear
|
||
+@end ifset
|
||
+
|
||
+@ifset MMIX
|
||
+@ifclear GENERIC
|
||
+@raisesections
|
||
+@end ifclear
|
||
+
|
||
+@node MMIX
|
||
+@section @code{ld} and MMIX
|
||
+For MMIX, there is a choice of generating @code{ELF} object files or
|
||
+@code{mmo} object files when linking. The simulator @code{mmix}
|
||
+understands the @code{mmo} format. The binutils @code{objcopy} utility
|
||
+can translate between the two formats.
|
||
+
|
||
+There is one special section, the @samp{.MMIX.reg_contents} section.
|
||
+Contents in this section is assumed to correspond to that of global
|
||
+registers, and symbols referring to it are translated to special symbols,
|
||
+equal to registers. In a final link, the start address of the
|
||
+@samp{.MMIX.reg_contents} section corresponds to the first allocated
|
||
+global register multiplied by 8. Register @code{$255} is not included in
|
||
+this section; it is always set to the program entry, which is at the
|
||
+symbol @code{Main} for @code{mmo} files.
|
||
+
|
||
+Global symbols with the prefix @code{__.MMIX.start.}, for example
|
||
+@code{__.MMIX.start..text} and @code{__.MMIX.start..data} are special.
|
||
+The default linker script uses these to set the default start address
|
||
+of a section.
|
||
+
|
||
+Initial and trailing multiples of zero-valued 32-bit words in a section,
|
||
+are left out from an mmo file.
|
||
+
|
||
+@ifclear GENERIC
|
||
+@lowersections
|
||
+@end ifclear
|
||
+@end ifset
|
||
+
|
||
+@ifset MSP430
|
||
+@ifclear GENERIC
|
||
+@raisesections
|
||
+@end ifclear
|
||
+
|
||
+@node MSP430
|
||
+@section @code{ld} and MSP430
|
||
+For the MSP430 it is possible to select the MPU architecture. The flag @samp{-m [mpu type]}
|
||
+will select an appropriate linker script for selected MPU type. (To get a list of known MPUs
|
||
+just pass @samp{-m help} option to the linker).
|
||
+
|
||
+@cindex MSP430 extra sections
|
||
+The linker will recognize some extra sections which are MSP430 specific:
|
||
+
|
||
+@table @code
|
||
+@item @samp{.vectors}
|
||
+Defines a portion of ROM where interrupt vectors located.
|
||
+
|
||
+@item @samp{.bootloader}
|
||
+Defines the bootloader portion of the ROM (if applicable). Any code
|
||
+in this section will be uploaded to the MPU.
|
||
+
|
||
+@item @samp{.infomem}
|
||
+Defines an information memory section (if applicable). Any code in
|
||
+this section will be uploaded to the MPU.
|
||
+
|
||
+@item @samp{.infomemnobits}
|
||
+This is the same as the @samp{.infomem} section except that any code
|
||
+in this section will not be uploaded to the MPU.
|
||
+
|
||
+@item @samp{.noinit}
|
||
+Denotes a portion of RAM located above @samp{.bss} section.
|
||
+
|
||
+The last two sections are used by gcc.
|
||
+@end table
|
||
+
|
||
+@table @option
|
||
+@cindex MSP430 Options
|
||
+@kindex --code-region
|
||
+@item --code-region=[either,lower,upper,none]
|
||
+This will transform .text* sections to [either,lower,upper].text* sections. The
|
||
+argument passed to GCC for -mcode-region is propagated to the linker
|
||
+using this option.
|
||
+
|
||
+@kindex --data-region
|
||
+@item --data-region=[either,lower,upper,none]
|
||
+This will transform .data*, .bss* and .rodata* sections to
|
||
+[either,lower,upper].[data,bss,rodata]* sections. The argument passed to GCC
|
||
+for -mdata-region is propagated to the linker using this option.
|
||
+
|
||
+@kindex --disable-sec-transformation
|
||
+@item --disable-sec-transformation
|
||
+Prevent the transformation of sections as specified by the @code{--code-region}
|
||
+and @code{--data-region} options.
|
||
+This is useful if you are compiling and linking using a single call to the GCC
|
||
+wrapper, and want to compile the source files using -m[code,data]-region but
|
||
+not transform the sections for prebuilt libraries and objects.
|
||
+@end table
|
||
+
|
||
+@ifclear GENERIC
|
||
+@lowersections
|
||
+@end ifclear
|
||
+@end ifset
|
||
+
|
||
+@ifset NDS32
|
||
+@ifclear GENERIC
|
||
+@raisesections
|
||
+@end ifclear
|
||
+
|
||
+@node NDS32
|
||
+@section @code{ld} and NDS32
|
||
+@kindex relaxing on NDS32
|
||
+For NDS32, there are some options to select relaxation behavior. The linker
|
||
+relaxes objects according to these options.
|
||
+
|
||
+@table @code
|
||
+@item @samp{--m[no-]fp-as-gp}
|
||
+Disable/enable fp-as-gp relaxation.
|
||
+
|
||
+@item @samp{--mexport-symbols=FILE}
|
||
+Exporting symbols and their address into FILE as linker script.
|
||
+
|
||
+@item @samp{--m[no-]ex9}
|
||
+Disable/enable link-time EX9 relaxation.
|
||
+
|
||
+@item @samp{--mexport-ex9=FILE}
|
||
+Export the EX9 table after linking.
|
||
+
|
||
+@item @samp{--mimport-ex9=FILE}
|
||
+Import the Ex9 table for EX9 relaxation.
|
||
+
|
||
+@item @samp{--mupdate-ex9}
|
||
+Update the existing EX9 table.
|
||
+
|
||
+@item @samp{--mex9-limit=NUM}
|
||
+Maximum number of entries in the ex9 table.
|
||
+
|
||
+@item @samp{--mex9-loop-aware}
|
||
+Avoid generating the EX9 instruction inside the loop.
|
||
+
|
||
+@item @samp{--m[no-]ifc}
|
||
+Disable/enable the link-time IFC optimization.
|
||
+
|
||
+@item @samp{--mifc-loop-aware}
|
||
+Avoid generating the IFC instruction inside the loop.
|
||
+@end table
|
||
+
|
||
+@ifclear GENERIC
|
||
+@lowersections
|
||
+@end ifclear
|
||
+@end ifset
|
||
+
|
||
+@ifset NIOSII
|
||
+@ifclear GENERIC
|
||
+@raisesections
|
||
+@end ifclear
|
||
+
|
||
+@node Nios II
|
||
+@section @command{ld} and the Altera Nios II
|
||
+@cindex Nios II call relaxation
|
||
+@kindex --relax on Nios II
|
||
+
|
||
+Call and immediate jump instructions on Nios II processors are limited to
|
||
+transferring control to addresses in the same 256MB memory segment,
|
||
+which may result in @command{ld} giving
|
||
+@samp{relocation truncated to fit} errors with very large programs.
|
||
+The command-line option @option{--relax} enables the generation of
|
||
+trampolines that can access the entire 32-bit address space for calls
|
||
+outside the normal @code{call} and @code{jmpi} address range. These
|
||
+trampolines are inserted at section boundaries, so may not themselves
|
||
+be reachable if an input section and its associated call trampolines are
|
||
+larger than 256MB.
|
||
+
|
||
+The @option{--relax} option is enabled by default unless @option{-r}
|
||
+is also specified. You can disable trampoline generation by using the
|
||
+@option{--no-relax} linker option. You can also disable this optimization
|
||
+locally by using the @samp{set .noat} directive in assembly-language
|
||
+source files, as the linker-inserted trampolines use the @code{at}
|
||
+register as a temporary.
|
||
+
|
||
+Note that the linker @option{--relax} option is independent of assembler
|
||
+relaxation options, and that using the GNU assembler's @option{-relax-all}
|
||
+option interferes with the linker's more selective call instruction relaxation.
|
||
+
|
||
+@ifclear GENERIC
|
||
+@lowersections
|
||
+@end ifclear
|
||
+@end ifset
|
||
+
|
||
+@ifset POWERPC
|
||
+@ifclear GENERIC
|
||
+@raisesections
|
||
+@end ifclear
|
||
+
|
||
+@node PowerPC ELF32
|
||
+@section @command{ld} and PowerPC 32-bit ELF Support
|
||
+@cindex PowerPC long branches
|
||
+@kindex --relax on PowerPC
|
||
+Branches on PowerPC processors are limited to a signed 26-bit
|
||
+displacement, which may result in @command{ld} giving
|
||
+@samp{relocation truncated to fit} errors with very large programs.
|
||
+@samp{--relax} enables the generation of trampolines that can access
|
||
+the entire 32-bit address space. These trampolines are inserted at
|
||
+section boundaries, so may not themselves be reachable if an input
|
||
+section exceeds 33M in size. You may combine @samp{-r} and
|
||
+@samp{--relax} to add trampolines in a partial link. In that case
|
||
+both branches to undefined symbols and inter-section branches are also
|
||
+considered potentially out of range, and trampolines inserted.
|
||
+
|
||
+@cindex PowerPC ELF32 options
|
||
+@table @option
|
||
+@cindex PowerPC PLT
|
||
+@kindex --bss-plt
|
||
+@item --bss-plt
|
||
+Current PowerPC GCC accepts a @samp{-msecure-plt} option that
|
||
+generates code capable of using a newer PLT and GOT layout that has
|
||
+the security advantage of no executable section ever needing to be
|
||
+writable and no writable section ever being executable. PowerPC
|
||
+@command{ld} will generate this layout, including stubs to access the
|
||
+PLT, if all input files (including startup and static libraries) were
|
||
+compiled with @samp{-msecure-plt}. @samp{--bss-plt} forces the old
|
||
+BSS PLT (and GOT layout) which can give slightly better performance.
|
||
+
|
||
+@kindex --secure-plt
|
||
+@item --secure-plt
|
||
+@command{ld} will use the new PLT and GOT layout if it is linking new
|
||
+@samp{-fpic} or @samp{-fPIC} code, but does not do so automatically
|
||
+when linking non-PIC code. This option requests the new PLT and GOT
|
||
+layout. A warning will be given if some object file requires the old
|
||
+style BSS PLT.
|
||
+
|
||
+@cindex PowerPC GOT
|
||
+@kindex --sdata-got
|
||
+@item --sdata-got
|
||
+The new secure PLT and GOT are placed differently relative to other
|
||
+sections compared to older BSS PLT and GOT placement. The location of
|
||
+@code{.plt} must change because the new secure PLT is an initialized
|
||
+section while the old PLT is uninitialized. The reason for the
|
||
+@code{.got} change is more subtle: The new placement allows
|
||
+@code{.got} to be read-only in applications linked with
|
||
+@samp{-z relro -z now}. However, this placement means that
|
||
+@code{.sdata} cannot always be used in shared libraries, because the
|
||
+PowerPC ABI accesses @code{.sdata} in shared libraries from the GOT
|
||
+pointer. @samp{--sdata-got} forces the old GOT placement. PowerPC
|
||
+GCC doesn't use @code{.sdata} in shared libraries, so this option is
|
||
+really only useful for other compilers that may do so.
|
||
+
|
||
+@cindex PowerPC stub symbols
|
||
+@kindex --emit-stub-syms
|
||
+@item --emit-stub-syms
|
||
+This option causes @command{ld} to label linker stubs with a local
|
||
+symbol that encodes the stub type and destination.
|
||
+
|
||
+@cindex PowerPC TLS optimization
|
||
+@kindex --no-tls-optimize
|
||
+@item --no-tls-optimize
|
||
+PowerPC @command{ld} normally performs some optimization of code
|
||
+sequences used to access Thread-Local Storage. Use this option to
|
||
+disable the optimization.
|
||
+@end table
|
||
+
|
||
+@ifclear GENERIC
|
||
+@lowersections
|
||
+@end ifclear
|
||
+@end ifset
|
||
+
|
||
+@ifset POWERPC64
|
||
+@ifclear GENERIC
|
||
+@raisesections
|
||
+@end ifclear
|
||
+
|
||
+@node PowerPC64 ELF64
|
||
+@section @command{ld} and PowerPC64 64-bit ELF Support
|
||
+
|
||
+@cindex PowerPC64 ELF64 options
|
||
+@table @option
|
||
+@cindex PowerPC64 stub grouping
|
||
+@kindex --stub-group-size
|
||
+@item --stub-group-size
|
||
+Long branch stubs, PLT call stubs and TOC adjusting stubs are placed
|
||
+by @command{ld} in stub sections located between groups of input sections.
|
||
+@samp{--stub-group-size} specifies the maximum size of a group of input
|
||
+sections handled by one stub section. Since branch offsets are signed,
|
||
+a stub section may serve two groups of input sections, one group before
|
||
+the stub section, and one group after it. However, when using
|
||
+conditional branches that require stubs, it may be better (for branch
|
||
+prediction) that stub sections only serve one group of input sections.
|
||
+A negative value for @samp{N} chooses this scheme, ensuring that
|
||
+branches to stubs always use a negative offset. Two special values of
|
||
+@samp{N} are recognized, @samp{1} and @samp{-1}. These both instruct
|
||
+@command{ld} to automatically size input section groups for the branch types
|
||
+detected, with the same behaviour regarding stub placement as other
|
||
+positive or negative values of @samp{N} respectively.
|
||
+
|
||
+Note that @samp{--stub-group-size} does not split input sections. A
|
||
+single input section larger than the group size specified will of course
|
||
+create a larger group (of one section). If input sections are too
|
||
+large, it may not be possible for a branch to reach its stub.
|
||
+
|
||
+@cindex PowerPC64 stub symbols
|
||
+@kindex --emit-stub-syms
|
||
+@item --emit-stub-syms
|
||
+This option causes @command{ld} to label linker stubs with a local
|
||
+symbol that encodes the stub type and destination.
|
||
+
|
||
+@cindex PowerPC64 dot symbols
|
||
+@kindex --dotsyms
|
||
+@kindex --no-dotsyms
|
||
+@item --dotsyms
|
||
+@itemx --no-dotsyms
|
||
+These two options control how @command{ld} interprets version patterns
|
||
+in a version script. Older PowerPC64 compilers emitted both a
|
||
+function descriptor symbol with the same name as the function, and a
|
||
+code entry symbol with the name prefixed by a dot (@samp{.}). To
|
||
+properly version a function @samp{foo}, the version script thus needs
|
||
+to control both @samp{foo} and @samp{.foo}. The option
|
||
+@samp{--dotsyms}, on by default, automatically adds the required
|
||
+dot-prefixed patterns. Use @samp{--no-dotsyms} to disable this
|
||
+feature.
|
||
+
|
||
+@cindex PowerPC64 register save/restore functions
|
||
+@kindex --save-restore-funcs
|
||
+@kindex --no-save-restore-funcs
|
||
+@item --save-restore-funcs
|
||
+@itemx --no-save-restore-funcs
|
||
+These two options control whether PowerPC64 @command{ld} automatically
|
||
+provides out-of-line register save and restore functions used by
|
||
+@samp{-Os} code. The default is to provide any such referenced
|
||
+function for a normal final link, and to not do so for a relocatable
|
||
+link.
|
||
+
|
||
+@cindex PowerPC64 TLS optimization
|
||
+@kindex --no-tls-optimize
|
||
+@item --no-tls-optimize
|
||
+PowerPC64 @command{ld} normally performs some optimization of code
|
||
+sequences used to access Thread-Local Storage. Use this option to
|
||
+disable the optimization.
|
||
+
|
||
+@cindex PowerPC64 __tls_get_addr optimization
|
||
+@kindex --tls-get-addr-optimize
|
||
+@kindex --no-tls-get-addr-optimize
|
||
+@kindex --tls-get-addr-regsave
|
||
+@kindex --no-tls-get-addr-regsave
|
||
+@item --tls-get-addr-optimize
|
||
+@itemx --no-tls-get-addr-optimize
|
||
+These options control how PowerPC64 @command{ld} uses a special
|
||
+stub to call __tls_get_addr. PowerPC64 glibc 2.22 and later support
|
||
+an optimization that allows the second and subsequent calls to
|
||
+@code{__tls_get_addr} for a given symbol to be resolved by the special
|
||
+stub without calling in to glibc. By default the linker enables
|
||
+generation of the stub when glibc advertises the availability of
|
||
+__tls_get_addr_opt.
|
||
+Using @option{--tls-get-addr-optimize} with an older glibc won't do
|
||
+much besides slow down your applications, but may be useful if linking
|
||
+an application against an older glibc with the expectation that it
|
||
+will normally be used on systems having a newer glibc.
|
||
+@option{--tls-get-addr-regsave} forces generation of a stub that saves
|
||
+and restores volatile registers around the call into glibc. Normally,
|
||
+this is done when the linker detects a call to __tls_get_addr_desc.
|
||
+Such calls then go via the register saving stub to __tls_get_addr_opt.
|
||
+@option{--no-tls-get-addr-regsave} disables generation of the
|
||
+register saves.
|
||
+
|
||
+@cindex PowerPC64 OPD optimization
|
||
+@kindex --no-opd-optimize
|
||
+@item --no-opd-optimize
|
||
+PowerPC64 @command{ld} normally removes @code{.opd} section entries
|
||
+corresponding to deleted link-once functions, or functions removed by
|
||
+the action of @samp{--gc-sections} or linker script @code{/DISCARD/}.
|
||
+Use this option to disable @code{.opd} optimization.
|
||
+
|
||
+@cindex PowerPC64 OPD spacing
|
||
+@kindex --non-overlapping-opd
|
||
+@item --non-overlapping-opd
|
||
+Some PowerPC64 compilers have an option to generate compressed
|
||
+@code{.opd} entries spaced 16 bytes apart, overlapping the third word,
|
||
+the static chain pointer (unused in C) with the first word of the next
|
||
+entry. This option expands such entries to the full 24 bytes.
|
||
+
|
||
+@cindex PowerPC64 TOC optimization
|
||
+@kindex --no-toc-optimize
|
||
+@item --no-toc-optimize
|
||
+PowerPC64 @command{ld} normally removes unused @code{.toc} section
|
||
+entries. Such entries are detected by examining relocations that
|
||
+reference the TOC in code sections. A reloc in a deleted code section
|
||
+marks a TOC word as unneeded, while a reloc in a kept code section
|
||
+marks a TOC word as needed. Since the TOC may reference itself, TOC
|
||
+relocs are also examined. TOC words marked as both needed and
|
||
+unneeded will of course be kept. TOC words without any referencing
|
||
+reloc are assumed to be part of a multi-word entry, and are kept or
|
||
+discarded as per the nearest marked preceding word. This works
|
||
+reliably for compiler generated code, but may be incorrect if assembly
|
||
+code is used to insert TOC entries. Use this option to disable the
|
||
+optimization.
|
||
+
|
||
+@cindex PowerPC64 inline PLT call optimization
|
||
+@kindex --no-inline-optimize
|
||
+@item --no-inline-optimize
|
||
+PowerPC64 @command{ld} normally replaces inline PLT call sequences
|
||
+marked with @code{R_PPC64_PLTSEQ}, @code{R_PPC64_PLTCALL},
|
||
+@code{R_PPC64_PLT16_HA} and @code{R_PPC64_PLT16_LO_DS} relocations by
|
||
+a number of @code{nop}s and a direct call when the function is defined
|
||
+locally and can't be overridden by some other definition. This option
|
||
+disables that optimization.
|
||
+
|
||
+@cindex PowerPC64 multi-TOC
|
||
+@kindex --no-multi-toc
|
||
+@item --no-multi-toc
|
||
+If given any toc option besides @code{-mcmodel=medium} or
|
||
+@code{-mcmodel=large}, PowerPC64 GCC generates code for a TOC model
|
||
+where TOC
|
||
+entries are accessed with a 16-bit offset from r2. This limits the
|
||
+total TOC size to 64K. PowerPC64 @command{ld} extends this limit by
|
||
+grouping code sections such that each group uses less than 64K for its
|
||
+TOC entries, then inserts r2 adjusting stubs between inter-group
|
||
+calls. @command{ld} does not split apart input sections, so cannot
|
||
+help if a single input file has a @code{.toc} section that exceeds
|
||
+64K, most likely from linking multiple files with @command{ld -r}.
|
||
+Use this option to turn off this feature.
|
||
+
|
||
+@cindex PowerPC64 TOC sorting
|
||
+@kindex --no-toc-sort
|
||
+@item --no-toc-sort
|
||
+By default, @command{ld} sorts TOC sections so that those whose file
|
||
+happens to have a section called @code{.init} or @code{.fini} are
|
||
+placed first, followed by TOC sections referenced by code generated
|
||
+with PowerPC64 gcc's @code{-mcmodel=small}, and lastly TOC sections
|
||
+referenced only by code generated with PowerPC64 gcc's
|
||
+@code{-mcmodel=medium} or @code{-mcmodel=large} options. Doing this
|
||
+results in better TOC grouping for multi-TOC. Use this option to turn
|
||
+off this feature.
|
||
+
|
||
+@cindex PowerPC64 PLT stub alignment
|
||
+@kindex --plt-align
|
||
+@kindex --no-plt-align
|
||
+@item --plt-align
|
||
+@itemx --no-plt-align
|
||
+Use these options to control whether individual PLT call stubs are
|
||
+aligned to a 32-byte boundary, or to the specified power of two
|
||
+boundary when using @code{--plt-align=}. A negative value may be
|
||
+specified to pad PLT call stubs so that they do not cross the
|
||
+specified power of two boundary (or the minimum number of boundaries
|
||
+if a PLT stub is so large that it must cross a boundary). By default
|
||
+PLT call stubs are aligned to 32-byte boundaries.
|
||
+
|
||
+@cindex PowerPC64 PLT call stub static chain
|
||
+@kindex --plt-static-chain
|
||
+@kindex --no-plt-static-chain
|
||
+@item --plt-static-chain
|
||
+@itemx --no-plt-static-chain
|
||
+Use these options to control whether PLT call stubs load the static
|
||
+chain pointer (r11). @code{ld} defaults to not loading the static
|
||
+chain since there is never any need to do so on a PLT call.
|
||
+
|
||
+@cindex PowerPC64 PLT call stub thread safety
|
||
+@kindex --plt-thread-safe
|
||
+@kindex --no-plt-thread-safe
|
||
+@item --plt-thread-safe
|
||
+@itemx --no-plt-thread-safe
|
||
+With power7's weakly ordered memory model, it is possible when using
|
||
+lazy binding for ld.so to update a plt entry in one thread and have
|
||
+another thread see the individual plt entry words update in the wrong
|
||
+order, despite ld.so carefully writing in the correct order and using
|
||
+memory write barriers. To avoid this we need some sort of read
|
||
+barrier in the call stub, or use LD_BIND_NOW=1. By default, @code{ld}
|
||
+looks for calls to commonly used functions that create threads, and if
|
||
+seen, adds the necessary barriers. Use these options to change the
|
||
+default behaviour.
|
||
+
|
||
+@cindex PowerPC64 ELFv2 PLT localentry optimization
|
||
+@kindex --plt-localentry
|
||
+@kindex --no-plt-localentry
|
||
+@item --plt-localentry
|
||
+@itemx --no-localentry
|
||
+ELFv2 functions with localentry:0 are those with a single entry point,
|
||
+ie. global entry == local entry, and that have no requirement on r2
|
||
+(the TOC/GOT pointer) or r12, and guarantee r2 is unchanged on return.
|
||
+Such an external function can be called via the PLT without saving r2
|
||
+or restoring it on return, avoiding a common load-hit-store for small
|
||
+functions. The optimization is attractive, with up to 40% reduction
|
||
+in execution time for a small function, but can result in symbol
|
||
+interposition failures. Also, minor changes in a shared library,
|
||
+including system libraries, can cause a function that was localentry:0
|
||
+to become localentry:8. This will result in a dynamic loader
|
||
+complaint and failure to run. The option is experimental, use with
|
||
+care. @option{--no-plt-localentry} is the default.
|
||
+
|
||
+@cindex PowerPC64 Power10 stubs
|
||
+@kindex --power10-stubs
|
||
+@kindex --no-power10-stubs
|
||
+@item --power10-stubs
|
||
+@itemx --no-power10-stubs
|
||
+When PowerPC64 @command{ld} links input object files containing
|
||
+relocations used on power10 prefixed instructions it normally creates
|
||
+linkage stubs (PLT call and long branch) using power10 instructions
|
||
+for @code{@@notoc} PLT calls where @code{r2} is not known. The
|
||
+power10 notoc stubs are smaller and faster, so are preferred for
|
||
+power10. @option{--power10-stubs} and @option{--no-power10-stubs}
|
||
+allow you to override the linker's selection of stub instructions.
|
||
+@option{--power10-stubs=auto} allows the user to select the default
|
||
+auto mode.
|
||
+@end table
|
||
+
|
||
+@ifclear GENERIC
|
||
+@lowersections
|
||
+@end ifclear
|
||
+@end ifset
|
||
+
|
||
+@ifset S/390
|
||
+@ifclear GENERIC
|
||
+@raisesections
|
||
+@end ifclear
|
||
+
|
||
+@node S/390 ELF
|
||
+@section @command{ld} and S/390 ELF Support
|
||
+
|
||
+@cindex S/390 ELF options
|
||
+@table @option
|
||
+
|
||
+@cindex S/390
|
||
+@kindex --s390-pgste
|
||
+@item --s390-pgste
|
||
+This option marks the result file with a @code{PT_S390_PGSTE}
|
||
+segment. The Linux kernel is supposed to allocate 4k page tables for
|
||
+binaries marked that way.
|
||
+@end table
|
||
+
|
||
+@ifclear GENERIC
|
||
+@lowersections
|
||
+@end ifclear
|
||
+@end ifset
|
||
+
|
||
+@ifset SPU
|
||
+@ifclear GENERIC
|
||
+@raisesections
|
||
+@end ifclear
|
||
+
|
||
+@node SPU ELF
|
||
+@section @command{ld} and SPU ELF Support
|
||
+
|
||
+@cindex SPU ELF options
|
||
+@table @option
|
||
+
|
||
+@cindex SPU plugins
|
||
+@kindex --plugin
|
||
+@item --plugin
|
||
+This option marks an executable as a PIC plugin module.
|
||
+
|
||
+@cindex SPU overlays
|
||
+@kindex --no-overlays
|
||
+@item --no-overlays
|
||
+Normally, @command{ld} recognizes calls to functions within overlay
|
||
+regions, and redirects such calls to an overlay manager via a stub.
|
||
+@command{ld} also provides a built-in overlay manager. This option
|
||
+turns off all this special overlay handling.
|
||
+
|
||
+@cindex SPU overlay stub symbols
|
||
+@kindex --emit-stub-syms
|
||
+@item --emit-stub-syms
|
||
+This option causes @command{ld} to label overlay stubs with a local
|
||
+symbol that encodes the stub type and destination.
|
||
+
|
||
+@cindex SPU extra overlay stubs
|
||
+@kindex --extra-overlay-stubs
|
||
+@item --extra-overlay-stubs
|
||
+This option causes @command{ld} to add overlay call stubs on all
|
||
+function calls out of overlay regions. Normally stubs are not added
|
||
+on calls to non-overlay regions.
|
||
+
|
||
+@cindex SPU local store size
|
||
+@kindex --local-store=lo:hi
|
||
+@item --local-store=lo:hi
|
||
+@command{ld} usually checks that a final executable for SPU fits in
|
||
+the address range 0 to 256k. This option may be used to change the
|
||
+range. Disable the check entirely with @option{--local-store=0:0}.
|
||
+
|
||
+@cindex SPU
|
||
+@kindex --stack-analysis
|
||
+@item --stack-analysis
|
||
+SPU local store space is limited. Over-allocation of stack space
|
||
+unnecessarily limits space available for code and data, while
|
||
+under-allocation results in runtime failures. If given this option,
|
||
+@command{ld} will provide an estimate of maximum stack usage.
|
||
+@command{ld} does this by examining symbols in code sections to
|
||
+determine the extents of functions, and looking at function prologues
|
||
+for stack adjusting instructions. A call-graph is created by looking
|
||
+for relocations on branch instructions. The graph is then searched
|
||
+for the maximum stack usage path. Note that this analysis does not
|
||
+find calls made via function pointers, and does not handle recursion
|
||
+and other cycles in the call graph. Stack usage may be
|
||
+under-estimated if your code makes such calls. Also, stack usage for
|
||
+dynamic allocation, e.g. alloca, will not be detected. If a link map
|
||
+is requested, detailed information about each function's stack usage
|
||
+and calls will be given.
|
||
+
|
||
+@cindex SPU
|
||
+@kindex --emit-stack-syms
|
||
+@item --emit-stack-syms
|
||
+This option, if given along with @option{--stack-analysis} will result
|
||
+in @command{ld} emitting stack sizing symbols for each function.
|
||
+These take the form @code{__stack_<function_name>} for global
|
||
+functions, and @code{__stack_<number>_<function_name>} for static
|
||
+functions. @code{<number>} is the section id in hex. The value of
|
||
+such symbols is the stack requirement for the corresponding function.
|
||
+The symbol size will be zero, type @code{STT_NOTYPE}, binding
|
||
+@code{STB_LOCAL}, and section @code{SHN_ABS}.
|
||
+@end table
|
||
+
|
||
+@ifclear GENERIC
|
||
+@lowersections
|
||
+@end ifclear
|
||
+@end ifset
|
||
+
|
||
+@ifset TICOFF
|
||
+@ifclear GENERIC
|
||
+@raisesections
|
||
+@end ifclear
|
||
+
|
||
+@node TI COFF
|
||
+@section @command{ld}'s Support for Various TI COFF Versions
|
||
+@cindex TI COFF versions
|
||
+@kindex --format=@var{version}
|
||
+The @samp{--format} switch allows selection of one of the various
|
||
+TI COFF versions. The latest of this writing is 2; versions 0 and 1 are
|
||
+also supported. The TI COFF versions also vary in header byte-order
|
||
+format; @command{ld} will read any version or byte order, but the output
|
||
+header format depends on the default specified by the specific target.
|
||
+
|
||
+@ifclear GENERIC
|
||
+@lowersections
|
||
+@end ifclear
|
||
+@end ifset
|
||
+
|
||
+@ifset WIN32
|
||
+@ifclear GENERIC
|
||
+@raisesections
|
||
+@end ifclear
|
||
+
|
||
+@node WIN32
|
||
+@section @command{ld} and WIN32 (cygwin/mingw)
|
||
+
|
||
+This section describes some of the win32 specific @command{ld} issues.
|
||
+See @ref{Options,,Command-line Options} for detailed description of the
|
||
+command-line options mentioned here.
|
||
+
|
||
+@table @emph
|
||
+@cindex import libraries
|
||
+@item import libraries
|
||
+The standard Windows linker creates and uses so-called import
|
||
+libraries, which contains information for linking to dll's. They are
|
||
+regular static archives and are handled as any other static
|
||
+archive. The cygwin and mingw ports of @command{ld} have specific
|
||
+support for creating such libraries provided with the
|
||
+@samp{--out-implib} command-line option.
|
||
+
|
||
+@item Resource only DLLs
|
||
+It is possible to create a DLL that only contains resources, ie just a
|
||
+@samp{.rsrc} section, but in order to do so a custom linker script
|
||
+must be used. This is because the built-in default linker scripts
|
||
+will always create @samp{.text} and @samp{.idata} sections, even if
|
||
+there is no input to go into them.
|
||
+
|
||
+The script should look like this, although the @code{OUTPUT_FORMAT}
|
||
+should be changed to match the desired format.
|
||
+
|
||
+@example
|
||
+OUTPUT_FORMAT(pei-i386)
|
||
+SECTIONS
|
||
+@{
|
||
+ . = SIZEOF_HEADERS;
|
||
+ . = ALIGN(__section_alignment__);
|
||
+ .rsrc __image_base__ + __section_alignment__ : ALIGN(4)
|
||
+ @{
|
||
+ KEEP (*(.rsrc))
|
||
+ KEEP (*(.rsrc$*))
|
||
+ @}
|
||
+ /DISCARD/ : @{ *(*) @}
|
||
+@}
|
||
+@end example
|
||
+
|
||
+With this script saved to a file called, eg @file{rsrc.ld}, a command
|
||
+line like this can be used to create the resource only DLL
|
||
+@file{rsrc.dll} from an input file called @file{rsrc.o}:
|
||
+
|
||
+@smallexample
|
||
+ld -dll --subsystem windows -e 0 -s rsrc.o -o rsrc.dll -T rsrc.ld
|
||
+@end smallexample
|
||
+
|
||
+@item exporting DLL symbols
|
||
+@cindex exporting DLL symbols
|
||
+The cygwin/mingw @command{ld} has several ways to export symbols for dll's.
|
||
+
|
||
+@table @emph
|
||
+@item using auto-export functionality
|
||
+@cindex using auto-export functionality
|
||
+By default @command{ld} exports symbols with the auto-export functionality,
|
||
+which is controlled by the following command-line options:
|
||
+
|
||
+@itemize
|
||
+@item --export-all-symbols [This is the default]
|
||
+@item --exclude-symbols
|
||
+@item --exclude-libs
|
||
+@item --exclude-modules-for-implib
|
||
+@item --version-script
|
||
+@end itemize
|
||
+
|
||
+When auto-export is in operation, @command{ld} will export all the non-local
|
||
+(global and common) symbols it finds in a DLL, with the exception of a few
|
||
+symbols known to belong to the system's runtime and libraries. As it will
|
||
+often not be desirable to export all of a DLL's symbols, which may include
|
||
+private functions that are not part of any public interface, the command-line
|
||
+options listed above may be used to filter symbols out from the list for
|
||
+exporting. The @samp{--output-def} option can be used in order to see the
|
||
+final list of exported symbols with all exclusions taken into effect.
|
||
+
|
||
+If @samp{--export-all-symbols} is not given explicitly on the
|
||
+command line, then the default auto-export behavior will be @emph{disabled}
|
||
+if either of the following are true:
|
||
+
|
||
+@itemize
|
||
+@item A DEF file is used.
|
||
+@item Any symbol in any object file was marked with the __declspec(dllexport) attribute.
|
||
+@end itemize
|
||
+
|
||
+@item using a DEF file
|
||
+@cindex using a DEF file
|
||
+Another way of exporting symbols is using a DEF file. A DEF file is
|
||
+an ASCII file containing definitions of symbols which should be
|
||
+exported when a dll is created. Usually it is named @samp{<dll
|
||
+name>.def} and is added as any other object file to the linker's
|
||
+command line. The file's name must end in @samp{.def} or @samp{.DEF}.
|
||
+
|
||
+@example
|
||
+gcc -o <output> <objectfiles> <dll name>.def
|
||
+@end example
|
||
+
|
||
+Using a DEF file turns off the normal auto-export behavior, unless the
|
||
+@samp{--export-all-symbols} option is also used.
|
||
+
|
||
+Here is an example of a DEF file for a shared library called @samp{xyz.dll}:
|
||
+
|
||
+@example
|
||
+LIBRARY "xyz.dll" BASE=0x20000000
|
||
+
|
||
+EXPORTS
|
||
+foo
|
||
+bar
|
||
+_bar = bar
|
||
+another_foo = abc.dll.afoo
|
||
+var1 DATA
|
||
+doo = foo == foo2
|
||
+eoo DATA == var1
|
||
+@end example
|
||
+
|
||
+This example defines a DLL with a non-default base address and seven
|
||
+symbols in the export table. The third exported symbol @code{_bar} is an
|
||
+alias for the second. The fourth symbol, @code{another_foo} is resolved
|
||
+by "forwarding" to another module and treating it as an alias for
|
||
+@code{afoo} exported from the DLL @samp{abc.dll}. The final symbol
|
||
+@code{var1} is declared to be a data object. The @samp{doo} symbol in
|
||
+export library is an alias of @samp{foo}, which gets the string name
|
||
+in export table @samp{foo2}. The @samp{eoo} symbol is an data export
|
||
+symbol, which gets in export table the name @samp{var1}.
|
||
+
|
||
+The optional @code{LIBRARY <name>} command indicates the @emph{internal}
|
||
+name of the output DLL. If @samp{<name>} does not include a suffix,
|
||
+the default library suffix, @samp{.DLL} is appended.
|
||
+
|
||
+When the .DEF file is used to build an application, rather than a
|
||
+library, the @code{NAME <name>} command should be used instead of
|
||
+@code{LIBRARY}. If @samp{<name>} does not include a suffix, the default
|
||
+executable suffix, @samp{.EXE} is appended.
|
||
+
|
||
+With either @code{LIBRARY <name>} or @code{NAME <name>} the optional
|
||
+specification @code{BASE = <number>} may be used to specify a
|
||
+non-default base address for the image.
|
||
+
|
||
+If neither @code{LIBRARY <name>} nor @code{NAME <name>} is specified,
|
||
+or they specify an empty string, the internal name is the same as the
|
||
+filename specified on the command line.
|
||
+
|
||
+The complete specification of an export symbol is:
|
||
+
|
||
+@example
|
||
+EXPORTS
|
||
+ ( ( ( <name1> [ = <name2> ] )
|
||
+ | ( <name1> = <module-name> . <external-name>))
|
||
+ [ @@ <integer> ] [NONAME] [DATA] [CONSTANT] [PRIVATE] [== <name3>] ) *
|
||
+@end example
|
||
+
|
||
+Declares @samp{<name1>} as an exported symbol from the DLL, or declares
|
||
+@samp{<name1>} as an exported alias for @samp{<name2>}; or declares
|
||
+@samp{<name1>} as a "forward" alias for the symbol
|
||
+@samp{<external-name>} in the DLL @samp{<module-name>}.
|
||
+Optionally, the symbol may be exported by the specified ordinal
|
||
+@samp{<integer>} alias. The optional @samp{<name3>} is the to be used
|
||
+string in import/export table for the symbol.
|
||
+
|
||
+The optional keywords that follow the declaration indicate:
|
||
+
|
||
+@code{NONAME}: Do not put the symbol name in the DLL's export table. It
|
||
+will still be exported by its ordinal alias (either the value specified
|
||
+by the .def specification or, otherwise, the value assigned by the
|
||
+linker). The symbol name, however, does remain visible in the import
|
||
+library (if any), unless @code{PRIVATE} is also specified.
|
||
+
|
||
+@code{DATA}: The symbol is a variable or object, rather than a function.
|
||
+The import lib will export only an indirect reference to @code{foo} as
|
||
+the symbol @code{_imp__foo} (ie, @code{foo} must be resolved as
|
||
+@code{*_imp__foo}).
|
||
+
|
||
+@code{CONSTANT}: Like @code{DATA}, but put the undecorated @code{foo} as
|
||
+well as @code{_imp__foo} into the import library. Both refer to the
|
||
+read-only import address table's pointer to the variable, not to the
|
||
+variable itself. This can be dangerous. If the user code fails to add
|
||
+the @code{dllimport} attribute and also fails to explicitly add the
|
||
+extra indirection that the use of the attribute enforces, the
|
||
+application will behave unexpectedly.
|
||
+
|
||
+@code{PRIVATE}: Put the symbol in the DLL's export table, but do not put
|
||
+it into the static import library used to resolve imports at link time. The
|
||
+symbol can still be imported using the @code{LoadLibrary/GetProcAddress}
|
||
+API at runtime or by using the GNU ld extension of linking directly to
|
||
+the DLL without an import library.
|
||
+
|
||
+See ld/deffilep.y in the binutils sources for the full specification of
|
||
+other DEF file statements
|
||
+
|
||
+@cindex creating a DEF file
|
||
+While linking a shared dll, @command{ld} is able to create a DEF file
|
||
+with the @samp{--output-def <file>} command-line option.
|
||
+
|
||
+@item Using decorations
|
||
+@cindex Using decorations
|
||
+Another way of marking symbols for export is to modify the source code
|
||
+itself, so that when building the DLL each symbol to be exported is
|
||
+declared as:
|
||
+
|
||
+@example
|
||
+__declspec(dllexport) int a_variable
|
||
+__declspec(dllexport) void a_function(int with_args)
|
||
+@end example
|
||
+
|
||
+All such symbols will be exported from the DLL. If, however,
|
||
+any of the object files in the DLL contain symbols decorated in
|
||
+this way, then the normal auto-export behavior is disabled, unless
|
||
+the @samp{--export-all-symbols} option is also used.
|
||
+
|
||
+Note that object files that wish to access these symbols must @emph{not}
|
||
+decorate them with dllexport. Instead, they should use dllimport,
|
||
+instead:
|
||
+
|
||
+@example
|
||
+__declspec(dllimport) int a_variable
|
||
+__declspec(dllimport) void a_function(int with_args)
|
||
+@end example
|
||
+
|
||
+This complicates the structure of library header files, because
|
||
+when included by the library itself the header must declare the
|
||
+variables and functions as dllexport, but when included by client
|
||
+code the header must declare them as dllimport. There are a number
|
||
+of idioms that are typically used to do this; often client code can
|
||
+omit the __declspec() declaration completely. See
|
||
+@samp{--enable-auto-import} and @samp{automatic data imports} for more
|
||
+information.
|
||
+@end table
|
||
+
|
||
+@cindex automatic data imports
|
||
+@item automatic data imports
|
||
+The standard Windows dll format supports data imports from dlls only
|
||
+by adding special decorations (dllimport/dllexport), which let the
|
||
+compiler produce specific assembler instructions to deal with this
|
||
+issue. This increases the effort necessary to port existing Un*x
|
||
+code to these platforms, especially for large
|
||
+c++ libraries and applications. The auto-import feature, which was
|
||
+initially provided by Paul Sokolovsky, allows one to omit the
|
||
+decorations to achieve a behavior that conforms to that on POSIX/Un*x
|
||
+platforms. This feature is enabled with the @samp{--enable-auto-import}
|
||
+command-line option, although it is enabled by default on cygwin/mingw.
|
||
+The @samp{--enable-auto-import} option itself now serves mainly to
|
||
+suppress any warnings that are ordinarily emitted when linked objects
|
||
+trigger the feature's use.
|
||
+
|
||
+auto-import of variables does not always work flawlessly without
|
||
+additional assistance. Sometimes, you will see this message
|
||
+
|
||
+"variable '<var>' can't be auto-imported. Please read the
|
||
+documentation for ld's @code{--enable-auto-import} for details."
|
||
+
|
||
+The @samp{--enable-auto-import} documentation explains why this error
|
||
+occurs, and several methods that can be used to overcome this difficulty.
|
||
+One of these methods is the @emph{runtime pseudo-relocs} feature, described
|
||
+below.
|
||
+
|
||
+@cindex runtime pseudo-relocation
|
||
+For complex variables imported from DLLs (such as structs or classes),
|
||
+object files typically contain a base address for the variable and an
|
||
+offset (@emph{addend}) within the variable--to specify a particular
|
||
+field or public member, for instance. Unfortunately, the runtime loader used
|
||
+in win32 environments is incapable of fixing these references at runtime
|
||
+without the additional information supplied by dllimport/dllexport decorations.
|
||
+The standard auto-import feature described above is unable to resolve these
|
||
+references.
|
||
+
|
||
+The @samp{--enable-runtime-pseudo-relocs} switch allows these references to
|
||
+be resolved without error, while leaving the task of adjusting the references
|
||
+themselves (with their non-zero addends) to specialized code provided by the
|
||
+runtime environment. Recent versions of the cygwin and mingw environments and
|
||
+compilers provide this runtime support; older versions do not. However, the
|
||
+support is only necessary on the developer's platform; the compiled result will
|
||
+run without error on an older system.
|
||
+
|
||
+@samp{--enable-runtime-pseudo-relocs} is not the default; it must be explicitly
|
||
+enabled as needed.
|
||
+
|
||
+@cindex direct linking to a dll
|
||
+@item direct linking to a dll
|
||
+The cygwin/mingw ports of @command{ld} support the direct linking,
|
||
+including data symbols, to a dll without the usage of any import
|
||
+libraries. This is much faster and uses much less memory than does the
|
||
+traditional import library method, especially when linking large
|
||
+libraries or applications. When @command{ld} creates an import lib, each
|
||
+function or variable exported from the dll is stored in its own bfd, even
|
||
+though a single bfd could contain many exports. The overhead involved in
|
||
+storing, loading, and processing so many bfd's is quite large, and explains the
|
||
+tremendous time, memory, and storage needed to link against particularly
|
||
+large or complex libraries when using import libs.
|
||
+
|
||
+Linking directly to a dll uses no extra command-line switches other than
|
||
+@samp{-L} and @samp{-l}, because @command{ld} already searches for a number
|
||
+of names to match each library. All that is needed from the developer's
|
||
+perspective is an understanding of this search, in order to force ld to
|
||
+select the dll instead of an import library.
|
||
+
|
||
+
|
||
+For instance, when ld is called with the argument @samp{-lxxx} it will attempt
|
||
+to find, in the first directory of its search path,
|
||
+
|
||
+@example
|
||
+libxxx.dll.a
|
||
+xxx.dll.a
|
||
+libxxx.a
|
||
+xxx.lib
|
||
+libxxx.lib
|
||
+cygxxx.dll (*)
|
||
+libxxx.dll
|
||
+xxx.dll
|
||
+@end example
|
||
+
|
||
+before moving on to the next directory in the search path.
|
||
+
|
||
+(*) Actually, this is not @samp{cygxxx.dll} but in fact is @samp{<prefix>xxx.dll},
|
||
+where @samp{<prefix>} is set by the @command{ld} option
|
||
+@samp{--dll-search-prefix=<prefix>}. In the case of cygwin, the standard gcc spec
|
||
+file includes @samp{--dll-search-prefix=cyg}, so in effect we actually search for
|
||
+@samp{cygxxx.dll}.
|
||
+
|
||
+Other win32-based unix environments, such as mingw or pw32, may use other
|
||
+@samp{<prefix>}es, although at present only cygwin makes use of this feature. It
|
||
+was originally intended to help avoid name conflicts among dll's built for the
|
||
+various win32/un*x environments, so that (for example) two versions of a zlib dll
|
||
+could coexist on the same machine.
|
||
+
|
||
+The generic cygwin/mingw path layout uses a @samp{bin} directory for
|
||
+applications and dll's and a @samp{lib} directory for the import
|
||
+libraries (using cygwin nomenclature):
|
||
+
|
||
+@example
|
||
+bin/
|
||
+ cygxxx.dll
|
||
+lib/
|
||
+ libxxx.dll.a (in case of dll's)
|
||
+ libxxx.a (in case of static archive)
|
||
+@end example
|
||
+
|
||
+Linking directly to a dll without using the import library can be
|
||
+done two ways:
|
||
+
|
||
+1. Use the dll directly by adding the @samp{bin} path to the link line
|
||
+@example
|
||
+gcc -Wl,-verbose -o a.exe -L../bin/ -lxxx
|
||
+@end example
|
||
+
|
||
+However, as the dll's often have version numbers appended to their names
|
||
+(@samp{cygncurses-5.dll}) this will often fail, unless one specifies
|
||
+@samp{-L../bin -lncurses-5} to include the version. Import libs are generally
|
||
+not versioned, and do not have this difficulty.
|
||
+
|
||
+2. Create a symbolic link from the dll to a file in the @samp{lib}
|
||
+directory according to the above mentioned search pattern. This
|
||
+should be used to avoid unwanted changes in the tools needed for
|
||
+making the app/dll.
|
||
+
|
||
+@example
|
||
+ln -s bin/cygxxx.dll lib/[cyg|lib|]xxx.dll[.a]
|
||
+@end example
|
||
+
|
||
+Then you can link without any make environment changes.
|
||
+
|
||
+@example
|
||
+gcc -Wl,-verbose -o a.exe -L../lib/ -lxxx
|
||
+@end example
|
||
+
|
||
+This technique also avoids the version number problems, because the following is
|
||
+perfectly legal
|
||
+
|
||
+@example
|
||
+bin/
|
||
+ cygxxx-5.dll
|
||
+lib/
|
||
+ libxxx.dll.a -> ../bin/cygxxx-5.dll
|
||
+@end example
|
||
+
|
||
+Linking directly to a dll without using an import lib will work
|
||
+even when auto-import features are exercised, and even when
|
||
+@samp{--enable-runtime-pseudo-relocs} is used.
|
||
+
|
||
+Given the improvements in speed and memory usage, one might justifiably
|
||
+wonder why import libraries are used at all. There are three reasons:
|
||
+
|
||
+1. Until recently, the link-directly-to-dll functionality did @emph{not}
|
||
+work with auto-imported data.
|
||
+
|
||
+2. Sometimes it is necessary to include pure static objects within the
|
||
+import library (which otherwise contains only bfd's for indirection
|
||
+symbols that point to the exports of a dll). Again, the import lib
|
||
+for the cygwin kernel makes use of this ability, and it is not
|
||
+possible to do this without an import lib.
|
||
+
|
||
+3. Symbol aliases can only be resolved using an import lib. This is
|
||
+critical when linking against OS-supplied dll's (eg, the win32 API)
|
||
+in which symbols are usually exported as undecorated aliases of their
|
||
+stdcall-decorated assembly names.
|
||
+
|
||
+So, import libs are not going away. But the ability to replace
|
||
+true import libs with a simple symbolic link to (or a copy of)
|
||
+a dll, in many cases, is a useful addition to the suite of tools
|
||
+binutils makes available to the win32 developer. Given the
|
||
+massive improvements in memory requirements during linking, storage
|
||
+requirements, and linking speed, we expect that many developers
|
||
+will soon begin to use this feature whenever possible.
|
||
+
|
||
+@item symbol aliasing
|
||
+@table @emph
|
||
+@item adding additional names
|
||
+Sometimes, it is useful to export symbols with additional names.
|
||
+A symbol @samp{foo} will be exported as @samp{foo}, but it can also be
|
||
+exported as @samp{_foo} by using special directives in the DEF file
|
||
+when creating the dll. This will affect also the optional created
|
||
+import library. Consider the following DEF file:
|
||
+
|
||
+@example
|
||
+LIBRARY "xyz.dll" BASE=0x61000000
|
||
+
|
||
+EXPORTS
|
||
+foo
|
||
+_foo = foo
|
||
+@end example
|
||
+
|
||
+The line @samp{_foo = foo} maps the symbol @samp{foo} to @samp{_foo}.
|
||
+
|
||
+Another method for creating a symbol alias is to create it in the
|
||
+source code using the "weak" attribute:
|
||
+
|
||
+@example
|
||
+void foo () @{ /* Do something. */; @}
|
||
+void _foo () __attribute__ ((weak, alias ("foo")));
|
||
+@end example
|
||
+
|
||
+See the gcc manual for more information about attributes and weak
|
||
+symbols.
|
||
+
|
||
+@item renaming symbols
|
||
+Sometimes it is useful to rename exports. For instance, the cygwin
|
||
+kernel does this regularly. A symbol @samp{_foo} can be exported as
|
||
+@samp{foo} but not as @samp{_foo} by using special directives in the
|
||
+DEF file. (This will also affect the import library, if it is
|
||
+created). In the following example:
|
||
+
|
||
+@example
|
||
+LIBRARY "xyz.dll" BASE=0x61000000
|
||
+
|
||
+EXPORTS
|
||
+_foo = foo
|
||
+@end example
|
||
+
|
||
+The line @samp{_foo = foo} maps the exported symbol @samp{foo} to
|
||
+@samp{_foo}.
|
||
+@end table
|
||
+
|
||
+Note: using a DEF file disables the default auto-export behavior,
|
||
+unless the @samp{--export-all-symbols} command-line option is used.
|
||
+If, however, you are trying to rename symbols, then you should list
|
||
+@emph{all} desired exports in the DEF file, including the symbols
|
||
+that are not being renamed, and do @emph{not} use the
|
||
+@samp{--export-all-symbols} option. If you list only the
|
||
+renamed symbols in the DEF file, and use @samp{--export-all-symbols}
|
||
+to handle the other symbols, then the both the new names @emph{and}
|
||
+the original names for the renamed symbols will be exported.
|
||
+In effect, you'd be aliasing those symbols, not renaming them,
|
||
+which is probably not what you wanted.
|
||
+
|
||
+@cindex weak externals
|
||
+@item weak externals
|
||
+The Windows object format, PE, specifies a form of weak symbols called
|
||
+weak externals. When a weak symbol is linked and the symbol is not
|
||
+defined, the weak symbol becomes an alias for some other symbol. There
|
||
+are three variants of weak externals:
|
||
+@itemize
|
||
+@item Definition is searched for in objects and libraries, historically
|
||
+called lazy externals.
|
||
+@item Definition is searched for only in other objects, not in libraries.
|
||
+This form is not presently implemented.
|
||
+@item No search; the symbol is an alias. This form is not presently
|
||
+implemented.
|
||
+@end itemize
|
||
+As a GNU extension, weak symbols that do not specify an alternate symbol
|
||
+are supported. If the symbol is undefined when linking, the symbol
|
||
+uses a default value.
|
||
+
|
||
+@cindex aligned common symbols
|
||
+@item aligned common symbols
|
||
+As a GNU extension to the PE file format, it is possible to specify the
|
||
+desired alignment for a common symbol. This information is conveyed from
|
||
+the assembler or compiler to the linker by means of GNU-specific commands
|
||
+carried in the object file's @samp{.drectve} section, which are recognized
|
||
+by @command{ld} and respected when laying out the common symbols. Native
|
||
+tools will be able to process object files employing this GNU extension,
|
||
+but will fail to respect the alignment instructions, and may issue noisy
|
||
+warnings about unknown linker directives.
|
||
+
|
||
+@end table
|
||
+
|
||
+@ifclear GENERIC
|
||
+@lowersections
|
||
+@end ifclear
|
||
+@end ifset
|
||
+
|
||
+@ifset XTENSA
|
||
+@ifclear GENERIC
|
||
+@raisesections
|
||
+@end ifclear
|
||
+
|
||
+@node Xtensa
|
||
+@section @code{ld} and Xtensa Processors
|
||
+
|
||
+@cindex Xtensa processors
|
||
+The default @command{ld} behavior for Xtensa processors is to interpret
|
||
+@code{SECTIONS} commands so that lists of explicitly named sections in a
|
||
+specification with a wildcard file will be interleaved when necessary to
|
||
+keep literal pools within the range of PC-relative load offsets. For
|
||
+example, with the command:
|
||
+
|
||
+@smallexample
|
||
+SECTIONS
|
||
+@{
|
||
+ .text : @{
|
||
+ *(.literal .text)
|
||
+ @}
|
||
+@}
|
||
+@end smallexample
|
||
+
|
||
+@noindent
|
||
+@command{ld} may interleave some of the @code{.literal}
|
||
+and @code{.text} sections from different object files to ensure that the
|
||
+literal pools are within the range of PC-relative load offsets. A valid
|
||
+interleaving might place the @code{.literal} sections from an initial
|
||
+group of files followed by the @code{.text} sections of that group of
|
||
+files. Then, the @code{.literal} sections from the rest of the files
|
||
+and the @code{.text} sections from the rest of the files would follow.
|
||
+
|
||
+@cindex @option{--relax} on Xtensa
|
||
+@cindex relaxing on Xtensa
|
||
+Relaxation is enabled by default for the Xtensa version of @command{ld} and
|
||
+provides two important link-time optimizations. The first optimization
|
||
+is to combine identical literal values to reduce code size. A redundant
|
||
+literal will be removed and all the @code{L32R} instructions that use it
|
||
+will be changed to reference an identical literal, as long as the
|
||
+location of the replacement literal is within the offset range of all
|
||
+the @code{L32R} instructions. The second optimization is to remove
|
||
+unnecessary overhead from assembler-generated ``longcall'' sequences of
|
||
+@code{L32R}/@code{CALLX@var{n}} when the target functions are within
|
||
+range of direct @code{CALL@var{n}} instructions.
|
||
+
|
||
+For each of these cases where an indirect call sequence can be optimized
|
||
+to a direct call, the linker will change the @code{CALLX@var{n}}
|
||
+instruction to a @code{CALL@var{n}} instruction, remove the @code{L32R}
|
||
+instruction, and remove the literal referenced by the @code{L32R}
|
||
+instruction if it is not used for anything else. Removing the
|
||
+@code{L32R} instruction always reduces code size but can potentially
|
||
+hurt performance by changing the alignment of subsequent branch targets.
|
||
+By default, the linker will always preserve alignments, either by
|
||
+switching some instructions between 24-bit encodings and the equivalent
|
||
+density instructions or by inserting a no-op in place of the @code{L32R}
|
||
+instruction that was removed. If code size is more important than
|
||
+performance, the @option{--size-opt} option can be used to prevent the
|
||
+linker from widening density instructions or inserting no-ops, except in
|
||
+a few cases where no-ops are required for correctness.
|
||
+
|
||
+The following Xtensa-specific command-line options can be used to
|
||
+control the linker:
|
||
+
|
||
+@cindex Xtensa options
|
||
+@table @option
|
||
+@item --size-opt
|
||
+When optimizing indirect calls to direct calls, optimize for code size
|
||
+more than performance. With this option, the linker will not insert
|
||
+no-ops or widen density instructions to preserve branch target
|
||
+alignment. There may still be some cases where no-ops are required to
|
||
+preserve the correctness of the code.
|
||
+
|
||
+@item --abi-windowed
|
||
+@itemx --abi-call0
|
||
+Choose ABI for the output object and for the generated PLT code.
|
||
+PLT code inserted by the linker must match ABI of the output object
|
||
+because windowed and call0 ABI use incompatible function call
|
||
+conventions.
|
||
+Default ABI is chosen by the ABI tag in the @code{.xtensa.info} section
|
||
+of the first input object.
|
||
+A warning is issued if ABI tags of input objects do not match each other
|
||
+or the chosen output object ABI.
|
||
+@end table
|
||
+
|
||
+@ifclear GENERIC
|
||
+@lowersections
|
||
+@end ifclear
|
||
+@end ifset
|
||
+
|
||
+@ifclear SingleFormat
|
||
+@node BFD
|
||
+@chapter BFD
|
||
+
|
||
+@cindex back end
|
||
+@cindex object file management
|
||
+@cindex object formats available
|
||
+@kindex objdump -i
|
||
+The linker accesses object and archive files using the BFD libraries.
|
||
+These libraries allow the linker to use the same routines to operate on
|
||
+object files whatever the object file format. A different object file
|
||
+format can be supported simply by creating a new BFD back end and adding
|
||
+it to the library. To conserve runtime memory, however, the linker and
|
||
+associated tools are usually configured to support only a subset of the
|
||
+object file formats available. You can use @code{objdump -i}
|
||
+(@pxref{objdump,,objdump,binutils.info,The GNU Binary Utilities}) to
|
||
+list all the formats available for your configuration.
|
||
+
|
||
+@cindex BFD requirements
|
||
+@cindex requirements for BFD
|
||
+As with most implementations, BFD is a compromise between
|
||
+several conflicting requirements. The major factor influencing
|
||
+BFD design was efficiency: any time used converting between
|
||
+formats is time which would not have been spent had BFD not
|
||
+been involved. This is partly offset by abstraction payback; since
|
||
+BFD simplifies applications and back ends, more time and care
|
||
+may be spent optimizing algorithms for a greater speed.
|
||
+
|
||
+One minor artifact of the BFD solution which you should bear in
|
||
+mind is the potential for information loss. There are two places where
|
||
+useful information can be lost using the BFD mechanism: during
|
||
+conversion and during output. @xref{BFD information loss}.
|
||
+
|
||
+@menu
|
||
+* BFD outline:: How it works: an outline of BFD
|
||
+@end menu
|
||
+
|
||
+@node BFD outline
|
||
+@section How It Works: An Outline of BFD
|
||
+@cindex opening object files
|
||
+@include bfdsumm.texi
|
||
+@end ifclear
|
||
+
|
||
+@node Reporting Bugs
|
||
+@chapter Reporting Bugs
|
||
+@cindex bugs in @command{ld}
|
||
+@cindex reporting bugs in @command{ld}
|
||
+
|
||
+Your bug reports play an essential role in making @command{ld} reliable.
|
||
+
|
||
+Reporting a bug may help you by bringing a solution to your problem, or
|
||
+it may not. But in any case the principal function of a bug report is
|
||
+to help the entire community by making the next version of @command{ld}
|
||
+work better. Bug reports are your contribution to the maintenance of
|
||
+@command{ld}.
|
||
+
|
||
+In order for a bug report to serve its purpose, you must include the
|
||
+information that enables us to fix the bug.
|
||
+
|
||
+@menu
|
||
+* Bug Criteria:: Have you found a bug?
|
||
+* Bug Reporting:: How to report bugs
|
||
+@end menu
|
||
+
|
||
+@node Bug Criteria
|
||
+@section Have You Found a Bug?
|
||
+@cindex bug criteria
|
||
+
|
||
+If you are not sure whether you have found a bug, here are some guidelines:
|
||
+
|
||
+@itemize @bullet
|
||
+@cindex fatal signal
|
||
+@cindex linker crash
|
||
+@cindex crash of linker
|
||
+@item
|
||
+If the linker gets a fatal signal, for any input whatever, that is a
|
||
+@command{ld} bug. Reliable linkers never crash.
|
||
+
|
||
+@cindex error on valid input
|
||
+@item
|
||
+If @command{ld} produces an error message for valid input, that is a bug.
|
||
+
|
||
+@cindex invalid input
|
||
+@item
|
||
+If @command{ld} does not produce an error message for invalid input, that
|
||
+may be a bug. In the general case, the linker can not verify that
|
||
+object files are correct.
|
||
+
|
||
+@item
|
||
+If you are an experienced user of linkers, your suggestions for
|
||
+improvement of @command{ld} are welcome in any case.
|
||
+@end itemize
|
||
+
|
||
+@node Bug Reporting
|
||
+@section How to Report Bugs
|
||
+@cindex bug reports
|
||
+@cindex @command{ld} bugs, reporting
|
||
+
|
||
+A number of companies and individuals offer support for @sc{gnu}
|
||
+products. If you obtained @command{ld} from a support organization, we
|
||
+recommend you contact that organization first.
|
||
+
|
||
+You can find contact information for many support companies and
|
||
+individuals in the file @file{etc/SERVICE} in the @sc{gnu} Emacs
|
||
+distribution.
|
||
+
|
||
+@ifset BUGURL
|
||
+Otherwise, send bug reports for @command{ld} to
|
||
+@value{BUGURL}.
|
||
+@end ifset
|
||
+
|
||
+The fundamental principle of reporting bugs usefully is this:
|
||
+@strong{report all the facts}. If you are not sure whether to state a
|
||
+fact or leave it out, state it!
|
||
+
|
||
+Often people omit facts because they think they know what causes the
|
||
+problem and assume that some details do not matter. Thus, you might
|
||
+assume that the name of a symbol you use in an example does not
|
||
+matter. Well, probably it does not, but one cannot be sure. Perhaps
|
||
+the bug is a stray memory reference which happens to fetch from the
|
||
+location where that name is stored in memory; perhaps, if the name
|
||
+were different, the contents of that location would fool the linker
|
||
+into doing the right thing despite the bug. Play it safe and give a
|
||
+specific, complete example. That is the easiest thing for you to do,
|
||
+and the most helpful.
|
||
+
|
||
+Keep in mind that the purpose of a bug report is to enable us to fix
|
||
+the bug if it is new to us. Therefore, always write your bug reports
|
||
+on the assumption that the bug has not been reported previously.
|
||
+
|
||
+Sometimes people give a few sketchy facts and ask, ``Does this ring a
|
||
+bell?'' This cannot help us fix a bug, so it is basically useless. We
|
||
+respond by asking for enough details to enable us to investigate.
|
||
+You might as well expedite matters by sending them to begin with.
|
||
+
|
||
+To enable us to fix the bug, you should include all these things:
|
||
+
|
||
+@itemize @bullet
|
||
+@item
|
||
+The version of @command{ld}. @command{ld} announces it if you start it with
|
||
+the @samp{--version} argument.
|
||
+
|
||
+Without this, we will not know whether there is any point in looking for
|
||
+the bug in the current version of @command{ld}.
|
||
+
|
||
+@item
|
||
+Any patches you may have applied to the @command{ld} source, including any
|
||
+patches made to the @code{BFD} library.
|
||
+
|
||
+@item
|
||
+The type of machine you are using, and the operating system name and
|
||
+version number.
|
||
+
|
||
+@item
|
||
+What compiler (and its version) was used to compile @command{ld}---e.g.
|
||
+``@code{gcc-2.7}''.
|
||
+
|
||
+@item
|
||
+The command arguments you gave the linker to link your example and
|
||
+observe the bug. To guarantee you will not omit something important,
|
||
+list them all. A copy of the Makefile (or the output from make) is
|
||
+sufficient.
|
||
+
|
||
+If we were to try to guess the arguments, we would probably guess wrong
|
||
+and then we might not encounter the bug.
|
||
+
|
||
+@item
|
||
+A complete input file, or set of input files, that will reproduce the
|
||
+bug. It is generally most helpful to send the actual object files
|
||
+provided that they are reasonably small. Say no more than 10K. For
|
||
+bigger files you can either make them available by FTP or HTTP or else
|
||
+state that you are willing to send the object file(s) to whomever
|
||
+requests them. (Note - your email will be going to a mailing list, so
|
||
+we do not want to clog it up with large attachments). But small
|
||
+attachments are best.
|
||
+
|
||
+If the source files were assembled using @code{gas} or compiled using
|
||
+@code{gcc}, then it may be OK to send the source files rather than the
|
||
+object files. In this case, be sure to say exactly what version of
|
||
+@code{gas} or @code{gcc} was used to produce the object files. Also say
|
||
+how @code{gas} or @code{gcc} were configured.
|
||
+
|
||
+@item
|
||
+A description of what behavior you observe that you believe is
|
||
+incorrect. For example, ``It gets a fatal signal.''
|
||
+
|
||
+Of course, if the bug is that @command{ld} gets a fatal signal, then we
|
||
+will certainly notice it. But if the bug is incorrect output, we might
|
||
+not notice unless it is glaringly wrong. You might as well not give us
|
||
+a chance to make a mistake.
|
||
+
|
||
+Even if the problem you experience is a fatal signal, you should still
|
||
+say so explicitly. Suppose something strange is going on, such as, your
|
||
+copy of @command{ld} is out of sync, or you have encountered a bug in the
|
||
+C library on your system. (This has happened!) Your copy might crash
|
||
+and ours would not. If you told us to expect a crash, then when ours
|
||
+fails to crash, we would know that the bug was not happening for us. If
|
||
+you had not told us to expect a crash, then we would not be able to draw
|
||
+any conclusion from our observations.
|
||
+
|
||
+@item
|
||
+If you wish to suggest changes to the @command{ld} source, send us context
|
||
+diffs, as generated by @code{diff} with the @samp{-u}, @samp{-c}, or
|
||
+@samp{-p} option. Always send diffs from the old file to the new file.
|
||
+If you even discuss something in the @command{ld} source, refer to it by
|
||
+context, not by line number.
|
||
+
|
||
+The line numbers in our development sources will not match those in your
|
||
+sources. Your line numbers would convey no useful information to us.
|
||
+@end itemize
|
||
+
|
||
+Here are some things that are not necessary:
|
||
+
|
||
+@itemize @bullet
|
||
+@item
|
||
+A description of the envelope of the bug.
|
||
+
|
||
+Often people who encounter a bug spend a lot of time investigating
|
||
+which changes to the input file will make the bug go away and which
|
||
+changes will not affect it.
|
||
+
|
||
+This is often time consuming and not very useful, because the way we
|
||
+will find the bug is by running a single example under the debugger
|
||
+with breakpoints, not by pure deduction from a series of examples.
|
||
+We recommend that you save your time for something else.
|
||
+
|
||
+Of course, if you can find a simpler example to report @emph{instead}
|
||
+of the original one, that is a convenience for us. Errors in the
|
||
+output will be easier to spot, running under the debugger will take
|
||
+less time, and so on.
|
||
+
|
||
+However, simplification is not vital; if you do not want to do this,
|
||
+report the bug anyway and send us the entire test case you used.
|
||
+
|
||
+@item
|
||
+A patch for the bug.
|
||
+
|
||
+A patch for the bug does help us if it is a good one. But do not omit
|
||
+the necessary information, such as the test case, on the assumption that
|
||
+a patch is all we need. We might see problems with your patch and decide
|
||
+to fix the problem another way, or we might not understand it at all.
|
||
+
|
||
+Sometimes with a program as complicated as @command{ld} it is very hard to
|
||
+construct an example that will make the program follow a certain path
|
||
+through the code. If you do not send us the example, we will not be
|
||
+able to construct one, so we will not be able to verify that the bug is
|
||
+fixed.
|
||
+
|
||
+And if we cannot understand what bug you are trying to fix, or why your
|
||
+patch should be an improvement, we will not install it. A test case will
|
||
+help us to understand.
|
||
+
|
||
+@item
|
||
+A guess about what the bug is or what it depends on.
|
||
+
|
||
+Such guesses are usually wrong. Even we cannot guess right about such
|
||
+things without first using the debugger to find the facts.
|
||
+@end itemize
|
||
+
|
||
+@node MRI
|
||
+@appendix MRI Compatible Script Files
|
||
+@cindex MRI compatibility
|
||
+To aid users making the transition to @sc{gnu} @command{ld} from the MRI
|
||
+linker, @command{ld} can use MRI compatible linker scripts as an
|
||
+alternative to the more general-purpose linker scripting language
|
||
+described in @ref{Scripts}. MRI compatible linker scripts have a much
|
||
+simpler command set than the scripting language otherwise used with
|
||
+@command{ld}. @sc{gnu} @command{ld} supports the most commonly used MRI
|
||
+linker commands; these commands are described here.
|
||
+
|
||
+In general, MRI scripts aren't of much use with the @code{a.out} object
|
||
+file format, since it only has three sections and MRI scripts lack some
|
||
+features to make use of them.
|
||
+
|
||
+You can specify a file containing an MRI-compatible script using the
|
||
+@samp{-c} command-line option.
|
||
+
|
||
+Each command in an MRI-compatible script occupies its own line; each
|
||
+command line starts with the keyword that identifies the command (though
|
||
+blank lines are also allowed for punctuation). If a line of an
|
||
+MRI-compatible script begins with an unrecognized keyword, @command{ld}
|
||
+issues a warning message, but continues processing the script.
|
||
+
|
||
+Lines beginning with @samp{*} are comments.
|
||
+
|
||
+You can write these commands using all upper-case letters, or all
|
||
+lower case; for example, @samp{chip} is the same as @samp{CHIP}.
|
||
+The following list shows only the upper-case form of each command.
|
||
+
|
||
+@table @code
|
||
+@cindex @code{ABSOLUTE} (MRI)
|
||
+@item ABSOLUTE @var{secname}
|
||
+@itemx ABSOLUTE @var{secname}, @var{secname}, @dots{} @var{secname}
|
||
+Normally, @command{ld} includes in the output file all sections from all
|
||
+the input files. However, in an MRI-compatible script, you can use the
|
||
+@code{ABSOLUTE} command to restrict the sections that will be present in
|
||
+your output program. If the @code{ABSOLUTE} command is used at all in a
|
||
+script, then only the sections named explicitly in @code{ABSOLUTE}
|
||
+commands will appear in the linker output. You can still use other
|
||
+input sections (whatever you select on the command line, or using
|
||
+@code{LOAD}) to resolve addresses in the output file.
|
||
+
|
||
+@cindex @code{ALIAS} (MRI)
|
||
+@item ALIAS @var{out-secname}, @var{in-secname}
|
||
+Use this command to place the data from input section @var{in-secname}
|
||
+in a section called @var{out-secname} in the linker output file.
|
||
+
|
||
+@var{in-secname} may be an integer.
|
||
+
|
||
+@cindex @code{ALIGN} (MRI)
|
||
+@item ALIGN @var{secname} = @var{expression}
|
||
+Align the section called @var{secname} to @var{expression}. The
|
||
+@var{expression} should be a power of two.
|
||
+
|
||
+@cindex @code{BASE} (MRI)
|
||
+@item BASE @var{expression}
|
||
+Use the value of @var{expression} as the lowest address (other than
|
||
+absolute addresses) in the output file.
|
||
+
|
||
+@cindex @code{CHIP} (MRI)
|
||
+@item CHIP @var{expression}
|
||
+@itemx CHIP @var{expression}, @var{expression}
|
||
+This command does nothing; it is accepted only for compatibility.
|
||
+
|
||
+@cindex @code{END} (MRI)
|
||
+@item END
|
||
+This command does nothing whatever; it's only accepted for compatibility.
|
||
+
|
||
+@cindex @code{FORMAT} (MRI)
|
||
+@item FORMAT @var{output-format}
|
||
+Similar to the @code{OUTPUT_FORMAT} command in the more general linker
|
||
+language, but restricted to S-records, if @var{output-format} is @samp{S}
|
||
+
|
||
+@cindex @code{LIST} (MRI)
|
||
+@item LIST @var{anything}@dots{}
|
||
+Print (to the standard output file) a link map, as produced by the
|
||
+@command{ld} command-line option @samp{-M}.
|
||
+
|
||
+The keyword @code{LIST} may be followed by anything on the
|
||
+same line, with no change in its effect.
|
||
+
|
||
+@cindex @code{LOAD} (MRI)
|
||
+@item LOAD @var{filename}
|
||
+@itemx LOAD @var{filename}, @var{filename}, @dots{} @var{filename}
|
||
+Include one or more object file @var{filename} in the link; this has the
|
||
+same effect as specifying @var{filename} directly on the @command{ld}
|
||
+command line.
|
||
+
|
||
+@cindex @code{NAME} (MRI)
|
||
+@item NAME @var{output-name}
|
||
+@var{output-name} is the name for the program produced by @command{ld}; the
|
||
+MRI-compatible command @code{NAME} is equivalent to the command-line
|
||
+option @samp{-o} or the general script language command @code{OUTPUT}.
|
||
+
|
||
+@cindex @code{ORDER} (MRI)
|
||
+@item ORDER @var{secname}, @var{secname}, @dots{} @var{secname}
|
||
+@itemx ORDER @var{secname} @var{secname} @var{secname}
|
||
+Normally, @command{ld} orders the sections in its output file in the
|
||
+order in which they first appear in the input files. In an MRI-compatible
|
||
+script, you can override this ordering with the @code{ORDER} command. The
|
||
+sections you list with @code{ORDER} will appear first in your output
|
||
+file, in the order specified.
|
||
+
|
||
+@cindex @code{PUBLIC} (MRI)
|
||
+@item PUBLIC @var{name}=@var{expression}
|
||
+@itemx PUBLIC @var{name},@var{expression}
|
||
+@itemx PUBLIC @var{name} @var{expression}
|
||
+Supply a value (@var{expression}) for external symbol
|
||
+@var{name} used in the linker input files.
|
||
+
|
||
+@cindex @code{SECT} (MRI)
|
||
+@item SECT @var{secname}, @var{expression}
|
||
+@itemx SECT @var{secname}=@var{expression}
|
||
+@itemx SECT @var{secname} @var{expression}
|
||
+You can use any of these three forms of the @code{SECT} command to
|
||
+specify the start address (@var{expression}) for section @var{secname}.
|
||
+If you have more than one @code{SECT} statement for the same
|
||
+@var{secname}, only the @emph{first} sets the start address.
|
||
+@end table
|
||
+
|
||
+@node GNU Free Documentation License
|
||
+@appendix GNU Free Documentation License
|
||
+@include fdl.texi
|
||
+
|
||
+@node LD Index
|
||
+@unnumbered LD Index
|
||
+
|
||
+@printindex cp
|
||
+
|
||
+@tex
|
||
+% I think something like @@colophon should be in texinfo. In the
|
||
+% meantime:
|
||
+\long\def\colophon{\hbox to0pt{}\vfill
|
||
+\centerline{The body of this manual is set in}
|
||
+\centerline{\fontname\tenrm,}
|
||
+\centerline{with headings in {\bf\fontname\tenbf}}
|
||
+\centerline{and examples in {\tt\fontname\tentt}.}
|
||
+\centerline{{\it\fontname\tenit\/} and}
|
||
+\centerline{{\sl\fontname\tensl\/}}
|
||
+\centerline{are used for emphasis.}\vfill}
|
||
+\page\colophon
|
||
+% Blame: doc@@cygnus.com, 28mar91.
|
||
+@end tex
|
||
+
|
||
+@bye
|
||
diff -rupN binutils.orig/ld/ldfile.c binutils-2.41/ld/ldfile.c
|
||
--- binutils.orig/ld/ldfile.c 2024-05-13 13:03:47.800601771 +0100
|
||
+++ binutils-2.41/ld/ldfile.c 2024-05-13 13:04:08.595633300 +0100
|
||
@@ -868,19 +868,7 @@ ldfile_find_command_file (const char *na
|
||
return result;
|
||
}
|
||
|
||
-enum script_open_style {
|
||
- script_nonT,
|
||
- script_T,
|
||
- script_defaultT
|
||
-};
|
||
-
|
||
-struct script_name_list
|
||
-{
|
||
- struct script_name_list *next;
|
||
- enum script_open_style open_how;
|
||
- char name[1];
|
||
-};
|
||
-
|
||
+struct script_name_list *processed_scripts = NULL;
|
||
/* Open command file NAME. */
|
||
|
||
static void
|
||
@@ -888,7 +876,6 @@ ldfile_open_command_file_1 (const char *
|
||
{
|
||
FILE *ldlex_input_stack;
|
||
bool sysrooted;
|
||
- static struct script_name_list *processed_scripts = NULL;
|
||
struct script_name_list *script;
|
||
size_t len;
|
||
|
||
diff -rupN binutils.orig/ld/ldfile.c.orig binutils-2.41/ld/ldfile.c.orig
|
||
--- binutils.orig/ld/ldfile.c.orig 1970-01-01 01:00:00.000000000 +0100
|
||
+++ binutils-2.41/ld/ldfile.c.orig 2023-07-03 00:00:00.000000000 +0100
|
||
@@ -0,0 +1,998 @@
|
||
+/* Linker file opening and searching.
|
||
+ Copyright (C) 1991-2023 Free Software Foundation, Inc.
|
||
+
|
||
+ This file is part of the GNU Binutils.
|
||
+
|
||
+ This program is free software; you can redistribute it and/or modify
|
||
+ it under the terms of the GNU General Public License as published by
|
||
+ the Free Software Foundation; either version 3 of the License, or
|
||
+ (at your option) any later version.
|
||
+
|
||
+ This program is distributed in the hope that it will be useful,
|
||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
+ GNU General Public License for more details.
|
||
+
|
||
+ You should have received a copy of the GNU General Public License
|
||
+ along with this program; if not, write to the Free Software
|
||
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
|
||
+ MA 02110-1301, USA. */
|
||
+
|
||
+#include "sysdep.h"
|
||
+#include "bfd.h"
|
||
+#include "bfdlink.h"
|
||
+#include "ctf-api.h"
|
||
+#include "safe-ctype.h"
|
||
+#include "ld.h"
|
||
+#include "ldmisc.h"
|
||
+#include "ldexp.h"
|
||
+#include "ldlang.h"
|
||
+#include "ldfile.h"
|
||
+#include "ldmain.h"
|
||
+#include <ldgram.h>
|
||
+#include "ldlex.h"
|
||
+#include "ldemul.h"
|
||
+#include "libiberty.h"
|
||
+#include "filenames.h"
|
||
+#include <fnmatch.h>
|
||
+#if BFD_SUPPORTS_PLUGINS
|
||
+#include "plugin-api.h"
|
||
+#include "plugin.h"
|
||
+#endif /* BFD_SUPPORTS_PLUGINS */
|
||
+
|
||
+bool ldfile_assumed_script = false;
|
||
+const char *ldfile_output_machine_name = "";
|
||
+unsigned long ldfile_output_machine;
|
||
+enum bfd_architecture ldfile_output_architecture;
|
||
+search_dirs_type *search_head;
|
||
+
|
||
+#ifdef VMS
|
||
+static char *slash = "";
|
||
+#else
|
||
+#if defined (_WIN32) && !defined (__CYGWIN32__)
|
||
+static char *slash = "\\";
|
||
+#else
|
||
+static char *slash = "/";
|
||
+#endif
|
||
+#endif
|
||
+
|
||
+typedef struct search_arch
|
||
+{
|
||
+ char *name;
|
||
+ struct search_arch *next;
|
||
+} search_arch_type;
|
||
+
|
||
+static search_dirs_type **search_tail_ptr = &search_head;
|
||
+static search_arch_type *search_arch_head;
|
||
+static search_arch_type **search_arch_tail_ptr = &search_arch_head;
|
||
+
|
||
+typedef struct input_remap
|
||
+{
|
||
+ const char * pattern; /* Pattern to match input files. */
|
||
+ const char * renamed; /* Filename to use if the pattern matches. */
|
||
+ struct input_remap * next; /* Link in a chain of these structures. */
|
||
+} input_remap;
|
||
+
|
||
+static struct input_remap * input_remaps = NULL;
|
||
+
|
||
+void
|
||
+ldfile_add_remap (const char * pattern, const char * renamed)
|
||
+{
|
||
+ struct input_remap * new_entry;
|
||
+
|
||
+ new_entry = xmalloc (sizeof * new_entry);
|
||
+ new_entry->pattern = xstrdup (pattern);
|
||
+ new_entry->next = NULL;
|
||
+
|
||
+ /* Look for special filenames that mean that the input file should be ignored. */
|
||
+ if (strcmp (renamed, "/dev/null") == 0
|
||
+ || strcmp (renamed, "NUL") == 0)
|
||
+ new_entry->renamed = NULL;
|
||
+ else
|
||
+ /* FIXME: Should we add sanity checking of the 'renamed' string ? */
|
||
+ new_entry->renamed = xstrdup (renamed);
|
||
+
|
||
+ /* It would be easier to add this new node at the start of the chain,
|
||
+ but users expect that remapping will occur in the order in which
|
||
+ they occur on the command line, and in the remapping files. */
|
||
+ if (input_remaps == NULL)
|
||
+ {
|
||
+ input_remaps = new_entry;
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ struct input_remap * i;
|
||
+
|
||
+ for (i = input_remaps; i->next != NULL; i = i->next)
|
||
+ ;
|
||
+ i->next = new_entry;
|
||
+ }
|
||
+}
|
||
+
|
||
+void
|
||
+ldfile_remap_input_free (void)
|
||
+{
|
||
+ while (input_remaps != NULL)
|
||
+ {
|
||
+ struct input_remap * i = input_remaps;
|
||
+
|
||
+ input_remaps = i->next;
|
||
+ free ((void *) i->pattern);
|
||
+ free ((void *) i->renamed);
|
||
+ free (i);
|
||
+ }
|
||
+}
|
||
+
|
||
+bool
|
||
+ldfile_add_remap_file (const char * file)
|
||
+{
|
||
+ FILE * f;
|
||
+
|
||
+ f = fopen (file, FOPEN_RT);
|
||
+ if (f == NULL)
|
||
+ return false;
|
||
+
|
||
+ size_t linelen = 256;
|
||
+ char * line = xmalloc (linelen);
|
||
+
|
||
+ do
|
||
+ {
|
||
+ char * p = line;
|
||
+ char * q;
|
||
+
|
||
+ /* Normally this would use getline(3), but we need to be portable. */
|
||
+ while ((q = fgets (p, linelen - (p - line), f)) != NULL
|
||
+ && strlen (q) == linelen - (p - line) - 1
|
||
+ && line[linelen - 2] != '\n')
|
||
+ {
|
||
+ line = xrealloc (line, 2 * linelen);
|
||
+ p = line + linelen - 1;
|
||
+ linelen += linelen;
|
||
+ }
|
||
+
|
||
+ if (q == NULL && p == line)
|
||
+ break;
|
||
+
|
||
+ p = strchr (line, '\n');
|
||
+ if (p)
|
||
+ *p = '\0';
|
||
+
|
||
+ /* Because the file format does not know any form of quoting we
|
||
+ can search forward for the next '#' character and if found
|
||
+ make it terminating the line. */
|
||
+ p = strchr (line, '#');
|
||
+ if (p)
|
||
+ *p = '\0';
|
||
+
|
||
+ /* Remove leading whitespace. NUL is no whitespace character. */
|
||
+ p = line;
|
||
+ while (*p == ' ' || *p == '\f' || *p == '\r' || *p == '\t' || *p == '\v')
|
||
+ ++p;
|
||
+
|
||
+ /* If the line is blank it is ignored. */
|
||
+ if (*p == '\0')
|
||
+ continue;
|
||
+
|
||
+ char * pattern = p;
|
||
+
|
||
+ /* Advance past the pattern. We accept whitespace or '=' as an
|
||
+ end-of-pattern marker. */
|
||
+ while (*p && *p != '=' && *p != ' ' && *p != '\t' && *p != '\f'
|
||
+ && *p != '\r' && *p != '\v')
|
||
+ ++p;
|
||
+
|
||
+ if (*p == '\0')
|
||
+ {
|
||
+ einfo ("%F%P: malformed remap file entry: %s\n", line);
|
||
+ continue;
|
||
+ }
|
||
+
|
||
+ * p++ = '\0';
|
||
+
|
||
+ /* Skip whitespace again. */
|
||
+ while (*p == ' ' || *p == '\f' || *p == '\r' || *p == '\t' || *p == '\v')
|
||
+ ++p;
|
||
+
|
||
+ if (*p == '\0')
|
||
+ {
|
||
+ einfo ("%F%P: malformed remap file entry: %s\n", line);
|
||
+ continue;
|
||
+ }
|
||
+
|
||
+ char * renamed = p;
|
||
+
|
||
+ /* Advance past the rename entry. */
|
||
+ while (*p && *p != '=' && *p != ' ' && *p != '\t' && *p != '\f'
|
||
+ && *p != '\r' && *p != '\v')
|
||
+ ++p;
|
||
+ /* And terminate it. */
|
||
+ *p = '\0';
|
||
+
|
||
+ ldfile_add_remap (pattern, renamed);
|
||
+ }
|
||
+ while (! feof (f));
|
||
+
|
||
+ free (line);
|
||
+ fclose (f);
|
||
+
|
||
+ return true;
|
||
+}
|
||
+
|
||
+const char *
|
||
+ldfile_possibly_remap_input (const char * filename)
|
||
+{
|
||
+ struct input_remap * i;
|
||
+
|
||
+ if (filename == NULL)
|
||
+ return NULL;
|
||
+
|
||
+ for (i = input_remaps; i != NULL; i = i->next)
|
||
+ {
|
||
+ if (fnmatch (i->pattern, filename, 0) == 0)
|
||
+ {
|
||
+ if (verbose)
|
||
+ {
|
||
+ if (strpbrk ((i->pattern), "?*[") != NULL)
|
||
+ {
|
||
+ if (i->renamed)
|
||
+ info_msg (_("remap input file '%s' to '%s' based upon pattern '%s'\n"),
|
||
+ filename, i->renamed, i->pattern);
|
||
+ else
|
||
+ info_msg (_("remove input file '%s' based upon pattern '%s'\n"),
|
||
+ filename, i->pattern);
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ if (i->renamed)
|
||
+ info_msg (_("remap input file '%s' to '%s'\n"),
|
||
+ filename, i->renamed);
|
||
+ else
|
||
+ info_msg (_("remove input file '%s'\n"),
|
||
+ filename);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ return i->renamed;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ return filename;
|
||
+}
|
||
+
|
||
+void
|
||
+ldfile_print_input_remaps (void)
|
||
+{
|
||
+ if (input_remaps == NULL)
|
||
+ return;
|
||
+
|
||
+ minfo (_("\nInput File Remapping\n\n"));
|
||
+
|
||
+ struct input_remap * i;
|
||
+
|
||
+ for (i = input_remaps; i != NULL; i = i->next)
|
||
+ minfo (_(" Pattern: %s\tMaps To: %s\n"), i->pattern,
|
||
+ i->renamed ? i->renamed : _("<discard>"));
|
||
+}
|
||
+
|
||
+
|
||
+/* Test whether a pathname, after canonicalization, is the same or a
|
||
+ sub-directory of the sysroot directory. */
|
||
+
|
||
+static bool
|
||
+is_sysrooted_pathname (const char *name)
|
||
+{
|
||
+ char *realname;
|
||
+ int len;
|
||
+ bool result;
|
||
+
|
||
+ if (ld_canon_sysroot == NULL)
|
||
+ return false;
|
||
+
|
||
+ realname = lrealpath (name);
|
||
+ len = strlen (realname);
|
||
+ result = false;
|
||
+ if (len > ld_canon_sysroot_len
|
||
+ && IS_DIR_SEPARATOR (realname[ld_canon_sysroot_len]))
|
||
+ {
|
||
+ realname[ld_canon_sysroot_len] = '\0';
|
||
+ result = FILENAME_CMP (ld_canon_sysroot, realname) == 0;
|
||
+ }
|
||
+
|
||
+ free (realname);
|
||
+ return result;
|
||
+}
|
||
+
|
||
+/* Adds NAME to the library search path.
|
||
+ Makes a copy of NAME using xmalloc(). */
|
||
+
|
||
+void
|
||
+ldfile_add_library_path (const char *name, bool cmdline)
|
||
+{
|
||
+ search_dirs_type *new_dirs;
|
||
+
|
||
+ if (!cmdline && config.only_cmd_line_lib_dirs)
|
||
+ return;
|
||
+
|
||
+ new_dirs = (search_dirs_type *) xmalloc (sizeof (search_dirs_type));
|
||
+ new_dirs->next = NULL;
|
||
+ new_dirs->cmdline = cmdline;
|
||
+ *search_tail_ptr = new_dirs;
|
||
+ search_tail_ptr = &new_dirs->next;
|
||
+
|
||
+ /* If a directory is marked as honoring sysroot, prepend the sysroot path
|
||
+ now. */
|
||
+ if (name[0] == '=')
|
||
+ new_dirs->name = concat (ld_sysroot, name + 1, (const char *) NULL);
|
||
+ else if (startswith (name, "$SYSROOT"))
|
||
+ new_dirs->name = concat (ld_sysroot, name + strlen ("$SYSROOT"), (const char *) NULL);
|
||
+ else
|
||
+ new_dirs->name = xstrdup (name);
|
||
+}
|
||
+
|
||
+/* Try to open a BFD for a lang_input_statement. */
|
||
+
|
||
+bool
|
||
+ldfile_try_open_bfd (const char *attempt,
|
||
+ lang_input_statement_type *entry)
|
||
+{
|
||
+ entry->the_bfd = bfd_openr (attempt, entry->target);
|
||
+
|
||
+ if (verbose)
|
||
+ {
|
||
+ if (entry->the_bfd == NULL)
|
||
+ info_msg (_("attempt to open %s failed\n"), attempt);
|
||
+ else
|
||
+ info_msg (_("attempt to open %s succeeded\n"), attempt);
|
||
+ }
|
||
+
|
||
+ if (entry->the_bfd == NULL)
|
||
+ {
|
||
+ if (bfd_get_error () == bfd_error_invalid_target)
|
||
+ einfo (_("%F%P: invalid BFD target `%s'\n"), entry->target);
|
||
+ return false;
|
||
+ }
|
||
+
|
||
+ /* PR 30568: Do not track lto generated temporary object files. */
|
||
+#if BFD_SUPPORTS_PLUGINS
|
||
+ if (!entry->flags.lto_output)
|
||
+#endif
|
||
+ track_dependency_files (attempt);
|
||
+
|
||
+ /* Linker needs to decompress sections. */
|
||
+ entry->the_bfd->flags |= BFD_DECOMPRESS;
|
||
+
|
||
+ /* This is a linker input BFD. */
|
||
+ entry->the_bfd->is_linker_input = 1;
|
||
+
|
||
+#if BFD_SUPPORTS_PLUGINS
|
||
+ if (entry->flags.lto_output)
|
||
+ entry->the_bfd->lto_output = 1;
|
||
+#endif
|
||
+
|
||
+ /* If we are searching for this file, see if the architecture is
|
||
+ compatible with the output file. If it isn't, keep searching.
|
||
+ If we can't open the file as an object file, stop the search
|
||
+ here. If we are statically linking, ensure that we don't link
|
||
+ a dynamic object.
|
||
+
|
||
+ In the code below, it's OK to exit early if the check fails,
|
||
+ closing the checked BFD and returning false, but if the BFD
|
||
+ checks out compatible, do not exit early returning true, or
|
||
+ the plugins will not get a chance to claim the file. */
|
||
+
|
||
+ if (entry->flags.search_dirs || !entry->flags.dynamic)
|
||
+ {
|
||
+ bfd *check;
|
||
+
|
||
+ if (bfd_check_format (entry->the_bfd, bfd_archive))
|
||
+ check = bfd_openr_next_archived_file (entry->the_bfd, NULL);
|
||
+ else
|
||
+ check = entry->the_bfd;
|
||
+
|
||
+ if (check != NULL)
|
||
+ {
|
||
+ if (!bfd_check_format (check, bfd_object))
|
||
+ {
|
||
+ if (check == entry->the_bfd
|
||
+ && entry->flags.search_dirs
|
||
+ && bfd_get_error () == bfd_error_file_not_recognized
|
||
+ && !ldemul_unrecognized_file (entry))
|
||
+ {
|
||
+ int token, skip = 0;
|
||
+ char *arg, *arg1, *arg2, *arg3;
|
||
+ extern FILE *yyin;
|
||
+
|
||
+ /* Try to interpret the file as a linker script. */
|
||
+ ldfile_open_command_file (attempt);
|
||
+
|
||
+ ldfile_assumed_script = true;
|
||
+ parser_input = input_selected;
|
||
+ ldlex_script ();
|
||
+ token = INPUT_SCRIPT;
|
||
+ while (token != 0)
|
||
+ {
|
||
+ switch (token)
|
||
+ {
|
||
+ case OUTPUT_FORMAT:
|
||
+ if ((token = yylex ()) != '(')
|
||
+ continue;
|
||
+ if ((token = yylex ()) != NAME)
|
||
+ continue;
|
||
+ arg1 = yylval.name;
|
||
+ arg2 = NULL;
|
||
+ arg3 = NULL;
|
||
+ token = yylex ();
|
||
+ if (token == ',')
|
||
+ {
|
||
+ if ((token = yylex ()) != NAME)
|
||
+ {
|
||
+ free (arg1);
|
||
+ continue;
|
||
+ }
|
||
+ arg2 = yylval.name;
|
||
+ if ((token = yylex ()) != ','
|
||
+ || (token = yylex ()) != NAME)
|
||
+ {
|
||
+ free (arg1);
|
||
+ free (arg2);
|
||
+ continue;
|
||
+ }
|
||
+ arg3 = yylval.name;
|
||
+ token = yylex ();
|
||
+ }
|
||
+ if (token == ')')
|
||
+ {
|
||
+ switch (command_line.endian)
|
||
+ {
|
||
+ default:
|
||
+ case ENDIAN_UNSET:
|
||
+ arg = arg1; break;
|
||
+ case ENDIAN_BIG:
|
||
+ arg = arg2 ? arg2 : arg1; break;
|
||
+ case ENDIAN_LITTLE:
|
||
+ arg = arg3 ? arg3 : arg1; break;
|
||
+ }
|
||
+ if (strcmp (arg, lang_get_output_target ()) != 0)
|
||
+ skip = 1;
|
||
+ }
|
||
+ free (arg1);
|
||
+ free (arg2);
|
||
+ free (arg3);
|
||
+ break;
|
||
+ case NAME:
|
||
+ case LNAME:
|
||
+ case VERS_IDENTIFIER:
|
||
+ case VERS_TAG:
|
||
+ free (yylval.name);
|
||
+ break;
|
||
+ case INT:
|
||
+ free (yylval.bigint.str);
|
||
+ break;
|
||
+ }
|
||
+ token = yylex ();
|
||
+ }
|
||
+ ldlex_popstate ();
|
||
+ ldfile_assumed_script = false;
|
||
+ fclose (yyin);
|
||
+ yyin = NULL;
|
||
+ if (skip)
|
||
+ {
|
||
+ if (command_line.warn_search_mismatch)
|
||
+ einfo (_("%P: skipping incompatible %s "
|
||
+ "when searching for %s\n"),
|
||
+ attempt, entry->local_sym_name);
|
||
+ bfd_close (entry->the_bfd);
|
||
+ entry->the_bfd = NULL;
|
||
+ return false;
|
||
+ }
|
||
+ }
|
||
+ goto success;
|
||
+ }
|
||
+
|
||
+ if (!entry->flags.dynamic && (entry->the_bfd->flags & DYNAMIC) != 0)
|
||
+ {
|
||
+ einfo (_("%F%P: attempted static link of dynamic object `%s'\n"),
|
||
+ attempt);
|
||
+ bfd_close (entry->the_bfd);
|
||
+ entry->the_bfd = NULL;
|
||
+ return false;
|
||
+ }
|
||
+
|
||
+ if (entry->flags.search_dirs
|
||
+ && !bfd_arch_get_compatible (check, link_info.output_bfd,
|
||
+ command_line.accept_unknown_input_arch)
|
||
+ /* XCOFF archives can have 32 and 64 bit objects. */
|
||
+ && !(bfd_get_flavour (check) == bfd_target_xcoff_flavour
|
||
+ && (bfd_get_flavour (link_info.output_bfd)
|
||
+ == bfd_target_xcoff_flavour)
|
||
+ && bfd_check_format (entry->the_bfd, bfd_archive)))
|
||
+ {
|
||
+ if (command_line.warn_search_mismatch)
|
||
+ einfo (_("%P: skipping incompatible %s "
|
||
+ "when searching for %s\n"),
|
||
+ attempt, entry->local_sym_name);
|
||
+ bfd_close (entry->the_bfd);
|
||
+ entry->the_bfd = NULL;
|
||
+ return false;
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+ success:
|
||
+#if BFD_SUPPORTS_PLUGINS
|
||
+ /* If plugins are active, they get first chance to claim
|
||
+ any successfully-opened input file. We skip archives
|
||
+ here; the plugin wants us to offer it the individual
|
||
+ members when we enumerate them, not the whole file. We
|
||
+ also ignore corefiles, because that's just weird. It is
|
||
+ a needed side-effect of calling bfd_check_format with
|
||
+ bfd_object that it sets the bfd's arch and mach, which
|
||
+ will be needed when and if we want to bfd_create a new
|
||
+ one using this one as a template. */
|
||
+ if (link_info.lto_plugin_active
|
||
+ && !no_more_claiming
|
||
+ && bfd_check_format (entry->the_bfd, bfd_object))
|
||
+ plugin_maybe_claim (entry);
|
||
+#endif /* BFD_SUPPORTS_PLUGINS */
|
||
+
|
||
+ /* It opened OK, the format checked out, and the plugins have had
|
||
+ their chance to claim it, so this is success. */
|
||
+ return true;
|
||
+}
|
||
+
|
||
+/* Search for and open the file specified by ENTRY. If it is an
|
||
+ archive, use ARCH, LIB and SUFFIX to modify the file name. */
|
||
+
|
||
+bool
|
||
+ldfile_open_file_search (const char *arch,
|
||
+ lang_input_statement_type *entry,
|
||
+ const char *lib,
|
||
+ const char *suffix)
|
||
+{
|
||
+ search_dirs_type *search;
|
||
+
|
||
+ /* If this is not an archive, try to open it in the current
|
||
+ directory first. */
|
||
+ if (!entry->flags.maybe_archive)
|
||
+ {
|
||
+ if (entry->flags.sysrooted && IS_ABSOLUTE_PATH (entry->filename))
|
||
+ {
|
||
+ char *name = concat (ld_sysroot, entry->filename,
|
||
+ (const char *) NULL);
|
||
+ if (ldfile_try_open_bfd (name, entry))
|
||
+ {
|
||
+ entry->filename = name;
|
||
+ return true;
|
||
+ }
|
||
+ free (name);
|
||
+ }
|
||
+ else if (ldfile_try_open_bfd (entry->filename, entry))
|
||
+ return true;
|
||
+
|
||
+ if (IS_ABSOLUTE_PATH (entry->filename))
|
||
+ return false;
|
||
+ }
|
||
+
|
||
+ for (search = search_head; search != NULL; search = search->next)
|
||
+ {
|
||
+ char *string;
|
||
+
|
||
+ if (entry->flags.dynamic && !bfd_link_relocatable (&link_info))
|
||
+ {
|
||
+ if (ldemul_open_dynamic_archive (arch, search, entry))
|
||
+ return true;
|
||
+ }
|
||
+
|
||
+ if (entry->flags.maybe_archive && !entry->flags.full_name_provided)
|
||
+ string = concat (search->name, slash, lib, entry->filename,
|
||
+ arch, suffix, (const char *) NULL);
|
||
+ else
|
||
+ string = concat (search->name, slash, entry->filename,
|
||
+ (const char *) 0);
|
||
+
|
||
+ if (ldfile_try_open_bfd (string, entry))
|
||
+ {
|
||
+ entry->filename = string;
|
||
+ return true;
|
||
+ }
|
||
+
|
||
+ free (string);
|
||
+ }
|
||
+
|
||
+ return false;
|
||
+}
|
||
+
|
||
+/* Open the input file specified by ENTRY.
|
||
+ PR 4437: Do not stop on the first missing file, but
|
||
+ continue processing other input files in case there
|
||
+ are more errors to report. */
|
||
+
|
||
+void
|
||
+ldfile_open_file (lang_input_statement_type *entry)
|
||
+{
|
||
+ if (entry->the_bfd != NULL)
|
||
+ return;
|
||
+
|
||
+ if (!entry->flags.search_dirs)
|
||
+ {
|
||
+ if (ldfile_try_open_bfd (entry->filename, entry))
|
||
+ return;
|
||
+
|
||
+ if (filename_cmp (entry->filename, entry->local_sym_name) != 0)
|
||
+ einfo (_("%P: cannot find %s (%s): %E\n"),
|
||
+ entry->filename, entry->local_sym_name);
|
||
+ else
|
||
+ einfo (_("%P: cannot find %s: %E\n"), entry->local_sym_name);
|
||
+
|
||
+ entry->flags.missing_file = true;
|
||
+ input_flags.missing_file = true;
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ search_arch_type *arch;
|
||
+ bool found = false;
|
||
+
|
||
+ /* If extra_search_path is set, entry->filename is a relative path.
|
||
+ Search the directory of the current linker script before searching
|
||
+ other paths. */
|
||
+ if (entry->extra_search_path)
|
||
+ {
|
||
+ char *path = concat (entry->extra_search_path, slash, entry->filename,
|
||
+ (const char *)0);
|
||
+ if (ldfile_try_open_bfd (path, entry))
|
||
+ {
|
||
+ entry->filename = path;
|
||
+ entry->flags.search_dirs = false;
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ free (path);
|
||
+ }
|
||
+
|
||
+ /* Try to open <filename><suffix> or lib<filename><suffix>.a. */
|
||
+ for (arch = search_arch_head; arch != NULL; arch = arch->next)
|
||
+ {
|
||
+ found = ldfile_open_file_search (arch->name, entry, "lib", ".a");
|
||
+ if (found)
|
||
+ break;
|
||
+#ifdef VMS
|
||
+ found = ldfile_open_file_search (arch->name, entry, ":lib", ".a");
|
||
+ if (found)
|
||
+ break;
|
||
+#endif
|
||
+ found = ldemul_find_potential_libraries (arch->name, entry);
|
||
+ if (found)
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ /* If we have found the file, we don't need to search directories
|
||
+ again. */
|
||
+ if (found)
|
||
+ entry->flags.search_dirs = false;
|
||
+ else
|
||
+ {
|
||
+ if (entry->flags.sysrooted
|
||
+ && ld_sysroot
|
||
+ && IS_ABSOLUTE_PATH (entry->local_sym_name))
|
||
+ einfo (_("%P: cannot find %s inside %s\n"),
|
||
+ entry->local_sym_name, ld_sysroot);
|
||
+#if SUPPORT_ERROR_HANDLING_SCRIPT
|
||
+ else if (error_handling_script != NULL)
|
||
+ {
|
||
+ char * argv[4];
|
||
+ const char * res;
|
||
+ int status, err;
|
||
+
|
||
+ argv[0] = error_handling_script;
|
||
+ argv[1] = "missing-lib";
|
||
+ argv[2] = (char *) entry->local_sym_name;
|
||
+ argv[3] = NULL;
|
||
+
|
||
+ if (verbose)
|
||
+ einfo (_("%P: About to run error handling script '%s' with arguments: '%s' '%s'\n"),
|
||
+ argv[0], argv[1], argv[2]);
|
||
+
|
||
+ res = pex_one (PEX_SEARCH, error_handling_script, argv,
|
||
+ N_("error handling script"),
|
||
+ NULL /* Send stdout to random, temp file. */,
|
||
+ NULL /* Write to stderr. */,
|
||
+ &status, &err);
|
||
+ if (res != NULL)
|
||
+ {
|
||
+ einfo (_("%P: Failed to run error handling script '%s', reason: "),
|
||
+ error_handling_script);
|
||
+ /* FIXME: We assume here that errrno == err. */
|
||
+ perror (res);
|
||
+ }
|
||
+ else /* We ignore the return status of the script
|
||
+ and always print the error message. */
|
||
+ einfo (_("%P: cannot find %s: %E\n"), entry->local_sym_name);
|
||
+ }
|
||
+#endif
|
||
+ else
|
||
+ einfo (_("%P: cannot find %s: %E\n"), entry->local_sym_name);
|
||
+
|
||
+ /* PR 25747: Be kind to users who forgot to add the
|
||
+ "lib" prefix to their library when it was created. */
|
||
+ for (arch = search_arch_head; arch != NULL; arch = arch->next)
|
||
+ {
|
||
+ if (ldfile_open_file_search (arch->name, entry, "", ".a"))
|
||
+ {
|
||
+ const char * base = lbasename (entry->filename);
|
||
+
|
||
+ einfo (_("%P: note to link with %s use -l:%s or rename it to lib%s\n"),
|
||
+ entry->filename, base, base);
|
||
+ bfd_close (entry->the_bfd);
|
||
+ entry->the_bfd = NULL;
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ entry->flags.missing_file = true;
|
||
+ input_flags.missing_file = true;
|
||
+ }
|
||
+ }
|
||
+}
|
||
+
|
||
+/* Try to open NAME. */
|
||
+
|
||
+static FILE *
|
||
+try_open (const char *name, bool *sysrooted)
|
||
+{
|
||
+ FILE *result;
|
||
+
|
||
+ result = fopen (name, "r");
|
||
+
|
||
+ if (result != NULL)
|
||
+ *sysrooted = is_sysrooted_pathname (name);
|
||
+
|
||
+ if (verbose)
|
||
+ {
|
||
+ if (result == NULL)
|
||
+ info_msg (_("cannot find script file %s\n"), name);
|
||
+ else
|
||
+ info_msg (_("opened script file %s\n"), name);
|
||
+ }
|
||
+
|
||
+ return result;
|
||
+}
|
||
+
|
||
+/* Return TRUE iff directory DIR contains an "ldscripts" subdirectory. */
|
||
+
|
||
+static bool
|
||
+check_for_scripts_dir (char *dir)
|
||
+{
|
||
+ char *buf;
|
||
+ struct stat s;
|
||
+ bool res;
|
||
+
|
||
+ buf = concat (dir, "/ldscripts", (const char *) NULL);
|
||
+ res = stat (buf, &s) == 0 && S_ISDIR (s.st_mode);
|
||
+ free (buf);
|
||
+ return res;
|
||
+}
|
||
+
|
||
+/* Return the default directory for finding script files.
|
||
+ We look for the "ldscripts" directory in:
|
||
+
|
||
+ SCRIPTDIR (passed from Makefile)
|
||
+ (adjusted according to the current location of the binary)
|
||
+ the dir where this program is (for using it from the build tree). */
|
||
+
|
||
+static char *
|
||
+find_scripts_dir (void)
|
||
+{
|
||
+ char *dir;
|
||
+
|
||
+ dir = make_relative_prefix (program_name, BINDIR, SCRIPTDIR);
|
||
+ if (dir)
|
||
+ {
|
||
+ if (check_for_scripts_dir (dir))
|
||
+ return dir;
|
||
+ free (dir);
|
||
+ }
|
||
+
|
||
+ dir = make_relative_prefix (program_name, TOOLBINDIR, SCRIPTDIR);
|
||
+ if (dir)
|
||
+ {
|
||
+ if (check_for_scripts_dir (dir))
|
||
+ return dir;
|
||
+ free (dir);
|
||
+ }
|
||
+
|
||
+ /* Look for "ldscripts" in the dir where our binary is. */
|
||
+ dir = make_relative_prefix (program_name, ".", ".");
|
||
+ if (dir)
|
||
+ {
|
||
+ if (check_for_scripts_dir (dir))
|
||
+ return dir;
|
||
+ free (dir);
|
||
+ }
|
||
+
|
||
+ return NULL;
|
||
+}
|
||
+
|
||
+/* If DEFAULT_ONLY is false, try to open NAME; if that fails, look for
|
||
+ it in directories specified with -L, then in the default script
|
||
+ directory. If DEFAULT_ONLY is true, the search is restricted to
|
||
+ the default script location. */
|
||
+
|
||
+static FILE *
|
||
+ldfile_find_command_file (const char *name,
|
||
+ bool default_only,
|
||
+ bool *sysrooted)
|
||
+{
|
||
+ search_dirs_type *search;
|
||
+ FILE *result = NULL;
|
||
+ char *path;
|
||
+ static search_dirs_type *script_search;
|
||
+
|
||
+ if (!default_only)
|
||
+ {
|
||
+ /* First try raw name. */
|
||
+ result = try_open (name, sysrooted);
|
||
+ if (result != NULL)
|
||
+ return result;
|
||
+ }
|
||
+
|
||
+ if (!script_search)
|
||
+ {
|
||
+ char *script_dir = find_scripts_dir ();
|
||
+ if (script_dir)
|
||
+ {
|
||
+ search_dirs_type **save_tail_ptr = search_tail_ptr;
|
||
+ search_tail_ptr = &script_search;
|
||
+ ldfile_add_library_path (script_dir, true);
|
||
+ search_tail_ptr = save_tail_ptr;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ /* Temporarily append script_search to the path list so that the
|
||
+ paths specified with -L will be searched first. */
|
||
+ *search_tail_ptr = script_search;
|
||
+
|
||
+ /* Try now prefixes. */
|
||
+ for (search = default_only ? script_search : search_head;
|
||
+ search != NULL;
|
||
+ search = search->next)
|
||
+ {
|
||
+ path = concat (search->name, slash, name, (const char *) NULL);
|
||
+ result = try_open (path, sysrooted);
|
||
+ free (path);
|
||
+ if (result)
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ /* Restore the original path list. */
|
||
+ *search_tail_ptr = NULL;
|
||
+
|
||
+ return result;
|
||
+}
|
||
+
|
||
+enum script_open_style {
|
||
+ script_nonT,
|
||
+ script_T,
|
||
+ script_defaultT
|
||
+};
|
||
+
|
||
+struct script_name_list
|
||
+{
|
||
+ struct script_name_list *next;
|
||
+ enum script_open_style open_how;
|
||
+ char name[1];
|
||
+};
|
||
+
|
||
+/* Open command file NAME. */
|
||
+
|
||
+static void
|
||
+ldfile_open_command_file_1 (const char *name, enum script_open_style open_how)
|
||
+{
|
||
+ FILE *ldlex_input_stack;
|
||
+ bool sysrooted;
|
||
+ static struct script_name_list *processed_scripts = NULL;
|
||
+ struct script_name_list *script;
|
||
+ size_t len;
|
||
+
|
||
+ /* PR 24576: Catch the case where the user has accidentally included
|
||
+ the same linker script twice. */
|
||
+ for (script = processed_scripts; script != NULL; script = script->next)
|
||
+ {
|
||
+ if ((open_how != script_nonT || script->open_how != script_nonT)
|
||
+ && strcmp (name, script->name) == 0)
|
||
+ {
|
||
+ einfo (_("%F%P: error: linker script file '%s'"
|
||
+ " appears multiple times\n"), name);
|
||
+ return;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ /* FIXME: This memory is never freed, but that should not really matter.
|
||
+ It will be released when the linker exits, and it is unlikely to ever
|
||
+ be more than a few tens of bytes. */
|
||
+ len = strlen (name);
|
||
+ script = xmalloc (sizeof (*script) + len);
|
||
+ script->next = processed_scripts;
|
||
+ script->open_how = open_how;
|
||
+ memcpy (script->name, name, len + 1);
|
||
+ processed_scripts = script;
|
||
+
|
||
+ ldlex_input_stack = ldfile_find_command_file (name,
|
||
+ open_how == script_defaultT,
|
||
+ &sysrooted);
|
||
+ if (ldlex_input_stack == NULL)
|
||
+ {
|
||
+ bfd_set_error (bfd_error_system_call);
|
||
+ einfo (_("%F%P: cannot open linker script file %s: %E\n"), name);
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ track_dependency_files (name);
|
||
+
|
||
+ lex_push_file (ldlex_input_stack, name, sysrooted);
|
||
+
|
||
+ lineno = 1;
|
||
+
|
||
+ saved_script_handle = ldlex_input_stack;
|
||
+}
|
||
+
|
||
+/* Open command file NAME in the current directory, -L directories,
|
||
+ the default script location, in that order. */
|
||
+
|
||
+void
|
||
+ldfile_open_command_file (const char *name)
|
||
+{
|
||
+ ldfile_open_command_file_1 (name, script_nonT);
|
||
+}
|
||
+
|
||
+void
|
||
+ldfile_open_script_file (const char *name)
|
||
+{
|
||
+ ldfile_open_command_file_1 (name, script_T);
|
||
+}
|
||
+
|
||
+/* Open command file NAME at the default script location. */
|
||
+
|
||
+void
|
||
+ldfile_open_default_command_file (const char *name)
|
||
+{
|
||
+ ldfile_open_command_file_1 (name, script_defaultT);
|
||
+}
|
||
+
|
||
+void
|
||
+ldfile_add_arch (const char *in_name)
|
||
+{
|
||
+ char *name = xstrdup (in_name);
|
||
+ search_arch_type *new_arch
|
||
+ = (search_arch_type *) xmalloc (sizeof (search_arch_type));
|
||
+
|
||
+ ldfile_output_machine_name = in_name;
|
||
+
|
||
+ new_arch->name = name;
|
||
+ new_arch->next = NULL;
|
||
+ while (*name)
|
||
+ {
|
||
+ *name = TOLOWER (*name);
|
||
+ name++;
|
||
+ }
|
||
+ *search_arch_tail_ptr = new_arch;
|
||
+ search_arch_tail_ptr = &new_arch->next;
|
||
+
|
||
+}
|
||
+
|
||
+/* Set the output architecture. */
|
||
+
|
||
+void
|
||
+ldfile_set_output_arch (const char *string, enum bfd_architecture defarch)
|
||
+{
|
||
+ const bfd_arch_info_type *arch = bfd_scan_arch (string);
|
||
+
|
||
+ if (arch)
|
||
+ {
|
||
+ ldfile_output_architecture = arch->arch;
|
||
+ ldfile_output_machine = arch->mach;
|
||
+ ldfile_output_machine_name = arch->printable_name;
|
||
+ }
|
||
+ else if (defarch != bfd_arch_unknown)
|
||
+ ldfile_output_architecture = defarch;
|
||
+ else
|
||
+ einfo (_("%F%P: cannot represent machine `%s'\n"), string);
|
||
+}
|
||
diff -rupN binutils.orig/ld/ldfile.h binutils-2.41/ld/ldfile.h
|
||
--- binutils.orig/ld/ldfile.h 2024-05-13 13:03:47.801601773 +0100
|
||
+++ binutils-2.41/ld/ldfile.h 2024-05-13 13:04:08.595633300 +0100
|
||
@@ -29,7 +29,8 @@ extern const char *ldfile_output_machine
|
||
/* Structure used to hold the list of directories to search for
|
||
libraries. */
|
||
|
||
-typedef struct search_dirs {
|
||
+typedef struct search_dirs
|
||
+{
|
||
/* Next directory on list. */
|
||
struct search_dirs *next;
|
||
/* Name of directory. */
|
||
@@ -38,6 +39,22 @@ typedef struct search_dirs {
|
||
bool cmdline;
|
||
} search_dirs_type;
|
||
|
||
+enum script_open_style
|
||
+{
|
||
+ script_nonT,
|
||
+ script_T,
|
||
+ script_defaultT
|
||
+};
|
||
+
|
||
+struct script_name_list
|
||
+{
|
||
+ struct script_name_list * next;
|
||
+ enum script_open_style open_how;
|
||
+ char name[1];
|
||
+};
|
||
+
|
||
+extern struct script_name_list * processed_scripts;
|
||
+
|
||
extern search_dirs_type *search_head;
|
||
|
||
extern void ldfile_add_arch
|
||
diff -rupN binutils.orig/ld/ldgram.y binutils-2.41/ld/ldgram.y
|
||
--- binutils.orig/ld/ldgram.y 2024-05-13 13:03:47.802601774 +0100
|
||
+++ binutils-2.41/ld/ldgram.y 2024-05-13 13:04:08.596633302 +0100
|
||
@@ -154,7 +154,7 @@ static int error_index;
|
||
%token LOG2CEIL FORMAT PUBLIC DEFSYMEND BASE ALIAS TRUNCATE REL
|
||
%token INPUT_SCRIPT INPUT_MRI_SCRIPT INPUT_DEFSYM CASE EXTERN START
|
||
%token <name> VERS_TAG VERS_IDENTIFIER
|
||
-%token GLOBAL LOCAL VERSIONK INPUT_VERSION_SCRIPT
|
||
+%token GLOBAL LOCAL VERSIONK INPUT_VERSION_SCRIPT INPUT_SECTION_ORDERING_SCRIPT
|
||
%token KEEP ONLY_IF_RO ONLY_IF_RW SPECIAL INPUT_SECTION_FLAGS ALIGN_WITH_INPUT
|
||
%token EXCLUDE_FILE
|
||
%token CONSTANT
|
||
@@ -169,6 +169,7 @@ file:
|
||
INPUT_SCRIPT script_file
|
||
| INPUT_MRI_SCRIPT mri_script_file
|
||
| INPUT_VERSION_SCRIPT version_script_file
|
||
+ | INPUT_SECTION_ORDERING_SCRIPT section_ordering_script_file
|
||
| INPUT_DYNAMIC_LIST dynamic_list_file
|
||
| INPUT_DEFSYM defsym_expr
|
||
;
|
||
@@ -1503,6 +1504,39 @@ opt_semicolon:
|
||
| ';'
|
||
;
|
||
|
||
+section_ordering_script_file:
|
||
+ {
|
||
+ ldlex_script ();
|
||
+ PUSH_ERROR (_("section-ordering-file script"));
|
||
+ }
|
||
+ section_ordering_list
|
||
+ {
|
||
+ ldlex_popstate ();
|
||
+ POP_ERROR ();
|
||
+ }
|
||
+ ;
|
||
+
|
||
+section_ordering_list:
|
||
+ section_ordering_list section_order
|
||
+ | section_ordering_list statement_anywhere
|
||
+ |
|
||
+ ;
|
||
+
|
||
+section_order: NAME ':'
|
||
+ {
|
||
+ ldlex_wild ();
|
||
+ lang_enter_output_section_statement
|
||
+ ($1, NULL, 0, NULL, NULL, NULL, NULL, 0, 0);
|
||
+ }
|
||
+ '{'
|
||
+ statement_list_opt
|
||
+ '}'
|
||
+ {
|
||
+ ldlex_popstate ();
|
||
+ lang_leave_output_section_statement (NULL, NULL, NULL, NULL);
|
||
+ }
|
||
+ opt_comma
|
||
+
|
||
%%
|
||
void
|
||
yyerror(arg)
|
||
diff -rupN binutils.orig/ld/ldgram.y.orig binutils-2.41/ld/ldgram.y.orig
|
||
--- binutils.orig/ld/ldgram.y.orig 1970-01-01 01:00:00.000000000 +0100
|
||
+++ binutils-2.41/ld/ldgram.y.orig 2023-07-03 00:00:00.000000000 +0100
|
||
@@ -0,0 +1,1518 @@
|
||
+/* A YACC grammar to parse a superset of the AT&T linker scripting language.
|
||
+ Copyright (C) 1991-2023 Free Software Foundation, Inc.
|
||
+ Written by Steve Chamberlain of Cygnus Support (steve@cygnus.com).
|
||
+
|
||
+ This file is part of the GNU Binutils.
|
||
+
|
||
+ This program is free software; you can redistribute it and/or modify
|
||
+ it under the terms of the GNU General Public License as published by
|
||
+ the Free Software Foundation; either version 3 of the License, or
|
||
+ (at your option) any later version.
|
||
+
|
||
+ This program is distributed in the hope that it will be useful,
|
||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
+ GNU General Public License for more details.
|
||
+
|
||
+ You should have received a copy of the GNU General Public License
|
||
+ along with this program; if not, write to the Free Software
|
||
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
|
||
+ MA 02110-1301, USA. */
|
||
+
|
||
+%{
|
||
+/*
|
||
+
|
||
+ */
|
||
+
|
||
+#define DONTDECLARE_MALLOC
|
||
+
|
||
+#include "sysdep.h"
|
||
+#include "bfd.h"
|
||
+#include "bfdlink.h"
|
||
+#include "ctf-api.h"
|
||
+#include "ld.h"
|
||
+#include "ldexp.h"
|
||
+#include "ldver.h"
|
||
+#include "ldlang.h"
|
||
+#include "ldfile.h"
|
||
+#include "ldemul.h"
|
||
+#include "ldmisc.h"
|
||
+#include "ldmain.h"
|
||
+#include "mri.h"
|
||
+#include "ldctor.h"
|
||
+#include "ldlex.h"
|
||
+
|
||
+#ifndef YYDEBUG
|
||
+#define YYDEBUG 1
|
||
+#endif
|
||
+
|
||
+static enum section_type sectype;
|
||
+static etree_type *sectype_value;
|
||
+static lang_memory_region_type *region;
|
||
+
|
||
+static bool ldgram_had_keep = false;
|
||
+static char *ldgram_vers_current_lang = NULL;
|
||
+
|
||
+#define ERROR_NAME_MAX 20
|
||
+static char *error_names[ERROR_NAME_MAX];
|
||
+static int error_index;
|
||
+#define PUSH_ERROR(x) if (error_index < ERROR_NAME_MAX) error_names[error_index] = x; error_index++;
|
||
+#define POP_ERROR() error_index--;
|
||
+%}
|
||
+%union {
|
||
+ bfd_vma integer;
|
||
+ struct big_int
|
||
+ {
|
||
+ bfd_vma integer;
|
||
+ char *str;
|
||
+ } bigint;
|
||
+ fill_type *fill;
|
||
+ char *name;
|
||
+ const char *cname;
|
||
+ struct wildcard_spec wildcard;
|
||
+ struct wildcard_list *wildcard_list;
|
||
+ struct name_list *name_list;
|
||
+ struct flag_info_list *flag_info_list;
|
||
+ struct flag_info *flag_info;
|
||
+ int token;
|
||
+ union etree_union *etree;
|
||
+ struct phdr_info
|
||
+ {
|
||
+ bool filehdr;
|
||
+ bool phdrs;
|
||
+ union etree_union *at;
|
||
+ union etree_union *flags;
|
||
+ } phdr;
|
||
+ struct lang_nocrossref *nocrossref;
|
||
+ struct lang_output_section_phdr_list *section_phdr;
|
||
+ struct bfd_elf_version_deps *deflist;
|
||
+ struct bfd_elf_version_expr *versyms;
|
||
+ struct bfd_elf_version_tree *versnode;
|
||
+}
|
||
+
|
||
+%type <etree> exp opt_exp_with_type mustbe_exp opt_at phdr_type phdr_val
|
||
+%type <etree> opt_exp_without_type opt_subalign opt_align
|
||
+%type <fill> fill_opt fill_exp
|
||
+%type <name_list> exclude_name_list
|
||
+%type <wildcard_list> section_name_list
|
||
+%type <flag_info_list> sect_flag_list
|
||
+%type <flag_info> sect_flags
|
||
+%type <name> memspec_opt memspec_at_opt paren_script_name casesymlist
|
||
+%type <cname> wildcard_name
|
||
+%type <wildcard> section_name_spec filename_spec wildcard_maybe_exclude
|
||
+%token <bigint> INT
|
||
+%token <name> NAME LNAME
|
||
+%type <integer> length
|
||
+%type <phdr> phdr_qualifiers
|
||
+%type <nocrossref> nocrossref_list
|
||
+%type <section_phdr> phdr_opt
|
||
+%type <integer> opt_nocrossrefs
|
||
+
|
||
+%right <token> PLUSEQ MINUSEQ MULTEQ DIVEQ '=' LSHIFTEQ RSHIFTEQ ANDEQ OREQ
|
||
+%right <token> '?' ':'
|
||
+%left <token> OROR
|
||
+%left <token> ANDAND
|
||
+%left <token> '|'
|
||
+%left <token> '^'
|
||
+%left <token> '&'
|
||
+%left <token> EQ NE
|
||
+%left <token> '<' '>' LE GE
|
||
+%left <token> LSHIFT RSHIFT
|
||
+
|
||
+%left <token> '+' '-'
|
||
+%left <token> '*' '/' '%'
|
||
+
|
||
+%right UNARY
|
||
+%token END
|
||
+%left <token> '('
|
||
+%token <token> ALIGN_K BLOCK BIND QUAD SQUAD LONG SHORT BYTE ASCIZ
|
||
+%token SECTIONS PHDRS INSERT_K AFTER BEFORE LINKER_VERSION
|
||
+%token DATA_SEGMENT_ALIGN DATA_SEGMENT_RELRO_END DATA_SEGMENT_END
|
||
+%token SORT_BY_NAME SORT_BY_ALIGNMENT SORT_NONE
|
||
+%token SORT_BY_INIT_PRIORITY
|
||
+%token '{' '}'
|
||
+%token SIZEOF_HEADERS OUTPUT_FORMAT FORCE_COMMON_ALLOCATION OUTPUT_ARCH
|
||
+%token INHIBIT_COMMON_ALLOCATION FORCE_GROUP_ALLOCATION
|
||
+%token SEGMENT_START
|
||
+%token INCLUDE
|
||
+%token MEMORY
|
||
+%token REGION_ALIAS
|
||
+%token LD_FEATURE
|
||
+%token NOLOAD DSECT COPY INFO OVERLAY
|
||
+%token READONLY
|
||
+%token TYPE
|
||
+%token DEFINED TARGET_K SEARCH_DIR MAP ENTRY
|
||
+%token <integer> NEXT
|
||
+%token SIZEOF ALIGNOF ADDR LOADADDR MAX_K MIN_K
|
||
+%token STARTUP HLL SYSLIB FLOAT NOFLOAT NOCROSSREFS NOCROSSREFS_TO
|
||
+%token ORIGIN FILL
|
||
+%token LENGTH CREATE_OBJECT_SYMBOLS INPUT GROUP OUTPUT CONSTRUCTORS
|
||
+%token ALIGNMOD AT SUBALIGN HIDDEN PROVIDE PROVIDE_HIDDEN AS_NEEDED
|
||
+%type <token> assign_op atype attributes_opt sect_constraint opt_align_with_input
|
||
+%type <name> filename
|
||
+%token CHIP LIST SECT ABSOLUTE LOAD NEWLINE ENDWORD ORDER NAMEWORD ASSERT_K
|
||
+%token LOG2CEIL FORMAT PUBLIC DEFSYMEND BASE ALIAS TRUNCATE REL
|
||
+%token INPUT_SCRIPT INPUT_MRI_SCRIPT INPUT_DEFSYM CASE EXTERN START
|
||
+%token <name> VERS_TAG VERS_IDENTIFIER
|
||
+%token GLOBAL LOCAL VERSIONK INPUT_VERSION_SCRIPT
|
||
+%token KEEP ONLY_IF_RO ONLY_IF_RW SPECIAL INPUT_SECTION_FLAGS ALIGN_WITH_INPUT
|
||
+%token EXCLUDE_FILE
|
||
+%token CONSTANT
|
||
+%type <versyms> vers_defns
|
||
+%type <versnode> vers_tag
|
||
+%type <deflist> verdep
|
||
+%token INPUT_DYNAMIC_LIST
|
||
+
|
||
+%%
|
||
+
|
||
+file:
|
||
+ INPUT_SCRIPT script_file
|
||
+ | INPUT_MRI_SCRIPT mri_script_file
|
||
+ | INPUT_VERSION_SCRIPT version_script_file
|
||
+ | INPUT_DYNAMIC_LIST dynamic_list_file
|
||
+ | INPUT_DEFSYM defsym_expr
|
||
+ ;
|
||
+
|
||
+
|
||
+filename: NAME;
|
||
+
|
||
+
|
||
+defsym_expr:
|
||
+ { ldlex_expression(); }
|
||
+ assignment
|
||
+ { ldlex_popstate(); }
|
||
+ ;
|
||
+
|
||
+/* SYNTAX WITHIN AN MRI SCRIPT FILE */
|
||
+mri_script_file:
|
||
+ {
|
||
+ ldlex_mri_script ();
|
||
+ PUSH_ERROR (_("MRI style script"));
|
||
+ }
|
||
+ mri_script_lines
|
||
+ {
|
||
+ ldlex_popstate ();
|
||
+ mri_draw_tree ();
|
||
+ POP_ERROR ();
|
||
+ }
|
||
+ ;
|
||
+
|
||
+mri_script_lines:
|
||
+ mri_script_lines mri_script_command NEWLINE
|
||
+ |
|
||
+ ;
|
||
+
|
||
+mri_script_command:
|
||
+ CHIP exp
|
||
+ | CHIP exp ',' exp
|
||
+ | NAME {
|
||
+ einfo(_("%F%P: unrecognised keyword in MRI style script '%s'\n"),$1);
|
||
+ }
|
||
+ | LIST {
|
||
+ config.map_filename = "-";
|
||
+ }
|
||
+ | ORDER ordernamelist
|
||
+ | ENDWORD
|
||
+ | PUBLIC NAME '=' exp
|
||
+ { mri_public($2, $4); }
|
||
+ | PUBLIC NAME ',' exp
|
||
+ { mri_public($2, $4); }
|
||
+ | PUBLIC NAME exp
|
||
+ { mri_public($2, $3); }
|
||
+ | FORMAT NAME
|
||
+ { mri_format($2); }
|
||
+ | SECT NAME ',' exp
|
||
+ { mri_output_section($2, $4);}
|
||
+ | SECT NAME exp
|
||
+ { mri_output_section($2, $3);}
|
||
+ | SECT NAME '=' exp
|
||
+ { mri_output_section($2, $4);}
|
||
+ | ALIGN_K NAME '=' exp
|
||
+ { mri_align($2,$4); }
|
||
+ | ALIGN_K NAME ',' exp
|
||
+ { mri_align($2,$4); }
|
||
+ | ALIGNMOD NAME '=' exp
|
||
+ { mri_alignmod($2,$4); }
|
||
+ | ALIGNMOD NAME ',' exp
|
||
+ { mri_alignmod($2,$4); }
|
||
+ | ABSOLUTE mri_abs_name_list
|
||
+ | LOAD mri_load_name_list
|
||
+ | NAMEWORD NAME
|
||
+ { mri_name($2); }
|
||
+ | ALIAS NAME ',' NAME
|
||
+ { mri_alias($2,$4,0);}
|
||
+ | ALIAS NAME ',' INT
|
||
+ { mri_alias ($2, 0, (int) $4.integer); }
|
||
+ | BASE exp
|
||
+ { mri_base($2); }
|
||
+ | TRUNCATE INT
|
||
+ { mri_truncate ((unsigned int) $2.integer); }
|
||
+ | CASE casesymlist
|
||
+ | EXTERN extern_name_list
|
||
+ | INCLUDE filename
|
||
+ { ldfile_open_command_file ($2); }
|
||
+ mri_script_lines END
|
||
+ | START NAME
|
||
+ { lang_add_entry ($2, false); }
|
||
+ |
|
||
+ ;
|
||
+
|
||
+ordernamelist:
|
||
+ ordernamelist ',' NAME { mri_order($3); }
|
||
+ | ordernamelist NAME { mri_order($2); }
|
||
+ |
|
||
+ ;
|
||
+
|
||
+mri_load_name_list:
|
||
+ NAME
|
||
+ { mri_load($1); }
|
||
+ | mri_load_name_list ',' NAME { mri_load($3); }
|
||
+ ;
|
||
+
|
||
+mri_abs_name_list:
|
||
+ NAME
|
||
+ { mri_only_load($1); }
|
||
+ | mri_abs_name_list ',' NAME
|
||
+ { mri_only_load($3); }
|
||
+ ;
|
||
+
|
||
+casesymlist:
|
||
+ /* empty */ { $$ = NULL; }
|
||
+ | NAME
|
||
+ | casesymlist ',' NAME
|
||
+ ;
|
||
+
|
||
+extern_name_list:
|
||
+ NAME
|
||
+ { ldlang_add_undef ($1, false); }
|
||
+ | extern_name_list NAME
|
||
+ { ldlang_add_undef ($2, false); }
|
||
+ | extern_name_list ',' NAME
|
||
+ { ldlang_add_undef ($3, false); }
|
||
+ ;
|
||
+
|
||
+script_file:
|
||
+ { ldlex_script (); }
|
||
+ ifile_list
|
||
+ { ldlex_popstate (); }
|
||
+ ;
|
||
+
|
||
+ifile_list:
|
||
+ ifile_list ifile_p1
|
||
+ |
|
||
+ ;
|
||
+
|
||
+
|
||
+ifile_p1:
|
||
+ memory
|
||
+ | sections
|
||
+ | phdrs
|
||
+ | startup
|
||
+ | high_level_library
|
||
+ | low_level_library
|
||
+ | floating_point_support
|
||
+ | statement_anywhere
|
||
+ | version
|
||
+ | ';'
|
||
+ | TARGET_K '(' NAME ')'
|
||
+ { lang_add_target($3); }
|
||
+ | SEARCH_DIR '(' filename ')'
|
||
+ { ldfile_add_library_path ($3, false); }
|
||
+ | OUTPUT '(' filename ')'
|
||
+ { lang_add_output($3, 1); }
|
||
+ | OUTPUT_FORMAT '(' NAME ')'
|
||
+ { lang_add_output_format ($3, (char *) NULL,
|
||
+ (char *) NULL, 1); }
|
||
+ | OUTPUT_FORMAT '(' NAME ',' NAME ',' NAME ')'
|
||
+ { lang_add_output_format ($3, $5, $7, 1); }
|
||
+ | OUTPUT_ARCH '(' NAME ')'
|
||
+ { ldfile_set_output_arch ($3, bfd_arch_unknown); }
|
||
+ | FORCE_COMMON_ALLOCATION
|
||
+ { command_line.force_common_definition = true ; }
|
||
+ | FORCE_GROUP_ALLOCATION
|
||
+ { command_line.force_group_allocation = true ; }
|
||
+ | INHIBIT_COMMON_ALLOCATION
|
||
+ { link_info.inhibit_common_definition = true ; }
|
||
+ | INPUT '(' input_list ')'
|
||
+ | GROUP
|
||
+ { lang_enter_group (); }
|
||
+ '(' input_list ')'
|
||
+ { lang_leave_group (); }
|
||
+ | MAP '(' filename ')'
|
||
+ { lang_add_map($3); }
|
||
+ | INCLUDE filename
|
||
+ { ldfile_open_command_file ($2); }
|
||
+ ifile_list END
|
||
+ | NOCROSSREFS '(' nocrossref_list ')'
|
||
+ {
|
||
+ lang_add_nocrossref ($3);
|
||
+ }
|
||
+ | NOCROSSREFS_TO '(' nocrossref_list ')'
|
||
+ {
|
||
+ lang_add_nocrossref_to ($3);
|
||
+ }
|
||
+ | EXTERN '(' { ldlex_expression (); } extern_name_list ')'
|
||
+ { ldlex_popstate (); }
|
||
+ | INSERT_K AFTER NAME
|
||
+ { lang_add_insert ($3, 0); }
|
||
+ | INSERT_K BEFORE NAME
|
||
+ { lang_add_insert ($3, 1); }
|
||
+ | REGION_ALIAS '(' NAME ',' NAME ')'
|
||
+ { lang_memory_region_alias ($3, $5); }
|
||
+ | LD_FEATURE '(' NAME ')'
|
||
+ { lang_ld_feature ($3); }
|
||
+ ;
|
||
+
|
||
+input_list:
|
||
+ { ldlex_inputlist(); }
|
||
+ input_list1
|
||
+ { ldlex_popstate(); }
|
||
+
|
||
+input_list1:
|
||
+ NAME
|
||
+ { lang_add_input_file($1,lang_input_file_is_search_file_enum,
|
||
+ (char *)NULL); }
|
||
+ | input_list1 ',' NAME
|
||
+ { lang_add_input_file($3,lang_input_file_is_search_file_enum,
|
||
+ (char *)NULL); }
|
||
+ | input_list1 NAME
|
||
+ { lang_add_input_file($2,lang_input_file_is_search_file_enum,
|
||
+ (char *)NULL); }
|
||
+ | LNAME
|
||
+ { lang_add_input_file($1,lang_input_file_is_l_enum,
|
||
+ (char *)NULL); }
|
||
+ | input_list1 ',' LNAME
|
||
+ { lang_add_input_file($3,lang_input_file_is_l_enum,
|
||
+ (char *)NULL); }
|
||
+ | input_list1 LNAME
|
||
+ { lang_add_input_file($2,lang_input_file_is_l_enum,
|
||
+ (char *)NULL); }
|
||
+ | AS_NEEDED '('
|
||
+ { $<integer>$ = input_flags.add_DT_NEEDED_for_regular;
|
||
+ input_flags.add_DT_NEEDED_for_regular = true; }
|
||
+ input_list1 ')'
|
||
+ { input_flags.add_DT_NEEDED_for_regular = $<integer>3; }
|
||
+ | input_list1 ',' AS_NEEDED '('
|
||
+ { $<integer>$ = input_flags.add_DT_NEEDED_for_regular;
|
||
+ input_flags.add_DT_NEEDED_for_regular = true; }
|
||
+ input_list1 ')'
|
||
+ { input_flags.add_DT_NEEDED_for_regular = $<integer>5; }
|
||
+ | input_list1 AS_NEEDED '('
|
||
+ { $<integer>$ = input_flags.add_DT_NEEDED_for_regular;
|
||
+ input_flags.add_DT_NEEDED_for_regular = true; }
|
||
+ input_list1 ')'
|
||
+ { input_flags.add_DT_NEEDED_for_regular = $<integer>4; }
|
||
+ ;
|
||
+
|
||
+sections:
|
||
+ SECTIONS '{' sec_or_group_p1 '}'
|
||
+ ;
|
||
+
|
||
+sec_or_group_p1:
|
||
+ sec_or_group_p1 section
|
||
+ | sec_or_group_p1 statement_anywhere
|
||
+ |
|
||
+ ;
|
||
+
|
||
+statement_anywhere:
|
||
+ ENTRY '(' NAME ')'
|
||
+ { lang_add_entry ($3, false); }
|
||
+ | assignment separator
|
||
+ | ASSERT_K {ldlex_expression ();} '(' exp ',' NAME ')'
|
||
+ { ldlex_popstate ();
|
||
+ lang_add_assignment (exp_assert ($4, $6)); }
|
||
+ ;
|
||
+
|
||
+wildcard_name:
|
||
+ NAME
|
||
+ {
|
||
+ $$ = $1;
|
||
+ }
|
||
+ ;
|
||
+
|
||
+wildcard_maybe_exclude:
|
||
+ wildcard_name
|
||
+ {
|
||
+ $$.name = $1;
|
||
+ $$.sorted = none;
|
||
+ $$.exclude_name_list = NULL;
|
||
+ $$.section_flag_list = NULL;
|
||
+ }
|
||
+ | EXCLUDE_FILE '(' exclude_name_list ')' wildcard_name
|
||
+ {
|
||
+ $$.name = $5;
|
||
+ $$.sorted = none;
|
||
+ $$.exclude_name_list = $3;
|
||
+ $$.section_flag_list = NULL;
|
||
+ }
|
||
+ ;
|
||
+
|
||
+filename_spec:
|
||
+ wildcard_maybe_exclude
|
||
+ | SORT_BY_NAME '(' wildcard_maybe_exclude ')'
|
||
+ {
|
||
+ $$ = $3;
|
||
+ $$.sorted = by_name;
|
||
+ }
|
||
+ | SORT_NONE '(' wildcard_maybe_exclude ')'
|
||
+ {
|
||
+ $$ = $3;
|
||
+ $$.sorted = by_none;
|
||
+ }
|
||
+ ;
|
||
+
|
||
+section_name_spec:
|
||
+ wildcard_maybe_exclude
|
||
+ | SORT_BY_NAME '(' wildcard_maybe_exclude ')'
|
||
+ {
|
||
+ $$ = $3;
|
||
+ $$.sorted = by_name;
|
||
+ }
|
||
+ | SORT_BY_ALIGNMENT '(' wildcard_maybe_exclude ')'
|
||
+ {
|
||
+ $$ = $3;
|
||
+ $$.sorted = by_alignment;
|
||
+ }
|
||
+ | SORT_NONE '(' wildcard_maybe_exclude ')'
|
||
+ {
|
||
+ $$ = $3;
|
||
+ $$.sorted = by_none;
|
||
+ }
|
||
+ | SORT_BY_NAME '(' SORT_BY_ALIGNMENT '(' wildcard_maybe_exclude ')' ')'
|
||
+ {
|
||
+ $$ = $5;
|
||
+ $$.sorted = by_name_alignment;
|
||
+ }
|
||
+ | SORT_BY_NAME '(' SORT_BY_NAME '(' wildcard_maybe_exclude ')' ')'
|
||
+ {
|
||
+ $$ = $5;
|
||
+ $$.sorted = by_name;
|
||
+ }
|
||
+ | SORT_BY_ALIGNMENT '(' SORT_BY_NAME '(' wildcard_maybe_exclude ')' ')'
|
||
+ {
|
||
+ $$ = $5;
|
||
+ $$.sorted = by_alignment_name;
|
||
+ }
|
||
+ | SORT_BY_ALIGNMENT '(' SORT_BY_ALIGNMENT '(' wildcard_maybe_exclude ')' ')'
|
||
+ {
|
||
+ $$ = $5;
|
||
+ $$.sorted = by_alignment;
|
||
+ }
|
||
+ | SORT_BY_INIT_PRIORITY '(' wildcard_maybe_exclude ')'
|
||
+ {
|
||
+ $$ = $3;
|
||
+ $$.sorted = by_init_priority;
|
||
+ }
|
||
+ ;
|
||
+
|
||
+sect_flag_list: NAME
|
||
+ {
|
||
+ struct flag_info_list *n;
|
||
+ n = ((struct flag_info_list *) xmalloc (sizeof *n));
|
||
+ if ($1[0] == '!')
|
||
+ {
|
||
+ n->with = without_flags;
|
||
+ n->name = &$1[1];
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ n->with = with_flags;
|
||
+ n->name = $1;
|
||
+ }
|
||
+ n->valid = false;
|
||
+ n->next = NULL;
|
||
+ $$ = n;
|
||
+ }
|
||
+ | sect_flag_list '&' NAME
|
||
+ {
|
||
+ struct flag_info_list *n;
|
||
+ n = ((struct flag_info_list *) xmalloc (sizeof *n));
|
||
+ if ($3[0] == '!')
|
||
+ {
|
||
+ n->with = without_flags;
|
||
+ n->name = &$3[1];
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ n->with = with_flags;
|
||
+ n->name = $3;
|
||
+ }
|
||
+ n->valid = false;
|
||
+ n->next = $1;
|
||
+ $$ = n;
|
||
+ }
|
||
+ ;
|
||
+
|
||
+sect_flags:
|
||
+ INPUT_SECTION_FLAGS '(' sect_flag_list ')'
|
||
+ {
|
||
+ struct flag_info *n;
|
||
+ n = ((struct flag_info *) xmalloc (sizeof *n));
|
||
+ n->flag_list = $3;
|
||
+ n->flags_initialized = false;
|
||
+ n->not_with_flags = 0;
|
||
+ n->only_with_flags = 0;
|
||
+ $$ = n;
|
||
+ }
|
||
+ ;
|
||
+
|
||
+exclude_name_list:
|
||
+ exclude_name_list wildcard_name
|
||
+ {
|
||
+ struct name_list *tmp;
|
||
+ tmp = (struct name_list *) xmalloc (sizeof *tmp);
|
||
+ tmp->name = $2;
|
||
+ tmp->next = $1;
|
||
+ $$ = tmp;
|
||
+ }
|
||
+ |
|
||
+ wildcard_name
|
||
+ {
|
||
+ struct name_list *tmp;
|
||
+ tmp = (struct name_list *) xmalloc (sizeof *tmp);
|
||
+ tmp->name = $1;
|
||
+ tmp->next = NULL;
|
||
+ $$ = tmp;
|
||
+ }
|
||
+ ;
|
||
+
|
||
+section_name_list:
|
||
+ section_name_list opt_comma section_name_spec
|
||
+ {
|
||
+ struct wildcard_list *tmp;
|
||
+ tmp = (struct wildcard_list *) xmalloc (sizeof *tmp);
|
||
+ tmp->next = $1;
|
||
+ tmp->spec = $3;
|
||
+ $$ = tmp;
|
||
+ }
|
||
+ |
|
||
+ section_name_spec
|
||
+ {
|
||
+ struct wildcard_list *tmp;
|
||
+ tmp = (struct wildcard_list *) xmalloc (sizeof *tmp);
|
||
+ tmp->next = NULL;
|
||
+ tmp->spec = $1;
|
||
+ $$ = tmp;
|
||
+ }
|
||
+ ;
|
||
+
|
||
+input_section_spec_no_keep:
|
||
+ NAME
|
||
+ {
|
||
+ struct wildcard_spec tmp;
|
||
+ tmp.name = $1;
|
||
+ tmp.exclude_name_list = NULL;
|
||
+ tmp.sorted = none;
|
||
+ tmp.section_flag_list = NULL;
|
||
+ lang_add_wild (&tmp, NULL, ldgram_had_keep);
|
||
+ }
|
||
+ | sect_flags NAME
|
||
+ {
|
||
+ struct wildcard_spec tmp;
|
||
+ tmp.name = $2;
|
||
+ tmp.exclude_name_list = NULL;
|
||
+ tmp.sorted = none;
|
||
+ tmp.section_flag_list = $1;
|
||
+ lang_add_wild (&tmp, NULL, ldgram_had_keep);
|
||
+ }
|
||
+ | '[' section_name_list ']'
|
||
+ {
|
||
+ lang_add_wild (NULL, $2, ldgram_had_keep);
|
||
+ }
|
||
+ | sect_flags '[' section_name_list ']'
|
||
+ {
|
||
+ struct wildcard_spec tmp;
|
||
+ tmp.name = NULL;
|
||
+ tmp.exclude_name_list = NULL;
|
||
+ tmp.sorted = none;
|
||
+ tmp.section_flag_list = $1;
|
||
+ lang_add_wild (&tmp, $3, ldgram_had_keep);
|
||
+ }
|
||
+ | filename_spec '(' section_name_list ')'
|
||
+ {
|
||
+ lang_add_wild (&$1, $3, ldgram_had_keep);
|
||
+ }
|
||
+ | sect_flags filename_spec '(' section_name_list ')'
|
||
+ {
|
||
+ $2.section_flag_list = $1;
|
||
+ lang_add_wild (&$2, $4, ldgram_had_keep);
|
||
+ }
|
||
+ ;
|
||
+
|
||
+input_section_spec:
|
||
+ input_section_spec_no_keep
|
||
+ | KEEP '('
|
||
+ { ldgram_had_keep = true; }
|
||
+ input_section_spec_no_keep ')'
|
||
+ { ldgram_had_keep = false; }
|
||
+ ;
|
||
+
|
||
+statement:
|
||
+ ';'
|
||
+ | assignment separator
|
||
+ | CREATE_OBJECT_SYMBOLS
|
||
+ {
|
||
+ lang_add_attribute (lang_object_symbols_statement_enum);
|
||
+ }
|
||
+ | CONSTRUCTORS
|
||
+ {
|
||
+ lang_add_attribute (lang_constructors_statement_enum);
|
||
+ }
|
||
+ | SORT_BY_NAME '(' CONSTRUCTORS ')'
|
||
+ {
|
||
+ constructors_sorted = true;
|
||
+ lang_add_attribute (lang_constructors_statement_enum);
|
||
+ }
|
||
+ | input_section_spec
|
||
+ | length '(' mustbe_exp ')'
|
||
+ {
|
||
+ lang_add_data ((int) $1, $3);
|
||
+ }
|
||
+ | ASCIZ NAME
|
||
+ {
|
||
+ lang_add_string ($2);
|
||
+ }
|
||
+ | FILL '(' fill_exp ')'
|
||
+ {
|
||
+ lang_add_fill ($3);
|
||
+ }
|
||
+ | LINKER_VERSION
|
||
+ {
|
||
+ lang_add_version_string ();
|
||
+ }
|
||
+ | ASSERT_K
|
||
+ { ldlex_expression (); }
|
||
+ '(' exp ',' NAME ')' separator
|
||
+ {
|
||
+ ldlex_popstate ();
|
||
+ lang_add_assignment (exp_assert ($4, $6));
|
||
+ }
|
||
+ | INCLUDE filename
|
||
+ {
|
||
+ ldfile_open_command_file ($2);
|
||
+ }
|
||
+ statement_list_opt END
|
||
+ ;
|
||
+
|
||
+statement_list:
|
||
+ statement_list statement
|
||
+ | statement
|
||
+ ;
|
||
+
|
||
+statement_list_opt:
|
||
+ /* empty */
|
||
+ | statement_list
|
||
+ ;
|
||
+
|
||
+length:
|
||
+ QUAD
|
||
+ { $$ = $1; }
|
||
+ | SQUAD
|
||
+ { $$ = $1; }
|
||
+ | LONG
|
||
+ { $$ = $1; }
|
||
+ | SHORT
|
||
+ { $$ = $1; }
|
||
+ | BYTE
|
||
+ { $$ = $1; }
|
||
+ ;
|
||
+
|
||
+fill_exp:
|
||
+ mustbe_exp
|
||
+ {
|
||
+ $$ = exp_get_fill ($1, 0, _("fill value"));
|
||
+ }
|
||
+ ;
|
||
+
|
||
+fill_opt:
|
||
+ '=' fill_exp
|
||
+ { $$ = $2; }
|
||
+ | { $$ = (fill_type *) 0; }
|
||
+ ;
|
||
+
|
||
+assign_op:
|
||
+ PLUSEQ
|
||
+ { $$ = '+'; }
|
||
+ | MINUSEQ
|
||
+ { $$ = '-'; }
|
||
+ | MULTEQ
|
||
+ { $$ = '*'; }
|
||
+ | DIVEQ
|
||
+ { $$ = '/'; }
|
||
+ | LSHIFTEQ
|
||
+ { $$ = LSHIFT; }
|
||
+ | RSHIFTEQ
|
||
+ { $$ = RSHIFT; }
|
||
+ | ANDEQ
|
||
+ { $$ = '&'; }
|
||
+ | OREQ
|
||
+ { $$ = '|'; }
|
||
+
|
||
+ ;
|
||
+
|
||
+separator: ';' | ','
|
||
+ ;
|
||
+
|
||
+
|
||
+assignment:
|
||
+ NAME '=' mustbe_exp
|
||
+ {
|
||
+ lang_add_assignment (exp_assign ($1, $3, false));
|
||
+ }
|
||
+ | NAME assign_op mustbe_exp
|
||
+ {
|
||
+ lang_add_assignment (exp_assign ($1,
|
||
+ exp_binop ($2,
|
||
+ exp_nameop (NAME,
|
||
+ $1),
|
||
+ $3), false));
|
||
+ }
|
||
+ | HIDDEN '(' NAME '=' mustbe_exp ')'
|
||
+ {
|
||
+ lang_add_assignment (exp_assign ($3, $5, true));
|
||
+ }
|
||
+ | PROVIDE '(' NAME '=' mustbe_exp ')'
|
||
+ {
|
||
+ lang_add_assignment (exp_provide ($3, $5, false));
|
||
+ }
|
||
+ | PROVIDE_HIDDEN '(' NAME '=' mustbe_exp ')'
|
||
+ {
|
||
+ lang_add_assignment (exp_provide ($3, $5, true));
|
||
+ }
|
||
+ ;
|
||
+
|
||
+
|
||
+opt_comma:
|
||
+ ',' | ;
|
||
+
|
||
+
|
||
+memory:
|
||
+ MEMORY '{' memory_spec_list_opt '}'
|
||
+ ;
|
||
+
|
||
+memory_spec_list_opt: memory_spec_list | ;
|
||
+
|
||
+memory_spec_list:
|
||
+ memory_spec_list opt_comma memory_spec
|
||
+ | memory_spec
|
||
+ ;
|
||
+
|
||
+
|
||
+memory_spec: NAME
|
||
+ { region = lang_memory_region_lookup ($1, true); }
|
||
+ attributes_opt ':'
|
||
+ origin_spec opt_comma length_spec
|
||
+ {}
|
||
+ | INCLUDE filename
|
||
+ { ldfile_open_command_file ($2); }
|
||
+ memory_spec_list_opt END
|
||
+ ;
|
||
+
|
||
+origin_spec:
|
||
+ ORIGIN '=' mustbe_exp
|
||
+ {
|
||
+ region->origin_exp = $3;
|
||
+ }
|
||
+ ;
|
||
+
|
||
+length_spec:
|
||
+ LENGTH '=' mustbe_exp
|
||
+ {
|
||
+ if (yychar == NAME)
|
||
+ {
|
||
+ yyclearin;
|
||
+ ldlex_backup ();
|
||
+ }
|
||
+ region->length_exp = $3;
|
||
+ }
|
||
+ ;
|
||
+
|
||
+attributes_opt:
|
||
+ /* empty */
|
||
+ { /* dummy action to avoid bison 1.25 error message */ }
|
||
+ | '(' attributes_list ')'
|
||
+ ;
|
||
+
|
||
+attributes_list:
|
||
+ attributes_string
|
||
+ | attributes_list attributes_string
|
||
+ ;
|
||
+
|
||
+attributes_string:
|
||
+ NAME
|
||
+ { lang_set_flags (region, $1, 0); }
|
||
+ | '!' NAME
|
||
+ { lang_set_flags (region, $2, 1); }
|
||
+ ;
|
||
+
|
||
+startup:
|
||
+ STARTUP '(' filename ')'
|
||
+ { lang_startup($3); }
|
||
+ ;
|
||
+
|
||
+high_level_library:
|
||
+ HLL '(' high_level_library_NAME_list ')'
|
||
+ | HLL '(' ')'
|
||
+ { ldemul_hll((char *)NULL); }
|
||
+ ;
|
||
+
|
||
+high_level_library_NAME_list:
|
||
+ high_level_library_NAME_list opt_comma filename
|
||
+ { ldemul_hll($3); }
|
||
+ | filename
|
||
+ { ldemul_hll($1); }
|
||
+ ;
|
||
+
|
||
+low_level_library:
|
||
+ SYSLIB '(' low_level_library_NAME_list ')'
|
||
+ ;
|
||
+
|
||
+low_level_library_NAME_list:
|
||
+ low_level_library_NAME_list opt_comma filename
|
||
+ { ldemul_syslib($3); }
|
||
+ |
|
||
+ ;
|
||
+
|
||
+floating_point_support:
|
||
+ FLOAT
|
||
+ { lang_float(true); }
|
||
+ | NOFLOAT
|
||
+ { lang_float(false); }
|
||
+ ;
|
||
+
|
||
+nocrossref_list:
|
||
+ /* empty */
|
||
+ {
|
||
+ $$ = NULL;
|
||
+ }
|
||
+ | NAME nocrossref_list
|
||
+ {
|
||
+ struct lang_nocrossref *n;
|
||
+
|
||
+ n = (struct lang_nocrossref *) xmalloc (sizeof *n);
|
||
+ n->name = $1;
|
||
+ n->next = $2;
|
||
+ $$ = n;
|
||
+ }
|
||
+ | NAME ',' nocrossref_list
|
||
+ {
|
||
+ struct lang_nocrossref *n;
|
||
+
|
||
+ n = (struct lang_nocrossref *) xmalloc (sizeof *n);
|
||
+ n->name = $1;
|
||
+ n->next = $3;
|
||
+ $$ = n;
|
||
+ }
|
||
+ ;
|
||
+
|
||
+paren_script_name: { ldlex_script (); }
|
||
+ '(' NAME ')'
|
||
+ { ldlex_popstate (); $$ = $3; }
|
||
+
|
||
+mustbe_exp: { ldlex_expression (); }
|
||
+ exp
|
||
+ { ldlex_popstate (); $$ = $2; }
|
||
+ ;
|
||
+
|
||
+exp :
|
||
+ '-' exp %prec UNARY
|
||
+ { $$ = exp_unop ('-', $2); }
|
||
+ | '(' exp ')'
|
||
+ { $$ = $2; }
|
||
+ | NEXT '(' exp ')' %prec UNARY
|
||
+ { $$ = exp_unop ((int) $1,$3); }
|
||
+ | '!' exp %prec UNARY
|
||
+ { $$ = exp_unop ('!', $2); }
|
||
+ | '+' exp %prec UNARY
|
||
+ { $$ = $2; }
|
||
+ | '~' exp %prec UNARY
|
||
+ { $$ = exp_unop ('~', $2);}
|
||
+
|
||
+ | exp '*' exp
|
||
+ { $$ = exp_binop ('*', $1, $3); }
|
||
+ | exp '/' exp
|
||
+ { $$ = exp_binop ('/', $1, $3); }
|
||
+ | exp '%' exp
|
||
+ { $$ = exp_binop ('%', $1, $3); }
|
||
+ | exp '+' exp
|
||
+ { $$ = exp_binop ('+', $1, $3); }
|
||
+ | exp '-' exp
|
||
+ { $$ = exp_binop ('-' , $1, $3); }
|
||
+ | exp LSHIFT exp
|
||
+ { $$ = exp_binop (LSHIFT , $1, $3); }
|
||
+ | exp RSHIFT exp
|
||
+ { $$ = exp_binop (RSHIFT , $1, $3); }
|
||
+ | exp EQ exp
|
||
+ { $$ = exp_binop (EQ , $1, $3); }
|
||
+ | exp NE exp
|
||
+ { $$ = exp_binop (NE , $1, $3); }
|
||
+ | exp LE exp
|
||
+ { $$ = exp_binop (LE , $1, $3); }
|
||
+ | exp GE exp
|
||
+ { $$ = exp_binop (GE , $1, $3); }
|
||
+ | exp '<' exp
|
||
+ { $$ = exp_binop ('<' , $1, $3); }
|
||
+ | exp '>' exp
|
||
+ { $$ = exp_binop ('>' , $1, $3); }
|
||
+ | exp '&' exp
|
||
+ { $$ = exp_binop ('&' , $1, $3); }
|
||
+ | exp '^' exp
|
||
+ { $$ = exp_binop ('^' , $1, $3); }
|
||
+ | exp '|' exp
|
||
+ { $$ = exp_binop ('|' , $1, $3); }
|
||
+ | exp '?' exp ':' exp
|
||
+ { $$ = exp_trinop ('?' , $1, $3, $5); }
|
||
+ | exp ANDAND exp
|
||
+ { $$ = exp_binop (ANDAND , $1, $3); }
|
||
+ | exp OROR exp
|
||
+ { $$ = exp_binop (OROR , $1, $3); }
|
||
+ | DEFINED '(' NAME ')'
|
||
+ { $$ = exp_nameop (DEFINED, $3); }
|
||
+ | INT
|
||
+ { $$ = exp_bigintop ($1.integer, $1.str); }
|
||
+ | SIZEOF_HEADERS
|
||
+ { $$ = exp_nameop (SIZEOF_HEADERS,0); }
|
||
+
|
||
+ | ALIGNOF paren_script_name
|
||
+ { $$ = exp_nameop (ALIGNOF, $2); }
|
||
+ | SIZEOF paren_script_name
|
||
+ { $$ = exp_nameop (SIZEOF, $2); }
|
||
+ | ADDR paren_script_name
|
||
+ { $$ = exp_nameop (ADDR, $2); }
|
||
+ | LOADADDR paren_script_name
|
||
+ { $$ = exp_nameop (LOADADDR, $2); }
|
||
+ | CONSTANT '(' NAME ')'
|
||
+ { $$ = exp_nameop (CONSTANT,$3); }
|
||
+ | ABSOLUTE '(' exp ')'
|
||
+ { $$ = exp_unop (ABSOLUTE, $3); }
|
||
+ | ALIGN_K '(' exp ')'
|
||
+ { $$ = exp_unop (ALIGN_K,$3); }
|
||
+ | ALIGN_K '(' exp ',' exp ')'
|
||
+ { $$ = exp_binop (ALIGN_K,$3,$5); }
|
||
+ | DATA_SEGMENT_ALIGN '(' exp ',' exp ')'
|
||
+ { $$ = exp_binop (DATA_SEGMENT_ALIGN, $3, $5); }
|
||
+ | DATA_SEGMENT_RELRO_END '(' exp ',' exp ')'
|
||
+ { $$ = exp_binop (DATA_SEGMENT_RELRO_END, $5, $3); }
|
||
+ | DATA_SEGMENT_END '(' exp ')'
|
||
+ { $$ = exp_unop (DATA_SEGMENT_END, $3); }
|
||
+ | SEGMENT_START { ldlex_script (); } '(' NAME
|
||
+ { ldlex_popstate (); } ',' exp ')'
|
||
+ { /* The operands to the expression node are
|
||
+ placed in the opposite order from the way
|
||
+ in which they appear in the script as
|
||
+ that allows us to reuse more code in
|
||
+ fold_binary. */
|
||
+ $$ = exp_binop (SEGMENT_START,
|
||
+ $7,
|
||
+ exp_nameop (NAME, $4)); }
|
||
+ | BLOCK '(' exp ')'
|
||
+ { $$ = exp_unop (ALIGN_K,$3); }
|
||
+ | NAME
|
||
+ { $$ = exp_nameop (NAME,$1); }
|
||
+ | MAX_K '(' exp ',' exp ')'
|
||
+ { $$ = exp_binop (MAX_K, $3, $5 ); }
|
||
+ | MIN_K '(' exp ',' exp ')'
|
||
+ { $$ = exp_binop (MIN_K, $3, $5 ); }
|
||
+ | ASSERT_K '(' exp ',' NAME ')'
|
||
+ { $$ = exp_assert ($3, $5); }
|
||
+ | ORIGIN paren_script_name
|
||
+ { $$ = exp_nameop (ORIGIN, $2); }
|
||
+ | LENGTH paren_script_name
|
||
+ { $$ = exp_nameop (LENGTH, $2); }
|
||
+ | LOG2CEIL '(' exp ')'
|
||
+ { $$ = exp_unop (LOG2CEIL, $3); }
|
||
+ ;
|
||
+
|
||
+
|
||
+memspec_at_opt:
|
||
+ AT '>' NAME { $$ = $3; }
|
||
+ | { $$ = 0; }
|
||
+ ;
|
||
+
|
||
+opt_at:
|
||
+ AT '(' exp ')' { $$ = $3; }
|
||
+ | { $$ = 0; }
|
||
+ ;
|
||
+
|
||
+opt_align:
|
||
+ ALIGN_K '(' exp ')' { $$ = $3; }
|
||
+ | { $$ = 0; }
|
||
+ ;
|
||
+
|
||
+opt_align_with_input:
|
||
+ ALIGN_WITH_INPUT { $$ = ALIGN_WITH_INPUT; }
|
||
+ | { $$ = 0; }
|
||
+ ;
|
||
+
|
||
+opt_subalign:
|
||
+ SUBALIGN '(' exp ')' { $$ = $3; }
|
||
+ | { $$ = 0; }
|
||
+ ;
|
||
+
|
||
+sect_constraint:
|
||
+ ONLY_IF_RO { $$ = ONLY_IF_RO; }
|
||
+ | ONLY_IF_RW { $$ = ONLY_IF_RW; }
|
||
+ | SPECIAL { $$ = SPECIAL; }
|
||
+ | { $$ = 0; }
|
||
+ ;
|
||
+
|
||
+section: NAME
|
||
+ { ldlex_expression(); }
|
||
+ opt_exp_with_type
|
||
+ opt_at
|
||
+ opt_align
|
||
+ opt_align_with_input
|
||
+ opt_subalign
|
||
+ sect_constraint
|
||
+ {
|
||
+ ldlex_popstate ();
|
||
+ ldlex_wild ();
|
||
+ lang_enter_output_section_statement ($1, $3, sectype,
|
||
+ sectype_value, $5, $7, $4, $8, $6);
|
||
+ }
|
||
+ '{'
|
||
+ statement_list_opt
|
||
+ '}'
|
||
+ { ldlex_popstate (); }
|
||
+ memspec_opt memspec_at_opt phdr_opt fill_opt
|
||
+ {
|
||
+ /* fill_opt may have switched the lexer into
|
||
+ expression state, and back again, but in
|
||
+ order to find the end of the fill
|
||
+ expression the parser must look ahead one
|
||
+ token. If it is a NAME, throw it away as
|
||
+ it will have been lexed in the wrong
|
||
+ state. */
|
||
+ if (yychar == NAME)
|
||
+ {
|
||
+ yyclearin;
|
||
+ ldlex_backup ();
|
||
+ }
|
||
+ lang_leave_output_section_statement ($17, $14,
|
||
+ $16, $15);
|
||
+ }
|
||
+ opt_comma
|
||
+ | OVERLAY
|
||
+ { ldlex_expression (); }
|
||
+ opt_exp_without_type opt_nocrossrefs opt_at opt_subalign
|
||
+ { ldlex_popstate (); }
|
||
+ '{'
|
||
+ {
|
||
+ lang_enter_overlay ($3, $6);
|
||
+ }
|
||
+ overlay_section
|
||
+ '}'
|
||
+ memspec_opt memspec_at_opt phdr_opt fill_opt
|
||
+ {
|
||
+ if (yychar == NAME)
|
||
+ {
|
||
+ yyclearin;
|
||
+ ldlex_backup ();
|
||
+ }
|
||
+ lang_leave_overlay ($5, (int) $4,
|
||
+ $15, $12, $14, $13);
|
||
+ }
|
||
+ opt_comma
|
||
+ | /* The GROUP case is just enough to support the gcc
|
||
+ svr3.ifile script. It is not intended to be full
|
||
+ support. I'm not even sure what GROUP is supposed
|
||
+ to mean. */
|
||
+ GROUP
|
||
+ { ldlex_expression (); }
|
||
+ opt_exp_with_type
|
||
+ {
|
||
+ ldlex_popstate ();
|
||
+ lang_add_assignment (exp_assign (".", $3, false));
|
||
+ }
|
||
+ '{' sec_or_group_p1 '}'
|
||
+ | INCLUDE filename
|
||
+ {
|
||
+ ldfile_open_command_file ($2);
|
||
+ }
|
||
+ sec_or_group_p1 END
|
||
+ ;
|
||
+
|
||
+type:
|
||
+ NOLOAD { sectype = noload_section; }
|
||
+ | DSECT { sectype = noalloc_section; }
|
||
+ | COPY { sectype = noalloc_section; }
|
||
+ | INFO { sectype = noalloc_section; }
|
||
+ | OVERLAY { sectype = noalloc_section; }
|
||
+ | READONLY '(' TYPE '=' exp ')' { sectype = typed_readonly_section; sectype_value = $5; }
|
||
+ | READONLY { sectype = readonly_section; }
|
||
+ | TYPE '=' exp { sectype = type_section; sectype_value = $3; }
|
||
+ ;
|
||
+
|
||
+atype:
|
||
+ '(' type ')'
|
||
+ | /* EMPTY */ { sectype = normal_section; }
|
||
+ | '(' ')' { sectype = normal_section; }
|
||
+ ;
|
||
+
|
||
+opt_exp_with_type:
|
||
+ exp atype ':' { $$ = $1; }
|
||
+ | atype ':' { $$ = (etree_type *)NULL; }
|
||
+ | /* The BIND cases are to support the gcc svr3.ifile
|
||
+ script. They aren't intended to implement full
|
||
+ support for the BIND keyword. I'm not even sure
|
||
+ what BIND is supposed to mean. */
|
||
+ BIND '(' exp ')' atype ':' { $$ = $3; }
|
||
+ | BIND '(' exp ')' BLOCK '(' exp ')' atype ':'
|
||
+ { $$ = $3; }
|
||
+ ;
|
||
+
|
||
+opt_exp_without_type:
|
||
+ exp ':' { $$ = $1; }
|
||
+ | ':' { $$ = (etree_type *) NULL; }
|
||
+ ;
|
||
+
|
||
+opt_nocrossrefs:
|
||
+ /* empty */
|
||
+ { $$ = 0; }
|
||
+ | NOCROSSREFS
|
||
+ { $$ = 1; }
|
||
+ ;
|
||
+
|
||
+memspec_opt:
|
||
+ '>' NAME
|
||
+ { $$ = $2; }
|
||
+ | { $$ = DEFAULT_MEMORY_REGION; }
|
||
+ ;
|
||
+
|
||
+phdr_opt:
|
||
+ /* empty */
|
||
+ {
|
||
+ $$ = NULL;
|
||
+ }
|
||
+ | phdr_opt ':' NAME
|
||
+ {
|
||
+ struct lang_output_section_phdr_list *n;
|
||
+
|
||
+ n = ((struct lang_output_section_phdr_list *)
|
||
+ xmalloc (sizeof *n));
|
||
+ n->name = $3;
|
||
+ n->used = false;
|
||
+ n->next = $1;
|
||
+ $$ = n;
|
||
+ }
|
||
+ ;
|
||
+
|
||
+overlay_section:
|
||
+ /* empty */
|
||
+ | overlay_section
|
||
+ NAME
|
||
+ {
|
||
+ ldlex_wild ();
|
||
+ lang_enter_overlay_section ($2);
|
||
+ }
|
||
+ '{'
|
||
+ statement_list_opt
|
||
+ '}'
|
||
+ { ldlex_popstate (); }
|
||
+ phdr_opt fill_opt
|
||
+ {
|
||
+ if (yychar == NAME)
|
||
+ {
|
||
+ yyclearin;
|
||
+ ldlex_backup ();
|
||
+ }
|
||
+ lang_leave_overlay_section ($9, $8);
|
||
+ }
|
||
+ opt_comma
|
||
+ ;
|
||
+
|
||
+phdrs:
|
||
+ PHDRS '{' phdr_list '}'
|
||
+ ;
|
||
+
|
||
+phdr_list:
|
||
+ /* empty */
|
||
+ | phdr_list phdr
|
||
+ ;
|
||
+
|
||
+phdr:
|
||
+ NAME { ldlex_expression (); }
|
||
+ phdr_type phdr_qualifiers { ldlex_popstate (); }
|
||
+ ';'
|
||
+ {
|
||
+ lang_new_phdr ($1, $3, $4.filehdr, $4.phdrs, $4.at,
|
||
+ $4.flags);
|
||
+ }
|
||
+ ;
|
||
+
|
||
+phdr_type:
|
||
+ exp
|
||
+ {
|
||
+ $$ = $1;
|
||
+
|
||
+ if ($1->type.node_class == etree_name
|
||
+ && $1->type.node_code == NAME)
|
||
+ {
|
||
+ const char *s;
|
||
+ unsigned int i;
|
||
+ static const char * const phdr_types[] =
|
||
+ {
|
||
+ "PT_NULL", "PT_LOAD", "PT_DYNAMIC",
|
||
+ "PT_INTERP", "PT_NOTE", "PT_SHLIB",
|
||
+ "PT_PHDR", "PT_TLS"
|
||
+ };
|
||
+
|
||
+ s = $1->name.name;
|
||
+ for (i = 0;
|
||
+ i < sizeof phdr_types / sizeof phdr_types[0];
|
||
+ i++)
|
||
+ if (strcmp (s, phdr_types[i]) == 0)
|
||
+ {
|
||
+ $$ = exp_intop (i);
|
||
+ break;
|
||
+ }
|
||
+ if (i == sizeof phdr_types / sizeof phdr_types[0])
|
||
+ {
|
||
+ if (strcmp (s, "PT_GNU_EH_FRAME") == 0)
|
||
+ $$ = exp_intop (0x6474e550);
|
||
+ else if (strcmp (s, "PT_GNU_STACK") == 0)
|
||
+ $$ = exp_intop (0x6474e551);
|
||
+ else if (strcmp (s, "PT_GNU_RELRO") == 0)
|
||
+ $$ = exp_intop (0x6474e552);
|
||
+ else if (strcmp (s, "PT_GNU_PROPERTY") == 0)
|
||
+ $$ = exp_intop (0x6474e553);
|
||
+ else
|
||
+ {
|
||
+ einfo (_("\
|
||
+%X%P:%pS: unknown phdr type `%s' (try integer literal)\n"),
|
||
+ NULL, s);
|
||
+ $$ = exp_intop (0);
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+ ;
|
||
+
|
||
+phdr_qualifiers:
|
||
+ /* empty */
|
||
+ {
|
||
+ memset (&$$, 0, sizeof (struct phdr_info));
|
||
+ }
|
||
+ | NAME phdr_val phdr_qualifiers
|
||
+ {
|
||
+ $$ = $3;
|
||
+ if (strcmp ($1, "FILEHDR") == 0 && $2 == NULL)
|
||
+ $$.filehdr = true;
|
||
+ else if (strcmp ($1, "PHDRS") == 0 && $2 == NULL)
|
||
+ $$.phdrs = true;
|
||
+ else if (strcmp ($1, "FLAGS") == 0 && $2 != NULL)
|
||
+ $$.flags = $2;
|
||
+ else
|
||
+ einfo (_("%X%P:%pS: PHDRS syntax error at `%s'\n"),
|
||
+ NULL, $1);
|
||
+ }
|
||
+ | AT '(' exp ')' phdr_qualifiers
|
||
+ {
|
||
+ $$ = $5;
|
||
+ $$.at = $3;
|
||
+ }
|
||
+ ;
|
||
+
|
||
+phdr_val:
|
||
+ /* empty */
|
||
+ {
|
||
+ $$ = NULL;
|
||
+ }
|
||
+ | '(' exp ')'
|
||
+ {
|
||
+ $$ = $2;
|
||
+ }
|
||
+ ;
|
||
+
|
||
+dynamic_list_file:
|
||
+ {
|
||
+ ldlex_version_file ();
|
||
+ PUSH_ERROR (_("dynamic list"));
|
||
+ }
|
||
+ dynamic_list_nodes
|
||
+ {
|
||
+ ldlex_popstate ();
|
||
+ POP_ERROR ();
|
||
+ }
|
||
+ ;
|
||
+
|
||
+dynamic_list_nodes:
|
||
+ dynamic_list_node
|
||
+ | dynamic_list_nodes dynamic_list_node
|
||
+ ;
|
||
+
|
||
+dynamic_list_node:
|
||
+ '{' dynamic_list_tag '}' ';'
|
||
+ ;
|
||
+
|
||
+dynamic_list_tag:
|
||
+ vers_defns ';'
|
||
+ {
|
||
+ lang_append_dynamic_list (current_dynamic_list_p, $1);
|
||
+ }
|
||
+ ;
|
||
+
|
||
+/* This syntax is used within an external version script file. */
|
||
+
|
||
+version_script_file:
|
||
+ {
|
||
+ ldlex_version_file ();
|
||
+ PUSH_ERROR (_("VERSION script"));
|
||
+ }
|
||
+ vers_nodes
|
||
+ {
|
||
+ ldlex_popstate ();
|
||
+ POP_ERROR ();
|
||
+ }
|
||
+ ;
|
||
+
|
||
+/* This is used within a normal linker script file. */
|
||
+
|
||
+version:
|
||
+ {
|
||
+ ldlex_version_script ();
|
||
+ }
|
||
+ VERSIONK '{' vers_nodes '}'
|
||
+ {
|
||
+ ldlex_popstate ();
|
||
+ }
|
||
+ ;
|
||
+
|
||
+vers_nodes:
|
||
+ vers_node
|
||
+ | vers_nodes vers_node
|
||
+ ;
|
||
+
|
||
+vers_node:
|
||
+ '{' vers_tag '}' ';'
|
||
+ {
|
||
+ lang_register_vers_node (NULL, $2, NULL);
|
||
+ }
|
||
+ | VERS_TAG '{' vers_tag '}' ';'
|
||
+ {
|
||
+ lang_register_vers_node ($1, $3, NULL);
|
||
+ }
|
||
+ | VERS_TAG '{' vers_tag '}' verdep ';'
|
||
+ {
|
||
+ lang_register_vers_node ($1, $3, $5);
|
||
+ }
|
||
+ ;
|
||
+
|
||
+verdep:
|
||
+ VERS_TAG
|
||
+ {
|
||
+ $$ = lang_add_vers_depend (NULL, $1);
|
||
+ }
|
||
+ | verdep VERS_TAG
|
||
+ {
|
||
+ $$ = lang_add_vers_depend ($1, $2);
|
||
+ }
|
||
+ ;
|
||
+
|
||
+vers_tag:
|
||
+ /* empty */
|
||
+ {
|
||
+ $$ = lang_new_vers_node (NULL, NULL);
|
||
+ }
|
||
+ | vers_defns ';'
|
||
+ {
|
||
+ $$ = lang_new_vers_node ($1, NULL);
|
||
+ }
|
||
+ | GLOBAL ':' vers_defns ';'
|
||
+ {
|
||
+ $$ = lang_new_vers_node ($3, NULL);
|
||
+ }
|
||
+ | LOCAL ':' vers_defns ';'
|
||
+ {
|
||
+ $$ = lang_new_vers_node (NULL, $3);
|
||
+ }
|
||
+ | GLOBAL ':' vers_defns ';' LOCAL ':' vers_defns ';'
|
||
+ {
|
||
+ $$ = lang_new_vers_node ($3, $7);
|
||
+ }
|
||
+ ;
|
||
+
|
||
+vers_defns:
|
||
+ VERS_IDENTIFIER
|
||
+ {
|
||
+ $$ = lang_new_vers_pattern (NULL, $1, ldgram_vers_current_lang, false);
|
||
+ }
|
||
+ | NAME
|
||
+ {
|
||
+ $$ = lang_new_vers_pattern (NULL, $1, ldgram_vers_current_lang, true);
|
||
+ }
|
||
+ | vers_defns ';' VERS_IDENTIFIER
|
||
+ {
|
||
+ $$ = lang_new_vers_pattern ($1, $3, ldgram_vers_current_lang, false);
|
||
+ }
|
||
+ | vers_defns ';' NAME
|
||
+ {
|
||
+ $$ = lang_new_vers_pattern ($1, $3, ldgram_vers_current_lang, true);
|
||
+ }
|
||
+ | vers_defns ';' EXTERN NAME '{'
|
||
+ {
|
||
+ $<name>$ = ldgram_vers_current_lang;
|
||
+ ldgram_vers_current_lang = $4;
|
||
+ }
|
||
+ vers_defns opt_semicolon '}'
|
||
+ {
|
||
+ struct bfd_elf_version_expr *pat;
|
||
+ for (pat = $7; pat->next != NULL; pat = pat->next);
|
||
+ pat->next = $1;
|
||
+ $$ = $7;
|
||
+ ldgram_vers_current_lang = $<name>6;
|
||
+ }
|
||
+ | EXTERN NAME '{'
|
||
+ {
|
||
+ $<name>$ = ldgram_vers_current_lang;
|
||
+ ldgram_vers_current_lang = $2;
|
||
+ }
|
||
+ vers_defns opt_semicolon '}'
|
||
+ {
|
||
+ $$ = $5;
|
||
+ ldgram_vers_current_lang = $<name>4;
|
||
+ }
|
||
+ | GLOBAL
|
||
+ {
|
||
+ $$ = lang_new_vers_pattern (NULL, "global", ldgram_vers_current_lang, false);
|
||
+ }
|
||
+ | vers_defns ';' GLOBAL
|
||
+ {
|
||
+ $$ = lang_new_vers_pattern ($1, "global", ldgram_vers_current_lang, false);
|
||
+ }
|
||
+ | LOCAL
|
||
+ {
|
||
+ $$ = lang_new_vers_pattern (NULL, "local", ldgram_vers_current_lang, false);
|
||
+ }
|
||
+ | vers_defns ';' LOCAL
|
||
+ {
|
||
+ $$ = lang_new_vers_pattern ($1, "local", ldgram_vers_current_lang, false);
|
||
+ }
|
||
+ | EXTERN
|
||
+ {
|
||
+ $$ = lang_new_vers_pattern (NULL, "extern", ldgram_vers_current_lang, false);
|
||
+ }
|
||
+ | vers_defns ';' EXTERN
|
||
+ {
|
||
+ $$ = lang_new_vers_pattern ($1, "extern", ldgram_vers_current_lang, false);
|
||
+ }
|
||
+ ;
|
||
+
|
||
+opt_semicolon:
|
||
+ /* empty */
|
||
+ | ';'
|
||
+ ;
|
||
+
|
||
+%%
|
||
+void
|
||
+yyerror(arg)
|
||
+ const char *arg;
|
||
+{
|
||
+ if (ldfile_assumed_script)
|
||
+ einfo (_("%P:%s: file format not recognized; treating as linker script\n"),
|
||
+ ldlex_filename ());
|
||
+ if (error_index > 0 && error_index < ERROR_NAME_MAX)
|
||
+ einfo (_("%F%P:%pS: %s in %s\n"), NULL, arg, error_names[error_index - 1]);
|
||
+ else
|
||
+ einfo ("%F%P:%pS: %s\n", NULL, arg);
|
||
+}
|
||
diff -rupN binutils.orig/ld/ldlang.c binutils-2.41/ld/ldlang.c
|
||
--- binutils.orig/ld/ldlang.c 2024-05-13 13:03:47.804601777 +0100
|
||
+++ binutils-2.41/ld/ldlang.c 2024-05-13 13:04:08.599633306 +0100
|
||
@@ -1282,6 +1282,7 @@ output_section_statement_newfunc (struct
|
||
ret->s.output_section_statement.section_alignment = NULL;
|
||
ret->s.output_section_statement.block_value = 1;
|
||
lang_list_init (&ret->s.output_section_statement.children);
|
||
+ lang_list_init (&ret->s.output_section_statement.sort_children);
|
||
lang_statement_append (stat_ptr, &ret->s, &ret->s.header.next);
|
||
|
||
/* For every output section statement added to the list, except the
|
||
@@ -7566,13 +7567,22 @@ lang_enter_output_section_statement (con
|
||
lang_output_section_statement_type *os;
|
||
|
||
os = lang_output_section_statement_lookup (output_section_statement_name,
|
||
- constraint, 2);
|
||
+ constraint,
|
||
+ in_section_ordering ? 0 : 2);
|
||
+ if (os == NULL) /* && in_section_ordering */
|
||
+ einfo (_("%F%P:%pS: error: output section '%s' must already exist\n"),
|
||
+ NULL, output_section_statement_name);
|
||
current_section = os;
|
||
|
||
+ /* Make next things chain into subchain of this. */
|
||
+ push_stat_ptr (in_section_ordering ? &os->sort_children : &os->children);
|
||
+
|
||
+ if (in_section_ordering)
|
||
+ return os;
|
||
+
|
||
if (os->addr_tree == NULL)
|
||
- {
|
||
- os->addr_tree = address_exp;
|
||
- }
|
||
+ os->addr_tree = address_exp;
|
||
+
|
||
os->sectype = sectype;
|
||
if (sectype == type_section || sectype == typed_readonly_section)
|
||
os->sectype_value = sectype_value;
|
||
@@ -7582,9 +7592,6 @@ lang_enter_output_section_statement (con
|
||
os->flags = SEC_NO_FLAGS;
|
||
os->block_value = 1;
|
||
|
||
- /* Make next things chain into subchain of this. */
|
||
- push_stat_ptr (&os->children);
|
||
-
|
||
os->align_lma_with_input = align_with_input == ALIGN_WITH_INPUT;
|
||
if (os->align_lma_with_input && align != NULL)
|
||
einfo (_("%F%P:%pS: error: align with input and explicit align specified\n"),
|
||
@@ -7924,21 +7931,6 @@ find_rescan_insertion (lang_input_statem
|
||
return iter;
|
||
}
|
||
|
||
-/* Insert SRCLIST into DESTLIST after given element by chaining
|
||
- on FIELD as the next-pointer. (Counterintuitively does not need
|
||
- a pointer to the actual after-node itself, just its chain field.) */
|
||
-
|
||
-static void
|
||
-lang_list_insert_after (lang_statement_list_type *destlist,
|
||
- lang_statement_list_type *srclist,
|
||
- lang_statement_union_type **field)
|
||
-{
|
||
- *(srclist->tail) = *field;
|
||
- *field = srclist->head;
|
||
- if (destlist->tail == field)
|
||
- destlist->tail = srclist->tail;
|
||
-}
|
||
-
|
||
/* Detach new nodes added to DESTLIST since the time ORIGLIST
|
||
was taken as a copy of it and leave them in ORIGLIST. */
|
||
|
||
@@ -7986,6 +7978,21 @@ find_next_input_statement (lang_statemen
|
||
}
|
||
#endif /* BFD_SUPPORTS_PLUGINS */
|
||
|
||
+/* Insert SRCLIST into DESTLIST after given element by chaining
|
||
+ on FIELD as the next-pointer. (Counterintuitively does not need
|
||
+ a pointer to the actual after-node itself, just its chain field.) */
|
||
+
|
||
+static void
|
||
+lang_list_insert_after (lang_statement_list_type *destlist,
|
||
+ lang_statement_list_type *srclist,
|
||
+ lang_statement_union_type **field)
|
||
+{
|
||
+ *(srclist->tail) = *field;
|
||
+ *field = srclist->head;
|
||
+ if (destlist->tail == field)
|
||
+ destlist->tail = srclist->tail;
|
||
+}
|
||
+
|
||
/* Add NAME to the list of garbage collection entry points. */
|
||
|
||
void
|
||
@@ -8080,9 +8087,34 @@ reset_resolved_wilds (void)
|
||
lang_for_each_statement (reset_one_wild);
|
||
}
|
||
|
||
+/* For each output section statement, splice any entries on the
|
||
+ sort_children list before the first wild statement on the children
|
||
+ list. */
|
||
+
|
||
+static void
|
||
+lang_os_merge_sort_children (void)
|
||
+{
|
||
+ lang_output_section_statement_type *os;
|
||
+ for (os = (void *) lang_os_list.head; os != NULL; os = os->next)
|
||
+ {
|
||
+ if (os->sort_children.head != NULL)
|
||
+ {
|
||
+ lang_statement_union_type **where;
|
||
+ for (where = &os->children.head;
|
||
+ *where != NULL;
|
||
+ where = &(*where)->header.next)
|
||
+ if ((*where)->header.type == lang_wild_statement_enum)
|
||
+ break;
|
||
+ lang_list_insert_after (&os->children, &os->sort_children, where);
|
||
+ }
|
||
+ }
|
||
+}
|
||
+
|
||
void
|
||
lang_process (void)
|
||
{
|
||
+ lang_os_merge_sort_children ();
|
||
+
|
||
/* Finalize dynamic list. */
|
||
if (link_info.dynamic_list)
|
||
lang_finalize_version_expr_head (&link_info.dynamic_list->head);
|
||
@@ -8764,6 +8796,10 @@ lang_leave_output_section_statement (fil
|
||
lang_output_section_phdr_list *phdrs,
|
||
const char *lma_memspec)
|
||
{
|
||
+ pop_stat_ptr ();
|
||
+ if (in_section_ordering)
|
||
+ return;
|
||
+
|
||
lang_get_regions (¤t_section->region,
|
||
¤t_section->lma_region,
|
||
memspec, lma_memspec,
|
||
@@ -8772,7 +8808,6 @@ lang_leave_output_section_statement (fil
|
||
|
||
current_section->fill = fill;
|
||
current_section->phdrs = phdrs;
|
||
- pop_stat_ptr ();
|
||
}
|
||
|
||
/* Set the output format type. -oformat overrides scripts. */
|
||
diff -rupN binutils.orig/ld/ldlang.c.orig binutils-2.41/ld/ldlang.c.orig
|
||
--- binutils.orig/ld/ldlang.c.orig 1970-01-01 01:00:00.000000000 +0100
|
||
+++ binutils-2.41/ld/ldlang.c.orig 2023-07-03 00:00:00.000000000 +0100
|
||
@@ -0,0 +1,9907 @@
|
||
+/* Linker command language support.
|
||
+ Copyright (C) 1991-2023 Free Software Foundation, Inc.
|
||
+
|
||
+ This file is part of the GNU Binutils.
|
||
+
|
||
+ This program is free software; you can redistribute it and/or modify
|
||
+ it under the terms of the GNU General Public License as published by
|
||
+ the Free Software Foundation; either version 3 of the License, or
|
||
+ (at your option) any later version.
|
||
+
|
||
+ This program is distributed in the hope that it will be useful,
|
||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
+ GNU General Public License for more details.
|
||
+
|
||
+ You should have received a copy of the GNU General Public License
|
||
+ along with this program; if not, write to the Free Software
|
||
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
|
||
+ MA 02110-1301, USA. */
|
||
+
|
||
+#include "sysdep.h"
|
||
+#include <limits.h>
|
||
+#include "bfd.h"
|
||
+#include "libiberty.h"
|
||
+#include "filenames.h"
|
||
+#include "safe-ctype.h"
|
||
+#include "obstack.h"
|
||
+#include "bfdlink.h"
|
||
+#include "ctf-api.h"
|
||
+#include "ld.h"
|
||
+#include "ldmain.h"
|
||
+#include "ldexp.h"
|
||
+#include "ldlang.h"
|
||
+#include <ldgram.h>
|
||
+#include "ldlex.h"
|
||
+#include "ldmisc.h"
|
||
+#include "ldctor.h"
|
||
+#include "ldfile.h"
|
||
+#include "ldemul.h"
|
||
+#include "fnmatch.h"
|
||
+#include "demangle.h"
|
||
+#include "hashtab.h"
|
||
+#include "elf-bfd.h"
|
||
+#include "bfdver.h"
|
||
+
|
||
+#if BFD_SUPPORTS_PLUGINS
|
||
+#include "plugin.h"
|
||
+#endif
|
||
+
|
||
+#ifndef offsetof
|
||
+#define offsetof(TYPE, MEMBER) ((size_t) & (((TYPE*) 0)->MEMBER))
|
||
+#endif
|
||
+
|
||
+/* Convert between addresses in bytes and sizes in octets.
|
||
+ For currently supported targets, octets_per_byte is always a power
|
||
+ of two, so we can use shifts. */
|
||
+#define TO_ADDR(X) ((X) >> opb_shift)
|
||
+#define TO_SIZE(X) ((X) << opb_shift)
|
||
+
|
||
+/* Local variables. */
|
||
+static struct obstack stat_obstack;
|
||
+static struct obstack map_obstack;
|
||
+static struct obstack pt_obstack;
|
||
+
|
||
+#define obstack_chunk_alloc xmalloc
|
||
+#define obstack_chunk_free free
|
||
+static const char *entry_symbol_default = "start";
|
||
+static bool map_head_is_link_order = false;
|
||
+static lang_output_section_statement_type *default_common_section;
|
||
+static bool map_option_f;
|
||
+static bfd_vma print_dot;
|
||
+static lang_input_statement_type *first_file;
|
||
+static const char *current_target;
|
||
+static lang_statement_list_type *stat_save[10];
|
||
+static lang_statement_list_type **stat_save_ptr = &stat_save[0];
|
||
+static struct unique_sections *unique_section_list;
|
||
+static struct asneeded_minfo *asneeded_list_head;
|
||
+static unsigned int opb_shift = 0;
|
||
+
|
||
+/* Forward declarations. */
|
||
+static void exp_init_os (etree_type *);
|
||
+static lang_input_statement_type *lookup_name (const char *);
|
||
+static bool wont_add_section_p (asection *,
|
||
+ lang_output_section_statement_type *);
|
||
+static void insert_undefined (const char *);
|
||
+static bool sort_def_symbol (struct bfd_link_hash_entry *, void *);
|
||
+static lang_statement_union_type *new_statement (enum statement_enum type,
|
||
+ size_t size,
|
||
+ lang_statement_list_type *list);
|
||
+static void print_statement (lang_statement_union_type *,
|
||
+ lang_output_section_statement_type *);
|
||
+static void print_statement_list (lang_statement_union_type *,
|
||
+ lang_output_section_statement_type *);
|
||
+static void print_statements (void);
|
||
+static void print_input_section (asection *, bool);
|
||
+static bool lang_one_common (struct bfd_link_hash_entry *, void *);
|
||
+static void lang_record_phdrs (void);
|
||
+static void lang_do_version_exports_section (void);
|
||
+static void lang_finalize_version_expr_head
|
||
+ (struct bfd_elf_version_expr_head *);
|
||
+static void lang_do_memory_regions (bool);
|
||
+
|
||
+/* Exported variables. */
|
||
+const char *output_target;
|
||
+lang_output_section_statement_type *abs_output_section;
|
||
+/* Header for list of statements corresponding to any files involved in the
|
||
+ link, either specified from the command-line or added implicitely (eg.
|
||
+ archive member used to resolved undefined symbol, wildcard statement from
|
||
+ linker script, etc.). Next pointer is in next field of a
|
||
+ lang_statement_header_type (reached via header field in a
|
||
+ lang_statement_union). */
|
||
+lang_statement_list_type statement_list;
|
||
+lang_statement_list_type lang_os_list;
|
||
+lang_statement_list_type *stat_ptr = &statement_list;
|
||
+/* Header for list of statements corresponding to files used in the final
|
||
+ executable. This can be either object file specified on the command-line
|
||
+ or library member resolving an undefined reference. Next pointer is in next
|
||
+ field of a lang_input_statement_type (reached via input_statement field in a
|
||
+ lang_statement_union). */
|
||
+lang_statement_list_type file_chain = { NULL, NULL };
|
||
+/* Header for list of statements corresponding to files specified on the
|
||
+ command-line for linking. It thus contains real object files and archive
|
||
+ but not archive members. Next pointer is in next_real_file field of a
|
||
+ lang_input_statement_type statement (reached via input_statement field in a
|
||
+ lang_statement_union). */
|
||
+lang_statement_list_type input_file_chain;
|
||
+static const char *current_input_file;
|
||
+struct bfd_elf_dynamic_list **current_dynamic_list_p;
|
||
+struct bfd_sym_chain entry_symbol = { NULL, NULL };
|
||
+const char *entry_section = ".text";
|
||
+struct lang_input_statement_flags input_flags;
|
||
+bool entry_from_cmdline;
|
||
+bool lang_has_input_file = false;
|
||
+bool had_output_filename = false;
|
||
+bool lang_float_flag = false;
|
||
+bool delete_output_file_on_failure = false;
|
||
+bool enable_linker_version = false;
|
||
+struct lang_phdr *lang_phdr_list;
|
||
+struct lang_nocrossrefs *nocrossref_list;
|
||
+struct asneeded_minfo **asneeded_list_tail;
|
||
+#ifdef ENABLE_LIBCTF
|
||
+static ctf_dict_t *ctf_output;
|
||
+#endif
|
||
+
|
||
+/* Functions that traverse the linker script and might evaluate
|
||
+ DEFINED() need to increment this at the start of the traversal. */
|
||
+int lang_statement_iteration = 0;
|
||
+
|
||
+/* Count times through one_lang_size_sections_pass after mark phase. */
|
||
+static int lang_sizing_iteration = 0;
|
||
+
|
||
+/* Return TRUE if the PATTERN argument is a wildcard pattern.
|
||
+ Although backslashes are treated specially if a pattern contains
|
||
+ wildcards, we do not consider the mere presence of a backslash to
|
||
+ be enough to cause the pattern to be treated as a wildcard.
|
||
+ That lets us handle DOS filenames more naturally. */
|
||
+#define wildcardp(pattern) (strpbrk ((pattern), "?*[") != NULL)
|
||
+
|
||
+#define new_stat(x, y) \
|
||
+ (x##_type *) new_statement (x##_enum, sizeof (x##_type), y)
|
||
+
|
||
+#define outside_section_address(q) \
|
||
+ ((q)->output_offset + (q)->output_section->vma)
|
||
+
|
||
+#define outside_symbol_address(q) \
|
||
+ ((q)->value + outside_section_address (q->section))
|
||
+
|
||
+/* CTF sections smaller than this are not compressed: compression of
|
||
+ dictionaries this small doesn't gain much, and this lets consumers mmap the
|
||
+ sections directly out of the ELF file and use them with no decompression
|
||
+ overhead if they want to. */
|
||
+#define CTF_COMPRESSION_THRESHOLD 4096
|
||
+
|
||
+void *
|
||
+stat_alloc (size_t size)
|
||
+{
|
||
+ return obstack_alloc (&stat_obstack, size);
|
||
+}
|
||
+
|
||
+/* Code for handling simple wildcards without going through fnmatch,
|
||
+ which can be expensive because of charset translations etc. */
|
||
+
|
||
+/* A simple wild is a literal string followed by a single '*',
|
||
+ where the literal part is at least 4 characters long. */
|
||
+
|
||
+static bool
|
||
+is_simple_wild (const char *name)
|
||
+{
|
||
+ size_t len = strcspn (name, "*?[");
|
||
+ return len >= 4 && name[len] == '*' && name[len + 1] == '\0';
|
||
+}
|
||
+
|
||
+static bool
|
||
+match_simple_wild (const char *pattern, const char *name)
|
||
+{
|
||
+ /* The first four characters of the pattern are guaranteed valid
|
||
+ non-wildcard characters. So we can go faster. */
|
||
+ if (pattern[0] != name[0] || pattern[1] != name[1]
|
||
+ || pattern[2] != name[2] || pattern[3] != name[3])
|
||
+ return false;
|
||
+
|
||
+ pattern += 4;
|
||
+ name += 4;
|
||
+ while (*pattern != '*')
|
||
+ if (*name++ != *pattern++)
|
||
+ return false;
|
||
+
|
||
+ return true;
|
||
+}
|
||
+
|
||
+static int
|
||
+name_match (const char *pattern, const char *name)
|
||
+{
|
||
+ if (is_simple_wild (pattern))
|
||
+ return !match_simple_wild (pattern, name);
|
||
+ if (wildcardp (pattern))
|
||
+ return fnmatch (pattern, name, 0);
|
||
+ return strcmp (pattern, name);
|
||
+}
|
||
+
|
||
+/* Given an analyzed wildcard_spec SPEC, match it against NAME,
|
||
+ returns zero on a match, non-zero if there's no match. */
|
||
+
|
||
+static int
|
||
+spec_match (const struct wildcard_spec *spec, const char *name)
|
||
+{
|
||
+ size_t nl = spec->namelen;
|
||
+ size_t pl = spec->prefixlen;
|
||
+ size_t sl = spec->suffixlen;
|
||
+ size_t inputlen = strlen (name);
|
||
+ int r;
|
||
+
|
||
+ if (pl)
|
||
+ {
|
||
+ if (inputlen < pl)
|
||
+ return 1;
|
||
+
|
||
+ r = memcmp (spec->name, name, pl);
|
||
+ if (r)
|
||
+ return r;
|
||
+ }
|
||
+
|
||
+ if (sl)
|
||
+ {
|
||
+ if (inputlen < sl)
|
||
+ return 1;
|
||
+
|
||
+ r = memcmp (spec->name + nl - sl, name + inputlen - sl, sl);
|
||
+ if (r)
|
||
+ return r;
|
||
+ }
|
||
+
|
||
+ if (nl == pl + sl + 1 && spec->name[pl] == '*')
|
||
+ return 0;
|
||
+
|
||
+ if (nl > pl)
|
||
+ return fnmatch (spec->name + pl, name + pl, 0);
|
||
+
|
||
+ if (inputlen >= nl)
|
||
+ return name[nl];
|
||
+
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+static char *
|
||
+ldirname (const char *name)
|
||
+{
|
||
+ const char *base = lbasename (name);
|
||
+ char *dirname;
|
||
+
|
||
+ while (base > name && IS_DIR_SEPARATOR (base[-1]))
|
||
+ --base;
|
||
+ if (base == name)
|
||
+ return strdup (".");
|
||
+ dirname = strdup (name);
|
||
+ dirname[base - name] = '\0';
|
||
+ return dirname;
|
||
+}
|
||
+
|
||
+/* If PATTERN is of the form archive:file, return a pointer to the
|
||
+ separator. If not, return NULL. */
|
||
+
|
||
+static char *
|
||
+archive_path (const char *pattern)
|
||
+{
|
||
+ char *p = NULL;
|
||
+
|
||
+ if (link_info.path_separator == 0)
|
||
+ return p;
|
||
+
|
||
+ p = strchr (pattern, link_info.path_separator);
|
||
+#ifdef HAVE_DOS_BASED_FILE_SYSTEM
|
||
+ if (p == NULL || link_info.path_separator != ':')
|
||
+ return p;
|
||
+
|
||
+ /* Assume a match on the second char is part of drive specifier,
|
||
+ as in "c:\silly.dos". */
|
||
+ if (p == pattern + 1 && ISALPHA (*pattern))
|
||
+ p = strchr (p + 1, link_info.path_separator);
|
||
+#endif
|
||
+ return p;
|
||
+}
|
||
+
|
||
+/* Given that FILE_SPEC results in a non-NULL SEP result from archive_path,
|
||
+ return whether F matches FILE_SPEC. */
|
||
+
|
||
+static bool
|
||
+input_statement_is_archive_path (const char *file_spec, char *sep,
|
||
+ lang_input_statement_type *f)
|
||
+{
|
||
+ bool match = false;
|
||
+
|
||
+ if ((*(sep + 1) == 0
|
||
+ || name_match (sep + 1, f->filename) == 0)
|
||
+ && ((sep != file_spec)
|
||
+ == (f->the_bfd != NULL && f->the_bfd->my_archive != NULL)))
|
||
+ {
|
||
+ match = true;
|
||
+
|
||
+ if (sep != file_spec)
|
||
+ {
|
||
+ const char *aname = bfd_get_filename (f->the_bfd->my_archive);
|
||
+ *sep = 0;
|
||
+ match = name_match (file_spec, aname) == 0;
|
||
+ *sep = link_info.path_separator;
|
||
+ }
|
||
+ }
|
||
+ return match;
|
||
+}
|
||
+
|
||
+static bool
|
||
+unique_section_p (const asection *sec,
|
||
+ const lang_output_section_statement_type *os)
|
||
+{
|
||
+ struct unique_sections *unam;
|
||
+ const char *secnam;
|
||
+
|
||
+ if (!link_info.resolve_section_groups
|
||
+ && sec->owner != NULL
|
||
+ && bfd_is_group_section (sec->owner, sec))
|
||
+ return !(os != NULL
|
||
+ && strcmp (os->name, DISCARD_SECTION_NAME) == 0);
|
||
+
|
||
+ secnam = sec->name;
|
||
+ for (unam = unique_section_list; unam; unam = unam->next)
|
||
+ if (name_match (unam->name, secnam) == 0)
|
||
+ return true;
|
||
+
|
||
+ return false;
|
||
+}
|
||
+
|
||
+/* Generic traversal routines for finding matching sections. */
|
||
+
|
||
+/* Return true if FILE matches a pattern in EXCLUDE_LIST, otherwise return
|
||
+ false. */
|
||
+
|
||
+static bool
|
||
+walk_wild_file_in_exclude_list (struct name_list *exclude_list,
|
||
+ lang_input_statement_type *file)
|
||
+{
|
||
+ struct name_list *list_tmp;
|
||
+
|
||
+ for (list_tmp = exclude_list;
|
||
+ list_tmp;
|
||
+ list_tmp = list_tmp->next)
|
||
+ {
|
||
+ char *p = archive_path (list_tmp->name);
|
||
+
|
||
+ if (p != NULL)
|
||
+ {
|
||
+ if (input_statement_is_archive_path (list_tmp->name, p, file))
|
||
+ return true;
|
||
+ }
|
||
+
|
||
+ else if (name_match (list_tmp->name, file->filename) == 0)
|
||
+ return true;
|
||
+
|
||
+ /* FIXME: Perhaps remove the following at some stage? Matching
|
||
+ unadorned archives like this was never documented and has
|
||
+ been superceded by the archive:path syntax. */
|
||
+ else if (file->the_bfd != NULL
|
||
+ && file->the_bfd->my_archive != NULL
|
||
+ && name_match (list_tmp->name,
|
||
+ bfd_get_filename (file->the_bfd->my_archive)) == 0)
|
||
+ return true;
|
||
+ }
|
||
+
|
||
+ return false;
|
||
+}
|
||
+
|
||
+/* Add SECTION (from input FILE) to the list of matching sections
|
||
+ within PTR (the matching wildcard is SEC). */
|
||
+
|
||
+static void
|
||
+add_matching_section (lang_wild_statement_type *ptr,
|
||
+ struct wildcard_list *sec,
|
||
+ asection *section,
|
||
+ lang_input_statement_type *file)
|
||
+{
|
||
+ lang_input_matcher_type *new_section;
|
||
+ /* Add a section reference to the list. */
|
||
+ new_section = new_stat (lang_input_matcher, &ptr->matching_sections);
|
||
+ new_section->section = section;
|
||
+ new_section->pattern = sec;
|
||
+ new_section->input_stmt = file;
|
||
+}
|
||
+
|
||
+/* Process section S (from input file FILE) in relation to wildcard
|
||
+ statement PTR. We already know that a prefix of the name of S matches
|
||
+ some wildcard in PTR's wildcard list. Here we check if the filename
|
||
+ matches as well (if it's specified) and if any of the wildcards in fact
|
||
+ does match. */
|
||
+
|
||
+static void
|
||
+walk_wild_section_match (lang_wild_statement_type *ptr,
|
||
+ lang_input_statement_type *file,
|
||
+ asection *s)
|
||
+{
|
||
+ struct wildcard_list *sec;
|
||
+ const char *file_spec = ptr->filename;
|
||
+ char *p;
|
||
+
|
||
+ /* Check if filenames match. */
|
||
+ if (file_spec == NULL)
|
||
+ ;
|
||
+ else if ((p = archive_path (file_spec)) != NULL)
|
||
+ {
|
||
+ if (!input_statement_is_archive_path (file_spec, p, file))
|
||
+ return;
|
||
+ }
|
||
+ else if (wildcardp (file_spec))
|
||
+ {
|
||
+ if (fnmatch (file_spec, file->filename, 0) != 0)
|
||
+ return;
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ /* XXX Matching against non-wildcard filename in wild statements
|
||
+ was done by going through lookup_name, which uses
|
||
+ ->local_sym_name to compare against, not ->filename. We retain
|
||
+ this behaviour even though the above code paths use filename.
|
||
+ It would be more logical to use it here as well, in which
|
||
+ case the above wildcard() arm could be folded into this by using
|
||
+ name_match. This would also solve the worry of what to do
|
||
+ about unset local_sym_name (in which case lookup_name simply adds
|
||
+ the input file again). */
|
||
+ const char *filename = file->local_sym_name;
|
||
+ lang_input_statement_type *arch_is;
|
||
+ if (filename && filename_cmp (filename, file_spec) == 0)
|
||
+ ;
|
||
+ /* FIXME: see also walk_wild_file_in_exclude_list for why we
|
||
+ also check parents BFD (local_sym_)name to match input statements
|
||
+ with unadorned archive names. */
|
||
+ else if (file->the_bfd
|
||
+ && file->the_bfd->my_archive
|
||
+ && (arch_is = bfd_usrdata (file->the_bfd->my_archive))
|
||
+ && arch_is->local_sym_name
|
||
+ && filename_cmp (arch_is->local_sym_name, file_spec) == 0)
|
||
+ ;
|
||
+ else
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ /* If filename is excluded we're done. */
|
||
+ if (walk_wild_file_in_exclude_list (ptr->exclude_name_list, file))
|
||
+ return;
|
||
+
|
||
+ /* Check section name against each wildcard spec. If there's no
|
||
+ wildcard all sections match. */
|
||
+ sec = ptr->section_list;
|
||
+ if (sec == NULL)
|
||
+ add_matching_section (ptr, sec, s, file);
|
||
+ else
|
||
+ {
|
||
+ const char *sname = bfd_section_name (s);
|
||
+ for (; sec != NULL; sec = sec->next)
|
||
+ {
|
||
+ if (sec->spec.name != NULL
|
||
+ && spec_match (&sec->spec, sname) != 0)
|
||
+ continue;
|
||
+
|
||
+ /* Don't process sections from files which were excluded. */
|
||
+ if (!walk_wild_file_in_exclude_list (sec->spec.exclude_name_list,
|
||
+ file))
|
||
+ add_matching_section (ptr, sec, s, file);
|
||
+ }
|
||
+ }
|
||
+}
|
||
+
|
||
+/* Return the numerical value of the init_priority attribute from
|
||
+ section name NAME. */
|
||
+
|
||
+static int
|
||
+get_init_priority (const asection *sec)
|
||
+{
|
||
+ const char *name = bfd_section_name (sec);
|
||
+ const char *dot;
|
||
+
|
||
+ /* GCC uses the following section names for the init_priority
|
||
+ attribute with numerical values 101 to 65535 inclusive. A
|
||
+ lower value means a higher priority.
|
||
+
|
||
+ 1: .init_array.NNNNN/.fini_array.NNNNN: Where NNNNN is the
|
||
+ decimal numerical value of the init_priority attribute.
|
||
+ The order of execution in .init_array is forward and
|
||
+ .fini_array is backward.
|
||
+ 2: .ctors.NNNNN/.dtors.NNNNN: Where NNNNN is 65535 minus the
|
||
+ decimal numerical value of the init_priority attribute.
|
||
+ The order of execution in .ctors is backward and .dtors
|
||
+ is forward.
|
||
+
|
||
+ .init_array.NNNNN sections would normally be placed in an output
|
||
+ .init_array section, .fini_array.NNNNN in .fini_array,
|
||
+ .ctors.NNNNN in .ctors, and .dtors.NNNNN in .dtors. This means
|
||
+ we should sort by increasing number (and could just use
|
||
+ SORT_BY_NAME in scripts). However if .ctors.NNNNN sections are
|
||
+ being placed in .init_array (which may also contain
|
||
+ .init_array.NNNNN sections) or .dtors.NNNNN sections are being
|
||
+ placed in .fini_array then we need to extract the init_priority
|
||
+ attribute and sort on that. */
|
||
+ dot = strrchr (name, '.');
|
||
+ if (dot != NULL && ISDIGIT (dot[1]))
|
||
+ {
|
||
+ char *end;
|
||
+ unsigned long init_priority = strtoul (dot + 1, &end, 10);
|
||
+ if (*end == 0)
|
||
+ {
|
||
+ if (dot == name + 6
|
||
+ && (strncmp (name, ".ctors", 6) == 0
|
||
+ || strncmp (name, ".dtors", 6) == 0))
|
||
+ init_priority = 65535 - init_priority;
|
||
+ if (init_priority <= INT_MAX)
|
||
+ return init_priority;
|
||
+ }
|
||
+ }
|
||
+ return -1;
|
||
+}
|
||
+
|
||
+/* Compare sections ASEC and BSEC according to SORT. */
|
||
+
|
||
+static int
|
||
+compare_section (sort_type sort, asection *asec, asection *bsec)
|
||
+{
|
||
+ int ret;
|
||
+ int a_priority, b_priority;
|
||
+
|
||
+ switch (sort)
|
||
+ {
|
||
+ default:
|
||
+ abort ();
|
||
+
|
||
+ case by_init_priority:
|
||
+ a_priority = get_init_priority (asec);
|
||
+ b_priority = get_init_priority (bsec);
|
||
+ if (a_priority < 0 || b_priority < 0)
|
||
+ goto sort_by_name;
|
||
+ ret = a_priority - b_priority;
|
||
+ if (ret)
|
||
+ break;
|
||
+ else
|
||
+ goto sort_by_name;
|
||
+
|
||
+ case by_alignment_name:
|
||
+ ret = bfd_section_alignment (bsec) - bfd_section_alignment (asec);
|
||
+ if (ret)
|
||
+ break;
|
||
+ /* Fall through. */
|
||
+
|
||
+ case by_name:
|
||
+ sort_by_name:
|
||
+ ret = strcmp (bfd_section_name (asec), bfd_section_name (bsec));
|
||
+ break;
|
||
+
|
||
+ case by_name_alignment:
|
||
+ ret = strcmp (bfd_section_name (asec), bfd_section_name (bsec));
|
||
+ if (ret)
|
||
+ break;
|
||
+ /* Fall through. */
|
||
+
|
||
+ case by_alignment:
|
||
+ ret = bfd_section_alignment (bsec) - bfd_section_alignment (asec);
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ return ret;
|
||
+}
|
||
+
|
||
+/* PE puts the sort key in the input statement. */
|
||
+
|
||
+static const char *
|
||
+sort_filename (bfd *abfd)
|
||
+{
|
||
+ lang_input_statement_type *is = bfd_usrdata (abfd);
|
||
+ if (is->sort_key)
|
||
+ return is->sort_key;
|
||
+ return bfd_get_filename (abfd);
|
||
+}
|
||
+
|
||
+/* Handle wildcard sorting. This returns the place in a binary search tree
|
||
+ where this FILE:SECTION should be inserted for wild statement WILD where
|
||
+ the spec SEC was the matching one. The tree is later linearized. */
|
||
+
|
||
+static lang_section_bst_type **
|
||
+wild_sort (lang_wild_statement_type *wild,
|
||
+ struct wildcard_list *sec,
|
||
+ lang_input_statement_type *file,
|
||
+ asection *section)
|
||
+{
|
||
+ lang_section_bst_type **tree;
|
||
+
|
||
+ if (!wild->filenames_sorted
|
||
+ && (sec == NULL || sec->spec.sorted == none
|
||
+ || sec->spec.sorted == by_none))
|
||
+ {
|
||
+ /* We might be called even if _this_ spec doesn't need sorting,
|
||
+ in which case we simply append at the right end of tree. */
|
||
+ return wild->rightmost;
|
||
+ }
|
||
+
|
||
+ tree = &wild->tree;
|
||
+ while (*tree)
|
||
+ {
|
||
+ /* Sorting by filename takes precedence over sorting by section
|
||
+ name. */
|
||
+
|
||
+ if (wild->filenames_sorted)
|
||
+ {
|
||
+ const char *fn, *ln;
|
||
+ bool fa, la;
|
||
+ int i;
|
||
+ asection *lsec = (*tree)->section;
|
||
+
|
||
+ /* The PE support for the .idata section as generated by
|
||
+ dlltool assumes that files will be sorted by the name of
|
||
+ the archive and then the name of the file within the
|
||
+ archive. */
|
||
+
|
||
+ fa = file->the_bfd->my_archive != NULL;
|
||
+ if (fa)
|
||
+ fn = sort_filename (file->the_bfd->my_archive);
|
||
+ else
|
||
+ fn = sort_filename (file->the_bfd);
|
||
+
|
||
+ la = lsec->owner->my_archive != NULL;
|
||
+ if (la)
|
||
+ ln = sort_filename (lsec->owner->my_archive);
|
||
+ else
|
||
+ ln = sort_filename (lsec->owner);
|
||
+
|
||
+ i = filename_cmp (fn, ln);
|
||
+ if (i > 0)
|
||
+ { tree = &((*tree)->right); continue; }
|
||
+ else if (i < 0)
|
||
+ { tree = &((*tree)->left); continue; }
|
||
+
|
||
+ if (fa || la)
|
||
+ {
|
||
+ if (fa)
|
||
+ fn = sort_filename (file->the_bfd);
|
||
+ if (la)
|
||
+ ln = sort_filename (lsec->owner);
|
||
+
|
||
+ i = filename_cmp (fn, ln);
|
||
+ if (i > 0)
|
||
+ { tree = &((*tree)->right); continue; }
|
||
+ else if (i < 0)
|
||
+ { tree = &((*tree)->left); continue; }
|
||
+ }
|
||
+ }
|
||
+
|
||
+ /* Here either the files are not sorted by name, or we are
|
||
+ looking at the sections for this file. */
|
||
+
|
||
+ /* Find the correct node to append this section. */
|
||
+ if (sec && sec->spec.sorted != none && sec->spec.sorted != by_none
|
||
+ && compare_section (sec->spec.sorted, section, (*tree)->section) < 0)
|
||
+ tree = &((*tree)->left);
|
||
+ else
|
||
+ tree = &((*tree)->right);
|
||
+ }
|
||
+
|
||
+ return tree;
|
||
+}
|
||
+
|
||
+/* Use wild_sort to build a BST to sort sections. */
|
||
+
|
||
+static void
|
||
+output_section_callback_sort (lang_wild_statement_type *ptr,
|
||
+ struct wildcard_list *sec,
|
||
+ asection *section,
|
||
+ lang_input_statement_type *file,
|
||
+ void *output)
|
||
+{
|
||
+ lang_section_bst_type *node;
|
||
+ lang_section_bst_type **tree;
|
||
+ lang_output_section_statement_type *os;
|
||
+
|
||
+ os = (lang_output_section_statement_type *) output;
|
||
+
|
||
+ if (unique_section_p (section, os))
|
||
+ return;
|
||
+
|
||
+ /* Don't add sections to the tree when we already know that
|
||
+ lang_add_section won't do anything with it. */
|
||
+ if (wont_add_section_p (section, os))
|
||
+ return;
|
||
+
|
||
+ node = (lang_section_bst_type *) xmalloc (sizeof (lang_section_bst_type));
|
||
+ node->left = 0;
|
||
+ node->right = 0;
|
||
+ node->section = section;
|
||
+ node->pattern = ptr->section_list;
|
||
+
|
||
+ tree = wild_sort (ptr, sec, file, section);
|
||
+ if (tree != NULL)
|
||
+ {
|
||
+ *tree = node;
|
||
+ if (tree == ptr->rightmost)
|
||
+ ptr->rightmost = &node->right;
|
||
+ }
|
||
+}
|
||
+
|
||
+/* Convert a sorted sections' BST back to list form. */
|
||
+
|
||
+static void
|
||
+output_section_callback_tree_to_list (lang_wild_statement_type *ptr,
|
||
+ lang_section_bst_type *tree,
|
||
+ void *output)
|
||
+{
|
||
+ if (tree->left)
|
||
+ output_section_callback_tree_to_list (ptr, tree->left, output);
|
||
+
|
||
+ lang_add_section (&ptr->children, tree->section, tree->pattern,
|
||
+ ptr->section_flag_list,
|
||
+ (lang_output_section_statement_type *) output);
|
||
+
|
||
+ if (tree->right)
|
||
+ output_section_callback_tree_to_list (ptr, tree->right, output);
|
||
+
|
||
+ free (tree);
|
||
+}
|
||
+
|
||
+
|
||
+/* Sections are matched against wildcard statements via a prefix tree.
|
||
+ The prefix tree holds prefixes of all matching patterns (up to the first
|
||
+ wildcard character), and the wild statement from which those patterns
|
||
+ came. When matching a section name against the tree we're walking through
|
||
+ the tree character by character. Each statement we hit is one that
|
||
+ potentially matches. This is checked by actually going through the
|
||
+ (glob) matching routines.
|
||
+
|
||
+ When the section name turns out to actually match we record that section
|
||
+ in the wild statements list of matching sections. */
|
||
+
|
||
+/* A prefix can be matched by multiple statement, so we need a list of them. */
|
||
+struct wild_stmt_list
|
||
+{
|
||
+ lang_wild_statement_type *stmt;
|
||
+ struct wild_stmt_list *next;
|
||
+};
|
||
+
|
||
+/* The prefix tree itself. */
|
||
+struct prefixtree
|
||
+{
|
||
+ /* The list of all children (linked via .next). */
|
||
+ struct prefixtree *child;
|
||
+ struct prefixtree *next;
|
||
+ /* This tree node is responsible for the prefix of parent plus 'c'. */
|
||
+ char c;
|
||
+ /* The statements that potentially can match this prefix. */
|
||
+ struct wild_stmt_list *stmt;
|
||
+};
|
||
+
|
||
+/* We always have a root node in the prefix tree. It corresponds to the
|
||
+ empty prefix. E.g. a glob like "*" would sit in this root. */
|
||
+static struct prefixtree the_root, *ptroot = &the_root;
|
||
+
|
||
+/* Given a prefix tree in *TREE, corresponding to prefix P, find or
|
||
+ INSERT the tree node corresponding to prefix P+C. */
|
||
+
|
||
+static struct prefixtree *
|
||
+get_prefix_tree (struct prefixtree **tree, char c, bool insert)
|
||
+{
|
||
+ struct prefixtree *t;
|
||
+ for (t = *tree; t; t = t->next)
|
||
+ if (t->c == c)
|
||
+ return t;
|
||
+ if (!insert)
|
||
+ return NULL;
|
||
+ t = (struct prefixtree *) obstack_alloc (&pt_obstack, sizeof *t);
|
||
+ t->child = NULL;
|
||
+ t->next = *tree;
|
||
+ t->c = c;
|
||
+ t->stmt = NULL;
|
||
+ *tree = t;
|
||
+ return t;
|
||
+}
|
||
+
|
||
+/* Add STMT to the set of statements that can be matched by the prefix
|
||
+ corresponding to prefix tree T. */
|
||
+
|
||
+static void
|
||
+pt_add_stmt (struct prefixtree *t, lang_wild_statement_type *stmt)
|
||
+{
|
||
+ struct wild_stmt_list *sl, **psl;
|
||
+ sl = (struct wild_stmt_list *) obstack_alloc (&pt_obstack, sizeof *sl);
|
||
+ sl->stmt = stmt;
|
||
+ sl->next = NULL;
|
||
+ psl = &t->stmt;
|
||
+ while (*psl)
|
||
+ psl = &(*psl)->next;
|
||
+ *psl = sl;
|
||
+}
|
||
+
|
||
+/* Insert STMT into the global prefix tree. */
|
||
+
|
||
+static void
|
||
+insert_prefix_tree (lang_wild_statement_type *stmt)
|
||
+{
|
||
+ struct wildcard_list *sec;
|
||
+ struct prefixtree *t;
|
||
+
|
||
+ if (!stmt->section_list)
|
||
+ {
|
||
+ /* If we have no section_list (no wildcards in the wild STMT),
|
||
+ then every section name will match, so add this to the root. */
|
||
+ pt_add_stmt (ptroot, stmt);
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ for (sec = stmt->section_list; sec; sec = sec->next)
|
||
+ {
|
||
+ const char *name = sec->spec.name ? sec->spec.name : "*";
|
||
+ char c;
|
||
+ t = ptroot;
|
||
+ for (; (c = *name); name++)
|
||
+ {
|
||
+ if (c == '*' || c == '[' || c == '?')
|
||
+ break;
|
||
+ t = get_prefix_tree (&t->child, c, true);
|
||
+ }
|
||
+ /* If we hit a glob character, the matching prefix is what we saw
|
||
+ until now. If we hit the end of pattern (hence it's no glob) then
|
||
+ we can do better: we only need to record a match when a section name
|
||
+ completely matches, not merely a prefix, so record the trailing 0
|
||
+ as well. */
|
||
+ if (!c)
|
||
+ t = get_prefix_tree (&t->child, 0, true);
|
||
+ pt_add_stmt (t, stmt);
|
||
+ }
|
||
+}
|
||
+
|
||
+/* Dump T indented by INDENT spaces. */
|
||
+
|
||
+static void
|
||
+debug_prefix_tree_rec (struct prefixtree *t, int indent)
|
||
+{
|
||
+ for (; t; t = t->next)
|
||
+ {
|
||
+ struct wild_stmt_list *sl;
|
||
+ printf ("%*s %c", indent, "", t->c);
|
||
+ for (sl = t->stmt; sl; sl = sl->next)
|
||
+ {
|
||
+ struct wildcard_list *curr;
|
||
+ printf (" %p ", sl->stmt);
|
||
+ for (curr = sl->stmt->section_list; curr; curr = curr->next)
|
||
+ printf ("%s ", curr->spec.name ? curr->spec.name : "*");
|
||
+ }
|
||
+ printf ("\n");
|
||
+ debug_prefix_tree_rec (t->child, indent + 2);
|
||
+ }
|
||
+}
|
||
+
|
||
+/* Dump the global prefix tree. */
|
||
+
|
||
+static void
|
||
+debug_prefix_tree (void)
|
||
+{
|
||
+ debug_prefix_tree_rec (ptroot, 2);
|
||
+}
|
||
+
|
||
+/* Like strcspn() but start to look from the end to beginning of
|
||
+ S. Returns the length of the suffix of S consisting entirely
|
||
+ of characters not in REJECT. */
|
||
+
|
||
+static size_t
|
||
+rstrcspn (const char *s, const char *reject)
|
||
+{
|
||
+ size_t len = strlen (s), sufflen = 0;
|
||
+ while (len--)
|
||
+ {
|
||
+ char c = s[len];
|
||
+ if (strchr (reject, c) != 0)
|
||
+ break;
|
||
+ sufflen++;
|
||
+ }
|
||
+ return sufflen;
|
||
+}
|
||
+
|
||
+/* Analyze the wildcards in wild statement PTR to setup various
|
||
+ things for quick matching. */
|
||
+
|
||
+static void
|
||
+analyze_walk_wild_section_handler (lang_wild_statement_type *ptr)
|
||
+{
|
||
+ struct wildcard_list *sec;
|
||
+
|
||
+ ptr->tree = NULL;
|
||
+ ptr->rightmost = &ptr->tree;
|
||
+
|
||
+ for (sec = ptr->section_list; sec != NULL; sec = sec->next)
|
||
+ {
|
||
+ if (sec->spec.name)
|
||
+ {
|
||
+ sec->spec.namelen = strlen (sec->spec.name);
|
||
+ sec->spec.prefixlen = strcspn (sec->spec.name, "?*[");
|
||
+ sec->spec.suffixlen = rstrcspn (sec->spec.name + sec->spec.prefixlen,
|
||
+ "?*]");
|
||
+ }
|
||
+ else
|
||
+ sec->spec.namelen = sec->spec.prefixlen = sec->spec.suffixlen = 0;
|
||
+ }
|
||
+
|
||
+ insert_prefix_tree (ptr);
|
||
+}
|
||
+
|
||
+/* Match all sections from FILE against the global prefix tree,
|
||
+ and record them into each wild statement that has a match. */
|
||
+
|
||
+static void
|
||
+resolve_wild_sections (lang_input_statement_type *file)
|
||
+{
|
||
+ asection *s;
|
||
+
|
||
+ if (file->flags.just_syms)
|
||
+ return;
|
||
+
|
||
+ for (s = file->the_bfd->sections; s != NULL; s = s->next)
|
||
+ {
|
||
+ const char *sname = bfd_section_name (s);
|
||
+ char c = 1;
|
||
+ struct prefixtree *t = ptroot;
|
||
+ //printf (" YYY consider %s of %s\n", sname, file->the_bfd->filename);
|
||
+ do
|
||
+ {
|
||
+ if (t->stmt)
|
||
+ {
|
||
+ struct wild_stmt_list *sl;
|
||
+ for (sl = t->stmt; sl; sl = sl->next)
|
||
+ {
|
||
+ walk_wild_section_match (sl->stmt, file, s);
|
||
+ //printf (" ZZZ maybe place into %p\n", sl->stmt);
|
||
+ }
|
||
+ }
|
||
+ if (!c)
|
||
+ break;
|
||
+ c = *sname++;
|
||
+ t = get_prefix_tree (&t->child, c, false);
|
||
+ }
|
||
+ while (t);
|
||
+ }
|
||
+}
|
||
+
|
||
+/* Match all sections from all input files against the global prefix tree. */
|
||
+
|
||
+static void
|
||
+resolve_wilds (void)
|
||
+{
|
||
+ LANG_FOR_EACH_INPUT_STATEMENT (f)
|
||
+ {
|
||
+ //printf("XXX %s\n", f->filename);
|
||
+ if (f->the_bfd == NULL
|
||
+ || !bfd_check_format (f->the_bfd, bfd_archive))
|
||
+ resolve_wild_sections (f);
|
||
+ else
|
||
+ {
|
||
+ bfd *member;
|
||
+
|
||
+ /* This is an archive file. We must map each member of the
|
||
+ archive separately. */
|
||
+ member = bfd_openr_next_archived_file (f->the_bfd, NULL);
|
||
+ while (member != NULL)
|
||
+ {
|
||
+ /* When lookup_name is called, it will call the add_symbols
|
||
+ entry point for the archive. For each element of the
|
||
+ archive which is included, BFD will call ldlang_add_file,
|
||
+ which will set the usrdata field of the member to the
|
||
+ lang_input_statement. */
|
||
+ if (bfd_usrdata (member) != NULL)
|
||
+ resolve_wild_sections (bfd_usrdata (member));
|
||
+
|
||
+ member = bfd_openr_next_archived_file (f->the_bfd, member);
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+}
|
||
+
|
||
+/* For each input section that matches wild statement S calls
|
||
+ CALLBACK with DATA. */
|
||
+
|
||
+static void
|
||
+walk_wild (lang_wild_statement_type *s, callback_t callback, void *data)
|
||
+{
|
||
+ lang_statement_union_type *l;
|
||
+
|
||
+ for (l = s->matching_sections.head; l; l = l->header.next)
|
||
+ {
|
||
+ (*callback) (s, l->input_matcher.pattern, l->input_matcher.section,
|
||
+ l->input_matcher.input_stmt, data);
|
||
+ }
|
||
+}
|
||
+
|
||
+/* lang_for_each_statement walks the parse tree and calls the provided
|
||
+ function for each node, except those inside output section statements
|
||
+ with constraint set to -1. */
|
||
+
|
||
+void
|
||
+lang_for_each_statement_worker (void (*func) (lang_statement_union_type *),
|
||
+ lang_statement_union_type *s)
|
||
+{
|
||
+ for (; s != NULL; s = s->header.next)
|
||
+ {
|
||
+ func (s);
|
||
+
|
||
+ switch (s->header.type)
|
||
+ {
|
||
+ case lang_constructors_statement_enum:
|
||
+ lang_for_each_statement_worker (func, constructor_list.head);
|
||
+ break;
|
||
+ case lang_output_section_statement_enum:
|
||
+ if (s->output_section_statement.constraint != -1)
|
||
+ lang_for_each_statement_worker
|
||
+ (func, s->output_section_statement.children.head);
|
||
+ break;
|
||
+ case lang_wild_statement_enum:
|
||
+ lang_for_each_statement_worker (func,
|
||
+ s->wild_statement.children.head);
|
||
+ break;
|
||
+ case lang_group_statement_enum:
|
||
+ lang_for_each_statement_worker (func,
|
||
+ s->group_statement.children.head);
|
||
+ break;
|
||
+ case lang_data_statement_enum:
|
||
+ case lang_reloc_statement_enum:
|
||
+ case lang_object_symbols_statement_enum:
|
||
+ case lang_output_statement_enum:
|
||
+ case lang_target_statement_enum:
|
||
+ case lang_input_section_enum:
|
||
+ case lang_input_statement_enum:
|
||
+ case lang_assignment_statement_enum:
|
||
+ case lang_padding_statement_enum:
|
||
+ case lang_address_statement_enum:
|
||
+ case lang_fill_statement_enum:
|
||
+ case lang_insert_statement_enum:
|
||
+ break;
|
||
+ default:
|
||
+ FAIL ();
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+}
|
||
+
|
||
+void
|
||
+lang_for_each_statement (void (*func) (lang_statement_union_type *))
|
||
+{
|
||
+ lang_for_each_statement_worker (func, statement_list.head);
|
||
+}
|
||
+
|
||
+/*----------------------------------------------------------------------*/
|
||
+
|
||
+void
|
||
+lang_list_init (lang_statement_list_type *list)
|
||
+{
|
||
+ list->head = NULL;
|
||
+ list->tail = &list->head;
|
||
+}
|
||
+
|
||
+static void
|
||
+lang_statement_append (lang_statement_list_type *list,
|
||
+ void *element,
|
||
+ void *field)
|
||
+{
|
||
+ *(list->tail) = element;
|
||
+ list->tail = field;
|
||
+}
|
||
+
|
||
+void
|
||
+push_stat_ptr (lang_statement_list_type *new_ptr)
|
||
+{
|
||
+ if (stat_save_ptr >= stat_save + sizeof (stat_save) / sizeof (stat_save[0]))
|
||
+ abort ();
|
||
+ *stat_save_ptr++ = stat_ptr;
|
||
+ stat_ptr = new_ptr;
|
||
+}
|
||
+
|
||
+void
|
||
+pop_stat_ptr (void)
|
||
+{
|
||
+ if (stat_save_ptr <= stat_save)
|
||
+ abort ();
|
||
+ stat_ptr = *--stat_save_ptr;
|
||
+}
|
||
+
|
||
+/* Build a new statement node for the parse tree. */
|
||
+
|
||
+static lang_statement_union_type *
|
||
+new_statement (enum statement_enum type,
|
||
+ size_t size,
|
||
+ lang_statement_list_type *list)
|
||
+{
|
||
+ lang_statement_union_type *new_stmt;
|
||
+
|
||
+ new_stmt = stat_alloc (size);
|
||
+ new_stmt->header.type = type;
|
||
+ new_stmt->header.next = NULL;
|
||
+ lang_statement_append (list, new_stmt, &new_stmt->header.next);
|
||
+ return new_stmt;
|
||
+}
|
||
+
|
||
+/* Build a new input file node for the language. There are several
|
||
+ ways in which we treat an input file, eg, we only look at symbols,
|
||
+ or prefix it with a -l etc.
|
||
+
|
||
+ We can be supplied with requests for input files more than once;
|
||
+ they may, for example be split over several lines like foo.o(.text)
|
||
+ foo.o(.data) etc, so when asked for a file we check that we haven't
|
||
+ got it already so we don't duplicate the bfd. */
|
||
+
|
||
+static lang_input_statement_type *
|
||
+new_afile (const char *name,
|
||
+ lang_input_file_enum_type file_type,
|
||
+ const char *target,
|
||
+ const char *from_filename)
|
||
+{
|
||
+ lang_input_statement_type *p;
|
||
+
|
||
+ lang_has_input_file = true;
|
||
+
|
||
+ /* PR 30632: It is OK for name to be NULL. For example
|
||
+ see the initialization of first_file in lang_init(). */
|
||
+ if (name != NULL)
|
||
+ {
|
||
+ name = ldfile_possibly_remap_input (name);
|
||
+ /* But if a name is remapped to NULL, it should be ignored. */
|
||
+ if (name == NULL)
|
||
+ return NULL;
|
||
+ }
|
||
+
|
||
+ p = new_stat (lang_input_statement, stat_ptr);
|
||
+ memset (&p->the_bfd, 0,
|
||
+ sizeof (*p) - offsetof (lang_input_statement_type, the_bfd));
|
||
+ p->extra_search_path = NULL;
|
||
+ p->target = target;
|
||
+ p->flags.dynamic = input_flags.dynamic;
|
||
+ p->flags.add_DT_NEEDED_for_dynamic = input_flags.add_DT_NEEDED_for_dynamic;
|
||
+ p->flags.add_DT_NEEDED_for_regular = input_flags.add_DT_NEEDED_for_regular;
|
||
+ p->flags.whole_archive = input_flags.whole_archive;
|
||
+ p->flags.sysrooted = input_flags.sysrooted;
|
||
+ p->sort_key = NULL;
|
||
+
|
||
+ switch (file_type)
|
||
+ {
|
||
+ case lang_input_file_is_symbols_only_enum:
|
||
+ p->filename = name;
|
||
+ p->local_sym_name = name;
|
||
+ p->flags.real = true;
|
||
+ p->flags.just_syms = true;
|
||
+ break;
|
||
+ case lang_input_file_is_fake_enum:
|
||
+ p->filename = name;
|
||
+ p->local_sym_name = name;
|
||
+ break;
|
||
+ case lang_input_file_is_l_enum:
|
||
+ if (name[0] == ':' && name[1] != '\0')
|
||
+ {
|
||
+ p->filename = name + 1;
|
||
+ p->flags.full_name_provided = true;
|
||
+ }
|
||
+ else
|
||
+ p->filename = name;
|
||
+ p->local_sym_name = concat ("-l", name, (const char *) NULL);
|
||
+ p->flags.maybe_archive = true;
|
||
+ p->flags.real = true;
|
||
+ p->flags.search_dirs = true;
|
||
+ break;
|
||
+ case lang_input_file_is_marker_enum:
|
||
+ p->filename = name;
|
||
+ p->local_sym_name = name;
|
||
+ p->flags.search_dirs = true;
|
||
+ break;
|
||
+ case lang_input_file_is_search_file_enum:
|
||
+ p->filename = name;
|
||
+ p->local_sym_name = name;
|
||
+ /* If name is a relative path, search the directory of the current linker
|
||
+ script first. */
|
||
+ if (from_filename && !IS_ABSOLUTE_PATH (name))
|
||
+ p->extra_search_path = ldirname (from_filename);
|
||
+ p->flags.real = true;
|
||
+ p->flags.search_dirs = true;
|
||
+ break;
|
||
+ case lang_input_file_is_file_enum:
|
||
+ p->filename = name;
|
||
+ p->local_sym_name = name;
|
||
+ p->flags.real = true;
|
||
+ break;
|
||
+ default:
|
||
+ FAIL ();
|
||
+ }
|
||
+
|
||
+ lang_statement_append (&input_file_chain, p, &p->next_real_file);
|
||
+ return p;
|
||
+}
|
||
+
|
||
+lang_input_statement_type *
|
||
+lang_add_input_file (const char *name,
|
||
+ lang_input_file_enum_type file_type,
|
||
+ const char *target)
|
||
+{
|
||
+ if (name != NULL
|
||
+ && (*name == '=' || startswith (name, "$SYSROOT")))
|
||
+ {
|
||
+ lang_input_statement_type *ret;
|
||
+ char *sysrooted_name
|
||
+ = concat (ld_sysroot,
|
||
+ name + (*name == '=' ? 1 : strlen ("$SYSROOT")),
|
||
+ (const char *) NULL);
|
||
+
|
||
+ /* We've now forcibly prepended the sysroot, making the input
|
||
+ file independent of the context. Therefore, temporarily
|
||
+ force a non-sysrooted context for this statement, so it won't
|
||
+ get the sysroot prepended again when opened. (N.B. if it's a
|
||
+ script, any child nodes with input files starting with "/"
|
||
+ will be handled as "sysrooted" as they'll be found to be
|
||
+ within the sysroot subdirectory.) */
|
||
+ unsigned int outer_sysrooted = input_flags.sysrooted;
|
||
+ input_flags.sysrooted = 0;
|
||
+ ret = new_afile (sysrooted_name, file_type, target, NULL);
|
||
+ input_flags.sysrooted = outer_sysrooted;
|
||
+ return ret;
|
||
+ }
|
||
+
|
||
+ return new_afile (name, file_type, target, current_input_file);
|
||
+}
|
||
+
|
||
+struct out_section_hash_entry
|
||
+{
|
||
+ struct bfd_hash_entry root;
|
||
+ lang_statement_union_type s;
|
||
+};
|
||
+
|
||
+/* The hash table. */
|
||
+
|
||
+static struct bfd_hash_table output_section_statement_table;
|
||
+
|
||
+/* Support routines for the hash table used by lang_output_section_find,
|
||
+ initialize the table, fill in an entry and remove the table. */
|
||
+
|
||
+static struct bfd_hash_entry *
|
||
+output_section_statement_newfunc (struct bfd_hash_entry *entry,
|
||
+ struct bfd_hash_table *table,
|
||
+ const char *string)
|
||
+{
|
||
+ lang_output_section_statement_type **nextp;
|
||
+ struct out_section_hash_entry *ret;
|
||
+
|
||
+ if (entry == NULL)
|
||
+ {
|
||
+ entry = (struct bfd_hash_entry *) bfd_hash_allocate (table,
|
||
+ sizeof (*ret));
|
||
+ if (entry == NULL)
|
||
+ return entry;
|
||
+ }
|
||
+
|
||
+ entry = bfd_hash_newfunc (entry, table, string);
|
||
+ if (entry == NULL)
|
||
+ return entry;
|
||
+
|
||
+ ret = (struct out_section_hash_entry *) entry;
|
||
+ memset (&ret->s, 0, sizeof (ret->s));
|
||
+ ret->s.header.type = lang_output_section_statement_enum;
|
||
+ ret->s.output_section_statement.subsection_alignment = NULL;
|
||
+ ret->s.output_section_statement.section_alignment = NULL;
|
||
+ ret->s.output_section_statement.block_value = 1;
|
||
+ lang_list_init (&ret->s.output_section_statement.children);
|
||
+ lang_statement_append (stat_ptr, &ret->s, &ret->s.header.next);
|
||
+
|
||
+ /* For every output section statement added to the list, except the
|
||
+ first one, lang_os_list.tail points to the "next"
|
||
+ field of the last element of the list. */
|
||
+ if (lang_os_list.head != NULL)
|
||
+ ret->s.output_section_statement.prev
|
||
+ = ((lang_output_section_statement_type *)
|
||
+ ((char *) lang_os_list.tail
|
||
+ - offsetof (lang_output_section_statement_type, next)));
|
||
+
|
||
+ /* GCC's strict aliasing rules prevent us from just casting the
|
||
+ address, so we store the pointer in a variable and cast that
|
||
+ instead. */
|
||
+ nextp = &ret->s.output_section_statement.next;
|
||
+ lang_statement_append (&lang_os_list, &ret->s, nextp);
|
||
+ return &ret->root;
|
||
+}
|
||
+
|
||
+static void
|
||
+output_section_statement_table_init (void)
|
||
+{
|
||
+ if (!bfd_hash_table_init_n (&output_section_statement_table,
|
||
+ output_section_statement_newfunc,
|
||
+ sizeof (struct out_section_hash_entry),
|
||
+ 61))
|
||
+ einfo (_("%F%P: can not create hash table: %E\n"));
|
||
+}
|
||
+
|
||
+static void
|
||
+output_section_statement_table_free (void)
|
||
+{
|
||
+ bfd_hash_table_free (&output_section_statement_table);
|
||
+}
|
||
+
|
||
+/* Build enough state so that the parser can build its tree. */
|
||
+
|
||
+void
|
||
+lang_init (void)
|
||
+{
|
||
+ obstack_begin (&stat_obstack, 1000);
|
||
+ obstack_init (&pt_obstack);
|
||
+
|
||
+ stat_ptr = &statement_list;
|
||
+
|
||
+ output_section_statement_table_init ();
|
||
+
|
||
+ lang_list_init (stat_ptr);
|
||
+
|
||
+ lang_list_init (&input_file_chain);
|
||
+ lang_list_init (&lang_os_list);
|
||
+ lang_list_init (&file_chain);
|
||
+ first_file = lang_add_input_file (NULL, lang_input_file_is_marker_enum,
|
||
+ NULL);
|
||
+ abs_output_section =
|
||
+ lang_output_section_statement_lookup (BFD_ABS_SECTION_NAME, 0, 1);
|
||
+
|
||
+ abs_output_section->bfd_section = bfd_abs_section_ptr;
|
||
+
|
||
+ asneeded_list_head = NULL;
|
||
+ asneeded_list_tail = &asneeded_list_head;
|
||
+}
|
||
+
|
||
+void
|
||
+lang_finish (void)
|
||
+{
|
||
+ output_section_statement_table_free ();
|
||
+ ldfile_remap_input_free ();
|
||
+}
|
||
+
|
||
+/*----------------------------------------------------------------------
|
||
+ A region is an area of memory declared with the
|
||
+ MEMORY { name:org=exp, len=exp ... }
|
||
+ syntax.
|
||
+
|
||
+ We maintain a list of all the regions here.
|
||
+
|
||
+ If no regions are specified in the script, then the default is used
|
||
+ which is created when looked up to be the entire data space.
|
||
+
|
||
+ If create is true we are creating a region inside a MEMORY block.
|
||
+ In this case it is probably an error to create a region that has
|
||
+ already been created. If we are not inside a MEMORY block it is
|
||
+ dubious to use an undeclared region name (except DEFAULT_MEMORY_REGION)
|
||
+ and so we issue a warning.
|
||
+
|
||
+ Each region has at least one name. The first name is either
|
||
+ DEFAULT_MEMORY_REGION or the name given in the MEMORY block. You can add
|
||
+ alias names to an existing region within a script with
|
||
+ REGION_ALIAS (alias, region_name). Each name corresponds to at most one
|
||
+ region. */
|
||
+
|
||
+static lang_memory_region_type *lang_memory_region_list;
|
||
+static lang_memory_region_type **lang_memory_region_list_tail
|
||
+ = &lang_memory_region_list;
|
||
+
|
||
+lang_memory_region_type *
|
||
+lang_memory_region_lookup (const char *const name, bool create)
|
||
+{
|
||
+ lang_memory_region_name *n;
|
||
+ lang_memory_region_type *r;
|
||
+ lang_memory_region_type *new_region;
|
||
+
|
||
+ /* NAME is NULL for LMA memspecs if no region was specified. */
|
||
+ if (name == NULL)
|
||
+ return NULL;
|
||
+
|
||
+ for (r = lang_memory_region_list; r != NULL; r = r->next)
|
||
+ for (n = &r->name_list; n != NULL; n = n->next)
|
||
+ if (strcmp (n->name, name) == 0)
|
||
+ {
|
||
+ if (create)
|
||
+ einfo (_("%P:%pS: warning: redeclaration of memory region `%s'\n"),
|
||
+ NULL, name);
|
||
+ return r;
|
||
+ }
|
||
+
|
||
+ if (!create && strcmp (name, DEFAULT_MEMORY_REGION))
|
||
+ einfo (_("%P:%pS: warning: memory region `%s' not declared\n"),
|
||
+ NULL, name);
|
||
+
|
||
+ new_region = stat_alloc (sizeof (lang_memory_region_type));
|
||
+
|
||
+ new_region->name_list.name = xstrdup (name);
|
||
+ new_region->name_list.next = NULL;
|
||
+ new_region->next = NULL;
|
||
+ new_region->origin_exp = NULL;
|
||
+ new_region->origin = 0;
|
||
+ new_region->length_exp = NULL;
|
||
+ new_region->length = ~(bfd_size_type) 0;
|
||
+ new_region->current = 0;
|
||
+ new_region->last_os = NULL;
|
||
+ new_region->flags = 0;
|
||
+ new_region->not_flags = 0;
|
||
+ new_region->had_full_message = false;
|
||
+
|
||
+ *lang_memory_region_list_tail = new_region;
|
||
+ lang_memory_region_list_tail = &new_region->next;
|
||
+
|
||
+ return new_region;
|
||
+}
|
||
+
|
||
+void
|
||
+lang_memory_region_alias (const char *alias, const char *region_name)
|
||
+{
|
||
+ lang_memory_region_name *n;
|
||
+ lang_memory_region_type *r;
|
||
+ lang_memory_region_type *region;
|
||
+
|
||
+ /* The default region must be unique. This ensures that it is not necessary
|
||
+ to iterate through the name list if someone wants the check if a region is
|
||
+ the default memory region. */
|
||
+ if (strcmp (region_name, DEFAULT_MEMORY_REGION) == 0
|
||
+ || strcmp (alias, DEFAULT_MEMORY_REGION) == 0)
|
||
+ einfo (_("%F%P:%pS: error: alias for default memory region\n"), NULL);
|
||
+
|
||
+ /* Look for the target region and check if the alias is not already
|
||
+ in use. */
|
||
+ region = NULL;
|
||
+ for (r = lang_memory_region_list; r != NULL; r = r->next)
|
||
+ for (n = &r->name_list; n != NULL; n = n->next)
|
||
+ {
|
||
+ if (region == NULL && strcmp (n->name, region_name) == 0)
|
||
+ region = r;
|
||
+ if (strcmp (n->name, alias) == 0)
|
||
+ einfo (_("%F%P:%pS: error: redefinition of memory region "
|
||
+ "alias `%s'\n"),
|
||
+ NULL, alias);
|
||
+ }
|
||
+
|
||
+ /* Check if the target region exists. */
|
||
+ if (region == NULL)
|
||
+ einfo (_("%F%P:%pS: error: memory region `%s' "
|
||
+ "for alias `%s' does not exist\n"),
|
||
+ NULL, region_name, alias);
|
||
+
|
||
+ /* Add alias to region name list. */
|
||
+ n = stat_alloc (sizeof (lang_memory_region_name));
|
||
+ n->name = xstrdup (alias);
|
||
+ n->next = region->name_list.next;
|
||
+ region->name_list.next = n;
|
||
+}
|
||
+
|
||
+static lang_memory_region_type *
|
||
+lang_memory_default (asection *section)
|
||
+{
|
||
+ lang_memory_region_type *p;
|
||
+
|
||
+ flagword sec_flags = section->flags;
|
||
+
|
||
+ /* Override SEC_DATA to mean a writable section. */
|
||
+ if ((sec_flags & (SEC_ALLOC | SEC_READONLY | SEC_CODE)) == SEC_ALLOC)
|
||
+ sec_flags |= SEC_DATA;
|
||
+
|
||
+ for (p = lang_memory_region_list; p != NULL; p = p->next)
|
||
+ {
|
||
+ if ((p->flags & sec_flags) != 0
|
||
+ && (p->not_flags & sec_flags) == 0)
|
||
+ {
|
||
+ return p;
|
||
+ }
|
||
+ }
|
||
+ return lang_memory_region_lookup (DEFAULT_MEMORY_REGION, false);
|
||
+}
|
||
+
|
||
+/* Get the output section statement directly from the userdata. */
|
||
+
|
||
+lang_output_section_statement_type *
|
||
+lang_output_section_get (const asection *output_section)
|
||
+{
|
||
+ return bfd_section_userdata (output_section);
|
||
+}
|
||
+
|
||
+/* Find or create an output_section_statement with the given NAME.
|
||
+ If CONSTRAINT is non-zero match one with that constraint, otherwise
|
||
+ match any non-negative constraint. If CREATE is 0 return NULL when
|
||
+ no match exists. If CREATE is 1, create an output_section_statement
|
||
+ when no match exists or if CONSTRAINT is SPECIAL. If CREATE is 2,
|
||
+ always make a new output_section_statement. */
|
||
+
|
||
+lang_output_section_statement_type *
|
||
+lang_output_section_statement_lookup (const char *name,
|
||
+ int constraint,
|
||
+ int create)
|
||
+{
|
||
+ struct out_section_hash_entry *entry;
|
||
+
|
||
+ entry = ((struct out_section_hash_entry *)
|
||
+ bfd_hash_lookup (&output_section_statement_table, name,
|
||
+ create != 0, false));
|
||
+ if (entry == NULL)
|
||
+ {
|
||
+ if (create)
|
||
+ einfo (_("%F%P: failed creating section `%s': %E\n"), name);
|
||
+ return NULL;
|
||
+ }
|
||
+
|
||
+ if (entry->s.output_section_statement.name != NULL)
|
||
+ {
|
||
+ /* We have a section of this name, but it might not have the correct
|
||
+ constraint. */
|
||
+ struct out_section_hash_entry *last_ent;
|
||
+
|
||
+ name = entry->s.output_section_statement.name;
|
||
+ do
|
||
+ {
|
||
+ if (create != 2
|
||
+ && !(create && constraint == SPECIAL)
|
||
+ && (constraint == entry->s.output_section_statement.constraint
|
||
+ || (constraint == 0
|
||
+ && entry->s.output_section_statement.constraint >= 0)))
|
||
+ return &entry->s.output_section_statement;
|
||
+ last_ent = entry;
|
||
+ entry = (struct out_section_hash_entry *) entry->root.next;
|
||
+ }
|
||
+ while (entry != NULL
|
||
+ && name == entry->s.output_section_statement.name);
|
||
+
|
||
+ if (!create)
|
||
+ return NULL;
|
||
+
|
||
+ entry
|
||
+ = ((struct out_section_hash_entry *)
|
||
+ output_section_statement_newfunc (NULL,
|
||
+ &output_section_statement_table,
|
||
+ name));
|
||
+ if (entry == NULL)
|
||
+ {
|
||
+ einfo (_("%F%P: failed creating section `%s': %E\n"), name);
|
||
+ return NULL;
|
||
+ }
|
||
+ entry->root = last_ent->root;
|
||
+ last_ent->root.next = &entry->root;
|
||
+ }
|
||
+
|
||
+ entry->s.output_section_statement.name = name;
|
||
+ entry->s.output_section_statement.constraint = constraint;
|
||
+ entry->s.output_section_statement.dup_output = (create == 2
|
||
+ || constraint == SPECIAL);
|
||
+ return &entry->s.output_section_statement;
|
||
+}
|
||
+
|
||
+/* Find the next output_section_statement with the same name as OS.
|
||
+ If CONSTRAINT is non-zero, find one with that constraint otherwise
|
||
+ match any non-negative constraint. */
|
||
+
|
||
+lang_output_section_statement_type *
|
||
+next_matching_output_section_statement (lang_output_section_statement_type *os,
|
||
+ int constraint)
|
||
+{
|
||
+ /* All output_section_statements are actually part of a
|
||
+ struct out_section_hash_entry. */
|
||
+ struct out_section_hash_entry *entry = (struct out_section_hash_entry *)
|
||
+ ((char *) os
|
||
+ - offsetof (struct out_section_hash_entry, s.output_section_statement));
|
||
+ const char *name = os->name;
|
||
+
|
||
+ ASSERT (name == entry->root.string);
|
||
+ do
|
||
+ {
|
||
+ entry = (struct out_section_hash_entry *) entry->root.next;
|
||
+ if (entry == NULL
|
||
+ || name != entry->s.output_section_statement.name)
|
||
+ return NULL;
|
||
+ }
|
||
+ while (constraint != entry->s.output_section_statement.constraint
|
||
+ && (constraint != 0
|
||
+ || entry->s.output_section_statement.constraint < 0));
|
||
+
|
||
+ return &entry->s.output_section_statement;
|
||
+}
|
||
+
|
||
+/* A variant of lang_output_section_find used by place_orphan.
|
||
+ Returns the output statement that should precede a new output
|
||
+ statement for SEC. If an exact match is found on certain flags,
|
||
+ sets *EXACT too. */
|
||
+
|
||
+lang_output_section_statement_type *
|
||
+lang_output_section_find_by_flags (const asection *sec,
|
||
+ flagword sec_flags,
|
||
+ lang_output_section_statement_type **exact,
|
||
+ lang_match_sec_type_func match_type)
|
||
+{
|
||
+ lang_output_section_statement_type *first, *look, *found;
|
||
+ flagword look_flags, differ;
|
||
+
|
||
+ /* We know the first statement on this list is *ABS*. May as well
|
||
+ skip it. */
|
||
+ first = (void *) lang_os_list.head;
|
||
+ first = first->next;
|
||
+
|
||
+ /* First try for an exact match. */
|
||
+ found = NULL;
|
||
+ for (look = first; look; look = look->next)
|
||
+ {
|
||
+ look_flags = look->flags;
|
||
+ if (look->bfd_section != NULL)
|
||
+ {
|
||
+ look_flags = look->bfd_section->flags;
|
||
+ if (match_type && !match_type (link_info.output_bfd,
|
||
+ look->bfd_section,
|
||
+ sec->owner, sec))
|
||
+ continue;
|
||
+ }
|
||
+ differ = look_flags ^ sec_flags;
|
||
+ if (!(differ & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY
|
||
+ | SEC_CODE | SEC_SMALL_DATA | SEC_THREAD_LOCAL)))
|
||
+ found = look;
|
||
+ }
|
||
+ if (found != NULL)
|
||
+ {
|
||
+ if (exact != NULL)
|
||
+ *exact = found;
|
||
+ return found;
|
||
+ }
|
||
+
|
||
+ if ((sec_flags & SEC_CODE) != 0
|
||
+ && (sec_flags & SEC_ALLOC) != 0)
|
||
+ {
|
||
+ /* Try for a rw code section. */
|
||
+ for (look = first; look; look = look->next)
|
||
+ {
|
||
+ look_flags = look->flags;
|
||
+ if (look->bfd_section != NULL)
|
||
+ {
|
||
+ look_flags = look->bfd_section->flags;
|
||
+ if (match_type && !match_type (link_info.output_bfd,
|
||
+ look->bfd_section,
|
||
+ sec->owner, sec))
|
||
+ continue;
|
||
+ }
|
||
+ differ = look_flags ^ sec_flags;
|
||
+ if (!(differ & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD
|
||
+ | SEC_CODE | SEC_SMALL_DATA | SEC_THREAD_LOCAL)))
|
||
+ found = look;
|
||
+ }
|
||
+ }
|
||
+ else if ((sec_flags & SEC_READONLY) != 0
|
||
+ && (sec_flags & SEC_ALLOC) != 0)
|
||
+ {
|
||
+ /* .rodata can go after .text, .sdata2 after .rodata. */
|
||
+ for (look = first; look; look = look->next)
|
||
+ {
|
||
+ look_flags = look->flags;
|
||
+ if (look->bfd_section != NULL)
|
||
+ {
|
||
+ look_flags = look->bfd_section->flags;
|
||
+ if (match_type && !match_type (link_info.output_bfd,
|
||
+ look->bfd_section,
|
||
+ sec->owner, sec))
|
||
+ continue;
|
||
+ }
|
||
+ differ = look_flags ^ sec_flags;
|
||
+ if (!(differ & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD
|
||
+ | SEC_READONLY | SEC_SMALL_DATA))
|
||
+ || (!(differ & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD
|
||
+ | SEC_READONLY))
|
||
+ && !(look_flags & SEC_SMALL_DATA)))
|
||
+ found = look;
|
||
+ }
|
||
+ }
|
||
+ else if ((sec_flags & SEC_THREAD_LOCAL) != 0
|
||
+ && (sec_flags & SEC_ALLOC) != 0)
|
||
+ {
|
||
+ /* .tdata can go after .data, .tbss after .tdata. Treat .tbss
|
||
+ as if it were a loaded section, and don't use match_type. */
|
||
+ bool seen_thread_local = false;
|
||
+
|
||
+ match_type = NULL;
|
||
+ for (look = first; look; look = look->next)
|
||
+ {
|
||
+ look_flags = look->flags;
|
||
+ if (look->bfd_section != NULL)
|
||
+ look_flags = look->bfd_section->flags;
|
||
+
|
||
+ differ = look_flags ^ (sec_flags | SEC_LOAD | SEC_HAS_CONTENTS);
|
||
+ if (!(differ & (SEC_THREAD_LOCAL | SEC_ALLOC)))
|
||
+ {
|
||
+ /* .tdata and .tbss must be adjacent and in that order. */
|
||
+ if (!(look_flags & SEC_LOAD)
|
||
+ && (sec_flags & SEC_LOAD))
|
||
+ /* ..so if we're at a .tbss section and we're placing
|
||
+ a .tdata section stop looking and return the
|
||
+ previous section. */
|
||
+ break;
|
||
+ found = look;
|
||
+ seen_thread_local = true;
|
||
+ }
|
||
+ else if (seen_thread_local)
|
||
+ break;
|
||
+ else if (!(differ & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD)))
|
||
+ found = look;
|
||
+ }
|
||
+ }
|
||
+ else if ((sec_flags & SEC_SMALL_DATA) != 0
|
||
+ && (sec_flags & SEC_ALLOC) != 0)
|
||
+ {
|
||
+ /* .sdata goes after .data, .sbss after .sdata. */
|
||
+ for (look = first; look; look = look->next)
|
||
+ {
|
||
+ look_flags = look->flags;
|
||
+ if (look->bfd_section != NULL)
|
||
+ {
|
||
+ look_flags = look->bfd_section->flags;
|
||
+ if (match_type && !match_type (link_info.output_bfd,
|
||
+ look->bfd_section,
|
||
+ sec->owner, sec))
|
||
+ continue;
|
||
+ }
|
||
+ differ = look_flags ^ sec_flags;
|
||
+ if (!(differ & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD
|
||
+ | SEC_THREAD_LOCAL))
|
||
+ || ((look_flags & SEC_SMALL_DATA)
|
||
+ && !(sec_flags & SEC_HAS_CONTENTS)))
|
||
+ found = look;
|
||
+ }
|
||
+ }
|
||
+ else if ((sec_flags & SEC_HAS_CONTENTS) != 0
|
||
+ && (sec_flags & SEC_ALLOC) != 0)
|
||
+ {
|
||
+ /* .data goes after .rodata. */
|
||
+ for (look = first; look; look = look->next)
|
||
+ {
|
||
+ look_flags = look->flags;
|
||
+ if (look->bfd_section != NULL)
|
||
+ {
|
||
+ look_flags = look->bfd_section->flags;
|
||
+ if (match_type && !match_type (link_info.output_bfd,
|
||
+ look->bfd_section,
|
||
+ sec->owner, sec))
|
||
+ continue;
|
||
+ }
|
||
+ differ = look_flags ^ sec_flags;
|
||
+ if (!(differ & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD
|
||
+ | SEC_SMALL_DATA | SEC_THREAD_LOCAL)))
|
||
+ found = look;
|
||
+ }
|
||
+ }
|
||
+ else if ((sec_flags & SEC_ALLOC) != 0)
|
||
+ {
|
||
+ /* .bss goes after any other alloc section. */
|
||
+ for (look = first; look; look = look->next)
|
||
+ {
|
||
+ look_flags = look->flags;
|
||
+ if (look->bfd_section != NULL)
|
||
+ {
|
||
+ look_flags = look->bfd_section->flags;
|
||
+ if (match_type && !match_type (link_info.output_bfd,
|
||
+ look->bfd_section,
|
||
+ sec->owner, sec))
|
||
+ continue;
|
||
+ }
|
||
+ differ = look_flags ^ sec_flags;
|
||
+ if (!(differ & SEC_ALLOC))
|
||
+ found = look;
|
||
+ }
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ /* non-alloc go last. */
|
||
+ for (look = first; look; look = look->next)
|
||
+ {
|
||
+ look_flags = look->flags;
|
||
+ if (look->bfd_section != NULL)
|
||
+ look_flags = look->bfd_section->flags;
|
||
+ differ = look_flags ^ sec_flags;
|
||
+ if (!(differ & SEC_DEBUGGING))
|
||
+ found = look;
|
||
+ }
|
||
+ return found;
|
||
+ }
|
||
+
|
||
+ if (found || !match_type)
|
||
+ return found;
|
||
+
|
||
+ return lang_output_section_find_by_flags (sec, sec_flags, NULL, NULL);
|
||
+}
|
||
+
|
||
+/* Find the last output section before given output statement.
|
||
+ Used by place_orphan. */
|
||
+
|
||
+static asection *
|
||
+output_prev_sec_find (lang_output_section_statement_type *os)
|
||
+{
|
||
+ lang_output_section_statement_type *lookup;
|
||
+
|
||
+ for (lookup = os->prev; lookup != NULL; lookup = lookup->prev)
|
||
+ {
|
||
+ if (lookup->constraint < 0)
|
||
+ continue;
|
||
+
|
||
+ if (lookup->bfd_section != NULL)
|
||
+ return lookup->bfd_section;
|
||
+ }
|
||
+
|
||
+ return NULL;
|
||
+}
|
||
+
|
||
+/* Look for a suitable place for a new output section statement. The
|
||
+ idea is to skip over anything that might be inside a SECTIONS {}
|
||
+ statement in a script, before we find another output section
|
||
+ statement. Assignments to "dot" before an output section statement
|
||
+ are assumed to belong to it, except in two cases; The first
|
||
+ assignment to dot, and assignments before non-alloc sections.
|
||
+ Otherwise we might put an orphan before . = . + SIZEOF_HEADERS or
|
||
+ similar assignments that set the initial address, or we might
|
||
+ insert non-alloc note sections among assignments setting end of
|
||
+ image symbols. */
|
||
+
|
||
+static lang_statement_union_type **
|
||
+insert_os_after (lang_statement_union_type *after)
|
||
+{
|
||
+ lang_statement_union_type **where;
|
||
+ lang_statement_union_type **assign = NULL;
|
||
+ bool ignore_first;
|
||
+
|
||
+ ignore_first = after == lang_os_list.head;
|
||
+
|
||
+ for (where = &after->header.next;
|
||
+ *where != NULL;
|
||
+ where = &(*where)->header.next)
|
||
+ {
|
||
+ switch ((*where)->header.type)
|
||
+ {
|
||
+ case lang_assignment_statement_enum:
|
||
+ if (assign == NULL)
|
||
+ {
|
||
+ lang_assignment_statement_type *ass;
|
||
+
|
||
+ ass = &(*where)->assignment_statement;
|
||
+ if (ass->exp->type.node_class != etree_assert
|
||
+ && ass->exp->assign.dst[0] == '.'
|
||
+ && ass->exp->assign.dst[1] == 0)
|
||
+ {
|
||
+ if (!ignore_first)
|
||
+ assign = where;
|
||
+ ignore_first = false;
|
||
+ }
|
||
+ }
|
||
+ continue;
|
||
+ case lang_wild_statement_enum:
|
||
+ case lang_input_section_enum:
|
||
+ case lang_object_symbols_statement_enum:
|
||
+ case lang_fill_statement_enum:
|
||
+ case lang_data_statement_enum:
|
||
+ case lang_reloc_statement_enum:
|
||
+ case lang_padding_statement_enum:
|
||
+ case lang_constructors_statement_enum:
|
||
+ assign = NULL;
|
||
+ ignore_first = false;
|
||
+ continue;
|
||
+ case lang_output_section_statement_enum:
|
||
+ if (assign != NULL)
|
||
+ {
|
||
+ asection *s = (*where)->output_section_statement.bfd_section;
|
||
+
|
||
+ if (s == NULL
|
||
+ || s->map_head.s == NULL
|
||
+ || (s->flags & SEC_ALLOC) != 0)
|
||
+ where = assign;
|
||
+ }
|
||
+ break;
|
||
+ case lang_input_statement_enum:
|
||
+ case lang_address_statement_enum:
|
||
+ case lang_target_statement_enum:
|
||
+ case lang_output_statement_enum:
|
||
+ case lang_group_statement_enum:
|
||
+ case lang_insert_statement_enum:
|
||
+ continue;
|
||
+ case lang_input_matcher_enum:
|
||
+ FAIL ();
|
||
+ }
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ return where;
|
||
+}
|
||
+
|
||
+lang_output_section_statement_type *
|
||
+lang_insert_orphan (asection *s,
|
||
+ const char *secname,
|
||
+ int constraint,
|
||
+ lang_output_section_statement_type *after,
|
||
+ struct orphan_save *place,
|
||
+ etree_type *address,
|
||
+ lang_statement_list_type *add_child)
|
||
+{
|
||
+ lang_statement_list_type add;
|
||
+ lang_output_section_statement_type *os;
|
||
+ lang_output_section_statement_type **os_tail;
|
||
+
|
||
+ /* If we have found an appropriate place for the output section
|
||
+ statements for this orphan, add them to our own private list,
|
||
+ inserting them later into the global statement list. */
|
||
+ if (after != NULL)
|
||
+ {
|
||
+ lang_list_init (&add);
|
||
+ push_stat_ptr (&add);
|
||
+ }
|
||
+
|
||
+ if (bfd_link_relocatable (&link_info)
|
||
+ || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0)
|
||
+ address = exp_intop (0);
|
||
+
|
||
+ os_tail = (lang_output_section_statement_type **) lang_os_list.tail;
|
||
+ os = lang_enter_output_section_statement (
|
||
+ secname, address, normal_section, 0, NULL, NULL, NULL, constraint, 0);
|
||
+
|
||
+ if (add_child == NULL)
|
||
+ add_child = &os->children;
|
||
+ lang_add_section (add_child, s, NULL, NULL, os);
|
||
+
|
||
+ if (after && (s->flags & (SEC_LOAD | SEC_ALLOC)) != 0)
|
||
+ {
|
||
+ const char *region = (after->region
|
||
+ ? after->region->name_list.name
|
||
+ : DEFAULT_MEMORY_REGION);
|
||
+ const char *lma_region = (after->lma_region
|
||
+ ? after->lma_region->name_list.name
|
||
+ : NULL);
|
||
+ lang_leave_output_section_statement (NULL, region, after->phdrs,
|
||
+ lma_region);
|
||
+ }
|
||
+ else
|
||
+ lang_leave_output_section_statement (NULL, DEFAULT_MEMORY_REGION, NULL,
|
||
+ NULL);
|
||
+
|
||
+ /* Restore the global list pointer. */
|
||
+ if (after != NULL)
|
||
+ pop_stat_ptr ();
|
||
+
|
||
+ if (after != NULL && os->bfd_section != NULL)
|
||
+ {
|
||
+ asection *snew, *as;
|
||
+ bool place_after = place->stmt == NULL;
|
||
+ bool insert_after = true;
|
||
+
|
||
+ snew = os->bfd_section;
|
||
+
|
||
+ /* Shuffle the bfd section list to make the output file look
|
||
+ neater. This is really only cosmetic. */
|
||
+ if (place->section == NULL
|
||
+ && after != (void *) lang_os_list.head)
|
||
+ {
|
||
+ asection *bfd_section = after->bfd_section;
|
||
+
|
||
+ /* If the output statement hasn't been used to place any input
|
||
+ sections (and thus doesn't have an output bfd_section),
|
||
+ look for the closest prior output statement having an
|
||
+ output section. */
|
||
+ if (bfd_section == NULL)
|
||
+ bfd_section = output_prev_sec_find (after);
|
||
+
|
||
+ if (bfd_section != NULL
|
||
+ && bfd_section->owner != NULL
|
||
+ && bfd_section != snew)
|
||
+ place->section = &bfd_section->next;
|
||
+ }
|
||
+
|
||
+ if (place->section == NULL)
|
||
+ place->section = &link_info.output_bfd->sections;
|
||
+
|
||
+ as = *place->section;
|
||
+
|
||
+ if (!as)
|
||
+ {
|
||
+ /* Put the section at the end of the list. */
|
||
+
|
||
+ /* Unlink the section. */
|
||
+ bfd_section_list_remove (link_info.output_bfd, snew);
|
||
+
|
||
+ /* Now tack it back on in the right place. */
|
||
+ bfd_section_list_append (link_info.output_bfd, snew);
|
||
+ }
|
||
+ else if ((bfd_get_flavour (link_info.output_bfd)
|
||
+ == bfd_target_elf_flavour)
|
||
+ && (bfd_get_flavour (s->owner)
|
||
+ == bfd_target_elf_flavour)
|
||
+ && ((elf_section_type (s) == SHT_NOTE
|
||
+ && (s->flags & SEC_LOAD) != 0)
|
||
+ || (elf_section_type (as) == SHT_NOTE
|
||
+ && (as->flags & SEC_LOAD) != 0)))
|
||
+ {
|
||
+ /* Make sure that output note sections are grouped and sorted
|
||
+ by alignments when inserting a note section or insert a
|
||
+ section after a note section, */
|
||
+ asection *sec;
|
||
+ /* A specific section after which the output note section
|
||
+ should be placed. */
|
||
+ asection *after_sec;
|
||
+ /* True if we need to insert the orphan section after a
|
||
+ specific section to maintain output note section order. */
|
||
+ bool after_sec_note = false;
|
||
+
|
||
+ static asection *first_orphan_note = NULL;
|
||
+
|
||
+ /* Group and sort output note section by alignments in
|
||
+ ascending order. */
|
||
+ after_sec = NULL;
|
||
+ if (elf_section_type (s) == SHT_NOTE
|
||
+ && (s->flags & SEC_LOAD) != 0)
|
||
+ {
|
||
+ /* Search from the beginning for the last output note
|
||
+ section with equal or larger alignments. NB: Don't
|
||
+ place orphan note section after non-note sections. */
|
||
+
|
||
+ first_orphan_note = NULL;
|
||
+ for (sec = link_info.output_bfd->sections;
|
||
+ (sec != NULL
|
||
+ && !bfd_is_abs_section (sec));
|
||
+ sec = sec->next)
|
||
+ if (sec != snew
|
||
+ && elf_section_type (sec) == SHT_NOTE
|
||
+ && (sec->flags & SEC_LOAD) != 0)
|
||
+ {
|
||
+ if (!first_orphan_note)
|
||
+ first_orphan_note = sec;
|
||
+ if (sec->alignment_power >= s->alignment_power)
|
||
+ after_sec = sec;
|
||
+ }
|
||
+ else if (first_orphan_note)
|
||
+ {
|
||
+ /* Stop if there is non-note section after the first
|
||
+ orphan note section. */
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ /* If this will be the first orphan note section, it can
|
||
+ be placed at the default location. */
|
||
+ after_sec_note = first_orphan_note != NULL;
|
||
+ if (after_sec == NULL && after_sec_note)
|
||
+ {
|
||
+ /* If all output note sections have smaller
|
||
+ alignments, place the section before all
|
||
+ output orphan note sections. */
|
||
+ after_sec = first_orphan_note;
|
||
+ insert_after = false;
|
||
+ }
|
||
+ }
|
||
+ else if (first_orphan_note)
|
||
+ {
|
||
+ /* Don't place non-note sections in the middle of orphan
|
||
+ note sections. */
|
||
+ after_sec_note = true;
|
||
+ after_sec = as;
|
||
+ for (sec = as->next;
|
||
+ (sec != NULL
|
||
+ && !bfd_is_abs_section (sec));
|
||
+ sec = sec->next)
|
||
+ if (elf_section_type (sec) == SHT_NOTE
|
||
+ && (sec->flags & SEC_LOAD) != 0)
|
||
+ after_sec = sec;
|
||
+ }
|
||
+
|
||
+ if (after_sec_note)
|
||
+ {
|
||
+ if (after_sec)
|
||
+ {
|
||
+ /* Search forward to insert OS after AFTER_SEC output
|
||
+ statement. */
|
||
+ lang_output_section_statement_type *stmt, *next;
|
||
+ bool found = false;
|
||
+ for (stmt = after; stmt != NULL; stmt = next)
|
||
+ {
|
||
+ next = stmt->next;
|
||
+ if (insert_after)
|
||
+ {
|
||
+ if (stmt->bfd_section == after_sec)
|
||
+ {
|
||
+ place_after = true;
|
||
+ found = true;
|
||
+ after = stmt;
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ /* If INSERT_AFTER is FALSE, place OS before
|
||
+ AFTER_SEC output statement. */
|
||
+ if (next && next->bfd_section == after_sec)
|
||
+ {
|
||
+ place_after = true;
|
||
+ found = true;
|
||
+ after = stmt;
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+
|
||
+ /* Search backward to insert OS after AFTER_SEC output
|
||
+ statement. */
|
||
+ if (!found)
|
||
+ for (stmt = after; stmt != NULL; stmt = stmt->prev)
|
||
+ {
|
||
+ if (insert_after)
|
||
+ {
|
||
+ if (stmt->bfd_section == after_sec)
|
||
+ {
|
||
+ place_after = true;
|
||
+ after = stmt;
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ /* If INSERT_AFTER is FALSE, place OS before
|
||
+ AFTER_SEC output statement. */
|
||
+ if (stmt->next->bfd_section == after_sec)
|
||
+ {
|
||
+ place_after = true;
|
||
+ after = stmt;
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (after_sec == NULL
|
||
+ || (insert_after && after_sec->next != snew)
|
||
+ || (!insert_after && after_sec->prev != snew))
|
||
+ {
|
||
+ /* Unlink the section. */
|
||
+ bfd_section_list_remove (link_info.output_bfd, snew);
|
||
+
|
||
+ /* Place SNEW after AFTER_SEC. If AFTER_SEC is NULL,
|
||
+ prepend SNEW. */
|
||
+ if (after_sec)
|
||
+ {
|
||
+ if (insert_after)
|
||
+ bfd_section_list_insert_after (link_info.output_bfd,
|
||
+ after_sec, snew);
|
||
+ else
|
||
+ bfd_section_list_insert_before (link_info.output_bfd,
|
||
+ after_sec, snew);
|
||
+ }
|
||
+ else
|
||
+ bfd_section_list_prepend (link_info.output_bfd, snew);
|
||
+ }
|
||
+ }
|
||
+ else if (as != snew && as->prev != snew)
|
||
+ {
|
||
+ /* Unlink the section. */
|
||
+ bfd_section_list_remove (link_info.output_bfd, snew);
|
||
+
|
||
+ /* Now tack it back on in the right place. */
|
||
+ bfd_section_list_insert_before (link_info.output_bfd,
|
||
+ as, snew);
|
||
+ }
|
||
+ }
|
||
+ else if (as != snew && as->prev != snew)
|
||
+ {
|
||
+ /* Unlink the section. */
|
||
+ bfd_section_list_remove (link_info.output_bfd, snew);
|
||
+
|
||
+ /* Now tack it back on in the right place. */
|
||
+ bfd_section_list_insert_before (link_info.output_bfd, as, snew);
|
||
+ }
|
||
+
|
||
+ /* Save the end of this list. Further ophans of this type will
|
||
+ follow the one we've just added. */
|
||
+ place->section = &snew->next;
|
||
+
|
||
+ /* The following is non-cosmetic. We try to put the output
|
||
+ statements in some sort of reasonable order here, because they
|
||
+ determine the final load addresses of the orphan sections.
|
||
+ In addition, placing output statements in the wrong order may
|
||
+ require extra segments. For instance, given a typical
|
||
+ situation of all read-only sections placed in one segment and
|
||
+ following that a segment containing all the read-write
|
||
+ sections, we wouldn't want to place an orphan read/write
|
||
+ section before or amongst the read-only ones. */
|
||
+ if (add.head != NULL)
|
||
+ {
|
||
+ lang_output_section_statement_type *newly_added_os;
|
||
+
|
||
+ /* Place OS after AFTER if AFTER_NOTE is TRUE. */
|
||
+ if (place_after)
|
||
+ {
|
||
+ lang_statement_union_type **where;
|
||
+
|
||
+ where = insert_os_after ((lang_statement_union_type *) after);
|
||
+ *add.tail = *where;
|
||
+ *where = add.head;
|
||
+
|
||
+ place->os_tail = &after->next;
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ /* Put it after the last orphan statement we added. */
|
||
+ *add.tail = *place->stmt;
|
||
+ *place->stmt = add.head;
|
||
+ }
|
||
+
|
||
+ /* Fix the global list pointer if we happened to tack our
|
||
+ new list at the tail. */
|
||
+ if (*stat_ptr->tail == add.head)
|
||
+ stat_ptr->tail = add.tail;
|
||
+
|
||
+ /* Save the end of this list. */
|
||
+ place->stmt = add.tail;
|
||
+
|
||
+ /* Do the same for the list of output section statements. */
|
||
+ newly_added_os = *os_tail;
|
||
+ *os_tail = NULL;
|
||
+ newly_added_os->prev = (lang_output_section_statement_type *)
|
||
+ ((char *) place->os_tail
|
||
+ - offsetof (lang_output_section_statement_type, next));
|
||
+ newly_added_os->next = *place->os_tail;
|
||
+ if (newly_added_os->next != NULL)
|
||
+ newly_added_os->next->prev = newly_added_os;
|
||
+ *place->os_tail = newly_added_os;
|
||
+ place->os_tail = &newly_added_os->next;
|
||
+
|
||
+ /* Fixing the global list pointer here is a little different.
|
||
+ We added to the list in lang_enter_output_section_statement,
|
||
+ trimmed off the new output_section_statment above when
|
||
+ assigning *os_tail = NULL, but possibly added it back in
|
||
+ the same place when assigning *place->os_tail. */
|
||
+ if (*os_tail == NULL)
|
||
+ lang_os_list.tail = (lang_statement_union_type **) os_tail;
|
||
+ }
|
||
+ }
|
||
+ return os;
|
||
+}
|
||
+
|
||
+static void
|
||
+lang_print_asneeded (void)
|
||
+{
|
||
+ struct asneeded_minfo *m;
|
||
+
|
||
+ if (asneeded_list_head == NULL)
|
||
+ return;
|
||
+
|
||
+ minfo (_("\nAs-needed library included to satisfy reference by file (symbol)\n\n"));
|
||
+
|
||
+ for (m = asneeded_list_head; m != NULL; m = m->next)
|
||
+ {
|
||
+ int len;
|
||
+
|
||
+ minfo ("%s", m->soname);
|
||
+ len = strlen (m->soname);
|
||
+
|
||
+ if (len >= 29)
|
||
+ {
|
||
+ print_nl ();
|
||
+ len = 0;
|
||
+ }
|
||
+ print_spaces (30 - len);
|
||
+
|
||
+ if (m->ref != NULL)
|
||
+ minfo ("%pB ", m->ref);
|
||
+ minfo ("(%pT)\n", m->name);
|
||
+ }
|
||
+}
|
||
+
|
||
+static void
|
||
+lang_map_flags (flagword flag)
|
||
+{
|
||
+ if (flag & SEC_ALLOC)
|
||
+ minfo ("a");
|
||
+
|
||
+ if (flag & SEC_CODE)
|
||
+ minfo ("x");
|
||
+
|
||
+ if (flag & SEC_READONLY)
|
||
+ minfo ("r");
|
||
+
|
||
+ if (flag & SEC_DATA)
|
||
+ minfo ("w");
|
||
+
|
||
+ if (flag & SEC_LOAD)
|
||
+ minfo ("l");
|
||
+}
|
||
+
|
||
+void
|
||
+lang_map (void)
|
||
+{
|
||
+ lang_memory_region_type *m;
|
||
+ bool dis_header_printed = false;
|
||
+
|
||
+ ldfile_print_input_remaps ();
|
||
+
|
||
+ LANG_FOR_EACH_INPUT_STATEMENT (file)
|
||
+ {
|
||
+ asection *s;
|
||
+
|
||
+ if ((file->the_bfd->flags & (BFD_LINKER_CREATED | DYNAMIC)) != 0
|
||
+ || file->flags.just_syms)
|
||
+ continue;
|
||
+
|
||
+ if (config.print_map_discarded)
|
||
+ for (s = file->the_bfd->sections; s != NULL; s = s->next)
|
||
+ if ((s->output_section == NULL
|
||
+ || s->output_section->owner != link_info.output_bfd)
|
||
+ && (s->flags & (SEC_LINKER_CREATED | SEC_KEEP)) == 0)
|
||
+ {
|
||
+ if (! dis_header_printed)
|
||
+ {
|
||
+ minfo (_("\nDiscarded input sections\n\n"));
|
||
+ dis_header_printed = true;
|
||
+ }
|
||
+
|
||
+ print_input_section (s, true);
|
||
+ }
|
||
+ }
|
||
+ if (config.print_map_discarded && ! dis_header_printed)
|
||
+ minfo (_("\nThere are no discarded input sections\n"));
|
||
+
|
||
+ minfo (_("\nMemory Configuration\n\n"));
|
||
+ fprintf (config.map_file, "%-16s %-18s %-18s %s\n",
|
||
+ _("Name"), _("Origin"), _("Length"), _("Attributes"));
|
||
+
|
||
+ for (m = lang_memory_region_list; m != NULL; m = m->next)
|
||
+ {
|
||
+ fprintf (config.map_file, "%-16s", m->name_list.name);
|
||
+
|
||
+ char buf[32];
|
||
+ bfd_sprintf_vma (link_info.output_bfd, buf, m->origin);
|
||
+ fprintf (config.map_file, " 0x%-16s", buf);
|
||
+ bfd_sprintf_vma (link_info.output_bfd, buf, m->length);
|
||
+ fprintf (config.map_file,
|
||
+ " 0x%*s", m->flags || m->not_flags ? -17 : 0, buf);
|
||
+ if (m->flags)
|
||
+ lang_map_flags (m->flags);
|
||
+
|
||
+ if (m->not_flags)
|
||
+ {
|
||
+ minfo ("!");
|
||
+ lang_map_flags (m->not_flags);
|
||
+ }
|
||
+
|
||
+ print_nl ();
|
||
+ }
|
||
+
|
||
+ minfo (_("\nLinker script and memory map\n\n"));
|
||
+
|
||
+ if (!link_info.reduce_memory_overheads)
|
||
+ {
|
||
+ obstack_begin (&map_obstack, 1000);
|
||
+ bfd_link_hash_traverse (link_info.hash, sort_def_symbol, 0);
|
||
+ }
|
||
+ expld.phase = lang_fixed_phase_enum;
|
||
+ lang_statement_iteration++;
|
||
+ print_statements ();
|
||
+
|
||
+ ldemul_extra_map_file_text (link_info.output_bfd, &link_info,
|
||
+ config.map_file);
|
||
+}
|
||
+
|
||
+static bool
|
||
+sort_def_symbol (struct bfd_link_hash_entry *hash_entry,
|
||
+ void *info ATTRIBUTE_UNUSED)
|
||
+{
|
||
+ if ((hash_entry->type == bfd_link_hash_defined
|
||
+ || hash_entry->type == bfd_link_hash_defweak)
|
||
+ && hash_entry->u.def.section->owner != link_info.output_bfd
|
||
+ && hash_entry->u.def.section->owner != NULL)
|
||
+ {
|
||
+ input_section_userdata_type *ud;
|
||
+ struct map_symbol_def *def;
|
||
+
|
||
+ ud = bfd_section_userdata (hash_entry->u.def.section);
|
||
+ if (!ud)
|
||
+ {
|
||
+ ud = stat_alloc (sizeof (*ud));
|
||
+ bfd_set_section_userdata (hash_entry->u.def.section, ud);
|
||
+ ud->map_symbol_def_tail = &ud->map_symbol_def_head;
|
||
+ ud->map_symbol_def_count = 0;
|
||
+ }
|
||
+ else if (!ud->map_symbol_def_tail)
|
||
+ ud->map_symbol_def_tail = &ud->map_symbol_def_head;
|
||
+
|
||
+ def = (struct map_symbol_def *) obstack_alloc (&map_obstack, sizeof *def);
|
||
+ def->entry = hash_entry;
|
||
+ *(ud->map_symbol_def_tail) = def;
|
||
+ ud->map_symbol_def_tail = &def->next;
|
||
+ ud->map_symbol_def_count++;
|
||
+ }
|
||
+ return true;
|
||
+}
|
||
+
|
||
+/* Initialize an output section. */
|
||
+
|
||
+static void
|
||
+init_os (lang_output_section_statement_type *s, flagword flags)
|
||
+{
|
||
+ if (strcmp (s->name, DISCARD_SECTION_NAME) == 0)
|
||
+ einfo (_("%F%P: illegal use of `%s' section\n"), DISCARD_SECTION_NAME);
|
||
+
|
||
+ if (!s->dup_output)
|
||
+ s->bfd_section = bfd_get_section_by_name (link_info.output_bfd, s->name);
|
||
+ if (s->bfd_section == NULL)
|
||
+ s->bfd_section = bfd_make_section_anyway_with_flags (link_info.output_bfd,
|
||
+ s->name, flags);
|
||
+ if (s->bfd_section == NULL)
|
||
+ {
|
||
+ einfo (_("%F%P: output format %s cannot represent section"
|
||
+ " called %s: %E\n"),
|
||
+ link_info.output_bfd->xvec->name, s->name);
|
||
+ }
|
||
+ s->bfd_section->output_section = s->bfd_section;
|
||
+ s->bfd_section->output_offset = 0;
|
||
+
|
||
+ /* Set the userdata of the output section to the output section
|
||
+ statement to avoid lookup. */
|
||
+ bfd_set_section_userdata (s->bfd_section, s);
|
||
+
|
||
+ /* If there is a base address, make sure that any sections it might
|
||
+ mention are initialized. */
|
||
+ if (s->addr_tree != NULL)
|
||
+ exp_init_os (s->addr_tree);
|
||
+
|
||
+ if (s->load_base != NULL)
|
||
+ exp_init_os (s->load_base);
|
||
+
|
||
+ /* If supplied an alignment, set it. */
|
||
+ if (s->section_alignment != NULL)
|
||
+ s->bfd_section->alignment_power = exp_get_power (s->section_alignment,
|
||
+ "section alignment");
|
||
+}
|
||
+
|
||
+/* Make sure that all output sections mentioned in an expression are
|
||
+ initialized. */
|
||
+
|
||
+static void
|
||
+exp_init_os (etree_type *exp)
|
||
+{
|
||
+ switch (exp->type.node_class)
|
||
+ {
|
||
+ case etree_assign:
|
||
+ case etree_provide:
|
||
+ case etree_provided:
|
||
+ exp_init_os (exp->assign.src);
|
||
+ break;
|
||
+
|
||
+ case etree_binary:
|
||
+ exp_init_os (exp->binary.lhs);
|
||
+ exp_init_os (exp->binary.rhs);
|
||
+ break;
|
||
+
|
||
+ case etree_trinary:
|
||
+ exp_init_os (exp->trinary.cond);
|
||
+ exp_init_os (exp->trinary.lhs);
|
||
+ exp_init_os (exp->trinary.rhs);
|
||
+ break;
|
||
+
|
||
+ case etree_assert:
|
||
+ exp_init_os (exp->assert_s.child);
|
||
+ break;
|
||
+
|
||
+ case etree_unary:
|
||
+ exp_init_os (exp->unary.child);
|
||
+ break;
|
||
+
|
||
+ case etree_name:
|
||
+ switch (exp->type.node_code)
|
||
+ {
|
||
+ case ADDR:
|
||
+ case LOADADDR:
|
||
+ {
|
||
+ lang_output_section_statement_type *os;
|
||
+
|
||
+ os = lang_output_section_find (exp->name.name);
|
||
+ if (os != NULL && os->bfd_section == NULL)
|
||
+ init_os (os, 0);
|
||
+ }
|
||
+ }
|
||
+ break;
|
||
+
|
||
+ default:
|
||
+ break;
|
||
+ }
|
||
+}
|
||
+
|
||
+static void
|
||
+section_already_linked (bfd *abfd, asection *sec, void *data)
|
||
+{
|
||
+ lang_input_statement_type *entry = (lang_input_statement_type *) data;
|
||
+
|
||
+ /* If we are only reading symbols from this object, then we want to
|
||
+ discard all sections. */
|
||
+ if (entry->flags.just_syms)
|
||
+ {
|
||
+ bfd_link_just_syms (abfd, sec, &link_info);
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ /* Deal with SHF_EXCLUDE ELF sections. */
|
||
+ if (!bfd_link_relocatable (&link_info)
|
||
+ && (abfd->flags & BFD_PLUGIN) == 0
|
||
+ && (sec->flags & (SEC_GROUP | SEC_KEEP | SEC_EXCLUDE)) == SEC_EXCLUDE)
|
||
+ sec->output_section = bfd_abs_section_ptr;
|
||
+
|
||
+ if (!(abfd->flags & DYNAMIC))
|
||
+ bfd_section_already_linked (abfd, sec, &link_info);
|
||
+}
|
||
+
|
||
+
|
||
+/* Returns true if SECTION is one we know will be discarded based on its
|
||
+ section flags, otherwise returns false. */
|
||
+
|
||
+static bool
|
||
+lang_discard_section_p (asection *section)
|
||
+{
|
||
+ bool discard;
|
||
+ flagword flags = section->flags;
|
||
+
|
||
+ /* Discard sections marked with SEC_EXCLUDE. */
|
||
+ discard = (flags & SEC_EXCLUDE) != 0;
|
||
+
|
||
+ /* Discard the group descriptor sections when we're finally placing the
|
||
+ sections from within the group. */
|
||
+ if ((flags & SEC_GROUP) != 0
|
||
+ && link_info.resolve_section_groups)
|
||
+ discard = true;
|
||
+
|
||
+ /* Discard debugging sections if we are stripping debugging
|
||
+ information. */
|
||
+ if ((link_info.strip == strip_debugger || link_info.strip == strip_all)
|
||
+ && (flags & SEC_DEBUGGING) != 0)
|
||
+ discard = true;
|
||
+
|
||
+ /* Discard non-alloc sections if we are stripping section headers. */
|
||
+ else if (config.no_section_header && (flags & SEC_ALLOC) == 0)
|
||
+ discard = true;
|
||
+
|
||
+ return discard;
|
||
+}
|
||
+
|
||
+/* Return TRUE if SECTION is never going to be added to output statement
|
||
+ OUTPUT. lang_add_section() definitely won't do anything with SECTION
|
||
+ if this returns TRUE. It may do something (or not) if this returns FALSE.
|
||
+
|
||
+ Can be used as early-out to filter matches. This may set
|
||
+ output_section of SECTION, if it was unset, to the abs section in case
|
||
+ we discover SECTION to be always discarded. This may also give
|
||
+ warning messages. */
|
||
+
|
||
+static bool
|
||
+wont_add_section_p (asection *section,
|
||
+ lang_output_section_statement_type *output)
|
||
+{
|
||
+ bool discard;
|
||
+
|
||
+ /* Is this section one we know should be discarded? */
|
||
+ discard = lang_discard_section_p (section);
|
||
+
|
||
+ /* Discard input sections which are assigned to a section named
|
||
+ DISCARD_SECTION_NAME. */
|
||
+ if (strcmp (output->name, DISCARD_SECTION_NAME) == 0)
|
||
+ discard = true;
|
||
+
|
||
+ if (discard)
|
||
+ {
|
||
+ if (section->output_section == NULL)
|
||
+ {
|
||
+ /* This prevents future calls from assigning this section or
|
||
+ warning about it again. */
|
||
+ section->output_section = bfd_abs_section_ptr;
|
||
+ }
|
||
+ else if (bfd_is_abs_section (section->output_section))
|
||
+ ;
|
||
+ else if (link_info.non_contiguous_regions_warnings)
|
||
+ einfo (_("%P:%pS: warning: --enable-non-contiguous-regions makes "
|
||
+ "section `%pA' from `%pB' match /DISCARD/ clause.\n"),
|
||
+ NULL, section, section->owner);
|
||
+
|
||
+ return true;
|
||
+ }
|
||
+
|
||
+ if (section->output_section != NULL)
|
||
+ {
|
||
+ if (!link_info.non_contiguous_regions)
|
||
+ return true;
|
||
+
|
||
+ /* SECTION has already been handled in a special way
|
||
+ (eg. LINK_ONCE): skip it. */
|
||
+ if (bfd_is_abs_section (section->output_section))
|
||
+ return true;
|
||
+
|
||
+ /* Already assigned to the same output section, do not process
|
||
+ it again, to avoid creating loops between duplicate sections
|
||
+ later. */
|
||
+ if (section->output_section == output->bfd_section)
|
||
+ return true;
|
||
+
|
||
+ if (link_info.non_contiguous_regions_warnings && output->bfd_section)
|
||
+ einfo (_("%P:%pS: warning: --enable-non-contiguous-regions may "
|
||
+ "change behaviour for section `%pA' from `%pB' (assigned to "
|
||
+ "%pA, but additional match: %pA)\n"),
|
||
+ NULL, section, section->owner, section->output_section,
|
||
+ output->bfd_section);
|
||
+
|
||
+ /* SECTION has already been assigned to an output section, but
|
||
+ the user allows it to be mapped to another one in case it
|
||
+ overflows. We'll later update the actual output section in
|
||
+ size_input_section as appropriate. */
|
||
+ }
|
||
+
|
||
+ return false;
|
||
+}
|
||
+
|
||
+/* The wild routines.
|
||
+
|
||
+ These expand statements like *(.text) and foo.o to a list of
|
||
+ explicit actions, like foo.o(.text), bar.o(.text) and
|
||
+ foo.o(.text, .data). */
|
||
+
|
||
+/* Add SECTION to the output section OUTPUT. Do this by creating a
|
||
+ lang_input_section statement which is placed at PTR. */
|
||
+
|
||
+void
|
||
+lang_add_section (lang_statement_list_type *ptr,
|
||
+ asection *section,
|
||
+ struct wildcard_list *pattern,
|
||
+ struct flag_info *sflag_info,
|
||
+ lang_output_section_statement_type *output)
|
||
+{
|
||
+ flagword flags = section->flags;
|
||
+
|
||
+ lang_input_section_type *new_section;
|
||
+ bfd *abfd = link_info.output_bfd;
|
||
+
|
||
+ if (wont_add_section_p (section, output))
|
||
+ return;
|
||
+
|
||
+ if (sflag_info)
|
||
+ {
|
||
+ bool keep;
|
||
+
|
||
+ keep = bfd_lookup_section_flags (&link_info, sflag_info, section);
|
||
+ if (!keep)
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ /* We don't copy the SEC_NEVER_LOAD flag from an input section
|
||
+ to an output section, because we want to be able to include a
|
||
+ SEC_NEVER_LOAD section in the middle of an otherwise loaded
|
||
+ section (I don't know why we want to do this, but we do).
|
||
+ build_link_order in ldwrite.c handles this case by turning
|
||
+ the embedded SEC_NEVER_LOAD section into a fill. */
|
||
+ flags &= ~ SEC_NEVER_LOAD;
|
||
+
|
||
+ /* If final link, don't copy the SEC_LINK_ONCE flags, they've
|
||
+ already been processed. One reason to do this is that on pe
|
||
+ format targets, .text$foo sections go into .text and it's odd
|
||
+ to see .text with SEC_LINK_ONCE set. */
|
||
+ if ((flags & (SEC_LINK_ONCE | SEC_GROUP)) == (SEC_LINK_ONCE | SEC_GROUP))
|
||
+ {
|
||
+ if (link_info.resolve_section_groups)
|
||
+ flags &= ~(SEC_LINK_ONCE | SEC_LINK_DUPLICATES | SEC_RELOC);
|
||
+ else
|
||
+ flags &= ~(SEC_LINK_DUPLICATES | SEC_RELOC);
|
||
+ }
|
||
+ else if (!bfd_link_relocatable (&link_info))
|
||
+ flags &= ~(SEC_LINK_ONCE | SEC_LINK_DUPLICATES | SEC_RELOC);
|
||
+
|
||
+ switch (output->sectype)
|
||
+ {
|
||
+ case normal_section:
|
||
+ case overlay_section:
|
||
+ case first_overlay_section:
|
||
+ case type_section:
|
||
+ break;
|
||
+ case noalloc_section:
|
||
+ flags &= ~SEC_ALLOC;
|
||
+ break;
|
||
+ case typed_readonly_section:
|
||
+ case readonly_section:
|
||
+ flags |= SEC_READONLY;
|
||
+ break;
|
||
+ case noload_section:
|
||
+ flags &= ~SEC_LOAD;
|
||
+ flags |= SEC_NEVER_LOAD;
|
||
+ /* Unfortunately GNU ld has managed to evolve two different
|
||
+ meanings to NOLOAD in scripts. ELF gets a .bss style noload,
|
||
+ alloc, no contents section. All others get a noload, noalloc
|
||
+ section. */
|
||
+ if (bfd_get_flavour (link_info.output_bfd) == bfd_target_elf_flavour)
|
||
+ flags &= ~SEC_HAS_CONTENTS;
|
||
+ else
|
||
+ flags &= ~SEC_ALLOC;
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ if (output->bfd_section == NULL)
|
||
+ init_os (output, flags);
|
||
+
|
||
+ /* If SEC_READONLY is not set in the input section, then clear
|
||
+ it from the output section. */
|
||
+ output->bfd_section->flags &= flags | ~SEC_READONLY;
|
||
+
|
||
+ if (output->bfd_section->linker_has_input)
|
||
+ {
|
||
+ /* Only set SEC_READONLY flag on the first input section. */
|
||
+ flags &= ~ SEC_READONLY;
|
||
+
|
||
+ /* Keep SEC_MERGE and SEC_STRINGS only if they are the same. */
|
||
+ if ((output->bfd_section->flags & (SEC_MERGE | SEC_STRINGS))
|
||
+ != (flags & (SEC_MERGE | SEC_STRINGS))
|
||
+ || ((flags & SEC_MERGE) != 0
|
||
+ && output->bfd_section->entsize != section->entsize))
|
||
+ {
|
||
+ output->bfd_section->flags &= ~ (SEC_MERGE | SEC_STRINGS);
|
||
+ flags &= ~ (SEC_MERGE | SEC_STRINGS);
|
||
+ }
|
||
+ }
|
||
+ output->bfd_section->flags |= flags;
|
||
+
|
||
+ if (!output->bfd_section->linker_has_input)
|
||
+ {
|
||
+ output->bfd_section->linker_has_input = 1;
|
||
+ /* This must happen after flags have been updated. The output
|
||
+ section may have been created before we saw its first input
|
||
+ section, eg. for a data statement. */
|
||
+ bfd_init_private_section_data (section->owner, section,
|
||
+ link_info.output_bfd,
|
||
+ output->bfd_section,
|
||
+ &link_info);
|
||
+ if ((flags & SEC_MERGE) != 0)
|
||
+ output->bfd_section->entsize = section->entsize;
|
||
+ }
|
||
+
|
||
+ if ((flags & SEC_TIC54X_BLOCK) != 0
|
||
+ && bfd_get_arch (section->owner) == bfd_arch_tic54x)
|
||
+ {
|
||
+ /* FIXME: This value should really be obtained from the bfd... */
|
||
+ output->block_value = 128;
|
||
+ }
|
||
+
|
||
+ /* When a .ctors section is placed in .init_array it must be copied
|
||
+ in reverse order. Similarly for .dtors. Set that up. */
|
||
+ if (bfd_get_flavour (link_info.output_bfd) == bfd_target_elf_flavour
|
||
+ && ((startswith (section->name, ".ctors")
|
||
+ && strcmp (output->bfd_section->name, ".init_array") == 0)
|
||
+ || (startswith (section->name, ".dtors")
|
||
+ && strcmp (output->bfd_section->name, ".fini_array") == 0))
|
||
+ && (section->name[6] == 0 || section->name[6] == '.'))
|
||
+ section->flags |= SEC_ELF_REVERSE_COPY;
|
||
+
|
||
+ if (section->alignment_power > output->bfd_section->alignment_power)
|
||
+ output->bfd_section->alignment_power = section->alignment_power;
|
||
+
|
||
+ section->output_section = output->bfd_section;
|
||
+
|
||
+ if (!map_head_is_link_order)
|
||
+ {
|
||
+ asection *s = output->bfd_section->map_tail.s;
|
||
+ output->bfd_section->map_tail.s = section;
|
||
+ section->map_head.s = NULL;
|
||
+ section->map_tail.s = s;
|
||
+ if (s != NULL)
|
||
+ s->map_head.s = section;
|
||
+ else
|
||
+ output->bfd_section->map_head.s = section;
|
||
+ }
|
||
+
|
||
+ /* Add a section reference to the list. */
|
||
+ new_section = new_stat (lang_input_section, ptr);
|
||
+ new_section->section = section;
|
||
+ new_section->pattern = pattern;
|
||
+}
|
||
+
|
||
+/* Expand a wild statement for a particular FILE. SECTION may be
|
||
+ NULL, in which case it is a wild card. This assumes that the
|
||
+ wild statement doesn't need any sorting (of filenames or sections). */
|
||
+
|
||
+static void
|
||
+output_section_callback_nosort (lang_wild_statement_type *ptr,
|
||
+ struct wildcard_list *sec ATTRIBUTE_UNUSED,
|
||
+ asection *section,
|
||
+ lang_input_statement_type *file ATTRIBUTE_UNUSED,
|
||
+ void *output)
|
||
+{
|
||
+ lang_output_section_statement_type *os;
|
||
+
|
||
+ os = (lang_output_section_statement_type *) output;
|
||
+
|
||
+ /* Exclude sections that match UNIQUE_SECTION_LIST. */
|
||
+ if (unique_section_p (section, os))
|
||
+ return;
|
||
+
|
||
+ lang_add_section (&ptr->children, section, ptr->section_list,
|
||
+ ptr->section_flag_list, os);
|
||
+}
|
||
+
|
||
+/* Check if all sections in a wild statement for a particular FILE
|
||
+ are readonly. */
|
||
+
|
||
+static void
|
||
+check_section_callback (lang_wild_statement_type *ptr ATTRIBUTE_UNUSED,
|
||
+ struct wildcard_list *sec ATTRIBUTE_UNUSED,
|
||
+ asection *section,
|
||
+ lang_input_statement_type *file ATTRIBUTE_UNUSED,
|
||
+ void *output)
|
||
+{
|
||
+ lang_output_section_statement_type *os;
|
||
+
|
||
+ os = (lang_output_section_statement_type *) output;
|
||
+
|
||
+ /* Exclude sections that match UNIQUE_SECTION_LIST. */
|
||
+ if (unique_section_p (section, os))
|
||
+ return;
|
||
+
|
||
+ if (section->output_section == NULL && (section->flags & SEC_READONLY) == 0)
|
||
+ os->all_input_readonly = false;
|
||
+}
|
||
+
|
||
+/* This is passed a file name which must have been seen already and
|
||
+ added to the statement tree. We will see if it has been opened
|
||
+ already and had its symbols read. If not then we'll read it. */
|
||
+
|
||
+static lang_input_statement_type *
|
||
+lookup_name (const char *name)
|
||
+{
|
||
+ lang_input_statement_type *search;
|
||
+
|
||
+ for (search = (void *) input_file_chain.head;
|
||
+ search != NULL;
|
||
+ search = search->next_real_file)
|
||
+ {
|
||
+ /* Use the local_sym_name as the name of the file that has
|
||
+ already been loaded as filename might have been transformed
|
||
+ via the search directory lookup mechanism. */
|
||
+ const char *filename = search->local_sym_name;
|
||
+
|
||
+ if (filename != NULL
|
||
+ && filename_cmp (filename, name) == 0)
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ if (search == NULL)
|
||
+ {
|
||
+ /* Arrange to splice the input statement added by new_afile into
|
||
+ statement_list after the current input_file_chain tail.
|
||
+ We know input_file_chain is not an empty list, and that
|
||
+ lookup_name was called via open_input_bfds. Later calls to
|
||
+ lookup_name should always match an existing input_statement. */
|
||
+ lang_statement_union_type **tail = stat_ptr->tail;
|
||
+ lang_statement_union_type **after
|
||
+ = (void *) ((char *) input_file_chain.tail
|
||
+ - offsetof (lang_input_statement_type, next_real_file)
|
||
+ + offsetof (lang_input_statement_type, header.next));
|
||
+ lang_statement_union_type *rest = *after;
|
||
+ stat_ptr->tail = after;
|
||
+ search = new_afile (name, lang_input_file_is_search_file_enum,
|
||
+ default_target, NULL);
|
||
+ *stat_ptr->tail = rest;
|
||
+ if (*tail == NULL)
|
||
+ stat_ptr->tail = tail;
|
||
+ }
|
||
+
|
||
+ /* If we have already added this file, or this file is not real
|
||
+ don't add this file. */
|
||
+ if (search->flags.loaded || !search->flags.real)
|
||
+ return search;
|
||
+
|
||
+ if (!load_symbols (search, NULL))
|
||
+ return NULL;
|
||
+
|
||
+ return search;
|
||
+}
|
||
+
|
||
+/* Save LIST as a list of libraries whose symbols should not be exported. */
|
||
+
|
||
+struct excluded_lib
|
||
+{
|
||
+ char *name;
|
||
+ struct excluded_lib *next;
|
||
+};
|
||
+static struct excluded_lib *excluded_libs;
|
||
+
|
||
+void
|
||
+add_excluded_libs (const char *list)
|
||
+{
|
||
+ const char *p = list, *end;
|
||
+
|
||
+ while (*p != '\0')
|
||
+ {
|
||
+ struct excluded_lib *entry;
|
||
+ end = strpbrk (p, ",:");
|
||
+ if (end == NULL)
|
||
+ end = p + strlen (p);
|
||
+ entry = (struct excluded_lib *) xmalloc (sizeof (*entry));
|
||
+ entry->next = excluded_libs;
|
||
+ entry->name = (char *) xmalloc (end - p + 1);
|
||
+ memcpy (entry->name, p, end - p);
|
||
+ entry->name[end - p] = '\0';
|
||
+ excluded_libs = entry;
|
||
+ if (*end == '\0')
|
||
+ break;
|
||
+ p = end + 1;
|
||
+ }
|
||
+}
|
||
+
|
||
+static void
|
||
+check_excluded_libs (bfd *abfd)
|
||
+{
|
||
+ struct excluded_lib *lib = excluded_libs;
|
||
+
|
||
+ while (lib)
|
||
+ {
|
||
+ int len = strlen (lib->name);
|
||
+ const char *filename = lbasename (bfd_get_filename (abfd));
|
||
+
|
||
+ if (strcmp (lib->name, "ALL") == 0)
|
||
+ {
|
||
+ abfd->no_export = true;
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ if (filename_ncmp (lib->name, filename, len) == 0
|
||
+ && (filename[len] == '\0'
|
||
+ || (filename[len] == '.' && filename[len + 1] == 'a'
|
||
+ && filename[len + 2] == '\0')))
|
||
+ {
|
||
+ abfd->no_export = true;
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ lib = lib->next;
|
||
+ }
|
||
+}
|
||
+
|
||
+/* Get the symbols for an input file. */
|
||
+
|
||
+bool
|
||
+load_symbols (lang_input_statement_type *entry,
|
||
+ lang_statement_list_type *place)
|
||
+{
|
||
+ char **matching;
|
||
+
|
||
+ if (entry->flags.loaded)
|
||
+ return true;
|
||
+
|
||
+ ldfile_open_file (entry);
|
||
+
|
||
+ /* Do not process further if the file was missing. */
|
||
+ if (entry->flags.missing_file)
|
||
+ return true;
|
||
+
|
||
+ if (trace_files || verbose)
|
||
+ info_msg ("%pI\n", entry);
|
||
+
|
||
+ if (!bfd_check_format (entry->the_bfd, bfd_archive)
|
||
+ && !bfd_check_format_matches (entry->the_bfd, bfd_object, &matching))
|
||
+ {
|
||
+ bfd_error_type err;
|
||
+ struct lang_input_statement_flags save_flags;
|
||
+ extern FILE *yyin;
|
||
+
|
||
+ err = bfd_get_error ();
|
||
+
|
||
+ /* See if the emulation has some special knowledge. */
|
||
+ if (ldemul_unrecognized_file (entry))
|
||
+ {
|
||
+ if (err == bfd_error_file_ambiguously_recognized)
|
||
+ free (matching);
|
||
+ return true;
|
||
+ }
|
||
+
|
||
+ if (err == bfd_error_file_ambiguously_recognized)
|
||
+ {
|
||
+ char **p;
|
||
+
|
||
+ einfo (_("%P: %pB: file not recognized: %E;"
|
||
+ " matching formats:"), entry->the_bfd);
|
||
+ for (p = matching; *p != NULL; p++)
|
||
+ einfo (" %s", *p);
|
||
+ free (matching);
|
||
+ einfo ("%F\n");
|
||
+ }
|
||
+ else if (err != bfd_error_file_not_recognized
|
||
+ || place == NULL)
|
||
+ einfo (_("%F%P: %pB: file not recognized: %E\n"), entry->the_bfd);
|
||
+
|
||
+ bfd_close (entry->the_bfd);
|
||
+ entry->the_bfd = NULL;
|
||
+
|
||
+ /* Try to interpret the file as a linker script. */
|
||
+ save_flags = input_flags;
|
||
+ ldfile_open_command_file (entry->filename);
|
||
+
|
||
+ push_stat_ptr (place);
|
||
+ input_flags.add_DT_NEEDED_for_regular
|
||
+ = entry->flags.add_DT_NEEDED_for_regular;
|
||
+ input_flags.add_DT_NEEDED_for_dynamic
|
||
+ = entry->flags.add_DT_NEEDED_for_dynamic;
|
||
+ input_flags.whole_archive = entry->flags.whole_archive;
|
||
+ input_flags.dynamic = entry->flags.dynamic;
|
||
+
|
||
+ ldfile_assumed_script = true;
|
||
+ parser_input = input_script;
|
||
+ current_input_file = entry->filename;
|
||
+ yyparse ();
|
||
+ current_input_file = NULL;
|
||
+ ldfile_assumed_script = false;
|
||
+
|
||
+ /* missing_file is sticky. sysrooted will already have been
|
||
+ restored when seeing EOF in yyparse, but no harm to restore
|
||
+ again. */
|
||
+ save_flags.missing_file |= input_flags.missing_file;
|
||
+ input_flags = save_flags;
|
||
+ pop_stat_ptr ();
|
||
+ fclose (yyin);
|
||
+ yyin = NULL;
|
||
+ entry->flags.loaded = true;
|
||
+
|
||
+ return true;
|
||
+ }
|
||
+
|
||
+ if (ldemul_recognized_file (entry))
|
||
+ return true;
|
||
+
|
||
+ /* We don't call ldlang_add_file for an archive. Instead, the
|
||
+ add_symbols entry point will call ldlang_add_file, via the
|
||
+ add_archive_element callback, for each element of the archive
|
||
+ which is used. */
|
||
+ switch (bfd_get_format (entry->the_bfd))
|
||
+ {
|
||
+ default:
|
||
+ break;
|
||
+
|
||
+ case bfd_object:
|
||
+ if (!entry->flags.reload)
|
||
+ ldlang_add_file (entry);
|
||
+ break;
|
||
+
|
||
+ case bfd_archive:
|
||
+ check_excluded_libs (entry->the_bfd);
|
||
+
|
||
+ bfd_set_usrdata (entry->the_bfd, entry);
|
||
+ if (entry->flags.whole_archive)
|
||
+ {
|
||
+ bfd *member = NULL;
|
||
+ bool loaded = true;
|
||
+
|
||
+ for (;;)
|
||
+ {
|
||
+ bfd *subsbfd;
|
||
+ member = bfd_openr_next_archived_file (entry->the_bfd, member);
|
||
+
|
||
+ if (member == NULL)
|
||
+ break;
|
||
+
|
||
+ if (!bfd_check_format (member, bfd_object))
|
||
+ {
|
||
+ einfo (_("%F%P: %pB: member %pB in archive is not an object\n"),
|
||
+ entry->the_bfd, member);
|
||
+ loaded = false;
|
||
+ }
|
||
+
|
||
+ subsbfd = member;
|
||
+ if (!(*link_info.callbacks
|
||
+ ->add_archive_element) (&link_info, member,
|
||
+ "--whole-archive", &subsbfd))
|
||
+ abort ();
|
||
+
|
||
+ /* Potentially, the add_archive_element hook may have set a
|
||
+ substitute BFD for us. */
|
||
+ if (!bfd_link_add_symbols (subsbfd, &link_info))
|
||
+ {
|
||
+ einfo (_("%F%P: %pB: error adding symbols: %E\n"), member);
|
||
+ loaded = false;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ entry->flags.loaded = loaded;
|
||
+ return loaded;
|
||
+ }
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ if (bfd_link_add_symbols (entry->the_bfd, &link_info))
|
||
+ entry->flags.loaded = true;
|
||
+ else
|
||
+ einfo (_("%F%P: %pB: error adding symbols: %E\n"), entry->the_bfd);
|
||
+
|
||
+ return entry->flags.loaded;
|
||
+}
|
||
+
|
||
+/* Handle a wild statement. S->FILENAME or S->SECTION_LIST or both
|
||
+ may be NULL, indicating that it is a wildcard. Separate
|
||
+ lang_input_section statements are created for each part of the
|
||
+ expansion; they are added after the wild statement S. OUTPUT is
|
||
+ the output section. */
|
||
+
|
||
+static void
|
||
+wild (lang_wild_statement_type *s,
|
||
+ const char *target ATTRIBUTE_UNUSED,
|
||
+ lang_output_section_statement_type *output)
|
||
+{
|
||
+ struct wildcard_list *sec;
|
||
+
|
||
+ if (s->filenames_sorted || s->any_specs_sorted)
|
||
+ {
|
||
+ lang_section_bst_type *tree;
|
||
+
|
||
+ walk_wild (s, output_section_callback_sort, output);
|
||
+
|
||
+ tree = s->tree;
|
||
+ if (tree)
|
||
+ {
|
||
+ output_section_callback_tree_to_list (s, tree, output);
|
||
+ s->tree = NULL;
|
||
+ s->rightmost = &s->tree;
|
||
+ }
|
||
+ }
|
||
+ else
|
||
+ walk_wild (s, output_section_callback_nosort, output);
|
||
+
|
||
+ if (default_common_section == NULL)
|
||
+ for (sec = s->section_list; sec != NULL; sec = sec->next)
|
||
+ if (sec->spec.name != NULL && strcmp (sec->spec.name, "COMMON") == 0)
|
||
+ {
|
||
+ /* Remember the section that common is going to in case we
|
||
+ later get something which doesn't know where to put it. */
|
||
+ default_common_section = output;
|
||
+ break;
|
||
+ }
|
||
+}
|
||
+
|
||
+/* Return TRUE iff target is the sought target. */
|
||
+
|
||
+static int
|
||
+get_target (const bfd_target *target, void *data)
|
||
+{
|
||
+ const char *sought = (const char *) data;
|
||
+
|
||
+ return strcmp (target->name, sought) == 0;
|
||
+}
|
||
+
|
||
+/* Like strcpy() but convert to lower case as well. */
|
||
+
|
||
+static void
|
||
+stricpy (char *dest, const char *src)
|
||
+{
|
||
+ char c;
|
||
+
|
||
+ while ((c = *src++) != 0)
|
||
+ *dest++ = TOLOWER (c);
|
||
+
|
||
+ *dest = 0;
|
||
+}
|
||
+
|
||
+/* Remove the first occurrence of needle (if any) in haystack
|
||
+ from haystack. */
|
||
+
|
||
+static void
|
||
+strcut (char *haystack, const char *needle)
|
||
+{
|
||
+ haystack = strstr (haystack, needle);
|
||
+
|
||
+ if (haystack)
|
||
+ {
|
||
+ char *src;
|
||
+
|
||
+ for (src = haystack + strlen (needle); *src;)
|
||
+ *haystack++ = *src++;
|
||
+
|
||
+ *haystack = 0;
|
||
+ }
|
||
+}
|
||
+
|
||
+/* Compare two target format name strings.
|
||
+ Return a value indicating how "similar" they are. */
|
||
+
|
||
+static int
|
||
+name_compare (const char *first, const char *second)
|
||
+{
|
||
+ char *copy1;
|
||
+ char *copy2;
|
||
+ int result;
|
||
+
|
||
+ copy1 = (char *) xmalloc (strlen (first) + 1);
|
||
+ copy2 = (char *) xmalloc (strlen (second) + 1);
|
||
+
|
||
+ /* Convert the names to lower case. */
|
||
+ stricpy (copy1, first);
|
||
+ stricpy (copy2, second);
|
||
+
|
||
+ /* Remove size and endian strings from the name. */
|
||
+ strcut (copy1, "big");
|
||
+ strcut (copy1, "little");
|
||
+ strcut (copy2, "big");
|
||
+ strcut (copy2, "little");
|
||
+
|
||
+ /* Return a value based on how many characters match,
|
||
+ starting from the beginning. If both strings are
|
||
+ the same then return 10 * their length. */
|
||
+ for (result = 0; copy1[result] == copy2[result]; result++)
|
||
+ if (copy1[result] == 0)
|
||
+ {
|
||
+ result *= 10;
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ free (copy1);
|
||
+ free (copy2);
|
||
+
|
||
+ return result;
|
||
+}
|
||
+
|
||
+/* Set by closest_target_match() below. */
|
||
+static const bfd_target *winner;
|
||
+
|
||
+/* Scan all the valid bfd targets looking for one that has the endianness
|
||
+ requirement that was specified on the command line, and is the nearest
|
||
+ match to the original output target. */
|
||
+
|
||
+static int
|
||
+closest_target_match (const bfd_target *target, void *data)
|
||
+{
|
||
+ const bfd_target *original = (const bfd_target *) data;
|
||
+
|
||
+ if (command_line.endian == ENDIAN_BIG
|
||
+ && target->byteorder != BFD_ENDIAN_BIG)
|
||
+ return 0;
|
||
+
|
||
+ if (command_line.endian == ENDIAN_LITTLE
|
||
+ && target->byteorder != BFD_ENDIAN_LITTLE)
|
||
+ return 0;
|
||
+
|
||
+ /* Must be the same flavour. */
|
||
+ if (target->flavour != original->flavour)
|
||
+ return 0;
|
||
+
|
||
+ /* Ignore generic big and little endian elf vectors. */
|
||
+ if (strcmp (target->name, "elf32-big") == 0
|
||
+ || strcmp (target->name, "elf64-big") == 0
|
||
+ || strcmp (target->name, "elf32-little") == 0
|
||
+ || strcmp (target->name, "elf64-little") == 0)
|
||
+ return 0;
|
||
+
|
||
+ /* If we have not found a potential winner yet, then record this one. */
|
||
+ if (winner == NULL)
|
||
+ {
|
||
+ winner = target;
|
||
+ return 0;
|
||
+ }
|
||
+
|
||
+ /* Oh dear, we now have two potential candidates for a successful match.
|
||
+ Compare their names and choose the better one. */
|
||
+ if (name_compare (target->name, original->name)
|
||
+ > name_compare (winner->name, original->name))
|
||
+ winner = target;
|
||
+
|
||
+ /* Keep on searching until wqe have checked them all. */
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+/* Return the BFD target format of the first input file. */
|
||
+
|
||
+static const char *
|
||
+get_first_input_target (void)
|
||
+{
|
||
+ const char *target = NULL;
|
||
+
|
||
+ LANG_FOR_EACH_INPUT_STATEMENT (s)
|
||
+ {
|
||
+ if (s->header.type == lang_input_statement_enum
|
||
+ && s->flags.real)
|
||
+ {
|
||
+ ldfile_open_file (s);
|
||
+
|
||
+ if (s->the_bfd != NULL
|
||
+ && bfd_check_format (s->the_bfd, bfd_object))
|
||
+ {
|
||
+ target = bfd_get_target (s->the_bfd);
|
||
+
|
||
+ if (target != NULL)
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+
|
||
+ return target;
|
||
+}
|
||
+
|
||
+const char *
|
||
+lang_get_output_target (void)
|
||
+{
|
||
+ const char *target;
|
||
+
|
||
+ /* Has the user told us which output format to use? */
|
||
+ if (output_target != NULL)
|
||
+ return output_target;
|
||
+
|
||
+ /* No - has the current target been set to something other than
|
||
+ the default? */
|
||
+ if (current_target != default_target && current_target != NULL)
|
||
+ return current_target;
|
||
+
|
||
+ /* No - can we determine the format of the first input file? */
|
||
+ target = get_first_input_target ();
|
||
+ if (target != NULL)
|
||
+ return target;
|
||
+
|
||
+ /* Failed - use the default output target. */
|
||
+ return default_target;
|
||
+}
|
||
+
|
||
+/* Open the output file. */
|
||
+
|
||
+static void
|
||
+open_output (const char *name)
|
||
+{
|
||
+ lang_input_statement_type *f;
|
||
+ char *out = lrealpath (name);
|
||
+
|
||
+ for (f = (void *) input_file_chain.head;
|
||
+ f != NULL;
|
||
+ f = f->next_real_file)
|
||
+ if (f->flags.real)
|
||
+ {
|
||
+ char *in = lrealpath (f->local_sym_name);
|
||
+ if (filename_cmp (in, out) == 0)
|
||
+ einfo (_("%F%P: input file '%s' is the same as output file\n"),
|
||
+ f->filename);
|
||
+ free (in);
|
||
+ }
|
||
+ free (out);
|
||
+
|
||
+ output_target = lang_get_output_target ();
|
||
+
|
||
+ /* Has the user requested a particular endianness on the command
|
||
+ line? */
|
||
+ if (command_line.endian != ENDIAN_UNSET)
|
||
+ {
|
||
+ /* Get the chosen target. */
|
||
+ const bfd_target *target
|
||
+ = bfd_iterate_over_targets (get_target, (void *) output_target);
|
||
+
|
||
+ /* If the target is not supported, we cannot do anything. */
|
||
+ if (target != NULL)
|
||
+ {
|
||
+ enum bfd_endian desired_endian;
|
||
+
|
||
+ if (command_line.endian == ENDIAN_BIG)
|
||
+ desired_endian = BFD_ENDIAN_BIG;
|
||
+ else
|
||
+ desired_endian = BFD_ENDIAN_LITTLE;
|
||
+
|
||
+ /* See if the target has the wrong endianness. This should
|
||
+ not happen if the linker script has provided big and
|
||
+ little endian alternatives, but some scrips don't do
|
||
+ this. */
|
||
+ if (target->byteorder != desired_endian)
|
||
+ {
|
||
+ /* If it does, then see if the target provides
|
||
+ an alternative with the correct endianness. */
|
||
+ if (target->alternative_target != NULL
|
||
+ && (target->alternative_target->byteorder == desired_endian))
|
||
+ output_target = target->alternative_target->name;
|
||
+ else
|
||
+ {
|
||
+ /* Try to find a target as similar as possible to
|
||
+ the default target, but which has the desired
|
||
+ endian characteristic. */
|
||
+ bfd_iterate_over_targets (closest_target_match,
|
||
+ (void *) target);
|
||
+
|
||
+ /* Oh dear - we could not find any targets that
|
||
+ satisfy our requirements. */
|
||
+ if (winner == NULL)
|
||
+ einfo (_("%P: warning: could not find any targets"
|
||
+ " that match endianness requirement\n"));
|
||
+ else
|
||
+ output_target = winner->name;
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+
|
||
+ link_info.output_bfd = bfd_openw (name, output_target);
|
||
+
|
||
+ if (link_info.output_bfd == NULL)
|
||
+ {
|
||
+ if (bfd_get_error () == bfd_error_invalid_target)
|
||
+ einfo (_("%F%P: target %s not found\n"), output_target);
|
||
+
|
||
+ einfo (_("%F%P: cannot open output file %s: %E\n"), name);
|
||
+ }
|
||
+
|
||
+ delete_output_file_on_failure = true;
|
||
+
|
||
+ if (!bfd_set_format (link_info.output_bfd, bfd_object))
|
||
+ einfo (_("%F%P: %s: can not make object file: %E\n"), name);
|
||
+ if (!bfd_set_arch_mach (link_info.output_bfd,
|
||
+ ldfile_output_architecture,
|
||
+ ldfile_output_machine))
|
||
+ einfo (_("%F%P: %s: can not set architecture: %E\n"), name);
|
||
+
|
||
+ link_info.hash = bfd_link_hash_table_create (link_info.output_bfd);
|
||
+ if (link_info.hash == NULL)
|
||
+ einfo (_("%F%P: can not create hash table: %E\n"));
|
||
+
|
||
+ bfd_set_gp_size (link_info.output_bfd, g_switch_value);
|
||
+}
|
||
+
|
||
+static void
|
||
+ldlang_open_output (lang_statement_union_type *statement)
|
||
+{
|
||
+ switch (statement->header.type)
|
||
+ {
|
||
+ case lang_output_statement_enum:
|
||
+ ASSERT (link_info.output_bfd == NULL);
|
||
+ open_output (statement->output_statement.name);
|
||
+ ldemul_set_output_arch ();
|
||
+ if (config.magic_demand_paged
|
||
+ && !bfd_link_relocatable (&link_info))
|
||
+ link_info.output_bfd->flags |= D_PAGED;
|
||
+ else
|
||
+ link_info.output_bfd->flags &= ~D_PAGED;
|
||
+ if (config.text_read_only)
|
||
+ link_info.output_bfd->flags |= WP_TEXT;
|
||
+ else
|
||
+ link_info.output_bfd->flags &= ~WP_TEXT;
|
||
+ if (link_info.traditional_format)
|
||
+ link_info.output_bfd->flags |= BFD_TRADITIONAL_FORMAT;
|
||
+ else
|
||
+ link_info.output_bfd->flags &= ~BFD_TRADITIONAL_FORMAT;
|
||
+ if (config.no_section_header)
|
||
+ link_info.output_bfd->flags |= BFD_NO_SECTION_HEADER;
|
||
+ else
|
||
+ link_info.output_bfd->flags &= ~BFD_NO_SECTION_HEADER;
|
||
+ break;
|
||
+
|
||
+ case lang_target_statement_enum:
|
||
+ current_target = statement->target_statement.target;
|
||
+ break;
|
||
+ default:
|
||
+ break;
|
||
+ }
|
||
+}
|
||
+
|
||
+static void
|
||
+init_opb (asection *s)
|
||
+{
|
||
+ unsigned int x;
|
||
+
|
||
+ opb_shift = 0;
|
||
+ if (bfd_get_flavour (link_info.output_bfd) == bfd_target_elf_flavour
|
||
+ && s != NULL
|
||
+ && (s->flags & SEC_ELF_OCTETS) != 0)
|
||
+ return;
|
||
+
|
||
+ x = bfd_arch_mach_octets_per_byte (ldfile_output_architecture,
|
||
+ ldfile_output_machine);
|
||
+ if (x > 1)
|
||
+ while ((x & 1) == 0)
|
||
+ {
|
||
+ x >>= 1;
|
||
+ ++opb_shift;
|
||
+ }
|
||
+ ASSERT (x == 1);
|
||
+}
|
||
+
|
||
+/* Open all the input files. */
|
||
+
|
||
+enum open_bfd_mode
|
||
+ {
|
||
+ OPEN_BFD_NORMAL = 0,
|
||
+ OPEN_BFD_FORCE = 1,
|
||
+ OPEN_BFD_RESCAN = 2
|
||
+ };
|
||
+#if BFD_SUPPORTS_PLUGINS
|
||
+static lang_input_statement_type *plugin_insert = NULL;
|
||
+static struct bfd_link_hash_entry *plugin_undefs = NULL;
|
||
+#endif
|
||
+
|
||
+static void
|
||
+open_input_bfds (lang_statement_union_type *s, enum open_bfd_mode mode)
|
||
+{
|
||
+ for (; s != NULL; s = s->header.next)
|
||
+ {
|
||
+ switch (s->header.type)
|
||
+ {
|
||
+ case lang_constructors_statement_enum:
|
||
+ open_input_bfds (constructor_list.head, mode);
|
||
+ break;
|
||
+ case lang_output_section_statement_enum:
|
||
+ open_input_bfds (s->output_section_statement.children.head, mode);
|
||
+ break;
|
||
+ case lang_wild_statement_enum:
|
||
+ /* Maybe we should load the file's symbols. */
|
||
+ if ((mode & OPEN_BFD_RESCAN) == 0
|
||
+ && s->wild_statement.filename
|
||
+ && !wildcardp (s->wild_statement.filename)
|
||
+ && !archive_path (s->wild_statement.filename))
|
||
+ lookup_name (s->wild_statement.filename);
|
||
+ open_input_bfds (s->wild_statement.children.head, mode);
|
||
+ break;
|
||
+ case lang_group_statement_enum:
|
||
+ {
|
||
+ struct bfd_link_hash_entry *undefs;
|
||
+#if BFD_SUPPORTS_PLUGINS
|
||
+ lang_input_statement_type *plugin_insert_save;
|
||
+#endif
|
||
+
|
||
+ /* We must continually search the entries in the group
|
||
+ until no new symbols are added to the list of undefined
|
||
+ symbols. */
|
||
+
|
||
+ do
|
||
+ {
|
||
+#if BFD_SUPPORTS_PLUGINS
|
||
+ plugin_insert_save = plugin_insert;
|
||
+#endif
|
||
+ undefs = link_info.hash->undefs_tail;
|
||
+ open_input_bfds (s->group_statement.children.head,
|
||
+ mode | OPEN_BFD_FORCE);
|
||
+ }
|
||
+ while (undefs != link_info.hash->undefs_tail
|
||
+#if BFD_SUPPORTS_PLUGINS
|
||
+ /* Objects inserted by a plugin, which are loaded
|
||
+ before we hit this loop, may have added new
|
||
+ undefs. */
|
||
+ || (plugin_insert != plugin_insert_save && plugin_undefs)
|
||
+#endif
|
||
+ );
|
||
+ }
|
||
+ break;
|
||
+ case lang_target_statement_enum:
|
||
+ current_target = s->target_statement.target;
|
||
+ break;
|
||
+ case lang_input_statement_enum:
|
||
+ if (s->input_statement.flags.real)
|
||
+ {
|
||
+ lang_statement_union_type **os_tail;
|
||
+ lang_statement_list_type add;
|
||
+ bfd *abfd;
|
||
+
|
||
+ s->input_statement.target = current_target;
|
||
+
|
||
+ /* If we are being called from within a group, and this
|
||
+ is an archive which has already been searched, then
|
||
+ force it to be researched unless the whole archive
|
||
+ has been loaded already. Do the same for a rescan.
|
||
+ Likewise reload --as-needed shared libs. */
|
||
+ if (mode != OPEN_BFD_NORMAL
|
||
+#if BFD_SUPPORTS_PLUGINS
|
||
+ && ((mode & OPEN_BFD_RESCAN) == 0
|
||
+ || plugin_insert == NULL)
|
||
+#endif
|
||
+ && s->input_statement.flags.loaded
|
||
+ && (abfd = s->input_statement.the_bfd) != NULL
|
||
+ && ((bfd_get_format (abfd) == bfd_archive
|
||
+ && !s->input_statement.flags.whole_archive)
|
||
+ || (bfd_get_format (abfd) == bfd_object
|
||
+ && ((abfd->flags) & DYNAMIC) != 0
|
||
+ && s->input_statement.flags.add_DT_NEEDED_for_regular
|
||
+ && bfd_get_flavour (abfd) == bfd_target_elf_flavour
|
||
+ && (elf_dyn_lib_class (abfd) & DYN_AS_NEEDED) != 0)))
|
||
+ {
|
||
+ s->input_statement.flags.loaded = false;
|
||
+ s->input_statement.flags.reload = true;
|
||
+ }
|
||
+
|
||
+ os_tail = lang_os_list.tail;
|
||
+ lang_list_init (&add);
|
||
+
|
||
+ if (!load_symbols (&s->input_statement, &add))
|
||
+ config.make_executable = false;
|
||
+
|
||
+ if (add.head != NULL)
|
||
+ {
|
||
+ /* If this was a script with output sections then
|
||
+ tack any added statements on to the end of the
|
||
+ list. This avoids having to reorder the output
|
||
+ section statement list. Very likely the user
|
||
+ forgot -T, and whatever we do here will not meet
|
||
+ naive user expectations. */
|
||
+ if (os_tail != lang_os_list.tail)
|
||
+ {
|
||
+ einfo (_("%P: warning: %s contains output sections;"
|
||
+ " did you forget -T?\n"),
|
||
+ s->input_statement.filename);
|
||
+ *stat_ptr->tail = add.head;
|
||
+ stat_ptr->tail = add.tail;
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ *add.tail = s->header.next;
|
||
+ s->header.next = add.head;
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+#if BFD_SUPPORTS_PLUGINS
|
||
+ /* If we have found the point at which a plugin added new
|
||
+ files, clear plugin_insert to enable archive rescan. */
|
||
+ if (&s->input_statement == plugin_insert)
|
||
+ plugin_insert = NULL;
|
||
+#endif
|
||
+ break;
|
||
+ case lang_assignment_statement_enum:
|
||
+ if (s->assignment_statement.exp->type.node_class != etree_assert)
|
||
+ exp_fold_tree_no_dot (s->assignment_statement.exp);
|
||
+ break;
|
||
+ default:
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ /* Exit if any of the files were missing. */
|
||
+ if (input_flags.missing_file)
|
||
+ einfo ("%F");
|
||
+}
|
||
+
|
||
+#ifdef ENABLE_LIBCTF
|
||
+/* Emit CTF errors and warnings. fp can be NULL to report errors/warnings
|
||
+ that happened specifically at CTF open time. */
|
||
+static void
|
||
+lang_ctf_errs_warnings (ctf_dict_t *fp)
|
||
+{
|
||
+ ctf_next_t *i = NULL;
|
||
+ char *text;
|
||
+ int is_warning;
|
||
+ int err;
|
||
+
|
||
+ while ((text = ctf_errwarning_next (fp, &i, &is_warning, &err)) != NULL)
|
||
+ {
|
||
+ einfo (_("%s: %s\n"), is_warning ? _("CTF warning"): _("CTF error"),
|
||
+ text);
|
||
+ free (text);
|
||
+ }
|
||
+ if (err != ECTF_NEXT_END)
|
||
+ {
|
||
+ einfo (_("CTF error: cannot get CTF errors: `%s'\n"),
|
||
+ ctf_errmsg (err));
|
||
+ }
|
||
+
|
||
+ /* `err' returns errors from the error/warning iterator in particular.
|
||
+ These never assert. But if we have an fp, that could have recorded
|
||
+ an assertion failure: assert if it has done so. */
|
||
+ ASSERT (!fp || ctf_errno (fp) != ECTF_INTERNAL);
|
||
+}
|
||
+
|
||
+/* Open the CTF sections in the input files with libctf: if any were opened,
|
||
+ create a fake input file that we'll write the merged CTF data to later
|
||
+ on. */
|
||
+
|
||
+static void
|
||
+ldlang_open_ctf (void)
|
||
+{
|
||
+ int any_ctf = 0;
|
||
+ int err;
|
||
+
|
||
+ LANG_FOR_EACH_INPUT_STATEMENT (file)
|
||
+ {
|
||
+ asection *sect;
|
||
+
|
||
+ /* Incoming files from the compiler have a single ctf_dict_t in them
|
||
+ (which is presented to us by the libctf API in a ctf_archive_t
|
||
+ wrapper): files derived from a previous relocatable link have a CTF
|
||
+ archive containing possibly many CTF files. */
|
||
+
|
||
+ if ((file->the_ctf = ctf_bfdopen (file->the_bfd, &err)) == NULL)
|
||
+ {
|
||
+ if (err != ECTF_NOCTFDATA)
|
||
+ {
|
||
+ lang_ctf_errs_warnings (NULL);
|
||
+ einfo (_("%P: warning: CTF section in %pB not loaded; "
|
||
+ "its types will be discarded: %s\n"), file->the_bfd,
|
||
+ ctf_errmsg (err));
|
||
+ }
|
||
+ continue;
|
||
+ }
|
||
+
|
||
+ /* Prevent the contents of this section from being written, while
|
||
+ requiring the section itself to be duplicated in the output, but only
|
||
+ once. */
|
||
+ /* This section must exist if ctf_bfdopen() succeeded. */
|
||
+ sect = bfd_get_section_by_name (file->the_bfd, ".ctf");
|
||
+ sect->size = 0;
|
||
+ sect->flags |= SEC_NEVER_LOAD | SEC_HAS_CONTENTS | SEC_LINKER_CREATED;
|
||
+
|
||
+ if (any_ctf)
|
||
+ sect->flags |= SEC_EXCLUDE;
|
||
+ any_ctf = 1;
|
||
+ }
|
||
+
|
||
+ if (!any_ctf)
|
||
+ {
|
||
+ ctf_output = NULL;
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ if ((ctf_output = ctf_create (&err)) != NULL)
|
||
+ return;
|
||
+
|
||
+ einfo (_("%P: warning: CTF output not created: `%s'\n"),
|
||
+ ctf_errmsg (err));
|
||
+
|
||
+ LANG_FOR_EACH_INPUT_STATEMENT (errfile)
|
||
+ ctf_close (errfile->the_ctf);
|
||
+}
|
||
+
|
||
+/* Merge together CTF sections. After this, only the symtab-dependent
|
||
+ function and data object sections need adjustment. */
|
||
+
|
||
+static void
|
||
+lang_merge_ctf (void)
|
||
+{
|
||
+ asection *output_sect;
|
||
+ int flags = 0;
|
||
+
|
||
+ if (!ctf_output)
|
||
+ return;
|
||
+
|
||
+ output_sect = bfd_get_section_by_name (link_info.output_bfd, ".ctf");
|
||
+
|
||
+ /* If the section was discarded, don't waste time merging. */
|
||
+ if (output_sect == NULL)
|
||
+ {
|
||
+ ctf_dict_close (ctf_output);
|
||
+ ctf_output = NULL;
|
||
+
|
||
+ LANG_FOR_EACH_INPUT_STATEMENT (file)
|
||
+ {
|
||
+ ctf_close (file->the_ctf);
|
||
+ file->the_ctf = NULL;
|
||
+ }
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ LANG_FOR_EACH_INPUT_STATEMENT (file)
|
||
+ {
|
||
+ if (!file->the_ctf)
|
||
+ continue;
|
||
+
|
||
+ /* Takes ownership of file->the_ctf. */
|
||
+ if (ctf_link_add_ctf (ctf_output, file->the_ctf, file->filename) < 0)
|
||
+ {
|
||
+ einfo (_("%P: warning: CTF section in %pB cannot be linked: `%s'\n"),
|
||
+ file->the_bfd, ctf_errmsg (ctf_errno (ctf_output)));
|
||
+ ctf_close (file->the_ctf);
|
||
+ file->the_ctf = NULL;
|
||
+ continue;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (!config.ctf_share_duplicated)
|
||
+ flags = CTF_LINK_SHARE_UNCONFLICTED;
|
||
+ else
|
||
+ flags = CTF_LINK_SHARE_DUPLICATED;
|
||
+ if (!config.ctf_variables)
|
||
+ flags |= CTF_LINK_OMIT_VARIABLES_SECTION;
|
||
+ if (bfd_link_relocatable (&link_info))
|
||
+ flags |= CTF_LINK_NO_FILTER_REPORTED_SYMS;
|
||
+
|
||
+ if (ctf_link (ctf_output, flags) < 0)
|
||
+ {
|
||
+ lang_ctf_errs_warnings (ctf_output);
|
||
+ einfo (_("%P: warning: CTF linking failed; "
|
||
+ "output will have no CTF section: %s\n"),
|
||
+ ctf_errmsg (ctf_errno (ctf_output)));
|
||
+ if (output_sect)
|
||
+ {
|
||
+ output_sect->size = 0;
|
||
+ output_sect->flags |= SEC_EXCLUDE;
|
||
+ }
|
||
+ }
|
||
+ /* Output any lingering errors that didn't come from ctf_link. */
|
||
+ lang_ctf_errs_warnings (ctf_output);
|
||
+}
|
||
+
|
||
+/* Let the emulation acquire strings from the dynamic strtab to help it optimize
|
||
+ the CTF, if supported. */
|
||
+
|
||
+void
|
||
+ldlang_ctf_acquire_strings (struct elf_strtab_hash *dynstrtab)
|
||
+{
|
||
+ ldemul_acquire_strings_for_ctf (ctf_output, dynstrtab);
|
||
+}
|
||
+
|
||
+/* Inform the emulation about the addition of a new dynamic symbol, in BFD
|
||
+ internal format. */
|
||
+void ldlang_ctf_new_dynsym (int symidx, struct elf_internal_sym *sym)
|
||
+{
|
||
+ ldemul_new_dynsym_for_ctf (ctf_output, symidx, sym);
|
||
+}
|
||
+
|
||
+/* Write out the CTF section. Called early, if the emulation isn't going to
|
||
+ need to dedup against the strtab and symtab, then possibly called from the
|
||
+ target linker code if the dedup has happened. */
|
||
+static void
|
||
+lang_write_ctf (int late)
|
||
+{
|
||
+ size_t output_size;
|
||
+ asection *output_sect;
|
||
+
|
||
+ if (!ctf_output)
|
||
+ return;
|
||
+
|
||
+ if (late)
|
||
+ {
|
||
+ /* Emit CTF late if this emulation says it can do so. */
|
||
+ if (ldemul_emit_ctf_early ())
|
||
+ return;
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ if (!ldemul_emit_ctf_early ())
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ /* Inform the emulation that all the symbols that will be received have
|
||
+ been. */
|
||
+
|
||
+ ldemul_new_dynsym_for_ctf (ctf_output, 0, NULL);
|
||
+
|
||
+ /* Emit CTF. */
|
||
+
|
||
+ output_sect = bfd_get_section_by_name (link_info.output_bfd, ".ctf");
|
||
+ if (output_sect)
|
||
+ {
|
||
+ output_sect->contents = ctf_link_write (ctf_output, &output_size,
|
||
+ CTF_COMPRESSION_THRESHOLD);
|
||
+ output_sect->size = output_size;
|
||
+ output_sect->flags |= SEC_IN_MEMORY | SEC_KEEP;
|
||
+
|
||
+ lang_ctf_errs_warnings (ctf_output);
|
||
+ if (!output_sect->contents)
|
||
+ {
|
||
+ einfo (_("%P: warning: CTF section emission failed; "
|
||
+ "output will have no CTF section: %s\n"),
|
||
+ ctf_errmsg (ctf_errno (ctf_output)));
|
||
+ output_sect->size = 0;
|
||
+ output_sect->flags |= SEC_EXCLUDE;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ /* This also closes every CTF input file used in the link. */
|
||
+ ctf_dict_close (ctf_output);
|
||
+ ctf_output = NULL;
|
||
+
|
||
+ LANG_FOR_EACH_INPUT_STATEMENT (file)
|
||
+ file->the_ctf = NULL;
|
||
+}
|
||
+
|
||
+/* Write out the CTF section late, if the emulation needs that. */
|
||
+
|
||
+void
|
||
+ldlang_write_ctf_late (void)
|
||
+{
|
||
+ /* Trigger a "late call", if the emulation needs one. */
|
||
+
|
||
+ lang_write_ctf (1);
|
||
+}
|
||
+#else
|
||
+static void
|
||
+ldlang_open_ctf (void)
|
||
+{
|
||
+ LANG_FOR_EACH_INPUT_STATEMENT (file)
|
||
+ {
|
||
+ asection *sect;
|
||
+
|
||
+ /* If built without CTF, warn and delete all CTF sections from the output.
|
||
+ (The alternative would be to simply concatenate them, which does not
|
||
+ yield a valid CTF section.) */
|
||
+
|
||
+ if ((sect = bfd_get_section_by_name (file->the_bfd, ".ctf")) != NULL)
|
||
+ {
|
||
+ einfo (_("%P: warning: CTF section in %pB not linkable: "
|
||
+ "%P was built without support for CTF\n"), file->the_bfd);
|
||
+ sect->size = 0;
|
||
+ sect->flags |= SEC_EXCLUDE;
|
||
+ }
|
||
+ }
|
||
+}
|
||
+
|
||
+static void lang_merge_ctf (void) {}
|
||
+void
|
||
+ldlang_ctf_acquire_strings (struct elf_strtab_hash *dynstrtab
|
||
+ ATTRIBUTE_UNUSED) {}
|
||
+void
|
||
+ldlang_ctf_new_dynsym (int symidx ATTRIBUTE_UNUSED,
|
||
+ struct elf_internal_sym *sym ATTRIBUTE_UNUSED) {}
|
||
+static void lang_write_ctf (int late ATTRIBUTE_UNUSED) {}
|
||
+void ldlang_write_ctf_late (void) {}
|
||
+#endif
|
||
+
|
||
+/* Add the supplied name to the symbol table as an undefined reference.
|
||
+ This is a two step process as the symbol table doesn't even exist at
|
||
+ the time the ld command line is processed. First we put the name
|
||
+ on a list, then, once the output file has been opened, transfer the
|
||
+ name to the symbol table. */
|
||
+
|
||
+typedef struct bfd_sym_chain ldlang_undef_chain_list_type;
|
||
+
|
||
+#define ldlang_undef_chain_list_head entry_symbol.next
|
||
+
|
||
+void
|
||
+ldlang_add_undef (const char *const name, bool cmdline ATTRIBUTE_UNUSED)
|
||
+{
|
||
+ ldlang_undef_chain_list_type *new_undef;
|
||
+
|
||
+ new_undef = stat_alloc (sizeof (*new_undef));
|
||
+ new_undef->next = ldlang_undef_chain_list_head;
|
||
+ ldlang_undef_chain_list_head = new_undef;
|
||
+
|
||
+ new_undef->name = xstrdup (name);
|
||
+
|
||
+ if (link_info.output_bfd != NULL)
|
||
+ insert_undefined (new_undef->name);
|
||
+}
|
||
+
|
||
+/* Insert NAME as undefined in the symbol table. */
|
||
+
|
||
+static void
|
||
+insert_undefined (const char *name)
|
||
+{
|
||
+ struct bfd_link_hash_entry *h;
|
||
+
|
||
+ h = bfd_link_hash_lookup (link_info.hash, name, true, false, true);
|
||
+ if (h == NULL)
|
||
+ einfo (_("%F%P: bfd_link_hash_lookup failed: %E\n"));
|
||
+ if (h->type == bfd_link_hash_new)
|
||
+ {
|
||
+ h->type = bfd_link_hash_undefined;
|
||
+ h->u.undef.abfd = NULL;
|
||
+ h->non_ir_ref_regular = true;
|
||
+ bfd_link_add_undef (link_info.hash, h);
|
||
+ }
|
||
+}
|
||
+
|
||
+/* Run through the list of undefineds created above and place them
|
||
+ into the linker hash table as undefined symbols belonging to the
|
||
+ script file. */
|
||
+
|
||
+static void
|
||
+lang_place_undefineds (void)
|
||
+{
|
||
+ ldlang_undef_chain_list_type *ptr;
|
||
+
|
||
+ for (ptr = ldlang_undef_chain_list_head; ptr != NULL; ptr = ptr->next)
|
||
+ insert_undefined (ptr->name);
|
||
+}
|
||
+
|
||
+/* Mark -u symbols against garbage collection. */
|
||
+
|
||
+static void
|
||
+lang_mark_undefineds (void)
|
||
+{
|
||
+ ldlang_undef_chain_list_type *ptr;
|
||
+
|
||
+ if (is_elf_hash_table (link_info.hash))
|
||
+ for (ptr = ldlang_undef_chain_list_head; ptr != NULL; ptr = ptr->next)
|
||
+ {
|
||
+ struct elf_link_hash_entry *h = (struct elf_link_hash_entry *)
|
||
+ bfd_link_hash_lookup (link_info.hash, ptr->name, false, false, true);
|
||
+ if (h != NULL)
|
||
+ h->mark = 1;
|
||
+ }
|
||
+}
|
||
+
|
||
+/* Structure used to build the list of symbols that the user has required
|
||
+ be defined. */
|
||
+
|
||
+struct require_defined_symbol
|
||
+{
|
||
+ const char *name;
|
||
+ struct require_defined_symbol *next;
|
||
+};
|
||
+
|
||
+/* The list of symbols that the user has required be defined. */
|
||
+
|
||
+static struct require_defined_symbol *require_defined_symbol_list;
|
||
+
|
||
+/* Add a new symbol NAME to the list of symbols that are required to be
|
||
+ defined. */
|
||
+
|
||
+void
|
||
+ldlang_add_require_defined (const char *const name)
|
||
+{
|
||
+ struct require_defined_symbol *ptr;
|
||
+
|
||
+ ldlang_add_undef (name, true);
|
||
+ ptr = stat_alloc (sizeof (*ptr));
|
||
+ ptr->next = require_defined_symbol_list;
|
||
+ ptr->name = strdup (name);
|
||
+ require_defined_symbol_list = ptr;
|
||
+}
|
||
+
|
||
+/* Check that all symbols the user required to be defined, are defined,
|
||
+ raise an error if we find a symbol that is not defined. */
|
||
+
|
||
+static void
|
||
+ldlang_check_require_defined_symbols (void)
|
||
+{
|
||
+ struct require_defined_symbol *ptr;
|
||
+
|
||
+ for (ptr = require_defined_symbol_list; ptr != NULL; ptr = ptr->next)
|
||
+ {
|
||
+ struct bfd_link_hash_entry *h;
|
||
+
|
||
+ h = bfd_link_hash_lookup (link_info.hash, ptr->name,
|
||
+ false, false, true);
|
||
+ if (h == NULL
|
||
+ || (h->type != bfd_link_hash_defined
|
||
+ && h->type != bfd_link_hash_defweak))
|
||
+ einfo(_("%X%P: required symbol `%s' not defined\n"), ptr->name);
|
||
+ }
|
||
+}
|
||
+
|
||
+/* Check for all readonly or some readwrite sections. */
|
||
+
|
||
+static void
|
||
+check_input_sections
|
||
+ (lang_statement_union_type *s,
|
||
+ lang_output_section_statement_type *output_section_statement)
|
||
+{
|
||
+ for (; s != NULL; s = s->header.next)
|
||
+ {
|
||
+ switch (s->header.type)
|
||
+ {
|
||
+ case lang_wild_statement_enum:
|
||
+ walk_wild (&s->wild_statement, check_section_callback,
|
||
+ output_section_statement);
|
||
+ if (!output_section_statement->all_input_readonly)
|
||
+ return;
|
||
+ break;
|
||
+ case lang_constructors_statement_enum:
|
||
+ check_input_sections (constructor_list.head,
|
||
+ output_section_statement);
|
||
+ if (!output_section_statement->all_input_readonly)
|
||
+ return;
|
||
+ break;
|
||
+ case lang_group_statement_enum:
|
||
+ check_input_sections (s->group_statement.children.head,
|
||
+ output_section_statement);
|
||
+ if (!output_section_statement->all_input_readonly)
|
||
+ return;
|
||
+ break;
|
||
+ default:
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+}
|
||
+
|
||
+/* Update wildcard statements if needed. */
|
||
+
|
||
+static void
|
||
+update_wild_statements (lang_statement_union_type *s)
|
||
+{
|
||
+ struct wildcard_list *sec;
|
||
+
|
||
+ switch (sort_section)
|
||
+ {
|
||
+ default:
|
||
+ FAIL ();
|
||
+
|
||
+ case none:
|
||
+ break;
|
||
+
|
||
+ case by_name:
|
||
+ case by_alignment:
|
||
+ for (; s != NULL; s = s->header.next)
|
||
+ {
|
||
+ switch (s->header.type)
|
||
+ {
|
||
+ default:
|
||
+ break;
|
||
+
|
||
+ case lang_wild_statement_enum:
|
||
+ for (sec = s->wild_statement.section_list; sec != NULL;
|
||
+ sec = sec->next)
|
||
+ /* Don't sort .init/.fini sections. */
|
||
+ if (strcmp (sec->spec.name, ".init") != 0
|
||
+ && strcmp (sec->spec.name, ".fini") != 0)
|
||
+ {
|
||
+ switch (sec->spec.sorted)
|
||
+ {
|
||
+ case none:
|
||
+ sec->spec.sorted = sort_section;
|
||
+ break;
|
||
+ case by_name:
|
||
+ if (sort_section == by_alignment)
|
||
+ sec->spec.sorted = by_name_alignment;
|
||
+ break;
|
||
+ case by_alignment:
|
||
+ if (sort_section == by_name)
|
||
+ sec->spec.sorted = by_alignment_name;
|
||
+ break;
|
||
+ default:
|
||
+ break;
|
||
+ }
|
||
+ s->wild_statement.any_specs_sorted = true;
|
||
+ }
|
||
+ break;
|
||
+
|
||
+ case lang_constructors_statement_enum:
|
||
+ update_wild_statements (constructor_list.head);
|
||
+ break;
|
||
+
|
||
+ case lang_output_section_statement_enum:
|
||
+ update_wild_statements
|
||
+ (s->output_section_statement.children.head);
|
||
+ break;
|
||
+
|
||
+ case lang_group_statement_enum:
|
||
+ update_wild_statements (s->group_statement.children.head);
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+ break;
|
||
+ }
|
||
+}
|
||
+
|
||
+/* Open input files and attach to output sections. */
|
||
+
|
||
+static void
|
||
+map_input_to_output_sections
|
||
+ (lang_statement_union_type *s, const char *target,
|
||
+ lang_output_section_statement_type *os)
|
||
+{
|
||
+ for (; s != NULL; s = s->header.next)
|
||
+ {
|
||
+ lang_output_section_statement_type *tos;
|
||
+ flagword flags;
|
||
+ unsigned int type = 0;
|
||
+
|
||
+ switch (s->header.type)
|
||
+ {
|
||
+ case lang_wild_statement_enum:
|
||
+ wild (&s->wild_statement, target, os);
|
||
+ break;
|
||
+ case lang_constructors_statement_enum:
|
||
+ map_input_to_output_sections (constructor_list.head,
|
||
+ target,
|
||
+ os);
|
||
+ break;
|
||
+ case lang_output_section_statement_enum:
|
||
+ tos = &s->output_section_statement;
|
||
+ if (tos->constraint == ONLY_IF_RW
|
||
+ || tos->constraint == ONLY_IF_RO)
|
||
+ {
|
||
+ tos->all_input_readonly = true;
|
||
+ check_input_sections (tos->children.head, tos);
|
||
+ if (tos->all_input_readonly != (tos->constraint == ONLY_IF_RO))
|
||
+ tos->constraint = -1;
|
||
+ }
|
||
+ if (tos->constraint >= 0)
|
||
+ map_input_to_output_sections (tos->children.head,
|
||
+ target,
|
||
+ tos);
|
||
+ break;
|
||
+ case lang_output_statement_enum:
|
||
+ break;
|
||
+ case lang_target_statement_enum:
|
||
+ target = s->target_statement.target;
|
||
+ break;
|
||
+ case lang_group_statement_enum:
|
||
+ map_input_to_output_sections (s->group_statement.children.head,
|
||
+ target,
|
||
+ os);
|
||
+ break;
|
||
+ case lang_data_statement_enum:
|
||
+ /* Make sure that any sections mentioned in the expression
|
||
+ are initialized. */
|
||
+ exp_init_os (s->data_statement.exp);
|
||
+ /* The output section gets CONTENTS, ALLOC and LOAD, but
|
||
+ these may be overridden by the script. */
|
||
+ flags = SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD;
|
||
+ switch (os->sectype)
|
||
+ {
|
||
+ case normal_section:
|
||
+ case overlay_section:
|
||
+ case first_overlay_section:
|
||
+ break;
|
||
+ case noalloc_section:
|
||
+ flags = SEC_HAS_CONTENTS;
|
||
+ break;
|
||
+ case readonly_section:
|
||
+ flags |= SEC_READONLY;
|
||
+ break;
|
||
+ case typed_readonly_section:
|
||
+ flags |= SEC_READONLY;
|
||
+ /* Fall through. */
|
||
+ case type_section:
|
||
+ if (os->sectype_value->type.node_class == etree_name
|
||
+ && os->sectype_value->type.node_code == NAME)
|
||
+ {
|
||
+ const char *name = os->sectype_value->name.name;
|
||
+ if (strcmp (name, "SHT_PROGBITS") == 0)
|
||
+ type = SHT_PROGBITS;
|
||
+ else if (strcmp (name, "SHT_STRTAB") == 0)
|
||
+ type = SHT_STRTAB;
|
||
+ else if (strcmp (name, "SHT_NOTE") == 0)
|
||
+ type = SHT_NOTE;
|
||
+ else if (strcmp (name, "SHT_NOBITS") == 0)
|
||
+ type = SHT_NOBITS;
|
||
+ else if (strcmp (name, "SHT_INIT_ARRAY") == 0)
|
||
+ type = SHT_INIT_ARRAY;
|
||
+ else if (strcmp (name, "SHT_FINI_ARRAY") == 0)
|
||
+ type = SHT_FINI_ARRAY;
|
||
+ else if (strcmp (name, "SHT_PREINIT_ARRAY") == 0)
|
||
+ type = SHT_PREINIT_ARRAY;
|
||
+ else
|
||
+ einfo (_ ("%F%P: invalid type for output section `%s'\n"),
|
||
+ os->name);
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ exp_fold_tree_no_dot (os->sectype_value);
|
||
+ if (expld.result.valid_p)
|
||
+ type = expld.result.value;
|
||
+ else
|
||
+ einfo (_ ("%F%P: invalid type for output section `%s'\n"),
|
||
+ os->name);
|
||
+ }
|
||
+ break;
|
||
+ case noload_section:
|
||
+ if (bfd_get_flavour (link_info.output_bfd)
|
||
+ == bfd_target_elf_flavour)
|
||
+ flags = SEC_NEVER_LOAD | SEC_ALLOC;
|
||
+ else
|
||
+ flags = SEC_NEVER_LOAD | SEC_HAS_CONTENTS;
|
||
+ break;
|
||
+ }
|
||
+ if (os->bfd_section == NULL)
|
||
+ init_os (os, flags | SEC_READONLY);
|
||
+ else
|
||
+ os->bfd_section->flags |= flags;
|
||
+ os->bfd_section->type = type;
|
||
+ break;
|
||
+ case lang_input_section_enum:
|
||
+ break;
|
||
+ case lang_fill_statement_enum:
|
||
+ case lang_object_symbols_statement_enum:
|
||
+ case lang_reloc_statement_enum:
|
||
+ case lang_padding_statement_enum:
|
||
+ case lang_input_statement_enum:
|
||
+ if (os != NULL && os->bfd_section == NULL)
|
||
+ init_os (os, 0);
|
||
+ break;
|
||
+ case lang_assignment_statement_enum:
|
||
+ if (os != NULL && os->bfd_section == NULL)
|
||
+ init_os (os, 0);
|
||
+
|
||
+ /* Make sure that any sections mentioned in the assignment
|
||
+ are initialized. */
|
||
+ exp_init_os (s->assignment_statement.exp);
|
||
+ break;
|
||
+ case lang_address_statement_enum:
|
||
+ /* Mark the specified section with the supplied address.
|
||
+ If this section was actually a segment marker, then the
|
||
+ directive is ignored if the linker script explicitly
|
||
+ processed the segment marker. Originally, the linker
|
||
+ treated segment directives (like -Ttext on the
|
||
+ command-line) as section directives. We honor the
|
||
+ section directive semantics for backwards compatibility;
|
||
+ linker scripts that do not specifically check for
|
||
+ SEGMENT_START automatically get the old semantics. */
|
||
+ if (!s->address_statement.segment
|
||
+ || !s->address_statement.segment->used)
|
||
+ {
|
||
+ const char *name = s->address_statement.section_name;
|
||
+
|
||
+ /* Create the output section statement here so that
|
||
+ orphans with a set address will be placed after other
|
||
+ script sections. If we let the orphan placement code
|
||
+ place them in amongst other sections then the address
|
||
+ will affect following script sections, which is
|
||
+ likely to surprise naive users. */
|
||
+ tos = lang_output_section_statement_lookup (name, 0, 1);
|
||
+ tos->addr_tree = s->address_statement.address;
|
||
+ if (tos->bfd_section == NULL)
|
||
+ init_os (tos, 0);
|
||
+ }
|
||
+ break;
|
||
+ case lang_insert_statement_enum:
|
||
+ break;
|
||
+ case lang_input_matcher_enum:
|
||
+ FAIL ();
|
||
+ }
|
||
+ }
|
||
+}
|
||
+
|
||
+/* An insert statement snips out all the linker statements from the
|
||
+ start of the list and places them after the output section
|
||
+ statement specified by the insert. This operation is complicated
|
||
+ by the fact that we keep a doubly linked list of output section
|
||
+ statements as well as the singly linked list of all statements.
|
||
+ FIXME someday: Twiddling with the list not only moves statements
|
||
+ from the user's script but also input and group statements that are
|
||
+ built from command line object files and --start-group. We only
|
||
+ get away with this because the list pointers used by file_chain
|
||
+ and input_file_chain are not reordered, and processing via
|
||
+ statement_list after this point mostly ignores input statements.
|
||
+ One exception is the map file, where LOAD and START GROUP/END GROUP
|
||
+ can end up looking odd. */
|
||
+
|
||
+static void
|
||
+process_insert_statements (lang_statement_union_type **start)
|
||
+{
|
||
+ lang_statement_union_type **s;
|
||
+ lang_output_section_statement_type *first_os = NULL;
|
||
+ lang_output_section_statement_type *last_os = NULL;
|
||
+ lang_output_section_statement_type *os;
|
||
+
|
||
+ s = start;
|
||
+ while (*s != NULL)
|
||
+ {
|
||
+ if ((*s)->header.type == lang_output_section_statement_enum)
|
||
+ {
|
||
+ /* Keep pointers to the first and last output section
|
||
+ statement in the sequence we may be about to move. */
|
||
+ os = &(*s)->output_section_statement;
|
||
+
|
||
+ ASSERT (last_os == NULL || last_os->next == os);
|
||
+ last_os = os;
|
||
+
|
||
+ /* Set constraint negative so that lang_output_section_find
|
||
+ won't match this output section statement. At this
|
||
+ stage in linking constraint has values in the range
|
||
+ [-1, ONLY_IN_RW]. */
|
||
+ last_os->constraint = -2 - last_os->constraint;
|
||
+ if (first_os == NULL)
|
||
+ first_os = last_os;
|
||
+ }
|
||
+ else if ((*s)->header.type == lang_group_statement_enum)
|
||
+ {
|
||
+ /* A user might put -T between --start-group and
|
||
+ --end-group. One way this odd construct might arise is
|
||
+ from a wrapper around ld to change library search
|
||
+ behaviour. For example:
|
||
+ #! /bin/sh
|
||
+ exec real_ld --start-group "$@" --end-group
|
||
+ This isn't completely unreasonable so go looking inside a
|
||
+ group statement for insert statements. */
|
||
+ process_insert_statements (&(*s)->group_statement.children.head);
|
||
+ }
|
||
+ else if ((*s)->header.type == lang_insert_statement_enum)
|
||
+ {
|
||
+ lang_insert_statement_type *i = &(*s)->insert_statement;
|
||
+ lang_output_section_statement_type *where;
|
||
+ lang_statement_union_type **ptr;
|
||
+ lang_statement_union_type *first;
|
||
+
|
||
+ if (link_info.non_contiguous_regions)
|
||
+ {
|
||
+ einfo (_("warning: INSERT statement in linker script is "
|
||
+ "incompatible with --enable-non-contiguous-regions.\n"));
|
||
+ }
|
||
+
|
||
+ where = lang_output_section_find (i->where);
|
||
+ if (where != NULL && i->is_before)
|
||
+ {
|
||
+ do
|
||
+ where = where->prev;
|
||
+ while (where != NULL && where->constraint < 0);
|
||
+ }
|
||
+ if (where == NULL)
|
||
+ {
|
||
+ einfo (_("%F%P: %s not found for insert\n"), i->where);
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ /* Deal with reordering the output section statement list. */
|
||
+ if (last_os != NULL)
|
||
+ {
|
||
+ asection *first_sec, *last_sec;
|
||
+ struct lang_output_section_statement_struct **next;
|
||
+
|
||
+ /* Snip out the output sections we are moving. */
|
||
+ first_os->prev->next = last_os->next;
|
||
+ if (last_os->next == NULL)
|
||
+ {
|
||
+ next = &first_os->prev->next;
|
||
+ lang_os_list.tail = (lang_statement_union_type **) next;
|
||
+ }
|
||
+ else
|
||
+ last_os->next->prev = first_os->prev;
|
||
+ /* Add them in at the new position. */
|
||
+ last_os->next = where->next;
|
||
+ if (where->next == NULL)
|
||
+ {
|
||
+ next = &last_os->next;
|
||
+ lang_os_list.tail = (lang_statement_union_type **) next;
|
||
+ }
|
||
+ else
|
||
+ where->next->prev = last_os;
|
||
+ first_os->prev = where;
|
||
+ where->next = first_os;
|
||
+
|
||
+ /* Move the bfd sections in the same way. */
|
||
+ first_sec = NULL;
|
||
+ last_sec = NULL;
|
||
+ for (os = first_os; os != NULL; os = os->next)
|
||
+ {
|
||
+ os->constraint = -2 - os->constraint;
|
||
+ if (os->bfd_section != NULL
|
||
+ && os->bfd_section->owner != NULL)
|
||
+ {
|
||
+ last_sec = os->bfd_section;
|
||
+ if (first_sec == NULL)
|
||
+ first_sec = last_sec;
|
||
+ }
|
||
+ if (os == last_os)
|
||
+ break;
|
||
+ }
|
||
+ if (last_sec != NULL)
|
||
+ {
|
||
+ asection *sec = where->bfd_section;
|
||
+ if (sec == NULL)
|
||
+ sec = output_prev_sec_find (where);
|
||
+
|
||
+ /* The place we want to insert must come after the
|
||
+ sections we are moving. So if we find no
|
||
+ section or if the section is the same as our
|
||
+ last section, then no move is needed. */
|
||
+ if (sec != NULL && sec != last_sec)
|
||
+ {
|
||
+ /* Trim them off. */
|
||
+ if (first_sec->prev != NULL)
|
||
+ first_sec->prev->next = last_sec->next;
|
||
+ else
|
||
+ link_info.output_bfd->sections = last_sec->next;
|
||
+ if (last_sec->next != NULL)
|
||
+ last_sec->next->prev = first_sec->prev;
|
||
+ else
|
||
+ link_info.output_bfd->section_last = first_sec->prev;
|
||
+ /* Add back. */
|
||
+ if (sec->owner == NULL)
|
||
+ /* SEC is the absolute section, from the
|
||
+ first dummy output section statement. Add
|
||
+ back the sections we trimmed off to the
|
||
+ start of the bfd sections. */
|
||
+ sec = NULL;
|
||
+ if (sec != NULL)
|
||
+ last_sec->next = sec->next;
|
||
+ else
|
||
+ last_sec->next = link_info.output_bfd->sections;
|
||
+ if (last_sec->next != NULL)
|
||
+ last_sec->next->prev = last_sec;
|
||
+ else
|
||
+ link_info.output_bfd->section_last = last_sec;
|
||
+ first_sec->prev = sec;
|
||
+ if (first_sec->prev != NULL)
|
||
+ first_sec->prev->next = first_sec;
|
||
+ else
|
||
+ link_info.output_bfd->sections = first_sec;
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+
|
||
+ lang_statement_union_type *after = (void *) where;
|
||
+ if (where == &lang_os_list.head->output_section_statement
|
||
+ && where->next == first_os)
|
||
+ {
|
||
+ /* PR30155. Handle a corner case where the statement
|
||
+ list is something like the following:
|
||
+ . LOAD t.o
|
||
+ . .data 0x0000000000000000 0x0
|
||
+ . [0x0000000000000000] b = .
|
||
+ . *(.data)
|
||
+ . .data 0x0000000000000000 0x0 t.o
|
||
+ . 0x0000000000000000 0x4 LONG 0x0
|
||
+ . INSERT BEFORE .text.start
|
||
+ . [0x0000000000000004] a = .
|
||
+ . .text.start 0x0000000000000000 0x0
|
||
+ . [0x0000000000000000] c = .
|
||
+ . OUTPUT(a.out elf64-x86-64)
|
||
+ Here we do not want to allow insert_os_after to
|
||
+ choose a point inside the list we are moving.
|
||
+ That would lose the list. Instead, let
|
||
+ insert_os_after work from the INSERT, which in this
|
||
+ particular example will result in inserting after
|
||
+ the assignment "a = .". */
|
||
+ after = *s;
|
||
+ }
|
||
+ ptr = insert_os_after (after);
|
||
+ /* Snip everything from the start of the list, up to and
|
||
+ including the insert statement we are currently processing. */
|
||
+ first = *start;
|
||
+ *start = (*s)->header.next;
|
||
+ /* Add them back where they belong, minus the insert. */
|
||
+ *s = *ptr;
|
||
+ if (*s == NULL)
|
||
+ statement_list.tail = s;
|
||
+ *ptr = first;
|
||
+ s = start;
|
||
+ first_os = NULL;
|
||
+ last_os = NULL;
|
||
+ continue;
|
||
+ }
|
||
+ s = &(*s)->header.next;
|
||
+ }
|
||
+
|
||
+ /* Undo constraint twiddling. */
|
||
+ for (os = first_os; os != NULL; os = os->next)
|
||
+ {
|
||
+ os->constraint = -2 - os->constraint;
|
||
+ if (os == last_os)
|
||
+ break;
|
||
+ }
|
||
+}
|
||
+
|
||
+/* An output section might have been removed after its statement was
|
||
+ added. For example, ldemul_before_allocation can remove dynamic
|
||
+ sections if they turn out to be not needed. Clean them up here. */
|
||
+
|
||
+void
|
||
+strip_excluded_output_sections (void)
|
||
+{
|
||
+ lang_output_section_statement_type *os;
|
||
+
|
||
+ /* Run lang_size_sections (if not already done). */
|
||
+ if (expld.phase != lang_mark_phase_enum)
|
||
+ {
|
||
+ expld.phase = lang_mark_phase_enum;
|
||
+ expld.dataseg.phase = exp_seg_none;
|
||
+ one_lang_size_sections_pass (NULL, false);
|
||
+ lang_reset_memory_regions ();
|
||
+ }
|
||
+
|
||
+ for (os = (void *) lang_os_list.head;
|
||
+ os != NULL;
|
||
+ os = os->next)
|
||
+ {
|
||
+ asection *output_section;
|
||
+ bool exclude;
|
||
+
|
||
+ if (os->constraint < 0)
|
||
+ continue;
|
||
+
|
||
+ output_section = os->bfd_section;
|
||
+ if (output_section == NULL)
|
||
+ continue;
|
||
+
|
||
+ exclude = (output_section->rawsize == 0
|
||
+ && (output_section->flags & SEC_KEEP) == 0
|
||
+ && !bfd_section_removed_from_list (link_info.output_bfd,
|
||
+ output_section));
|
||
+
|
||
+ /* Some sections have not yet been sized, notably .gnu.version,
|
||
+ .dynsym, .dynstr and .hash. These all have SEC_LINKER_CREATED
|
||
+ input sections, so don't drop output sections that have such
|
||
+ input sections unless they are also marked SEC_EXCLUDE. */
|
||
+ if (exclude && output_section->map_head.s != NULL)
|
||
+ {
|
||
+ asection *s;
|
||
+
|
||
+ for (s = output_section->map_head.s; s != NULL; s = s->map_head.s)
|
||
+ if ((s->flags & SEC_EXCLUDE) == 0
|
||
+ && ((s->flags & SEC_LINKER_CREATED) != 0
|
||
+ || link_info.emitrelocations))
|
||
+ {
|
||
+ exclude = false;
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (exclude)
|
||
+ {
|
||
+ /* We don't set bfd_section to NULL since bfd_section of the
|
||
+ removed output section statement may still be used. */
|
||
+ if (!os->update_dot)
|
||
+ os->ignored = true;
|
||
+ output_section->flags |= SEC_EXCLUDE;
|
||
+ bfd_section_list_remove (link_info.output_bfd, output_section);
|
||
+ link_info.output_bfd->section_count--;
|
||
+ }
|
||
+ }
|
||
+}
|
||
+
|
||
+/* Called from ldwrite to clear out asection.map_head and
|
||
+ asection.map_tail for use as link_orders in ldwrite. */
|
||
+
|
||
+void
|
||
+lang_clear_os_map (void)
|
||
+{
|
||
+ lang_output_section_statement_type *os;
|
||
+
|
||
+ if (map_head_is_link_order)
|
||
+ return;
|
||
+
|
||
+ for (os = (void *) lang_os_list.head;
|
||
+ os != NULL;
|
||
+ os = os->next)
|
||
+ {
|
||
+ asection *output_section;
|
||
+
|
||
+ if (os->constraint < 0)
|
||
+ continue;
|
||
+
|
||
+ output_section = os->bfd_section;
|
||
+ if (output_section == NULL)
|
||
+ continue;
|
||
+
|
||
+ /* TODO: Don't just junk map_head.s, turn them into link_orders. */
|
||
+ output_section->map_head.link_order = NULL;
|
||
+ output_section->map_tail.link_order = NULL;
|
||
+ }
|
||
+
|
||
+ /* Stop future calls to lang_add_section from messing with map_head
|
||
+ and map_tail link_order fields. */
|
||
+ map_head_is_link_order = true;
|
||
+}
|
||
+
|
||
+static void
|
||
+print_output_section_statement
|
||
+ (lang_output_section_statement_type *output_section_statement)
|
||
+{
|
||
+ asection *section = output_section_statement->bfd_section;
|
||
+ int len;
|
||
+
|
||
+ if (output_section_statement != abs_output_section)
|
||
+ {
|
||
+ minfo ("\n%s", output_section_statement->name);
|
||
+
|
||
+ if (section != NULL)
|
||
+ {
|
||
+ print_dot = section->vma;
|
||
+
|
||
+ len = strlen (output_section_statement->name);
|
||
+ if (len >= SECTION_NAME_MAP_LENGTH - 1)
|
||
+ {
|
||
+ print_nl ();
|
||
+ len = 0;
|
||
+ }
|
||
+ print_spaces (SECTION_NAME_MAP_LENGTH - len);
|
||
+
|
||
+ minfo ("0x%V %W", section->vma, TO_ADDR (section->size));
|
||
+
|
||
+ if (section->vma != section->lma)
|
||
+ minfo (_(" load address 0x%V"), section->lma);
|
||
+
|
||
+ if (output_section_statement->update_dot_tree != NULL)
|
||
+ exp_fold_tree (output_section_statement->update_dot_tree,
|
||
+ bfd_abs_section_ptr, &print_dot);
|
||
+ }
|
||
+
|
||
+ print_nl ();
|
||
+ }
|
||
+
|
||
+ print_statement_list (output_section_statement->children.head,
|
||
+ output_section_statement);
|
||
+}
|
||
+
|
||
+static void
|
||
+print_assignment (lang_assignment_statement_type *assignment,
|
||
+ lang_output_section_statement_type *output_section)
|
||
+{
|
||
+ bool is_dot;
|
||
+ etree_type *tree;
|
||
+ asection *osec;
|
||
+
|
||
+ print_spaces (SECTION_NAME_MAP_LENGTH);
|
||
+
|
||
+ if (assignment->exp->type.node_class == etree_assert)
|
||
+ {
|
||
+ is_dot = false;
|
||
+ tree = assignment->exp->assert_s.child;
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ const char *dst = assignment->exp->assign.dst;
|
||
+
|
||
+ is_dot = (dst[0] == '.' && dst[1] == 0);
|
||
+ tree = assignment->exp;
|
||
+ }
|
||
+
|
||
+ osec = output_section->bfd_section;
|
||
+ if (osec == NULL)
|
||
+ osec = bfd_abs_section_ptr;
|
||
+
|
||
+ if (assignment->exp->type.node_class != etree_provide)
|
||
+ exp_fold_tree (tree, osec, &print_dot);
|
||
+ else
|
||
+ expld.result.valid_p = false;
|
||
+
|
||
+ char buf[32];
|
||
+ const char *str = buf;
|
||
+ if (expld.result.valid_p)
|
||
+ {
|
||
+ bfd_vma value;
|
||
+
|
||
+ if (assignment->exp->type.node_class == etree_assert
|
||
+ || is_dot
|
||
+ || expld.assign_name != NULL)
|
||
+ {
|
||
+ value = expld.result.value;
|
||
+
|
||
+ if (expld.result.section != NULL)
|
||
+ value += expld.result.section->vma;
|
||
+
|
||
+ buf[0] = '0';
|
||
+ buf[1] = 'x';
|
||
+ bfd_sprintf_vma (link_info.output_bfd, buf + 2, value);
|
||
+ if (is_dot)
|
||
+ print_dot = value;
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ struct bfd_link_hash_entry *h;
|
||
+
|
||
+ h = bfd_link_hash_lookup (link_info.hash, assignment->exp->assign.dst,
|
||
+ false, false, true);
|
||
+ if (h != NULL
|
||
+ && (h->type == bfd_link_hash_defined
|
||
+ || h->type == bfd_link_hash_defweak))
|
||
+ {
|
||
+ value = h->u.def.value;
|
||
+ value += h->u.def.section->output_section->vma;
|
||
+ value += h->u.def.section->output_offset;
|
||
+
|
||
+ buf[0] = '[';
|
||
+ buf[1] = '0';
|
||
+ buf[2] = 'x';
|
||
+ bfd_sprintf_vma (link_info.output_bfd, buf + 3, value);
|
||
+ strcat (buf, "]");
|
||
+ }
|
||
+ else
|
||
+ str = "[unresolved]";
|
||
+ }
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ if (assignment->exp->type.node_class == etree_provide)
|
||
+ str = "[!provide]";
|
||
+ else
|
||
+ str = "*undef*";
|
||
+ }
|
||
+ expld.assign_name = NULL;
|
||
+
|
||
+ fprintf (config.map_file, "%-34s", str);
|
||
+ exp_print_tree (assignment->exp);
|
||
+ print_nl ();
|
||
+}
|
||
+
|
||
+static void
|
||
+print_input_statement (lang_input_statement_type *statm)
|
||
+{
|
||
+ if (statm->filename != NULL)
|
||
+ fprintf (config.map_file, "LOAD %s\n", statm->filename);
|
||
+}
|
||
+
|
||
+/* Print all symbols defined in a particular section. This is called
|
||
+ via bfd_link_hash_traverse, or by print_all_symbols. */
|
||
+
|
||
+bool
|
||
+print_one_symbol (struct bfd_link_hash_entry *hash_entry, void *ptr)
|
||
+{
|
||
+ asection *sec = (asection *) ptr;
|
||
+
|
||
+ if ((hash_entry->type == bfd_link_hash_defined
|
||
+ || hash_entry->type == bfd_link_hash_defweak)
|
||
+ && sec == hash_entry->u.def.section)
|
||
+ {
|
||
+ print_spaces (SECTION_NAME_MAP_LENGTH);
|
||
+ minfo ("0x%V ",
|
||
+ (hash_entry->u.def.value
|
||
+ + hash_entry->u.def.section->output_offset
|
||
+ + hash_entry->u.def.section->output_section->vma));
|
||
+
|
||
+ minfo (" %pT\n", hash_entry->root.string);
|
||
+ }
|
||
+
|
||
+ return true;
|
||
+}
|
||
+
|
||
+static int
|
||
+hash_entry_addr_cmp (const void *a, const void *b)
|
||
+{
|
||
+ const struct bfd_link_hash_entry *l = *(const struct bfd_link_hash_entry **)a;
|
||
+ const struct bfd_link_hash_entry *r = *(const struct bfd_link_hash_entry **)b;
|
||
+
|
||
+ if (l->u.def.value < r->u.def.value)
|
||
+ return -1;
|
||
+ else if (l->u.def.value > r->u.def.value)
|
||
+ return 1;
|
||
+ else
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+static void
|
||
+print_all_symbols (asection *sec)
|
||
+{
|
||
+ input_section_userdata_type *ud = bfd_section_userdata (sec);
|
||
+ struct map_symbol_def *def;
|
||
+ struct bfd_link_hash_entry **entries;
|
||
+ unsigned int i;
|
||
+
|
||
+ if (!ud)
|
||
+ return;
|
||
+
|
||
+ *ud->map_symbol_def_tail = 0;
|
||
+
|
||
+ /* Sort the symbols by address. */
|
||
+ entries = (struct bfd_link_hash_entry **)
|
||
+ obstack_alloc (&map_obstack,
|
||
+ ud->map_symbol_def_count * sizeof (*entries));
|
||
+
|
||
+ for (i = 0, def = ud->map_symbol_def_head; def; def = def->next, i++)
|
||
+ entries[i] = def->entry;
|
||
+
|
||
+ qsort (entries, ud->map_symbol_def_count, sizeof (*entries),
|
||
+ hash_entry_addr_cmp);
|
||
+
|
||
+ /* Print the symbols. */
|
||
+ for (i = 0; i < ud->map_symbol_def_count; i++)
|
||
+ ldemul_print_symbol (entries[i], sec);
|
||
+
|
||
+ obstack_free (&map_obstack, entries);
|
||
+}
|
||
+
|
||
+/* Returns TRUE if SYM is a symbol suitable for printing
|
||
+ in a linker map as a local symbol. */
|
||
+
|
||
+static bool
|
||
+ld_is_local_symbol (asymbol * sym)
|
||
+{
|
||
+ const char * name = bfd_asymbol_name (sym);
|
||
+
|
||
+ if (name == NULL || *name == 0)
|
||
+ return false;
|
||
+
|
||
+ if (strcmp (name, "(null)") == 0)
|
||
+ return false;
|
||
+
|
||
+ /* Skip .Lxxx and such like. */
|
||
+ if (bfd_is_local_label (link_info.output_bfd, sym))
|
||
+ return false;
|
||
+
|
||
+ /* FIXME: This is intended to skip ARM mapping symbols,
|
||
+ which for some reason are not excluded by bfd_is_local_label,
|
||
+ but maybe it is wrong for other architectures.
|
||
+ It would be better to fix bfd_is_local_label. */
|
||
+ if (*name == '$')
|
||
+ return false;
|
||
+
|
||
+ /* Some local symbols, eg _GLOBAL_OFFSET_TABLE_, are present
|
||
+ in the hash table, so do not print duplicates here. */
|
||
+ struct bfd_link_hash_entry * h;
|
||
+ h = bfd_link_hash_lookup (link_info.hash, name, false /* create */,
|
||
+ false /* copy */, true /* follow */);
|
||
+ if (h == NULL)
|
||
+ return true;
|
||
+
|
||
+ /* Symbols from the plugin owned BFD will not get their own
|
||
+ iteration of this function, but can be on the link_info
|
||
+ list. So include them here. */
|
||
+ if (h->u.def.section->owner != NULL
|
||
+ && ((bfd_get_file_flags (h->u.def.section->owner) & (BFD_LINKER_CREATED | BFD_PLUGIN))
|
||
+ == (BFD_LINKER_CREATED | BFD_PLUGIN)))
|
||
+ return true;
|
||
+
|
||
+ return false;
|
||
+}
|
||
+
|
||
+/* Print information about an input section to the map file. */
|
||
+
|
||
+static void
|
||
+print_input_section (asection *i, bool is_discarded)
|
||
+{
|
||
+ bfd_size_type size = i->size;
|
||
+ int len;
|
||
+ bfd_vma addr;
|
||
+
|
||
+ init_opb (i);
|
||
+
|
||
+ minfo (" %s", i->name);
|
||
+
|
||
+ len = 1 + strlen (i->name);
|
||
+ if (len >= SECTION_NAME_MAP_LENGTH - 1)
|
||
+ {
|
||
+ print_nl ();
|
||
+ len = 0;
|
||
+ }
|
||
+ print_spaces (SECTION_NAME_MAP_LENGTH - len);
|
||
+
|
||
+ if (i->output_section != NULL
|
||
+ && i->output_section->owner == link_info.output_bfd)
|
||
+ addr = i->output_section->vma + i->output_offset;
|
||
+ else
|
||
+ {
|
||
+ addr = print_dot;
|
||
+ if (!is_discarded)
|
||
+ size = 0;
|
||
+ }
|
||
+
|
||
+ char buf[32];
|
||
+ bfd_sprintf_vma (link_info.output_bfd, buf, addr);
|
||
+ minfo ("0x%s %W %pB\n", buf, TO_ADDR (size), i->owner);
|
||
+
|
||
+ if (size != i->rawsize && i->rawsize != 0)
|
||
+ {
|
||
+ len = SECTION_NAME_MAP_LENGTH + 3 + strlen (buf);
|
||
+ print_spaces (len);
|
||
+ minfo (_("%W (size before relaxing)\n"), TO_ADDR (i->rawsize));
|
||
+ }
|
||
+
|
||
+ if (i->output_section != NULL
|
||
+ && i->output_section->owner == link_info.output_bfd)
|
||
+ {
|
||
+ if (link_info.reduce_memory_overheads)
|
||
+ bfd_link_hash_traverse (link_info.hash, ldemul_print_symbol, i);
|
||
+ else
|
||
+ print_all_symbols (i);
|
||
+
|
||
+ /* Update print_dot, but make sure that we do not move it
|
||
+ backwards - this could happen if we have overlays and a
|
||
+ later overlay is shorter than an earier one. */
|
||
+ if (addr + TO_ADDR (size) > print_dot)
|
||
+ print_dot = addr + TO_ADDR (size);
|
||
+
|
||
+ if (config.print_map_locals)
|
||
+ {
|
||
+ long storage_needed;
|
||
+
|
||
+ /* FIXME: It would be better to cache this table, rather
|
||
+ than recreating it for each output section. */
|
||
+ /* FIXME: This call is not working for non-ELF based targets.
|
||
+ Find out why. */
|
||
+ storage_needed = bfd_get_symtab_upper_bound (link_info.output_bfd);
|
||
+ if (storage_needed > 0)
|
||
+ {
|
||
+ asymbol ** symbol_table;
|
||
+ long number_of_symbols;
|
||
+ long j;
|
||
+
|
||
+ symbol_table = xmalloc (storage_needed);
|
||
+ number_of_symbols = bfd_canonicalize_symtab (link_info.output_bfd, symbol_table);
|
||
+
|
||
+ for (j = 0; j < number_of_symbols; j++)
|
||
+ {
|
||
+ asymbol * sym = symbol_table[j];
|
||
+ bfd_vma sym_addr = sym->value + i->output_section->vma;
|
||
+
|
||
+ if (sym->section == i->output_section
|
||
+ && (sym->flags & BSF_LOCAL) != 0
|
||
+ && sym_addr >= addr
|
||
+ && sym_addr < print_dot
|
||
+ && ld_is_local_symbol (sym))
|
||
+ {
|
||
+ print_spaces (SECTION_NAME_MAP_LENGTH);
|
||
+ minfo ("0x%V (local) %s\n", sym_addr, bfd_asymbol_name (sym));
|
||
+ }
|
||
+ }
|
||
+
|
||
+ free (symbol_table);
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+}
|
||
+
|
||
+static void
|
||
+print_fill_statement (lang_fill_statement_type *fill)
|
||
+{
|
||
+ size_t size;
|
||
+ unsigned char *p;
|
||
+ fputs (" FILL mask 0x", config.map_file);
|
||
+ for (p = fill->fill->data, size = fill->fill->size; size != 0; p++, size--)
|
||
+ fprintf (config.map_file, "%02x", *p);
|
||
+ fputs ("\n", config.map_file);
|
||
+}
|
||
+
|
||
+static void
|
||
+print_data_statement (lang_data_statement_type *data)
|
||
+{
|
||
+ bfd_vma addr;
|
||
+ bfd_size_type size;
|
||
+ const char *name;
|
||
+
|
||
+ init_opb (data->output_section);
|
||
+ print_spaces (SECTION_NAME_MAP_LENGTH);
|
||
+
|
||
+ addr = data->output_offset;
|
||
+ if (data->output_section != NULL)
|
||
+ addr += data->output_section->vma;
|
||
+
|
||
+ switch (data->type)
|
||
+ {
|
||
+ default:
|
||
+ abort ();
|
||
+ case BYTE:
|
||
+ size = BYTE_SIZE;
|
||
+ name = "BYTE";
|
||
+ break;
|
||
+ case SHORT:
|
||
+ size = SHORT_SIZE;
|
||
+ name = "SHORT";
|
||
+ break;
|
||
+ case LONG:
|
||
+ size = LONG_SIZE;
|
||
+ name = "LONG";
|
||
+ break;
|
||
+ case QUAD:
|
||
+ size = QUAD_SIZE;
|
||
+ name = "QUAD";
|
||
+ break;
|
||
+ case SQUAD:
|
||
+ size = QUAD_SIZE;
|
||
+ name = "SQUAD";
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ if (size < TO_SIZE ((unsigned) 1))
|
||
+ size = TO_SIZE ((unsigned) 1);
|
||
+ minfo ("0x%V %W %s 0x%v", addr, TO_ADDR (size), name, data->value);
|
||
+
|
||
+ if (data->exp->type.node_class != etree_value)
|
||
+ {
|
||
+ print_space ();
|
||
+ exp_print_tree (data->exp);
|
||
+ }
|
||
+
|
||
+ print_nl ();
|
||
+
|
||
+ print_dot = addr + TO_ADDR (size);
|
||
+}
|
||
+
|
||
+/* Print an address statement. These are generated by options like
|
||
+ -Ttext. */
|
||
+
|
||
+static void
|
||
+print_address_statement (lang_address_statement_type *address)
|
||
+{
|
||
+ minfo (_("Address of section %s set to "), address->section_name);
|
||
+ exp_print_tree (address->address);
|
||
+ print_nl ();
|
||
+}
|
||
+
|
||
+/* Print a reloc statement. */
|
||
+
|
||
+static void
|
||
+print_reloc_statement (lang_reloc_statement_type *reloc)
|
||
+{
|
||
+ bfd_vma addr;
|
||
+ bfd_size_type size;
|
||
+
|
||
+ init_opb (reloc->output_section);
|
||
+ print_spaces (SECTION_NAME_MAP_LENGTH);
|
||
+
|
||
+ addr = reloc->output_offset;
|
||
+ if (reloc->output_section != NULL)
|
||
+ addr += reloc->output_section->vma;
|
||
+
|
||
+ size = bfd_get_reloc_size (reloc->howto);
|
||
+
|
||
+ minfo ("0x%V %W RELOC %s ", addr, TO_ADDR (size), reloc->howto->name);
|
||
+
|
||
+ if (reloc->name != NULL)
|
||
+ minfo ("%s+", reloc->name);
|
||
+ else
|
||
+ minfo ("%s+", reloc->section->name);
|
||
+
|
||
+ exp_print_tree (reloc->addend_exp);
|
||
+
|
||
+ print_nl ();
|
||
+
|
||
+ print_dot = addr + TO_ADDR (size);
|
||
+}
|
||
+
|
||
+static void
|
||
+print_padding_statement (lang_padding_statement_type *s)
|
||
+{
|
||
+ int len;
|
||
+ bfd_vma addr;
|
||
+
|
||
+ init_opb (s->output_section);
|
||
+ minfo (" *fill*");
|
||
+
|
||
+ len = sizeof " *fill*" - 1;
|
||
+ print_spaces (SECTION_NAME_MAP_LENGTH - len);
|
||
+
|
||
+ addr = s->output_offset;
|
||
+ if (s->output_section != NULL)
|
||
+ addr += s->output_section->vma;
|
||
+ minfo ("0x%V %W ", addr, TO_ADDR (s->size));
|
||
+
|
||
+ if (s->fill->size != 0)
|
||
+ {
|
||
+ size_t size;
|
||
+ unsigned char *p;
|
||
+ for (p = s->fill->data, size = s->fill->size; size != 0; p++, size--)
|
||
+ fprintf (config.map_file, "%02x", *p);
|
||
+ }
|
||
+
|
||
+ print_nl ();
|
||
+
|
||
+ print_dot = addr + TO_ADDR (s->size);
|
||
+}
|
||
+
|
||
+static void
|
||
+print_wild_statement (lang_wild_statement_type *w,
|
||
+ lang_output_section_statement_type *os)
|
||
+{
|
||
+ struct wildcard_list *sec;
|
||
+
|
||
+ print_space ();
|
||
+
|
||
+ if (w->exclude_name_list)
|
||
+ {
|
||
+ name_list *tmp;
|
||
+ minfo ("EXCLUDE_FILE(%s", w->exclude_name_list->name);
|
||
+ for (tmp = w->exclude_name_list->next; tmp; tmp = tmp->next)
|
||
+ minfo (" %s", tmp->name);
|
||
+ minfo (") ");
|
||
+ }
|
||
+
|
||
+ if (w->filenames_sorted)
|
||
+ minfo ("SORT_BY_NAME(");
|
||
+ if (w->filename != NULL)
|
||
+ minfo ("%s", w->filename);
|
||
+ else
|
||
+ minfo ("*");
|
||
+ if (w->filenames_sorted)
|
||
+ minfo (")");
|
||
+
|
||
+ minfo ("(");
|
||
+ for (sec = w->section_list; sec; sec = sec->next)
|
||
+ {
|
||
+ int closing_paren = 0;
|
||
+
|
||
+ switch (sec->spec.sorted)
|
||
+ {
|
||
+ case none:
|
||
+ break;
|
||
+
|
||
+ case by_name:
|
||
+ minfo ("SORT_BY_NAME(");
|
||
+ closing_paren = 1;
|
||
+ break;
|
||
+
|
||
+ case by_alignment:
|
||
+ minfo ("SORT_BY_ALIGNMENT(");
|
||
+ closing_paren = 1;
|
||
+ break;
|
||
+
|
||
+ case by_name_alignment:
|
||
+ minfo ("SORT_BY_NAME(SORT_BY_ALIGNMENT(");
|
||
+ closing_paren = 2;
|
||
+ break;
|
||
+
|
||
+ case by_alignment_name:
|
||
+ minfo ("SORT_BY_ALIGNMENT(SORT_BY_NAME(");
|
||
+ closing_paren = 2;
|
||
+ break;
|
||
+
|
||
+ case by_none:
|
||
+ minfo ("SORT_NONE(");
|
||
+ closing_paren = 1;
|
||
+ break;
|
||
+
|
||
+ case by_init_priority:
|
||
+ minfo ("SORT_BY_INIT_PRIORITY(");
|
||
+ closing_paren = 1;
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ if (sec->spec.exclude_name_list != NULL)
|
||
+ {
|
||
+ name_list *tmp;
|
||
+ minfo ("EXCLUDE_FILE(%s", sec->spec.exclude_name_list->name);
|
||
+ for (tmp = sec->spec.exclude_name_list->next; tmp; tmp = tmp->next)
|
||
+ minfo (" %s", tmp->name);
|
||
+ minfo (") ");
|
||
+ }
|
||
+ if (sec->spec.name != NULL)
|
||
+ minfo ("%s", sec->spec.name);
|
||
+ else
|
||
+ minfo ("*");
|
||
+ for (;closing_paren > 0; closing_paren--)
|
||
+ minfo (")");
|
||
+ if (sec->next)
|
||
+ minfo (" ");
|
||
+ }
|
||
+ minfo (")");
|
||
+
|
||
+ print_nl ();
|
||
+
|
||
+ print_statement_list (w->children.head, os);
|
||
+}
|
||
+
|
||
+/* Print a group statement. */
|
||
+
|
||
+static void
|
||
+print_group (lang_group_statement_type *s,
|
||
+ lang_output_section_statement_type *os)
|
||
+{
|
||
+ fprintf (config.map_file, "START GROUP\n");
|
||
+ print_statement_list (s->children.head, os);
|
||
+ fprintf (config.map_file, "END GROUP\n");
|
||
+}
|
||
+
|
||
+/* Print the list of statements in S.
|
||
+ This can be called for any statement type. */
|
||
+
|
||
+static void
|
||
+print_statement_list (lang_statement_union_type *s,
|
||
+ lang_output_section_statement_type *os)
|
||
+{
|
||
+ while (s != NULL)
|
||
+ {
|
||
+ print_statement (s, os);
|
||
+ s = s->header.next;
|
||
+ }
|
||
+}
|
||
+
|
||
+/* Print the first statement in statement list S.
|
||
+ This can be called for any statement type. */
|
||
+
|
||
+static void
|
||
+print_statement (lang_statement_union_type *s,
|
||
+ lang_output_section_statement_type *os)
|
||
+{
|
||
+ switch (s->header.type)
|
||
+ {
|
||
+ default:
|
||
+ fprintf (config.map_file, _("Fail with %d\n"), s->header.type);
|
||
+ FAIL ();
|
||
+ break;
|
||
+ case lang_constructors_statement_enum:
|
||
+ if (constructor_list.head != NULL)
|
||
+ {
|
||
+ if (constructors_sorted)
|
||
+ minfo (" SORT (CONSTRUCTORS)\n");
|
||
+ else
|
||
+ minfo (" CONSTRUCTORS\n");
|
||
+ print_statement_list (constructor_list.head, os);
|
||
+ }
|
||
+ break;
|
||
+ case lang_wild_statement_enum:
|
||
+ print_wild_statement (&s->wild_statement, os);
|
||
+ break;
|
||
+ case lang_address_statement_enum:
|
||
+ print_address_statement (&s->address_statement);
|
||
+ break;
|
||
+ case lang_object_symbols_statement_enum:
|
||
+ minfo (" CREATE_OBJECT_SYMBOLS\n");
|
||
+ break;
|
||
+ case lang_fill_statement_enum:
|
||
+ print_fill_statement (&s->fill_statement);
|
||
+ break;
|
||
+ case lang_data_statement_enum:
|
||
+ print_data_statement (&s->data_statement);
|
||
+ break;
|
||
+ case lang_reloc_statement_enum:
|
||
+ print_reloc_statement (&s->reloc_statement);
|
||
+ break;
|
||
+ case lang_input_section_enum:
|
||
+ print_input_section (s->input_section.section, false);
|
||
+ break;
|
||
+ case lang_padding_statement_enum:
|
||
+ print_padding_statement (&s->padding_statement);
|
||
+ break;
|
||
+ case lang_output_section_statement_enum:
|
||
+ print_output_section_statement (&s->output_section_statement);
|
||
+ break;
|
||
+ case lang_assignment_statement_enum:
|
||
+ print_assignment (&s->assignment_statement, os);
|
||
+ break;
|
||
+ case lang_target_statement_enum:
|
||
+ fprintf (config.map_file, "TARGET(%s)\n", s->target_statement.target);
|
||
+ break;
|
||
+ case lang_output_statement_enum:
|
||
+ minfo ("OUTPUT(%s", s->output_statement.name);
|
||
+ if (output_target != NULL)
|
||
+ minfo (" %s", output_target);
|
||
+ minfo (")\n");
|
||
+ break;
|
||
+ case lang_input_statement_enum:
|
||
+ print_input_statement (&s->input_statement);
|
||
+ break;
|
||
+ case lang_group_statement_enum:
|
||
+ print_group (&s->group_statement, os);
|
||
+ break;
|
||
+ case lang_insert_statement_enum:
|
||
+ minfo ("INSERT %s %s\n",
|
||
+ s->insert_statement.is_before ? "BEFORE" : "AFTER",
|
||
+ s->insert_statement.where);
|
||
+ break;
|
||
+ }
|
||
+}
|
||
+
|
||
+static void
|
||
+print_statements (void)
|
||
+{
|
||
+ print_statement_list (statement_list.head, abs_output_section);
|
||
+}
|
||
+
|
||
+/* Print the first N statements in statement list S to STDERR.
|
||
+ If N == 0, nothing is printed.
|
||
+ If N < 0, the entire list is printed.
|
||
+ Intended to be called from GDB. */
|
||
+
|
||
+void
|
||
+dprint_statement (lang_statement_union_type *s, int n)
|
||
+{
|
||
+ FILE *map_save = config.map_file;
|
||
+
|
||
+ config.map_file = stderr;
|
||
+
|
||
+ if (n < 0)
|
||
+ print_statement_list (s, abs_output_section);
|
||
+ else
|
||
+ {
|
||
+ while (s && --n >= 0)
|
||
+ {
|
||
+ print_statement (s, abs_output_section);
|
||
+ s = s->header.next;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ config.map_file = map_save;
|
||
+}
|
||
+
|
||
+static void
|
||
+insert_pad (lang_statement_union_type **ptr,
|
||
+ fill_type *fill,
|
||
+ bfd_size_type alignment_needed,
|
||
+ asection *output_section,
|
||
+ bfd_vma dot)
|
||
+{
|
||
+ static fill_type zero_fill;
|
||
+ lang_statement_union_type *pad = NULL;
|
||
+
|
||
+ if (ptr != &statement_list.head)
|
||
+ pad = ((lang_statement_union_type *)
|
||
+ ((char *) ptr - offsetof (lang_statement_union_type, header.next)));
|
||
+ if (pad != NULL
|
||
+ && pad->header.type == lang_padding_statement_enum
|
||
+ && pad->padding_statement.output_section == output_section)
|
||
+ {
|
||
+ /* Use the existing pad statement. */
|
||
+ }
|
||
+ else if ((pad = *ptr) != NULL
|
||
+ && pad->header.type == lang_padding_statement_enum
|
||
+ && pad->padding_statement.output_section == output_section)
|
||
+ {
|
||
+ /* Use the existing pad statement. */
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ /* Make a new padding statement, linked into existing chain. */
|
||
+ pad = stat_alloc (sizeof (lang_padding_statement_type));
|
||
+ pad->header.next = *ptr;
|
||
+ *ptr = pad;
|
||
+ pad->header.type = lang_padding_statement_enum;
|
||
+ pad->padding_statement.output_section = output_section;
|
||
+ if (fill == NULL)
|
||
+ fill = &zero_fill;
|
||
+ pad->padding_statement.fill = fill;
|
||
+ }
|
||
+ pad->padding_statement.output_offset = dot - output_section->vma;
|
||
+ pad->padding_statement.size = alignment_needed;
|
||
+ if (!(output_section->flags & SEC_FIXED_SIZE))
|
||
+ output_section->size = TO_SIZE (dot + TO_ADDR (alignment_needed)
|
||
+ - output_section->vma);
|
||
+}
|
||
+
|
||
+/* Work out how much this section will move the dot point. */
|
||
+
|
||
+static bfd_vma
|
||
+size_input_section
|
||
+ (lang_statement_union_type **this_ptr,
|
||
+ lang_output_section_statement_type *output_section_statement,
|
||
+ fill_type *fill,
|
||
+ bool *removed,
|
||
+ bfd_vma dot)
|
||
+{
|
||
+ lang_input_section_type *is = &((*this_ptr)->input_section);
|
||
+ asection *i = is->section;
|
||
+ asection *o = output_section_statement->bfd_section;
|
||
+ *removed = 0;
|
||
+
|
||
+ if (link_info.non_contiguous_regions)
|
||
+ {
|
||
+ /* If the input section I has already been successfully assigned
|
||
+ to an output section other than O, don't bother with it and
|
||
+ let the caller remove it from the list. Keep processing in
|
||
+ case we have already handled O, because the repeated passes
|
||
+ have reinitialized its size. */
|
||
+ if (i->already_assigned && i->already_assigned != o)
|
||
+ {
|
||
+ *removed = 1;
|
||
+ return dot;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (i->sec_info_type == SEC_INFO_TYPE_JUST_SYMS)
|
||
+ i->output_offset = i->vma - o->vma;
|
||
+ else if (((i->flags & SEC_EXCLUDE) != 0)
|
||
+ || output_section_statement->ignored)
|
||
+ i->output_offset = dot - o->vma;
|
||
+ else
|
||
+ {
|
||
+ bfd_size_type alignment_needed;
|
||
+
|
||
+ /* Align this section first to the input sections requirement,
|
||
+ then to the output section's requirement. If this alignment
|
||
+ is greater than any seen before, then record it too. Perform
|
||
+ the alignment by inserting a magic 'padding' statement. */
|
||
+
|
||
+ if (output_section_statement->subsection_alignment != NULL)
|
||
+ i->alignment_power
|
||
+ = exp_get_power (output_section_statement->subsection_alignment,
|
||
+ "subsection alignment");
|
||
+
|
||
+ if (o->alignment_power < i->alignment_power)
|
||
+ o->alignment_power = i->alignment_power;
|
||
+
|
||
+ alignment_needed = align_power (dot, i->alignment_power) - dot;
|
||
+
|
||
+ if (alignment_needed != 0)
|
||
+ {
|
||
+ insert_pad (this_ptr, fill, TO_SIZE (alignment_needed), o, dot);
|
||
+ dot += alignment_needed;
|
||
+ }
|
||
+
|
||
+ if (link_info.non_contiguous_regions)
|
||
+ {
|
||
+ /* If I would overflow O, let the caller remove I from the
|
||
+ list. */
|
||
+ if (output_section_statement->region)
|
||
+ {
|
||
+ bfd_vma end = output_section_statement->region->origin
|
||
+ + output_section_statement->region->length;
|
||
+
|
||
+ if (dot + TO_ADDR (i->size) > end)
|
||
+ {
|
||
+ if (i->flags & SEC_LINKER_CREATED)
|
||
+ einfo (_("%F%P: Output section `%pA' not large enough for "
|
||
+ "the linker-created stubs section `%pA'.\n"),
|
||
+ i->output_section, i);
|
||
+
|
||
+ if (i->rawsize && i->rawsize != i->size)
|
||
+ einfo (_("%F%P: Relaxation not supported with "
|
||
+ "--enable-non-contiguous-regions (section `%pA' "
|
||
+ "would overflow `%pA' after it changed size).\n"),
|
||
+ i, i->output_section);
|
||
+
|
||
+ *removed = 1;
|
||
+ dot = end;
|
||
+ i->output_section = NULL;
|
||
+ return dot;
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+
|
||
+ /* Remember where in the output section this input section goes. */
|
||
+ i->output_offset = dot - o->vma;
|
||
+
|
||
+ /* Mark how big the output section must be to contain this now. */
|
||
+ dot += TO_ADDR (i->size);
|
||
+ if (!(o->flags & SEC_FIXED_SIZE))
|
||
+ o->size = TO_SIZE (dot - o->vma);
|
||
+
|
||
+ if (link_info.non_contiguous_regions)
|
||
+ {
|
||
+ /* Record that I was successfully assigned to O, and update
|
||
+ its actual output section too. */
|
||
+ i->already_assigned = o;
|
||
+ i->output_section = o;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ return dot;
|
||
+}
|
||
+
|
||
+struct check_sec
|
||
+{
|
||
+ asection *sec;
|
||
+ bool warned;
|
||
+};
|
||
+
|
||
+static int
|
||
+sort_sections_by_lma (const void *arg1, const void *arg2)
|
||
+{
|
||
+ const asection *sec1 = ((const struct check_sec *) arg1)->sec;
|
||
+ const asection *sec2 = ((const struct check_sec *) arg2)->sec;
|
||
+
|
||
+ if (sec1->lma < sec2->lma)
|
||
+ return -1;
|
||
+ else if (sec1->lma > sec2->lma)
|
||
+ return 1;
|
||
+ else if (sec1->id < sec2->id)
|
||
+ return -1;
|
||
+ else if (sec1->id > sec2->id)
|
||
+ return 1;
|
||
+
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+static int
|
||
+sort_sections_by_vma (const void *arg1, const void *arg2)
|
||
+{
|
||
+ const asection *sec1 = ((const struct check_sec *) arg1)->sec;
|
||
+ const asection *sec2 = ((const struct check_sec *) arg2)->sec;
|
||
+
|
||
+ if (sec1->vma < sec2->vma)
|
||
+ return -1;
|
||
+ else if (sec1->vma > sec2->vma)
|
||
+ return 1;
|
||
+ else if (sec1->id < sec2->id)
|
||
+ return -1;
|
||
+ else if (sec1->id > sec2->id)
|
||
+ return 1;
|
||
+
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+#define IS_TBSS(s) \
|
||
+ ((s->flags & (SEC_LOAD | SEC_THREAD_LOCAL)) == SEC_THREAD_LOCAL)
|
||
+
|
||
+#define IGNORE_SECTION(s) \
|
||
+ ((s->flags & SEC_ALLOC) == 0 || IS_TBSS (s))
|
||
+
|
||
+/* Check to see if any allocated sections overlap with other allocated
|
||
+ sections. This can happen if a linker script specifies the output
|
||
+ section addresses of the two sections. Also check whether any memory
|
||
+ region has overflowed. */
|
||
+
|
||
+static void
|
||
+lang_check_section_addresses (void)
|
||
+{
|
||
+ asection *s, *p;
|
||
+ struct check_sec *sections;
|
||
+ size_t i, count;
|
||
+ bfd_vma addr_mask;
|
||
+ bfd_vma s_start;
|
||
+ bfd_vma s_end;
|
||
+ bfd_vma p_start = 0;
|
||
+ bfd_vma p_end = 0;
|
||
+ lang_memory_region_type *m;
|
||
+ bool overlays;
|
||
+
|
||
+ /* Detect address space overflow on allocated sections. */
|
||
+ addr_mask = ((bfd_vma) 1 <<
|
||
+ (bfd_arch_bits_per_address (link_info.output_bfd) - 1)) - 1;
|
||
+ addr_mask = (addr_mask << 1) + 1;
|
||
+ for (s = link_info.output_bfd->sections; s != NULL; s = s->next)
|
||
+ if ((s->flags & SEC_ALLOC) != 0)
|
||
+ {
|
||
+ s_end = (s->vma + s->size) & addr_mask;
|
||
+ if (s_end != 0 && s_end < (s->vma & addr_mask))
|
||
+ einfo (_("%X%P: section %s VMA wraps around address space\n"),
|
||
+ s->name);
|
||
+ else
|
||
+ {
|
||
+ s_end = (s->lma + s->size) & addr_mask;
|
||
+ if (s_end != 0 && s_end < (s->lma & addr_mask))
|
||
+ einfo (_("%X%P: section %s LMA wraps around address space\n"),
|
||
+ s->name);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (bfd_count_sections (link_info.output_bfd) <= 1)
|
||
+ return;
|
||
+
|
||
+ count = bfd_count_sections (link_info.output_bfd);
|
||
+ sections = XNEWVEC (struct check_sec, count);
|
||
+
|
||
+ /* Scan all sections in the output list. */
|
||
+ count = 0;
|
||
+ for (s = link_info.output_bfd->sections; s != NULL; s = s->next)
|
||
+ {
|
||
+ if (IGNORE_SECTION (s)
|
||
+ || s->size == 0)
|
||
+ continue;
|
||
+
|
||
+ sections[count].sec = s;
|
||
+ sections[count].warned = false;
|
||
+ count++;
|
||
+ }
|
||
+
|
||
+ if (count <= 1)
|
||
+ {
|
||
+ free (sections);
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ qsort (sections, count, sizeof (*sections), sort_sections_by_lma);
|
||
+
|
||
+ /* First check section LMAs. There should be no overlap of LMAs on
|
||
+ loadable sections, even with overlays. */
|
||
+ for (p = NULL, i = 0; i < count; i++)
|
||
+ {
|
||
+ s = sections[i].sec;
|
||
+ init_opb (s);
|
||
+ if ((s->flags & SEC_LOAD) != 0)
|
||
+ {
|
||
+ s_start = s->lma;
|
||
+ s_end = s_start + TO_ADDR (s->size) - 1;
|
||
+
|
||
+ /* Look for an overlap. We have sorted sections by lma, so
|
||
+ we know that s_start >= p_start. Besides the obvious
|
||
+ case of overlap when the current section starts before
|
||
+ the previous one ends, we also must have overlap if the
|
||
+ previous section wraps around the address space. */
|
||
+ if (p != NULL
|
||
+ && (s_start <= p_end
|
||
+ || p_end < p_start))
|
||
+ {
|
||
+ einfo (_("%X%P: section %s LMA [%V,%V]"
|
||
+ " overlaps section %s LMA [%V,%V]\n"),
|
||
+ s->name, s_start, s_end, p->name, p_start, p_end);
|
||
+ sections[i].warned = true;
|
||
+ }
|
||
+ p = s;
|
||
+ p_start = s_start;
|
||
+ p_end = s_end;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ /* If any non-zero size allocated section (excluding tbss) starts at
|
||
+ exactly the same VMA as another such section, then we have
|
||
+ overlays. Overlays generated by the OVERLAY keyword will have
|
||
+ this property. It is possible to intentionally generate overlays
|
||
+ that fail this test, but it would be unusual. */
|
||
+ qsort (sections, count, sizeof (*sections), sort_sections_by_vma);
|
||
+ overlays = false;
|
||
+ p_start = sections[0].sec->vma;
|
||
+ for (i = 1; i < count; i++)
|
||
+ {
|
||
+ s_start = sections[i].sec->vma;
|
||
+ if (p_start == s_start)
|
||
+ {
|
||
+ overlays = true;
|
||
+ break;
|
||
+ }
|
||
+ p_start = s_start;
|
||
+ }
|
||
+
|
||
+ /* Now check section VMAs if no overlays were detected. */
|
||
+ if (!overlays)
|
||
+ {
|
||
+ for (p = NULL, i = 0; i < count; i++)
|
||
+ {
|
||
+ s = sections[i].sec;
|
||
+ init_opb (s);
|
||
+ s_start = s->vma;
|
||
+ s_end = s_start + TO_ADDR (s->size) - 1;
|
||
+
|
||
+ if (p != NULL
|
||
+ && !sections[i].warned
|
||
+ && (s_start <= p_end
|
||
+ || p_end < p_start))
|
||
+ einfo (_("%X%P: section %s VMA [%V,%V]"
|
||
+ " overlaps section %s VMA [%V,%V]\n"),
|
||
+ s->name, s_start, s_end, p->name, p_start, p_end);
|
||
+ p = s;
|
||
+ p_start = s_start;
|
||
+ p_end = s_end;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ free (sections);
|
||
+
|
||
+ /* If any memory region has overflowed, report by how much.
|
||
+ We do not issue this diagnostic for regions that had sections
|
||
+ explicitly placed outside their bounds; os_region_check's
|
||
+ diagnostics are adequate for that case.
|
||
+
|
||
+ FIXME: It is conceivable that m->current - (m->origin + m->length)
|
||
+ might overflow a 32-bit integer. There is, alas, no way to print
|
||
+ a bfd_vma quantity in decimal. */
|
||
+ for (m = lang_memory_region_list; m; m = m->next)
|
||
+ if (m->had_full_message)
|
||
+ {
|
||
+ unsigned long over = m->current - (m->origin + m->length);
|
||
+ einfo (ngettext ("%X%P: region `%s' overflowed by %lu byte\n",
|
||
+ "%X%P: region `%s' overflowed by %lu bytes\n",
|
||
+ over),
|
||
+ m->name_list.name, over);
|
||
+ }
|
||
+}
|
||
+
|
||
+/* Make sure the new address is within the region. We explicitly permit the
|
||
+ current address to be at the exact end of the region when the address is
|
||
+ non-zero, in case the region is at the end of addressable memory and the
|
||
+ calculation wraps around. */
|
||
+
|
||
+static void
|
||
+os_region_check (lang_output_section_statement_type *os,
|
||
+ lang_memory_region_type *region,
|
||
+ etree_type *tree,
|
||
+ bfd_vma rbase)
|
||
+{
|
||
+ if ((region->current < region->origin
|
||
+ || (region->current - region->origin > region->length))
|
||
+ && ((region->current != region->origin + region->length)
|
||
+ || rbase == 0))
|
||
+ {
|
||
+ if (tree != NULL)
|
||
+ {
|
||
+ einfo (_("%X%P: address 0x%v of %pB section `%s'"
|
||
+ " is not within region `%s'\n"),
|
||
+ region->current,
|
||
+ os->bfd_section->owner,
|
||
+ os->bfd_section->name,
|
||
+ region->name_list.name);
|
||
+ }
|
||
+ else if (!region->had_full_message)
|
||
+ {
|
||
+ region->had_full_message = true;
|
||
+
|
||
+ einfo (_("%X%P: %pB section `%s' will not fit in region `%s'\n"),
|
||
+ os->bfd_section->owner,
|
||
+ os->bfd_section->name,
|
||
+ region->name_list.name);
|
||
+ }
|
||
+ }
|
||
+}
|
||
+
|
||
+static void
|
||
+ldlang_check_relro_region (lang_statement_union_type *s)
|
||
+{
|
||
+ seg_align_type *seg = &expld.dataseg;
|
||
+
|
||
+ if (seg->relro == exp_seg_relro_start)
|
||
+ {
|
||
+ if (!seg->relro_start_stat)
|
||
+ seg->relro_start_stat = s;
|
||
+ else
|
||
+ {
|
||
+ ASSERT (seg->relro_start_stat == s);
|
||
+ }
|
||
+ }
|
||
+ else if (seg->relro == exp_seg_relro_end)
|
||
+ {
|
||
+ if (!seg->relro_end_stat)
|
||
+ seg->relro_end_stat = s;
|
||
+ else
|
||
+ {
|
||
+ ASSERT (seg->relro_end_stat == s);
|
||
+ }
|
||
+ }
|
||
+}
|
||
+
|
||
+/* Set the sizes for all the output sections. */
|
||
+
|
||
+static bfd_vma
|
||
+lang_size_sections_1
|
||
+ (lang_statement_union_type **prev,
|
||
+ lang_output_section_statement_type *output_section_statement,
|
||
+ fill_type *fill,
|
||
+ bfd_vma dot,
|
||
+ bool *relax,
|
||
+ bool check_regions)
|
||
+{
|
||
+ lang_statement_union_type *s;
|
||
+ lang_statement_union_type *prev_s = NULL;
|
||
+ bool removed_prev_s = false;
|
||
+
|
||
+ /* Size up the sections from their constituent parts. */
|
||
+ for (s = *prev; s != NULL; prev_s = s, s = s->header.next)
|
||
+ {
|
||
+ bool removed = false;
|
||
+
|
||
+ switch (s->header.type)
|
||
+ {
|
||
+ case lang_output_section_statement_enum:
|
||
+ {
|
||
+ bfd_vma newdot, after, dotdelta;
|
||
+ lang_output_section_statement_type *os;
|
||
+ lang_memory_region_type *r;
|
||
+ int section_alignment = 0;
|
||
+
|
||
+ os = &s->output_section_statement;
|
||
+ init_opb (os->bfd_section);
|
||
+ if (os->constraint == -1)
|
||
+ break;
|
||
+
|
||
+ /* FIXME: We shouldn't need to zero section vmas for ld -r
|
||
+ here, in lang_insert_orphan, or in the default linker scripts.
|
||
+ This is covering for coff backend linker bugs. See PR6945. */
|
||
+ if (os->addr_tree == NULL
|
||
+ && bfd_link_relocatable (&link_info)
|
||
+ && (bfd_get_flavour (link_info.output_bfd)
|
||
+ == bfd_target_coff_flavour))
|
||
+ os->addr_tree = exp_intop (0);
|
||
+ if (os->addr_tree != NULL)
|
||
+ {
|
||
+ exp_fold_tree (os->addr_tree, bfd_abs_section_ptr, &dot);
|
||
+
|
||
+ if (expld.result.valid_p)
|
||
+ {
|
||
+ dot = expld.result.value;
|
||
+ if (expld.result.section != NULL)
|
||
+ dot += expld.result.section->vma;
|
||
+ }
|
||
+ else if (expld.phase != lang_mark_phase_enum)
|
||
+ einfo (_("%F%P:%pS: non constant or forward reference"
|
||
+ " address expression for section %s\n"),
|
||
+ os->addr_tree, os->name);
|
||
+ }
|
||
+
|
||
+ if (os->bfd_section == NULL)
|
||
+ /* This section was removed or never actually created. */
|
||
+ break;
|
||
+
|
||
+ /* If this is a COFF shared library section, use the size and
|
||
+ address from the input section. FIXME: This is COFF
|
||
+ specific; it would be cleaner if there were some other way
|
||
+ to do this, but nothing simple comes to mind. */
|
||
+ if (((bfd_get_flavour (link_info.output_bfd)
|
||
+ == bfd_target_ecoff_flavour)
|
||
+ || (bfd_get_flavour (link_info.output_bfd)
|
||
+ == bfd_target_coff_flavour))
|
||
+ && (os->bfd_section->flags & SEC_COFF_SHARED_LIBRARY) != 0)
|
||
+ {
|
||
+ asection *input;
|
||
+
|
||
+ if (os->children.head == NULL
|
||
+ || os->children.head->header.next != NULL
|
||
+ || (os->children.head->header.type
|
||
+ != lang_input_section_enum))
|
||
+ einfo (_("%X%P: internal error on COFF shared library"
|
||
+ " section %s\n"), os->name);
|
||
+
|
||
+ input = os->children.head->input_section.section;
|
||
+ bfd_set_section_vma (os->bfd_section,
|
||
+ bfd_section_vma (input));
|
||
+ if (!(os->bfd_section->flags & SEC_FIXED_SIZE))
|
||
+ os->bfd_section->size = input->size;
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ newdot = dot;
|
||
+ dotdelta = 0;
|
||
+ if (bfd_is_abs_section (os->bfd_section))
|
||
+ {
|
||
+ /* No matter what happens, an abs section starts at zero. */
|
||
+ ASSERT (os->bfd_section->vma == 0);
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ if (os->addr_tree == NULL)
|
||
+ {
|
||
+ /* No address specified for this section, get one
|
||
+ from the region specification. */
|
||
+ if (os->region == NULL
|
||
+ || ((os->bfd_section->flags & (SEC_ALLOC | SEC_LOAD))
|
||
+ && os->region->name_list.name[0] == '*'
|
||
+ && strcmp (os->region->name_list.name,
|
||
+ DEFAULT_MEMORY_REGION) == 0))
|
||
+ {
|
||
+ os->region = lang_memory_default (os->bfd_section);
|
||
+ }
|
||
+
|
||
+ /* If a loadable section is using the default memory
|
||
+ region, and some non default memory regions were
|
||
+ defined, issue an error message. */
|
||
+ if (!os->ignored
|
||
+ && !IGNORE_SECTION (os->bfd_section)
|
||
+ && !bfd_link_relocatable (&link_info)
|
||
+ && check_regions
|
||
+ && strcmp (os->region->name_list.name,
|
||
+ DEFAULT_MEMORY_REGION) == 0
|
||
+ && lang_memory_region_list != NULL
|
||
+ && (strcmp (lang_memory_region_list->name_list.name,
|
||
+ DEFAULT_MEMORY_REGION) != 0
|
||
+ || lang_memory_region_list->next != NULL)
|
||
+ && lang_sizing_iteration == 1)
|
||
+ {
|
||
+ /* By default this is an error rather than just a
|
||
+ warning because if we allocate the section to the
|
||
+ default memory region we can end up creating an
|
||
+ excessively large binary, or even seg faulting when
|
||
+ attempting to perform a negative seek. See
|
||
+ sources.redhat.com/ml/binutils/2003-04/msg00423.html
|
||
+ for an example of this. This behaviour can be
|
||
+ overridden by the using the --no-check-sections
|
||
+ switch. */
|
||
+ if (command_line.check_section_addresses)
|
||
+ einfo (_("%F%P: error: no memory region specified"
|
||
+ " for loadable section `%s'\n"),
|
||
+ bfd_section_name (os->bfd_section));
|
||
+ else
|
||
+ einfo (_("%P: warning: no memory region specified"
|
||
+ " for loadable section `%s'\n"),
|
||
+ bfd_section_name (os->bfd_section));
|
||
+ }
|
||
+
|
||
+ newdot = os->region->current;
|
||
+ section_alignment = os->bfd_section->alignment_power;
|
||
+ }
|
||
+ else
|
||
+ section_alignment = exp_get_power (os->section_alignment,
|
||
+ "section alignment");
|
||
+
|
||
+ /* Align to what the section needs. */
|
||
+ if (section_alignment > 0)
|
||
+ {
|
||
+ bfd_vma savedot = newdot;
|
||
+ bfd_vma diff = 0;
|
||
+
|
||
+ newdot = align_power (newdot, section_alignment);
|
||
+ dotdelta = newdot - savedot;
|
||
+
|
||
+ if (lang_sizing_iteration == 1)
|
||
+ diff = dotdelta;
|
||
+ else if (lang_sizing_iteration > 1)
|
||
+ {
|
||
+ /* Only report adjustments that would change
|
||
+ alignment from what we have already reported. */
|
||
+ diff = newdot - os->bfd_section->vma;
|
||
+ if (!(diff & (((bfd_vma) 1 << section_alignment) - 1)))
|
||
+ diff = 0;
|
||
+ }
|
||
+ if (diff != 0
|
||
+ && (config.warn_section_align
|
||
+ || os->addr_tree != NULL))
|
||
+ einfo (_("%P: warning: "
|
||
+ "start of section %s changed by %ld\n"),
|
||
+ os->name, (long) diff);
|
||
+ }
|
||
+
|
||
+ bfd_set_section_vma (os->bfd_section, newdot);
|
||
+
|
||
+ os->bfd_section->output_offset = 0;
|
||
+ }
|
||
+
|
||
+ lang_size_sections_1 (&os->children.head, os,
|
||
+ os->fill, newdot, relax, check_regions);
|
||
+
|
||
+ os->processed_vma = true;
|
||
+
|
||
+ if (bfd_is_abs_section (os->bfd_section) || os->ignored)
|
||
+ /* Except for some special linker created sections,
|
||
+ no output section should change from zero size
|
||
+ after strip_excluded_output_sections. A non-zero
|
||
+ size on an ignored section indicates that some
|
||
+ input section was not sized early enough. */
|
||
+ ASSERT (os->bfd_section->size == 0);
|
||
+ else
|
||
+ {
|
||
+ dot = os->bfd_section->vma;
|
||
+
|
||
+ /* Put the section within the requested block size, or
|
||
+ align at the block boundary. */
|
||
+ after = ((dot
|
||
+ + TO_ADDR (os->bfd_section->size)
|
||
+ + os->block_value - 1)
|
||
+ & - (bfd_vma) os->block_value);
|
||
+
|
||
+ if (!(os->bfd_section->flags & SEC_FIXED_SIZE))
|
||
+ os->bfd_section->size = TO_SIZE (after
|
||
+ - os->bfd_section->vma);
|
||
+ }
|
||
+
|
||
+ /* Set section lma. */
|
||
+ r = os->region;
|
||
+ if (r == NULL)
|
||
+ r = lang_memory_region_lookup (DEFAULT_MEMORY_REGION, false);
|
||
+
|
||
+ if (os->load_base)
|
||
+ {
|
||
+ bfd_vma lma = exp_get_abs_int (os->load_base, 0, "load base");
|
||
+ os->bfd_section->lma = lma;
|
||
+ }
|
||
+ else if (os->lma_region != NULL)
|
||
+ {
|
||
+ bfd_vma lma = os->lma_region->current;
|
||
+
|
||
+ if (os->align_lma_with_input)
|
||
+ lma += dotdelta;
|
||
+ else
|
||
+ {
|
||
+ /* When LMA_REGION is the same as REGION, align the LMA
|
||
+ as we did for the VMA, possibly including alignment
|
||
+ from the bfd section. If a different region, then
|
||
+ only align according to the value in the output
|
||
+ statement. */
|
||
+ if (os->lma_region != os->region)
|
||
+ section_alignment = exp_get_power (os->section_alignment,
|
||
+ "section alignment");
|
||
+ if (section_alignment > 0)
|
||
+ lma = align_power (lma, section_alignment);
|
||
+ }
|
||
+ os->bfd_section->lma = lma;
|
||
+ }
|
||
+ else if (r->last_os != NULL
|
||
+ && (os->bfd_section->flags & SEC_ALLOC) != 0)
|
||
+ {
|
||
+ bfd_vma lma;
|
||
+ asection *last;
|
||
+
|
||
+ last = r->last_os->output_section_statement.bfd_section;
|
||
+
|
||
+ /* A backwards move of dot should be accompanied by
|
||
+ an explicit assignment to the section LMA (ie.
|
||
+ os->load_base set) because backwards moves can
|
||
+ create overlapping LMAs. */
|
||
+ if (dot < last->vma
|
||
+ && os->bfd_section->size != 0
|
||
+ && dot + TO_ADDR (os->bfd_section->size) <= last->vma)
|
||
+ {
|
||
+ /* If dot moved backwards then leave lma equal to
|
||
+ vma. This is the old default lma, which might
|
||
+ just happen to work when the backwards move is
|
||
+ sufficiently large. Nag if this changes anything,
|
||
+ so people can fix their linker scripts. */
|
||
+
|
||
+ if (last->vma != last->lma)
|
||
+ einfo (_("%P: warning: dot moved backwards "
|
||
+ "before `%s'\n"), os->name);
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ /* If this is an overlay, set the current lma to that
|
||
+ at the end of the previous section. */
|
||
+ if (os->sectype == overlay_section)
|
||
+ lma = last->lma + TO_ADDR (last->size);
|
||
+
|
||
+ /* Otherwise, keep the same lma to vma relationship
|
||
+ as the previous section. */
|
||
+ else
|
||
+ lma = os->bfd_section->vma + last->lma - last->vma;
|
||
+
|
||
+ if (section_alignment > 0)
|
||
+ lma = align_power (lma, section_alignment);
|
||
+ os->bfd_section->lma = lma;
|
||
+ }
|
||
+ }
|
||
+ os->processed_lma = true;
|
||
+
|
||
+ /* Keep track of normal sections using the default
|
||
+ lma region. We use this to set the lma for
|
||
+ following sections. Overlays or other linker
|
||
+ script assignment to lma might mean that the
|
||
+ default lma == vma is incorrect.
|
||
+ To avoid warnings about dot moving backwards when using
|
||
+ -Ttext, don't start tracking sections until we find one
|
||
+ of non-zero size or with lma set differently to vma.
|
||
+ Do this tracking before we short-cut the loop so that we
|
||
+ track changes for the case where the section size is zero,
|
||
+ but the lma is set differently to the vma. This is
|
||
+ important, if an orphan section is placed after an
|
||
+ otherwise empty output section that has an explicit lma
|
||
+ set, we want that lma reflected in the orphans lma. */
|
||
+ if (((!IGNORE_SECTION (os->bfd_section)
|
||
+ && (os->bfd_section->size != 0
|
||
+ || (r->last_os == NULL
|
||
+ && os->bfd_section->vma != os->bfd_section->lma)
|
||
+ || (r->last_os != NULL
|
||
+ && dot >= (r->last_os->output_section_statement
|
||
+ .bfd_section->vma))))
|
||
+ || os->sectype == first_overlay_section)
|
||
+ && os->lma_region == NULL
|
||
+ && !bfd_link_relocatable (&link_info))
|
||
+ r->last_os = s;
|
||
+
|
||
+ if (bfd_is_abs_section (os->bfd_section) || os->ignored)
|
||
+ break;
|
||
+
|
||
+ /* .tbss sections effectively have zero size. */
|
||
+ if (!IS_TBSS (os->bfd_section)
|
||
+ || bfd_link_relocatable (&link_info))
|
||
+ dotdelta = TO_ADDR (os->bfd_section->size);
|
||
+ else
|
||
+ dotdelta = 0;
|
||
+ dot += dotdelta;
|
||
+
|
||
+ if (os->update_dot_tree != 0)
|
||
+ exp_fold_tree (os->update_dot_tree, bfd_abs_section_ptr, &dot);
|
||
+
|
||
+ /* Update dot in the region ?
|
||
+ We only do this if the section is going to be allocated,
|
||
+ since unallocated sections do not contribute to the region's
|
||
+ overall size in memory. */
|
||
+ if (os->region != NULL
|
||
+ && (os->bfd_section->flags & (SEC_ALLOC | SEC_LOAD)))
|
||
+ {
|
||
+ os->region->current = dot;
|
||
+
|
||
+ if (check_regions)
|
||
+ /* Make sure the new address is within the region. */
|
||
+ os_region_check (os, os->region, os->addr_tree,
|
||
+ os->bfd_section->vma);
|
||
+
|
||
+ if (os->lma_region != NULL && os->lma_region != os->region
|
||
+ && ((os->bfd_section->flags & SEC_LOAD)
|
||
+ || os->align_lma_with_input))
|
||
+ {
|
||
+ os->lma_region->current = os->bfd_section->lma + dotdelta;
|
||
+
|
||
+ if (check_regions)
|
||
+ os_region_check (os, os->lma_region, NULL,
|
||
+ os->bfd_section->lma);
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+ break;
|
||
+
|
||
+ case lang_constructors_statement_enum:
|
||
+ dot = lang_size_sections_1 (&constructor_list.head,
|
||
+ output_section_statement,
|
||
+ fill, dot, relax, check_regions);
|
||
+ break;
|
||
+
|
||
+ case lang_data_statement_enum:
|
||
+ {
|
||
+ unsigned int size = 0;
|
||
+
|
||
+ s->data_statement.output_offset =
|
||
+ dot - output_section_statement->bfd_section->vma;
|
||
+ s->data_statement.output_section =
|
||
+ output_section_statement->bfd_section;
|
||
+
|
||
+ /* We might refer to provided symbols in the expression, and
|
||
+ need to mark them as needed. */
|
||
+ exp_fold_tree (s->data_statement.exp, bfd_abs_section_ptr, &dot);
|
||
+
|
||
+ switch (s->data_statement.type)
|
||
+ {
|
||
+ default:
|
||
+ abort ();
|
||
+ case QUAD:
|
||
+ case SQUAD:
|
||
+ size = QUAD_SIZE;
|
||
+ break;
|
||
+ case LONG:
|
||
+ size = LONG_SIZE;
|
||
+ break;
|
||
+ case SHORT:
|
||
+ size = SHORT_SIZE;
|
||
+ break;
|
||
+ case BYTE:
|
||
+ size = BYTE_SIZE;
|
||
+ break;
|
||
+ }
|
||
+ if (size < TO_SIZE ((unsigned) 1))
|
||
+ size = TO_SIZE ((unsigned) 1);
|
||
+ dot += TO_ADDR (size);
|
||
+ if (!(output_section_statement->bfd_section->flags
|
||
+ & SEC_FIXED_SIZE))
|
||
+ output_section_statement->bfd_section->size
|
||
+ = TO_SIZE (dot - output_section_statement->bfd_section->vma);
|
||
+
|
||
+ }
|
||
+ break;
|
||
+
|
||
+ case lang_reloc_statement_enum:
|
||
+ {
|
||
+ int size;
|
||
+
|
||
+ s->reloc_statement.output_offset =
|
||
+ dot - output_section_statement->bfd_section->vma;
|
||
+ s->reloc_statement.output_section =
|
||
+ output_section_statement->bfd_section;
|
||
+ size = bfd_get_reloc_size (s->reloc_statement.howto);
|
||
+ dot += TO_ADDR (size);
|
||
+ if (!(output_section_statement->bfd_section->flags
|
||
+ & SEC_FIXED_SIZE))
|
||
+ output_section_statement->bfd_section->size
|
||
+ = TO_SIZE (dot - output_section_statement->bfd_section->vma);
|
||
+ }
|
||
+ break;
|
||
+
|
||
+ case lang_wild_statement_enum:
|
||
+ dot = lang_size_sections_1 (&s->wild_statement.children.head,
|
||
+ output_section_statement,
|
||
+ fill, dot, relax, check_regions);
|
||
+ break;
|
||
+
|
||
+ case lang_object_symbols_statement_enum:
|
||
+ link_info.create_object_symbols_section
|
||
+ = output_section_statement->bfd_section;
|
||
+ output_section_statement->bfd_section->flags |= SEC_KEEP;
|
||
+ break;
|
||
+
|
||
+ case lang_output_statement_enum:
|
||
+ case lang_target_statement_enum:
|
||
+ break;
|
||
+
|
||
+ case lang_input_section_enum:
|
||
+ {
|
||
+ asection *i;
|
||
+
|
||
+ i = s->input_section.section;
|
||
+ if (relax)
|
||
+ {
|
||
+ bool again;
|
||
+
|
||
+ if (!bfd_relax_section (i->owner, i, &link_info, &again))
|
||
+ einfo (_("%F%P: can't relax section: %E\n"));
|
||
+ if (again)
|
||
+ *relax = true;
|
||
+ }
|
||
+ dot = size_input_section (prev, output_section_statement,
|
||
+ fill, &removed, dot);
|
||
+ }
|
||
+ break;
|
||
+
|
||
+ case lang_input_statement_enum:
|
||
+ break;
|
||
+
|
||
+ case lang_fill_statement_enum:
|
||
+ s->fill_statement.output_section =
|
||
+ output_section_statement->bfd_section;
|
||
+
|
||
+ fill = s->fill_statement.fill;
|
||
+ break;
|
||
+
|
||
+ case lang_assignment_statement_enum:
|
||
+ {
|
||
+ bfd_vma newdot = dot;
|
||
+ etree_type *tree = s->assignment_statement.exp;
|
||
+
|
||
+ expld.dataseg.relro = exp_seg_relro_none;
|
||
+
|
||
+ exp_fold_tree (tree,
|
||
+ output_section_statement->bfd_section,
|
||
+ &newdot);
|
||
+
|
||
+ ldlang_check_relro_region (s);
|
||
+
|
||
+ expld.dataseg.relro = exp_seg_relro_none;
|
||
+
|
||
+ /* This symbol may be relative to this section. */
|
||
+ if ((tree->type.node_class == etree_provided
|
||
+ || tree->type.node_class == etree_assign)
|
||
+ && (tree->assign.dst [0] != '.'
|
||
+ || tree->assign.dst [1] != '\0'))
|
||
+ output_section_statement->update_dot = 1;
|
||
+
|
||
+ if (!output_section_statement->ignored)
|
||
+ {
|
||
+ if (output_section_statement == abs_output_section)
|
||
+ {
|
||
+ /* If we don't have an output section, then just adjust
|
||
+ the default memory address. */
|
||
+ lang_memory_region_lookup (DEFAULT_MEMORY_REGION,
|
||
+ false)->current = newdot;
|
||
+ }
|
||
+ else if (newdot != dot)
|
||
+ {
|
||
+ /* Insert a pad after this statement. We can't
|
||
+ put the pad before when relaxing, in case the
|
||
+ assignment references dot. */
|
||
+ insert_pad (&s->header.next, fill, TO_SIZE (newdot - dot),
|
||
+ output_section_statement->bfd_section, dot);
|
||
+
|
||
+ /* Don't neuter the pad below when relaxing. */
|
||
+ s = s->header.next;
|
||
+
|
||
+ /* If dot is advanced, this implies that the section
|
||
+ should have space allocated to it, unless the
|
||
+ user has explicitly stated that the section
|
||
+ should not be allocated. */
|
||
+ if (output_section_statement->sectype != noalloc_section
|
||
+ && (output_section_statement->sectype != noload_section
|
||
+ || (bfd_get_flavour (link_info.output_bfd)
|
||
+ == bfd_target_elf_flavour)))
|
||
+ output_section_statement->bfd_section->flags |= SEC_ALLOC;
|
||
+ }
|
||
+ dot = newdot;
|
||
+ }
|
||
+ }
|
||
+ break;
|
||
+
|
||
+ case lang_padding_statement_enum:
|
||
+ /* If this is the first time lang_size_sections is called,
|
||
+ we won't have any padding statements. If this is the
|
||
+ second or later passes when relaxing, we should allow
|
||
+ padding to shrink. If padding is needed on this pass, it
|
||
+ will be added back in. */
|
||
+ s->padding_statement.size = 0;
|
||
+
|
||
+ /* Make sure output_offset is valid. If relaxation shrinks
|
||
+ the section and this pad isn't needed, it's possible to
|
||
+ have output_offset larger than the final size of the
|
||
+ section. bfd_set_section_contents will complain even for
|
||
+ a pad size of zero. */
|
||
+ s->padding_statement.output_offset
|
||
+ = dot - output_section_statement->bfd_section->vma;
|
||
+ break;
|
||
+
|
||
+ case lang_group_statement_enum:
|
||
+ dot = lang_size_sections_1 (&s->group_statement.children.head,
|
||
+ output_section_statement,
|
||
+ fill, dot, relax, check_regions);
|
||
+ break;
|
||
+
|
||
+ case lang_insert_statement_enum:
|
||
+ break;
|
||
+
|
||
+ /* We can only get here when relaxing is turned on. */
|
||
+ case lang_address_statement_enum:
|
||
+ break;
|
||
+
|
||
+ default:
|
||
+ FAIL ();
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ /* If an input section doesn't fit in the current output
|
||
+ section, remove it from the list. Handle the case where we
|
||
+ have to remove an input_section statement here: there is a
|
||
+ special case to remove the first element of the list. */
|
||
+ if (link_info.non_contiguous_regions && removed)
|
||
+ {
|
||
+ /* If we removed the first element during the previous
|
||
+ iteration, override the loop assignment of prev_s. */
|
||
+ if (removed_prev_s)
|
||
+ prev_s = NULL;
|
||
+
|
||
+ if (prev_s)
|
||
+ {
|
||
+ /* If there was a real previous input section, just skip
|
||
+ the current one. */
|
||
+ prev_s->header.next=s->header.next;
|
||
+ s = prev_s;
|
||
+ removed_prev_s = false;
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ /* Remove the first input section of the list. */
|
||
+ *prev = s->header.next;
|
||
+ removed_prev_s = true;
|
||
+ }
|
||
+
|
||
+ /* Move to next element, unless we removed the head of the
|
||
+ list. */
|
||
+ if (!removed_prev_s)
|
||
+ prev = &s->header.next;
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ prev = &s->header.next;
|
||
+ removed_prev_s = false;
|
||
+ }
|
||
+ }
|
||
+ return dot;
|
||
+}
|
||
+
|
||
+/* Callback routine that is used in _bfd_elf_map_sections_to_segments.
|
||
+ The BFD library has set NEW_SEGMENT to TRUE iff it thinks that
|
||
+ CURRENT_SECTION and PREVIOUS_SECTION ought to be placed into different
|
||
+ segments. We are allowed an opportunity to override this decision. */
|
||
+
|
||
+bool
|
||
+ldlang_override_segment_assignment (struct bfd_link_info *info ATTRIBUTE_UNUSED,
|
||
+ bfd *abfd ATTRIBUTE_UNUSED,
|
||
+ asection *current_section,
|
||
+ asection *previous_section,
|
||
+ bool new_segment)
|
||
+{
|
||
+ lang_output_section_statement_type *cur;
|
||
+ lang_output_section_statement_type *prev;
|
||
+
|
||
+ /* The checks below are only necessary when the BFD library has decided
|
||
+ that the two sections ought to be placed into the same segment. */
|
||
+ if (new_segment)
|
||
+ return true;
|
||
+
|
||
+ /* Paranoia checks. */
|
||
+ if (current_section == NULL || previous_section == NULL)
|
||
+ return new_segment;
|
||
+
|
||
+ /* If this flag is set, the target never wants code and non-code
|
||
+ sections comingled in the same segment. */
|
||
+ if (config.separate_code
|
||
+ && ((current_section->flags ^ previous_section->flags) & SEC_CODE))
|
||
+ return true;
|
||
+
|
||
+ /* Find the memory regions associated with the two sections.
|
||
+ We call lang_output_section_find() here rather than scanning the list
|
||
+ of output sections looking for a matching section pointer because if
|
||
+ we have a large number of sections then a hash lookup is faster. */
|
||
+ cur = lang_output_section_find (current_section->name);
|
||
+ prev = lang_output_section_find (previous_section->name);
|
||
+
|
||
+ /* More paranoia. */
|
||
+ if (cur == NULL || prev == NULL)
|
||
+ return new_segment;
|
||
+
|
||
+ /* If the regions are different then force the sections to live in
|
||
+ different segments. See the email thread starting at the following
|
||
+ URL for the reasons why this is necessary:
|
||
+ http://sourceware.org/ml/binutils/2007-02/msg00216.html */
|
||
+ return cur->region != prev->region;
|
||
+}
|
||
+
|
||
+void
|
||
+one_lang_size_sections_pass (bool *relax, bool check_regions)
|
||
+{
|
||
+ lang_statement_iteration++;
|
||
+ if (expld.phase != lang_mark_phase_enum)
|
||
+ lang_sizing_iteration++;
|
||
+ lang_size_sections_1 (&statement_list.head, abs_output_section,
|
||
+ 0, 0, relax, check_regions);
|
||
+}
|
||
+
|
||
+static bool
|
||
+lang_size_segment (void)
|
||
+{
|
||
+ /* If XXX_SEGMENT_ALIGN XXX_SEGMENT_END pair was seen, check whether
|
||
+ a page could be saved in the data segment. */
|
||
+ seg_align_type *seg = &expld.dataseg;
|
||
+ bfd_vma first, last;
|
||
+
|
||
+ first = -seg->base & (seg->commonpagesize - 1);
|
||
+ last = seg->end & (seg->commonpagesize - 1);
|
||
+ if (first && last
|
||
+ && ((seg->base & ~(seg->commonpagesize - 1))
|
||
+ != (seg->end & ~(seg->commonpagesize - 1)))
|
||
+ && first + last <= seg->commonpagesize)
|
||
+ {
|
||
+ seg->phase = exp_seg_adjust;
|
||
+ return true;
|
||
+ }
|
||
+
|
||
+ seg->phase = exp_seg_done;
|
||
+ return false;
|
||
+}
|
||
+
|
||
+static bfd_vma
|
||
+lang_size_relro_segment_1 (void)
|
||
+{
|
||
+ seg_align_type *seg = &expld.dataseg;
|
||
+ bfd_vma relro_end, desired_end;
|
||
+ asection *sec;
|
||
+
|
||
+ /* Compute the expected PT_GNU_RELRO/PT_LOAD segment end. */
|
||
+ relro_end = (seg->relro_end + seg->relropagesize - 1) & -seg->relropagesize;
|
||
+
|
||
+ /* Adjust by the offset arg of XXX_SEGMENT_RELRO_END. */
|
||
+ desired_end = relro_end - seg->relro_offset;
|
||
+
|
||
+ /* For sections in the relro segment.. */
|
||
+ for (sec = link_info.output_bfd->section_last; sec; sec = sec->prev)
|
||
+ if ((sec->flags & SEC_ALLOC) != 0
|
||
+ && sec->vma >= seg->base
|
||
+ && sec->vma < seg->relro_end - seg->relro_offset)
|
||
+ {
|
||
+ /* Where do we want to put this section so that it ends as
|
||
+ desired? */
|
||
+ bfd_vma start, end, bump;
|
||
+
|
||
+ end = start = sec->vma;
|
||
+ if (!IS_TBSS (sec))
|
||
+ end += TO_ADDR (sec->size);
|
||
+ bump = desired_end - end;
|
||
+ /* We'd like to increase START by BUMP, but we must heed
|
||
+ alignment so the increase might be less than optimum. */
|
||
+ start += bump;
|
||
+ start &= ~(((bfd_vma) 1 << sec->alignment_power) - 1);
|
||
+ /* This is now the desired end for the previous section. */
|
||
+ desired_end = start;
|
||
+ }
|
||
+
|
||
+ seg->phase = exp_seg_relro_adjust;
|
||
+ ASSERT (desired_end >= seg->base);
|
||
+ seg->base = desired_end;
|
||
+ return relro_end;
|
||
+}
|
||
+
|
||
+static bool
|
||
+lang_size_relro_segment (bool *relax, bool check_regions)
|
||
+{
|
||
+ bool do_reset = false;
|
||
+
|
||
+ if (link_info.relro && expld.dataseg.relro_end)
|
||
+ {
|
||
+ bfd_vma data_initial_base = expld.dataseg.base;
|
||
+ bfd_vma data_relro_end = lang_size_relro_segment_1 ();
|
||
+
|
||
+ lang_reset_memory_regions ();
|
||
+ one_lang_size_sections_pass (relax, check_regions);
|
||
+
|
||
+ /* Assignments to dot, or to output section address in a user
|
||
+ script have increased padding over the original. Revert. */
|
||
+ if (expld.dataseg.relro_end > data_relro_end)
|
||
+ {
|
||
+ expld.dataseg.base = data_initial_base;
|
||
+ do_reset = true;
|
||
+ }
|
||
+ }
|
||
+ else if (lang_size_segment ())
|
||
+ do_reset = true;
|
||
+
|
||
+ return do_reset;
|
||
+}
|
||
+
|
||
+void
|
||
+lang_size_sections (bool *relax, bool check_regions)
|
||
+{
|
||
+ expld.phase = lang_allocating_phase_enum;
|
||
+ expld.dataseg.phase = exp_seg_none;
|
||
+
|
||
+ one_lang_size_sections_pass (relax, check_regions);
|
||
+
|
||
+ if (expld.dataseg.phase != exp_seg_end_seen)
|
||
+ expld.dataseg.phase = exp_seg_done;
|
||
+
|
||
+ if (expld.dataseg.phase == exp_seg_end_seen)
|
||
+ {
|
||
+ bool do_reset
|
||
+ = lang_size_relro_segment (relax, check_regions);
|
||
+
|
||
+ if (do_reset)
|
||
+ {
|
||
+ lang_reset_memory_regions ();
|
||
+ one_lang_size_sections_pass (relax, check_regions);
|
||
+ }
|
||
+
|
||
+ if (link_info.relro && expld.dataseg.relro_end)
|
||
+ {
|
||
+ link_info.relro_start = expld.dataseg.base;
|
||
+ link_info.relro_end = expld.dataseg.relro_end;
|
||
+ }
|
||
+ }
|
||
+}
|
||
+
|
||
+static lang_output_section_statement_type *current_section;
|
||
+static lang_assignment_statement_type *current_assign;
|
||
+static bool prefer_next_section;
|
||
+
|
||
+/* Worker function for lang_do_assignments. Recursiveness goes here. */
|
||
+
|
||
+static bfd_vma
|
||
+lang_do_assignments_1 (lang_statement_union_type *s,
|
||
+ lang_output_section_statement_type *current_os,
|
||
+ fill_type *fill,
|
||
+ bfd_vma dot,
|
||
+ bool *found_end)
|
||
+{
|
||
+ for (; s != NULL; s = s->header.next)
|
||
+ {
|
||
+ switch (s->header.type)
|
||
+ {
|
||
+ case lang_constructors_statement_enum:
|
||
+ dot = lang_do_assignments_1 (constructor_list.head,
|
||
+ current_os, fill, dot, found_end);
|
||
+ break;
|
||
+
|
||
+ case lang_output_section_statement_enum:
|
||
+ {
|
||
+ lang_output_section_statement_type *os;
|
||
+ bfd_vma newdot;
|
||
+
|
||
+ os = &(s->output_section_statement);
|
||
+ os->after_end = *found_end;
|
||
+ init_opb (os->bfd_section);
|
||
+ newdot = dot;
|
||
+ if (os->bfd_section != NULL)
|
||
+ {
|
||
+ if (!os->ignored && (os->bfd_section->flags & SEC_ALLOC) != 0)
|
||
+ {
|
||
+ current_section = os;
|
||
+ prefer_next_section = false;
|
||
+ }
|
||
+ newdot = os->bfd_section->vma;
|
||
+ }
|
||
+ newdot = lang_do_assignments_1 (os->children.head,
|
||
+ os, os->fill, newdot, found_end);
|
||
+ if (!os->ignored)
|
||
+ {
|
||
+ if (os->bfd_section != NULL)
|
||
+ {
|
||
+ newdot = os->bfd_section->vma;
|
||
+
|
||
+ /* .tbss sections effectively have zero size. */
|
||
+ if (!IS_TBSS (os->bfd_section)
|
||
+ || bfd_link_relocatable (&link_info))
|
||
+ newdot += TO_ADDR (os->bfd_section->size);
|
||
+
|
||
+ if (os->update_dot_tree != NULL)
|
||
+ exp_fold_tree (os->update_dot_tree,
|
||
+ bfd_abs_section_ptr, &newdot);
|
||
+ }
|
||
+ dot = newdot;
|
||
+ }
|
||
+ }
|
||
+ break;
|
||
+
|
||
+ case lang_wild_statement_enum:
|
||
+
|
||
+ dot = lang_do_assignments_1 (s->wild_statement.children.head,
|
||
+ current_os, fill, dot, found_end);
|
||
+ break;
|
||
+
|
||
+ case lang_object_symbols_statement_enum:
|
||
+ case lang_output_statement_enum:
|
||
+ case lang_target_statement_enum:
|
||
+ break;
|
||
+
|
||
+ case lang_data_statement_enum:
|
||
+ exp_fold_tree (s->data_statement.exp, bfd_abs_section_ptr, &dot);
|
||
+ if (expld.result.valid_p)
|
||
+ {
|
||
+ s->data_statement.value = expld.result.value;
|
||
+ if (expld.result.section != NULL)
|
||
+ s->data_statement.value += expld.result.section->vma;
|
||
+ }
|
||
+ else if (expld.phase == lang_final_phase_enum)
|
||
+ einfo (_("%F%P: invalid data statement\n"));
|
||
+ {
|
||
+ unsigned int size;
|
||
+ switch (s->data_statement.type)
|
||
+ {
|
||
+ default:
|
||
+ abort ();
|
||
+ case QUAD:
|
||
+ case SQUAD:
|
||
+ size = QUAD_SIZE;
|
||
+ break;
|
||
+ case LONG:
|
||
+ size = LONG_SIZE;
|
||
+ break;
|
||
+ case SHORT:
|
||
+ size = SHORT_SIZE;
|
||
+ break;
|
||
+ case BYTE:
|
||
+ size = BYTE_SIZE;
|
||
+ break;
|
||
+ }
|
||
+ if (size < TO_SIZE ((unsigned) 1))
|
||
+ size = TO_SIZE ((unsigned) 1);
|
||
+ dot += TO_ADDR (size);
|
||
+ }
|
||
+ break;
|
||
+
|
||
+ case lang_reloc_statement_enum:
|
||
+ exp_fold_tree (s->reloc_statement.addend_exp,
|
||
+ bfd_abs_section_ptr, &dot);
|
||
+ if (expld.result.valid_p)
|
||
+ s->reloc_statement.addend_value = expld.result.value;
|
||
+ else if (expld.phase == lang_final_phase_enum)
|
||
+ einfo (_("%F%P: invalid reloc statement\n"));
|
||
+ dot += TO_ADDR (bfd_get_reloc_size (s->reloc_statement.howto));
|
||
+ break;
|
||
+
|
||
+ case lang_input_section_enum:
|
||
+ {
|
||
+ asection *in = s->input_section.section;
|
||
+
|
||
+ if ((in->flags & SEC_EXCLUDE) == 0)
|
||
+ dot += TO_ADDR (in->size);
|
||
+ }
|
||
+ break;
|
||
+
|
||
+ case lang_input_statement_enum:
|
||
+ break;
|
||
+
|
||
+ case lang_fill_statement_enum:
|
||
+ fill = s->fill_statement.fill;
|
||
+ break;
|
||
+
|
||
+ case lang_assignment_statement_enum:
|
||
+ current_assign = &s->assignment_statement;
|
||
+ if (current_assign->exp->type.node_class != etree_assert)
|
||
+ {
|
||
+ const char *p = current_assign->exp->assign.dst;
|
||
+
|
||
+ if (current_os == abs_output_section && p[0] == '.' && p[1] == 0)
|
||
+ prefer_next_section = true;
|
||
+
|
||
+ while (*p == '_')
|
||
+ ++p;
|
||
+ if (strcmp (p, "end") == 0)
|
||
+ *found_end = true;
|
||
+ }
|
||
+ exp_fold_tree (s->assignment_statement.exp,
|
||
+ (current_os->bfd_section != NULL
|
||
+ ? current_os->bfd_section : bfd_und_section_ptr),
|
||
+ &dot);
|
||
+ break;
|
||
+
|
||
+ case lang_padding_statement_enum:
|
||
+ dot += TO_ADDR (s->padding_statement.size);
|
||
+ break;
|
||
+
|
||
+ case lang_group_statement_enum:
|
||
+ dot = lang_do_assignments_1 (s->group_statement.children.head,
|
||
+ current_os, fill, dot, found_end);
|
||
+ break;
|
||
+
|
||
+ case lang_insert_statement_enum:
|
||
+ break;
|
||
+
|
||
+ case lang_address_statement_enum:
|
||
+ break;
|
||
+
|
||
+ default:
|
||
+ FAIL ();
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+ return dot;
|
||
+}
|
||
+
|
||
+void
|
||
+lang_do_assignments (lang_phase_type phase)
|
||
+{
|
||
+ bool found_end = false;
|
||
+
|
||
+ current_section = NULL;
|
||
+ prefer_next_section = false;
|
||
+ expld.phase = phase;
|
||
+ lang_statement_iteration++;
|
||
+ lang_do_assignments_1 (statement_list.head,
|
||
+ abs_output_section, NULL, 0, &found_end);
|
||
+}
|
||
+
|
||
+/* For an assignment statement outside of an output section statement,
|
||
+ choose the best of neighbouring output sections to use for values
|
||
+ of "dot". */
|
||
+
|
||
+asection *
|
||
+section_for_dot (void)
|
||
+{
|
||
+ asection *s;
|
||
+
|
||
+ /* Assignments belong to the previous output section, unless there
|
||
+ has been an assignment to "dot", in which case following
|
||
+ assignments belong to the next output section. (The assumption
|
||
+ is that an assignment to "dot" is setting up the address for the
|
||
+ next output section.) Except that past the assignment to "_end"
|
||
+ we always associate with the previous section. This exception is
|
||
+ for targets like SH that define an alloc .stack or other
|
||
+ weirdness after non-alloc sections. */
|
||
+ if (current_section == NULL || prefer_next_section)
|
||
+ {
|
||
+ lang_statement_union_type *stmt;
|
||
+ lang_output_section_statement_type *os;
|
||
+
|
||
+ for (stmt = (lang_statement_union_type *) current_assign;
|
||
+ stmt != NULL;
|
||
+ stmt = stmt->header.next)
|
||
+ if (stmt->header.type == lang_output_section_statement_enum)
|
||
+ break;
|
||
+
|
||
+ os = stmt ? &stmt->output_section_statement : NULL;
|
||
+ while (os != NULL
|
||
+ && !os->after_end
|
||
+ && (os->bfd_section == NULL
|
||
+ || (os->bfd_section->flags & SEC_EXCLUDE) != 0
|
||
+ || bfd_section_removed_from_list (link_info.output_bfd,
|
||
+ os->bfd_section)))
|
||
+ os = os->next;
|
||
+
|
||
+ if (current_section == NULL || os == NULL || !os->after_end)
|
||
+ {
|
||
+ if (os != NULL)
|
||
+ s = os->bfd_section;
|
||
+ else
|
||
+ s = link_info.output_bfd->section_last;
|
||
+ while (s != NULL
|
||
+ && ((s->flags & SEC_ALLOC) == 0
|
||
+ || (s->flags & SEC_THREAD_LOCAL) != 0))
|
||
+ s = s->prev;
|
||
+ if (s != NULL)
|
||
+ return s;
|
||
+
|
||
+ return bfd_abs_section_ptr;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ s = current_section->bfd_section;
|
||
+
|
||
+ /* The section may have been stripped. */
|
||
+ while (s != NULL
|
||
+ && ((s->flags & SEC_EXCLUDE) != 0
|
||
+ || (s->flags & SEC_ALLOC) == 0
|
||
+ || (s->flags & SEC_THREAD_LOCAL) != 0
|
||
+ || bfd_section_removed_from_list (link_info.output_bfd, s)))
|
||
+ s = s->prev;
|
||
+ if (s == NULL)
|
||
+ s = link_info.output_bfd->sections;
|
||
+ while (s != NULL
|
||
+ && ((s->flags & SEC_ALLOC) == 0
|
||
+ || (s->flags & SEC_THREAD_LOCAL) != 0))
|
||
+ s = s->next;
|
||
+ if (s != NULL)
|
||
+ return s;
|
||
+
|
||
+ return bfd_abs_section_ptr;
|
||
+}
|
||
+
|
||
+/* Array of __start/__stop/.startof./.sizeof/ symbols. */
|
||
+
|
||
+static struct bfd_link_hash_entry **start_stop_syms;
|
||
+static size_t start_stop_count = 0;
|
||
+static size_t start_stop_alloc = 0;
|
||
+
|
||
+/* Give start/stop SYMBOL for SEC a preliminary definition, and add it
|
||
+ to start_stop_syms. */
|
||
+
|
||
+static void
|
||
+lang_define_start_stop (const char *symbol, asection *sec)
|
||
+{
|
||
+ struct bfd_link_hash_entry *h;
|
||
+
|
||
+ h = bfd_define_start_stop (link_info.output_bfd, &link_info, symbol, sec);
|
||
+ if (h != NULL)
|
||
+ {
|
||
+ if (start_stop_count == start_stop_alloc)
|
||
+ {
|
||
+ start_stop_alloc = 2 * start_stop_alloc + 10;
|
||
+ start_stop_syms
|
||
+ = xrealloc (start_stop_syms,
|
||
+ start_stop_alloc * sizeof (*start_stop_syms));
|
||
+ }
|
||
+ start_stop_syms[start_stop_count++] = h;
|
||
+ }
|
||
+}
|
||
+
|
||
+/* Check for input sections whose names match references to
|
||
+ __start_SECNAME or __stop_SECNAME symbols. Give the symbols
|
||
+ preliminary definitions. */
|
||
+
|
||
+static void
|
||
+lang_init_start_stop (void)
|
||
+{
|
||
+ bfd *abfd;
|
||
+ asection *s;
|
||
+ char leading_char = bfd_get_symbol_leading_char (link_info.output_bfd);
|
||
+
|
||
+ for (abfd = link_info.input_bfds; abfd != NULL; abfd = abfd->link.next)
|
||
+ for (s = abfd->sections; s != NULL; s = s->next)
|
||
+ {
|
||
+ const char *ps;
|
||
+ const char *secname = s->name;
|
||
+
|
||
+ for (ps = secname; *ps != '\0'; ps++)
|
||
+ if (!ISALNUM ((unsigned char) *ps) && *ps != '_')
|
||
+ break;
|
||
+ if (*ps == '\0')
|
||
+ {
|
||
+ char *symbol = (char *) xmalloc (10 + strlen (secname));
|
||
+
|
||
+ symbol[0] = leading_char;
|
||
+ sprintf (symbol + (leading_char != 0), "__start_%s", secname);
|
||
+ lang_define_start_stop (symbol, s);
|
||
+
|
||
+ symbol[1] = leading_char;
|
||
+ memcpy (symbol + 1 + (leading_char != 0), "__stop", 6);
|
||
+ lang_define_start_stop (symbol + 1, s);
|
||
+
|
||
+ free (symbol);
|
||
+ }
|
||
+ }
|
||
+}
|
||
+
|
||
+/* Iterate over start_stop_syms. */
|
||
+
|
||
+static void
|
||
+foreach_start_stop (void (*func) (struct bfd_link_hash_entry *))
|
||
+{
|
||
+ size_t i;
|
||
+
|
||
+ for (i = 0; i < start_stop_count; ++i)
|
||
+ func (start_stop_syms[i]);
|
||
+}
|
||
+
|
||
+/* __start and __stop symbols are only supposed to be defined by the
|
||
+ linker for orphan sections, but we now extend that to sections that
|
||
+ map to an output section of the same name. The symbols were
|
||
+ defined early for --gc-sections, before we mapped input to output
|
||
+ sections, so undo those that don't satisfy this rule. */
|
||
+
|
||
+static void
|
||
+undef_start_stop (struct bfd_link_hash_entry *h)
|
||
+{
|
||
+ if (h->ldscript_def)
|
||
+ return;
|
||
+
|
||
+ if (h->u.def.section->output_section == NULL
|
||
+ || h->u.def.section->output_section->owner != link_info.output_bfd
|
||
+ || strcmp (h->u.def.section->name,
|
||
+ h->u.def.section->output_section->name) != 0)
|
||
+ {
|
||
+ asection *sec = bfd_get_section_by_name (link_info.output_bfd,
|
||
+ h->u.def.section->name);
|
||
+ if (sec != NULL)
|
||
+ {
|
||
+ /* When there are more than one input sections with the same
|
||
+ section name, SECNAME, linker picks the first one to define
|
||
+ __start_SECNAME and __stop_SECNAME symbols. When the first
|
||
+ input section is removed by comdat group, we need to check
|
||
+ if there is still an output section with section name
|
||
+ SECNAME. */
|
||
+ asection *i;
|
||
+ for (i = sec->map_head.s; i != NULL; i = i->map_head.s)
|
||
+ if (strcmp (h->u.def.section->name, i->name) == 0)
|
||
+ {
|
||
+ h->u.def.section = i;
|
||
+ return;
|
||
+ }
|
||
+ }
|
||
+ h->type = bfd_link_hash_undefined;
|
||
+ h->u.undef.abfd = NULL;
|
||
+ if (is_elf_hash_table (link_info.hash))
|
||
+ {
|
||
+ const struct elf_backend_data *bed;
|
||
+ struct elf_link_hash_entry *eh = (struct elf_link_hash_entry *) h;
|
||
+ unsigned int was_forced = eh->forced_local;
|
||
+
|
||
+ bed = get_elf_backend_data (link_info.output_bfd);
|
||
+ (*bed->elf_backend_hide_symbol) (&link_info, eh, true);
|
||
+ if (!eh->ref_regular_nonweak)
|
||
+ h->type = bfd_link_hash_undefweak;
|
||
+ eh->def_regular = 0;
|
||
+ eh->forced_local = was_forced;
|
||
+ }
|
||
+ }
|
||
+}
|
||
+
|
||
+static void
|
||
+lang_undef_start_stop (void)
|
||
+{
|
||
+ foreach_start_stop (undef_start_stop);
|
||
+}
|
||
+
|
||
+/* Check for output sections whose names match references to
|
||
+ .startof.SECNAME or .sizeof.SECNAME symbols. Give the symbols
|
||
+ preliminary definitions. */
|
||
+
|
||
+static void
|
||
+lang_init_startof_sizeof (void)
|
||
+{
|
||
+ asection *s;
|
||
+
|
||
+ for (s = link_info.output_bfd->sections; s != NULL; s = s->next)
|
||
+ {
|
||
+ const char *secname = s->name;
|
||
+ char *symbol = (char *) xmalloc (10 + strlen (secname));
|
||
+
|
||
+ sprintf (symbol, ".startof.%s", secname);
|
||
+ lang_define_start_stop (symbol, s);
|
||
+
|
||
+ memcpy (symbol + 1, ".size", 5);
|
||
+ lang_define_start_stop (symbol + 1, s);
|
||
+ free (symbol);
|
||
+ }
|
||
+}
|
||
+
|
||
+/* Set .startof., .sizeof., __start and __stop symbols final values. */
|
||
+
|
||
+static void
|
||
+set_start_stop (struct bfd_link_hash_entry *h)
|
||
+{
|
||
+ if (h->ldscript_def
|
||
+ || h->type != bfd_link_hash_defined)
|
||
+ return;
|
||
+
|
||
+ if (h->root.string[0] == '.')
|
||
+ {
|
||
+ /* .startof. or .sizeof. symbol.
|
||
+ .startof. already has final value. */
|
||
+ if (h->root.string[2] == 'i')
|
||
+ {
|
||
+ /* .sizeof. */
|
||
+ h->u.def.value = TO_ADDR (h->u.def.section->size);
|
||
+ h->u.def.section = bfd_abs_section_ptr;
|
||
+ }
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ /* __start or __stop symbol. */
|
||
+ int has_lead = bfd_get_symbol_leading_char (link_info.output_bfd) != 0;
|
||
+
|
||
+ h->u.def.section = h->u.def.section->output_section;
|
||
+ if (h->root.string[4 + has_lead] == 'o')
|
||
+ {
|
||
+ /* __stop_ */
|
||
+ h->u.def.value = TO_ADDR (h->u.def.section->size);
|
||
+ }
|
||
+ }
|
||
+}
|
||
+
|
||
+static void
|
||
+lang_finalize_start_stop (void)
|
||
+{
|
||
+ foreach_start_stop (set_start_stop);
|
||
+}
|
||
+
|
||
+static void
|
||
+lang_symbol_tweaks (void)
|
||
+{
|
||
+ /* Give initial values for __start and __stop symbols, so that ELF
|
||
+ gc_sections will keep sections referenced by these symbols. Must
|
||
+ be done before lang_do_assignments. */
|
||
+ if (config.build_constructors)
|
||
+ lang_init_start_stop ();
|
||
+
|
||
+ /* Make __ehdr_start hidden, and set def_regular even though it is
|
||
+ likely undefined at this stage. For lang_check_relocs. */
|
||
+ if (is_elf_hash_table (link_info.hash)
|
||
+ && !bfd_link_relocatable (&link_info))
|
||
+ {
|
||
+ struct elf_link_hash_entry *h = (struct elf_link_hash_entry *)
|
||
+ bfd_link_hash_lookup (link_info.hash, "__ehdr_start",
|
||
+ false, false, true);
|
||
+
|
||
+ /* Only adjust the export class if the symbol was referenced
|
||
+ and not defined, otherwise leave it alone. */
|
||
+ if (h != NULL
|
||
+ && (h->root.type == bfd_link_hash_new
|
||
+ || h->root.type == bfd_link_hash_undefined
|
||
+ || h->root.type == bfd_link_hash_undefweak
|
||
+ || h->root.type == bfd_link_hash_common))
|
||
+ {
|
||
+ const struct elf_backend_data *bed;
|
||
+ bed = get_elf_backend_data (link_info.output_bfd);
|
||
+ (*bed->elf_backend_hide_symbol) (&link_info, h, true);
|
||
+ if (ELF_ST_VISIBILITY (h->other) != STV_INTERNAL)
|
||
+ h->other = (h->other & ~ELF_ST_VISIBILITY (-1)) | STV_HIDDEN;
|
||
+ h->def_regular = 1;
|
||
+ h->root.linker_def = 1;
|
||
+ h->root.rel_from_abs = 1;
|
||
+ }
|
||
+ }
|
||
+}
|
||
+
|
||
+static void
|
||
+lang_end (void)
|
||
+{
|
||
+ struct bfd_link_hash_entry *h;
|
||
+ bool warn;
|
||
+
|
||
+ if ((bfd_link_relocatable (&link_info) && !link_info.gc_sections)
|
||
+ || bfd_link_dll (&link_info))
|
||
+ warn = entry_from_cmdline;
|
||
+ else
|
||
+ warn = true;
|
||
+
|
||
+ /* Force the user to specify a root when generating a relocatable with
|
||
+ --gc-sections, unless --gc-keep-exported was also given. */
|
||
+ if (bfd_link_relocatable (&link_info)
|
||
+ && link_info.gc_sections
|
||
+ && !link_info.gc_keep_exported)
|
||
+ {
|
||
+ struct bfd_sym_chain *sym;
|
||
+
|
||
+ for (sym = link_info.gc_sym_list; sym != NULL; sym = sym->next)
|
||
+ {
|
||
+ h = bfd_link_hash_lookup (link_info.hash, sym->name,
|
||
+ false, false, false);
|
||
+ if (h != NULL
|
||
+ && (h->type == bfd_link_hash_defined
|
||
+ || h->type == bfd_link_hash_defweak)
|
||
+ && !bfd_is_const_section (h->u.def.section))
|
||
+ break;
|
||
+ }
|
||
+ if (!sym)
|
||
+ einfo (_("%F%P: --gc-sections requires a defined symbol root "
|
||
+ "specified by -e or -u\n"));
|
||
+ }
|
||
+
|
||
+ if (entry_symbol.name == NULL)
|
||
+ {
|
||
+ /* No entry has been specified. Look for the default entry, but
|
||
+ don't warn if we don't find it. */
|
||
+ entry_symbol.name = entry_symbol_default;
|
||
+ warn = false;
|
||
+ }
|
||
+
|
||
+ h = bfd_link_hash_lookup (link_info.hash, entry_symbol.name,
|
||
+ false, false, true);
|
||
+ if (h != NULL
|
||
+ && (h->type == bfd_link_hash_defined
|
||
+ || h->type == bfd_link_hash_defweak)
|
||
+ && h->u.def.section->output_section != NULL)
|
||
+ {
|
||
+ bfd_vma val;
|
||
+
|
||
+ val = (h->u.def.value
|
||
+ + bfd_section_vma (h->u.def.section->output_section)
|
||
+ + h->u.def.section->output_offset);
|
||
+ if (!bfd_set_start_address (link_info.output_bfd, val))
|
||
+ einfo (_("%F%P: %s: can't set start address\n"), entry_symbol.name);
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ bfd_vma val;
|
||
+ const char *send;
|
||
+
|
||
+ /* We couldn't find the entry symbol. Try parsing it as a
|
||
+ number. */
|
||
+ val = bfd_scan_vma (entry_symbol.name, &send, 0);
|
||
+ if (*send == '\0')
|
||
+ {
|
||
+ if (!bfd_set_start_address (link_info.output_bfd, val))
|
||
+ einfo (_("%F%P: can't set start address\n"));
|
||
+ }
|
||
+ /* BZ 2004952: Only use the start of the entry section for executables. */
|
||
+ else if bfd_link_executable (&link_info)
|
||
+ {
|
||
+ asection *ts;
|
||
+
|
||
+ /* Can't find the entry symbol, and it's not a number. Use
|
||
+ the first address in the text section. */
|
||
+ ts = bfd_get_section_by_name (link_info.output_bfd, entry_section);
|
||
+ if (ts != NULL)
|
||
+ {
|
||
+ if (warn)
|
||
+ einfo (_("%P: warning: cannot find entry symbol %s;"
|
||
+ " defaulting to %V\n"),
|
||
+ entry_symbol.name,
|
||
+ bfd_section_vma (ts));
|
||
+ if (!bfd_set_start_address (link_info.output_bfd,
|
||
+ bfd_section_vma (ts)))
|
||
+ einfo (_("%F%P: can't set start address\n"));
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ if (warn)
|
||
+ einfo (_("%P: warning: cannot find entry symbol %s;"
|
||
+ " not setting start address\n"),
|
||
+ entry_symbol.name);
|
||
+ }
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ if (warn)
|
||
+ einfo (_("%P: warning: cannot find entry symbol %s;"
|
||
+ " not setting start address\n"),
|
||
+ entry_symbol.name);
|
||
+ }
|
||
+ }
|
||
+}
|
||
+
|
||
+/* This is a small function used when we want to ignore errors from
|
||
+ BFD. */
|
||
+
|
||
+static void
|
||
+ignore_bfd_errors (const char *fmt ATTRIBUTE_UNUSED,
|
||
+ va_list ap ATTRIBUTE_UNUSED)
|
||
+{
|
||
+ /* Don't do anything. */
|
||
+}
|
||
+
|
||
+/* Check that the architecture of all the input files is compatible
|
||
+ with the output file. Also call the backend to let it do any
|
||
+ other checking that is needed. */
|
||
+
|
||
+static void
|
||
+lang_check (void)
|
||
+{
|
||
+ lang_input_statement_type *file;
|
||
+ bfd *input_bfd;
|
||
+ const bfd_arch_info_type *compatible;
|
||
+
|
||
+ for (file = (void *) file_chain.head;
|
||
+ file != NULL;
|
||
+ file = file->next)
|
||
+ {
|
||
+#if BFD_SUPPORTS_PLUGINS
|
||
+ /* Don't check format of files claimed by plugin. */
|
||
+ if (file->flags.claimed)
|
||
+ continue;
|
||
+#endif /* BFD_SUPPORTS_PLUGINS */
|
||
+ input_bfd = file->the_bfd;
|
||
+ compatible
|
||
+ = bfd_arch_get_compatible (input_bfd, link_info.output_bfd,
|
||
+ command_line.accept_unknown_input_arch);
|
||
+
|
||
+ /* In general it is not possible to perform a relocatable
|
||
+ link between differing object formats when the input
|
||
+ file has relocations, because the relocations in the
|
||
+ input format may not have equivalent representations in
|
||
+ the output format (and besides BFD does not translate
|
||
+ relocs for other link purposes than a final link). */
|
||
+ if (!file->flags.just_syms
|
||
+ && (bfd_link_relocatable (&link_info)
|
||
+ || link_info.emitrelocations)
|
||
+ && (compatible == NULL
|
||
+ || (bfd_get_flavour (input_bfd)
|
||
+ != bfd_get_flavour (link_info.output_bfd)))
|
||
+ && (bfd_get_file_flags (input_bfd) & HAS_RELOC) != 0)
|
||
+ {
|
||
+ einfo (_("%F%P: relocatable linking with relocations from"
|
||
+ " format %s (%pB) to format %s (%pB) is not supported\n"),
|
||
+ bfd_get_target (input_bfd), input_bfd,
|
||
+ bfd_get_target (link_info.output_bfd), link_info.output_bfd);
|
||
+ /* einfo with %F exits. */
|
||
+ }
|
||
+
|
||
+ if (compatible == NULL)
|
||
+ {
|
||
+ if (command_line.warn_mismatch)
|
||
+ einfo (_("%X%P: %s architecture of input file `%pB'"
|
||
+ " is incompatible with %s output\n"),
|
||
+ bfd_printable_name (input_bfd), input_bfd,
|
||
+ bfd_printable_name (link_info.output_bfd));
|
||
+ }
|
||
+
|
||
+ /* If the input bfd has no contents, it shouldn't set the
|
||
+ private data of the output bfd. */
|
||
+ else if (!file->flags.just_syms
|
||
+ && ((input_bfd->flags & DYNAMIC) != 0
|
||
+ || bfd_count_sections (input_bfd) != 0))
|
||
+ {
|
||
+ bfd_error_handler_type pfn = NULL;
|
||
+
|
||
+ /* If we aren't supposed to warn about mismatched input
|
||
+ files, temporarily set the BFD error handler to a
|
||
+ function which will do nothing. We still want to call
|
||
+ bfd_merge_private_bfd_data, since it may set up
|
||
+ information which is needed in the output file. */
|
||
+ if (!command_line.warn_mismatch)
|
||
+ pfn = bfd_set_error_handler (ignore_bfd_errors);
|
||
+ if (!bfd_merge_private_bfd_data (input_bfd, &link_info))
|
||
+ {
|
||
+ if (command_line.warn_mismatch)
|
||
+ einfo (_("%X%P: failed to merge target specific data"
|
||
+ " of file %pB\n"), input_bfd);
|
||
+ }
|
||
+ if (!command_line.warn_mismatch)
|
||
+ bfd_set_error_handler (pfn);
|
||
+ }
|
||
+ }
|
||
+}
|
||
+
|
||
+/* Look through all the global common symbols and attach them to the
|
||
+ correct section. The -sort-common command line switch may be used
|
||
+ to roughly sort the entries by alignment. */
|
||
+
|
||
+static void
|
||
+lang_common (void)
|
||
+{
|
||
+ if (link_info.inhibit_common_definition)
|
||
+ return;
|
||
+ if (bfd_link_relocatable (&link_info)
|
||
+ && !command_line.force_common_definition)
|
||
+ return;
|
||
+
|
||
+ if (!config.sort_common)
|
||
+ bfd_link_hash_traverse (link_info.hash, lang_one_common, NULL);
|
||
+ else
|
||
+ {
|
||
+ unsigned int power;
|
||
+
|
||
+ if (config.sort_common == sort_descending)
|
||
+ {
|
||
+ for (power = 4; power > 0; power--)
|
||
+ bfd_link_hash_traverse (link_info.hash, lang_one_common, &power);
|
||
+
|
||
+ power = 0;
|
||
+ bfd_link_hash_traverse (link_info.hash, lang_one_common, &power);
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ for (power = 0; power <= 4; power++)
|
||
+ bfd_link_hash_traverse (link_info.hash, lang_one_common, &power);
|
||
+
|
||
+ power = (unsigned int) -1;
|
||
+ bfd_link_hash_traverse (link_info.hash, lang_one_common, &power);
|
||
+ }
|
||
+ }
|
||
+}
|
||
+
|
||
+/* Place one common symbol in the correct section. */
|
||
+
|
||
+static bool
|
||
+lang_one_common (struct bfd_link_hash_entry *h, void *info)
|
||
+{
|
||
+ unsigned int power_of_two;
|
||
+ bfd_vma size;
|
||
+ asection *section;
|
||
+
|
||
+ if (h->type != bfd_link_hash_common)
|
||
+ return true;
|
||
+
|
||
+ size = h->u.c.size;
|
||
+ power_of_two = h->u.c.p->alignment_power;
|
||
+
|
||
+ if (config.sort_common == sort_descending
|
||
+ && power_of_two < *(unsigned int *) info)
|
||
+ return true;
|
||
+ else if (config.sort_common == sort_ascending
|
||
+ && power_of_two > *(unsigned int *) info)
|
||
+ return true;
|
||
+
|
||
+ section = h->u.c.p->section;
|
||
+ if (!bfd_define_common_symbol (link_info.output_bfd, &link_info, h))
|
||
+ einfo (_("%F%P: could not define common symbol `%pT': %E\n"),
|
||
+ h->root.string);
|
||
+
|
||
+ if (config.map_file != NULL)
|
||
+ {
|
||
+ static bool header_printed;
|
||
+ int len;
|
||
+ char *name;
|
||
+ char buf[32];
|
||
+
|
||
+ if (!header_printed)
|
||
+ {
|
||
+ minfo (_("\nAllocating common symbols\n"));
|
||
+ minfo (_("Common symbol size file\n\n"));
|
||
+ header_printed = true;
|
||
+ }
|
||
+
|
||
+ name = bfd_demangle (link_info.output_bfd, h->root.string,
|
||
+ DMGL_ANSI | DMGL_PARAMS);
|
||
+ if (name == NULL)
|
||
+ {
|
||
+ minfo ("%s", h->root.string);
|
||
+ len = strlen (h->root.string);
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ minfo ("%s", name);
|
||
+ len = strlen (name);
|
||
+ free (name);
|
||
+ }
|
||
+
|
||
+ if (len >= 19)
|
||
+ {
|
||
+ print_nl ();
|
||
+ len = 0;
|
||
+ }
|
||
+
|
||
+ sprintf (buf, "%" PRIx64, (uint64_t) size);
|
||
+ fprintf (config.map_file, "%*s0x%-16s", 20 - len, "", buf);
|
||
+
|
||
+ minfo ("%pB\n", section->owner);
|
||
+ }
|
||
+
|
||
+ return true;
|
||
+}
|
||
+
|
||
+/* Handle a single orphan section S, placing the orphan into an appropriate
|
||
+ output section. The effects of the --orphan-handling command line
|
||
+ option are handled here. */
|
||
+
|
||
+static void
|
||
+ldlang_place_orphan (asection *s)
|
||
+{
|
||
+ if (config.orphan_handling == orphan_handling_discard)
|
||
+ {
|
||
+ lang_output_section_statement_type *os;
|
||
+ os = lang_output_section_statement_lookup (DISCARD_SECTION_NAME, 0, 1);
|
||
+ if (os->addr_tree == NULL
|
||
+ && (bfd_link_relocatable (&link_info)
|
||
+ || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0))
|
||
+ os->addr_tree = exp_intop (0);
|
||
+ lang_add_section (&os->children, s, NULL, NULL, os);
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ lang_output_section_statement_type *os;
|
||
+ const char *name = s->name;
|
||
+ int constraint = 0;
|
||
+
|
||
+ if (config.orphan_handling == orphan_handling_error)
|
||
+ einfo (_("%X%P: error: unplaced orphan section `%pA' from `%pB'\n"),
|
||
+ s, s->owner);
|
||
+
|
||
+ if (config.unique_orphan_sections || unique_section_p (s, NULL))
|
||
+ constraint = SPECIAL;
|
||
+
|
||
+ os = ldemul_place_orphan (s, name, constraint);
|
||
+ if (os == NULL)
|
||
+ {
|
||
+ os = lang_output_section_statement_lookup (name, constraint, 1);
|
||
+ if (os->addr_tree == NULL
|
||
+ && (bfd_link_relocatable (&link_info)
|
||
+ || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0))
|
||
+ os->addr_tree = exp_intop (0);
|
||
+ lang_add_section (&os->children, s, NULL, NULL, os);
|
||
+ }
|
||
+
|
||
+ if (config.orphan_handling == orphan_handling_warn)
|
||
+ einfo (_("%P: warning: orphan section `%pA' from `%pB' being "
|
||
+ "placed in section `%s'\n"),
|
||
+ s, s->owner, os->name);
|
||
+ }
|
||
+}
|
||
+
|
||
+/* Run through the input files and ensure that every input section has
|
||
+ somewhere to go. If one is found without a destination then create
|
||
+ an input request and place it into the statement tree. */
|
||
+
|
||
+static void
|
||
+lang_place_orphans (void)
|
||
+{
|
||
+ LANG_FOR_EACH_INPUT_STATEMENT (file)
|
||
+ {
|
||
+ asection *s;
|
||
+
|
||
+ for (s = file->the_bfd->sections; s != NULL; s = s->next)
|
||
+ {
|
||
+ if (s->output_section == NULL)
|
||
+ {
|
||
+ /* This section of the file is not attached, root
|
||
+ around for a sensible place for it to go. */
|
||
+
|
||
+ if (file->flags.just_syms)
|
||
+ bfd_link_just_syms (file->the_bfd, s, &link_info);
|
||
+ else if (lang_discard_section_p (s))
|
||
+ s->output_section = bfd_abs_section_ptr;
|
||
+ else if (strcmp (s->name, "COMMON") == 0)
|
||
+ {
|
||
+ /* This is a lonely common section which must have
|
||
+ come from an archive. We attach to the section
|
||
+ with the wildcard. */
|
||
+ if (!bfd_link_relocatable (&link_info)
|
||
+ || command_line.force_common_definition)
|
||
+ {
|
||
+ if (default_common_section == NULL)
|
||
+ default_common_section
|
||
+ = lang_output_section_statement_lookup (".bss", 0, 1);
|
||
+ lang_add_section (&default_common_section->children, s,
|
||
+ NULL, NULL, default_common_section);
|
||
+ }
|
||
+ }
|
||
+ else
|
||
+ ldlang_place_orphan (s);
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+}
|
||
+
|
||
+void
|
||
+lang_set_flags (lang_memory_region_type *ptr, const char *flags, int invert)
|
||
+{
|
||
+ flagword *ptr_flags;
|
||
+
|
||
+ ptr_flags = invert ? &ptr->not_flags : &ptr->flags;
|
||
+
|
||
+ while (*flags)
|
||
+ {
|
||
+ switch (*flags)
|
||
+ {
|
||
+ /* PR 17900: An exclamation mark in the attributes reverses
|
||
+ the sense of any of the attributes that follow. */
|
||
+ case '!':
|
||
+ invert = !invert;
|
||
+ ptr_flags = invert ? &ptr->not_flags : &ptr->flags;
|
||
+ break;
|
||
+
|
||
+ case 'A': case 'a':
|
||
+ *ptr_flags |= SEC_ALLOC;
|
||
+ break;
|
||
+
|
||
+ case 'R': case 'r':
|
||
+ *ptr_flags |= SEC_READONLY;
|
||
+ break;
|
||
+
|
||
+ case 'W': case 'w':
|
||
+ *ptr_flags |= SEC_DATA;
|
||
+ break;
|
||
+
|
||
+ case 'X': case 'x':
|
||
+ *ptr_flags |= SEC_CODE;
|
||
+ break;
|
||
+
|
||
+ case 'L': case 'l':
|
||
+ case 'I': case 'i':
|
||
+ *ptr_flags |= SEC_LOAD;
|
||
+ break;
|
||
+
|
||
+ default:
|
||
+ einfo (_("%F%P: invalid character %c (%d) in flags\n"),
|
||
+ *flags, *flags);
|
||
+ break;
|
||
+ }
|
||
+ flags++;
|
||
+ }
|
||
+}
|
||
+
|
||
+/* Call a function on each real input file. This function will be
|
||
+ called on an archive, but not on the elements. */
|
||
+
|
||
+void
|
||
+lang_for_each_input_file (void (*func) (lang_input_statement_type *))
|
||
+{
|
||
+ lang_input_statement_type *f;
|
||
+
|
||
+ for (f = (void *) input_file_chain.head;
|
||
+ f != NULL;
|
||
+ f = f->next_real_file)
|
||
+ if (f->flags.real)
|
||
+ func (f);
|
||
+}
|
||
+
|
||
+/* Call a function on each real file. The function will be called on
|
||
+ all the elements of an archive which are included in the link, but
|
||
+ will not be called on the archive file itself. */
|
||
+
|
||
+void
|
||
+lang_for_each_file (void (*func) (lang_input_statement_type *))
|
||
+{
|
||
+ LANG_FOR_EACH_INPUT_STATEMENT (f)
|
||
+ {
|
||
+ if (f->flags.real)
|
||
+ func (f);
|
||
+ }
|
||
+}
|
||
+
|
||
+void
|
||
+ldlang_add_file (lang_input_statement_type *entry)
|
||
+{
|
||
+ lang_statement_append (&file_chain, entry, &entry->next);
|
||
+
|
||
+ /* The BFD linker needs to have a list of all input BFDs involved in
|
||
+ a link. */
|
||
+ ASSERT (link_info.input_bfds_tail != &entry->the_bfd->link.next
|
||
+ && entry->the_bfd->link.next == NULL);
|
||
+ ASSERT (entry->the_bfd != link_info.output_bfd);
|
||
+
|
||
+ *link_info.input_bfds_tail = entry->the_bfd;
|
||
+ link_info.input_bfds_tail = &entry->the_bfd->link.next;
|
||
+ bfd_set_usrdata (entry->the_bfd, entry);
|
||
+ bfd_set_gp_size (entry->the_bfd, g_switch_value);
|
||
+
|
||
+ /* Look through the sections and check for any which should not be
|
||
+ included in the link. We need to do this now, so that we can
|
||
+ notice when the backend linker tries to report multiple
|
||
+ definition errors for symbols which are in sections we aren't
|
||
+ going to link. FIXME: It might be better to entirely ignore
|
||
+ symbols which are defined in sections which are going to be
|
||
+ discarded. This would require modifying the backend linker for
|
||
+ each backend which might set the SEC_LINK_ONCE flag. If we do
|
||
+ this, we should probably handle SEC_EXCLUDE in the same way. */
|
||
+
|
||
+ bfd_map_over_sections (entry->the_bfd, section_already_linked, entry);
|
||
+}
|
||
+
|
||
+void
|
||
+lang_add_output (const char *name, int from_script)
|
||
+{
|
||
+ /* Make -o on command line override OUTPUT in script. */
|
||
+ if (!had_output_filename || !from_script)
|
||
+ {
|
||
+ output_filename = name;
|
||
+ had_output_filename = true;
|
||
+ }
|
||
+}
|
||
+
|
||
+lang_output_section_statement_type *
|
||
+lang_enter_output_section_statement (const char *output_section_statement_name,
|
||
+ etree_type *address_exp,
|
||
+ enum section_type sectype,
|
||
+ etree_type *sectype_value,
|
||
+ etree_type *align,
|
||
+ etree_type *subalign,
|
||
+ etree_type *ebase,
|
||
+ int constraint,
|
||
+ int align_with_input)
|
||
+{
|
||
+ lang_output_section_statement_type *os;
|
||
+
|
||
+ os = lang_output_section_statement_lookup (output_section_statement_name,
|
||
+ constraint, 2);
|
||
+ current_section = os;
|
||
+
|
||
+ if (os->addr_tree == NULL)
|
||
+ {
|
||
+ os->addr_tree = address_exp;
|
||
+ }
|
||
+ os->sectype = sectype;
|
||
+ if (sectype == type_section || sectype == typed_readonly_section)
|
||
+ os->sectype_value = sectype_value;
|
||
+ else if (sectype == noload_section)
|
||
+ os->flags = SEC_NEVER_LOAD;
|
||
+ else
|
||
+ os->flags = SEC_NO_FLAGS;
|
||
+ os->block_value = 1;
|
||
+
|
||
+ /* Make next things chain into subchain of this. */
|
||
+ push_stat_ptr (&os->children);
|
||
+
|
||
+ os->align_lma_with_input = align_with_input == ALIGN_WITH_INPUT;
|
||
+ if (os->align_lma_with_input && align != NULL)
|
||
+ einfo (_("%F%P:%pS: error: align with input and explicit align specified\n"),
|
||
+ NULL);
|
||
+
|
||
+ os->subsection_alignment = subalign;
|
||
+ os->section_alignment = align;
|
||
+
|
||
+ os->load_base = ebase;
|
||
+ return os;
|
||
+}
|
||
+
|
||
+void
|
||
+lang_final (void)
|
||
+{
|
||
+ lang_output_statement_type *new_stmt;
|
||
+
|
||
+ new_stmt = new_stat (lang_output_statement, stat_ptr);
|
||
+ new_stmt->name = output_filename;
|
||
+}
|
||
+
|
||
+/* Reset the current counters in the regions. */
|
||
+
|
||
+void
|
||
+lang_reset_memory_regions (void)
|
||
+{
|
||
+ lang_memory_region_type *p = lang_memory_region_list;
|
||
+ asection *o;
|
||
+ lang_output_section_statement_type *os;
|
||
+
|
||
+ for (p = lang_memory_region_list; p != NULL; p = p->next)
|
||
+ {
|
||
+ p->current = p->origin;
|
||
+ p->last_os = NULL;
|
||
+ }
|
||
+
|
||
+ for (os = (void *) lang_os_list.head;
|
||
+ os != NULL;
|
||
+ os = os->next)
|
||
+ {
|
||
+ os->processed_vma = false;
|
||
+ os->processed_lma = false;
|
||
+ }
|
||
+
|
||
+ for (o = link_info.output_bfd->sections; o != NULL; o = o->next)
|
||
+ {
|
||
+ /* Save the last size for possible use by bfd_relax_section. */
|
||
+ o->rawsize = o->size;
|
||
+ if (!(o->flags & SEC_FIXED_SIZE))
|
||
+ o->size = 0;
|
||
+ }
|
||
+}
|
||
+
|
||
+/* Worker for lang_gc_sections_1. */
|
||
+
|
||
+static void
|
||
+gc_section_callback (lang_wild_statement_type *ptr,
|
||
+ struct wildcard_list *sec ATTRIBUTE_UNUSED,
|
||
+ asection *section,
|
||
+ lang_input_statement_type *file ATTRIBUTE_UNUSED,
|
||
+ void *data ATTRIBUTE_UNUSED)
|
||
+{
|
||
+ /* If the wild pattern was marked KEEP, the member sections
|
||
+ should be as well. */
|
||
+ if (ptr->keep_sections)
|
||
+ section->flags |= SEC_KEEP;
|
||
+}
|
||
+
|
||
+/* Iterate over sections marking them against GC. */
|
||
+
|
||
+static void
|
||
+lang_gc_sections_1 (lang_statement_union_type *s)
|
||
+{
|
||
+ for (; s != NULL; s = s->header.next)
|
||
+ {
|
||
+ switch (s->header.type)
|
||
+ {
|
||
+ case lang_wild_statement_enum:
|
||
+ walk_wild (&s->wild_statement, gc_section_callback, NULL);
|
||
+ break;
|
||
+ case lang_constructors_statement_enum:
|
||
+ lang_gc_sections_1 (constructor_list.head);
|
||
+ break;
|
||
+ case lang_output_section_statement_enum:
|
||
+ lang_gc_sections_1 (s->output_section_statement.children.head);
|
||
+ break;
|
||
+ case lang_group_statement_enum:
|
||
+ lang_gc_sections_1 (s->group_statement.children.head);
|
||
+ break;
|
||
+ default:
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+}
|
||
+
|
||
+static void
|
||
+lang_gc_sections (void)
|
||
+{
|
||
+ /* Keep all sections so marked in the link script. */
|
||
+ lang_gc_sections_1 (statement_list.head);
|
||
+
|
||
+ /* SEC_EXCLUDE is ignored when doing a relocatable link, except in
|
||
+ the special case of .stabstr debug info. (See bfd/stabs.c)
|
||
+ Twiddle the flag here, to simplify later linker code. */
|
||
+ if (bfd_link_relocatable (&link_info))
|
||
+ {
|
||
+ LANG_FOR_EACH_INPUT_STATEMENT (f)
|
||
+ {
|
||
+ asection *sec;
|
||
+#if BFD_SUPPORTS_PLUGINS
|
||
+ if (f->flags.claimed)
|
||
+ continue;
|
||
+#endif
|
||
+ for (sec = f->the_bfd->sections; sec != NULL; sec = sec->next)
|
||
+ if ((sec->flags & SEC_DEBUGGING) == 0
|
||
+ || strcmp (sec->name, ".stabstr") != 0)
|
||
+ sec->flags &= ~SEC_EXCLUDE;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (link_info.gc_sections)
|
||
+ bfd_gc_sections (link_info.output_bfd, &link_info);
|
||
+}
|
||
+
|
||
+/* Worker for lang_find_relro_sections_1. */
|
||
+
|
||
+static void
|
||
+find_relro_section_callback (lang_wild_statement_type *ptr ATTRIBUTE_UNUSED,
|
||
+ struct wildcard_list *sec ATTRIBUTE_UNUSED,
|
||
+ asection *section,
|
||
+ lang_input_statement_type *file ATTRIBUTE_UNUSED,
|
||
+ void *data)
|
||
+{
|
||
+ /* Discarded, excluded and ignored sections effectively have zero
|
||
+ size. */
|
||
+ if (section->output_section != NULL
|
||
+ && section->output_section->owner == link_info.output_bfd
|
||
+ && (section->output_section->flags & SEC_EXCLUDE) == 0
|
||
+ && !IGNORE_SECTION (section)
|
||
+ && section->size != 0)
|
||
+ {
|
||
+ bool *has_relro_section = (bool *) data;
|
||
+ *has_relro_section = true;
|
||
+ }
|
||
+}
|
||
+
|
||
+/* Iterate over sections for relro sections. */
|
||
+
|
||
+static void
|
||
+lang_find_relro_sections_1 (lang_statement_union_type *s,
|
||
+ bool *has_relro_section)
|
||
+{
|
||
+ if (*has_relro_section)
|
||
+ return;
|
||
+
|
||
+ for (; s != NULL; s = s->header.next)
|
||
+ {
|
||
+ if (s == expld.dataseg.relro_end_stat)
|
||
+ break;
|
||
+
|
||
+ switch (s->header.type)
|
||
+ {
|
||
+ case lang_wild_statement_enum:
|
||
+ walk_wild (&s->wild_statement,
|
||
+ find_relro_section_callback,
|
||
+ has_relro_section);
|
||
+ break;
|
||
+ case lang_constructors_statement_enum:
|
||
+ lang_find_relro_sections_1 (constructor_list.head,
|
||
+ has_relro_section);
|
||
+ break;
|
||
+ case lang_output_section_statement_enum:
|
||
+ lang_find_relro_sections_1 (s->output_section_statement.children.head,
|
||
+ has_relro_section);
|
||
+ break;
|
||
+ case lang_group_statement_enum:
|
||
+ lang_find_relro_sections_1 (s->group_statement.children.head,
|
||
+ has_relro_section);
|
||
+ break;
|
||
+ default:
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+}
|
||
+
|
||
+static void
|
||
+lang_find_relro_sections (void)
|
||
+{
|
||
+ bool has_relro_section = false;
|
||
+
|
||
+ /* Check all sections in the link script. */
|
||
+
|
||
+ lang_find_relro_sections_1 (expld.dataseg.relro_start_stat,
|
||
+ &has_relro_section);
|
||
+
|
||
+ if (!has_relro_section)
|
||
+ link_info.relro = false;
|
||
+}
|
||
+
|
||
+/* Relax all sections until bfd_relax_section gives up. */
|
||
+
|
||
+void
|
||
+lang_relax_sections (bool need_layout)
|
||
+{
|
||
+ /* NB: Also enable relaxation to layout sections for DT_RELR. */
|
||
+ if (RELAXATION_ENABLED || link_info.enable_dt_relr)
|
||
+ {
|
||
+ /* We may need more than one relaxation pass. */
|
||
+ int i = link_info.relax_pass;
|
||
+
|
||
+ /* The backend can use it to determine the current pass. */
|
||
+ link_info.relax_pass = 0;
|
||
+
|
||
+ while (i--)
|
||
+ {
|
||
+ /* Keep relaxing until bfd_relax_section gives up. */
|
||
+ bool relax_again;
|
||
+
|
||
+ link_info.relax_trip = -1;
|
||
+ do
|
||
+ {
|
||
+ link_info.relax_trip++;
|
||
+
|
||
+ /* Note: pe-dll.c does something like this also. If you find
|
||
+ you need to change this code, you probably need to change
|
||
+ pe-dll.c also. DJ */
|
||
+
|
||
+ /* Do all the assignments with our current guesses as to
|
||
+ section sizes. */
|
||
+ lang_do_assignments (lang_assigning_phase_enum);
|
||
+
|
||
+ /* We must do this after lang_do_assignments, because it uses
|
||
+ size. */
|
||
+ lang_reset_memory_regions ();
|
||
+
|
||
+ /* Perform another relax pass - this time we know where the
|
||
+ globals are, so can make a better guess. */
|
||
+ relax_again = false;
|
||
+ lang_size_sections (&relax_again, false);
|
||
+ }
|
||
+ while (relax_again);
|
||
+
|
||
+ link_info.relax_pass++;
|
||
+ }
|
||
+ need_layout = true;
|
||
+ }
|
||
+
|
||
+ if (need_layout)
|
||
+ {
|
||
+ /* Final extra sizing to report errors. */
|
||
+ lang_do_assignments (lang_assigning_phase_enum);
|
||
+ lang_reset_memory_regions ();
|
||
+ lang_size_sections (NULL, true);
|
||
+ }
|
||
+}
|
||
+
|
||
+#if BFD_SUPPORTS_PLUGINS
|
||
+/* Find the insert point for the plugin's replacement files. We
|
||
+ place them after the first claimed real object file, or if the
|
||
+ first claimed object is an archive member, after the last real
|
||
+ object file immediately preceding the archive. In the event
|
||
+ no objects have been claimed at all, we return the first dummy
|
||
+ object file on the list as the insert point; that works, but
|
||
+ the callee must be careful when relinking the file_chain as it
|
||
+ is not actually on that chain, only the statement_list and the
|
||
+ input_file list; in that case, the replacement files must be
|
||
+ inserted at the head of the file_chain. */
|
||
+
|
||
+static lang_input_statement_type *
|
||
+find_replacements_insert_point (bool *before)
|
||
+{
|
||
+ lang_input_statement_type *claim1, *lastobject;
|
||
+ lastobject = (void *) input_file_chain.head;
|
||
+ for (claim1 = (void *) file_chain.head;
|
||
+ claim1 != NULL;
|
||
+ claim1 = claim1->next)
|
||
+ {
|
||
+ if (claim1->flags.claimed)
|
||
+ {
|
||
+ *before = claim1->flags.claim_archive;
|
||
+ return claim1->flags.claim_archive ? lastobject : claim1;
|
||
+ }
|
||
+ /* Update lastobject if this is a real object file. */
|
||
+ if (claim1->the_bfd != NULL && claim1->the_bfd->my_archive == NULL)
|
||
+ lastobject = claim1;
|
||
+ }
|
||
+ /* No files were claimed by the plugin. Choose the last object
|
||
+ file found on the list (maybe the first, dummy entry) as the
|
||
+ insert point. */
|
||
+ *before = false;
|
||
+ return lastobject;
|
||
+}
|
||
+
|
||
+/* Find where to insert ADD, an archive element or shared library
|
||
+ added during a rescan. */
|
||
+
|
||
+static lang_input_statement_type **
|
||
+find_rescan_insertion (lang_input_statement_type *add)
|
||
+{
|
||
+ bfd *add_bfd = add->the_bfd;
|
||
+ lang_input_statement_type *f;
|
||
+ lang_input_statement_type *last_loaded = NULL;
|
||
+ lang_input_statement_type *before = NULL;
|
||
+ lang_input_statement_type **iter = NULL;
|
||
+
|
||
+ if (add_bfd->my_archive != NULL)
|
||
+ add_bfd = add_bfd->my_archive;
|
||
+
|
||
+ /* First look through the input file chain, to find an object file
|
||
+ before the one we've rescanned. Normal object files always
|
||
+ appear on both the input file chain and the file chain, so this
|
||
+ lets us get quickly to somewhere near the correct place on the
|
||
+ file chain if it is full of archive elements. Archives don't
|
||
+ appear on the file chain, but if an element has been extracted
|
||
+ then their input_statement->next points at it. */
|
||
+ for (f = (void *) input_file_chain.head;
|
||
+ f != NULL;
|
||
+ f = f->next_real_file)
|
||
+ {
|
||
+ if (f->the_bfd == add_bfd)
|
||
+ {
|
||
+ before = last_loaded;
|
||
+ if (f->next != NULL)
|
||
+ return &f->next->next;
|
||
+ }
|
||
+ if (f->the_bfd != NULL && f->next != NULL)
|
||
+ last_loaded = f;
|
||
+ }
|
||
+
|
||
+ for (iter = before ? &before->next : &file_chain.head->input_statement.next;
|
||
+ *iter != NULL;
|
||
+ iter = &(*iter)->next)
|
||
+ if (!(*iter)->flags.claim_archive
|
||
+ && (*iter)->the_bfd->my_archive == NULL)
|
||
+ break;
|
||
+
|
||
+ return iter;
|
||
+}
|
||
+
|
||
+/* Insert SRCLIST into DESTLIST after given element by chaining
|
||
+ on FIELD as the next-pointer. (Counterintuitively does not need
|
||
+ a pointer to the actual after-node itself, just its chain field.) */
|
||
+
|
||
+static void
|
||
+lang_list_insert_after (lang_statement_list_type *destlist,
|
||
+ lang_statement_list_type *srclist,
|
||
+ lang_statement_union_type **field)
|
||
+{
|
||
+ *(srclist->tail) = *field;
|
||
+ *field = srclist->head;
|
||
+ if (destlist->tail == field)
|
||
+ destlist->tail = srclist->tail;
|
||
+}
|
||
+
|
||
+/* Detach new nodes added to DESTLIST since the time ORIGLIST
|
||
+ was taken as a copy of it and leave them in ORIGLIST. */
|
||
+
|
||
+static void
|
||
+lang_list_remove_tail (lang_statement_list_type *destlist,
|
||
+ lang_statement_list_type *origlist)
|
||
+{
|
||
+ union lang_statement_union **savetail;
|
||
+ /* Check that ORIGLIST really is an earlier state of DESTLIST. */
|
||
+ ASSERT (origlist->head == destlist->head);
|
||
+ savetail = origlist->tail;
|
||
+ origlist->head = *(savetail);
|
||
+ origlist->tail = destlist->tail;
|
||
+ destlist->tail = savetail;
|
||
+ *savetail = NULL;
|
||
+}
|
||
+
|
||
+static lang_statement_union_type **
|
||
+find_next_input_statement (lang_statement_union_type **s)
|
||
+{
|
||
+ for ( ; *s; s = &(*s)->header.next)
|
||
+ {
|
||
+ lang_statement_union_type **t;
|
||
+ switch ((*s)->header.type)
|
||
+ {
|
||
+ case lang_input_statement_enum:
|
||
+ return s;
|
||
+ case lang_wild_statement_enum:
|
||
+ t = &(*s)->wild_statement.children.head;
|
||
+ break;
|
||
+ case lang_group_statement_enum:
|
||
+ t = &(*s)->group_statement.children.head;
|
||
+ break;
|
||
+ case lang_output_section_statement_enum:
|
||
+ t = &(*s)->output_section_statement.children.head;
|
||
+ break;
|
||
+ default:
|
||
+ continue;
|
||
+ }
|
||
+ t = find_next_input_statement (t);
|
||
+ if (*t)
|
||
+ return t;
|
||
+ }
|
||
+ return s;
|
||
+}
|
||
+#endif /* BFD_SUPPORTS_PLUGINS */
|
||
+
|
||
+/* Add NAME to the list of garbage collection entry points. */
|
||
+
|
||
+void
|
||
+lang_add_gc_name (const char *name)
|
||
+{
|
||
+ struct bfd_sym_chain *sym;
|
||
+
|
||
+ if (name == NULL)
|
||
+ return;
|
||
+
|
||
+ sym = stat_alloc (sizeof (*sym));
|
||
+
|
||
+ sym->next = link_info.gc_sym_list;
|
||
+ sym->name = name;
|
||
+ link_info.gc_sym_list = sym;
|
||
+}
|
||
+
|
||
+/* Check relocations. */
|
||
+
|
||
+static void
|
||
+lang_check_relocs (void)
|
||
+{
|
||
+ if (link_info.check_relocs_after_open_input)
|
||
+ {
|
||
+ bfd *abfd;
|
||
+
|
||
+ for (abfd = link_info.input_bfds;
|
||
+ abfd != (bfd *) NULL; abfd = abfd->link.next)
|
||
+ if (!bfd_link_check_relocs (abfd, &link_info))
|
||
+ {
|
||
+ /* No object output, fail return. */
|
||
+ config.make_executable = false;
|
||
+ /* Note: we do not abort the loop, but rather
|
||
+ continue the scan in case there are other
|
||
+ bad relocations to report. */
|
||
+ }
|
||
+ }
|
||
+}
|
||
+
|
||
+/* Look through all output sections looking for places where we can
|
||
+ propagate forward the lma region. */
|
||
+
|
||
+static void
|
||
+lang_propagate_lma_regions (void)
|
||
+{
|
||
+ lang_output_section_statement_type *os;
|
||
+
|
||
+ for (os = (void *) lang_os_list.head;
|
||
+ os != NULL;
|
||
+ os = os->next)
|
||
+ {
|
||
+ if (os->prev != NULL
|
||
+ && os->lma_region == NULL
|
||
+ && os->load_base == NULL
|
||
+ && os->addr_tree == NULL
|
||
+ && os->region == os->prev->region)
|
||
+ os->lma_region = os->prev->lma_region;
|
||
+ }
|
||
+}
|
||
+
|
||
+static void
|
||
+warn_non_contiguous_discards (void)
|
||
+{
|
||
+ LANG_FOR_EACH_INPUT_STATEMENT (file)
|
||
+ {
|
||
+ if ((file->the_bfd->flags & (BFD_LINKER_CREATED | DYNAMIC)) != 0
|
||
+ || file->flags.just_syms)
|
||
+ continue;
|
||
+
|
||
+ for (asection *s = file->the_bfd->sections; s != NULL; s = s->next)
|
||
+ if (s->output_section == NULL
|
||
+ && (s->flags & SEC_LINKER_CREATED) == 0)
|
||
+ einfo (_("%P: warning: --enable-non-contiguous-regions "
|
||
+ "discards section `%pA' from `%pB'\n"),
|
||
+ s, file->the_bfd);
|
||
+ }
|
||
+}
|
||
+
|
||
+static void
|
||
+reset_one_wild (lang_statement_union_type *statement)
|
||
+{
|
||
+ if (statement->header.type == lang_wild_statement_enum)
|
||
+ {
|
||
+ lang_wild_statement_type *stmt = &statement->wild_statement;
|
||
+ lang_list_init (&stmt->matching_sections);
|
||
+ }
|
||
+}
|
||
+
|
||
+static void
|
||
+reset_resolved_wilds (void)
|
||
+{
|
||
+ lang_for_each_statement (reset_one_wild);
|
||
+}
|
||
+
|
||
+void
|
||
+lang_process (void)
|
||
+{
|
||
+ /* Finalize dynamic list. */
|
||
+ if (link_info.dynamic_list)
|
||
+ lang_finalize_version_expr_head (&link_info.dynamic_list->head);
|
||
+
|
||
+ current_target = default_target;
|
||
+
|
||
+ /* Open the output file. */
|
||
+ lang_for_each_statement (ldlang_open_output);
|
||
+ init_opb (NULL);
|
||
+
|
||
+ ldemul_create_output_section_statements ();
|
||
+
|
||
+ /* Add to the hash table all undefineds on the command line. */
|
||
+ lang_place_undefineds ();
|
||
+
|
||
+ if (!bfd_section_already_linked_table_init ())
|
||
+ einfo (_("%F%P: can not create hash table: %E\n"));
|
||
+
|
||
+ /* A first pass through the memory regions ensures that if any region
|
||
+ references a symbol for its origin or length then this symbol will be
|
||
+ added to the symbol table. Having these symbols in the symbol table
|
||
+ means that when we call open_input_bfds PROVIDE statements will
|
||
+ trigger to provide any needed symbols. The regions origins and
|
||
+ lengths are not assigned as a result of this call. */
|
||
+ lang_do_memory_regions (false);
|
||
+
|
||
+ /* Create a bfd for each input file. */
|
||
+ current_target = default_target;
|
||
+ lang_statement_iteration++;
|
||
+ open_input_bfds (statement_list.head, OPEN_BFD_NORMAL);
|
||
+
|
||
+ /* Now that open_input_bfds has processed assignments and provide
|
||
+ statements we can give values to symbolic origin/length now. */
|
||
+ lang_do_memory_regions (true);
|
||
+
|
||
+ ldemul_before_plugin_all_symbols_read ();
|
||
+
|
||
+#if BFD_SUPPORTS_PLUGINS
|
||
+ if (link_info.lto_plugin_active)
|
||
+ {
|
||
+ lang_statement_list_type added;
|
||
+ lang_statement_list_type files, inputfiles;
|
||
+
|
||
+ /* Now all files are read, let the plugin(s) decide if there
|
||
+ are any more to be added to the link before we call the
|
||
+ emulation's after_open hook. We create a private list of
|
||
+ input statements for this purpose, which we will eventually
|
||
+ insert into the global statement list after the first claimed
|
||
+ file. */
|
||
+ added = *stat_ptr;
|
||
+ /* We need to manipulate all three chains in synchrony. */
|
||
+ files = file_chain;
|
||
+ inputfiles = input_file_chain;
|
||
+ if (plugin_call_all_symbols_read ())
|
||
+ einfo (_("%F%P: %s: plugin reported error after all symbols read\n"),
|
||
+ plugin_error_plugin ());
|
||
+ link_info.lto_all_symbols_read = true;
|
||
+ /* Open any newly added files, updating the file chains. */
|
||
+ plugin_undefs = link_info.hash->undefs_tail;
|
||
+ open_input_bfds (*added.tail, OPEN_BFD_NORMAL);
|
||
+ if (plugin_undefs == link_info.hash->undefs_tail)
|
||
+ plugin_undefs = NULL;
|
||
+ /* Restore the global list pointer now they have all been added. */
|
||
+ lang_list_remove_tail (stat_ptr, &added);
|
||
+ /* And detach the fresh ends of the file lists. */
|
||
+ lang_list_remove_tail (&file_chain, &files);
|
||
+ lang_list_remove_tail (&input_file_chain, &inputfiles);
|
||
+ /* Were any new files added? */
|
||
+ if (added.head != NULL)
|
||
+ {
|
||
+ /* If so, we will insert them into the statement list immediately
|
||
+ after the first input file that was claimed by the plugin,
|
||
+ unless that file was an archive in which case it is inserted
|
||
+ immediately before. */
|
||
+ bool before;
|
||
+ lang_statement_union_type **prev;
|
||
+ plugin_insert = find_replacements_insert_point (&before);
|
||
+ /* If a plugin adds input files without having claimed any, we
|
||
+ don't really have a good idea where to place them. Just putting
|
||
+ them at the start or end of the list is liable to leave them
|
||
+ outside the crtbegin...crtend range. */
|
||
+ ASSERT (plugin_insert != NULL);
|
||
+ /* Splice the new statement list into the old one. */
|
||
+ prev = &plugin_insert->header.next;
|
||
+ if (before)
|
||
+ {
|
||
+ prev = find_next_input_statement (prev);
|
||
+ if (*prev != (void *) plugin_insert->next_real_file)
|
||
+ {
|
||
+ /* We didn't find the expected input statement.
|
||
+ Fall back to adding after plugin_insert. */
|
||
+ prev = &plugin_insert->header.next;
|
||
+ }
|
||
+ }
|
||
+ lang_list_insert_after (stat_ptr, &added, prev);
|
||
+ /* Likewise for the file chains. */
|
||
+ lang_list_insert_after (&input_file_chain, &inputfiles,
|
||
+ (void *) &plugin_insert->next_real_file);
|
||
+ /* We must be careful when relinking file_chain; we may need to
|
||
+ insert the new files at the head of the list if the insert
|
||
+ point chosen is the dummy first input file. */
|
||
+ if (plugin_insert->filename)
|
||
+ lang_list_insert_after (&file_chain, &files,
|
||
+ (void *) &plugin_insert->next);
|
||
+ else
|
||
+ lang_list_insert_after (&file_chain, &files, &file_chain.head);
|
||
+
|
||
+ /* Rescan archives in case new undefined symbols have appeared. */
|
||
+ files = file_chain;
|
||
+ lang_statement_iteration++;
|
||
+ open_input_bfds (statement_list.head, OPEN_BFD_RESCAN);
|
||
+ lang_list_remove_tail (&file_chain, &files);
|
||
+ while (files.head != NULL)
|
||
+ {
|
||
+ lang_input_statement_type **insert;
|
||
+ lang_input_statement_type **iter, *temp;
|
||
+ bfd *my_arch;
|
||
+
|
||
+ insert = find_rescan_insertion (&files.head->input_statement);
|
||
+ /* All elements from an archive can be added at once. */
|
||
+ iter = &files.head->input_statement.next;
|
||
+ my_arch = files.head->input_statement.the_bfd->my_archive;
|
||
+ if (my_arch != NULL)
|
||
+ for (; *iter != NULL; iter = &(*iter)->next)
|
||
+ if ((*iter)->the_bfd->my_archive != my_arch)
|
||
+ break;
|
||
+ temp = *insert;
|
||
+ *insert = &files.head->input_statement;
|
||
+ files.head = (lang_statement_union_type *) *iter;
|
||
+ *iter = temp;
|
||
+ if (file_chain.tail == (lang_statement_union_type **) insert)
|
||
+ file_chain.tail = (lang_statement_union_type **) iter;
|
||
+ if (my_arch != NULL)
|
||
+ {
|
||
+ lang_input_statement_type *parent = bfd_usrdata (my_arch);
|
||
+ if (parent != NULL)
|
||
+ parent->next = (lang_input_statement_type *)
|
||
+ ((char *) iter
|
||
+ - offsetof (lang_input_statement_type, next));
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+#endif /* BFD_SUPPORTS_PLUGINS */
|
||
+
|
||
+ struct bfd_sym_chain **sym = &link_info.gc_sym_list;
|
||
+ while (*sym)
|
||
+ sym = &(*sym)->next;
|
||
+
|
||
+ *sym = &entry_symbol;
|
||
+
|
||
+ if (entry_symbol.name == NULL)
|
||
+ {
|
||
+ *sym = ldlang_undef_chain_list_head;
|
||
+
|
||
+ /* entry_symbol is normally initialised by an ENTRY definition in the
|
||
+ linker script or the -e command line option. But if neither of
|
||
+ these have been used, the target specific backend may still have
|
||
+ provided an entry symbol via a call to lang_default_entry().
|
||
+ Unfortunately this value will not be processed until lang_end()
|
||
+ is called, long after this function has finished. So detect this
|
||
+ case here and add the target's entry symbol to the list of starting
|
||
+ points for garbage collection resolution. */
|
||
+ lang_add_gc_name (entry_symbol_default);
|
||
+ }
|
||
+
|
||
+ lang_add_gc_name (link_info.init_function);
|
||
+ lang_add_gc_name (link_info.fini_function);
|
||
+
|
||
+ ldemul_after_open ();
|
||
+ if (config.map_file != NULL)
|
||
+ lang_print_asneeded ();
|
||
+
|
||
+ ldlang_open_ctf ();
|
||
+
|
||
+ bfd_section_already_linked_table_free ();
|
||
+
|
||
+ /* Make sure that we're not mixing architectures. We call this
|
||
+ after all the input files have been opened, but before we do any
|
||
+ other processing, so that any operations merge_private_bfd_data
|
||
+ does on the output file will be known during the rest of the
|
||
+ link. */
|
||
+ lang_check ();
|
||
+
|
||
+ /* Handle .exports instead of a version script if we're told to do so. */
|
||
+ if (command_line.version_exports_section)
|
||
+ lang_do_version_exports_section ();
|
||
+
|
||
+ /* Build all sets based on the information gathered from the input
|
||
+ files. */
|
||
+ ldctor_build_sets ();
|
||
+
|
||
+ lang_symbol_tweaks ();
|
||
+
|
||
+ /* PR 13683: We must rerun the assignments prior to running garbage
|
||
+ collection in order to make sure that all symbol aliases are resolved. */
|
||
+ lang_do_assignments (lang_mark_phase_enum);
|
||
+ expld.phase = lang_first_phase_enum;
|
||
+
|
||
+ /* Size up the common data. */
|
||
+ lang_common ();
|
||
+
|
||
+ if (0)
|
||
+ debug_prefix_tree ();
|
||
+
|
||
+ resolve_wilds ();
|
||
+
|
||
+ /* Remove unreferenced sections if asked to. */
|
||
+ lang_gc_sections ();
|
||
+
|
||
+ lang_mark_undefineds ();
|
||
+
|
||
+ /* Check relocations. */
|
||
+ lang_check_relocs ();
|
||
+
|
||
+ ldemul_after_check_relocs ();
|
||
+
|
||
+ /* There might have been new sections created (e.g. as result of
|
||
+ checking relocs to need a .got, or suchlike), so to properly order
|
||
+ them into our lists of matching sections reset them here. */
|
||
+ reset_resolved_wilds ();
|
||
+ resolve_wilds ();
|
||
+
|
||
+ /* Update wild statements in case the user gave --sort-section.
|
||
+ Note how the option might have come after the linker script and
|
||
+ so couldn't have been set when the wild statements were created. */
|
||
+ update_wild_statements (statement_list.head);
|
||
+
|
||
+ /* Run through the contours of the script and attach input sections
|
||
+ to the correct output sections. */
|
||
+ lang_statement_iteration++;
|
||
+ map_input_to_output_sections (statement_list.head, NULL, NULL);
|
||
+
|
||
+ /* Start at the statement immediately after the special abs_section
|
||
+ output statement, so that it isn't reordered. */
|
||
+ process_insert_statements (&lang_os_list.head->header.next);
|
||
+
|
||
+ ldemul_before_place_orphans ();
|
||
+
|
||
+ /* Find any sections not attached explicitly and handle them. */
|
||
+ lang_place_orphans ();
|
||
+
|
||
+ if (!bfd_link_relocatable (&link_info))
|
||
+ {
|
||
+ asection *found;
|
||
+
|
||
+ /* Merge SEC_MERGE sections. This has to be done after GC of
|
||
+ sections, so that GCed sections are not merged, but before
|
||
+ assigning dynamic symbols, since removing whole input sections
|
||
+ is hard then. */
|
||
+ bfd_merge_sections (link_info.output_bfd, &link_info);
|
||
+
|
||
+ /* Look for a text section and set the readonly attribute in it. */
|
||
+ found = bfd_get_section_by_name (link_info.output_bfd, ".text");
|
||
+
|
||
+ if (found != NULL)
|
||
+ {
|
||
+ if (config.text_read_only)
|
||
+ found->flags |= SEC_READONLY;
|
||
+ else
|
||
+ found->flags &= ~SEC_READONLY;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ /* Merge together CTF sections. After this, only the symtab-dependent
|
||
+ function and data object sections need adjustment. */
|
||
+ lang_merge_ctf ();
|
||
+
|
||
+ /* Emit the CTF, iff the emulation doesn't need to do late emission after
|
||
+ examining things laid out late, like the strtab. */
|
||
+ lang_write_ctf (0);
|
||
+
|
||
+ /* Copy forward lma regions for output sections in same lma region. */
|
||
+ lang_propagate_lma_regions ();
|
||
+
|
||
+ /* Defining __start/__stop symbols early for --gc-sections to work
|
||
+ around a glibc build problem can result in these symbols being
|
||
+ defined when they should not be. Fix them now. */
|
||
+ if (config.build_constructors)
|
||
+ lang_undef_start_stop ();
|
||
+
|
||
+ /* Define .startof./.sizeof. symbols with preliminary values before
|
||
+ dynamic symbols are created. */
|
||
+ if (!bfd_link_relocatable (&link_info))
|
||
+ lang_init_startof_sizeof ();
|
||
+
|
||
+ /* Do anything special before sizing sections. This is where ELF
|
||
+ and other back-ends size dynamic sections. */
|
||
+ ldemul_before_allocation ();
|
||
+
|
||
+ /* We must record the program headers before we try to fix the
|
||
+ section positions, since they will affect SIZEOF_HEADERS. */
|
||
+ lang_record_phdrs ();
|
||
+
|
||
+ /* Check relro sections. */
|
||
+ if (link_info.relro && !bfd_link_relocatable (&link_info))
|
||
+ lang_find_relro_sections ();
|
||
+
|
||
+ /* Size up the sections. */
|
||
+ lang_size_sections (NULL, !RELAXATION_ENABLED);
|
||
+
|
||
+ /* See if anything special should be done now we know how big
|
||
+ everything is. This is where relaxation is done. */
|
||
+ ldemul_after_allocation ();
|
||
+
|
||
+ /* Fix any __start, __stop, .startof. or .sizeof. symbols. */
|
||
+ lang_finalize_start_stop ();
|
||
+
|
||
+ /* Do all the assignments again, to report errors. Assignment
|
||
+ statements are processed multiple times, updating symbols; In
|
||
+ open_input_bfds, lang_do_assignments, and lang_size_sections.
|
||
+ Since lang_relax_sections calls lang_do_assignments, symbols are
|
||
+ also updated in ldemul_after_allocation. */
|
||
+ lang_do_assignments (lang_final_phase_enum);
|
||
+
|
||
+ ldemul_finish ();
|
||
+
|
||
+ /* Convert absolute symbols to section relative. */
|
||
+ ldexp_finalize_syms ();
|
||
+
|
||
+ /* Make sure that the section addresses make sense. */
|
||
+ if (command_line.check_section_addresses)
|
||
+ lang_check_section_addresses ();
|
||
+
|
||
+ if (link_info.non_contiguous_regions
|
||
+ && link_info.non_contiguous_regions_warnings)
|
||
+ warn_non_contiguous_discards ();
|
||
+
|
||
+ /* Check any required symbols are known. */
|
||
+ ldlang_check_require_defined_symbols ();
|
||
+
|
||
+ lang_end ();
|
||
+}
|
||
+
|
||
+void
|
||
+lang_add_version_string (void)
|
||
+{
|
||
+ if (! enable_linker_version)
|
||
+ return;
|
||
+
|
||
+ const char * str = "GNU ld ";
|
||
+ int len = strlen (str);
|
||
+ int i;
|
||
+
|
||
+ for (i = 0 ; i < len ; i++)
|
||
+ lang_add_data (BYTE, exp_intop (str[i]));
|
||
+
|
||
+ str = BFD_VERSION_STRING;
|
||
+ len = strlen (str);
|
||
+
|
||
+ for (i = 0 ; i < len ; i++)
|
||
+ lang_add_data (BYTE, exp_intop (str[i]));
|
||
+
|
||
+ lang_add_data (BYTE, exp_intop ('\0'));
|
||
+}
|
||
+
|
||
+/* EXPORTED TO YACC */
|
||
+
|
||
+void
|
||
+lang_add_wild (struct wildcard_spec *filespec,
|
||
+ struct wildcard_list *section_list,
|
||
+ bool keep_sections)
|
||
+{
|
||
+ struct wildcard_list *curr, *next;
|
||
+ lang_wild_statement_type *new_stmt;
|
||
+ bool any_specs_sorted = false;
|
||
+
|
||
+ /* Reverse the list as the parser puts it back to front. */
|
||
+ for (curr = section_list, section_list = NULL;
|
||
+ curr != NULL;
|
||
+ section_list = curr, curr = next)
|
||
+ {
|
||
+ if (curr->spec.sorted != none && curr->spec.sorted != by_none)
|
||
+ any_specs_sorted = true;
|
||
+ next = curr->next;
|
||
+ curr->next = section_list;
|
||
+ }
|
||
+
|
||
+ if (filespec != NULL && filespec->name != NULL)
|
||
+ {
|
||
+ if (strcmp (filespec->name, "*") == 0)
|
||
+ filespec->name = NULL;
|
||
+ else if (!wildcardp (filespec->name))
|
||
+ lang_has_input_file = true;
|
||
+ }
|
||
+
|
||
+ new_stmt = new_stat (lang_wild_statement, stat_ptr);
|
||
+ new_stmt->filename = NULL;
|
||
+ new_stmt->filenames_sorted = false;
|
||
+ new_stmt->any_specs_sorted = any_specs_sorted;
|
||
+ new_stmt->section_flag_list = NULL;
|
||
+ new_stmt->exclude_name_list = NULL;
|
||
+ if (filespec != NULL)
|
||
+ {
|
||
+ new_stmt->filename = filespec->name;
|
||
+ new_stmt->filenames_sorted = filespec->sorted == by_name;
|
||
+ new_stmt->section_flag_list = filespec->section_flag_list;
|
||
+ new_stmt->exclude_name_list = filespec->exclude_name_list;
|
||
+ }
|
||
+ new_stmt->section_list = section_list;
|
||
+ new_stmt->keep_sections = keep_sections;
|
||
+ lang_list_init (&new_stmt->children);
|
||
+ lang_list_init (&new_stmt->matching_sections);
|
||
+ analyze_walk_wild_section_handler (new_stmt);
|
||
+ if (0)
|
||
+ {
|
||
+ printf ("wild %s(", new_stmt->filename ? new_stmt->filename : "*");
|
||
+ for (curr = new_stmt->section_list; curr; curr = curr->next)
|
||
+ printf ("%s ", curr->spec.name ? curr->spec.name : "*");
|
||
+ printf (")\n");
|
||
+ }
|
||
+}
|
||
+
|
||
+void
|
||
+lang_section_start (const char *name, etree_type *address,
|
||
+ const segment_type *segment)
|
||
+{
|
||
+ lang_address_statement_type *ad;
|
||
+
|
||
+ ad = new_stat (lang_address_statement, stat_ptr);
|
||
+ ad->section_name = name;
|
||
+ ad->address = address;
|
||
+ ad->segment = segment;
|
||
+}
|
||
+
|
||
+/* Set the start symbol to NAME. CMDLINE is nonzero if this is called
|
||
+ because of a -e argument on the command line, or zero if this is
|
||
+ called by ENTRY in a linker script. Command line arguments take
|
||
+ precedence. */
|
||
+
|
||
+void
|
||
+lang_add_entry (const char *name, bool cmdline)
|
||
+{
|
||
+ if (entry_symbol.name == NULL
|
||
+ || cmdline
|
||
+ || !entry_from_cmdline)
|
||
+ {
|
||
+ entry_symbol.name = name;
|
||
+ entry_from_cmdline = cmdline;
|
||
+ }
|
||
+}
|
||
+
|
||
+/* Set the default start symbol to NAME. .em files should use this,
|
||
+ not lang_add_entry, to override the use of "start" if neither the
|
||
+ linker script nor the command line specifies an entry point. NAME
|
||
+ must be permanently allocated. */
|
||
+void
|
||
+lang_default_entry (const char *name)
|
||
+{
|
||
+ entry_symbol_default = name;
|
||
+}
|
||
+
|
||
+void
|
||
+lang_add_target (const char *name)
|
||
+{
|
||
+ lang_target_statement_type *new_stmt;
|
||
+
|
||
+ new_stmt = new_stat (lang_target_statement, stat_ptr);
|
||
+ new_stmt->target = name;
|
||
+}
|
||
+
|
||
+void
|
||
+lang_add_map (const char *name)
|
||
+{
|
||
+ while (*name)
|
||
+ {
|
||
+ switch (*name)
|
||
+ {
|
||
+ case 'F':
|
||
+ map_option_f = true;
|
||
+ break;
|
||
+ }
|
||
+ name++;
|
||
+ }
|
||
+}
|
||
+
|
||
+void
|
||
+lang_add_fill (fill_type *fill)
|
||
+{
|
||
+ lang_fill_statement_type *new_stmt;
|
||
+
|
||
+ new_stmt = new_stat (lang_fill_statement, stat_ptr);
|
||
+ new_stmt->fill = fill;
|
||
+}
|
||
+
|
||
+void
|
||
+lang_add_data (int type, union etree_union *exp)
|
||
+{
|
||
+ lang_data_statement_type *new_stmt;
|
||
+
|
||
+ new_stmt = new_stat (lang_data_statement, stat_ptr);
|
||
+ new_stmt->exp = exp;
|
||
+ new_stmt->type = type;
|
||
+}
|
||
+
|
||
+void
|
||
+lang_add_string (const char *s)
|
||
+{
|
||
+ bfd_vma len = strlen (s);
|
||
+ bfd_vma i;
|
||
+ bool escape = false;
|
||
+
|
||
+ /* Add byte expressions until end of string. */
|
||
+ for (i = 0 ; i < len; i++)
|
||
+ {
|
||
+ char c = *s++;
|
||
+
|
||
+ if (escape)
|
||
+ {
|
||
+ switch (c)
|
||
+ {
|
||
+ default:
|
||
+ /* Ignore the escape. */
|
||
+ break;
|
||
+
|
||
+ case 'n': c = '\n'; break;
|
||
+ case 'r': c = '\r'; break;
|
||
+ case 't': c = '\t'; break;
|
||
+
|
||
+ case '0':
|
||
+ case '1':
|
||
+ case '2':
|
||
+ case '3':
|
||
+ case '4':
|
||
+ case '5':
|
||
+ case '6':
|
||
+ case '7':
|
||
+ /* We have an octal number. */
|
||
+ {
|
||
+ unsigned int value = c - '0';
|
||
+
|
||
+ c = *s;
|
||
+ if ((c >= '0') && (c <= '7'))
|
||
+ {
|
||
+ value <<= 3;
|
||
+ value += (c - '0');
|
||
+ i++;
|
||
+ s++;
|
||
+
|
||
+ c = *s;
|
||
+ if ((c >= '0') && (c <= '7'))
|
||
+ {
|
||
+ value <<= 3;
|
||
+ value += (c - '0');
|
||
+ i++;
|
||
+ s++;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (value > 0xff)
|
||
+ {
|
||
+ /* octal: \777 is treated as '\077' + '7' */
|
||
+ value >>= 3;
|
||
+ i--;
|
||
+ s--;
|
||
+ }
|
||
+
|
||
+ c = value;
|
||
+ }
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ lang_add_data (BYTE, exp_intop (c));
|
||
+ escape = false;
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ if (c == '\\')
|
||
+ escape = true;
|
||
+ else
|
||
+ lang_add_data (BYTE, exp_intop (c));
|
||
+ }
|
||
+ }
|
||
+
|
||
+ /* Remeber to terminate the string. */
|
||
+ lang_add_data (BYTE, exp_intop (0));
|
||
+}
|
||
+
|
||
+/* Create a new reloc statement. RELOC is the BFD relocation type to
|
||
+ generate. HOWTO is the corresponding howto structure (we could
|
||
+ look this up, but the caller has already done so). SECTION is the
|
||
+ section to generate a reloc against, or NAME is the name of the
|
||
+ symbol to generate a reloc against. Exactly one of SECTION and
|
||
+ NAME must be NULL. ADDEND is an expression for the addend. */
|
||
+
|
||
+void
|
||
+lang_add_reloc (bfd_reloc_code_real_type reloc,
|
||
+ reloc_howto_type *howto,
|
||
+ asection *section,
|
||
+ const char *name,
|
||
+ union etree_union *addend)
|
||
+{
|
||
+ lang_reloc_statement_type *p = new_stat (lang_reloc_statement, stat_ptr);
|
||
+
|
||
+ p->reloc = reloc;
|
||
+ p->howto = howto;
|
||
+ p->section = section;
|
||
+ p->name = name;
|
||
+ p->addend_exp = addend;
|
||
+
|
||
+ p->addend_value = 0;
|
||
+ p->output_section = NULL;
|
||
+ p->output_offset = 0;
|
||
+}
|
||
+
|
||
+lang_assignment_statement_type *
|
||
+lang_add_assignment (etree_type *exp)
|
||
+{
|
||
+ lang_assignment_statement_type *new_stmt;
|
||
+
|
||
+ new_stmt = new_stat (lang_assignment_statement, stat_ptr);
|
||
+ new_stmt->exp = exp;
|
||
+ return new_stmt;
|
||
+}
|
||
+
|
||
+void
|
||
+lang_add_attribute (enum statement_enum attribute)
|
||
+{
|
||
+ new_statement (attribute, sizeof (lang_statement_header_type), stat_ptr);
|
||
+}
|
||
+
|
||
+void
|
||
+lang_startup (const char *name)
|
||
+{
|
||
+ if (first_file->filename != NULL)
|
||
+ {
|
||
+ einfo (_("%F%P: multiple STARTUP files\n"));
|
||
+ }
|
||
+ first_file->filename = name;
|
||
+ first_file->local_sym_name = name;
|
||
+ first_file->flags.real = true;
|
||
+}
|
||
+
|
||
+void
|
||
+lang_float (bool maybe)
|
||
+{
|
||
+ lang_float_flag = maybe;
|
||
+}
|
||
+
|
||
+
|
||
+/* Work out the load- and run-time regions from a script statement, and
|
||
+ store them in *LMA_REGION and *REGION respectively.
|
||
+
|
||
+ MEMSPEC is the name of the run-time region, or the value of
|
||
+ DEFAULT_MEMORY_REGION if the statement didn't specify one.
|
||
+ LMA_MEMSPEC is the name of the load-time region, or null if the
|
||
+ statement didn't specify one.HAVE_LMA_P is TRUE if the statement
|
||
+ had an explicit load address.
|
||
+
|
||
+ It is an error to specify both a load region and a load address. */
|
||
+
|
||
+static void
|
||
+lang_get_regions (lang_memory_region_type **region,
|
||
+ lang_memory_region_type **lma_region,
|
||
+ const char *memspec,
|
||
+ const char *lma_memspec,
|
||
+ bool have_lma,
|
||
+ bool have_vma)
|
||
+{
|
||
+ *lma_region = lang_memory_region_lookup (lma_memspec, false);
|
||
+
|
||
+ /* If no runtime region or VMA has been specified, but the load region
|
||
+ has been specified, then use the load region for the runtime region
|
||
+ as well. */
|
||
+ if (lma_memspec != NULL
|
||
+ && !have_vma
|
||
+ && strcmp (memspec, DEFAULT_MEMORY_REGION) == 0)
|
||
+ *region = *lma_region;
|
||
+ else
|
||
+ *region = lang_memory_region_lookup (memspec, false);
|
||
+
|
||
+ if (have_lma && lma_memspec != 0)
|
||
+ einfo (_("%X%P:%pS: section has both a load address and a load region\n"),
|
||
+ NULL);
|
||
+}
|
||
+
|
||
+void
|
||
+lang_leave_output_section_statement (fill_type *fill, const char *memspec,
|
||
+ lang_output_section_phdr_list *phdrs,
|
||
+ const char *lma_memspec)
|
||
+{
|
||
+ lang_get_regions (¤t_section->region,
|
||
+ ¤t_section->lma_region,
|
||
+ memspec, lma_memspec,
|
||
+ current_section->load_base != NULL,
|
||
+ current_section->addr_tree != NULL);
|
||
+
|
||
+ current_section->fill = fill;
|
||
+ current_section->phdrs = phdrs;
|
||
+ pop_stat_ptr ();
|
||
+}
|
||
+
|
||
+/* Set the output format type. -oformat overrides scripts. */
|
||
+
|
||
+void
|
||
+lang_add_output_format (const char *format,
|
||
+ const char *big,
|
||
+ const char *little,
|
||
+ int from_script)
|
||
+{
|
||
+ if (output_target == NULL || !from_script)
|
||
+ {
|
||
+ if (command_line.endian == ENDIAN_BIG
|
||
+ && big != NULL)
|
||
+ format = big;
|
||
+ else if (command_line.endian == ENDIAN_LITTLE
|
||
+ && little != NULL)
|
||
+ format = little;
|
||
+
|
||
+ output_target = format;
|
||
+ }
|
||
+}
|
||
+
|
||
+void
|
||
+lang_add_insert (const char *where, int is_before)
|
||
+{
|
||
+ lang_insert_statement_type *new_stmt;
|
||
+
|
||
+ new_stmt = new_stat (lang_insert_statement, stat_ptr);
|
||
+ new_stmt->where = where;
|
||
+ new_stmt->is_before = is_before;
|
||
+ saved_script_handle = previous_script_handle;
|
||
+}
|
||
+
|
||
+/* Enter a group. This creates a new lang_group_statement, and sets
|
||
+ stat_ptr to build new statements within the group. */
|
||
+
|
||
+void
|
||
+lang_enter_group (void)
|
||
+{
|
||
+ lang_group_statement_type *g;
|
||
+
|
||
+ g = new_stat (lang_group_statement, stat_ptr);
|
||
+ lang_list_init (&g->children);
|
||
+ push_stat_ptr (&g->children);
|
||
+}
|
||
+
|
||
+/* Leave a group. This just resets stat_ptr to start writing to the
|
||
+ regular list of statements again. Note that this will not work if
|
||
+ groups can occur inside anything else which can adjust stat_ptr,
|
||
+ but currently they can't. */
|
||
+
|
||
+void
|
||
+lang_leave_group (void)
|
||
+{
|
||
+ pop_stat_ptr ();
|
||
+}
|
||
+
|
||
+/* Add a new program header. This is called for each entry in a PHDRS
|
||
+ command in a linker script. */
|
||
+
|
||
+void
|
||
+lang_new_phdr (const char *name,
|
||
+ etree_type *type,
|
||
+ bool filehdr,
|
||
+ bool phdrs,
|
||
+ etree_type *at,
|
||
+ etree_type *flags)
|
||
+{
|
||
+ struct lang_phdr *n, **pp;
|
||
+ bool hdrs;
|
||
+
|
||
+ n = stat_alloc (sizeof (struct lang_phdr));
|
||
+ n->next = NULL;
|
||
+ n->name = name;
|
||
+ n->type = exp_get_vma (type, 0, "program header type");
|
||
+ n->filehdr = filehdr;
|
||
+ n->phdrs = phdrs;
|
||
+ n->at = at;
|
||
+ n->flags = flags;
|
||
+
|
||
+ hdrs = n->type == 1 && (phdrs || filehdr);
|
||
+
|
||
+ for (pp = &lang_phdr_list; *pp != NULL; pp = &(*pp)->next)
|
||
+ if (hdrs
|
||
+ && (*pp)->type == 1
|
||
+ && !((*pp)->filehdr || (*pp)->phdrs))
|
||
+ {
|
||
+ einfo (_("%X%P:%pS: PHDRS and FILEHDR are not supported"
|
||
+ " when prior PT_LOAD headers lack them\n"), NULL);
|
||
+ hdrs = false;
|
||
+ }
|
||
+
|
||
+ *pp = n;
|
||
+}
|
||
+
|
||
+/* Record the program header information in the output BFD. FIXME: We
|
||
+ should not be calling an ELF specific function here. */
|
||
+
|
||
+static void
|
||
+lang_record_phdrs (void)
|
||
+{
|
||
+ unsigned int alc;
|
||
+ asection **secs;
|
||
+ lang_output_section_phdr_list *last;
|
||
+ struct lang_phdr *l;
|
||
+ lang_output_section_statement_type *os;
|
||
+
|
||
+ alc = 10;
|
||
+ secs = (asection **) xmalloc (alc * sizeof (asection *));
|
||
+ last = NULL;
|
||
+
|
||
+ for (l = lang_phdr_list; l != NULL; l = l->next)
|
||
+ {
|
||
+ unsigned int c;
|
||
+ flagword flags;
|
||
+ bfd_vma at;
|
||
+
|
||
+ c = 0;
|
||
+ for (os = (void *) lang_os_list.head;
|
||
+ os != NULL;
|
||
+ os = os->next)
|
||
+ {
|
||
+ lang_output_section_phdr_list *pl;
|
||
+
|
||
+ if (os->constraint < 0)
|
||
+ continue;
|
||
+
|
||
+ pl = os->phdrs;
|
||
+ if (pl != NULL)
|
||
+ last = pl;
|
||
+ else
|
||
+ {
|
||
+ if (os->sectype == noload_section
|
||
+ || os->bfd_section == NULL
|
||
+ || (os->bfd_section->flags & SEC_ALLOC) == 0)
|
||
+ continue;
|
||
+
|
||
+ /* Don't add orphans to PT_INTERP header. */
|
||
+ if (l->type == 3)
|
||
+ continue;
|
||
+
|
||
+ if (last == NULL)
|
||
+ {
|
||
+ lang_output_section_statement_type *tmp_os;
|
||
+
|
||
+ /* If we have not run across a section with a program
|
||
+ header assigned to it yet, then scan forwards to find
|
||
+ one. This prevents inconsistencies in the linker's
|
||
+ behaviour when a script has specified just a single
|
||
+ header and there are sections in that script which are
|
||
+ not assigned to it, and which occur before the first
|
||
+ use of that header. See here for more details:
|
||
+ http://sourceware.org/ml/binutils/2007-02/msg00291.html */
|
||
+ for (tmp_os = os; tmp_os; tmp_os = tmp_os->next)
|
||
+ if (tmp_os->phdrs)
|
||
+ {
|
||
+ last = tmp_os->phdrs;
|
||
+ break;
|
||
+ }
|
||
+ if (last == NULL)
|
||
+ einfo (_("%F%P: no sections assigned to phdrs\n"));
|
||
+ }
|
||
+ pl = last;
|
||
+ }
|
||
+
|
||
+ if (os->bfd_section == NULL)
|
||
+ continue;
|
||
+
|
||
+ for (; pl != NULL; pl = pl->next)
|
||
+ {
|
||
+ if (strcmp (pl->name, l->name) == 0)
|
||
+ {
|
||
+ if (c >= alc)
|
||
+ {
|
||
+ alc *= 2;
|
||
+ secs = (asection **) xrealloc (secs,
|
||
+ alc * sizeof (asection *));
|
||
+ }
|
||
+ secs[c] = os->bfd_section;
|
||
+ ++c;
|
||
+ pl->used = true;
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (l->flags == NULL)
|
||
+ flags = 0;
|
||
+ else
|
||
+ flags = exp_get_vma (l->flags, 0, "phdr flags");
|
||
+
|
||
+ if (l->at == NULL)
|
||
+ at = 0;
|
||
+ else
|
||
+ at = exp_get_vma (l->at, 0, "phdr load address");
|
||
+
|
||
+ if (!bfd_record_phdr (link_info.output_bfd, l->type,
|
||
+ l->flags != NULL, flags, l->at != NULL,
|
||
+ at, l->filehdr, l->phdrs, c, secs))
|
||
+ einfo (_("%F%P: bfd_record_phdr failed: %E\n"));
|
||
+ }
|
||
+
|
||
+ free (secs);
|
||
+
|
||
+ /* Make sure all the phdr assignments succeeded. */
|
||
+ for (os = (void *) lang_os_list.head;
|
||
+ os != NULL;
|
||
+ os = os->next)
|
||
+ {
|
||
+ lang_output_section_phdr_list *pl;
|
||
+
|
||
+ if (os->constraint < 0
|
||
+ || os->bfd_section == NULL)
|
||
+ continue;
|
||
+
|
||
+ for (pl = os->phdrs;
|
||
+ pl != NULL;
|
||
+ pl = pl->next)
|
||
+ if (!pl->used && strcmp (pl->name, "NONE") != 0)
|
||
+ einfo (_("%X%P: section `%s' assigned to non-existent phdr `%s'\n"),
|
||
+ os->name, pl->name);
|
||
+ }
|
||
+}
|
||
+
|
||
+/* Record a list of sections which may not be cross referenced. */
|
||
+
|
||
+void
|
||
+lang_add_nocrossref (lang_nocrossref_type *l)
|
||
+{
|
||
+ struct lang_nocrossrefs *n;
|
||
+
|
||
+ n = (struct lang_nocrossrefs *) xmalloc (sizeof *n);
|
||
+ n->next = nocrossref_list;
|
||
+ n->list = l;
|
||
+ n->onlyfirst = false;
|
||
+ nocrossref_list = n;
|
||
+
|
||
+ /* Set notice_all so that we get informed about all symbols. */
|
||
+ link_info.notice_all = true;
|
||
+}
|
||
+
|
||
+/* Record a section that cannot be referenced from a list of sections. */
|
||
+
|
||
+void
|
||
+lang_add_nocrossref_to (lang_nocrossref_type *l)
|
||
+{
|
||
+ lang_add_nocrossref (l);
|
||
+ nocrossref_list->onlyfirst = true;
|
||
+}
|
||
+
|
||
+/* Overlay handling. We handle overlays with some static variables. */
|
||
+
|
||
+/* The overlay virtual address. */
|
||
+static etree_type *overlay_vma;
|
||
+/* And subsection alignment. */
|
||
+static etree_type *overlay_subalign;
|
||
+
|
||
+/* An expression for the maximum section size seen so far. */
|
||
+static etree_type *overlay_max;
|
||
+
|
||
+/* A list of all the sections in this overlay. */
|
||
+
|
||
+struct overlay_list {
|
||
+ struct overlay_list *next;
|
||
+ lang_output_section_statement_type *os;
|
||
+};
|
||
+
|
||
+static struct overlay_list *overlay_list;
|
||
+
|
||
+/* Start handling an overlay. */
|
||
+
|
||
+void
|
||
+lang_enter_overlay (etree_type *vma_expr, etree_type *subalign)
|
||
+{
|
||
+ /* The grammar should prevent nested overlays from occurring. */
|
||
+ ASSERT (overlay_vma == NULL
|
||
+ && overlay_subalign == NULL
|
||
+ && overlay_max == NULL);
|
||
+
|
||
+ overlay_vma = vma_expr;
|
||
+ overlay_subalign = subalign;
|
||
+}
|
||
+
|
||
+/* Start a section in an overlay. We handle this by calling
|
||
+ lang_enter_output_section_statement with the correct VMA.
|
||
+ lang_leave_overlay sets up the LMA and memory regions. */
|
||
+
|
||
+void
|
||
+lang_enter_overlay_section (const char *name)
|
||
+{
|
||
+ struct overlay_list *n;
|
||
+ etree_type *size;
|
||
+
|
||
+ lang_enter_output_section_statement (name, overlay_vma, overlay_section,
|
||
+ 0, 0, overlay_subalign, 0, 0, 0);
|
||
+
|
||
+ /* If this is the first section, then base the VMA of future
|
||
+ sections on this one. This will work correctly even if `.' is
|
||
+ used in the addresses. */
|
||
+ if (overlay_list == NULL)
|
||
+ overlay_vma = exp_nameop (ADDR, name);
|
||
+
|
||
+ /* Remember the section. */
|
||
+ n = (struct overlay_list *) xmalloc (sizeof *n);
|
||
+ n->os = current_section;
|
||
+ n->next = overlay_list;
|
||
+ overlay_list = n;
|
||
+
|
||
+ size = exp_nameop (SIZEOF, name);
|
||
+
|
||
+ /* Arrange to work out the maximum section end address. */
|
||
+ if (overlay_max == NULL)
|
||
+ overlay_max = size;
|
||
+ else
|
||
+ overlay_max = exp_binop (MAX_K, overlay_max, size);
|
||
+}
|
||
+
|
||
+/* Finish a section in an overlay. There isn't any special to do
|
||
+ here. */
|
||
+
|
||
+void
|
||
+lang_leave_overlay_section (fill_type *fill,
|
||
+ lang_output_section_phdr_list *phdrs)
|
||
+{
|
||
+ const char *name;
|
||
+ char *clean, *s2;
|
||
+ const char *s1;
|
||
+ char *buf;
|
||
+
|
||
+ name = current_section->name;
|
||
+
|
||
+ /* For now, assume that DEFAULT_MEMORY_REGION is the run-time memory
|
||
+ region and that no load-time region has been specified. It doesn't
|
||
+ really matter what we say here, since lang_leave_overlay will
|
||
+ override it. */
|
||
+ lang_leave_output_section_statement (fill, DEFAULT_MEMORY_REGION, phdrs, 0);
|
||
+
|
||
+ /* Define the magic symbols. */
|
||
+
|
||
+ clean = (char *) xmalloc (strlen (name) + 1);
|
||
+ s2 = clean;
|
||
+ for (s1 = name; *s1 != '\0'; s1++)
|
||
+ if (ISALNUM (*s1) || *s1 == '_')
|
||
+ *s2++ = *s1;
|
||
+ *s2 = '\0';
|
||
+
|
||
+ buf = (char *) xmalloc (strlen (clean) + sizeof "__load_start_");
|
||
+ sprintf (buf, "__load_start_%s", clean);
|
||
+ lang_add_assignment (exp_provide (buf,
|
||
+ exp_nameop (LOADADDR, name),
|
||
+ false));
|
||
+
|
||
+ buf = (char *) xmalloc (strlen (clean) + sizeof "__load_stop_");
|
||
+ sprintf (buf, "__load_stop_%s", clean);
|
||
+ lang_add_assignment (exp_provide (buf,
|
||
+ exp_binop ('+',
|
||
+ exp_nameop (LOADADDR, name),
|
||
+ exp_nameop (SIZEOF, name)),
|
||
+ false));
|
||
+
|
||
+ free (clean);
|
||
+}
|
||
+
|
||
+/* Finish an overlay. If there are any overlay wide settings, this
|
||
+ looks through all the sections in the overlay and sets them. */
|
||
+
|
||
+void
|
||
+lang_leave_overlay (etree_type *lma_expr,
|
||
+ int nocrossrefs,
|
||
+ fill_type *fill,
|
||
+ const char *memspec,
|
||
+ lang_output_section_phdr_list *phdrs,
|
||
+ const char *lma_memspec)
|
||
+{
|
||
+ lang_memory_region_type *region;
|
||
+ lang_memory_region_type *lma_region;
|
||
+ struct overlay_list *l;
|
||
+ lang_nocrossref_type *nocrossref;
|
||
+
|
||
+ lang_get_regions (®ion, &lma_region,
|
||
+ memspec, lma_memspec,
|
||
+ lma_expr != NULL, false);
|
||
+
|
||
+ nocrossref = NULL;
|
||
+
|
||
+ /* After setting the size of the last section, set '.' to end of the
|
||
+ overlay region. */
|
||
+ if (overlay_list != NULL)
|
||
+ {
|
||
+ overlay_list->os->update_dot = 1;
|
||
+ overlay_list->os->update_dot_tree
|
||
+ = exp_assign (".", exp_binop ('+', overlay_vma, overlay_max), false);
|
||
+ }
|
||
+
|
||
+ l = overlay_list;
|
||
+ while (l != NULL)
|
||
+ {
|
||
+ struct overlay_list *next;
|
||
+
|
||
+ if (fill != NULL && l->os->fill == NULL)
|
||
+ l->os->fill = fill;
|
||
+
|
||
+ l->os->region = region;
|
||
+ l->os->lma_region = lma_region;
|
||
+
|
||
+ /* The first section has the load address specified in the
|
||
+ OVERLAY statement. The rest are worked out from that.
|
||
+ The base address is not needed (and should be null) if
|
||
+ an LMA region was specified. */
|
||
+ if (l->next == 0)
|
||
+ {
|
||
+ l->os->load_base = lma_expr;
|
||
+ l->os->sectype = first_overlay_section;
|
||
+ }
|
||
+ if (phdrs != NULL && l->os->phdrs == NULL)
|
||
+ l->os->phdrs = phdrs;
|
||
+
|
||
+ if (nocrossrefs)
|
||
+ {
|
||
+ lang_nocrossref_type *nc;
|
||
+
|
||
+ nc = (lang_nocrossref_type *) xmalloc (sizeof *nc);
|
||
+ nc->name = l->os->name;
|
||
+ nc->next = nocrossref;
|
||
+ nocrossref = nc;
|
||
+ }
|
||
+
|
||
+ next = l->next;
|
||
+ free (l);
|
||
+ l = next;
|
||
+ }
|
||
+
|
||
+ if (nocrossref != NULL)
|
||
+ lang_add_nocrossref (nocrossref);
|
||
+
|
||
+ overlay_vma = NULL;
|
||
+ overlay_list = NULL;
|
||
+ overlay_max = NULL;
|
||
+ overlay_subalign = NULL;
|
||
+}
|
||
+
|
||
+/* Version handling. This is only useful for ELF. */
|
||
+
|
||
+/* If PREV is NULL, return first version pattern matching particular symbol.
|
||
+ If PREV is non-NULL, return first version pattern matching particular
|
||
+ symbol after PREV (previously returned by lang_vers_match). */
|
||
+
|
||
+static struct bfd_elf_version_expr *
|
||
+lang_vers_match (struct bfd_elf_version_expr_head *head,
|
||
+ struct bfd_elf_version_expr *prev,
|
||
+ const char *sym)
|
||
+{
|
||
+ const char *c_sym;
|
||
+ const char *cxx_sym = sym;
|
||
+ const char *java_sym = sym;
|
||
+ struct bfd_elf_version_expr *expr = NULL;
|
||
+ enum demangling_styles curr_style;
|
||
+
|
||
+ curr_style = CURRENT_DEMANGLING_STYLE;
|
||
+ cplus_demangle_set_style (no_demangling);
|
||
+ c_sym = bfd_demangle (link_info.output_bfd, sym, DMGL_NO_OPTS);
|
||
+ if (!c_sym)
|
||
+ c_sym = sym;
|
||
+ cplus_demangle_set_style (curr_style);
|
||
+
|
||
+ if (head->mask & BFD_ELF_VERSION_CXX_TYPE)
|
||
+ {
|
||
+ cxx_sym = bfd_demangle (link_info.output_bfd, sym,
|
||
+ DMGL_PARAMS | DMGL_ANSI);
|
||
+ if (!cxx_sym)
|
||
+ cxx_sym = sym;
|
||
+ }
|
||
+ if (head->mask & BFD_ELF_VERSION_JAVA_TYPE)
|
||
+ {
|
||
+ java_sym = bfd_demangle (link_info.output_bfd, sym, DMGL_JAVA);
|
||
+ if (!java_sym)
|
||
+ java_sym = sym;
|
||
+ }
|
||
+
|
||
+ if (head->htab && (prev == NULL || prev->literal))
|
||
+ {
|
||
+ struct bfd_elf_version_expr e;
|
||
+
|
||
+ switch (prev ? prev->mask : 0)
|
||
+ {
|
||
+ case 0:
|
||
+ if (head->mask & BFD_ELF_VERSION_C_TYPE)
|
||
+ {
|
||
+ e.pattern = c_sym;
|
||
+ expr = (struct bfd_elf_version_expr *)
|
||
+ htab_find ((htab_t) head->htab, &e);
|
||
+ while (expr && strcmp (expr->pattern, c_sym) == 0)
|
||
+ if (expr->mask == BFD_ELF_VERSION_C_TYPE)
|
||
+ goto out_ret;
|
||
+ else
|
||
+ expr = expr->next;
|
||
+ }
|
||
+ /* Fallthrough */
|
||
+ case BFD_ELF_VERSION_C_TYPE:
|
||
+ if (head->mask & BFD_ELF_VERSION_CXX_TYPE)
|
||
+ {
|
||
+ e.pattern = cxx_sym;
|
||
+ expr = (struct bfd_elf_version_expr *)
|
||
+ htab_find ((htab_t) head->htab, &e);
|
||
+ while (expr && strcmp (expr->pattern, cxx_sym) == 0)
|
||
+ if (expr->mask == BFD_ELF_VERSION_CXX_TYPE)
|
||
+ goto out_ret;
|
||
+ else
|
||
+ expr = expr->next;
|
||
+ }
|
||
+ /* Fallthrough */
|
||
+ case BFD_ELF_VERSION_CXX_TYPE:
|
||
+ if (head->mask & BFD_ELF_VERSION_JAVA_TYPE)
|
||
+ {
|
||
+ e.pattern = java_sym;
|
||
+ expr = (struct bfd_elf_version_expr *)
|
||
+ htab_find ((htab_t) head->htab, &e);
|
||
+ while (expr && strcmp (expr->pattern, java_sym) == 0)
|
||
+ if (expr->mask == BFD_ELF_VERSION_JAVA_TYPE)
|
||
+ goto out_ret;
|
||
+ else
|
||
+ expr = expr->next;
|
||
+ }
|
||
+ /* Fallthrough */
|
||
+ default:
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ /* Finally, try the wildcards. */
|
||
+ if (prev == NULL || prev->literal)
|
||
+ expr = head->remaining;
|
||
+ else
|
||
+ expr = prev->next;
|
||
+ for (; expr; expr = expr->next)
|
||
+ {
|
||
+ const char *s;
|
||
+
|
||
+ if (!expr->pattern)
|
||
+ continue;
|
||
+
|
||
+ if (expr->pattern[0] == '*' && expr->pattern[1] == '\0')
|
||
+ break;
|
||
+
|
||
+ if (expr->mask == BFD_ELF_VERSION_JAVA_TYPE)
|
||
+ s = java_sym;
|
||
+ else if (expr->mask == BFD_ELF_VERSION_CXX_TYPE)
|
||
+ s = cxx_sym;
|
||
+ else
|
||
+ s = c_sym;
|
||
+ if (fnmatch (expr->pattern, s, 0) == 0)
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ out_ret:
|
||
+ if (c_sym != sym)
|
||
+ free ((char *) c_sym);
|
||
+ if (cxx_sym != sym)
|
||
+ free ((char *) cxx_sym);
|
||
+ if (java_sym != sym)
|
||
+ free ((char *) java_sym);
|
||
+ return expr;
|
||
+}
|
||
+
|
||
+/* Return NULL if the PATTERN argument is a glob pattern, otherwise,
|
||
+ return a pointer to the symbol name with any backslash quotes removed. */
|
||
+
|
||
+static const char *
|
||
+realsymbol (const char *pattern)
|
||
+{
|
||
+ const char *p;
|
||
+ bool changed = false, backslash = false;
|
||
+ char *s, *symbol = (char *) xmalloc (strlen (pattern) + 1);
|
||
+
|
||
+ for (p = pattern, s = symbol; *p != '\0'; ++p)
|
||
+ {
|
||
+ /* It is a glob pattern only if there is no preceding
|
||
+ backslash. */
|
||
+ if (backslash)
|
||
+ {
|
||
+ /* Remove the preceding backslash. */
|
||
+ *(s - 1) = *p;
|
||
+ backslash = false;
|
||
+ changed = true;
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ if (*p == '?' || *p == '*' || *p == '[')
|
||
+ {
|
||
+ free (symbol);
|
||
+ return NULL;
|
||
+ }
|
||
+
|
||
+ *s++ = *p;
|
||
+ backslash = *p == '\\';
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (changed)
|
||
+ {
|
||
+ *s = '\0';
|
||
+ return symbol;
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ free (symbol);
|
||
+ return pattern;
|
||
+ }
|
||
+}
|
||
+
|
||
+/* This is called for each variable name or match expression. NEW_NAME is
|
||
+ the name of the symbol to match, or, if LITERAL_P is FALSE, a glob
|
||
+ pattern to be matched against symbol names. */
|
||
+
|
||
+struct bfd_elf_version_expr *
|
||
+lang_new_vers_pattern (struct bfd_elf_version_expr *orig,
|
||
+ const char *new_name,
|
||
+ const char *lang,
|
||
+ bool literal_p)
|
||
+{
|
||
+ struct bfd_elf_version_expr *ret;
|
||
+
|
||
+ ret = (struct bfd_elf_version_expr *) xmalloc (sizeof *ret);
|
||
+ ret->next = orig;
|
||
+ ret->symver = 0;
|
||
+ ret->script = 0;
|
||
+ ret->literal = true;
|
||
+ ret->pattern = literal_p ? new_name : realsymbol (new_name);
|
||
+ if (ret->pattern == NULL)
|
||
+ {
|
||
+ ret->pattern = new_name;
|
||
+ ret->literal = false;
|
||
+ }
|
||
+
|
||
+ if (lang == NULL || strcasecmp (lang, "C") == 0)
|
||
+ ret->mask = BFD_ELF_VERSION_C_TYPE;
|
||
+ else if (strcasecmp (lang, "C++") == 0)
|
||
+ ret->mask = BFD_ELF_VERSION_CXX_TYPE;
|
||
+ else if (strcasecmp (lang, "Java") == 0)
|
||
+ ret->mask = BFD_ELF_VERSION_JAVA_TYPE;
|
||
+ else
|
||
+ {
|
||
+ einfo (_("%X%P: unknown language `%s' in version information\n"),
|
||
+ lang);
|
||
+ ret->mask = BFD_ELF_VERSION_C_TYPE;
|
||
+ }
|
||
+
|
||
+ return ldemul_new_vers_pattern (ret);
|
||
+}
|
||
+
|
||
+/* This is called for each set of variable names and match
|
||
+ expressions. */
|
||
+
|
||
+struct bfd_elf_version_tree *
|
||
+lang_new_vers_node (struct bfd_elf_version_expr *globals,
|
||
+ struct bfd_elf_version_expr *locals)
|
||
+{
|
||
+ struct bfd_elf_version_tree *ret;
|
||
+
|
||
+ ret = (struct bfd_elf_version_tree *) xcalloc (1, sizeof *ret);
|
||
+ ret->globals.list = globals;
|
||
+ ret->locals.list = locals;
|
||
+ ret->match = lang_vers_match;
|
||
+ ret->name_indx = (unsigned int) -1;
|
||
+ return ret;
|
||
+}
|
||
+
|
||
+/* This static variable keeps track of version indices. */
|
||
+
|
||
+static int version_index;
|
||
+
|
||
+static hashval_t
|
||
+version_expr_head_hash (const void *p)
|
||
+{
|
||
+ const struct bfd_elf_version_expr *e =
|
||
+ (const struct bfd_elf_version_expr *) p;
|
||
+
|
||
+ return htab_hash_string (e->pattern);
|
||
+}
|
||
+
|
||
+static int
|
||
+version_expr_head_eq (const void *p1, const void *p2)
|
||
+{
|
||
+ const struct bfd_elf_version_expr *e1 =
|
||
+ (const struct bfd_elf_version_expr *) p1;
|
||
+ const struct bfd_elf_version_expr *e2 =
|
||
+ (const struct bfd_elf_version_expr *) p2;
|
||
+
|
||
+ return strcmp (e1->pattern, e2->pattern) == 0;
|
||
+}
|
||
+
|
||
+static void
|
||
+lang_finalize_version_expr_head (struct bfd_elf_version_expr_head *head)
|
||
+{
|
||
+ size_t count = 0;
|
||
+ struct bfd_elf_version_expr *e, *next;
|
||
+ struct bfd_elf_version_expr **list_loc, **remaining_loc;
|
||
+
|
||
+ for (e = head->list; e; e = e->next)
|
||
+ {
|
||
+ if (e->literal)
|
||
+ count++;
|
||
+ head->mask |= e->mask;
|
||
+ }
|
||
+
|
||
+ if (count)
|
||
+ {
|
||
+ head->htab = htab_create (count * 2, version_expr_head_hash,
|
||
+ version_expr_head_eq, NULL);
|
||
+ list_loc = &head->list;
|
||
+ remaining_loc = &head->remaining;
|
||
+ for (e = head->list; e; e = next)
|
||
+ {
|
||
+ next = e->next;
|
||
+ if (!e->literal)
|
||
+ {
|
||
+ *remaining_loc = e;
|
||
+ remaining_loc = &e->next;
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ void **loc = htab_find_slot ((htab_t) head->htab, e, INSERT);
|
||
+
|
||
+ if (*loc)
|
||
+ {
|
||
+ struct bfd_elf_version_expr *e1, *last;
|
||
+
|
||
+ e1 = (struct bfd_elf_version_expr *) *loc;
|
||
+ last = NULL;
|
||
+ do
|
||
+ {
|
||
+ if (e1->mask == e->mask)
|
||
+ {
|
||
+ last = NULL;
|
||
+ break;
|
||
+ }
|
||
+ last = e1;
|
||
+ e1 = e1->next;
|
||
+ }
|
||
+ while (e1 && strcmp (e1->pattern, e->pattern) == 0);
|
||
+
|
||
+ if (last == NULL)
|
||
+ {
|
||
+ /* This is a duplicate. */
|
||
+ /* FIXME: Memory leak. Sometimes pattern is not
|
||
+ xmalloced alone, but in larger chunk of memory. */
|
||
+ /* free (e->pattern); */
|
||
+ free (e);
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ e->next = last->next;
|
||
+ last->next = e;
|
||
+ }
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ *loc = e;
|
||
+ *list_loc = e;
|
||
+ list_loc = &e->next;
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+ *remaining_loc = NULL;
|
||
+ *list_loc = head->remaining;
|
||
+ }
|
||
+ else
|
||
+ head->remaining = head->list;
|
||
+}
|
||
+
|
||
+/* This is called when we know the name and dependencies of the
|
||
+ version. */
|
||
+
|
||
+void
|
||
+lang_register_vers_node (const char *name,
|
||
+ struct bfd_elf_version_tree *version,
|
||
+ struct bfd_elf_version_deps *deps)
|
||
+{
|
||
+ struct bfd_elf_version_tree *t, **pp;
|
||
+ struct bfd_elf_version_expr *e1;
|
||
+
|
||
+ if (name == NULL)
|
||
+ name = "";
|
||
+
|
||
+ if (link_info.version_info != NULL
|
||
+ && (name[0] == '\0' || link_info.version_info->name[0] == '\0'))
|
||
+ {
|
||
+ einfo (_("%X%P: anonymous version tag cannot be combined"
|
||
+ " with other version tags\n"));
|
||
+ free (version);
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ /* Make sure this node has a unique name. */
|
||
+ for (t = link_info.version_info; t != NULL; t = t->next)
|
||
+ if (strcmp (t->name, name) == 0)
|
||
+ einfo (_("%X%P: duplicate version tag `%s'\n"), name);
|
||
+
|
||
+ lang_finalize_version_expr_head (&version->globals);
|
||
+ lang_finalize_version_expr_head (&version->locals);
|
||
+
|
||
+ /* Check the global and local match names, and make sure there
|
||
+ aren't any duplicates. */
|
||
+
|
||
+ for (e1 = version->globals.list; e1 != NULL; e1 = e1->next)
|
||
+ {
|
||
+ for (t = link_info.version_info; t != NULL; t = t->next)
|
||
+ {
|
||
+ struct bfd_elf_version_expr *e2;
|
||
+
|
||
+ if (t->locals.htab && e1->literal)
|
||
+ {
|
||
+ e2 = (struct bfd_elf_version_expr *)
|
||
+ htab_find ((htab_t) t->locals.htab, e1);
|
||
+ while (e2 && strcmp (e1->pattern, e2->pattern) == 0)
|
||
+ {
|
||
+ if (e1->mask == e2->mask)
|
||
+ einfo (_("%X%P: duplicate expression `%s'"
|
||
+ " in version information\n"), e1->pattern);
|
||
+ e2 = e2->next;
|
||
+ }
|
||
+ }
|
||
+ else if (!e1->literal)
|
||
+ for (e2 = t->locals.remaining; e2 != NULL; e2 = e2->next)
|
||
+ if (strcmp (e1->pattern, e2->pattern) == 0
|
||
+ && e1->mask == e2->mask)
|
||
+ einfo (_("%X%P: duplicate expression `%s'"
|
||
+ " in version information\n"), e1->pattern);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ for (e1 = version->locals.list; e1 != NULL; e1 = e1->next)
|
||
+ {
|
||
+ for (t = link_info.version_info; t != NULL; t = t->next)
|
||
+ {
|
||
+ struct bfd_elf_version_expr *e2;
|
||
+
|
||
+ if (t->globals.htab && e1->literal)
|
||
+ {
|
||
+ e2 = (struct bfd_elf_version_expr *)
|
||
+ htab_find ((htab_t) t->globals.htab, e1);
|
||
+ while (e2 && strcmp (e1->pattern, e2->pattern) == 0)
|
||
+ {
|
||
+ if (e1->mask == e2->mask)
|
||
+ einfo (_("%X%P: duplicate expression `%s'"
|
||
+ " in version information\n"),
|
||
+ e1->pattern);
|
||
+ e2 = e2->next;
|
||
+ }
|
||
+ }
|
||
+ else if (!e1->literal)
|
||
+ for (e2 = t->globals.remaining; e2 != NULL; e2 = e2->next)
|
||
+ if (strcmp (e1->pattern, e2->pattern) == 0
|
||
+ && e1->mask == e2->mask)
|
||
+ einfo (_("%X%P: duplicate expression `%s'"
|
||
+ " in version information\n"), e1->pattern);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ version->deps = deps;
|
||
+ version->name = name;
|
||
+ if (name[0] != '\0')
|
||
+ {
|
||
+ ++version_index;
|
||
+ version->vernum = version_index;
|
||
+ }
|
||
+ else
|
||
+ version->vernum = 0;
|
||
+
|
||
+ for (pp = &link_info.version_info; *pp != NULL; pp = &(*pp)->next)
|
||
+ ;
|
||
+ *pp = version;
|
||
+}
|
||
+
|
||
+/* This is called when we see a version dependency. */
|
||
+
|
||
+struct bfd_elf_version_deps *
|
||
+lang_add_vers_depend (struct bfd_elf_version_deps *list, const char *name)
|
||
+{
|
||
+ struct bfd_elf_version_deps *ret;
|
||
+ struct bfd_elf_version_tree *t;
|
||
+
|
||
+ ret = (struct bfd_elf_version_deps *) xmalloc (sizeof *ret);
|
||
+ ret->next = list;
|
||
+
|
||
+ for (t = link_info.version_info; t != NULL; t = t->next)
|
||
+ {
|
||
+ if (strcmp (t->name, name) == 0)
|
||
+ {
|
||
+ ret->version_needed = t;
|
||
+ return ret;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ einfo (_("%X%P: unable to find version dependency `%s'\n"), name);
|
||
+
|
||
+ ret->version_needed = NULL;
|
||
+ return ret;
|
||
+}
|
||
+
|
||
+static void
|
||
+lang_do_version_exports_section (void)
|
||
+{
|
||
+ struct bfd_elf_version_expr *greg = NULL, *lreg;
|
||
+
|
||
+ LANG_FOR_EACH_INPUT_STATEMENT (is)
|
||
+ {
|
||
+ asection *sec = bfd_get_section_by_name (is->the_bfd, ".exports");
|
||
+ char *contents, *p;
|
||
+ bfd_size_type len;
|
||
+
|
||
+ if (sec == NULL)
|
||
+ continue;
|
||
+
|
||
+ len = sec->size;
|
||
+ contents = (char *) xmalloc (len);
|
||
+ if (!bfd_get_section_contents (is->the_bfd, sec, contents, 0, len))
|
||
+ einfo (_("%X%P: unable to read .exports section contents\n"), sec);
|
||
+
|
||
+ p = contents;
|
||
+ while (p < contents + len)
|
||
+ {
|
||
+ greg = lang_new_vers_pattern (greg, p, NULL, false);
|
||
+ p = strchr (p, '\0') + 1;
|
||
+ }
|
||
+
|
||
+ /* Do not free the contents, as we used them creating the regex. */
|
||
+
|
||
+ /* Do not include this section in the link. */
|
||
+ sec->flags |= SEC_EXCLUDE | SEC_KEEP;
|
||
+ }
|
||
+
|
||
+ lreg = lang_new_vers_pattern (NULL, "*", NULL, false);
|
||
+ lang_register_vers_node (command_line.version_exports_section,
|
||
+ lang_new_vers_node (greg, lreg), NULL);
|
||
+}
|
||
+
|
||
+/* Evaluate LENGTH and ORIGIN parts of MEMORY spec. This is initially
|
||
+ called with UPDATE_REGIONS_P set to FALSE, in this case no errors are
|
||
+ thrown, however, references to symbols in the origin and length fields
|
||
+ will be pushed into the symbol table, this allows PROVIDE statements to
|
||
+ then provide these symbols. This function is called a second time with
|
||
+ UPDATE_REGIONS_P set to TRUE, this time the we update the actual region
|
||
+ data structures, and throw errors if missing symbols are encountered. */
|
||
+
|
||
+static void
|
||
+lang_do_memory_regions (bool update_regions_p)
|
||
+{
|
||
+ lang_memory_region_type *r = lang_memory_region_list;
|
||
+
|
||
+ for (; r != NULL; r = r->next)
|
||
+ {
|
||
+ if (r->origin_exp)
|
||
+ {
|
||
+ exp_fold_tree_no_dot (r->origin_exp);
|
||
+ if (update_regions_p)
|
||
+ {
|
||
+ if (expld.result.valid_p)
|
||
+ {
|
||
+ r->origin = expld.result.value;
|
||
+ r->current = r->origin;
|
||
+ }
|
||
+ else
|
||
+ einfo (_("%P: invalid origin for memory region %s\n"),
|
||
+ r->name_list.name);
|
||
+ }
|
||
+ }
|
||
+ if (r->length_exp)
|
||
+ {
|
||
+ exp_fold_tree_no_dot (r->length_exp);
|
||
+ if (update_regions_p)
|
||
+ {
|
||
+ if (expld.result.valid_p)
|
||
+ r->length = expld.result.value;
|
||
+ else
|
||
+ einfo (_("%P: invalid length for memory region %s\n"),
|
||
+ r->name_list.name);
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+}
|
||
+
|
||
+void
|
||
+lang_add_unique (const char *name)
|
||
+{
|
||
+ struct unique_sections *ent;
|
||
+
|
||
+ for (ent = unique_section_list; ent; ent = ent->next)
|
||
+ if (strcmp (ent->name, name) == 0)
|
||
+ return;
|
||
+
|
||
+ ent = (struct unique_sections *) xmalloc (sizeof *ent);
|
||
+ ent->name = xstrdup (name);
|
||
+ ent->next = unique_section_list;
|
||
+ unique_section_list = ent;
|
||
+}
|
||
+
|
||
+/* Append the list of dynamic symbols to the existing one. */
|
||
+
|
||
+void
|
||
+lang_append_dynamic_list (struct bfd_elf_dynamic_list **list_p,
|
||
+ struct bfd_elf_version_expr *dynamic)
|
||
+{
|
||
+ if (*list_p)
|
||
+ {
|
||
+ struct bfd_elf_version_expr *tail;
|
||
+ for (tail = dynamic; tail->next != NULL; tail = tail->next)
|
||
+ ;
|
||
+ tail->next = (*list_p)->head.list;
|
||
+ (*list_p)->head.list = dynamic;
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ struct bfd_elf_dynamic_list *d;
|
||
+
|
||
+ d = (struct bfd_elf_dynamic_list *) xcalloc (1, sizeof *d);
|
||
+ d->head.list = dynamic;
|
||
+ d->match = lang_vers_match;
|
||
+ *list_p = d;
|
||
+ }
|
||
+}
|
||
+
|
||
+/* Append the list of C++ typeinfo dynamic symbols to the existing
|
||
+ one. */
|
||
+
|
||
+void
|
||
+lang_append_dynamic_list_cpp_typeinfo (void)
|
||
+{
|
||
+ const char *symbols[] =
|
||
+ {
|
||
+ "typeinfo name for*",
|
||
+ "typeinfo for*"
|
||
+ };
|
||
+ struct bfd_elf_version_expr *dynamic = NULL;
|
||
+ unsigned int i;
|
||
+
|
||
+ for (i = 0; i < ARRAY_SIZE (symbols); i++)
|
||
+ dynamic = lang_new_vers_pattern (dynamic, symbols [i], "C++",
|
||
+ false);
|
||
+
|
||
+ lang_append_dynamic_list (&link_info.dynamic_list, dynamic);
|
||
+}
|
||
+
|
||
+/* Append the list of C++ operator new and delete dynamic symbols to the
|
||
+ existing one. */
|
||
+
|
||
+void
|
||
+lang_append_dynamic_list_cpp_new (void)
|
||
+{
|
||
+ const char *symbols[] =
|
||
+ {
|
||
+ "operator new*",
|
||
+ "operator delete*"
|
||
+ };
|
||
+ struct bfd_elf_version_expr *dynamic = NULL;
|
||
+ unsigned int i;
|
||
+
|
||
+ for (i = 0; i < ARRAY_SIZE (symbols); i++)
|
||
+ dynamic = lang_new_vers_pattern (dynamic, symbols [i], "C++",
|
||
+ false);
|
||
+
|
||
+ lang_append_dynamic_list (&link_info.dynamic_list, dynamic);
|
||
+}
|
||
+
|
||
+/* Scan a space and/or comma separated string of features. */
|
||
+
|
||
+void
|
||
+lang_ld_feature (char *str)
|
||
+{
|
||
+ char *p, *q;
|
||
+
|
||
+ p = str;
|
||
+ while (*p)
|
||
+ {
|
||
+ char sep;
|
||
+ while (*p == ',' || ISSPACE (*p))
|
||
+ ++p;
|
||
+ if (!*p)
|
||
+ break;
|
||
+ q = p + 1;
|
||
+ while (*q && *q != ',' && !ISSPACE (*q))
|
||
+ ++q;
|
||
+ sep = *q;
|
||
+ *q = 0;
|
||
+ if (strcasecmp (p, "SANE_EXPR") == 0)
|
||
+ config.sane_expr = true;
|
||
+ else
|
||
+ einfo (_("%X%P: unknown feature `%s'\n"), p);
|
||
+ *q = sep;
|
||
+ p = q;
|
||
+ }
|
||
+}
|
||
+
|
||
+/* Pretty print memory amount. */
|
||
+
|
||
+static void
|
||
+lang_print_memory_size (uint64_t sz)
|
||
+{
|
||
+ if ((sz & 0x3fffffff) == 0)
|
||
+ printf ("%10" PRIu64 " GB", sz >> 30);
|
||
+ else if ((sz & 0xfffff) == 0)
|
||
+ printf ("%10" PRIu64 " MB", sz >> 20);
|
||
+ else if ((sz & 0x3ff) == 0)
|
||
+ printf ("%10" PRIu64 " KB", sz >> 10);
|
||
+ else
|
||
+ printf (" %10" PRIu64 " B", sz);
|
||
+}
|
||
+
|
||
+/* Implement --print-memory-usage: disply per region memory usage. */
|
||
+
|
||
+void
|
||
+lang_print_memory_usage (void)
|
||
+{
|
||
+ lang_memory_region_type *r;
|
||
+
|
||
+ printf ("Memory region Used Size Region Size %%age Used\n");
|
||
+ for (r = lang_memory_region_list; r->next != NULL; r = r->next)
|
||
+ {
|
||
+ bfd_vma used_length = r->current - r->origin;
|
||
+
|
||
+ printf ("%16s: ",r->name_list.name);
|
||
+ lang_print_memory_size (used_length);
|
||
+ lang_print_memory_size (r->length);
|
||
+
|
||
+ if (r->length != 0)
|
||
+ {
|
||
+ double percent = used_length * 100.0 / r->length;
|
||
+ printf (" %6.2f%%", percent);
|
||
+ }
|
||
+ printf ("\n");
|
||
+ }
|
||
+}
|
||
diff -rupN binutils.orig/ld/ldlang.h binutils-2.41/ld/ldlang.h
|
||
--- binutils.orig/ld/ldlang.h 2024-05-13 13:03:47.804601777 +0100
|
||
+++ binutils-2.41/ld/ldlang.h 2024-05-13 13:04:08.599633306 +0100
|
||
@@ -141,7 +141,12 @@ typedef struct lang_output_section_phdr_
|
||
typedef struct lang_output_section_statement_struct
|
||
{
|
||
lang_statement_header_type header;
|
||
+ /* Input sections to be mapped to this output section. */
|
||
lang_statement_list_type children;
|
||
+ /* Input sections to be mapped to the start of this output section.
|
||
+ These sections are provided by the --section-ordering file, if used. */
|
||
+ lang_statement_list_type sort_children;
|
||
+
|
||
struct lang_output_section_statement_struct *next;
|
||
struct lang_output_section_statement_struct *prev;
|
||
const char *name;
|
||
diff -rupN binutils.orig/ld/ldlex.h binutils-2.41/ld/ldlex.h
|
||
--- binutils.orig/ld/ldlex.h 2024-05-13 13:03:48.141602288 +0100
|
||
+++ binutils-2.41/ld/ldlex.h 2024-05-13 13:04:08.599633306 +0100
|
||
@@ -62,6 +62,7 @@ enum option_values
|
||
OPTION_SONAME,
|
||
OPTION_SORT_COMMON,
|
||
OPTION_SORT_SECTION,
|
||
+ OPTION_SECTION_ORDERING_FILE,
|
||
OPTION_STATS,
|
||
OPTION_SYMBOLIC,
|
||
OPTION_SYMBOLIC_FUNCTIONS,
|
||
@@ -190,6 +191,7 @@ typedef enum input_enum
|
||
input_script,
|
||
input_mri_script,
|
||
input_version_script,
|
||
+ input_section_ordering_script,
|
||
input_dynamic_list,
|
||
input_defsym
|
||
} input_type;
|
||
diff -rupN binutils.orig/ld/ldlex.h.orig binutils-2.41/ld/ldlex.h.orig
|
||
--- binutils.orig/ld/ldlex.h.orig 1970-01-01 01:00:00.000000000 +0100
|
||
+++ binutils-2.41/ld/ldlex.h.orig 2024-05-13 13:03:25.176567468 +0100
|
||
@@ -0,0 +1,222 @@
|
||
+/* ldlex.h -
|
||
+ Copyright (C) 1991-2023 Free Software Foundation, Inc.
|
||
+
|
||
+ This file is part of the GNU Binutils.
|
||
+
|
||
+ This program is free software; you can redistribute it and/or modify
|
||
+ it under the terms of the GNU General Public License as published by
|
||
+ the Free Software Foundation; either version 3 of the License, or
|
||
+ (at your option) any later version.
|
||
+
|
||
+ This program is distributed in the hope that it will be useful,
|
||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
+ GNU General Public License for more details.
|
||
+
|
||
+ You should have received a copy of the GNU General Public License
|
||
+ along with this program; if not, write to the Free Software
|
||
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
|
||
+ MA 02110-1301, USA. */
|
||
+
|
||
+#ifndef LDLEX_H
|
||
+#define LDLEX_H
|
||
+
|
||
+#include <stdio.h>
|
||
+
|
||
+/* Codes used for the long options with no short synonyms. 150 isn't
|
||
+ special; it's just an arbitrary non-ASCII char value. */
|
||
+enum option_values
|
||
+{
|
||
+ OPTION_ASSERT = 150,
|
||
+ OPTION_CALL_SHARED,
|
||
+ OPTION_CREF,
|
||
+ OPTION_DEFSYM,
|
||
+ OPTION_DEMANGLE,
|
||
+ OPTION_DYNAMIC_LINKER,
|
||
+ OPTION_NO_DYNAMIC_LINKER,
|
||
+ OPTION_SYSROOT,
|
||
+ OPTION_OUT_IMPLIB,
|
||
+ OPTION_EB,
|
||
+ OPTION_EL,
|
||
+ OPTION_EMBEDDED_RELOCS,
|
||
+ OPTION_EXPORT_DYNAMIC,
|
||
+ OPTION_NO_EXPORT_DYNAMIC,
|
||
+ OPTION_HELP,
|
||
+ OPTION_IGNORE,
|
||
+ OPTION_MAP,
|
||
+ OPTION_NO_DEMANGLE,
|
||
+ OPTION_NO_KEEP_MEMORY,
|
||
+ OPTION_NO_WARN_MISMATCH,
|
||
+ OPTION_NO_WARN_SEARCH_MISMATCH,
|
||
+ OPTION_NOINHIBIT_EXEC,
|
||
+ OPTION_NON_SHARED,
|
||
+ OPTION_NO_WHOLE_ARCHIVE,
|
||
+ OPTION_OFORMAT,
|
||
+ OPTION_RELAX,
|
||
+ OPTION_NO_RELAX,
|
||
+ OPTION_NO_SYMBOLIC,
|
||
+ OPTION_RETAIN_SYMBOLS_FILE,
|
||
+ OPTION_RPATH,
|
||
+ OPTION_RPATH_LINK,
|
||
+ OPTION_SHARED,
|
||
+ OPTION_SONAME,
|
||
+ OPTION_SORT_COMMON,
|
||
+ OPTION_SORT_SECTION,
|
||
+ OPTION_STATS,
|
||
+ OPTION_SYMBOLIC,
|
||
+ OPTION_SYMBOLIC_FUNCTIONS,
|
||
+ OPTION_TASK_LINK,
|
||
+ OPTION_TBSS,
|
||
+ OPTION_TDATA,
|
||
+ OPTION_TTEXT,
|
||
+ OPTION_TTEXT_SEGMENT,
|
||
+ OPTION_TRODATA_SEGMENT,
|
||
+ OPTION_TLDATA_SEGMENT,
|
||
+ OPTION_TRADITIONAL_FORMAT,
|
||
+ OPTION_UR,
|
||
+ OPTION_VERBOSE,
|
||
+ OPTION_VERSION,
|
||
+ OPTION_VERSION_SCRIPT,
|
||
+ OPTION_VERSION_EXPORTS_SECTION,
|
||
+ OPTION_DYNAMIC_LIST,
|
||
+ OPTION_DYNAMIC_LIST_CPP_NEW,
|
||
+ OPTION_DYNAMIC_LIST_CPP_TYPEINFO,
|
||
+ OPTION_DYNAMIC_LIST_DATA,
|
||
+ OPTION_EXPORT_DYNAMIC_SYMBOL,
|
||
+ OPTION_EXPORT_DYNAMIC_SYMBOL_LIST,
|
||
+ OPTION_WARN_COMMON,
|
||
+ OPTION_WARN_CONSTRUCTORS,
|
||
+ OPTION_WARN_FATAL,
|
||
+ OPTION_NO_WARN_FATAL,
|
||
+ OPTION_NO_WARNINGS,
|
||
+ OPTION_WARN_MULTIPLE_GP,
|
||
+ OPTION_WARN_ONCE,
|
||
+ OPTION_WARN_SECTION_ALIGN,
|
||
+ OPTION_SPLIT_BY_RELOC,
|
||
+ OPTION_SPLIT_BY_FILE ,
|
||
+ OPTION_WHOLE_ARCHIVE,
|
||
+ OPTION_ADD_DT_NEEDED_FOR_DYNAMIC,
|
||
+ OPTION_NO_ADD_DT_NEEDED_FOR_DYNAMIC,
|
||
+ OPTION_ADD_DT_NEEDED_FOR_REGULAR,
|
||
+ OPTION_NO_ADD_DT_NEEDED_FOR_REGULAR,
|
||
+ OPTION_WRAP,
|
||
+ OPTION_FORCE_EXE_SUFFIX,
|
||
+ OPTION_GC_SECTIONS,
|
||
+ OPTION_NO_GC_SECTIONS,
|
||
+ OPTION_PRINT_GC_SECTIONS,
|
||
+ OPTION_NO_PRINT_GC_SECTIONS,
|
||
+ OPTION_GC_KEEP_EXPORTED,
|
||
+ OPTION_HASH_SIZE,
|
||
+ OPTION_CHECK_SECTIONS,
|
||
+ OPTION_NO_CHECK_SECTIONS,
|
||
+ OPTION_NO_UNDEFINED,
|
||
+ OPTION_INIT,
|
||
+ OPTION_FINI,
|
||
+ OPTION_SECTION_START,
|
||
+ OPTION_UNIQUE,
|
||
+ OPTION_TARGET_HELP,
|
||
+ OPTION_ALLOW_SHLIB_UNDEFINED,
|
||
+ OPTION_NO_ALLOW_SHLIB_UNDEFINED,
|
||
+ OPTION_ALLOW_MULTIPLE_DEFINITION,
|
||
+#if SUPPORT_ERROR_HANDLING_SCRIPT
|
||
+ OPTION_ERROR_HANDLING_SCRIPT,
|
||
+#endif
|
||
+ OPTION_UNDEFINED_VERSION,
|
||
+ OPTION_NO_UNDEFINED_VERSION,
|
||
+ OPTION_DEFAULT_SYMVER,
|
||
+ OPTION_DEFAULT_IMPORTED_SYMVER,
|
||
+ OPTION_DISCARD_NONE,
|
||
+ OPTION_SPARE_DYNAMIC_TAGS,
|
||
+ OPTION_NO_DEFINE_COMMON,
|
||
+ OPTION_NOSTDLIB,
|
||
+ OPTION_NO_OMAGIC,
|
||
+ OPTION_STRIP_DISCARDED,
|
||
+ OPTION_NO_STRIP_DISCARDED,
|
||
+ OPTION_ACCEPT_UNKNOWN_INPUT_ARCH,
|
||
+ OPTION_NO_ACCEPT_UNKNOWN_INPUT_ARCH,
|
||
+ OPTION_PIE,
|
||
+ OPTION_NO_PIE,
|
||
+ OPTION_UNRESOLVED_SYMBOLS,
|
||
+ OPTION_WARN_UNRESOLVED_SYMBOLS,
|
||
+ OPTION_ERROR_UNRESOLVED_SYMBOLS,
|
||
+ OPTION_WARN_TEXTREL,
|
||
+ OPTION_WARN_ALTERNATE_EM,
|
||
+ OPTION_REDUCE_MEMORY_OVERHEADS,
|
||
+ OPTION_MAX_CACHE_SIZE,
|
||
+#if BFD_SUPPORTS_PLUGINS
|
||
+ OPTION_PLUGIN,
|
||
+ OPTION_PLUGIN_OPT,
|
||
+#endif /* BFD_SUPPORTS_PLUGINS */
|
||
+ OPTION_DEFAULT_SCRIPT,
|
||
+ OPTION_PRINT_OUTPUT_FORMAT,
|
||
+ OPTION_PRINT_SYSROOT,
|
||
+ OPTION_IGNORE_UNRESOLVED_SYMBOL,
|
||
+ OPTION_PUSH_STATE,
|
||
+ OPTION_POP_STATE,
|
||
+ OPTION_DISABLE_MULTIPLE_DEFS_ABS,
|
||
+ OPTION_PRINT_MEMORY_USAGE,
|
||
+ OPTION_REQUIRE_DEFINED_SYMBOL,
|
||
+ OPTION_ORPHAN_HANDLING,
|
||
+ OPTION_FORCE_GROUP_ALLOCATION,
|
||
+ OPTION_PRINT_MAP_DISCARDED,
|
||
+ OPTION_NO_PRINT_MAP_DISCARDED,
|
||
+ OPTION_PRINT_MAP_LOCALS,
|
||
+ OPTION_NO_PRINT_MAP_LOCALS,
|
||
+ OPTION_NON_CONTIGUOUS_REGIONS,
|
||
+ OPTION_NON_CONTIGUOUS_REGIONS_WARNINGS,
|
||
+ OPTION_DEPENDENCY_FILE,
|
||
+ OPTION_CTF_VARIABLES,
|
||
+ OPTION_NO_CTF_VARIABLES,
|
||
+ OPTION_CTF_SHARE_TYPES,
|
||
+ OPTION_ERROR_EXECSTACK,
|
||
+ OPTION_NO_ERROR_EXECSTACK,
|
||
+ OPTION_WARN_EXECSTACK_OBJECTS,
|
||
+ OPTION_WARN_EXECSTACK,
|
||
+ OPTION_NO_WARN_EXECSTACK,
|
||
+ OPTION_WARN_RWX_SEGMENTS,
|
||
+ OPTION_NO_WARN_RWX_SEGMENTS,
|
||
+ OPTION_ERROR_RWX_SEGMENTS,
|
||
+ OPTION_NO_ERROR_RWX_SEGMENTS,
|
||
+ OPTION_ENABLE_LINKER_VERSION,
|
||
+ OPTION_DISABLE_LINKER_VERSION,
|
||
+ OPTION_REMAP_INPUTS,
|
||
+ OPTION_REMAP_INPUTS_FILE,
|
||
+};
|
||
+
|
||
+/* The initial parser states. */
|
||
+typedef enum input_enum
|
||
+{
|
||
+ input_selected, /* We've set the initial state. */
|
||
+ input_script,
|
||
+ input_mri_script,
|
||
+ input_version_script,
|
||
+ input_dynamic_list,
|
||
+ input_defsym
|
||
+} input_type;
|
||
+
|
||
+extern input_type parser_input;
|
||
+
|
||
+extern unsigned int lineno;
|
||
+extern const char *lex_string;
|
||
+
|
||
+/* In ldlex.l. */
|
||
+extern int yylex (void);
|
||
+extern void lex_push_file (FILE *, const char *, unsigned int);
|
||
+extern void lex_redirect (const char *, const char *, unsigned int);
|
||
+extern void ldlex_script (void);
|
||
+extern void ldlex_inputlist (void);
|
||
+extern void ldlex_mri_script (void);
|
||
+extern void ldlex_version_script (void);
|
||
+extern void ldlex_version_file (void);
|
||
+extern void ldlex_expression (void);
|
||
+extern void ldlex_wild (void);
|
||
+extern void ldlex_popstate (void);
|
||
+extern void ldlex_backup (void);
|
||
+extern const char* ldlex_filename (void);
|
||
+
|
||
+/* In lexsup.c. */
|
||
+extern int lex_input (void);
|
||
+extern void lex_unput (int);
|
||
+extern void parse_args (unsigned, char **);
|
||
+
|
||
+#endif
|
||
diff -rupN binutils.orig/ld/ldlex.l binutils-2.41/ld/ldlex.l
|
||
--- binutils.orig/ld/ldlex.l 2024-05-13 13:03:47.805601779 +0100
|
||
+++ binutils-2.41/ld/ldlex.l 2024-05-13 13:04:08.599633306 +0100
|
||
@@ -120,11 +120,12 @@ V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([
|
||
parser_input = input_selected;
|
||
switch (t)
|
||
{
|
||
- case input_script: return INPUT_SCRIPT; break;
|
||
- case input_mri_script: return INPUT_MRI_SCRIPT; break;
|
||
- case input_version_script: return INPUT_VERSION_SCRIPT; break;
|
||
- case input_dynamic_list: return INPUT_DYNAMIC_LIST; break;
|
||
- case input_defsym: return INPUT_DEFSYM; break;
|
||
+ case input_script: return INPUT_SCRIPT;
|
||
+ case input_mri_script: return INPUT_MRI_SCRIPT;
|
||
+ case input_version_script: return INPUT_VERSION_SCRIPT;
|
||
+ case input_section_ordering_script: return INPUT_SECTION_ORDERING_SCRIPT;
|
||
+ case input_dynamic_list: return INPUT_DYNAMIC_LIST;
|
||
+ case input_defsym: return INPUT_DEFSYM;
|
||
default: abort ();
|
||
}
|
||
}
|
||
diff -rupN binutils.orig/ld/ldmain.c binutils-2.41/ld/ldmain.c
|
||
--- binutils.orig/ld/ldmain.c 2024-05-13 13:03:47.805601779 +0100
|
||
+++ binutils-2.41/ld/ldmain.c 2024-05-13 13:04:08.599633306 +0100
|
||
@@ -90,6 +90,8 @@ bool version_printed;
|
||
/* TRUE if we should demangle symbol names. */
|
||
bool demangling;
|
||
|
||
+bool in_section_ordering;
|
||
+
|
||
args_type command_line;
|
||
|
||
ld_config_type config;
|
||
@@ -246,6 +248,26 @@ ld_bfd_error_handler (const char *fmt, v
|
||
(*default_bfd_error_handler) (fmt, ap);
|
||
}
|
||
|
||
+static void
|
||
+display_external_script (void)
|
||
+{
|
||
+ if (saved_script_handle == NULL)
|
||
+ return;
|
||
+
|
||
+ static const int ld_bufsz = 8193;
|
||
+ size_t n;
|
||
+ char *buf = (char *) xmalloc (ld_bufsz);
|
||
+
|
||
+ rewind (saved_script_handle);
|
||
+ while ((n = fread (buf, 1, ld_bufsz - 1, saved_script_handle)) > 0)
|
||
+ {
|
||
+ buf[n] = 0;
|
||
+ info_msg ("%s", buf);
|
||
+ }
|
||
+ rewind (saved_script_handle);
|
||
+ free (buf);
|
||
+}
|
||
+
|
||
int
|
||
main (int argc, char **argv)
|
||
{
|
||
@@ -416,26 +438,13 @@ main (int argc, char **argv)
|
||
if (verbose)
|
||
{
|
||
if (saved_script_handle)
|
||
- info_msg (_("using external linker script:"));
|
||
+ info_msg (_("using external linker script: %s"), processed_scripts->name);
|
||
else
|
||
info_msg (_("using internal linker script:"));
|
||
info_msg ("\n==================================================\n");
|
||
|
||
if (saved_script_handle)
|
||
- {
|
||
- static const int ld_bufsz = 8193;
|
||
- size_t n;
|
||
- char *buf = (char *) xmalloc (ld_bufsz);
|
||
-
|
||
- rewind (saved_script_handle);
|
||
- while ((n = fread (buf, 1, ld_bufsz - 1, saved_script_handle)) > 0)
|
||
- {
|
||
- buf[n] = 0;
|
||
- info_msg ("%s", buf);
|
||
- }
|
||
- rewind (saved_script_handle);
|
||
- free (buf);
|
||
- }
|
||
+ display_external_script ();
|
||
else
|
||
{
|
||
int isfile;
|
||
@@ -446,6 +455,22 @@ main (int argc, char **argv)
|
||
info_msg ("\n==================================================\n");
|
||
}
|
||
|
||
+ if (command_line.section_ordering_file)
|
||
+ {
|
||
+ FILE *hold_script_handle;
|
||
+
|
||
+ hold_script_handle = saved_script_handle;
|
||
+ ldfile_open_command_file (command_line.section_ordering_file);
|
||
+ if (verbose)
|
||
+ display_external_script ();
|
||
+ saved_script_handle = hold_script_handle;
|
||
+ in_section_ordering = true;
|
||
+ parser_input = input_section_ordering_script;
|
||
+ yyparse ();
|
||
+ in_section_ordering = false;
|
||
+
|
||
+ }
|
||
+
|
||
if (command_line.force_group_allocation
|
||
|| !bfd_link_relocatable (&link_info))
|
||
link_info.resolve_section_groups = true;
|
||
diff -rupN binutils.orig/ld/lexsup.c binutils-2.41/ld/lexsup.c
|
||
--- binutils.orig/ld/lexsup.c 2024-05-13 13:03:48.141602288 +0100
|
||
+++ binutils-2.41/ld/lexsup.c 2024-05-13 13:04:08.599633306 +0100
|
||
@@ -484,6 +484,9 @@ static const struct ld_option ld_options
|
||
{ {"sort-section", required_argument, NULL, OPTION_SORT_SECTION},
|
||
'\0', N_("name|alignment"),
|
||
N_("Sort sections by name or maximum alignment"), TWO_DASHES },
|
||
+ { {"section-ordering-file", required_argument, NULL, OPTION_SECTION_ORDERING_FILE},
|
||
+ '\0', N_("FILE"),
|
||
+ N_("Sort sections by statements in FILE"), TWO_DASHES },
|
||
{ {"spare-dynamic-tags", required_argument, NULL, OPTION_SPARE_DYNAMIC_TAGS},
|
||
'\0', N_("COUNT"), N_("How many tags to reserve in .dynamic section"),
|
||
TWO_DASHES },
|
||
@@ -1394,6 +1397,12 @@ parse_args (unsigned argc, char **argv)
|
||
einfo (_("%F%P: invalid section sorting option: %s\n"),
|
||
optarg);
|
||
break;
|
||
+ case OPTION_SECTION_ORDERING_FILE:
|
||
+ if (command_line.section_ordering_file != NULL
|
||
+ && strcmp (optarg, command_line.section_ordering_file) != 0)
|
||
+ einfo (_("%P: warning: section ordering file changed. Ignoring earlier definition\n"));
|
||
+ command_line.section_ordering_file = optarg;
|
||
+ break;
|
||
case OPTION_STATS:
|
||
config.stats = true;
|
||
break;
|
||
diff -rupN binutils.orig/ld/lexsup.c.orig binutils-2.41/ld/lexsup.c.orig
|
||
--- binutils.orig/ld/lexsup.c.orig 1970-01-01 01:00:00.000000000 +0100
|
||
+++ binutils-2.41/ld/lexsup.c.orig 2024-05-13 13:03:25.177567469 +0100
|
||
@@ -0,0 +1,2476 @@
|
||
+/* Parse options for the GNU linker.
|
||
+ Copyright (C) 1991-2023 Free Software Foundation, Inc.
|
||
+
|
||
+ This file is part of the GNU Binutils.
|
||
+
|
||
+ This program is free software; you can redistribute it and/or modify
|
||
+ it under the terms of the GNU General Public License as published by
|
||
+ the Free Software Foundation; either version 3 of the License, or
|
||
+ (at your option) any later version.
|
||
+
|
||
+ This program is distributed in the hope that it will be useful,
|
||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
+ GNU General Public License for more details.
|
||
+
|
||
+ You should have received a copy of the GNU General Public License
|
||
+ along with this program; if not, write to the Free Software
|
||
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
|
||
+ MA 02110-1301, USA. */
|
||
+
|
||
+#include "sysdep.h"
|
||
+#include "bfd.h"
|
||
+#include "bfdver.h"
|
||
+#include "libiberty.h"
|
||
+#include "filenames.h"
|
||
+#include <stdio.h>
|
||
+#include <string.h>
|
||
+#include <errno.h>
|
||
+#include "safe-ctype.h"
|
||
+#include "getopt.h"
|
||
+#include "bfdlink.h"
|
||
+#include "ctf-api.h"
|
||
+#include "ld.h"
|
||
+#include "ldmain.h"
|
||
+#include "ldmisc.h"
|
||
+#include "ldexp.h"
|
||
+#include "ldlang.h"
|
||
+#include <ldgram.h>
|
||
+#include "ldlex.h"
|
||
+#include "ldfile.h"
|
||
+#include "ldver.h"
|
||
+#include "ldemul.h"
|
||
+#include "demangle.h"
|
||
+#if BFD_SUPPORTS_PLUGINS
|
||
+#include "plugin.h"
|
||
+#endif /* BFD_SUPPORTS_PLUGINS */
|
||
+
|
||
+#ifndef PATH_SEPARATOR
|
||
+#if defined (__MSDOS__) || (defined (_WIN32) && ! defined (__CYGWIN32__))
|
||
+#define PATH_SEPARATOR ';'
|
||
+#else
|
||
+#define PATH_SEPARATOR ':'
|
||
+#endif
|
||
+#endif
|
||
+
|
||
+/* Somewhere above, sys/stat.h got included . . . . */
|
||
+#if !defined(S_ISDIR) && defined(S_IFDIR)
|
||
+#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
|
||
+#endif
|
||
+
|
||
+static void set_default_dirlist (char *);
|
||
+static void set_section_start (char *, char *);
|
||
+static void set_segment_start (const char *, char *);
|
||
+static void help (void);
|
||
+
|
||
+/* The long options. This structure is used for both the option
|
||
+ parsing and the help text. */
|
||
+
|
||
+enum control_enum {
|
||
+ /* Use one dash before long option name. */
|
||
+ ONE_DASH = 1,
|
||
+ /* Use two dashes before long option name. */
|
||
+ TWO_DASHES = 2,
|
||
+ /* Only accept two dashes before the long option name.
|
||
+ This is an overloading of the use of this enum, since originally it
|
||
+ was only intended to tell the --help display function how to display
|
||
+ the long option name. This feature was added in order to resolve
|
||
+ the confusion about the -omagic command line switch. Is it setting
|
||
+ the output file name to "magic" or is it setting the NMAGIC flag on
|
||
+ the output ? It has been decided that it is setting the output file
|
||
+ name, and that if you want to set the NMAGIC flag you should use -N
|
||
+ or --omagic. */
|
||
+ EXACTLY_TWO_DASHES,
|
||
+ /* Don't mention this option in --help output. */
|
||
+ NO_HELP
|
||
+};
|
||
+
|
||
+struct ld_option
|
||
+{
|
||
+ /* The long option information. */
|
||
+ struct option opt;
|
||
+ /* The short option with the same meaning ('\0' if none). */
|
||
+ char shortopt;
|
||
+ /* The name of the argument (NULL if none). */
|
||
+ const char *arg;
|
||
+ /* The documentation string. If this is NULL, this is a synonym for
|
||
+ the previous option. */
|
||
+ const char *doc;
|
||
+ enum control_enum control;
|
||
+};
|
||
+
|
||
+static const struct ld_option ld_options[] =
|
||
+{
|
||
+ { {NULL, required_argument, NULL, '\0'},
|
||
+ 'a', N_("KEYWORD"), N_("Shared library control for HP/UX compatibility"),
|
||
+ ONE_DASH },
|
||
+ { {"architecture", required_argument, NULL, 'A'},
|
||
+ 'A', N_("ARCH"), N_("Set architecture") , TWO_DASHES },
|
||
+ { {"format", required_argument, NULL, 'b'},
|
||
+ 'b', N_("TARGET"), N_("Specify target for following input files"),
|
||
+ TWO_DASHES },
|
||
+ { {"mri-script", required_argument, NULL, 'c'},
|
||
+ 'c', N_("FILE"), N_("Read MRI format linker script"), TWO_DASHES },
|
||
+ { {"dc", no_argument, NULL, 'd'},
|
||
+ 'd', NULL, N_("Force common symbols to be defined"), ONE_DASH },
|
||
+ { {"dp", no_argument, NULL, 'd'},
|
||
+ '\0', NULL, NULL, ONE_DASH },
|
||
+ { {"dependency-file", required_argument, NULL, OPTION_DEPENDENCY_FILE},
|
||
+ '\0', N_("FILE"), N_("Write dependency file"), TWO_DASHES },
|
||
+ { {"force-group-allocation", no_argument, NULL,
|
||
+ OPTION_FORCE_GROUP_ALLOCATION},
|
||
+ '\0', NULL, N_("Force group members out of groups"), TWO_DASHES },
|
||
+ { {"entry", required_argument, NULL, 'e'},
|
||
+ 'e', N_("ADDRESS"), N_("Set start address"), TWO_DASHES },
|
||
+ { {"export-dynamic", no_argument, NULL, OPTION_EXPORT_DYNAMIC},
|
||
+ 'E', NULL, N_("Export all dynamic symbols"), TWO_DASHES },
|
||
+ { {"no-export-dynamic", no_argument, NULL, OPTION_NO_EXPORT_DYNAMIC},
|
||
+ '\0', NULL, N_("Undo the effect of --export-dynamic"), TWO_DASHES },
|
||
+ { {"enable-non-contiguous-regions", no_argument, NULL, OPTION_NON_CONTIGUOUS_REGIONS},
|
||
+ '\0', NULL, N_("Enable support of non-contiguous memory regions"), TWO_DASHES },
|
||
+ { {"enable-non-contiguous-regions-warnings", no_argument, NULL, OPTION_NON_CONTIGUOUS_REGIONS_WARNINGS},
|
||
+ '\0', NULL, N_("Enable warnings when --enable-non-contiguous-regions may cause unexpected behaviour"), TWO_DASHES },
|
||
+ { {"disable-linker-version", no_argument, NULL, OPTION_DISABLE_LINKER_VERSION},
|
||
+ '\0', NULL, N_("Disable the LINKER_VERSION linker script directive"), TWO_DASHES },
|
||
+ { {"enable-linker-version", no_argument, NULL, OPTION_ENABLE_LINKER_VERSION},
|
||
+ '\0', NULL, N_("Enable the LINKER_VERSION linker script directive"), TWO_DASHES },
|
||
+ { {"EB", no_argument, NULL, OPTION_EB},
|
||
+ '\0', NULL, N_("Link big-endian objects"), ONE_DASH },
|
||
+ { {"EL", no_argument, NULL, OPTION_EL},
|
||
+ '\0', NULL, N_("Link little-endian objects"), ONE_DASH },
|
||
+ { {"auxiliary", required_argument, NULL, 'f'},
|
||
+ 'f', N_("SHLIB"), N_("Auxiliary filter for shared object symbol table"),
|
||
+ TWO_DASHES },
|
||
+ { {"filter", required_argument, NULL, 'F'},
|
||
+ 'F', N_("SHLIB"), N_("Filter for shared object symbol table"),
|
||
+ TWO_DASHES },
|
||
+ { {NULL, no_argument, NULL, '\0'},
|
||
+ 'g', NULL, N_("Ignored"), ONE_DASH },
|
||
+ { {"gpsize", required_argument, NULL, 'G'},
|
||
+ 'G', N_("SIZE"), N_("Small data size (if no size, same as --shared)"),
|
||
+ TWO_DASHES },
|
||
+ { {"soname", required_argument, NULL, OPTION_SONAME},
|
||
+ 'h', N_("FILENAME"), N_("Set internal name of shared library"), ONE_DASH },
|
||
+ { {"dynamic-linker", required_argument, NULL, OPTION_DYNAMIC_LINKER},
|
||
+ 'I', N_("PROGRAM"), N_("Set PROGRAM as the dynamic linker to use"),
|
||
+ TWO_DASHES },
|
||
+ { {"no-dynamic-linker", no_argument, NULL, OPTION_NO_DYNAMIC_LINKER},
|
||
+ '\0', NULL, N_("Produce an executable with no program interpreter header"),
|
||
+ TWO_DASHES },
|
||
+ { {"library", required_argument, NULL, 'l'},
|
||
+ 'l', N_("LIBNAME"), N_("Search for library LIBNAME"), TWO_DASHES },
|
||
+ { {"library-path", required_argument, NULL, 'L'},
|
||
+ 'L', N_("DIRECTORY"), N_("Add DIRECTORY to library search path"),
|
||
+ TWO_DASHES },
|
||
+ { {"sysroot=<DIRECTORY>", required_argument, NULL, OPTION_SYSROOT},
|
||
+ '\0', NULL, N_("Override the default sysroot location"), TWO_DASHES },
|
||
+ { {NULL, required_argument, NULL, '\0'},
|
||
+ 'm', N_("EMULATION"), N_("Set emulation"), ONE_DASH },
|
||
+ { {"print-map", no_argument, NULL, 'M'},
|
||
+ 'M', NULL, N_("Print map file on standard output"), TWO_DASHES },
|
||
+ { {"nmagic", no_argument, NULL, 'n'},
|
||
+ 'n', NULL, N_("Do not page align data"), TWO_DASHES },
|
||
+ { {"omagic", no_argument, NULL, 'N'},
|
||
+ 'N', NULL, N_("Do not page align data, do not make text readonly"),
|
||
+ EXACTLY_TWO_DASHES },
|
||
+ { {"no-omagic", no_argument, NULL, OPTION_NO_OMAGIC},
|
||
+ '\0', NULL, N_("Page align data, make text readonly"),
|
||
+ EXACTLY_TWO_DASHES },
|
||
+ { {"output", required_argument, NULL, 'o'},
|
||
+ 'o', N_("FILE"), N_("Set output file name"), EXACTLY_TWO_DASHES },
|
||
+ { {NULL, required_argument, NULL, '\0'},
|
||
+ 'O', NULL, N_("Optimize output file"), ONE_DASH },
|
||
+ { {"out-implib", required_argument, NULL, OPTION_OUT_IMPLIB},
|
||
+ '\0', N_("FILE"), N_("Generate import library"), TWO_DASHES },
|
||
+#if BFD_SUPPORTS_PLUGINS
|
||
+ { {"plugin", required_argument, NULL, OPTION_PLUGIN},
|
||
+ '\0', N_("PLUGIN"), N_("Load named plugin"), ONE_DASH },
|
||
+ { {"plugin-opt", required_argument, NULL, OPTION_PLUGIN_OPT},
|
||
+ '\0', N_("ARG"), N_("Send arg to last-loaded plugin"), ONE_DASH },
|
||
+ { {"flto", optional_argument, NULL, OPTION_IGNORE},
|
||
+ '\0', NULL, N_("Ignored for GCC LTO option compatibility"),
|
||
+ ONE_DASH },
|
||
+ { {"flto-partition=", required_argument, NULL, OPTION_IGNORE},
|
||
+ '\0', NULL, N_("Ignored for GCC LTO option compatibility"),
|
||
+ ONE_DASH },
|
||
+#else
|
||
+ { {"plugin", required_argument, NULL, OPTION_IGNORE},
|
||
+ '\0', N_("PLUGIN"), N_("Load named plugin (ignored)"), ONE_DASH },
|
||
+ { {"plugin-opt", required_argument, NULL, OPTION_IGNORE},
|
||
+ '\0', N_("ARG"), N_("Send arg to last-loaded plugin (ignored)"), ONE_DASH },
|
||
+#endif /* BFD_SUPPORTS_PLUGINS */
|
||
+ { {"fuse-ld=", required_argument, NULL, OPTION_IGNORE},
|
||
+ '\0', NULL, N_("Ignored for GCC linker option compatibility"),
|
||
+ ONE_DASH },
|
||
+ { {"map-whole-files", optional_argument, NULL, OPTION_IGNORE},
|
||
+ '\0', NULL, N_("Ignored for gold option compatibility"),
|
||
+ TWO_DASHES },
|
||
+ { {"no-map-whole-files", optional_argument, NULL, OPTION_IGNORE},
|
||
+ '\0', NULL, N_("Ignored for gold option compatibility"),
|
||
+ TWO_DASHES },
|
||
+ { {"Qy", no_argument, NULL, OPTION_IGNORE},
|
||
+ '\0', NULL, N_("Ignored for SVR4 compatibility"), ONE_DASH },
|
||
+ { {"emit-relocs", no_argument, NULL, 'q'},
|
||
+ 'q', NULL, "Generate relocations in final output", TWO_DASHES },
|
||
+ { {"relocatable", no_argument, NULL, 'r'},
|
||
+ 'r', NULL, N_("Generate relocatable output"), TWO_DASHES },
|
||
+ { {NULL, no_argument, NULL, '\0'},
|
||
+ 'i', NULL, NULL, ONE_DASH },
|
||
+ { {"just-symbols", required_argument, NULL, 'R'},
|
||
+ 'R', N_("FILE"), N_("Just link symbols (if directory, same as --rpath)"),
|
||
+ TWO_DASHES },
|
||
+
|
||
+ { {"remap-inputs-file", required_argument, NULL, OPTION_REMAP_INPUTS_FILE},
|
||
+ '\0', N_("FILE"), "Provide a FILE containing input remapings", TWO_DASHES },
|
||
+ { {"remap-inputs", required_argument, NULL, OPTION_REMAP_INPUTS},
|
||
+ '\0', N_("PATTERN=FILE"), "Remap input files matching PATTERN to FILE", TWO_DASHES },
|
||
+
|
||
+ { {"strip-all", no_argument, NULL, 's'},
|
||
+ 's', NULL, N_("Strip all symbols"), TWO_DASHES },
|
||
+ { {"strip-debug", no_argument, NULL, 'S'},
|
||
+ 'S', NULL, N_("Strip debugging symbols"), TWO_DASHES },
|
||
+ { {"strip-discarded", no_argument, NULL, OPTION_STRIP_DISCARDED},
|
||
+ '\0', NULL, N_("Strip symbols in discarded sections"), TWO_DASHES },
|
||
+ { {"no-strip-discarded", no_argument, NULL, OPTION_NO_STRIP_DISCARDED},
|
||
+ '\0', NULL, N_("Do not strip symbols in discarded sections"), TWO_DASHES },
|
||
+ { {"trace", no_argument, NULL, 't'},
|
||
+ 't', NULL, N_("Trace file opens"), TWO_DASHES },
|
||
+ { {"script", required_argument, NULL, 'T'},
|
||
+ 'T', N_("FILE"), N_("Read linker script"), TWO_DASHES },
|
||
+ { {"default-script", required_argument, NULL, OPTION_DEFAULT_SCRIPT},
|
||
+ '\0', N_("FILE"), N_("Read default linker script"), TWO_DASHES },
|
||
+ { {"dT", required_argument, NULL, OPTION_DEFAULT_SCRIPT},
|
||
+ '\0', NULL, NULL, ONE_DASH },
|
||
+ { {"undefined", required_argument, NULL, 'u'},
|
||
+ 'u', N_("SYMBOL"), N_("Start with undefined reference to SYMBOL"),
|
||
+ TWO_DASHES },
|
||
+ { {"require-defined", required_argument, NULL, OPTION_REQUIRE_DEFINED_SYMBOL},
|
||
+ '\0', N_("SYMBOL"), N_("Require SYMBOL be defined in the final output"),
|
||
+ TWO_DASHES },
|
||
+ { {"unique", optional_argument, NULL, OPTION_UNIQUE},
|
||
+ '\0', N_("[=SECTION]"),
|
||
+ N_("Don't merge input [SECTION | orphan] sections"), TWO_DASHES },
|
||
+ { {"Ur", no_argument, NULL, OPTION_UR},
|
||
+ '\0', NULL, N_("Build global constructor/destructor tables"), ONE_DASH },
|
||
+ { {"version", no_argument, NULL, OPTION_VERSION},
|
||
+ 'v', NULL, N_("Print version information"), TWO_DASHES },
|
||
+ { {NULL, no_argument, NULL, '\0'},
|
||
+ 'V', NULL, N_("Print version and emulation information"), ONE_DASH },
|
||
+ { {"discard-all", no_argument, NULL, 'x'},
|
||
+ 'x', NULL, N_("Discard all local symbols"), TWO_DASHES },
|
||
+ { {"discard-locals", no_argument, NULL, 'X'},
|
||
+ 'X', NULL, N_("Discard temporary local symbols (default)"), TWO_DASHES },
|
||
+ { {"discard-none", no_argument, NULL, OPTION_DISCARD_NONE},
|
||
+ '\0', NULL, N_("Don't discard any local symbols"), TWO_DASHES },
|
||
+ { {"trace-symbol", required_argument, NULL, 'y'},
|
||
+ 'y', N_("SYMBOL"), N_("Trace mentions of SYMBOL"), TWO_DASHES },
|
||
+ { {NULL, required_argument, NULL, '\0'},
|
||
+ 'Y', N_("PATH"), N_("Default search path for Solaris compatibility"),
|
||
+ ONE_DASH },
|
||
+ { {"start-group", no_argument, NULL, '('},
|
||
+ '(', NULL, N_("Start a group"), TWO_DASHES },
|
||
+ { {"end-group", no_argument, NULL, ')'},
|
||
+ ')', NULL, N_("End a group"), TWO_DASHES },
|
||
+ { {"accept-unknown-input-arch", no_argument, NULL,
|
||
+ OPTION_ACCEPT_UNKNOWN_INPUT_ARCH},
|
||
+ '\0', NULL,
|
||
+ N_("Accept input files whose architecture cannot be determined"),
|
||
+ TWO_DASHES },
|
||
+ { {"no-accept-unknown-input-arch", no_argument, NULL,
|
||
+ OPTION_NO_ACCEPT_UNKNOWN_INPUT_ARCH},
|
||
+ '\0', NULL, N_("Reject input files whose architecture is unknown"),
|
||
+ TWO_DASHES },
|
||
+
|
||
+ /* The next two options are deprecated because of their similarity to
|
||
+ --as-needed and --no-as-needed. They have been replaced by
|
||
+ --copy-dt-needed-entries and --no-copy-dt-needed-entries. */
|
||
+ { {"add-needed", no_argument, NULL, OPTION_ADD_DT_NEEDED_FOR_DYNAMIC},
|
||
+ '\0', NULL, NULL, NO_HELP },
|
||
+ { {"no-add-needed", no_argument, NULL, OPTION_NO_ADD_DT_NEEDED_FOR_DYNAMIC},
|
||
+ '\0', NULL, NULL, NO_HELP },
|
||
+
|
||
+ { {"as-needed", no_argument, NULL, OPTION_ADD_DT_NEEDED_FOR_REGULAR},
|
||
+ '\0', NULL, N_("Only set DT_NEEDED for following dynamic libs if used"),
|
||
+ TWO_DASHES },
|
||
+ { {"no-as-needed", no_argument, NULL, OPTION_NO_ADD_DT_NEEDED_FOR_REGULAR},
|
||
+ '\0', NULL, N_("Always set DT_NEEDED for dynamic libraries mentioned on\n"
|
||
+ " the command line"),
|
||
+ TWO_DASHES },
|
||
+ { {"assert", required_argument, NULL, OPTION_ASSERT},
|
||
+ '\0', N_("KEYWORD"), N_("Ignored for SunOS compatibility"), ONE_DASH },
|
||
+ { {"Bdynamic", no_argument, NULL, OPTION_CALL_SHARED},
|
||
+ '\0', NULL, N_("Link against shared libraries"), ONE_DASH },
|
||
+ { {"dy", no_argument, NULL, OPTION_CALL_SHARED},
|
||
+ '\0', NULL, NULL, ONE_DASH },
|
||
+ { {"call_shared", no_argument, NULL, OPTION_CALL_SHARED},
|
||
+ '\0', NULL, NULL, ONE_DASH },
|
||
+ { {"Bstatic", no_argument, NULL, OPTION_NON_SHARED},
|
||
+ '\0', NULL, N_("Do not link against shared libraries"), ONE_DASH },
|
||
+ { {"dn", no_argument, NULL, OPTION_NON_SHARED},
|
||
+ '\0', NULL, NULL, ONE_DASH },
|
||
+ { {"non_shared", no_argument, NULL, OPTION_NON_SHARED},
|
||
+ '\0', NULL, NULL, ONE_DASH },
|
||
+ { {"static", no_argument, NULL, OPTION_NON_SHARED},
|
||
+ '\0', NULL, NULL, ONE_DASH },
|
||
+ { {"Bno-symbolic", no_argument, NULL, OPTION_NO_SYMBOLIC},
|
||
+ '\0', NULL, N_("Don't bind global references locally"), ONE_DASH },
|
||
+ { {"Bsymbolic", no_argument, NULL, OPTION_SYMBOLIC},
|
||
+ '\0', NULL, N_("Bind global references locally"), ONE_DASH },
|
||
+ { {"Bsymbolic-functions", no_argument, NULL, OPTION_SYMBOLIC_FUNCTIONS},
|
||
+ '\0', NULL, N_("Bind global function references locally"), ONE_DASH },
|
||
+ { {"check-sections", no_argument, NULL, OPTION_CHECK_SECTIONS},
|
||
+ '\0', NULL, N_("Check section addresses for overlaps (default)"),
|
||
+ TWO_DASHES },
|
||
+ { {"no-check-sections", no_argument, NULL, OPTION_NO_CHECK_SECTIONS},
|
||
+ '\0', NULL, N_("Do not check section addresses for overlaps"),
|
||
+ TWO_DASHES },
|
||
+ { {"copy-dt-needed-entries", no_argument, NULL,
|
||
+ OPTION_ADD_DT_NEEDED_FOR_DYNAMIC},
|
||
+ '\0', NULL, N_("Copy DT_NEEDED links mentioned inside DSOs that follow"),
|
||
+ TWO_DASHES },
|
||
+ { {"no-copy-dt-needed-entries", no_argument, NULL,
|
||
+ OPTION_NO_ADD_DT_NEEDED_FOR_DYNAMIC},
|
||
+ '\0', NULL, N_("Do not copy DT_NEEDED links mentioned inside DSOs that follow"),
|
||
+ TWO_DASHES },
|
||
+
|
||
+ { {"cref", no_argument, NULL, OPTION_CREF},
|
||
+ '\0', NULL, N_("Output cross reference table"), TWO_DASHES },
|
||
+ { {"defsym", required_argument, NULL, OPTION_DEFSYM},
|
||
+ '\0', N_("SYMBOL=EXPRESSION"), N_("Define a symbol"), TWO_DASHES },
|
||
+ { {"demangle", optional_argument, NULL, OPTION_DEMANGLE},
|
||
+ '\0', N_("[=STYLE]"), N_("Demangle symbol names [using STYLE]"),
|
||
+ TWO_DASHES },
|
||
+ { {"disable-multiple-abs-defs", no_argument, NULL,
|
||
+ OPTION_DISABLE_MULTIPLE_DEFS_ABS},
|
||
+ '\0', NULL, N_("Do not allow multiple definitions with symbols included\n"
|
||
+ " in filename invoked by -R "
|
||
+ "or --just-symbols"),
|
||
+ TWO_DASHES},
|
||
+ { {"embedded-relocs", no_argument, NULL, OPTION_EMBEDDED_RELOCS},
|
||
+ '\0', NULL, N_("Generate embedded relocs"), TWO_DASHES},
|
||
+ { {"fatal-warnings", no_argument, NULL, OPTION_WARN_FATAL},
|
||
+ '\0', NULL, N_("Treat warnings as errors"),
|
||
+ TWO_DASHES },
|
||
+ { {"no-fatal-warnings", no_argument, NULL, OPTION_NO_WARN_FATAL},
|
||
+ '\0', NULL, N_("Do not treat warnings as errors (default)"),
|
||
+ TWO_DASHES },
|
||
+ { {"fini", required_argument, NULL, OPTION_FINI},
|
||
+ '\0', N_("SYMBOL"), N_("Call SYMBOL at unload-time"), ONE_DASH },
|
||
+ { {"force-exe-suffix", no_argument, NULL, OPTION_FORCE_EXE_SUFFIX},
|
||
+ '\0', NULL, N_("Force generation of file with .exe suffix"), TWO_DASHES},
|
||
+ { {"gc-sections", no_argument, NULL, OPTION_GC_SECTIONS},
|
||
+ '\0', NULL, N_("Remove unused sections (on some targets)"),
|
||
+ TWO_DASHES },
|
||
+ { {"no-gc-sections", no_argument, NULL, OPTION_NO_GC_SECTIONS},
|
||
+ '\0', NULL, N_("Don't remove unused sections (default)"),
|
||
+ TWO_DASHES },
|
||
+ { {"print-gc-sections", no_argument, NULL, OPTION_PRINT_GC_SECTIONS},
|
||
+ '\0', NULL, N_("List removed unused sections on stderr"),
|
||
+ TWO_DASHES },
|
||
+ { {"no-print-gc-sections", no_argument, NULL, OPTION_NO_PRINT_GC_SECTIONS},
|
||
+ '\0', NULL, N_("Do not list removed unused sections"),
|
||
+ TWO_DASHES },
|
||
+ { {"gc-keep-exported", no_argument, NULL, OPTION_GC_KEEP_EXPORTED},
|
||
+ '\0', NULL, N_("Keep exported symbols when removing unused sections"),
|
||
+ TWO_DASHES },
|
||
+ { {"hash-size=<NUMBER>", required_argument, NULL, OPTION_HASH_SIZE},
|
||
+ '\0', NULL, N_("Set default hash table size close to <NUMBER>"),
|
||
+ TWO_DASHES },
|
||
+ { {"help", no_argument, NULL, OPTION_HELP},
|
||
+ '\0', NULL, N_("Print option help"), TWO_DASHES },
|
||
+ { {"init", required_argument, NULL, OPTION_INIT},
|
||
+ '\0', N_("SYMBOL"), N_("Call SYMBOL at load-time"), ONE_DASH },
|
||
+ { {"Map", required_argument, NULL, OPTION_MAP},
|
||
+ '\0', N_("FILE/DIR"), N_("Write a linker map to FILE or DIR/<outputname>.map"), ONE_DASH },
|
||
+ { {"no-define-common", no_argument, NULL, OPTION_NO_DEFINE_COMMON},
|
||
+ '\0', NULL, N_("Do not define Common storage"), TWO_DASHES },
|
||
+ { {"no-demangle", no_argument, NULL, OPTION_NO_DEMANGLE },
|
||
+ '\0', NULL, N_("Do not demangle symbol names"), TWO_DASHES },
|
||
+ { {"no-keep-memory", no_argument, NULL, OPTION_NO_KEEP_MEMORY},
|
||
+ '\0', NULL, N_("Use less memory and more disk I/O"), TWO_DASHES },
|
||
+ { {"no-undefined", no_argument, NULL, OPTION_NO_UNDEFINED},
|
||
+ '\0', NULL, N_("Do not allow unresolved references in object files"),
|
||
+ TWO_DASHES },
|
||
+ { {"no-warnings", no_argument, NULL, OPTION_NO_WARNINGS},
|
||
+ 'w', NULL, N_("Do not display any warning or error messages"),
|
||
+ TWO_DASHES },
|
||
+ { {"allow-shlib-undefined", no_argument, NULL, OPTION_ALLOW_SHLIB_UNDEFINED},
|
||
+ '\0', NULL, N_("Allow unresolved references in shared libraries"),
|
||
+ TWO_DASHES },
|
||
+ { {"no-allow-shlib-undefined", no_argument, NULL,
|
||
+ OPTION_NO_ALLOW_SHLIB_UNDEFINED},
|
||
+ '\0', NULL, N_("Do not allow unresolved references in shared libs"),
|
||
+ TWO_DASHES },
|
||
+ { {"allow-multiple-definition", no_argument, NULL,
|
||
+ OPTION_ALLOW_MULTIPLE_DEFINITION},
|
||
+ '\0', NULL, N_("Allow multiple definitions"), TWO_DASHES },
|
||
+#if SUPPORT_ERROR_HANDLING_SCRIPT
|
||
+ { {"error-handling-script", required_argument, NULL,
|
||
+ OPTION_ERROR_HANDLING_SCRIPT},
|
||
+ '\0', N_("SCRIPT"), N_("Provide a script to help with undefined symbol errors"), TWO_DASHES},
|
||
+#endif
|
||
+ { {"undefined-version", no_argument, NULL, OPTION_UNDEFINED_VERSION},
|
||
+ '\0', NULL, N_("Allow undefined version"), EXACTLY_TWO_DASHES },
|
||
+ { {"no-undefined-version", no_argument, NULL, OPTION_NO_UNDEFINED_VERSION},
|
||
+ '\0', NULL, N_("Disallow undefined version"), TWO_DASHES },
|
||
+ { {"default-symver", no_argument, NULL, OPTION_DEFAULT_SYMVER},
|
||
+ '\0', NULL, N_("Create default symbol version"), TWO_DASHES },
|
||
+ { {"default-imported-symver", no_argument, NULL,
|
||
+ OPTION_DEFAULT_IMPORTED_SYMVER},
|
||
+ '\0', NULL, N_("Create default symbol version for imported symbols"),
|
||
+ TWO_DASHES },
|
||
+ { {"no-warn-mismatch", no_argument, NULL, OPTION_NO_WARN_MISMATCH},
|
||
+ '\0', NULL, N_("Don't warn about mismatched input files"), TWO_DASHES},
|
||
+ { {"no-warn-search-mismatch", no_argument, NULL,
|
||
+ OPTION_NO_WARN_SEARCH_MISMATCH},
|
||
+ '\0', NULL, N_("Don't warn on finding an incompatible library"),
|
||
+ TWO_DASHES},
|
||
+ { {"no-whole-archive", no_argument, NULL, OPTION_NO_WHOLE_ARCHIVE},
|
||
+ '\0', NULL, N_("Turn off --whole-archive"), TWO_DASHES },
|
||
+ { {"noinhibit-exec", no_argument, NULL, OPTION_NOINHIBIT_EXEC},
|
||
+ '\0', NULL, N_("Create an output file even if errors occur"),
|
||
+ TWO_DASHES },
|
||
+ { {"noinhibit_exec", no_argument, NULL, OPTION_NOINHIBIT_EXEC},
|
||
+ '\0', NULL, NULL, NO_HELP },
|
||
+ { {"nostdlib", no_argument, NULL, OPTION_NOSTDLIB},
|
||
+ '\0', NULL, N_("Only use library directories specified on\n"
|
||
+ " the command line"),
|
||
+ ONE_DASH },
|
||
+ { {"oformat", required_argument, NULL, OPTION_OFORMAT},
|
||
+ '\0', N_("TARGET"), N_("Specify target of output file"),
|
||
+ EXACTLY_TWO_DASHES },
|
||
+ { {"print-output-format", no_argument, NULL, OPTION_PRINT_OUTPUT_FORMAT},
|
||
+ '\0', NULL, N_("Print default output format"), TWO_DASHES },
|
||
+ { {"print-sysroot", no_argument, NULL, OPTION_PRINT_SYSROOT},
|
||
+ '\0', NULL, N_("Print current sysroot"), TWO_DASHES },
|
||
+ { {"qmagic", no_argument, NULL, OPTION_IGNORE},
|
||
+ '\0', NULL, N_("Ignored for Linux compatibility"), ONE_DASH },
|
||
+ { {"reduce-memory-overheads", no_argument, NULL,
|
||
+ OPTION_REDUCE_MEMORY_OVERHEADS},
|
||
+ '\0', NULL, N_("Reduce memory overheads, possibly taking much longer"),
|
||
+ TWO_DASHES },
|
||
+ { {"max-cache-size=SIZE", required_argument, NULL,
|
||
+ OPTION_MAX_CACHE_SIZE},
|
||
+ '\0', NULL, N_("Set the maximum cache size to SIZE bytes"),
|
||
+ TWO_DASHES },
|
||
+ { {"relax", no_argument, NULL, OPTION_RELAX},
|
||
+ '\0', NULL, N_("Reduce code size by using target specific optimizations"), TWO_DASHES },
|
||
+ { {"no-relax", no_argument, NULL, OPTION_NO_RELAX},
|
||
+ '\0', NULL, N_("Do not use relaxation techniques to reduce code size"), TWO_DASHES },
|
||
+ { {"retain-symbols-file", required_argument, NULL,
|
||
+ OPTION_RETAIN_SYMBOLS_FILE},
|
||
+ '\0', N_("FILE"), N_("Keep only symbols listed in FILE"), TWO_DASHES },
|
||
+ { {"rpath", required_argument, NULL, OPTION_RPATH},
|
||
+ '\0', N_("PATH"), N_("Set runtime shared library search path"), ONE_DASH },
|
||
+ { {"rpath-link", required_argument, NULL, OPTION_RPATH_LINK},
|
||
+ '\0', N_("PATH"), N_("Set link time shared library search path"),
|
||
+ ONE_DASH },
|
||
+ { {"shared", no_argument, NULL, OPTION_SHARED},
|
||
+ '\0', NULL, N_("Create a shared library"), ONE_DASH },
|
||
+ { {"Bshareable", no_argument, NULL, OPTION_SHARED }, /* FreeBSD. */
|
||
+ '\0', NULL, NULL, ONE_DASH },
|
||
+ { {"pie", no_argument, NULL, OPTION_PIE},
|
||
+ '\0', NULL, N_("Create a position independent executable"), ONE_DASH },
|
||
+ { {"pic-executable", no_argument, NULL, OPTION_PIE},
|
||
+ '\0', NULL, NULL, TWO_DASHES },
|
||
+ { {"no-pie", no_argument, NULL, OPTION_NO_PIE},
|
||
+ '\0', NULL, N_("Create a position dependent executable (default)"), ONE_DASH },
|
||
+ { {"sort-common", optional_argument, NULL, OPTION_SORT_COMMON},
|
||
+ '\0', N_("[=ascending|descending]"),
|
||
+ N_("Sort common symbols by alignment [in specified order]"),
|
||
+ TWO_DASHES },
|
||
+ { {"sort_common", no_argument, NULL, OPTION_SORT_COMMON},
|
||
+ '\0', NULL, NULL, NO_HELP },
|
||
+ { {"sort-section", required_argument, NULL, OPTION_SORT_SECTION},
|
||
+ '\0', N_("name|alignment"),
|
||
+ N_("Sort sections by name or maximum alignment"), TWO_DASHES },
|
||
+ { {"spare-dynamic-tags", required_argument, NULL, OPTION_SPARE_DYNAMIC_TAGS},
|
||
+ '\0', N_("COUNT"), N_("How many tags to reserve in .dynamic section"),
|
||
+ TWO_DASHES },
|
||
+ { {"split-by-file", optional_argument, NULL, OPTION_SPLIT_BY_FILE},
|
||
+ '\0', N_("[=SIZE]"), N_("Split output sections every SIZE octets"),
|
||
+ TWO_DASHES },
|
||
+ { {"split-by-reloc", optional_argument, NULL, OPTION_SPLIT_BY_RELOC},
|
||
+ '\0', N_("[=COUNT]"), N_("Split output sections every COUNT relocs"),
|
||
+ TWO_DASHES },
|
||
+ { {"stats", no_argument, NULL, OPTION_STATS},
|
||
+ '\0', NULL, N_("Print memory usage statistics"), TWO_DASHES },
|
||
+ { {"target-help", no_argument, NULL, OPTION_TARGET_HELP},
|
||
+ '\0', NULL, N_("Display target specific options"), TWO_DASHES },
|
||
+ { {"task-link", required_argument, NULL, OPTION_TASK_LINK},
|
||
+ '\0', N_("SYMBOL"), N_("Do task level linking"), TWO_DASHES },
|
||
+ { {"traditional-format", no_argument, NULL, OPTION_TRADITIONAL_FORMAT},
|
||
+ '\0', NULL, N_("Use same format as native linker"), TWO_DASHES },
|
||
+ { {"section-start", required_argument, NULL, OPTION_SECTION_START},
|
||
+ '\0', N_("SECTION=ADDRESS"), N_("Set address of named section"),
|
||
+ TWO_DASHES },
|
||
+ { {"Tbss", required_argument, NULL, OPTION_TBSS},
|
||
+ '\0', N_("ADDRESS"), N_("Set address of .bss section"), ONE_DASH },
|
||
+ { {"Tdata", required_argument, NULL, OPTION_TDATA},
|
||
+ '\0', N_("ADDRESS"), N_("Set address of .data section"), ONE_DASH },
|
||
+ { {"Ttext", required_argument, NULL, OPTION_TTEXT},
|
||
+ '\0', N_("ADDRESS"), N_("Set address of .text section"), ONE_DASH },
|
||
+ { {"Ttext-segment", required_argument, NULL, OPTION_TTEXT_SEGMENT},
|
||
+ '\0', N_("ADDRESS"), N_("Set address of text segment"), ONE_DASH },
|
||
+ { {"Trodata-segment", required_argument, NULL, OPTION_TRODATA_SEGMENT},
|
||
+ '\0', N_("ADDRESS"), N_("Set address of rodata segment"), ONE_DASH },
|
||
+ { {"Tldata-segment", required_argument, NULL, OPTION_TLDATA_SEGMENT},
|
||
+ '\0', N_("ADDRESS"), N_("Set address of ldata segment"), ONE_DASH },
|
||
+ { {"unresolved-symbols=<method>", required_argument, NULL,
|
||
+ OPTION_UNRESOLVED_SYMBOLS},
|
||
+ '\0', NULL, N_("How to handle unresolved symbols. <method> is:\n"
|
||
+ " ignore-all, report-all, ignore-in-object-files,\n"
|
||
+ " ignore-in-shared-libs"),
|
||
+ TWO_DASHES },
|
||
+ { {"verbose", optional_argument, NULL, OPTION_VERBOSE},
|
||
+ '\0', N_("[=NUMBER]"),
|
||
+ N_("Output lots of information during link"), TWO_DASHES },
|
||
+ { {"dll-verbose", no_argument, NULL, OPTION_VERBOSE}, /* Linux. */
|
||
+ '\0', NULL, NULL, NO_HELP },
|
||
+ { {"version-script", required_argument, NULL, OPTION_VERSION_SCRIPT },
|
||
+ '\0', N_("FILE"), N_("Read version information script"), TWO_DASHES },
|
||
+ { {"version-exports-section", required_argument, NULL,
|
||
+ OPTION_VERSION_EXPORTS_SECTION },
|
||
+ '\0', N_("SYMBOL"), N_("Take export symbols list from .exports, using\n"
|
||
+ " SYMBOL as the version."),
|
||
+ TWO_DASHES },
|
||
+ { {"dynamic-list-data", no_argument, NULL, OPTION_DYNAMIC_LIST_DATA},
|
||
+ '\0', NULL, N_("Add data symbols to dynamic list"), TWO_DASHES },
|
||
+ { {"dynamic-list-cpp-new", no_argument, NULL, OPTION_DYNAMIC_LIST_CPP_NEW},
|
||
+ '\0', NULL, N_("Use C++ operator new/delete dynamic list"), TWO_DASHES },
|
||
+ { {"dynamic-list-cpp-typeinfo", no_argument, NULL, OPTION_DYNAMIC_LIST_CPP_TYPEINFO},
|
||
+ '\0', NULL, N_("Use C++ typeinfo dynamic list"), TWO_DASHES },
|
||
+ { {"dynamic-list", required_argument, NULL, OPTION_DYNAMIC_LIST},
|
||
+ '\0', N_("FILE"), N_("Read dynamic list"), TWO_DASHES },
|
||
+ { {"export-dynamic-symbol", required_argument, NULL, OPTION_EXPORT_DYNAMIC_SYMBOL},
|
||
+ '\0', N_("SYMBOL"), N_("Export the specified symbol"), EXACTLY_TWO_DASHES },
|
||
+ { {"export-dynamic-symbol-list", required_argument, NULL, OPTION_EXPORT_DYNAMIC_SYMBOL_LIST},
|
||
+ '\0', N_("FILE"), N_("Read export dynamic symbol list"), EXACTLY_TWO_DASHES },
|
||
+ { {"warn-common", no_argument, NULL, OPTION_WARN_COMMON},
|
||
+ '\0', NULL, N_("Warn about duplicate common symbols"), TWO_DASHES },
|
||
+ { {"warn-constructors", no_argument, NULL, OPTION_WARN_CONSTRUCTORS},
|
||
+ '\0', NULL, N_("Warn if global constructors/destructors are seen"),
|
||
+ TWO_DASHES },
|
||
+
|
||
+ { {"error-execstack", no_argument, NULL, OPTION_ERROR_EXECSTACK},
|
||
+ '\0', NULL, NULL, TWO_DASHES },
|
||
+ { {"no-error-execstack", no_argument, NULL, OPTION_NO_ERROR_EXECSTACK},
|
||
+ '\0', NULL, NULL, TWO_DASHES },
|
||
+ { {"warn-execstack-objects", no_argument, NULL, OPTION_WARN_EXECSTACK_OBJECTS},
|
||
+ '\0', NULL, NULL, TWO_DASHES },
|
||
+ { {"warn-execstack", no_argument, NULL, OPTION_WARN_EXECSTACK},
|
||
+ '\0', NULL, NULL, TWO_DASHES },
|
||
+ { {"no-warn-execstack", no_argument, NULL, OPTION_NO_WARN_EXECSTACK},
|
||
+ '\0', NULL, NULL, TWO_DASHES },
|
||
+
|
||
+ { {"error-rwx-segments", no_argument, NULL, OPTION_ERROR_RWX_SEGMENTS},
|
||
+ '\0', NULL, NULL, TWO_DASHES },
|
||
+ { {"no-error-rwx-segments", no_argument, NULL, OPTION_NO_ERROR_RWX_SEGMENTS},
|
||
+ '\0', NULL, NULL, TWO_DASHES },
|
||
+ { {"warn-rwx-segments", no_argument, NULL, OPTION_WARN_RWX_SEGMENTS},
|
||
+ '\0', NULL, NULL, TWO_DASHES },
|
||
+ { {"no-warn-rwx-segments", no_argument, NULL, OPTION_NO_WARN_RWX_SEGMENTS},
|
||
+ '\0', NULL, NULL, TWO_DASHES },
|
||
+
|
||
+ { {"warn-multiple-gp", no_argument, NULL, OPTION_WARN_MULTIPLE_GP},
|
||
+ '\0', NULL, N_("Warn if the multiple GP values are used"), TWO_DASHES },
|
||
+ { {"warn-once", no_argument, NULL, OPTION_WARN_ONCE},
|
||
+ '\0', NULL, N_("Warn only once per undefined symbol"), TWO_DASHES },
|
||
+ { {"warn-section-align", no_argument, NULL, OPTION_WARN_SECTION_ALIGN},
|
||
+ '\0', NULL, N_("Warn if start of section changes due to alignment"),
|
||
+ TWO_DASHES },
|
||
+ { {"warn-textrel", no_argument, NULL, OPTION_WARN_TEXTREL},
|
||
+ '\0', NULL,
|
||
+#if DEFAULT_LD_TEXTREL_CHECK_WARNING
|
||
+ N_("Warn if output has DT_TEXTREL (default)"),
|
||
+#else
|
||
+ N_("Warn if output has DT_TEXTREL"),
|
||
+#endif
|
||
+ TWO_DASHES },
|
||
+ { {"warn-shared-textrel", no_argument, NULL, OPTION_WARN_TEXTREL},
|
||
+ '\0', NULL, NULL, NO_HELP },
|
||
+ { {"warn-alternate-em", no_argument, NULL, OPTION_WARN_ALTERNATE_EM},
|
||
+ '\0', NULL, N_("Warn if an object has alternate ELF machine code"),
|
||
+ TWO_DASHES },
|
||
+ { {"warn-unresolved-symbols", no_argument, NULL,
|
||
+ OPTION_WARN_UNRESOLVED_SYMBOLS},
|
||
+ '\0', NULL, N_("Report unresolved symbols as warnings"), TWO_DASHES },
|
||
+ { {"error-unresolved-symbols", no_argument, NULL,
|
||
+ OPTION_ERROR_UNRESOLVED_SYMBOLS},
|
||
+ '\0', NULL, N_("Report unresolved symbols as errors"), TWO_DASHES },
|
||
+ { {"whole-archive", no_argument, NULL, OPTION_WHOLE_ARCHIVE},
|
||
+ '\0', NULL, N_("Include all objects from following archives"),
|
||
+ TWO_DASHES },
|
||
+ { {"wrap", required_argument, NULL, OPTION_WRAP},
|
||
+ '\0', N_("SYMBOL"), N_("Use wrapper functions for SYMBOL"), TWO_DASHES },
|
||
+ { {"ignore-unresolved-symbol", required_argument, NULL,
|
||
+ OPTION_IGNORE_UNRESOLVED_SYMBOL},
|
||
+ '\0', N_("SYMBOL"),
|
||
+ N_("Unresolved SYMBOL will not cause an error or warning"), TWO_DASHES },
|
||
+ { {"push-state", no_argument, NULL, OPTION_PUSH_STATE},
|
||
+ '\0', NULL, N_("Push state of flags governing input file handling"),
|
||
+ TWO_DASHES },
|
||
+ { {"pop-state", no_argument, NULL, OPTION_POP_STATE},
|
||
+ '\0', NULL, N_("Pop state of flags governing input file handling"),
|
||
+ TWO_DASHES },
|
||
+ { {"print-memory-usage", no_argument, NULL, OPTION_PRINT_MEMORY_USAGE},
|
||
+ '\0', NULL, N_("Report target memory usage"), TWO_DASHES },
|
||
+ { {"orphan-handling", required_argument, NULL, OPTION_ORPHAN_HANDLING},
|
||
+ '\0', N_("=MODE"), N_("Control how orphan sections are handled."),
|
||
+ TWO_DASHES },
|
||
+ { {"print-map-discarded", no_argument, NULL, OPTION_PRINT_MAP_DISCARDED},
|
||
+ '\0', NULL, N_("Show discarded sections in map file output (default)"),
|
||
+ TWO_DASHES },
|
||
+ { {"no-print-map-discarded", no_argument, NULL, OPTION_NO_PRINT_MAP_DISCARDED},
|
||
+ '\0', NULL, N_("Do not show discarded sections in map file output"),
|
||
+ TWO_DASHES },
|
||
+ { {"print-map-locals", no_argument, NULL, OPTION_PRINT_MAP_LOCALS},
|
||
+ '\0', NULL, N_("Show local symbols in map file output"),
|
||
+ TWO_DASHES },
|
||
+ { {"no-print-map-locals", no_argument, NULL, OPTION_NO_PRINT_MAP_LOCALS},
|
||
+ '\0', NULL, N_("Do not show local symbols in map file output (default)"),
|
||
+ TWO_DASHES },
|
||
+ { {"ctf-variables", no_argument, NULL, OPTION_CTF_VARIABLES},
|
||
+ '\0', NULL, N_("Emit names and types of static variables in CTF"),
|
||
+ TWO_DASHES },
|
||
+ { {"no-ctf-variables", no_argument, NULL, OPTION_NO_CTF_VARIABLES},
|
||
+ '\0', NULL, N_("Do not emit names and types of static variables in CTF"),
|
||
+ TWO_DASHES },
|
||
+ { {"ctf-share-types=<method>", required_argument, NULL,
|
||
+ OPTION_CTF_SHARE_TYPES},
|
||
+ '\0', NULL, N_("How to share CTF types between translation units.\n"
|
||
+ " <method> is: share-unconflicted (default),\n"
|
||
+ " share-duplicated"),
|
||
+ TWO_DASHES },
|
||
+};
|
||
+
|
||
+#define OPTION_COUNT ARRAY_SIZE (ld_options)
|
||
+
|
||
+void
|
||
+parse_args (unsigned argc, char **argv)
|
||
+{
|
||
+ unsigned i;
|
||
+ int is, il, irl;
|
||
+ int ingroup = 0;
|
||
+ char *default_dirlist = NULL;
|
||
+ char *shortopts;
|
||
+ struct option *longopts;
|
||
+ struct option *really_longopts;
|
||
+ int last_optind;
|
||
+ enum symbolic_enum
|
||
+ {
|
||
+ symbolic_unset = 0,
|
||
+ symbolic,
|
||
+ symbolic_functions,
|
||
+ } opt_symbolic = symbolic_unset;
|
||
+ enum dynamic_list_enum
|
||
+ {
|
||
+ dynamic_list_unset = 0,
|
||
+ dynamic_list_data,
|
||
+ dynamic_list
|
||
+ } opt_dynamic_list = dynamic_list_unset;
|
||
+ struct bfd_elf_dynamic_list *export_list = NULL;
|
||
+
|
||
+ shortopts = (char *) xmalloc (OPTION_COUNT * 3 + 2);
|
||
+ longopts = (struct option *)
|
||
+ xmalloc (sizeof (*longopts) * (OPTION_COUNT + 1));
|
||
+ really_longopts = (struct option *)
|
||
+ xmalloc (sizeof (*really_longopts) * (OPTION_COUNT + 1));
|
||
+
|
||
+ /* Starting the short option string with '-' is for programs that
|
||
+ expect options and other ARGV-elements in any order and that care about
|
||
+ the ordering of the two. We describe each non-option ARGV-element
|
||
+ as if it were the argument of an option with character code 1. */
|
||
+ shortopts[0] = '-';
|
||
+ is = 1;
|
||
+ il = 0;
|
||
+ irl = 0;
|
||
+ for (i = 0; i < OPTION_COUNT; i++)
|
||
+ {
|
||
+ if (ld_options[i].shortopt != '\0')
|
||
+ {
|
||
+ shortopts[is] = ld_options[i].shortopt;
|
||
+ ++is;
|
||
+ if (ld_options[i].opt.has_arg == required_argument
|
||
+ || ld_options[i].opt.has_arg == optional_argument)
|
||
+ {
|
||
+ shortopts[is] = ':';
|
||
+ ++is;
|
||
+ if (ld_options[i].opt.has_arg == optional_argument)
|
||
+ {
|
||
+ shortopts[is] = ':';
|
||
+ ++is;
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+ if (ld_options[i].opt.name != NULL)
|
||
+ {
|
||
+ if (ld_options[i].control == EXACTLY_TWO_DASHES)
|
||
+ {
|
||
+ really_longopts[irl] = ld_options[i].opt;
|
||
+ ++irl;
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ longopts[il] = ld_options[i].opt;
|
||
+ ++il;
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+ shortopts[is] = '\0';
|
||
+ longopts[il].name = NULL;
|
||
+ really_longopts[irl].name = NULL;
|
||
+
|
||
+ ldemul_add_options (is, &shortopts, il, &longopts, irl, &really_longopts);
|
||
+
|
||
+ /* The -G option is ambiguous on different platforms. Sometimes it
|
||
+ specifies the largest data size to put into the small data
|
||
+ section. Sometimes it is equivalent to --shared. Unfortunately,
|
||
+ the first form takes an argument, while the second does not.
|
||
+
|
||
+ We need to permit the --shared form because on some platforms,
|
||
+ such as Solaris, gcc -shared will pass -G to the linker.
|
||
+
|
||
+ To permit either usage, we look through the argument list. If we
|
||
+ find -G not followed by a number, we change it into --shared.
|
||
+ This will work for most normal cases. */
|
||
+ for (i = 1; i < argc; i++)
|
||
+ if (strcmp (argv[i], "-G") == 0
|
||
+ && (i + 1 >= argc
|
||
+ || ! ISDIGIT (argv[i + 1][0])))
|
||
+ argv[i] = (char *) "--shared";
|
||
+
|
||
+ /* Because we permit long options to start with a single dash, and
|
||
+ we have a --library option, and the -l option is conventionally
|
||
+ used with an immediately following argument, we can have bad
|
||
+ results if somebody tries to use -l with a library whose name
|
||
+ happens to start with "ibrary", as in -li. We avoid problems by
|
||
+ simply turning -l into --library. This means that users will
|
||
+ have to use two dashes in order to use --library, which is OK
|
||
+ since that's how it is documented.
|
||
+
|
||
+ FIXME: It's possible that this problem can arise for other short
|
||
+ options as well, although the user does always have the recourse
|
||
+ of adding a space between the option and the argument. */
|
||
+ for (i = 1; i < argc; i++)
|
||
+ {
|
||
+ if (argv[i][0] == '-'
|
||
+ && argv[i][1] == 'l'
|
||
+ && argv[i][2] != '\0')
|
||
+ {
|
||
+ char *n;
|
||
+
|
||
+ n = (char *) xmalloc (strlen (argv[i]) + 20);
|
||
+ sprintf (n, "--library=%s", argv[i] + 2);
|
||
+ argv[i] = n;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ last_optind = -1;
|
||
+ while (1)
|
||
+ {
|
||
+ int longind = 0;
|
||
+ int optc;
|
||
+ static unsigned int defsym_count;
|
||
+
|
||
+ /* Using last_optind lets us avoid calling ldemul_parse_args
|
||
+ multiple times on a single option, which would lead to
|
||
+ confusion in the internal static variables maintained by
|
||
+ getopt. This could otherwise happen for an argument like
|
||
+ -nx, in which the -n is parsed as a single option, and we
|
||
+ loop around to pick up the -x. */
|
||
+ if (optind != last_optind)
|
||
+ if (ldemul_parse_args (argc, argv))
|
||
+ continue;
|
||
+
|
||
+ /* getopt_long_only is like getopt_long, but '-' as well as '--'
|
||
+ can indicate a long option. */
|
||
+ opterr = 0;
|
||
+ last_optind = optind;
|
||
+ optc = getopt_long_only (argc, argv, shortopts, longopts, &longind);
|
||
+ if (optc == '?')
|
||
+ {
|
||
+ optind = last_optind;
|
||
+ optc = getopt_long (argc, argv, "-", really_longopts, &longind);
|
||
+ }
|
||
+ /* Attempt to detect grouped short options, eg: "-non-start".
|
||
+ Accepting such options is error prone as it is not clear if the user
|
||
+ intended "-n -o n-start" or "--non-start". */
|
||
+ else if (longind == 0 /* This is a short option. */
|
||
+ && optc > 32 /* It is a valid option. */
|
||
+ /* The character is not the second character of argv[last_optind]. */
|
||
+ && optc != argv[last_optind][1])
|
||
+ {
|
||
+ if (optarg)
|
||
+ einfo (_("%F%P: Error: unable to disambiguate: %s (did you mean -%s ?)\n"),
|
||
+ argv[last_optind], argv[last_optind]);
|
||
+ else
|
||
+ einfo (_("%P: Warning: grouped short command line options are deprecated: %s\n"), argv[last_optind]);
|
||
+ }
|
||
+
|
||
+ if (ldemul_handle_option (optc))
|
||
+ continue;
|
||
+
|
||
+ if (optc == -1)
|
||
+ break;
|
||
+
|
||
+ switch (optc)
|
||
+ {
|
||
+ case '?':
|
||
+ {
|
||
+ /* If the last word on the command line is an option that
|
||
+ requires an argument, getopt will refuse to recognise it.
|
||
+ Try to catch such options here and issue a more helpful
|
||
+ error message than just "unrecognized option". */
|
||
+ int opt;
|
||
+
|
||
+ for (opt = ARRAY_SIZE (ld_options); opt--;)
|
||
+ if (ld_options[opt].opt.has_arg == required_argument
|
||
+ /* FIXME: There are a few short options that do not
|
||
+ have long equivalents, but which require arguments.
|
||
+ We should handle them too. */
|
||
+ && ld_options[opt].opt.name != NULL
|
||
+ && strcmp (argv[last_optind] + ld_options[opt].control, ld_options[opt].opt.name) == 0)
|
||
+ {
|
||
+ einfo (_("%P: %s: missing argument\n"), argv[last_optind]);
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ if (opt == -1)
|
||
+ einfo (_("%P: unrecognized option '%s'\n"), argv[last_optind]);
|
||
+ }
|
||
+ /* Fall through. */
|
||
+
|
||
+ default:
|
||
+ einfo (_("%F%P: use the --help option for usage information\n"));
|
||
+ break;
|
||
+
|
||
+ case 1: /* File name. */
|
||
+ lang_add_input_file (optarg, lang_input_file_is_file_enum, NULL);
|
||
+ break;
|
||
+
|
||
+ case OPTION_IGNORE:
|
||
+ break;
|
||
+ case 'a':
|
||
+ /* For HP/UX compatibility. Actually -a shared should mean
|
||
+ ``use only shared libraries'' but, then, we don't
|
||
+ currently support shared libraries on HP/UX anyhow. */
|
||
+ if (strcmp (optarg, "archive") == 0)
|
||
+ input_flags.dynamic = false;
|
||
+ else if (strcmp (optarg, "shared") == 0
|
||
+ || strcmp (optarg, "default") == 0)
|
||
+ input_flags.dynamic = true;
|
||
+ else
|
||
+ einfo (_("%F%P: unrecognized -a option `%s'\n"), optarg);
|
||
+ break;
|
||
+ case OPTION_ASSERT:
|
||
+ /* FIXME: We just ignore these, but we should handle them. */
|
||
+ if (strcmp (optarg, "definitions") == 0)
|
||
+ ;
|
||
+ else if (strcmp (optarg, "nodefinitions") == 0)
|
||
+ ;
|
||
+ else if (strcmp (optarg, "nosymbolic") == 0)
|
||
+ ;
|
||
+ else if (strcmp (optarg, "pure-text") == 0)
|
||
+ ;
|
||
+ else
|
||
+ einfo (_("%F%P: unrecognized -assert option `%s'\n"), optarg);
|
||
+ break;
|
||
+ case 'A':
|
||
+ ldfile_add_arch (optarg);
|
||
+ break;
|
||
+ case 'b':
|
||
+ lang_add_target (optarg);
|
||
+ break;
|
||
+ case 'c':
|
||
+ ldfile_open_command_file (optarg);
|
||
+ parser_input = input_mri_script;
|
||
+ yyparse ();
|
||
+ break;
|
||
+ case OPTION_CALL_SHARED:
|
||
+ input_flags.dynamic = true;
|
||
+ break;
|
||
+ case OPTION_NON_SHARED:
|
||
+ input_flags.dynamic = false;
|
||
+ break;
|
||
+ case OPTION_CREF:
|
||
+ command_line.cref = true;
|
||
+ link_info.notice_all = true;
|
||
+ break;
|
||
+ case 'd':
|
||
+ command_line.force_common_definition = true;
|
||
+ break;
|
||
+ case OPTION_FORCE_GROUP_ALLOCATION:
|
||
+ command_line.force_group_allocation = true;
|
||
+ break;
|
||
+ case OPTION_DEFSYM:
|
||
+ lex_string = optarg;
|
||
+ lex_redirect (optarg, "--defsym", ++defsym_count);
|
||
+ parser_input = input_defsym;
|
||
+ yyparse ();
|
||
+ lex_string = NULL;
|
||
+ break;
|
||
+ case OPTION_DEMANGLE:
|
||
+ demangling = true;
|
||
+ if (optarg != NULL)
|
||
+ {
|
||
+ enum demangling_styles style;
|
||
+
|
||
+ style = cplus_demangle_name_to_style (optarg);
|
||
+ if (style == unknown_demangling)
|
||
+ einfo (_("%F%P: unknown demangling style `%s'\n"),
|
||
+ optarg);
|
||
+
|
||
+ cplus_demangle_set_style (style);
|
||
+ }
|
||
+ break;
|
||
+ case 'I': /* Used on Solaris. */
|
||
+ case OPTION_DYNAMIC_LINKER:
|
||
+ command_line.interpreter = optarg;
|
||
+ link_info.nointerp = 0;
|
||
+ break;
|
||
+ case OPTION_NO_DYNAMIC_LINKER:
|
||
+ link_info.nointerp = 1;
|
||
+ break;
|
||
+ case OPTION_SYSROOT:
|
||
+ /* Already handled in ldmain.c. */
|
||
+ break;
|
||
+ case OPTION_EB:
|
||
+ command_line.endian = ENDIAN_BIG;
|
||
+ break;
|
||
+ case OPTION_EL:
|
||
+ command_line.endian = ENDIAN_LITTLE;
|
||
+ break;
|
||
+ case OPTION_EMBEDDED_RELOCS:
|
||
+ command_line.embedded_relocs = true;
|
||
+ break;
|
||
+ case OPTION_EXPORT_DYNAMIC:
|
||
+ case 'E': /* HP/UX compatibility. */
|
||
+ link_info.export_dynamic = true;
|
||
+ break;
|
||
+ case OPTION_NO_EXPORT_DYNAMIC:
|
||
+ link_info.export_dynamic = false;
|
||
+ break;
|
||
+ case OPTION_NON_CONTIGUOUS_REGIONS:
|
||
+ link_info.non_contiguous_regions = true;
|
||
+ break;
|
||
+ case OPTION_NON_CONTIGUOUS_REGIONS_WARNINGS:
|
||
+ link_info.non_contiguous_regions_warnings = true;
|
||
+ break;
|
||
+
|
||
+ case OPTION_ERROR_EXECSTACK:
|
||
+ link_info.error_execstack = 1;
|
||
+ break;
|
||
+ case OPTION_NO_ERROR_EXECSTACK:
|
||
+ link_info.error_execstack = 0;
|
||
+ break;
|
||
+ case OPTION_WARN_EXECSTACK_OBJECTS:
|
||
+ link_info.warn_execstack = 2;
|
||
+ break;
|
||
+ case OPTION_WARN_EXECSTACK:
|
||
+ link_info.warn_execstack = 1;
|
||
+ break;
|
||
+ case OPTION_NO_WARN_EXECSTACK:
|
||
+ link_info.warn_execstack = 0;
|
||
+ break;
|
||
+
|
||
+ case OPTION_ERROR_RWX_SEGMENTS:
|
||
+ link_info.warn_is_error_for_rwx_segments = 1;
|
||
+ break;
|
||
+ case OPTION_NO_ERROR_RWX_SEGMENTS:
|
||
+ link_info.warn_is_error_for_rwx_segments = 0;
|
||
+ break;
|
||
+ case OPTION_WARN_RWX_SEGMENTS:
|
||
+ link_info.no_warn_rwx_segments = 0;
|
||
+ link_info.user_warn_rwx_segments = 1;
|
||
+ break;
|
||
+ case OPTION_NO_WARN_RWX_SEGMENTS:
|
||
+ link_info.no_warn_rwx_segments = 1;
|
||
+ link_info.user_warn_rwx_segments = 1;
|
||
+ break;
|
||
+
|
||
+ case 'e':
|
||
+ lang_add_entry (optarg, true);
|
||
+ break;
|
||
+ case 'f':
|
||
+ if (command_line.auxiliary_filters == NULL)
|
||
+ {
|
||
+ command_line.auxiliary_filters = (char **)
|
||
+ xmalloc (2 * sizeof (char *));
|
||
+ command_line.auxiliary_filters[0] = optarg;
|
||
+ command_line.auxiliary_filters[1] = NULL;
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ int c;
|
||
+ char **p;
|
||
+
|
||
+ c = 0;
|
||
+ for (p = command_line.auxiliary_filters; *p != NULL; p++)
|
||
+ ++c;
|
||
+ command_line.auxiliary_filters = (char **)
|
||
+ xrealloc (command_line.auxiliary_filters,
|
||
+ (c + 2) * sizeof (char *));
|
||
+ command_line.auxiliary_filters[c] = optarg;
|
||
+ command_line.auxiliary_filters[c + 1] = NULL;
|
||
+ }
|
||
+ break;
|
||
+ case 'F':
|
||
+ command_line.filter_shlib = optarg;
|
||
+ break;
|
||
+ case OPTION_FORCE_EXE_SUFFIX:
|
||
+ command_line.force_exe_suffix = true;
|
||
+ break;
|
||
+ case 'G':
|
||
+ {
|
||
+ char *end;
|
||
+ g_switch_value = strtoul (optarg, &end, 0);
|
||
+ if (*end)
|
||
+ einfo (_("%F%P: invalid number `%s'\n"), optarg);
|
||
+ }
|
||
+ break;
|
||
+ case 'g':
|
||
+ /* Ignore. */
|
||
+ break;
|
||
+ case OPTION_GC_SECTIONS:
|
||
+ link_info.gc_sections = true;
|
||
+ break;
|
||
+ case OPTION_PRINT_GC_SECTIONS:
|
||
+ link_info.print_gc_sections = true;
|
||
+ break;
|
||
+ case OPTION_GC_KEEP_EXPORTED:
|
||
+ link_info.gc_keep_exported = true;
|
||
+ break;
|
||
+ case OPTION_HELP:
|
||
+ help ();
|
||
+ xexit (0);
|
||
+ break;
|
||
+ case 'L':
|
||
+ ldfile_add_library_path (optarg, true);
|
||
+ break;
|
||
+ case 'l':
|
||
+ lang_add_input_file (optarg, lang_input_file_is_l_enum, NULL);
|
||
+ break;
|
||
+ case 'M':
|
||
+ config.map_filename = "-";
|
||
+ break;
|
||
+ case 'm':
|
||
+ /* Ignore. Was handled in a pre-parse. */
|
||
+ break;
|
||
+ case OPTION_MAP:
|
||
+ config.map_filename = optarg;
|
||
+ break;
|
||
+ case 'N':
|
||
+ config.text_read_only = false;
|
||
+ config.magic_demand_paged = false;
|
||
+ input_flags.dynamic = false;
|
||
+ break;
|
||
+ case OPTION_NO_OMAGIC:
|
||
+ config.text_read_only = true;
|
||
+ config.magic_demand_paged = true;
|
||
+ /* NB/ Does not set input_flags.dynamic to TRUE.
|
||
+ Use --call-shared or -Bdynamic for this. */
|
||
+ break;
|
||
+ case 'n':
|
||
+ config.text_read_only = true;
|
||
+ config.magic_demand_paged = false;
|
||
+ input_flags.dynamic = false;
|
||
+ break;
|
||
+ case OPTION_NO_DEFINE_COMMON:
|
||
+ link_info.inhibit_common_definition = true;
|
||
+ break;
|
||
+ case OPTION_NO_DEMANGLE:
|
||
+ demangling = false;
|
||
+ break;
|
||
+ case OPTION_NO_GC_SECTIONS:
|
||
+ link_info.gc_sections = false;
|
||
+ break;
|
||
+ case OPTION_NO_PRINT_GC_SECTIONS:
|
||
+ link_info.print_gc_sections = false;
|
||
+ break;
|
||
+ case OPTION_NO_KEEP_MEMORY:
|
||
+ link_info.keep_memory = false;
|
||
+ break;
|
||
+ case OPTION_NO_UNDEFINED:
|
||
+ link_info.unresolved_syms_in_objects = RM_DIAGNOSE;
|
||
+ break;
|
||
+ case OPTION_ALLOW_SHLIB_UNDEFINED:
|
||
+ link_info.unresolved_syms_in_shared_libs = RM_IGNORE;
|
||
+ break;
|
||
+ case OPTION_NO_ALLOW_SHLIB_UNDEFINED:
|
||
+ link_info.unresolved_syms_in_shared_libs = RM_DIAGNOSE;
|
||
+ break;
|
||
+ case OPTION_UNRESOLVED_SYMBOLS:
|
||
+ if (strcmp (optarg, "ignore-all") == 0)
|
||
+ {
|
||
+ link_info.unresolved_syms_in_objects = RM_IGNORE;
|
||
+ link_info.unresolved_syms_in_shared_libs = RM_IGNORE;
|
||
+ }
|
||
+ else if (strcmp (optarg, "report-all") == 0)
|
||
+ {
|
||
+ link_info.unresolved_syms_in_objects = RM_DIAGNOSE;
|
||
+ link_info.unresolved_syms_in_shared_libs = RM_DIAGNOSE;
|
||
+ }
|
||
+ else if (strcmp (optarg, "ignore-in-object-files") == 0)
|
||
+ {
|
||
+ link_info.unresolved_syms_in_objects = RM_IGNORE;
|
||
+ link_info.unresolved_syms_in_shared_libs = RM_DIAGNOSE;
|
||
+ }
|
||
+ else if (strcmp (optarg, "ignore-in-shared-libs") == 0)
|
||
+ {
|
||
+ link_info.unresolved_syms_in_objects = RM_DIAGNOSE;
|
||
+ link_info.unresolved_syms_in_shared_libs = RM_IGNORE;
|
||
+ }
|
||
+ else
|
||
+ einfo (_("%F%P: bad --unresolved-symbols option: %s\n"), optarg);
|
||
+ break;
|
||
+ case OPTION_WARN_UNRESOLVED_SYMBOLS:
|
||
+ link_info.warn_unresolved_syms = true;
|
||
+ break;
|
||
+ case OPTION_ERROR_UNRESOLVED_SYMBOLS:
|
||
+ link_info.warn_unresolved_syms = false;
|
||
+ break;
|
||
+ case OPTION_ALLOW_MULTIPLE_DEFINITION:
|
||
+ link_info.allow_multiple_definition = true;
|
||
+ break;
|
||
+
|
||
+#if SUPPORT_ERROR_HANDLING_SCRIPT
|
||
+ case OPTION_ERROR_HANDLING_SCRIPT:
|
||
+ /* FIXME: Should we warn if the script is being overridden by another ?
|
||
+ Or maybe they should be chained together ? */
|
||
+ error_handling_script = optarg;
|
||
+ break;
|
||
+#endif
|
||
+
|
||
+ case OPTION_ENABLE_LINKER_VERSION:
|
||
+ enable_linker_version = true;
|
||
+ break;
|
||
+ case OPTION_DISABLE_LINKER_VERSION:
|
||
+ enable_linker_version = false;
|
||
+ break;
|
||
+
|
||
+ case OPTION_UNDEFINED_VERSION:
|
||
+ link_info.allow_undefined_version = true;
|
||
+ break;
|
||
+ case OPTION_NO_UNDEFINED_VERSION:
|
||
+ link_info.allow_undefined_version = false;
|
||
+ break;
|
||
+ case OPTION_DEFAULT_SYMVER:
|
||
+ link_info.create_default_symver = true;
|
||
+ break;
|
||
+ case OPTION_DEFAULT_IMPORTED_SYMVER:
|
||
+ link_info.default_imported_symver = true;
|
||
+ break;
|
||
+ case OPTION_NO_WARN_MISMATCH:
|
||
+ command_line.warn_mismatch = false;
|
||
+ break;
|
||
+ case OPTION_NO_WARN_SEARCH_MISMATCH:
|
||
+ command_line.warn_search_mismatch = false;
|
||
+ break;
|
||
+ case OPTION_NOINHIBIT_EXEC:
|
||
+ force_make_executable = true;
|
||
+ break;
|
||
+ case OPTION_NOSTDLIB:
|
||
+ config.only_cmd_line_lib_dirs = true;
|
||
+ break;
|
||
+ case OPTION_NO_WHOLE_ARCHIVE:
|
||
+ input_flags.whole_archive = false;
|
||
+ break;
|
||
+ case 'O':
|
||
+ /* FIXME "-O<non-digits> <value>" used to set the address of
|
||
+ section <non-digits>. Was this for compatibility with
|
||
+ something, or can we create a new option to do that
|
||
+ (with a syntax similar to -defsym)?
|
||
+ getopt can't handle two args to an option without kludges. */
|
||
+
|
||
+ /* Enable optimizations of output files. */
|
||
+ link_info.optimize = strtoul (optarg, NULL, 0) != 0;
|
||
+ break;
|
||
+ case 'o':
|
||
+ lang_add_output (optarg, 0);
|
||
+ break;
|
||
+ case OPTION_OFORMAT:
|
||
+ lang_add_output_format (optarg, NULL, NULL, 0);
|
||
+ break;
|
||
+ case OPTION_OUT_IMPLIB:
|
||
+ command_line.out_implib_filename = xstrdup (optarg);
|
||
+ break;
|
||
+ case OPTION_PRINT_SYSROOT:
|
||
+ if (*ld_sysroot)
|
||
+ puts (ld_sysroot);
|
||
+ xexit (0);
|
||
+ break;
|
||
+ case OPTION_PRINT_OUTPUT_FORMAT:
|
||
+ command_line.print_output_format = true;
|
||
+ break;
|
||
+#if BFD_SUPPORTS_PLUGINS
|
||
+ case OPTION_PLUGIN:
|
||
+ plugin_opt_plugin (optarg);
|
||
+ break;
|
||
+ case OPTION_PLUGIN_OPT:
|
||
+ if (plugin_opt_plugin_arg (optarg))
|
||
+ einfo (_("%F%P: bad -plugin-opt option\n"));
|
||
+ break;
|
||
+#endif /* BFD_SUPPORTS_PLUGINS */
|
||
+ case 'q':
|
||
+ link_info.emitrelocations = true;
|
||
+ break;
|
||
+ case 'i':
|
||
+ case 'r':
|
||
+ if (optind == last_optind)
|
||
+ /* This can happen if the user put "-rpath,a" on the command
|
||
+ line. (Or something similar. The comma is important).
|
||
+ Getopt becomes confused and thinks that this is a -r option
|
||
+ but it cannot parse the text after the -r so it refuses to
|
||
+ increment the optind counter. Detect this case and issue
|
||
+ an error message here. We cannot just make this a warning,
|
||
+ increment optind, and continue because getopt is too confused
|
||
+ and will seg-fault the next time around. */
|
||
+ einfo(_("%F%P: unrecognised option: %s\n"), argv[optind]);
|
||
+
|
||
+ if (bfd_link_pic (&link_info))
|
||
+ einfo (_("%F%P: -r and %s may not be used together\n"),
|
||
+ bfd_link_dll (&link_info) ? "-shared" : "-pie");
|
||
+
|
||
+ link_info.type = type_relocatable;
|
||
+ config.build_constructors = false;
|
||
+ config.magic_demand_paged = false;
|
||
+ config.text_read_only = false;
|
||
+ input_flags.dynamic = false;
|
||
+ break;
|
||
+ case 'R':
|
||
+ /* The GNU linker traditionally uses -R to mean to include
|
||
+ only the symbols from a file. The Solaris linker uses -R
|
||
+ to set the path used by the runtime linker to find
|
||
+ libraries. This is the GNU linker -rpath argument. We
|
||
+ try to support both simultaneously by checking the file
|
||
+ named. If it is a directory, rather than a regular file,
|
||
+ we assume -rpath was meant. */
|
||
+ {
|
||
+ struct stat s;
|
||
+
|
||
+ if (stat (optarg, &s) >= 0
|
||
+ && ! S_ISDIR (s.st_mode))
|
||
+ {
|
||
+ lang_add_input_file (optarg,
|
||
+ lang_input_file_is_symbols_only_enum,
|
||
+ NULL);
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+ /* Fall through. */
|
||
+ case OPTION_RPATH:
|
||
+ if (command_line.rpath == NULL)
|
||
+ command_line.rpath = xstrdup (optarg);
|
||
+ else
|
||
+ {
|
||
+ size_t rpath_len = strlen (command_line.rpath);
|
||
+ size_t optarg_len = strlen (optarg);
|
||
+ char *buf;
|
||
+ char *cp = command_line.rpath;
|
||
+
|
||
+ /* First see whether OPTARG is already in the path. */
|
||
+ do
|
||
+ {
|
||
+ if (strncmp (optarg, cp, optarg_len) == 0
|
||
+ && (cp[optarg_len] == 0
|
||
+ || cp[optarg_len] == config.rpath_separator))
|
||
+ /* We found it. */
|
||
+ break;
|
||
+
|
||
+ /* Not yet found. */
|
||
+ cp = strchr (cp, config.rpath_separator);
|
||
+ if (cp != NULL)
|
||
+ ++cp;
|
||
+ }
|
||
+ while (cp != NULL);
|
||
+
|
||
+ if (cp == NULL)
|
||
+ {
|
||
+ buf = (char *) xmalloc (rpath_len + optarg_len + 2);
|
||
+ sprintf (buf, "%s%c%s", command_line.rpath,
|
||
+ config.rpath_separator, optarg);
|
||
+ free (command_line.rpath);
|
||
+ command_line.rpath = buf;
|
||
+ }
|
||
+ }
|
||
+ break;
|
||
+ case OPTION_RPATH_LINK:
|
||
+ if (command_line.rpath_link == NULL)
|
||
+ command_line.rpath_link = xstrdup (optarg);
|
||
+ else
|
||
+ {
|
||
+ char *buf;
|
||
+
|
||
+ buf = (char *) xmalloc (strlen (command_line.rpath_link)
|
||
+ + strlen (optarg)
|
||
+ + 2);
|
||
+ sprintf (buf, "%s%c%s", command_line.rpath_link,
|
||
+ config.rpath_separator, optarg);
|
||
+ free (command_line.rpath_link);
|
||
+ command_line.rpath_link = buf;
|
||
+ }
|
||
+ break;
|
||
+ case OPTION_NO_RELAX:
|
||
+ DISABLE_RELAXATION;
|
||
+ break;
|
||
+ case OPTION_RELAX:
|
||
+ ENABLE_RELAXATION;
|
||
+ break;
|
||
+ case OPTION_RETAIN_SYMBOLS_FILE:
|
||
+ add_keepsyms_file (optarg);
|
||
+ break;
|
||
+ case 'S':
|
||
+ link_info.strip = strip_debugger;
|
||
+ break;
|
||
+ case 's':
|
||
+ link_info.strip = strip_all;
|
||
+ break;
|
||
+ case OPTION_STRIP_DISCARDED:
|
||
+ link_info.strip_discarded = true;
|
||
+ break;
|
||
+ case OPTION_NO_STRIP_DISCARDED:
|
||
+ link_info.strip_discarded = false;
|
||
+ break;
|
||
+ case OPTION_DISABLE_MULTIPLE_DEFS_ABS:
|
||
+ link_info.prohibit_multiple_definition_absolute = true;
|
||
+ break;
|
||
+ case OPTION_SHARED:
|
||
+ if (config.has_shared)
|
||
+ {
|
||
+ if (bfd_link_relocatable (&link_info))
|
||
+ einfo (_("%F%P: -r and %s may not be used together\n"),
|
||
+ "-shared");
|
||
+
|
||
+ link_info.type = type_dll;
|
||
+ /* When creating a shared library, the default
|
||
+ behaviour is to ignore any unresolved references. */
|
||
+ if (link_info.unresolved_syms_in_objects == RM_NOT_YET_SET)
|
||
+ link_info.unresolved_syms_in_objects = RM_IGNORE;
|
||
+ if (link_info.unresolved_syms_in_shared_libs == RM_NOT_YET_SET)
|
||
+ link_info.unresolved_syms_in_shared_libs = RM_IGNORE;
|
||
+ }
|
||
+ else
|
||
+ einfo (_("%F%P: -shared not supported\n"));
|
||
+ break;
|
||
+ case OPTION_NO_PIE:
|
||
+ link_info.type = type_pde;
|
||
+ break;
|
||
+ case OPTION_PIE:
|
||
+ if (config.has_shared)
|
||
+ {
|
||
+ if (bfd_link_relocatable (&link_info))
|
||
+ einfo (_("%F%P: -r and %s may not be used together\n"), "-pie");
|
||
+
|
||
+ link_info.type = type_pie;
|
||
+ }
|
||
+ else
|
||
+ einfo (_("%F%P: -pie not supported\n"));
|
||
+ break;
|
||
+ case 'h': /* Used on Solaris. */
|
||
+ case OPTION_SONAME:
|
||
+ if (optarg[0] == '\0' && command_line.soname
|
||
+ && command_line.soname[0])
|
||
+ einfo (_("%P: SONAME must not be empty string; keeping previous one\n"));
|
||
+ else
|
||
+ command_line.soname = optarg;
|
||
+ break;
|
||
+ case OPTION_SORT_COMMON:
|
||
+ if (optarg == NULL
|
||
+ || strcmp (optarg, N_("descending")) == 0)
|
||
+ config.sort_common = sort_descending;
|
||
+ else if (strcmp (optarg, N_("ascending")) == 0)
|
||
+ config.sort_common = sort_ascending;
|
||
+ else
|
||
+ einfo (_("%F%P: invalid common section sorting option: %s\n"),
|
||
+ optarg);
|
||
+ break;
|
||
+ case OPTION_SORT_SECTION:
|
||
+ if (strcmp (optarg, N_("name")) == 0)
|
||
+ sort_section = by_name;
|
||
+ else if (strcmp (optarg, N_("alignment")) == 0)
|
||
+ sort_section = by_alignment;
|
||
+ else
|
||
+ einfo (_("%F%P: invalid section sorting option: %s\n"),
|
||
+ optarg);
|
||
+ break;
|
||
+ case OPTION_STATS:
|
||
+ config.stats = true;
|
||
+ break;
|
||
+ case OPTION_NO_SYMBOLIC:
|
||
+ opt_symbolic = symbolic_unset;
|
||
+ break;
|
||
+ case OPTION_SYMBOLIC:
|
||
+ opt_symbolic = symbolic;
|
||
+ break;
|
||
+ case OPTION_SYMBOLIC_FUNCTIONS:
|
||
+ opt_symbolic = symbolic_functions;
|
||
+ break;
|
||
+ case 't':
|
||
+ ++trace_files;
|
||
+ break;
|
||
+ case 'T':
|
||
+ previous_script_handle = saved_script_handle;
|
||
+ ldfile_open_script_file (optarg);
|
||
+ parser_input = input_script;
|
||
+ yyparse ();
|
||
+ previous_script_handle = NULL;
|
||
+ break;
|
||
+ case OPTION_DEFAULT_SCRIPT:
|
||
+ command_line.default_script = optarg;
|
||
+ break;
|
||
+ case OPTION_SECTION_START:
|
||
+ {
|
||
+ char *optarg2;
|
||
+ char *sec_name;
|
||
+ int len;
|
||
+
|
||
+ /* Check for <something>=<somthing>... */
|
||
+ optarg2 = strchr (optarg, '=');
|
||
+ if (optarg2 == NULL)
|
||
+ einfo (_("%F%P: invalid argument to option"
|
||
+ " \"--section-start\"\n"));
|
||
+
|
||
+ optarg2++;
|
||
+
|
||
+ /* So far so good. Are all the args present? */
|
||
+ if ((*optarg == '\0') || (*optarg2 == '\0'))
|
||
+ einfo (_("%F%P: missing argument(s) to option"
|
||
+ " \"--section-start\"\n"));
|
||
+
|
||
+ /* We must copy the section name as set_section_start
|
||
+ doesn't do it for us. */
|
||
+ len = optarg2 - optarg;
|
||
+ sec_name = (char *) xmalloc (len);
|
||
+ memcpy (sec_name, optarg, len - 1);
|
||
+ sec_name[len - 1] = 0;
|
||
+
|
||
+ /* Then set it... */
|
||
+ set_section_start (sec_name, optarg2);
|
||
+ }
|
||
+ break;
|
||
+ case OPTION_TARGET_HELP:
|
||
+ /* Mention any target specific options. */
|
||
+ ldemul_list_emulation_options (stdout);
|
||
+ exit (0);
|
||
+ case OPTION_TBSS:
|
||
+ set_segment_start (".bss", optarg);
|
||
+ break;
|
||
+ case OPTION_TDATA:
|
||
+ set_segment_start (".data", optarg);
|
||
+ break;
|
||
+ case OPTION_TTEXT:
|
||
+ set_segment_start (".text", optarg);
|
||
+ break;
|
||
+ case OPTION_TTEXT_SEGMENT:
|
||
+ set_segment_start (".text-segment", optarg);
|
||
+ break;
|
||
+ case OPTION_TRODATA_SEGMENT:
|
||
+ set_segment_start (".rodata-segment", optarg);
|
||
+ break;
|
||
+ case OPTION_TLDATA_SEGMENT:
|
||
+ set_segment_start (".ldata-segment", optarg);
|
||
+ break;
|
||
+ case OPTION_TRADITIONAL_FORMAT:
|
||
+ link_info.traditional_format = true;
|
||
+ break;
|
||
+ case OPTION_TASK_LINK:
|
||
+ link_info.task_link = true;
|
||
+ /* Fall through. */
|
||
+ case OPTION_UR:
|
||
+ if (bfd_link_pic (&link_info))
|
||
+ einfo (_("%F%P: -r and %s may not be used together\n"),
|
||
+ bfd_link_dll (&link_info) ? "-shared" : "-pie");
|
||
+
|
||
+ link_info.type = type_relocatable;
|
||
+ config.build_constructors = true;
|
||
+ config.magic_demand_paged = false;
|
||
+ config.text_read_only = false;
|
||
+ input_flags.dynamic = false;
|
||
+ break;
|
||
+ case 'u':
|
||
+ ldlang_add_undef (optarg, true);
|
||
+ break;
|
||
+ case OPTION_REQUIRE_DEFINED_SYMBOL:
|
||
+ ldlang_add_require_defined (optarg);
|
||
+ break;
|
||
+ case OPTION_UNIQUE:
|
||
+ if (optarg != NULL)
|
||
+ lang_add_unique (optarg);
|
||
+ else
|
||
+ config.unique_orphan_sections = true;
|
||
+ break;
|
||
+ case OPTION_VERBOSE:
|
||
+ ldversion (1);
|
||
+ version_printed = true;
|
||
+ verbose = true;
|
||
+ overflow_cutoff_limit = -2;
|
||
+ if (optarg != NULL)
|
||
+ {
|
||
+ char *end;
|
||
+ int level ATTRIBUTE_UNUSED = strtoul (optarg, &end, 0);
|
||
+ if (*end)
|
||
+ einfo (_("%F%P: invalid number `%s'\n"), optarg);
|
||
+#if BFD_SUPPORTS_PLUGINS
|
||
+ report_plugin_symbols = level > 1;
|
||
+#endif /* BFD_SUPPORTS_PLUGINS */
|
||
+ }
|
||
+ break;
|
||
+ case 'v':
|
||
+ ldversion (0);
|
||
+ version_printed = true;
|
||
+ break;
|
||
+ case 'V':
|
||
+ ldversion (1);
|
||
+ version_printed = true;
|
||
+ break;
|
||
+ case OPTION_VERSION:
|
||
+ ldversion (2);
|
||
+ xexit (0);
|
||
+ break;
|
||
+ case OPTION_VERSION_SCRIPT:
|
||
+ /* This option indicates a small script that only specifies
|
||
+ version information. Read it, but don't assume that
|
||
+ we've seen a linker script. */
|
||
+ {
|
||
+ FILE *hold_script_handle;
|
||
+
|
||
+ hold_script_handle = saved_script_handle;
|
||
+ ldfile_open_command_file (optarg);
|
||
+ saved_script_handle = hold_script_handle;
|
||
+ parser_input = input_version_script;
|
||
+ yyparse ();
|
||
+ }
|
||
+ break;
|
||
+ case OPTION_VERSION_EXPORTS_SECTION:
|
||
+ /* This option records a version symbol to be applied to the
|
||
+ symbols listed for export to be found in the object files
|
||
+ .exports sections. */
|
||
+ command_line.version_exports_section = optarg;
|
||
+ break;
|
||
+ case OPTION_DYNAMIC_LIST_DATA:
|
||
+ opt_dynamic_list = dynamic_list_data;
|
||
+ break;
|
||
+ case OPTION_DYNAMIC_LIST_CPP_TYPEINFO:
|
||
+ lang_append_dynamic_list_cpp_typeinfo ();
|
||
+ if (opt_dynamic_list != dynamic_list_data)
|
||
+ opt_dynamic_list = dynamic_list;
|
||
+ break;
|
||
+ case OPTION_DYNAMIC_LIST_CPP_NEW:
|
||
+ lang_append_dynamic_list_cpp_new ();
|
||
+ if (opt_dynamic_list != dynamic_list_data)
|
||
+ opt_dynamic_list = dynamic_list;
|
||
+ break;
|
||
+ case OPTION_DYNAMIC_LIST:
|
||
+ /* This option indicates a small script that only specifies
|
||
+ a dynamic list. Read it, but don't assume that we've
|
||
+ seen a linker script. */
|
||
+ {
|
||
+ FILE *hold_script_handle;
|
||
+
|
||
+ hold_script_handle = saved_script_handle;
|
||
+ ldfile_open_command_file (optarg);
|
||
+ saved_script_handle = hold_script_handle;
|
||
+ parser_input = input_dynamic_list;
|
||
+ current_dynamic_list_p = &link_info.dynamic_list;
|
||
+ yyparse ();
|
||
+ }
|
||
+ if (opt_dynamic_list != dynamic_list_data)
|
||
+ opt_dynamic_list = dynamic_list;
|
||
+ break;
|
||
+ case OPTION_EXPORT_DYNAMIC_SYMBOL:
|
||
+ {
|
||
+ struct bfd_elf_version_expr *expr
|
||
+ = lang_new_vers_pattern (NULL, xstrdup (optarg), NULL,
|
||
+ false);
|
||
+ lang_append_dynamic_list (&export_list, expr);
|
||
+ }
|
||
+ break;
|
||
+ case OPTION_EXPORT_DYNAMIC_SYMBOL_LIST:
|
||
+ /* This option indicates a small script that only specifies
|
||
+ an export list. Read it, but don't assume that we've
|
||
+ seen a linker script. */
|
||
+ {
|
||
+ FILE *hold_script_handle;
|
||
+
|
||
+ hold_script_handle = saved_script_handle;
|
||
+ ldfile_open_command_file (optarg);
|
||
+ saved_script_handle = hold_script_handle;
|
||
+ parser_input = input_dynamic_list;
|
||
+ current_dynamic_list_p = &export_list;
|
||
+ yyparse ();
|
||
+ }
|
||
+ break;
|
||
+ case OPTION_WARN_COMMON:
|
||
+ config.warn_common = true;
|
||
+ break;
|
||
+ case OPTION_WARN_CONSTRUCTORS:
|
||
+ config.warn_constructors = true;
|
||
+ break;
|
||
+ case OPTION_WARN_FATAL:
|
||
+ config.fatal_warnings = true;
|
||
+ break;
|
||
+ case OPTION_NO_WARN_FATAL:
|
||
+ config.fatal_warnings = false;
|
||
+ break;
|
||
+ case OPTION_NO_WARNINGS:
|
||
+ case 'w':
|
||
+ config.no_warnings = true;
|
||
+ config.fatal_warnings = false;
|
||
+ break;
|
||
+ case OPTION_WARN_MULTIPLE_GP:
|
||
+ config.warn_multiple_gp = true;
|
||
+ break;
|
||
+ case OPTION_WARN_ONCE:
|
||
+ config.warn_once = true;
|
||
+ break;
|
||
+ case OPTION_WARN_SECTION_ALIGN:
|
||
+ config.warn_section_align = true;
|
||
+ break;
|
||
+ case OPTION_WARN_TEXTREL:
|
||
+ link_info.textrel_check = textrel_check_warning;
|
||
+ break;
|
||
+ case OPTION_WARN_ALTERNATE_EM:
|
||
+ link_info.warn_alternate_em = true;
|
||
+ break;
|
||
+ case OPTION_WHOLE_ARCHIVE:
|
||
+ input_flags.whole_archive = true;
|
||
+ break;
|
||
+ case OPTION_ADD_DT_NEEDED_FOR_DYNAMIC:
|
||
+ input_flags.add_DT_NEEDED_for_dynamic = true;
|
||
+ break;
|
||
+ case OPTION_NO_ADD_DT_NEEDED_FOR_DYNAMIC:
|
||
+ input_flags.add_DT_NEEDED_for_dynamic = false;
|
||
+ break;
|
||
+ case OPTION_ADD_DT_NEEDED_FOR_REGULAR:
|
||
+ input_flags.add_DT_NEEDED_for_regular = true;
|
||
+ break;
|
||
+ case OPTION_NO_ADD_DT_NEEDED_FOR_REGULAR:
|
||
+ input_flags.add_DT_NEEDED_for_regular = false;
|
||
+ break;
|
||
+ case OPTION_WRAP:
|
||
+ add_wrap (optarg);
|
||
+ break;
|
||
+ case OPTION_IGNORE_UNRESOLVED_SYMBOL:
|
||
+ add_ignoresym (&link_info, optarg);
|
||
+ break;
|
||
+ case OPTION_DISCARD_NONE:
|
||
+ link_info.discard = discard_none;
|
||
+ break;
|
||
+ case 'X':
|
||
+ link_info.discard = discard_l;
|
||
+ break;
|
||
+ case 'x':
|
||
+ link_info.discard = discard_all;
|
||
+ break;
|
||
+ case 'Y':
|
||
+ if (startswith (optarg, "P,"))
|
||
+ optarg += 2;
|
||
+ free (default_dirlist);
|
||
+ default_dirlist = xstrdup (optarg);
|
||
+ break;
|
||
+ case 'y':
|
||
+ add_ysym (optarg);
|
||
+ break;
|
||
+ case OPTION_SPARE_DYNAMIC_TAGS:
|
||
+ link_info.spare_dynamic_tags = strtoul (optarg, NULL, 0);
|
||
+ break;
|
||
+ case OPTION_SPLIT_BY_RELOC:
|
||
+ if (optarg != NULL)
|
||
+ config.split_by_reloc = strtoul (optarg, NULL, 0);
|
||
+ else
|
||
+ config.split_by_reloc = 32768;
|
||
+ break;
|
||
+ case OPTION_SPLIT_BY_FILE:
|
||
+ if (optarg != NULL)
|
||
+ config.split_by_file = bfd_scan_vma (optarg, NULL, 0);
|
||
+ else
|
||
+ config.split_by_file = 1;
|
||
+ break;
|
||
+ case OPTION_CHECK_SECTIONS:
|
||
+ command_line.check_section_addresses = 1;
|
||
+ break;
|
||
+ case OPTION_NO_CHECK_SECTIONS:
|
||
+ command_line.check_section_addresses = 0;
|
||
+ break;
|
||
+ case OPTION_ACCEPT_UNKNOWN_INPUT_ARCH:
|
||
+ command_line.accept_unknown_input_arch = true;
|
||
+ break;
|
||
+ case OPTION_NO_ACCEPT_UNKNOWN_INPUT_ARCH:
|
||
+ command_line.accept_unknown_input_arch = false;
|
||
+ break;
|
||
+ case '(':
|
||
+ lang_enter_group ();
|
||
+ ingroup++;
|
||
+ break;
|
||
+ case ')':
|
||
+ if (! ingroup)
|
||
+ einfo (_("%F%P: group ended before it began (--help for usage)\n"));
|
||
+
|
||
+ lang_leave_group ();
|
||
+ ingroup--;
|
||
+ break;
|
||
+
|
||
+ case OPTION_INIT:
|
||
+ link_info.init_function = optarg;
|
||
+ break;
|
||
+
|
||
+ case OPTION_FINI:
|
||
+ link_info.fini_function = optarg;
|
||
+ break;
|
||
+
|
||
+ case OPTION_REMAP_INPUTS_FILE:
|
||
+ if (! ldfile_add_remap_file (optarg))
|
||
+ einfo (_("%F%P: failed to add remap file %s\n"), optarg);
|
||
+ break;
|
||
+
|
||
+ case OPTION_REMAP_INPUTS:
|
||
+ {
|
||
+ char *optarg2 = strchr (optarg, '=');
|
||
+ if (optarg2 == NULL)
|
||
+ /* FIXME: Should we allow --remap-inputs=@myfile as a synonym
|
||
+ for --remap-inputs-file=myfile ? */
|
||
+ einfo (_("%F%P: invalid argument to option --remap-inputs\n"));
|
||
+ size_t len = optarg2 - optarg;
|
||
+ char * pattern = xmalloc (len + 1);
|
||
+ memcpy (pattern, optarg, len);
|
||
+ pattern[len] = 0;
|
||
+ ldfile_add_remap (pattern, optarg2 + 1);
|
||
+ free (pattern);
|
||
+ }
|
||
+ break;
|
||
+
|
||
+ case OPTION_REDUCE_MEMORY_OVERHEADS:
|
||
+ link_info.reduce_memory_overheads = true;
|
||
+ if (config.hash_table_size == 0)
|
||
+ config.hash_table_size = 1021;
|
||
+ break;
|
||
+
|
||
+ case OPTION_MAX_CACHE_SIZE:
|
||
+ {
|
||
+ char *end;
|
||
+ bfd_size_type cache_size = strtoul (optarg, &end, 0);
|
||
+ if (*end != '\0')
|
||
+ einfo (_("%F%P: invalid cache memory size: %s\n"),
|
||
+ optarg);
|
||
+ link_info.max_cache_size = cache_size;
|
||
+ }
|
||
+ break;
|
||
+
|
||
+ case OPTION_HASH_SIZE:
|
||
+ {
|
||
+ bfd_size_type new_size;
|
||
+
|
||
+ new_size = strtoul (optarg, NULL, 0);
|
||
+ if (new_size)
|
||
+ config.hash_table_size = new_size;
|
||
+ else
|
||
+ einfo (_("%X%P: --hash-size needs a numeric argument\n"));
|
||
+ }
|
||
+ break;
|
||
+
|
||
+ case OPTION_PUSH_STATE:
|
||
+ input_flags.pushed = xmemdup (&input_flags,
|
||
+ sizeof (input_flags),
|
||
+ sizeof (input_flags));
|
||
+ break;
|
||
+
|
||
+ case OPTION_POP_STATE:
|
||
+ if (input_flags.pushed == NULL)
|
||
+ einfo (_("%F%P: no state pushed before popping\n"));
|
||
+ else
|
||
+ {
|
||
+ struct lang_input_statement_flags *oldp = input_flags.pushed;
|
||
+ memcpy (&input_flags, oldp, sizeof (input_flags));
|
||
+ free (oldp);
|
||
+ }
|
||
+ break;
|
||
+
|
||
+ case OPTION_PRINT_MEMORY_USAGE:
|
||
+ command_line.print_memory_usage = true;
|
||
+ break;
|
||
+
|
||
+ case OPTION_ORPHAN_HANDLING:
|
||
+ if (strcasecmp (optarg, "place") == 0)
|
||
+ config.orphan_handling = orphan_handling_place;
|
||
+ else if (strcasecmp (optarg, "warn") == 0)
|
||
+ config.orphan_handling = orphan_handling_warn;
|
||
+ else if (strcasecmp (optarg, "error") == 0)
|
||
+ config.orphan_handling = orphan_handling_error;
|
||
+ else if (strcasecmp (optarg, "discard") == 0)
|
||
+ config.orphan_handling = orphan_handling_discard;
|
||
+ else
|
||
+ einfo (_("%F%P: invalid argument to option"
|
||
+ " \"--orphan-handling\"\n"));
|
||
+ break;
|
||
+
|
||
+ case OPTION_NO_PRINT_MAP_DISCARDED:
|
||
+ config.print_map_discarded = false;
|
||
+ break;
|
||
+
|
||
+ case OPTION_PRINT_MAP_DISCARDED:
|
||
+ config.print_map_discarded = true;
|
||
+ break;
|
||
+
|
||
+ case OPTION_NO_PRINT_MAP_LOCALS:
|
||
+ config.print_map_locals = false;
|
||
+ break;
|
||
+
|
||
+ case OPTION_PRINT_MAP_LOCALS:
|
||
+ config.print_map_locals = true;
|
||
+ break;
|
||
+
|
||
+ case OPTION_DEPENDENCY_FILE:
|
||
+ config.dependency_file = optarg;
|
||
+ break;
|
||
+
|
||
+ case OPTION_CTF_VARIABLES:
|
||
+ config.ctf_variables = true;
|
||
+ break;
|
||
+
|
||
+ case OPTION_NO_CTF_VARIABLES:
|
||
+ config.ctf_variables = false;
|
||
+ break;
|
||
+
|
||
+ case OPTION_CTF_SHARE_TYPES:
|
||
+ if (strcmp (optarg, "share-unconflicted") == 0)
|
||
+ config.ctf_share_duplicated = false;
|
||
+ else if (strcmp (optarg, "share-duplicated") == 0)
|
||
+ config.ctf_share_duplicated = true;
|
||
+ else
|
||
+ einfo (_("%F%P: bad --ctf-share-types option: %s\n"), optarg);
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ free (really_longopts);
|
||
+ free (longopts);
|
||
+ free (shortopts);
|
||
+
|
||
+ /* Run a couple of checks on the map filename. */
|
||
+ if (config.map_filename)
|
||
+ {
|
||
+ char * new_name = NULL;
|
||
+ char * percent;
|
||
+ int res = 0;
|
||
+
|
||
+ if (config.map_filename[0] == 0)
|
||
+ {
|
||
+ einfo (_("%P: no file/directory name provided for map output; ignored\n"));
|
||
+ config.map_filename = NULL;
|
||
+ }
|
||
+ else if (strcmp (config.map_filename, "-") == 0)
|
||
+ ; /* Write to stdout. Handled in main(). */
|
||
+ else if ((percent = strchr (config.map_filename, '%')) != NULL)
|
||
+ {
|
||
+ /* FIXME: Check for a second % character and issue an error ? */
|
||
+
|
||
+ /* Construct a map file by replacing the % character with the (full)
|
||
+ output filename. If the % character was the last character in
|
||
+ the original map filename then add a .map extension. */
|
||
+ percent[0] = 0;
|
||
+ res = asprintf (&new_name, "%s%s%s", config.map_filename,
|
||
+ output_filename,
|
||
+ percent[1] ? percent + 1 : ".map");
|
||
+
|
||
+ /* FIXME: Should we ensure that any directory components in new_name exist ? */
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ struct stat s;
|
||
+
|
||
+ /* If the map filename is actually a directory then create
|
||
+ a file inside it, based upon the output filename. */
|
||
+ if (stat (config.map_filename, &s) < 0)
|
||
+ {
|
||
+ if (errno != ENOENT)
|
||
+ einfo (_("%P: cannot stat linker map file: %E\n"));
|
||
+ }
|
||
+ else if (S_ISDIR (s.st_mode))
|
||
+ {
|
||
+ char lastc = config.map_filename[strlen (config.map_filename) - 1];
|
||
+ res = asprintf (&new_name, "%s%s%s.map",
|
||
+ config.map_filename,
|
||
+ IS_DIR_SEPARATOR (lastc) ? "" : "/",
|
||
+ lbasename (output_filename));
|
||
+ }
|
||
+ else if (! S_ISREG (s.st_mode))
|
||
+ {
|
||
+ einfo (_("%P: linker map file is not a regular file\n"));
|
||
+ config.map_filename = NULL;
|
||
+ }
|
||
+ /* else FIXME: Check write permission ? */
|
||
+ }
|
||
+
|
||
+ if (res < 0)
|
||
+ {
|
||
+ /* If the asprintf failed then something is probably very
|
||
+ wrong. Better to halt now rather than continue on
|
||
+ into more problems. */
|
||
+ einfo (_("%P%F: cannot create name for linker map file: %E\n"));
|
||
+ }
|
||
+ else if (new_name != NULL)
|
||
+ {
|
||
+ /* This is a trivial memory leak. */
|
||
+ config.map_filename = new_name;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (command_line.soname && command_line.soname[0] == '\0')
|
||
+ {
|
||
+ einfo (_("%P: SONAME must not be empty string; ignored\n"));
|
||
+ command_line.soname = NULL;
|
||
+ }
|
||
+
|
||
+ while (ingroup)
|
||
+ {
|
||
+ einfo (_("%P: missing --end-group; added as last command line option\n"));
|
||
+ lang_leave_group ();
|
||
+ ingroup--;
|
||
+ }
|
||
+
|
||
+ if (default_dirlist != NULL)
|
||
+ {
|
||
+ set_default_dirlist (default_dirlist);
|
||
+ free (default_dirlist);
|
||
+ }
|
||
+
|
||
+ if (link_info.unresolved_syms_in_objects == RM_NOT_YET_SET)
|
||
+ /* FIXME: Should we allow emulations a chance to set this ? */
|
||
+ link_info.unresolved_syms_in_objects = RM_DIAGNOSE;
|
||
+
|
||
+ if (link_info.unresolved_syms_in_shared_libs == RM_NOT_YET_SET)
|
||
+ /* FIXME: Should we allow emulations a chance to set this ? */
|
||
+ link_info.unresolved_syms_in_shared_libs = RM_DIAGNOSE;
|
||
+
|
||
+ if (bfd_link_relocatable (&link_info)
|
||
+ && command_line.check_section_addresses < 0)
|
||
+ command_line.check_section_addresses = 0;
|
||
+
|
||
+ if (export_list)
|
||
+ {
|
||
+ struct bfd_elf_version_expr *head = export_list->head.list;
|
||
+ struct bfd_elf_version_expr *next;
|
||
+
|
||
+ /* For --export-dynamic-symbol[-list]:
|
||
+ 1. When building executable, treat like --dynamic-list.
|
||
+ 2. When building shared object:
|
||
+ a. If -Bsymbolic or --dynamic-list are used, treat like
|
||
+ --dynamic-list.
|
||
+ b. Otherwise, ignored.
|
||
+ */
|
||
+ if (!bfd_link_relocatable (&link_info)
|
||
+ && (bfd_link_executable (&link_info)
|
||
+ || opt_symbolic != symbolic_unset
|
||
+ || opt_dynamic_list != dynamic_list_unset))
|
||
+ {
|
||
+ /* Append the export list to link_info.dynamic_list. */
|
||
+ if (link_info.dynamic_list)
|
||
+ {
|
||
+ for (next = head; next->next != NULL; next = next->next)
|
||
+ ;
|
||
+ next->next = link_info.dynamic_list->head.list;
|
||
+ link_info.dynamic_list->head.list = head;
|
||
+ }
|
||
+ else
|
||
+ link_info.dynamic_list = export_list;
|
||
+
|
||
+ if (opt_dynamic_list != dynamic_list_data)
|
||
+ opt_dynamic_list = dynamic_list;
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ /* Free the export list. */
|
||
+ for (; head->next != NULL; head = next)
|
||
+ {
|
||
+ next = head->next;
|
||
+ free (head);
|
||
+ }
|
||
+ free (export_list);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ switch (opt_dynamic_list)
|
||
+ {
|
||
+ case dynamic_list_unset:
|
||
+ break;
|
||
+ case dynamic_list_data:
|
||
+ link_info.dynamic_data = true;
|
||
+ /* Fall through. */
|
||
+ case dynamic_list:
|
||
+ link_info.dynamic = true;
|
||
+ opt_symbolic = symbolic_unset;
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ /* -Bsymbolic and -Bsymbols-functions are for shared library output. */
|
||
+ if (bfd_link_dll (&link_info))
|
||
+ switch (opt_symbolic)
|
||
+ {
|
||
+ case symbolic_unset:
|
||
+ break;
|
||
+ case symbolic:
|
||
+ link_info.symbolic = true;
|
||
+ if (link_info.dynamic_list)
|
||
+ {
|
||
+ struct bfd_elf_version_expr *ent, *next;
|
||
+ for (ent = link_info.dynamic_list->head.list; ent; ent = next)
|
||
+ {
|
||
+ next = ent->next;
|
||
+ free (ent);
|
||
+ }
|
||
+ free (link_info.dynamic_list);
|
||
+ link_info.dynamic_list = NULL;
|
||
+ }
|
||
+ break;
|
||
+ case symbolic_functions:
|
||
+ link_info.dynamic = true;
|
||
+ link_info.dynamic_data = true;
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ /* -z nosectionheader implies --strip-all. */
|
||
+ if (config.no_section_header)
|
||
+ {
|
||
+ if (bfd_link_relocatable (&link_info))
|
||
+ einfo (_("%F%P: -r and -z nosectionheader may not be used together\n"));
|
||
+
|
||
+ link_info.strip = strip_all;
|
||
+ }
|
||
+
|
||
+ if (!bfd_link_dll (&link_info))
|
||
+ {
|
||
+ if (command_line.filter_shlib)
|
||
+ einfo (_("%F%P: -F may not be used without -shared\n"));
|
||
+ if (command_line.auxiliary_filters)
|
||
+ einfo (_("%F%P: -f may not be used without -shared\n"));
|
||
+ }
|
||
+
|
||
+ /* Treat ld -r -s as ld -r -S -x (i.e., strip all local symbols). I
|
||
+ don't see how else this can be handled, since in this case we
|
||
+ must preserve all externally visible symbols. */
|
||
+ if (bfd_link_relocatable (&link_info) && link_info.strip == strip_all)
|
||
+ {
|
||
+ link_info.strip = strip_debugger;
|
||
+ if (link_info.discard == discard_sec_merge)
|
||
+ link_info.discard = discard_all;
|
||
+ }
|
||
+}
|
||
+
|
||
+/* Add the (colon-separated) elements of DIRLIST_PTR to the
|
||
+ library search path. */
|
||
+
|
||
+static void
|
||
+set_default_dirlist (char *dirlist_ptr)
|
||
+{
|
||
+ char *p;
|
||
+
|
||
+ while (1)
|
||
+ {
|
||
+ p = strchr (dirlist_ptr, PATH_SEPARATOR);
|
||
+ if (p != NULL)
|
||
+ *p = '\0';
|
||
+ if (*dirlist_ptr != '\0')
|
||
+ ldfile_add_library_path (dirlist_ptr, true);
|
||
+ if (p == NULL)
|
||
+ break;
|
||
+ dirlist_ptr = p + 1;
|
||
+ }
|
||
+}
|
||
+
|
||
+static void
|
||
+set_section_start (char *sect, char *valstr)
|
||
+{
|
||
+ const char *end;
|
||
+ bfd_vma val = bfd_scan_vma (valstr, &end, 16);
|
||
+ if (*end)
|
||
+ einfo (_("%F%P: invalid hex number `%s'\n"), valstr);
|
||
+ lang_section_start (sect, exp_intop (val), NULL);
|
||
+}
|
||
+
|
||
+static void
|
||
+set_segment_start (const char *section, char *valstr)
|
||
+{
|
||
+ const char *name;
|
||
+ const char *end;
|
||
+ segment_type *seg;
|
||
+
|
||
+ bfd_vma val = bfd_scan_vma (valstr, &end, 16);
|
||
+ if (*end)
|
||
+ einfo (_("%F%P: invalid hex number `%s'\n"), valstr);
|
||
+ /* If we already have an entry for this segment, update the existing
|
||
+ value. */
|
||
+ name = section + 1;
|
||
+ for (seg = segments; seg; seg = seg->next)
|
||
+ if (strcmp (seg->name, name) == 0)
|
||
+ {
|
||
+ seg->value = val;
|
||
+ lang_section_start (section, exp_intop (val), seg);
|
||
+ return;
|
||
+ }
|
||
+ /* There was no existing value so we must create a new segment
|
||
+ entry. */
|
||
+ seg = stat_alloc (sizeof (*seg));
|
||
+ seg->name = name;
|
||
+ seg->value = val;
|
||
+ seg->used = false;
|
||
+ /* Add it to the linked list of segments. */
|
||
+ seg->next = segments;
|
||
+ segments = seg;
|
||
+ /* Historically, -Ttext and friends set the base address of a
|
||
+ particular section. For backwards compatibility, we still do
|
||
+ that. If a SEGMENT_START directive is seen, the section address
|
||
+ assignment will be disabled. */
|
||
+ lang_section_start (section, exp_intop (val), seg);
|
||
+}
|
||
+
|
||
+static void
|
||
+elf_shlib_list_options (FILE *file)
|
||
+{
|
||
+ fprintf (file, _("\
|
||
+ --audit=AUDITLIB Specify a library to use for auditing\n"));
|
||
+ fprintf (file, _("\
|
||
+ -Bgroup Selects group name lookup rules for DSO\n"));
|
||
+ fprintf (file, _("\
|
||
+ --disable-new-dtags Disable new dynamic tags\n"));
|
||
+ fprintf (file, _("\
|
||
+ --enable-new-dtags Enable new dynamic tags\n"));
|
||
+ fprintf (file, _("\
|
||
+ --eh-frame-hdr Create .eh_frame_hdr section\n"));
|
||
+ fprintf (file, _("\
|
||
+ --no-eh-frame-hdr Do not create .eh_frame_hdr section\n"));
|
||
+ fprintf (file, _("\
|
||
+ --exclude-libs=LIBS Make all symbols in LIBS hidden\n"));
|
||
+ fprintf (file, _("\
|
||
+ --hash-style=STYLE Set hash style to sysv/gnu/both. Default: "));
|
||
+ if (DEFAULT_EMIT_SYSV_HASH)
|
||
+ {
|
||
+ /* Note - these strings are not translated as
|
||
+ they are keywords not descriptive text. */
|
||
+ if (DEFAULT_EMIT_GNU_HASH)
|
||
+ fprintf (file, "both\n");
|
||
+ else
|
||
+ fprintf (file, "sysv\n");
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ if (DEFAULT_EMIT_GNU_HASH)
|
||
+ fprintf (file, "gnu\n");
|
||
+ else
|
||
+ /* FIXME: Can this happen ? */
|
||
+ fprintf (file, "none\n");
|
||
+ }
|
||
+ fprintf (file, _("\
|
||
+ -P AUDITLIB, --depaudit=AUDITLIB\n" "\
|
||
+ Specify a library to use for auditing dependencies\n"));
|
||
+ fprintf (file, _("\
|
||
+ -z combreloc Merge dynamic relocs into one section and sort\n"));
|
||
+ fprintf (file, _("\
|
||
+ -z nocombreloc Don't merge dynamic relocs into one section\n"));
|
||
+ fprintf (file, _("\
|
||
+ -z global Make symbols in DSO available for subsequently\n\
|
||
+ loaded objects\n"));
|
||
+ fprintf (file, _("\
|
||
+ -z initfirst Mark DSO to be initialized first at runtime\n"));
|
||
+ fprintf (file, _("\
|
||
+ -z interpose Mark object to interpose all DSOs but executable\n"));
|
||
+ fprintf (file, _("\
|
||
+ -z unique Mark DSO to be loaded at most once by default, and only in the main namespace\n"));
|
||
+ fprintf (file, _("\
|
||
+ -z nounique Don't mark DSO as a loadable at most once\n"));
|
||
+ fprintf (file, _("\
|
||
+ -z lazy Mark object lazy runtime binding (default)\n"));
|
||
+ fprintf (file, _("\
|
||
+ -z loadfltr Mark object requiring immediate process\n"));
|
||
+ fprintf (file, _("\
|
||
+ -z nocopyreloc Don't create copy relocs\n"));
|
||
+ fprintf (file, _("\
|
||
+ -z nodefaultlib Mark object not to use default search paths\n"));
|
||
+ fprintf (file, _("\
|
||
+ -z nodelete Mark DSO non-deletable at runtime\n"));
|
||
+ fprintf (file, _("\
|
||
+ -z nodlopen Mark DSO not available to dlopen\n"));
|
||
+ fprintf (file, _("\
|
||
+ -z nodump Mark DSO not available to dldump\n"));
|
||
+ fprintf (file, _("\
|
||
+ -z now Mark object non-lazy runtime binding\n"));
|
||
+ fprintf (file, _("\
|
||
+ -z origin Mark object requiring immediate $ORIGIN\n\
|
||
+ processing at runtime\n"));
|
||
+#if DEFAULT_LD_Z_RELRO
|
||
+ fprintf (file, _("\
|
||
+ -z relro Create RELRO program header (default)\n"));
|
||
+ fprintf (file, _("\
|
||
+ -z norelro Don't create RELRO program header\n"));
|
||
+#else
|
||
+ fprintf (file, _("\
|
||
+ -z relro Create RELRO program header\n"));
|
||
+ fprintf (file, _("\
|
||
+ -z norelro Don't create RELRO program header (default)\n"));
|
||
+#endif
|
||
+#if DEFAULT_LD_Z_SEPARATE_CODE
|
||
+ fprintf (file, _("\
|
||
+ -z separate-code Create separate code program header (default)\n"));
|
||
+ fprintf (file, _("\
|
||
+ -z noseparate-code Don't create separate code program header\n"));
|
||
+#else
|
||
+ fprintf (file, _("\
|
||
+ -z separate-code Create separate code program header\n"));
|
||
+ fprintf (file, _("\
|
||
+ -z noseparate-code Don't create separate code program header (default)\n"));
|
||
+#endif
|
||
+ fprintf (file, _("\
|
||
+ -z common Generate common symbols with STT_COMMON type\n"));
|
||
+ fprintf (file, _("\
|
||
+ -z nocommon Generate common symbols with STT_OBJECT type\n"));
|
||
+ if (link_info.textrel_check == textrel_check_error)
|
||
+ fprintf (file, _("\
|
||
+ -z text Treat DT_TEXTREL in output as error (default)\n"));
|
||
+ else
|
||
+ fprintf (file, _("\
|
||
+ -z text Treat DT_TEXTREL in output as error\n"));
|
||
+ if (link_info.textrel_check == textrel_check_none)
|
||
+ {
|
||
+ fprintf (file, _("\
|
||
+ -z notext Don't treat DT_TEXTREL in output as error (default)\n"));
|
||
+ fprintf (file, _("\
|
||
+ -z textoff Don't treat DT_TEXTREL in output as error (default)\n"));
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ fprintf (file, _("\
|
||
+ -z notext Don't treat DT_TEXTREL in output as error\n"));
|
||
+ fprintf (file, _("\
|
||
+ -z textoff Don't treat DT_TEXTREL in output as error\n"));
|
||
+ }
|
||
+}
|
||
+
|
||
+static void
|
||
+elf_static_list_options (FILE *file)
|
||
+{
|
||
+ fprintf (file, _("\
|
||
+ --build-id[=STYLE] Generate build ID note\n"));
|
||
+ fprintf (file, _("\
|
||
+ --package-metadata[=JSON] Generate package metadata note\n"));
|
||
+ fprintf (file, _("\
|
||
+ --compress-debug-sections=[none|zlib|zlib-gnu|zlib-gabi|zstd]\n\
|
||
+ Compress DWARF debug sections\n"));
|
||
+ fprintf (file, _("\
|
||
+ Default: %s\n"),
|
||
+ bfd_get_compression_algorithm_name (config.compress_debug));
|
||
+ fprintf (file, _("\
|
||
+ -z common-page-size=SIZE Set common page size to SIZE\n"));
|
||
+ fprintf (file, _("\
|
||
+ -z max-page-size=SIZE Set maximum page size to SIZE\n"));
|
||
+ fprintf (file, _("\
|
||
+ -z defs Report unresolved symbols in object files\n"));
|
||
+ fprintf (file, _("\
|
||
+ -z undefs Ignore unresolved symbols in object files\n"));
|
||
+ fprintf (file, _("\
|
||
+ -z muldefs Allow multiple definitions\n"));
|
||
+ fprintf (file, _("\
|
||
+ -z stack-size=SIZE Set size of stack segment\n"));
|
||
+
|
||
+ fprintf (file, _("\
|
||
+ -z execstack Mark executable as requiring executable stack\n"));
|
||
+ fprintf (file, _("\
|
||
+ -z noexecstack Mark executable as not requiring executable stack\n"));
|
||
+ fprintf (file, _("\
|
||
+ --warn-execstack-objects Generate a warning if an object file requests an executable stack\n"));
|
||
+#if DEFAULT_LD_WARN_EXECSTACK == 0
|
||
+ fprintf (file, _("\
|
||
+ --warn-execstack Generate a warning if creating an executable stack\n"));
|
||
+#else
|
||
+ fprintf (file, _("\
|
||
+ --warn-execstack Generate a warning if creating an executable stack (default)\n"));
|
||
+#endif
|
||
+#if DEFAULT_LD_WARN_EXECSTACK == 0
|
||
+ fprintf (file, _("\
|
||
+ --no-warn-execstack Do not generate a warning if creating an executable stack (default)\n"));
|
||
+#else
|
||
+ fprintf (file, _("\
|
||
+ --no-warn-execstack Do not generate a warning if creating an executable stack\n"));
|
||
+#endif
|
||
+ fprintf (file, _("\
|
||
+ --error-execstack Turn warnings about executable stacks into errors\n"));
|
||
+ fprintf (file, _("\
|
||
+ --no-error-execstack Do not turn warnings about executable stacks into errors\n"));
|
||
+
|
||
+#if DEFAULT_LD_WARN_RWX_SEGMENTS
|
||
+ fprintf (file, _("\
|
||
+ --warn-rwx-segments Generate a warning if a LOAD segment has RWX permissions (default)\n"));
|
||
+ fprintf (file, _("\
|
||
+ --no-warn-rwx-segments Do not generate a warning if a LOAD segments has RWX permissions\n"));
|
||
+#else
|
||
+ fprintf (file, _("\
|
||
+ --warn-rwx-segments Generate a warning if a LOAD segment has RWX permissions\n"));
|
||
+ fprintf (file, _("\
|
||
+ --no-warn-rwx-segments Do not generate a warning if a LOAD segments has RWX permissions (default)\n"));
|
||
+#endif
|
||
+ fprintf (file, _("\
|
||
+ --error-rwx-segments Turn warnings about loadable RWX segments into errors\n"));
|
||
+ fprintf (file, _("\
|
||
+ --no-error-rwx-segments Do not turn warnings about loadable RWX segments into errors\n"));
|
||
+
|
||
+ fprintf (file, _("\
|
||
+ -z unique-symbol Avoid duplicated local symbol names\n"));
|
||
+ fprintf (file, _("\
|
||
+ -z nounique-symbol Keep duplicated local symbol names (default)\n"));
|
||
+ fprintf (file, _("\
|
||
+ -z globalaudit Mark executable requiring global auditing\n"));
|
||
+ fprintf (file, _("\
|
||
+ -z start-stop-gc Enable garbage collection on __start/__stop\n"));
|
||
+ fprintf (file, _("\
|
||
+ -z nostart-stop-gc Don't garbage collect __start/__stop (default)\n"));
|
||
+ fprintf (file, _("\
|
||
+ -z start-stop-visibility=V Set visibility of built-in __start/__stop symbols\n\
|
||
+ to DEFAULT, PROTECTED, HIDDEN or INTERNAL\n"));
|
||
+ fprintf (file, _("\
|
||
+ -z sectionheader Generate section header (default)\n"));
|
||
+ fprintf (file, _("\
|
||
+ -z nosectionheader Do not generate section header\n"));
|
||
+}
|
||
+
|
||
+static void
|
||
+elf_plt_unwind_list_options (FILE *file)
|
||
+{
|
||
+ fprintf (file, _("\
|
||
+ --ld-generated-unwind-info Generate exception handling info for PLT\n"));
|
||
+ fprintf (file, _("\
|
||
+ --no-ld-generated-unwind-info\n\
|
||
+ Don't generate exception handling info for PLT\n"));
|
||
+}
|
||
+
|
||
+static void
|
||
+ld_list_options (FILE *file, bool elf, bool shlib, bool plt_unwind)
|
||
+{
|
||
+ if (!elf)
|
||
+ return;
|
||
+ printf (_("ELF emulations:\n"));
|
||
+ if (plt_unwind)
|
||
+ elf_plt_unwind_list_options (file);
|
||
+ elf_static_list_options (file);
|
||
+ if (shlib)
|
||
+ elf_shlib_list_options (file);
|
||
+}
|
||
+
|
||
+
|
||
+/* Print help messages for the options. */
|
||
+
|
||
+static void
|
||
+help (void)
|
||
+{
|
||
+ unsigned i;
|
||
+ const char **targets, **pp;
|
||
+ int len;
|
||
+
|
||
+ printf (_("Usage: %s [options] file...\n"), program_name);
|
||
+
|
||
+ printf (_("Options:\n"));
|
||
+ for (i = 0; i < OPTION_COUNT; i++)
|
||
+ {
|
||
+ if (ld_options[i].doc != NULL)
|
||
+ {
|
||
+ bool comma;
|
||
+ unsigned j;
|
||
+
|
||
+ printf (" ");
|
||
+
|
||
+ comma = false;
|
||
+ len = 2;
|
||
+
|
||
+ j = i;
|
||
+ do
|
||
+ {
|
||
+ if (ld_options[j].shortopt != '\0'
|
||
+ && ld_options[j].control != NO_HELP)
|
||
+ {
|
||
+ printf ("%s-%c", comma ? ", " : "", ld_options[j].shortopt);
|
||
+ len += (comma ? 2 : 0) + 2;
|
||
+ if (ld_options[j].arg != NULL)
|
||
+ {
|
||
+ if (ld_options[j].opt.has_arg != optional_argument)
|
||
+ {
|
||
+ printf (" ");
|
||
+ ++len;
|
||
+ }
|
||
+ printf ("%s", _(ld_options[j].arg));
|
||
+ len += strlen (_(ld_options[j].arg));
|
||
+ }
|
||
+ comma = true;
|
||
+ }
|
||
+ ++j;
|
||
+ }
|
||
+ while (j < OPTION_COUNT && ld_options[j].doc == NULL);
|
||
+
|
||
+ j = i;
|
||
+ do
|
||
+ {
|
||
+ if (ld_options[j].opt.name != NULL
|
||
+ && ld_options[j].control != NO_HELP)
|
||
+ {
|
||
+ int two_dashes =
|
||
+ (ld_options[j].control == TWO_DASHES
|
||
+ || ld_options[j].control == EXACTLY_TWO_DASHES);
|
||
+
|
||
+ printf ("%s-%s%s",
|
||
+ comma ? ", " : "",
|
||
+ two_dashes ? "-" : "",
|
||
+ ld_options[j].opt.name);
|
||
+ len += ((comma ? 2 : 0)
|
||
+ + 1
|
||
+ + (two_dashes ? 1 : 0)
|
||
+ + strlen (ld_options[j].opt.name));
|
||
+ if (ld_options[j].arg != NULL)
|
||
+ {
|
||
+ printf (" %s", _(ld_options[j].arg));
|
||
+ len += 1 + strlen (_(ld_options[j].arg));
|
||
+ }
|
||
+ comma = true;
|
||
+ }
|
||
+ ++j;
|
||
+ }
|
||
+ while (j < OPTION_COUNT && ld_options[j].doc == NULL);
|
||
+
|
||
+ if (len >= 30)
|
||
+ {
|
||
+ printf ("\n");
|
||
+ len = 0;
|
||
+ }
|
||
+
|
||
+ for (; len < 30; len++)
|
||
+ putchar (' ');
|
||
+
|
||
+ printf ("%s\n", _(ld_options[i].doc));
|
||
+ }
|
||
+ }
|
||
+ printf (_(" @FILE"));
|
||
+ for (len = strlen (" @FILE"); len < 30; len++)
|
||
+ putchar (' ');
|
||
+ printf (_("Read options from FILE\n"));
|
||
+
|
||
+ /* Note: Various tools (such as libtool) depend upon the
|
||
+ format of the listings below - do not change them. */
|
||
+ /* xgettext:c-format */
|
||
+ printf (_("%s: supported targets:"), program_name);
|
||
+ targets = bfd_target_list ();
|
||
+ for (pp = targets; *pp != NULL; pp++)
|
||
+ printf (" %s", *pp);
|
||
+ free (targets);
|
||
+ printf ("\n");
|
||
+
|
||
+ /* xgettext:c-format */
|
||
+ printf (_("%s: supported emulations: "), program_name);
|
||
+ ldemul_list_emulations (stdout);
|
||
+ printf ("\n");
|
||
+
|
||
+ /* xgettext:c-format */
|
||
+ printf (_("%s: emulation specific options:\n"), program_name);
|
||
+ ld_list_options (stdout, ELF_LIST_OPTIONS, ELF_SHLIB_LIST_OPTIONS,
|
||
+ ELF_PLT_UNWIND_LIST_OPTIONS);
|
||
+ ldemul_list_emulation_options (stdout);
|
||
+ printf ("\n");
|
||
+
|
||
+ if (REPORT_BUGS_TO[0])
|
||
+ printf (_("Report bugs to %s\n"), REPORT_BUGS_TO);
|
||
+}
|
||
diff -rupN binutils.orig/ld/testsuite/ld-scripts/section-order-1a.d binutils-2.41/ld/testsuite/ld-scripts/section-order-1a.d
|
||
--- binutils.orig/ld/testsuite/ld-scripts/section-order-1a.d 1970-01-01 01:00:00.000000000 +0100
|
||
+++ binutils-2.41/ld/testsuite/ld-scripts/section-order-1a.d 2024-05-13 13:04:08.599633306 +0100
|
||
@@ -0,0 +1,22 @@
|
||
+#name: Text Section Ordering (section-order-1a)
|
||
+#source: section-order-1b.s
|
||
+#source: section-order-1a.s
|
||
+#source: start.s
|
||
+#ld: --section-ordering-file section-order-1a.t
|
||
+#nm: -n
|
||
+
|
||
+#...
|
||
+[0-9a-f]+ T yyy
|
||
+#...
|
||
+[0-9a-f]+ T bar
|
||
+#...
|
||
+[0-9a-f]+ T [_]+start
|
||
+#...
|
||
+[0-9a-f]+ T xxx
|
||
+#...
|
||
+[0-9a-f]+ T foo
|
||
+#...
|
||
+[0-9a-f]+ T qqq
|
||
+#...
|
||
+[0-9a-f]+ T zzz
|
||
+#pass
|
||
diff -rupN binutils.orig/ld/testsuite/ld-scripts/section-order-1a.s binutils-2.41/ld/testsuite/ld-scripts/section-order-1a.s
|
||
--- binutils.orig/ld/testsuite/ld-scripts/section-order-1a.s 1970-01-01 01:00:00.000000000 +0100
|
||
+++ binutils-2.41/ld/testsuite/ld-scripts/section-order-1a.s 2024-05-13 13:04:08.599633306 +0100
|
||
@@ -0,0 +1,29 @@
|
||
+ .section .text.foo
|
||
+ .globl foo
|
||
+foo:
|
||
+ .dc.a 0
|
||
+
|
||
+ .section .text.bar
|
||
+ .globl bar
|
||
+bar:
|
||
+ .dc.a 0
|
||
+
|
||
+ .section .data.small
|
||
+ .globl small
|
||
+small:
|
||
+ .dc.a 0
|
||
+
|
||
+ .section .bar
|
||
+ .global bar
|
||
+bart:
|
||
+ .dc.a 0
|
||
+
|
||
+ .section .text.zzz
|
||
+ .global zzz
|
||
+zzz:
|
||
+ .dc.a 0
|
||
+
|
||
+ .section .data.bbb
|
||
+ .global bbb
|
||
+bbb:
|
||
+ .dc.a 0
|
||
diff -rupN binutils.orig/ld/testsuite/ld-scripts/section-order-1a.t binutils-2.41/ld/testsuite/ld-scripts/section-order-1a.t
|
||
--- binutils.orig/ld/testsuite/ld-scripts/section-order-1a.t 1970-01-01 01:00:00.000000000 +0100
|
||
+++ binutils-2.41/ld/testsuite/ld-scripts/section-order-1a.t 2024-05-13 13:04:08.599633306 +0100
|
||
@@ -0,0 +1,14 @@
|
||
+.text : {
|
||
+ *(.text.yyy)
|
||
+ *(.text.b?r)
|
||
+ *(.text)
|
||
+ *(.text.xxx .text.foo)
|
||
+}
|
||
+
|
||
+.data : {
|
||
+ *(.data.small)
|
||
+ *(.big*)
|
||
+ *(.bar .baz*)
|
||
+ *(.data.ccc)
|
||
+}
|
||
+
|
||
diff -rupN binutils.orig/ld/testsuite/ld-scripts/section-order-1b.d binutils-2.41/ld/testsuite/ld-scripts/section-order-1b.d
|
||
--- binutils.orig/ld/testsuite/ld-scripts/section-order-1b.d 1970-01-01 01:00:00.000000000 +0100
|
||
+++ binutils-2.41/ld/testsuite/ld-scripts/section-order-1b.d 2024-05-13 13:04:08.599633306 +0100
|
||
@@ -0,0 +1,18 @@
|
||
+#name: Text Section Ordering (section-order-1b)
|
||
+#source: section-order-1a.s
|
||
+#source: section-order-1b.s
|
||
+#source: start.s
|
||
+#ld: --section-ordering-file section-order-1b.t
|
||
+#nm: -n
|
||
+
|
||
+#...
|
||
+[0-9a-f]+ T yyy
|
||
+#...
|
||
+[0-9a-f]+ T bar
|
||
+#...
|
||
+[0-9a-f]+ T [_]+start
|
||
+#...
|
||
+[0-9a-f]+ T xxx
|
||
+#...
|
||
+[0-9a-f]+ T foo
|
||
+#pass
|
||
diff -rupN binutils.orig/ld/testsuite/ld-scripts/section-order-1b.s binutils-2.41/ld/testsuite/ld-scripts/section-order-1b.s
|
||
--- binutils.orig/ld/testsuite/ld-scripts/section-order-1b.s 1970-01-01 01:00:00.000000000 +0100
|
||
+++ binutils-2.41/ld/testsuite/ld-scripts/section-order-1b.s 2024-05-13 13:04:08.599633306 +0100
|
||
@@ -0,0 +1,34 @@
|
||
+ .section .text.xxx
|
||
+ .globl xxx
|
||
+xxx:
|
||
+ .dc.a 0
|
||
+
|
||
+ .section .text.yyy
|
||
+ .globl yyy
|
||
+yyy:
|
||
+ .dc.a 0
|
||
+
|
||
+ .section .big
|
||
+ .global big
|
||
+big:
|
||
+ .dc.a 0
|
||
+
|
||
+ .section .baz
|
||
+ .global baz
|
||
+baz:
|
||
+ .dc.a 0
|
||
+
|
||
+ .section .text.qqq
|
||
+ .global qqq
|
||
+qqq:
|
||
+ .dc.a 0
|
||
+
|
||
+ .section .data.ccc
|
||
+ .global ccc
|
||
+ccc:
|
||
+ .dc.a 0
|
||
+
|
||
+ .data
|
||
+ .global data_symbol
|
||
+data_symbol:
|
||
+ .dc.a 0
|
||
diff -rupN binutils.orig/ld/testsuite/ld-scripts/section-order-1b.t binutils-2.41/ld/testsuite/ld-scripts/section-order-1b.t
|
||
--- binutils.orig/ld/testsuite/ld-scripts/section-order-1b.t 1970-01-01 01:00:00.000000000 +0100
|
||
+++ binutils-2.41/ld/testsuite/ld-scripts/section-order-1b.t 2024-05-13 13:04:08.599633306 +0100
|
||
@@ -0,0 +1,7 @@
|
||
+.text : {
|
||
+ *(.text.yyy)
|
||
+ *(.text.b?r)
|
||
+ *(*t)
|
||
+ *(.text.xxx)
|
||
+ *(.text.foo)
|
||
+}
|
||
diff -rupN binutils.orig/ld/testsuite/ld-scripts/section-order-1c.d binutils-2.41/ld/testsuite/ld-scripts/section-order-1c.d
|
||
--- binutils.orig/ld/testsuite/ld-scripts/section-order-1c.d 1970-01-01 01:00:00.000000000 +0100
|
||
+++ binutils-2.41/ld/testsuite/ld-scripts/section-order-1c.d 2024-05-13 13:04:08.599633306 +0100
|
||
@@ -0,0 +1,14 @@
|
||
+#name: Data Section Ordering (section-order-1c)
|
||
+#source: section-order-1b.s
|
||
+#source: section-order-1a.s
|
||
+#source: start.s
|
||
+#ld: --section-ordering-file section-order-1a.t
|
||
+#nm: -n
|
||
+
|
||
+#...
|
||
+[0-9a-f]+ D small
|
||
+#...
|
||
+[0-9a-f]+ D big
|
||
+#...
|
||
+[0-9a-f]+ D ba.*
|
||
+#pass
|
||
diff -rupN binutils.orig/ld/testsuite/ld-scripts/section-order-1d.d binutils-2.41/ld/testsuite/ld-scripts/section-order-1d.d
|
||
--- binutils.orig/ld/testsuite/ld-scripts/section-order-1d.d 1970-01-01 01:00:00.000000000 +0100
|
||
+++ binutils-2.41/ld/testsuite/ld-scripts/section-order-1d.d 2024-05-13 13:04:08.599633306 +0100
|
||
@@ -0,0 +1,18 @@
|
||
+#name: Data Section Ordering (section-order-1d)
|
||
+#source: section-order-1a.s
|
||
+#source: section-order-1b.s
|
||
+#source: start.s
|
||
+#ld: --section-ordering-file section-order-1a.t
|
||
+#nm: -n
|
||
+
|
||
+#...
|
||
+[0-9a-f]+ D small
|
||
+#...
|
||
+[0-9a-f]+ D big
|
||
+#...
|
||
+[0-9a-f]+ d bart
|
||
+#...
|
||
+[0-9a-f]+ D ccc
|
||
+#...
|
||
+[0-9a-f]+ D bbb
|
||
+#pass
|
||
diff -rupN binutils.orig/ld/testsuite/ld-scripts/section-order.exp binutils-2.41/ld/testsuite/ld-scripts/section-order.exp
|
||
--- binutils.orig/ld/testsuite/ld-scripts/section-order.exp 1970-01-01 01:00:00.000000000 +0100
|
||
+++ binutils-2.41/ld/testsuite/ld-scripts/section-order.exp 2024-05-13 13:04:08.599633306 +0100
|
||
@@ -0,0 +1,45 @@
|
||
+# Test for --section-ordering-file FILE.
|
||
+# Copyright (C) 2024 Free Software Foundation, Inc.
|
||
+#
|
||
+# This file is part of the GNU Binutils.
|
||
+#
|
||
+# This program is free software; you can redistribute it and/or modify
|
||
+# it under the terms of the GNU General Public License as published by
|
||
+# the Free Software Foundation; either version 3 of the License, or
|
||
+# (at your option) any later version.
|
||
+#
|
||
+# This program is distributed in the hope that it will be useful,
|
||
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
+# GNU General Public License for more details.
|
||
+#
|
||
+# You should have received a copy of the GNU General Public License
|
||
+# along with this program; if not, write to the Free Software
|
||
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
|
||
+# MA 02110-1301, USA.
|
||
+
|
||
+# The --section-ordering-file option is only supported by ELF and
|
||
+# PE COFF linkers, which allow for arbitrarily named sections, eg:
|
||
+# .text.*
|
||
+if { !([is_elf_format] || [is_pecoff_format]) } {
|
||
+ return
|
||
+}
|
||
+
|
||
+set old_ldflags $LDFLAGS
|
||
+if { [istarget spu*-*-*] } then {
|
||
+ set LDFLAGS "$LDFLAGS --local-store 0:0 --no-overlays"
|
||
+} elseif { [is_pecoff_format] } then {
|
||
+ set LDFLAGS "$LDFLAGS --image-base 0"
|
||
+} elseif { [is_xcoff_format] } then {
|
||
+ set LDFLAGS "$LDFLAGS -bnogc"
|
||
+}
|
||
+
|
||
+set test_list [lsort [glob -nocomplain $srcdir/$subdir/section-order*.d]]
|
||
+foreach test_file $test_list {
|
||
+ set test_name [file rootname $test_file]
|
||
+ set map_file "tmpdir/[file tail $test_name].map"
|
||
+ verbose $test_name
|
||
+ run_dump_test $test_name
|
||
+}
|
||
+
|
||
+set LDFLAGS $old_ldflags
|
||
diff -rupN binutils.orig/ld/testsuite/ld-scripts/start.s binutils-2.41/ld/testsuite/ld-scripts/start.s
|
||
--- binutils.orig/ld/testsuite/ld-scripts/start.s 1970-01-01 01:00:00.000000000 +0100
|
||
+++ binutils-2.41/ld/testsuite/ld-scripts/start.s 2024-05-13 13:04:08.599633306 +0100
|
||
@@ -0,0 +1,14 @@
|
||
+ .text
|
||
+ .global start /* Used by SH targets. */
|
||
+start:
|
||
+ .global _start
|
||
+_start:
|
||
+ .global __start
|
||
+__start:
|
||
+ .global _mainCRTStartup /* Used by PE targets. */
|
||
+_mainCRTStartup:
|
||
+ .global main /* Used by HPPA targets. */
|
||
+main:
|
||
+ .globl _main /* Used by LynxOS targets. */
|
||
+_main:
|
||
+ .dc.a 0
|