diff options
Diffstat (limited to 'ld')
-rw-r--r-- | ld/ChangeLog | 24 | ||||
-rw-r--r-- | ld/NEWS | 6 | ||||
-rw-r--r-- | ld/emultempl/elf32.em | 32 | ||||
-rwxr-xr-x | ld/genscripts.sh | 44 | ||||
-rw-r--r-- | ld/ld.texinfo | 6 | ||||
-rw-r--r-- | ld/ldint.texinfo | 22 | ||||
-rw-r--r-- | ld/ldmain.c | 2 | ||||
-rw-r--r-- | ld/lexsup.c | 6 | ||||
-rw-r--r-- | ld/scripttempl/elf.sc | 27 |
9 files changed, 157 insertions, 12 deletions
diff --git a/ld/ChangeLog b/ld/ChangeLog index b4a1302..c29a986 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,27 @@ +2001-08-23 Jakub Jelinek <jakub@redhat.com> + + * emultempl/elf32.em (place_orphan): Place orphan .rel* sections + into .rel.dyn resp. .rela.dyn if combreloc. + (get_script): If .x linker script is equal to .xn, only put it + once into the binary. + Add .xc and .xsc scripts. + (parse_args): Handle -z combreloc and -z nocombreloc. + * scripttempl/elf.sc (.rela.sbss): Fix a typo. + For .xc and .xsc scripts put all .rel* or .rela* input sections + but .rel*.plt and PLT-like sections into .rel.dyn resp. .rela.dyn. + * genscripts.sh (GENERATE_COMBRELOC_SCRIPT): Set if SCRIPT_NAME + is elf. + Strip trailing whitespace from script. + Generate .xc and .xsc scripts if requested. + * ldmain.c (main): Initialize link_info.combreloc and + link_info.spare_dynamic_tags. + * lexsup.c (OPTION_SPARE_DYNAMIC_TAGS): Define. + (ld_options): Add --spare-dynamic-tags option. + (parse_args): Likewise. + * ld.texinfo: Document -z combreloc and -z nocombreloc. + * ldint.texinfo: Document .xc and .xsc linker scripts. + * NEWS: Add notes about -z combreloc and SHF_MERGE. + 2001-08-22 H.J. Lu <hjl@gnu.org> * emulparams/elf32fr30.sh: Add a newline. @@ -1,5 +1,11 @@ -*- text -*- +* 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. + * Support for AMD x86-64 architecture, by Jan Hubicka, SuSE Labs. * Support added for eliminating duplicate DWARF2 debug information by diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em index 93dc739..0e5cd99 100644 --- a/ld/emultempl/elf32.em +++ b/ld/emultempl/elf32.em @@ -1135,7 +1135,25 @@ gld${EMULATION_NAME}_place_orphan (file, s) else if (strncmp (secname, ".rel", 4) == 0 && (hold_rel.os != NULL || (hold_rel.os = output_rel_find ()) != NULL)) - place = &hold_rel; + { + if (! link_info.relocateable && link_info.combreloc) + { + if (strncmp (secname, ".rela", 5) == 0) + os = lang_output_section_find (".rela.dyn"); + else + os = lang_output_section_find (".rel.dyn"); + + if (os != NULL + && os->bfd_section != NULL + && ((s->flags ^ os->bfd_section->flags) + & (SEC_LOAD | SEC_ALLOC)) == 0) + { + lang_add_section (&os->children, s, os, file); + return true; + } + } + place = &hold_rel; + } else if ((s->flags & (SEC_CODE | SEC_READONLY)) == SEC_READONLY && HAVE_SECTION (hold_rodata, ".rodata")) place = &hold_rodata; @@ -1332,14 +1350,18 @@ echo ' ; else if (link_info.relocateable == true) return' >> e${EMULATION_NAME} sed $sc ldscripts/${EMULATION_NAME}.xr >> e${EMULATION_NAME}.c echo ' ; else if (!config.text_read_only) return' >> e${EMULATION_NAME}.c sed $sc ldscripts/${EMULATION_NAME}.xbn >> e${EMULATION_NAME}.c +if ! cmp -s ldscripts/${EMULATION_NAME}.x ldscripts/${EMULATION_NAME}.xn; then echo ' ; else if (!config.magic_demand_paged) return' >> e${EMULATION_NAME}.c sed $sc ldscripts/${EMULATION_NAME}.xn >> e${EMULATION_NAME}.c - +fi if test -n "$GENERATE_SHLIB_SCRIPT" ; then +echo ' ; else if (link_info.shared && link_info.combreloc) return' >> e${EMULATION_NAME}.c +sed $sc ldscripts/${EMULATION_NAME}.xsc >> e${EMULATION_NAME}.c echo ' ; else if (link_info.shared) return' >> e${EMULATION_NAME}.c sed $sc ldscripts/${EMULATION_NAME}.xs >> e${EMULATION_NAME}.c fi - +echo ' ; else if (link_info.combreloc) return' >> e${EMULATION_NAME}.c +sed $sc ldscripts/${EMULATION_NAME}.xc >> e${EMULATION_NAME}.c echo ' ; else return' >> e${EMULATION_NAME}.c sed $sc ldscripts/${EMULATION_NAME}.x >> e${EMULATION_NAME}.c echo '; }' >> e${EMULATION_NAME}.c @@ -1492,6 +1514,10 @@ cat >>e${EMULATION_NAME}.c <<EOF } else if (strcmp (optarg, "defs") == 0) link_info.no_undefined = true; + else if (strcmp (optarg, "combreloc") == 0) + link_info.combreloc = true; + else if (strcmp (optarg, "nocombreloc") == 0) + link_info.combreloc = false; /* What about the other Solaris -z options? FIXME. */ break; EOF diff --git a/ld/genscripts.sh b/ld/genscripts.sh index d3ab768..f169132 100755 --- a/ld/genscripts.sh +++ b/ld/genscripts.sh @@ -84,6 +84,17 @@ LIB_SEARCH_DIRS=`echo ${LIB_PATH} | tr ':' ' ' | sed -e 's/\([^ ][^ ]*\)/SEARCH_ # A .xs script is for generating a shared library with the --shared # flag; it is only generated if $GENERATE_SHLIB_SCRIPT is set by the # emulation parameters. +# A .xc script is for linking with -z combreloc; it is only generated if +# $GENERATE_COMBRELOC_SCRIPT is set by the emulation parameters or +# $SCRIPT_NAME is "elf". +# A .xsc script is for linking with --shared -z combreloc; it is generated +# if $GENERATE_COMBRELOC_SCRIPT is set by the emulation parameters or +# $SCRIPT_NAME is "elf" and $GENERATE_SHLIB_SCRIPT is set by the emulation +# parameters too. + +if [ "x$SCRIPT_NAME" = "xelf" ]; then + GENERATE_COMBRELOC_SCRIPT=yes +fi SEGMENT_SIZE=${SEGMENT_SIZE-${TARGET_PAGE_SIZE}} @@ -101,34 +112,45 @@ DATA_ALIGNMENT=${DATA_ALIGNMENT_r} DEFAULT_DATA_ALIGNMENT="ALIGN(${SEGMENT_SIZE})" ( . ${srcdir}/emulparams/${EMULATION_NAME}.sh . ${srcdir}/scripttempl/${SCRIPT_NAME}.sc -) | sed -e '/^ *$/d' > ldscripts/${EMULATION_NAME}.xr +) | sed -e '/^ *$/d;s/[ ]*$//' > ldscripts/${EMULATION_NAME}.xr LD_FLAG=u DATA_ALIGNMENT=${DATA_ALIGNMENT_u} CONSTRUCTING=" " ( . ${srcdir}/emulparams/${EMULATION_NAME}.sh . ${srcdir}/scripttempl/${SCRIPT_NAME}.sc -) | sed -e '/^ *$/d' > ldscripts/${EMULATION_NAME}.xu +) | sed -e '/^ *$/d;s/[ ]*$//' > ldscripts/${EMULATION_NAME}.xu LD_FLAG= DATA_ALIGNMENT=${DATA_ALIGNMENT_} RELOCATING=" " ( . ${srcdir}/emulparams/${EMULATION_NAME}.sh . ${srcdir}/scripttempl/${SCRIPT_NAME}.sc -) | sed -e '/^ *$/d' > ldscripts/${EMULATION_NAME}.x +) | sed -e '/^ *$/d;s/[ ]*$//' > ldscripts/${EMULATION_NAME}.x LD_FLAG=n DATA_ALIGNMENT=${DATA_ALIGNMENT_n} TEXT_START_ADDR=${NONPAGED_TEXT_START_ADDR-${TEXT_START_ADDR}} ( . ${srcdir}/emulparams/${EMULATION_NAME}.sh . ${srcdir}/scripttempl/${SCRIPT_NAME}.sc -) | sed -e '/^ *$/d' > ldscripts/${EMULATION_NAME}.xn +) | sed -e '/^ *$/d;s/[ ]*$//' > ldscripts/${EMULATION_NAME}.xn LD_FLAG=N DATA_ALIGNMENT=${DATA_ALIGNMENT_N} ( . ${srcdir}/emulparams/${EMULATION_NAME}.sh . ${srcdir}/scripttempl/${SCRIPT_NAME}.sc -) | sed -e '/^ *$/d' > ldscripts/${EMULATION_NAME}.xbn +) | sed -e '/^ *$/d;s/[ ]*$//' > ldscripts/${EMULATION_NAME}.xbn + +if test -n "$GENERATE_COMBRELOC_SCRIPT"; then + DATA_ALIGNMENT=${DATA_ALIGNMENT_c-${DATA_ALIGNMENT_}} + LD_FLAG=c + COMBRELOC=ldscripts/${EMULATION_NAME}.xc.tmp + ( . ${srcdir}/emulparams/${EMULATION_NAME}.sh + . ${srcdir}/scripttempl/${SCRIPT_NAME}.sc + ) | sed -e '/^ *$/d;s/[ ]*$//' > ldscripts/${EMULATION_NAME}.xc + rm -f ${COMBRELOC} + COMBRELOC= +fi if test -n "$GENERATE_SHLIB_SCRIPT"; then LD_FLAG=shared @@ -137,7 +159,17 @@ if test -n "$GENERATE_SHLIB_SCRIPT"; then # Note that TEXT_START_ADDR is set to NONPAGED_TEXT_START_ADDR. ( . ${srcdir}/emulparams/${EMULATION_NAME}.sh . ${srcdir}/scripttempl/${SCRIPT_NAME}.sc - ) | sed -e '/^ *$/d' > ldscripts/${EMULATION_NAME}.xs + ) | sed -e '/^ *$/d;s/[ ]*$//' > ldscripts/${EMULATION_NAME}.xs + if test -n "$GENERATE_COMBRELOC_SCRIPT"; then + LD_FLAG=cshared + DATA_ALIGNMENT=${DATA_ALIGNMENT_sc-${DATA_ALIGNMENT}} + COMBRELOC=ldscripts/${EMULATION_NAME}.xc.tmp + ( . ${srcdir}/emulparams/${EMULATION_NAME}.sh + . ${srcdir}/scripttempl/${SCRIPT_NAME}.sc + ) | sed -e '/^ *$/d;s/[ ]*$//' > ldscripts/${EMULATION_NAME}.xsc + rm -f ${COMBRELOC} + COMBRELOC= + fi fi for i in $EMULATION_LIBPATH ; do diff --git a/ld/ld.texinfo b/ld/ld.texinfo index 95785e0..5bc0a30 100644 --- a/ld/ld.texinfo +++ b/ld/ld.texinfo @@ -840,7 +840,8 @@ for Solaris compatibility. @item -z @var{keyword} The recognized keywords are @code{initfirst}, @code{interpose}, @code{loadfltr}, @code{nodefaultlib}, @code{nodelete}, @code{nodlopen}, -@code{nodump}, @code{now} and @code{origin}. The other keywords are +@code{nodump}, @code{now}, @code{origin}, @code{combreloc} and +@code{nocombreloc}. The other keywords are ignored for Solaris compatibility. @code{initfirst} marks the object to be initialized first at runtime before any other objects. @code{interpose} marks the object that its symbol table interposes @@ -854,6 +855,9 @@ of this object will ignore any default library search paths. @code{now} marks the object with the non-lazy runtime binding. @code{origin} marks the object may contain $ORIGIN. @code{defs} disallows undefined symbols. +@code{combreloc} combines multiple reloc sections and sorts them +to make dynamic symbol lookup caching possible. +@code{nocombreloc} disables multiple reloc sections combining. @kindex -( @cindex groups of archives diff --git a/ld/ldint.texinfo b/ld/ldint.texinfo index 47a9817..489750a 100644 --- a/ld/ldint.texinfo +++ b/ld/ldint.texinfo @@ -239,7 +239,7 @@ If @code{SCRIPT_NAME} is set to @var{script}, @code{genscripts.sh} will invoke @file{scripttempl/@var{script}.sc}. The @file{genscripts.sh} script will invoke the @file{scripttempl} -script 5 or 6 times. Each time it will set the shell variable +script 5 to 8 times. Each time it will set the shell variable @code{LD_FLAG} to a different value. When the linker is run, the options used will direct it to select a particular script. (Script selection is controlled by the @code{get_script} emulation entry point; @@ -278,6 +278,22 @@ this value if @code{GENERATE_SHLIB_SCRIPT} is defined in the this script at the appropriate time, normally when the linker is invoked with the @code{-shared} option. The output has an extension of @file{.xs}. +@item c +The @file{scripttempl} script is only invoked with @code{LD_FLAG} set to +this value if @code{GENERATE_COMBRELOC_SCRIPT} is defined in the +@file{emulparams} file or if @code{SCRIPT_NAME} is @code{elf}. The +@file{emultempl} script must arrange to use this script at the appropriate +time, normally when the linker is invoked with the @code{-z combreloc} +option. The output has an extension of +@file{.xc}. +@item cshared +The @file{scripttempl} script is only invoked with @code{LD_FLAG} set to +this value if @code{GENERATE_COMBRELOC_SCRIPT} is defined in the +@file{emulparams} file or if @code{SCRIPT_NAME} is @code{elf} and +@code{GENERATE_SHLIB_SCRIPT} is defined in the @file{emulparms} file. +The @file{emultempl} script must arrange to use this script at the +appropriate time, normally when the linker is invoked with the @code{-shared +-z combreloc} option. The output has an extension of @file{.xsc}. @end table Besides the shell variables set by the @file{emulparams} script, and the @@ -301,6 +317,10 @@ page aligned, or to @samp{.} when generating the @code{-N} script. @item CREATE_SHLIB This will be set to a non-empty string when generating a @code{-shared} script. + +@item COMBRELOC +This will be set to a non-empty string when generating @code{-z combreloc} +scripts to a temporary file name which can be used during script generation. @end table The conventional way to write a @file{scripttempl} script is to first diff --git a/ld/ldmain.c b/ld/ldmain.c index 0ec7891..b7114f9 100644 --- a/ld/ldmain.c +++ b/ld/ldmain.c @@ -244,6 +244,8 @@ main (argc, argv) link_info.flags = (bfd_vma) 0; link_info.flags_1 = (bfd_vma) 0; link_info.pei386_auto_import = false; + link_info.combreloc = false; + link_info.spare_dynamic_tags = 5; ldfile_add_arch (""); diff --git a/ld/lexsup.c b/ld/lexsup.c index 7e23a7d..5183b86 100644 --- a/ld/lexsup.c +++ b/ld/lexsup.c @@ -131,6 +131,7 @@ int parsing_defsym = 0; #define OPTION_TARGET_HELP (OPTION_UNIQUE + 1) #define OPTION_ALLOW_SHLIB_UNDEFINED (OPTION_TARGET_HELP + 1) #define OPTION_DISCARD_NONE (OPTION_ALLOW_SHLIB_UNDEFINED + 1) +#define OPTION_SPARE_DYNAMIC_TAGS (OPTION_DISCARD_NONE + 1) /* The long options. This structure is used for both the option parsing and the help text. */ @@ -347,6 +348,8 @@ static const struct ld_option ld_options[] = '\0', NULL, N_("Sort common symbols by size"), TWO_DASHES }, { {"sort_common", no_argument, NULL, OPTION_SORT_COMMON}, '\0', NULL, NULL, NO_HELP }, + { {"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}, @@ -1073,6 +1076,9 @@ the GNU General Public License. This program has absolutely no warranty.\n")); 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); diff --git a/ld/scripttempl/elf.sc b/ld/scripttempl/elf.sc index 84630bd..8ccf803 100644 --- a/ld/scripttempl/elf.sc +++ b/ld/scripttempl/elf.sc @@ -145,6 +145,13 @@ SECTIONS .gnu.version_d ${RELOCATING-0} : { *(.gnu.version_d) } .gnu.version_r ${RELOCATING-0} : { *(.gnu.version_r) } +EOF +if [ "x$COMBRELOC" = x ]; then + COMBRELOCCAT=cat +else + COMBRELOCCAT="cat > $COMBRELOC" +fi +eval $COMBRELOCCAT <<EOF .rel.init ${RELOCATING-0} : { *(.rel.init) } .rela.init ${RELOCATING-0} : { *(.rela.init) } .rel.text ${RELOCATING-0} : @@ -215,7 +222,7 @@ SECTIONS { *(.rela.sbss) ${RELOCATING+*(.rela.sbss.*)} - ${RELOCATING+*(.rel.gnu.linkonce.sb.*)} + ${RELOCATING+*(.rela.gnu.linkonce.sb.*)} } .rel.sdata2 ${RELOCATING-0} : { @@ -253,6 +260,24 @@ SECTIONS ${RELOCATING+*(.rela.bss.*)} ${RELOCATING+*(.rela.gnu.linkonce.b.*)} } +EOF +if [ -n "$COMBRELOC" ]; then +cat <<EOF + .rel.dyn : + { +EOF +sed -e '/^[ ]*[{}][ ]*$/d;/:[ ]*$/d;/\.rela\./d;s/^.*: { *\(.*\)}$/ \1/' $COMBRELOC +cat <<EOF + } + .rela.dyn : + { +EOF +sed -e '/^[ ]*[{}][ ]*$/d;/:[ ]*$/d;/\.rel\./d;s/^.*: { *\(.*\)}/ \1/' $COMBRELOC +cat <<EOF + } +EOF +fi +cat <<EOF .rel.plt ${RELOCATING-0} : { *(.rel.plt) } .rela.plt ${RELOCATING-0} : { *(.rela.plt) } ${OTHER_PLT_RELOC_SECTIONS} |