From mboxrd@z Thu Jan 1 00:00:00 1970 From: Jakub Jelinek To: binutils@sources.redhat.com, drepper@redhat.com Subject: [PATCH] Support -z combreloc in binutils Date: Wed, 15 Aug 2001 08:27:00 -0000 Message-id: <20010815173030.K510@sunsite.ms.mff.cuni.cz> X-SW-Source: 2001-08/msg00311.html Hi! This patch adds support for ld -z combreloc, which instead of creating usual zillions of .rel* resp. .rela* sections just creates one big (in addition to .rel.plt/.rela.plt or PLT-like rela section) .rel.dyn resp. .rela.dyn section with all dynamic relocations. This section is sorted if possible by increasing r_offset, with the exception that if there are multiple relocs against the same symbol, they are grouped together (which allows the dynamic linker to have a single entry cache for symbol lookups). In addition to this, it sets DT_RELCOUNT resp. DT_RELACOUNT dynamic tag in the way Solaris linker uses it (and compatible to the Solaris way, which is IMHO broken - R_*_RELATIVE symbols come last, not first), so that if a library has l_addr 0, all the R_*_RELATIVE relocs can be skipped for free. I tried to implement this so that only minimal changes in elf backends are needed (each backend just needs to provide function which categorizes reloc types: relative, plt, copy relocs or other relocs). Also, it reserves a few entries for use in prelinking, but user can disable this (this is necessary for DT_REL*COUNT too, since I don't want to create it if no relative relocs are found). 2001-08-15 Jakub Jelinek * elf-bfd.h (enum elf_reloc_type_class): New. (struct elf_backend_data): Add elf_backend_reloc_type_class. (_bfd_elf_reloc_type_class): New. * elfxx-target.h (elf_backend_reloc_type_class): Define. (elfNN_bed): Add elf_backend_reloc_type_class. * elf.c (_bfd_elf_reloc_type_class): New. * elf32-i386.c (elf_i386_reloc_type_class): New. (elf_backend_reloc_type_class): Define. * elflink.h (size_dynamic_sections): Add spare DT_NULL tags. (struct elf_link_sort_rela): New. (elf_link_sort_cmp1, elf_link_sort_cmp2, elf_link_sort_relocs): New. (elf_bfd_final_link): Call elf_link_sort_relocs. Convert one spare DT_NULL into DT_RELCOUNT resp. DT_RELACOUNT if necessary. * bfdlink.h (struct bfd_link_info): Add combreloc and spare_dynamic_tags fields. * 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. --- bfd/elf-bfd.h.jj Mon Aug 13 13:05:23 2001 +++ bfd/elf-bfd.h Wed Aug 15 17:16:55 2001 @@ -331,6 +331,14 @@ struct elf_size_info { ? (elf_symbol_type *) (S) \ : 0) +enum elf_reloc_type_class +{ + reloc_class_normal, + reloc_class_relative, + reloc_class_plt, + reloc_class_copy +}; + struct elf_backend_data { /* The architecture for this backend. */ @@ -636,10 +644,13 @@ struct elf_backend_data note is found in a core file. */ boolean (*elf_backend_grok_psinfo) PARAMS ((bfd *, Elf_Internal_Note *)); - /* Functions to print VMAs. Special code to handle 64 bit ELF files. */ + /* Functions to print VMAs. Special code to handle 64 bit ELF files. */ void (* elf_backend_sprintf_vma) PARAMS ((bfd *, char *, bfd_vma)); void (* elf_backend_fprintf_vma) PARAMS ((bfd *, PTR, bfd_vma)); + /* This function returns class of a reloc type. */ + enum elf_reloc_type_class (* elf_backend_reloc_type_class) PARAMS ((int)); + /* The swapping table to use when dealing with ECOFF information. Used for the MIPS ELF .mdebug section. */ const struct ecoff_debug_swap *elf_backend_ecoff_debug_swap; @@ -1005,6 +1016,8 @@ extern void bfd_elf_print_symbol PARAMS extern void _bfd_elf_sprintf_vma PARAMS ((bfd *, char *, bfd_vma)); extern void _bfd_elf_fprintf_vma PARAMS ((bfd *, PTR, bfd_vma)); + +extern enum elf_reloc_type_class _bfd_elf_reloc_type_class PARAMS ((int)); extern unsigned long bfd_elf_hash PARAMS ((const char *)); --- bfd/elfxx-target.h.jj Mon Aug 13 13:05:23 2001 +++ bfd/elfxx-target.h Wed Aug 15 17:16:55 2001 @@ -344,6 +344,9 @@ Foundation, Inc., 59 Temple Place - Suit #ifndef elf_backend_fprintf_vma #define elf_backend_fprintf_vma _bfd_elf_fprintf_vma #endif +#ifndef elf_backend_reloc_type_class +#define elf_backend_reloc_type_class _bfd_elf_reloc_type_class +#endif /* Previously, backends could only use SHT_REL or SHT_RELA relocation sections, but not both. They defined USE_REL to indicate SHT_REL @@ -431,6 +434,7 @@ static CONST struct elf_backend_data elf elf_backend_grok_psinfo, elf_backend_sprintf_vma, elf_backend_fprintf_vma, + elf_backend_reloc_type_class, elf_backend_ecoff_debug_swap, ELF_MACHINE_ALT1, ELF_MACHINE_ALT2, --- bfd/elf.c.jj Mon Aug 13 13:05:23 2001 +++ bfd/elf.c Wed Aug 15 17:16:55 2001 @@ -6057,3 +6057,10 @@ _bfd_elf_fprintf_vma (abfd, stream, valu fprintf_vma ((FILE *) stream, value); #endif } + +enum elf_reloc_type_class +_bfd_elf_reloc_type_class (type) + int type; +{ + return reloc_class_normal; +} --- bfd/elf32-i386.c.jj Mon Aug 13 13:05:23 2001 +++ bfd/elf32-i386.c Wed Aug 15 17:16:55 2001 @@ -63,6 +63,7 @@ static boolean elf_i386_finish_dynamic_s PARAMS ((bfd *, struct bfd_link_info *)); static boolean elf_i386_fake_sections PARAMS ((bfd *, Elf32_Internal_Shdr *, asection *)); +static enum elf_reloc_type_class elf_i386_reloc_type_class PARAMS ((int)); #define USE_REL 1 /* 386 uses REL relocations instead of RELA */ @@ -2215,6 +2216,22 @@ elf_i386_fake_sections (abfd, hdr, sec) return true; } +static enum elf_reloc_type_class +elf_i386_reloc_type_class (type) + int type; +{ + switch (type) + { + case R_386_RELATIVE: + return reloc_class_relative; + case R_386_JUMP_SLOT: + return reloc_class_plt; + case R_386_COPY: + return reloc_class_copy; + default: + return reloc_class_normal; + } +} #define TARGET_LITTLE_SYM bfd_elf32_i386_vec #define TARGET_LITTLE_NAME "elf32-i386" @@ -2246,5 +2263,6 @@ elf_i386_fake_sections (abfd, hdr, sec) #define elf_backend_relocate_section elf_i386_relocate_section #define elf_backend_size_dynamic_sections elf_i386_size_dynamic_sections #define elf_backend_fake_sections elf_i386_fake_sections +#define elf_backend_reloc_type_class elf_i386_reloc_type_class #include "elf32-target.h" --- bfd/elflink.h.jj Mon Aug 13 13:05:23 2001 +++ bfd/elflink.h Wed Aug 15 17:16:55 2001 @@ -67,6 +67,12 @@ static boolean elf_link_size_reloc_secti static void elf_link_adjust_relocs PARAMS ((bfd *, Elf_Internal_Shdr *, unsigned int, struct elf_link_hash_entry **)); +static int elf_link_sort_cmp1 + PARAMS ((const void *, const void *)); +static int elf_link_sort_cmp2 + PARAMS ((const void *, const void *)); +static size_t elf_link_sort_relocs + PARAMS ((bfd *, struct bfd_link_info *, asection **)); /* Given an ELF BFD, add symbols to the global hash table as appropriate. */ @@ -3065,6 +3071,7 @@ NAME(bfd_elf,size_dynamic_sections) (out asection *s; size_t bucketcount = 0; size_t hash_entry_size; + unsigned int dtagcount; /* Set up the version definition section. */ s = bfd_get_section_by_name (dynobj, ".gnu.version_d"); @@ -3439,8 +3446,9 @@ NAME(bfd_elf,size_dynamic_sections) (out BFD_ASSERT (s != NULL); s->_raw_size = _bfd_stringtab_size (elf_hash_table (info)->dynstr); - if (! elf_add_dynamic_entry (info, DT_NULL, 0)) - return false; + for (dtagcount = 0; dtagcount <= info->spare_dynamic_tags; ++dtagcount) + if (! elf_add_dynamic_entry (info, DT_NULL, 0)) + return false; } return true; @@ -4270,6 +4278,212 @@ elf_link_adjust_relocs (abfd, rel_hdr, c free (irela); } +struct elf_link_sort_rela +{ + bfd_vma offset; + enum elf_reloc_type_class type; + union + { + Elf_Internal_Rel rel; + Elf_Internal_Rela rela; + } u; +}; + +static int +elf_link_sort_cmp1 (A, B) + const PTR A; + const PTR B; +{ + struct elf_link_sort_rela *a = (struct elf_link_sort_rela *)A; + struct elf_link_sort_rela *b = (struct elf_link_sort_rela *)B; + int relativea, relativeb; + + relativea = a->type == reloc_class_relative; + relativeb = b->type == reloc_class_relative; + + if (relativea < relativeb) + return -1; + if (relativea > relativeb) + return 1; + if (ELF_R_SYM (a->u.rel.r_info) < ELF_R_SYM (b->u.rel.r_info)) + return -1; + if (ELF_R_SYM (a->u.rel.r_info) > ELF_R_SYM (b->u.rel.r_info)) + return 1; + if (a->u.rel.r_offset < b->u.rel.r_offset) + return -1; + if (a->u.rel.r_offset > b->u.rel.r_offset) + return 1; + return 0; +} + +static int +elf_link_sort_cmp2 (A, B) + const PTR A; + const PTR B; +{ + struct elf_link_sort_rela *a = (struct elf_link_sort_rela *)A; + struct elf_link_sort_rela *b = (struct elf_link_sort_rela *)B; + int copya, copyb; + + if (a->offset < b->offset) + return -1; + if (a->offset > b->offset) + return 1; + copya = a->type == reloc_class_copy; + copyb = b->type == reloc_class_copy; + if (copya < copyb) + return -1; + if (copya > copyb) + return 1; + if (a->u.rel.r_offset < b->u.rel.r_offset) + return -1; + if (a->u.rel.r_offset > b->u.rel.r_offset) + return 1; + return 0; +} + +static size_t +elf_link_sort_relocs (abfd, info, psec) + bfd *abfd; + struct bfd_link_info *info; + asection **psec; +{ + bfd *dynobj = elf_hash_table (info)->dynobj; + asection *reldyn, *o; + boolean rel = false; + size_t count, size, i, j, ret; + struct elf_link_sort_rela *rela; + struct elf_backend_data *bed = get_elf_backend_data (abfd); + + reldyn = bfd_get_section_by_name (abfd, ".rela.dyn"); + if (reldyn == NULL || reldyn->_raw_size == 0) + { + reldyn = bfd_get_section_by_name (abfd, ".rel.dyn"); + if (reldyn == NULL || reldyn->_raw_size == 0) + return 0; + rel = true; + count = reldyn->_raw_size / sizeof (Elf_External_Rel); + } + else + count = reldyn->_raw_size / sizeof (Elf_External_Rela); + + size = 0; + for (o = dynobj->sections; o != NULL; o = o->next) + if ((o->flags & (SEC_HAS_CONTENTS|SEC_LINKER_CREATED)) + == (SEC_HAS_CONTENTS|SEC_LINKER_CREATED) + && o->output_section == reldyn) + size += o->_raw_size; + + if (size != reldyn->_raw_size) + return 0; + + rela = (struct elf_link_sort_rela *) calloc (sizeof (*rela), count); + if (rela == NULL) + { + (*info->callbacks->warning) + (info, _("Not enough memory to sort relocations"), 0, abfd, 0, 0); + return 0; + } + + for (o = dynobj->sections; o != NULL; o = o->next) + if ((o->flags & (SEC_HAS_CONTENTS|SEC_LINKER_CREATED)) + == (SEC_HAS_CONTENTS|SEC_LINKER_CREATED) + && o->output_section == reldyn) + { + if (rel) + { + Elf_External_Rel *erel, *erelend; + struct elf_link_sort_rela *s; + + erel = (Elf_External_Rel *) o->contents; + erelend = (Elf_External_Rel *) ((PTR) o->contents + o->_raw_size); + s = rela + o->output_offset / sizeof (Elf_External_Rel); + for (; erel < erelend; erel++, s++) + { + if (bed->s->swap_reloc_in) + (*bed->s->swap_reloc_in) (abfd, (bfd_byte *) erel, &s->u.rel); + else + elf_swap_reloc_in (abfd, erel, &s->u.rel); + + s->type = (*bed->elf_backend_reloc_type_class) + (ELF_R_TYPE (s->u.rel.r_info)); + } + } + else + { + Elf_External_Rela *erela, *erelaend; + struct elf_link_sort_rela *s; + + erela = (Elf_External_Rela *) o->contents; + erelaend = (Elf_External_Rela *) ((PTR) o->contents + o->_raw_size); + s = rela + o->output_offset / sizeof (Elf_External_Rela); + for (; erela < erelaend; erela++, s++) + { + if (bed->s->swap_reloca_in) + (*bed->s->swap_reloca_in) (dynobj, (bfd_byte *) erela, &s->u.rela); + else + elf_swap_reloca_in (dynobj, erela, &s->u.rela); + + s->type = (*bed->elf_backend_reloc_type_class) + (ELF_R_TYPE (s->u.rel.r_info)); + } + } + } + + qsort (rela, count, sizeof (*rela), elf_link_sort_cmp1); + for (i = 0, j = 0; i < count && rela[i].type != reloc_class_relative; i++) + { + if (ELF_R_SYM (rela[i].u.rel.r_info) != ELF_R_SYM (rela[j].u.rel.r_info)) + j = i; + rela[i].offset = rela[j].u.rel.r_offset; + } + ret = count - i; + qsort (rela, i, sizeof (*rela), elf_link_sort_cmp2); + + for (o = dynobj->sections; o != NULL; o = o->next) + if ((o->flags & (SEC_HAS_CONTENTS|SEC_LINKER_CREATED)) + == (SEC_HAS_CONTENTS|SEC_LINKER_CREATED) + && o->output_section == reldyn) + { + if (rel) + { + Elf_External_Rel *erel, *erelend; + struct elf_link_sort_rela *s; + + erel = (Elf_External_Rel *) o->contents; + erelend = (Elf_External_Rel *) ((PTR) o->contents + o->_raw_size); + s = rela + o->output_offset / sizeof (Elf_External_Rel); + for (; erel < erelend; erel++, s++) + { + if (bed->s->swap_reloc_out) + (*bed->s->swap_reloc_out) (abfd, &s->u.rel, (bfd_byte *) erel); + else + elf_swap_reloc_out (abfd, &s->u.rel, erel); + } + } + else + { + Elf_External_Rela *erela, *erelaend; + struct elf_link_sort_rela *s; + + erela = (Elf_External_Rela *) o->contents; + erelaend = (Elf_External_Rela *) ((PTR) o->contents + o->_raw_size); + s = rela + o->output_offset / sizeof (Elf_External_Rela); + for (; erela < erelaend; erela++, s++) + { + if (bed->s->swap_reloca_out) + (*bed->s->swap_reloca_out) (dynobj, &s->u.rela, (bfd_byte *) erela); + else + elf_swap_reloca_out (dynobj, &s->u.rela, erela); + } + } + } + + free (rela); + *psec = reldyn; + return ret; +} + /* Do the final step of an ELF link. */ boolean @@ -4296,6 +4510,8 @@ elf_bfd_final_link (abfd, info) struct elf_backend_data *bed = get_elf_backend_data (abfd); struct elf_outext_info eoinfo; boolean merged; + size_t relativecount = 0; + asection *reldyn = 0; if (info->shared) abfd->flags |= DYNAMIC; @@ -4866,6 +5082,9 @@ elf_bfd_final_link (abfd, info) o->reloc_count = 0; } + if (dynamic && info->combreloc && dynobj != NULL) + relativecount = elf_link_sort_relocs (abfd, info, &reldyn); + /* If we are linking against a dynamic object, or generating a shared library, finish up the dynamic linking information. */ if (dynamic) @@ -4889,6 +5108,23 @@ elf_bfd_final_link (abfd, info) switch (dyn.d_tag) { default: + break; + case DT_NULL: + if (relativecount > 0 && dyncon + 1 < dynconend) + { + switch (elf_section_data (reldyn)->this_hdr.sh_type) + { + case SHT_REL: dyn.d_tag = DT_RELCOUNT; break; + case SHT_RELA: dyn.d_tag = DT_RELACOUNT; break; + default: break; + } + if (dyn.d_tag != DT_NULL) + { + dyn.d_un.d_val = relativecount; + elf_swap_dyn_out (dynobj, &dyn, dyncon); + relativecount = 0; + } + } break; case DT_INIT: name = info->init_function; --- include/bfdlink.h.jj Mon Aug 13 13:05:43 2001 +++ include/bfdlink.h Wed Aug 15 17:16:55 2001 @@ -278,6 +278,13 @@ struct bfd_link_info /* true if auto-import thunks for DATA items in pei386 DLLs should be generated/linked against. */ boolean pei386_auto_import; + + /* true if non-PLT relocs should be merged into one reloc section + and sorted so that relocs against the same symbol come together. */ + boolean combreloc; + + /* How many spare .dynamic DT_NULL entries should be added? */ + int spare_dynamic_tags; }; /* This structures holds a set of callback functions. These are --- ld/emultempl/elf32.em.jj Wed Aug 15 17:16:15 2001 +++ ld/emultempl/elf32.em Wed Aug 15 17:17:30 2001 @@ -1135,7 +1135,25 @@ gld${EMULATION_NAME}_place_orphan (file, 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.relocateabl 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 < 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= + 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,16 @@ if test -n "$GENERATE_SHLIB_SCRIPT"; the # 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 + 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 --- ld/ldmain.c.jj Mon Aug 13 13:10:57 2001 +++ ld/ldmain.c Wed Aug 15 17:16:55 2001 @@ -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 (""); --- ld/lexsup.c.jj Mon Aug 13 13:05:50 2001 +++ ld/lexsup.c Wed Aug 15 17:16:55 2001 @@ -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}, @@ -1072,6 +1075,9 @@ the GNU General Public License. This pr 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) Jakub