From 0f02bbd9f8fdee22cc91b4bef3f310d4dbc1eee5 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Sun, 30 Sep 2007 13:33:04 +0000 Subject: [PATCH] bfd/ * elflink.c (resolve_symbol): Handle symbols in SEC_MERGE sections. Don't test symbol st_shndx. Don't bother with bfd_link_hash_common symbols. Print longs rather than ints in debug messages. (eval_symbol): Replace "sym" and "advanced" params with "symp". Replace "addr" and "section_offset" params with "dot". Don't cast bfd_vma values to signed, cast them to bfd_signed_vma. (bfd_elf_perform_complex_relocation): Delete "output_bfd", "info", "local_syms" and "local_sections" params. Add "relocation". Delete code calculating relocation value. (evaluate_complex_relocation_symbols): Delete function. Fold into.. (elf_link_input_bfd): ..existing code examining relocs. * elf-bfd.h (bfd_elf_perform_complex_relocation): Update prototype. * elf32-mep.c (mep_elf_check_relocs): Delete function. (mep_elf_gc_sweep_hook, mep_elf_gc_mark_hook): Likewise. (mep_elf_object_p): Don't set elf_bad_symtab. (elf_backend_check_relocs): Don't define. (elf_backend_gc_mark_hook, elf_backend_gc_sweep_hook): Likewise. (elf_backend_can_gc_sections, USE_RELA): Likwise. (mep_elf_relocate_section): Move bfd_elf_perform_complex_relocation call after we have calculated reloc value. Delete local sym debug code. Use RELOC_FOR_GLOBAL_SYMBOL. Delete addend adjusting code.. (elf_backend_rela_normal): ..instead define this. ld/testsuite/ * ld-selective/sel-dump.exp: Add am33, m88k, mep to xfails. * ld-selective/selective.exp: Don't run for same target list we xfail sel-dump. --- bfd/ChangeLog | 27 ++ bfd/elf-bfd.h | 9 +- bfd/elf32-mep.c | 189 +--------- bfd/elflink.c | 448 +++++++----------------- ld/testsuite/ChangeLog | 6 + ld/testsuite/ld-selective/sel-dump.exp | 6 +- ld/testsuite/ld-selective/selective.exp | 11 +- 7 files changed, 185 insertions(+), 511 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 3d0777fd853..95a31dfea50 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,30 @@ +2007-09-29 Alan Modra + + * elflink.c (resolve_symbol): Handle symbols in SEC_MERGE + sections. Don't test symbol st_shndx. Don't bother with + bfd_link_hash_common symbols. Print longs rather than ints + in debug messages. + (eval_symbol): Replace "sym" and "advanced" params with "symp". + Replace "addr" and "section_offset" params with "dot". Don't + cast bfd_vma values to signed, cast them to bfd_signed_vma. + (bfd_elf_perform_complex_relocation): Delete "output_bfd", "info", + "local_syms" and "local_sections" params. Add "relocation". + Delete code calculating relocation value. + (evaluate_complex_relocation_symbols): Delete function. Fold into.. + (elf_link_input_bfd): ..existing code examining relocs. + * elf-bfd.h (bfd_elf_perform_complex_relocation): Update prototype. + * elf32-mep.c (mep_elf_check_relocs): Delete function. + (mep_elf_gc_sweep_hook, mep_elf_gc_mark_hook): Likewise. + (mep_elf_object_p): Don't set elf_bad_symtab. + (elf_backend_check_relocs): Don't define. + (elf_backend_gc_mark_hook, elf_backend_gc_sweep_hook): Likewise. + (elf_backend_can_gc_sections, USE_RELA): Likwise. + (mep_elf_relocate_section): Move bfd_elf_perform_complex_relocation + call after we have calculated reloc value. Delete local sym + debug code. Use RELOC_FOR_GLOBAL_SYMBOL. Delete addend + adjusting code.. + (elf_backend_rela_normal): ..instead define this. + 2007-09-28 Alan Modra * elf-m10300.c (mn10300_elf_check_relocs): Delete dead code. diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index d8d81dfbfb2..a707cef0cd2 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -1814,14 +1814,7 @@ extern bfd_boolean bfd_elf_match_symbols_in_sections (asection *, asection *, struct bfd_link_info *); extern void bfd_elf_perform_complex_relocation - (bfd * output_bfd ATTRIBUTE_UNUSED, - struct bfd_link_info * info, - bfd * input_bfd, - asection * input_section, - bfd_byte * contents, - Elf_Internal_Rela * rel, - Elf_Internal_Sym * local_syms, - asection ** local_sections); + (bfd *, asection *, bfd_byte *, Elf_Internal_Rela *, bfd_vma); extern bfd_boolean _bfd_elf_setup_sections (bfd *); diff --git a/bfd/elf32-mep.c b/bfd/elf32-mep.c index d1ee6a96952..e5d33caa5cd 100644 --- a/bfd/elf32-mep.c +++ b/bfd/elf32-mep.c @@ -402,48 +402,6 @@ mep_info_to_howto_rela r_type = ELF32_R_TYPE (dst->r_info); cache_ptr->howto = & mep_elf_howto_table [r_type]; } - -/* Look through the relocs for a section during the first phase. - Since we don't do .gots or .plts, we just need to consider the - virtual table relocs for gc. */ - -static bfd_boolean -mep_elf_check_relocs - (bfd * abfd, - struct bfd_link_info * info, - asection * sec, - const Elf_Internal_Rela * relocs) -{ - Elf_Internal_Shdr * symtab_hdr; - struct elf_link_hash_entry ** sym_hashes; - struct elf_link_hash_entry ** sym_hashes_end; - const Elf_Internal_Rela * rel; - const Elf_Internal_Rela * rel_end; - - if (info->relocatable) - return TRUE; - - symtab_hdr = &elf_tdata (abfd)->symtab_hdr; - sym_hashes = elf_sym_hashes (abfd); - sym_hashes_end = sym_hashes + symtab_hdr->sh_size / sizeof (Elf32_External_Sym); - if (!elf_bad_symtab (abfd)) - sym_hashes_end -= symtab_hdr->sh_info; - - rel_end = relocs + sec->reloc_count; - for (rel = relocs; rel < rel_end; rel++) - { - struct elf_link_hash_entry *h; - unsigned long r_symndx; - - r_symndx = ELF32_R_SYM (rel->r_info); - if (r_symndx < symtab_hdr->sh_info) - h = NULL; - else - h = sym_hashes[r_symndx - symtab_hdr->sh_info]; - } - return TRUE; -} - /* Relocate a MEP ELF section. There is some attempt to make this function usable for many architectures, @@ -513,18 +471,7 @@ mep_elf_relocate_section int r_type; r_type = ELF32_R_TYPE (rel->r_info); - r_symndx = ELF32_R_SYM (rel->r_info); - - /* Is this a complex relocation? */ - if (!info->relocatable && ELF32_R_TYPE (rel->r_info) == R_RELC) - { - bfd_elf_perform_complex_relocation (output_bfd, info, - input_bfd, input_section, contents, - rel, local_syms, local_sections); - continue; - } - howto = mep_elf_howto_table + ELF32_R_TYPE (rel->r_info); h = NULL; sym = NULL; @@ -539,56 +486,17 @@ mep_elf_relocate_section name = bfd_elf_string_from_elf_section (input_bfd, symtab_hdr->sh_link, sym->st_name); name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name; -#if 0 - fprintf (stderr, "local: sec: %s, sym: %s (%d), value: %x + %x + %x addend %x\n", - sec->name, name, sym->st_name, - sec->output_section->vma, sec->output_offset, - sym->st_value, rel->r_addend); -#endif } else { - relocation = 0; - h = sym_hashes [r_symndx]; + bfd_boolean warned, unresolved_reloc; - while (h->root.type == bfd_link_hash_indirect - || h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; + RELOC_FOR_GLOBAL_SYMBOL(info, input_bfd, input_section, rel, + r_symndx, symtab_hdr, sym_hashes, + h, sec, relocation, + unresolved_reloc, warned); name = h->root.root.string; - - if (h->root.type == bfd_link_hash_defined - || h->root.type == bfd_link_hash_defweak) - { - sec = h->root.u.def.section; - relocation = (h->root.u.def.value - + sec->output_section->vma - + sec->output_offset); -#if 0 - fprintf (stderr, - "defined: sec: %s, name: %s, value: %x + %x + %x gives: %x\n", - sec->name, name, h->root.u.def.value, - sec->output_section->vma, sec->output_offset, relocation); -#endif - } - else if (h->root.type == bfd_link_hash_undefweak) - { -#if 0 - fprintf (stderr, "undefined: sec: %s, name: %s\n", - sec->name, name); -#endif - } - else if (!info->relocatable) - { - if (! ((*info->callbacks->undefined_symbol) - (info, h->root.root.string, input_bfd, - input_section, rel->r_offset, - (!info->shared && info->unresolved_syms_in_objects == RM_GENERATE_ERROR)))) - return FALSE; -#if 0 - fprintf (stderr, "unknown: name: %s\n", name); -#endif - } } if (sec != NULL && elf_discarded_section (sec)) @@ -603,18 +511,15 @@ mep_elf_relocate_section } if (info->relocatable) - { - /* This is a relocatable link. We don't have to change - anything, unless the reloc is against a section symbol, - in which case we have to adjust according to where the - section symbol winds up in the output section. */ - if (sym != NULL && ELF_ST_TYPE (sym->st_info) == STT_SECTION) - rel->r_addend += sec->output_offset; - continue; - } + continue; switch (r_type) { + case R_RELC: + bfd_elf_perform_complex_relocation (input_bfd, input_section, + contents, rel, relocation); + continue; + default: r = mep_final_link_relocate (howto, input_bfd, input_section, contents, rel, relocation); @@ -675,63 +580,6 @@ mep_elf_relocate_section return TRUE; } - - -/* Update the got entry reference counts for the section being - removed. */ - -static bfd_boolean -mep_elf_gc_sweep_hook - (bfd * abfd ATTRIBUTE_UNUSED, - struct bfd_link_info * info ATTRIBUTE_UNUSED, - asection * sec ATTRIBUTE_UNUSED, - const Elf_Internal_Rela * relocs ATTRIBUTE_UNUSED) -{ - return TRUE; -} - -/* Return the section that should be marked against GC for a given - relocation. */ - -static asection * -mep_elf_gc_mark_hook - (asection * sec, - struct bfd_link_info * info ATTRIBUTE_UNUSED, - Elf_Internal_Rela * rel, - struct elf_link_hash_entry * h, - Elf_Internal_Sym * sym) -{ - if (h != NULL) - { - switch (ELF32_R_TYPE (rel->r_info)) - { - default: - switch (h->root.type) - { - case bfd_link_hash_defined: - case bfd_link_hash_defweak: - return h->root.u.def.section; - - case bfd_link_hash_common: - return h->root.u.c.p->section; - - default: - break; - } - } - } - else - { - if (!(elf_bad_symtab (sec->owner) - && ELF_ST_BIND (sym->st_info) != STB_LOCAL) - && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE) - && sym->st_shndx != SHN_COMMON)) - return bfd_section_from_elf_index (sec->owner, sym->st_shndx); - } - - return NULL; -} - /* Function to set the ELF flag bits. */ @@ -899,11 +747,6 @@ elf32_mep_machine (bfd * abfd) static bfd_boolean mep_elf_object_p (bfd * abfd) { - /* Irix 5 and 6 is broken. Object file symbol tables are not always - sorted correctly such that local symbols preceed global symbols, - and the sh_info field in the symbol table is not always right. */ - /* This is needed for the RELC support code. */ - elf_bad_symtab (abfd) = TRUE; bfd_default_set_arch_mach (abfd, bfd_arch_mep, elf32_mep_machine (abfd)); return TRUE; } @@ -940,23 +783,17 @@ mep_elf_fake_sections (bfd * abfd ATTRIBUTE_UNUSED, #define elf_info_to_howto_rel NULL #define elf_info_to_howto mep_info_to_howto_rela #define elf_backend_relocate_section mep_elf_relocate_section -#define elf_backend_gc_mark_hook mep_elf_gc_mark_hook -#define elf_backend_gc_sweep_hook mep_elf_gc_sweep_hook -#define elf_backend_check_relocs mep_elf_check_relocs #define elf_backend_object_p mep_elf_object_p #define elf_backend_section_flags mep_elf_section_flags #define elf_backend_fake_sections mep_elf_fake_sections -#define elf_backend_can_gc_sections 1 - #define bfd_elf32_bfd_reloc_type_lookup mep_reloc_type_lookup -#define bfd_elf32_bfd_reloc_name_lookup mep_reloc_name_lookup +#define bfd_elf32_bfd_reloc_name_lookup mep_reloc_name_lookup #define bfd_elf32_bfd_set_private_flags mep_elf_set_private_flags #define bfd_elf32_bfd_copy_private_bfd_data mep_elf_copy_private_bfd_data #define bfd_elf32_bfd_merge_private_bfd_data mep_elf_merge_private_bfd_data #define bfd_elf32_bfd_print_private_bfd_data mep_elf_print_private_bfd_data -/* We use only the RELA entries. */ -#define USE_RELA +#define elf_backend_rela_normal 1 #include "elf32-target.h" diff --git a/bfd/elflink.c b/bfd/elflink.c index ce59c3abf18..cac22b7c720 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -7281,7 +7281,6 @@ resolve_symbol (const char * name, struct bfd_link_hash_entry * global_entry; const char * candidate = NULL; Elf_Internal_Shdr * symtab_hdr; - asection * sec = NULL; size_t i; symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr; @@ -7289,7 +7288,6 @@ resolve_symbol (const char * name, for (i = 0; i < locsymcount; ++ i) { sym = isymbuf + i; - sec = finfo->sections [i]; if (ELF_ST_BIND (sym->st_info) != STB_LOCAL) continue; @@ -7298,26 +7296,18 @@ resolve_symbol (const char * name, symtab_hdr->sh_link, sym->st_name); #ifdef DEBUG - printf ("Comparing string: '%s' vs. '%s' = 0x%x\n", - name, candidate, (unsigned int)sym->st_value); + printf ("Comparing string: '%s' vs. '%s' = 0x%lx\n", + name, candidate, (unsigned long) sym->st_value); #endif if (candidate && strcmp (candidate, name) == 0) { - * result = sym->st_value; + asection *sec = finfo->sections [i]; - if (sym->st_shndx > SHN_UNDEF && - sym->st_shndx < SHN_LORESERVE) - { -#ifdef DEBUG - printf ("adjusting for sec '%s' @ 0x%x + 0x%x\n", - sec->output_section->name, - (unsigned int)sec->output_section->vma, - (unsigned int)sec->output_offset); -#endif - * result += sec->output_offset + sec->output_section->vma; - } + *result = _bfd_elf_rel_local_sym (input_bfd, sym, &sec, 0); + *result += sec->output_offset + sec->output_section->vma; #ifdef DEBUG - printf ("Found symbol with effective value %8.8x\n", (unsigned int)* result); + printf ("Found symbol with value %8.8lx\n", + (unsigned long) *result); #endif return TRUE; } @@ -7335,24 +7325,12 @@ resolve_symbol (const char * name, + global_entry->u.def.section->output_section->vma + global_entry->u.def.section->output_offset; #ifdef DEBUG - printf ("Found GLOBAL symbol '%s' with value %8.8x\n", - global_entry->root.string, (unsigned int)*result); + printf ("Found GLOBAL symbol '%s' with value %8.8lx\n", + global_entry->root.string, (unsigned long) *result); #endif return TRUE; } - if (global_entry->type == bfd_link_hash_common) - { - *result = global_entry->u.def.value + - bfd_com_section_ptr->output_section->vma + - bfd_com_section_ptr->output_offset; -#ifdef DEBUG - printf ("Found COMMON symbol '%s' with value %8.8x\n", - global_entry->root.string, (unsigned int)*result); -#endif - return TRUE; - } - return FALSE; } @@ -7402,12 +7380,10 @@ undefined_reference (const char * reftype, static bfd_boolean eval_symbol (bfd_vma * result, - char * sym, - char ** advanced, + const char ** symp, bfd * input_bfd, struct elf_final_link_info * finfo, - bfd_vma addr, - bfd_vma section_offset, + bfd_vma dot, Elf_Internal_Sym * isymbuf, size_t locsymcount, int signed_p) @@ -7418,6 +7394,7 @@ eval_symbol (bfd_vma * result, bfd_vma b; const int bufsz = 4096; char symbuf [bufsz]; + const char *sym = *symp; const char * symend; bfd_boolean symbol_is_section = FALSE; @@ -7433,21 +7410,21 @@ eval_symbol (bfd_vma * result, switch (* sym) { case '.': - * result = addr + section_offset; - * advanced = sym + 1; + *result = dot; + *symp = sym + 1; return TRUE; case '#': - ++ sym; - * result = strtoul (sym, advanced, 16); + ++sym; + *result = strtoul (sym, (char **) symp, 16); return TRUE; case 'S': symbol_is_section = TRUE; case 's': - ++ sym; - symlen = strtol (sym, &sym, 10); - ++ sym; /* Skip the trailing ':'. */ + ++sym; + symlen = strtol (sym, (char **) symp, 10); + sym = *symp + 1; /* Skip the trailing ':'. */ if ((symend < sym) || ((symlen + 1) > bufsz)) { @@ -7457,7 +7434,7 @@ eval_symbol (bfd_vma * result, memcpy (symbuf, sym, symlen); symbuf [symlen] = '\0'; - * advanced = sym + symlen; + *symp = sym + symlen; /* Is it always possible, with complex symbols, that gas "mis-guessed" the symbol as a section, or vice-versa. so we're pretty liberal in our @@ -7496,15 +7473,14 @@ eval_symbol (bfd_vma * result, sym += strlen (#op); \ if (* sym == ':') \ ++ sym; \ - if (!eval_symbol (&a, sym, &sym, input_bfd, finfo, addr, \ - section_offset, isymbuf, locsymcount, \ - signed_p)) \ + *symp = sym; \ + if (!eval_symbol (&a, symp, input_bfd, finfo, dot, \ + isymbuf, locsymcount, signed_p)) \ return FALSE; \ if (signed_p) \ - * result = op ((signed)a); \ + *result = op ((bfd_signed_vma) a); \ else \ * result = op a; \ - * advanced = sym; \ return TRUE; \ } @@ -7514,20 +7490,18 @@ eval_symbol (bfd_vma * result, sym += strlen (#op); \ if (* sym == ':') \ ++ sym; \ - if (!eval_symbol (&a, sym, &sym, input_bfd, finfo, addr, \ - section_offset, isymbuf, locsymcount, \ - signed_p)) \ + *symp = sym; \ + if (!eval_symbol (&a, symp, input_bfd, finfo, dot, \ + isymbuf, locsymcount, signed_p)) \ return FALSE; \ - ++ sym; \ - if (!eval_symbol (&b, sym, &sym, input_bfd, finfo, addr, \ - section_offset, isymbuf, locsymcount, \ - signed_p)) \ + ++*symp; \ + if (!eval_symbol (&b, symp, input_bfd, finfo, dot, \ + isymbuf, locsymcount, signed_p)) \ return FALSE; \ if (signed_p) \ - * result = ((signed) a) op ((signed) b); \ + *result = ((bfd_signed_vma) a) op ((bfd_signed_vma) b); \ else \ * result = a op b; \ - * advanced = sym; \ return TRUE; \ } @@ -7561,141 +7535,6 @@ eval_symbol (bfd_vma * result, } } -/* Entry point to evaluator, called from elf_link_input_bfd. */ - -static bfd_boolean -evaluate_complex_relocation_symbols (bfd *input_bfd, - struct elf_final_link_info *finfo, - Elf_Internal_Sym *isymbuf, - size_t locsymcount) -{ - const struct elf_backend_data * bed; - Elf_Internal_Shdr * symtab_hdr; - struct elf_link_hash_entry ** sym_hashes; - asection * reloc_sec; - bfd_boolean result = TRUE; - - /* For each section, we're going to check and see if it has any - complex relocations, and we're going to evaluate any of them - we can. */ - - if (finfo->info->relocatable) - return TRUE; - - symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr; - sym_hashes = elf_sym_hashes (input_bfd); - bed = get_elf_backend_data (input_bfd); - - for (reloc_sec = input_bfd->sections; reloc_sec; reloc_sec = reloc_sec->next) - { - Elf_Internal_Rela * internal_relocs; - unsigned long i; - - /* This section was omitted from the link. */ - if (! reloc_sec->linker_mark) - continue; - - /* Only process sections containing relocs. */ - if ((reloc_sec->flags & SEC_RELOC) == 0) - continue; - - if (reloc_sec->reloc_count == 0) - continue; - - /* Read in the relocs for this section. */ - internal_relocs - = _bfd_elf_link_read_relocs (input_bfd, reloc_sec, NULL, - (Elf_Internal_Rela *) NULL, - FALSE); - if (internal_relocs == NULL) - continue; - - for (i = reloc_sec->reloc_count; i--;) - { - Elf_Internal_Rela * rel; - char * sym_name; - bfd_vma index; - Elf_Internal_Sym * sym; - bfd_vma result; - bfd_vma section_offset; - bfd_vma addr; - int signed_p = 0; - - rel = internal_relocs + i; - section_offset = reloc_sec->output_section->vma - + reloc_sec->output_offset; - addr = rel->r_offset; - - index = ELF32_R_SYM (rel->r_info); - if (bed->s->arch_size == 64) - index >>= 24; - - if (index == STN_UNDEF) - continue; - - if (index < locsymcount) - { - /* The symbol is local. */ - sym = isymbuf + index; - - /* We're only processing STT_RELC or STT_SRELC type symbols. */ - if ((ELF_ST_TYPE (sym->st_info) != STT_RELC) && - (ELF_ST_TYPE (sym->st_info) != STT_SRELC)) - continue; - - sym_name = bfd_elf_string_from_elf_section - (input_bfd, symtab_hdr->sh_link, sym->st_name); - - signed_p = (ELF_ST_TYPE (sym->st_info) == STT_SRELC); - } - else - { - /* The symbol is global. */ - struct elf_link_hash_entry * h; - - if (elf_bad_symtab (input_bfd)) - continue; - - h = sym_hashes [index - locsymcount]; - while ( h->root.type == bfd_link_hash_indirect - || h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; - - if (h->type != STT_RELC && h->type != STT_SRELC) - continue; - - signed_p = (h->type == STT_SRELC); - sym_name = (char *) h->root.root.string; - } -#ifdef DEBUG - printf ("Encountered a complex symbol!"); - printf (" (input_bfd %s, section %s, reloc %ld\n", - input_bfd->filename, reloc_sec->name, i); - printf (" symbol: idx %8.8lx, name %s\n", - index, sym_name); - printf (" reloc : info %8.8lx, addr %8.8lx\n", - rel->r_info, addr); - printf (" Evaluating '%s' ...\n ", sym_name); -#endif - if (eval_symbol (& result, sym_name, & sym_name, input_bfd, - finfo, addr, section_offset, isymbuf, locsymcount, - signed_p)) - /* Symbol evaluated OK. Update to absolute value. */ - set_symbol_value (input_bfd, isymbuf, locsymcount, index, result); - - else - result = FALSE; - } - - if (internal_relocs != elf_section_data (reloc_sec)->relocs) - free (internal_relocs); - } - - /* If nothing went wrong, then we adjusted - everything we wanted to adjust. */ - return result; -} - static void put_value (bfd_vma size, unsigned long chunksz, @@ -7791,84 +7630,20 @@ decode_complex_addend } void -bfd_elf_perform_complex_relocation - (bfd * output_bfd ATTRIBUTE_UNUSED, - struct bfd_link_info * info, - bfd * input_bfd, - asection * input_section, - bfd_byte * contents, - Elf_Internal_Rela * rel, - Elf_Internal_Sym * local_syms, - asection ** local_sections) -{ - const struct elf_backend_data * bed; - Elf_Internal_Shdr * symtab_hdr; - asection * sec; - bfd_vma relocation = 0, shift, x; - bfd_vma r_symndx; - bfd_vma mask; - unsigned long start, oplen, len, wordsz, - chunksz, lsb0_p, signed_p, trunc_p; +bfd_elf_perform_complex_relocation (bfd *input_bfd, + asection *input_section, + bfd_byte *contents, + Elf_Internal_Rela *rel, + bfd_vma relocation) +{ + bfd_vma shift, x, mask; + unsigned long start, oplen, len, wordsz, chunksz, lsb0_p, signed_p, trunc_p; /* Perform this reloc, since it is complex. (this is not to say that it necessarily refers to a complex symbol; merely that it is a self-describing CGEN based reloc. i.e. the addend has the complete reloc information (bit start, end, word size, etc) encoded within it.). */ - r_symndx = ELF32_R_SYM (rel->r_info); - bed = get_elf_backend_data (input_bfd); - if (bed->s->arch_size == 64) - r_symndx >>= 24; - -#ifdef DEBUG - printf ("Performing complex relocation %ld...\n", r_symndx); -#endif - - symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr; - if (r_symndx < symtab_hdr->sh_info) - { - /* The symbol is local. */ - Elf_Internal_Sym * sym; - - sym = local_syms + r_symndx; - sec = local_sections [r_symndx]; - relocation = sym->st_value; - if (sym->st_shndx > SHN_UNDEF && - sym->st_shndx < SHN_LORESERVE) - relocation += (sec->output_offset + - sec->output_section->vma); - } - else - { - /* The symbol is global. */ - struct elf_link_hash_entry **sym_hashes; - struct elf_link_hash_entry * h; - - sym_hashes = elf_sym_hashes (input_bfd); - h = sym_hashes [r_symndx]; - - while (h->root.type == bfd_link_hash_indirect - || h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; - - if (h->root.type == bfd_link_hash_defined - || h->root.type == bfd_link_hash_defweak) - { - sec = h->root.u.def.section; - relocation = h->root.u.def.value; - - if (! bfd_is_abs_section (sec)) - relocation += (sec->output_section->vma - + sec->output_offset); - } - if (h->root.type == bfd_link_hash_undefined - && !((*info->callbacks->undefined_symbol) - (info, h->root.root.string, input_bfd, - input_section, rel->r_offset, - info->unresolved_syms_in_objects == RM_GENERATE_ERROR - || ELF_ST_VISIBILITY (h->other)))) - return; - } decode_complex_addend (& start, & oplen, & len, & wordsz, & chunksz, & lsb0_p, & signed_p, @@ -9213,10 +8988,6 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) return FALSE; } - if (! evaluate_complex_relocation_symbols (input_bfd, finfo, isymbuf, - locsymcount)) - return FALSE; - /* Relocate the contents of each section. */ sym_hashes = elf_sym_hashes (input_bfd); for (o = input_bfd->sections; o != NULL; o = o->next) @@ -9258,8 +9029,10 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) if ((o->flags & SEC_RELOC) != 0) { Elf_Internal_Rela *internal_relocs; + Elf_Internal_Rela *rel, *relend; bfd_vma r_type_mask; int r_sym_shift; + int action_discarded; int ret; /* Get the swapped relocs. */ @@ -9281,76 +9054,107 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) r_sym_shift = 32; } - /* Run through the relocs looking for any against symbols - from discarded sections and section symbols from - removed link-once sections. Complain about relocs - against discarded sections. Zero relocs against removed - link-once sections. */ + action_discarded = -1; if (!elf_section_ignore_discarded_relocs (o)) + action_discarded = (*bed->action_discarded) (o); + + /* Run through the relocs evaluating complex reloc symbols and + looking for relocs against symbols from discarded sections + or section symbols from removed link-once sections. + Complain about relocs against discarded sections. Zero + relocs against removed link-once sections. */ + + rel = internal_relocs; + relend = rel + o->reloc_count * bed->s->int_rels_per_ext_rel; + for ( ; rel < relend; rel++) { - Elf_Internal_Rela *rel, *relend; - unsigned int action = (*bed->action_discarded) (o); + unsigned long r_symndx = rel->r_info >> r_sym_shift; + unsigned int s_type; + asection **ps, *sec; + struct elf_link_hash_entry *h = NULL; + const char *sym_name; - rel = internal_relocs; - relend = rel + o->reloc_count * bed->s->int_rels_per_ext_rel; - for ( ; rel < relend; rel++) - { - unsigned long r_symndx = rel->r_info >> r_sym_shift; - asection **ps, *sec; - struct elf_link_hash_entry *h = NULL; - const char *sym_name; + if (r_symndx == STN_UNDEF) + continue; - if (r_symndx == STN_UNDEF) - continue; + if (r_symndx >= locsymcount + || (elf_bad_symtab (input_bfd) + && finfo->sections[r_symndx] == NULL)) + { + h = sym_hashes[r_symndx - extsymoff]; - if (r_symndx >= locsymcount - || (elf_bad_symtab (input_bfd) - && finfo->sections[r_symndx] == NULL)) + /* Badly formatted input files can contain relocs that + reference non-existant symbols. Check here so that + we do not seg fault. */ + if (h == NULL) { - h = sym_hashes[r_symndx - extsymoff]; + char buffer [32]; - /* Badly formatted input files can contain relocs that - reference non-existant symbols. Check here so that - we do not seg fault. */ - if (h == NULL) - { - char buffer [32]; + sprintf_vma (buffer, rel->r_info); + (*_bfd_error_handler) + (_("error: %B contains a reloc (0x%s) for section %A " + "that references a non-existent global symbol"), + input_bfd, o, buffer); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } - sprintf_vma (buffer, rel->r_info); - (*_bfd_error_handler) - (_("error: %B contains a reloc (0x%s) for section %A " - "that references a non-existent global symbol"), - input_bfd, o, buffer); - bfd_set_error (bfd_error_bad_value); - return FALSE; - } + while (h->root.type == bfd_link_hash_indirect + || h->root.type == bfd_link_hash_warning) + h = (struct elf_link_hash_entry *) h->root.u.i.link; - while (h->root.type == bfd_link_hash_indirect - || h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; + s_type = h->type; - if (h->root.type != bfd_link_hash_defined - && h->root.type != bfd_link_hash_defweak) - continue; + ps = NULL; + if (h->root.type == bfd_link_hash_defined + || h->root.type == bfd_link_hash_defweak) + ps = &h->root.u.def.section; - ps = &h->root.u.def.section; - sym_name = h->root.root.string; - } - else - { - Elf_Internal_Sym *sym = isymbuf + r_symndx; - ps = &finfo->sections[r_symndx]; - sym_name = bfd_elf_sym_name (input_bfd, - symtab_hdr, - sym, *ps); - } + sym_name = h->root.root.string; + } + else + { + Elf_Internal_Sym *sym = isymbuf + r_symndx; + s_type = ELF_ST_TYPE (sym->st_info); + ps = &finfo->sections[r_symndx]; + sym_name = bfd_elf_sym_name (input_bfd, symtab_hdr, + sym, *ps); + } + + if (s_type == STT_RELC || s_type == STT_SRELC) + { + bfd_vma val; + bfd_vma dot = (rel->r_offset + + o->output_offset + o->output_section->vma); +#ifdef DEBUG + printf ("Encountered a complex symbol!"); + printf (" (input_bfd %s, section %s, reloc %ld\n", + input_bfd->filename, o->name, rel - internal_relocs); + printf (" symbol: idx %8.8lx, name %s\n", + r_symndx, sym_name); + printf (" reloc : info %8.8lx, addr %8.8lx\n", + (unsigned long) rel->r_info, + (unsigned long) rel->r_offset); +#endif + if (!eval_symbol (&val, &sym_name, input_bfd, finfo, dot, + isymbuf, locsymcount, s_type == STT_SRELC)) + return FALSE; + + /* Symbol evaluated OK. Update to absolute value. */ + set_symbol_value (input_bfd, isymbuf, locsymcount, + r_symndx, val); + continue; + } + + if (action_discarded != -1 && ps != NULL) + { /* Complain if the definition comes from a discarded section. */ if ((sec = *ps) != NULL && elf_discarded_section (sec)) { BFD_ASSERT (r_symndx != 0); - if (action & COMPLAIN) + if (action_discarded & COMPLAIN) (*finfo->info->callbacks->einfo) (_("%X`%s' referenced in section `%A' of %B: " "defined in discarded section `%A' of %B\n"), @@ -9362,7 +9166,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) FIXME: This is quite broken. Modifying the symbol here means we will be changing all later uses of the symbol, not just in this section. */ - if (action & PRETEND) + if (action_discarded & PRETEND) { asection *kept; diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index 701cac39669..cecfd3c8af6 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2007-09-29 Alan Modra + + * ld-selective/sel-dump.exp: Add am33, m88k, mep to xfails. + * ld-selective/selective.exp: Don't run for same target list + we xfail sel-dump. + 2007-09-29 Mike Frysinger * ld-alpha/tlsbin.rd: Use [0-9]+ to match section header count and diff --git a/ld/testsuite/ld-selective/sel-dump.exp b/ld/testsuite/ld-selective/sel-dump.exp index 2f6f5de1ab8..76a757725f6 100644 --- a/ld/testsuite/ld-selective/sel-dump.exp +++ b/ld/testsuite/ld-selective/sel-dump.exp @@ -28,8 +28,8 @@ set test_list [lsort [glob -nocomplain $srcdir/$subdir/*.d]] for { set i 0 } { $i < [llength $test_list] } { incr i } { # We need to strip the ".d", but can leave the dirname. verbose [file rootname [lindex $test_list $i]] - setup_xfail "alpha*-*" "arc*-*" "d30v*-*" "dlx*-*" "hppa64-*-*" - setup_xfail "i370*-*" "i860*-*" "i960*-*" "ia64*-*" "mn10200-*" - setup_xfail "or32-*" "pj-*" + setup_xfail "alpha*-*" "am33*-*" "arc*-*" "d30v*-*" "dlx*-*" + setup_xfail "hppa*64-*-*" "i370*-*" "i860*-*" "i960*-*" "ia64*-*" + setup_xfail "m88*-*" "mn10200-*" "mep-*" "or32-*" "pj-*" run_dump_test [file rootname [lindex $test_list $i]] } diff --git a/ld/testsuite/ld-selective/selective.exp b/ld/testsuite/ld-selective/selective.exp index bae43722e8a..191cd63a1f7 100644 --- a/ld/testsuite/ld-selective/selective.exp +++ b/ld/testsuite/ld-selective/selective.exp @@ -27,8 +27,15 @@ if ![is_elf_format] { return } -# Alpha and IA64 do not support selective linking -if {[istarget "alpha*-*-*"] || [istarget "ia64-*-*"]} { +# These targets do not support selective linking +if {[istarget "alpha*-*-*"] || [istarget "am33*-*-*"] || + [istarget "arc-*-*"] || [istarget "d30v-*-*"] || + [istarget "dlx-*-*"] || [istarget "hppa*64*-*-*"] || + [istarget "i370-*-*"] || [istarget "i860-*-*"] || + [istarget "i960-*-*"] || [istarget "ia64-*-*"] || + [istarget "m88*-*-*"] || [istarget "mn10200-*-*"] || + [istarget "mep-*-*"] || [istarget "or32-*-*"] || + [istarget "pj*-*-*"]} { return } -- 2.30.2