From 986a241f8b043a790a63bc4e96bb731973a61ff4 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 18 Jul 2003 21:09:28 +0000 Subject: [PATCH] * elflink.c (_bfd_elf_dynamic_symbol_p): New. * elf-bfd.h (_bfd_elf_dynamic_symbol_p): Declare it. (SYMBOL_REFERENCES_LOCAL, SYMBOL_CALLS_LOCAL): Use it. * elf32-xtensa.c (xtensa_elf_dynamic_symbol_p): Likewise. * elf64-alpha.c (alpha_elf_dynamic_symbol_p): Likewise. * elf64-hppa.c (elf64_hppa_dynamic_symbol_p): Likewise. * elfxx-ia64.c (elfNN_ia64_dynamic_symbol_p): Likewise. Update all callers to provide the relocation being resolved. --- bfd/ChangeLog | 11 ++++++++ bfd/elf-bfd.h | 22 +++++---------- bfd/elf32-xtensa.c | 35 +++--------------------- bfd/elf64-alpha.c | 46 +++++-------------------------- bfd/elf64-hppa.c | 33 ++++++++--------------- bfd/elflink.c | 60 +++++++++++++++++++++++++++++++++++++++++ bfd/elfxx-ia64.c | 67 +++++++++++++++------------------------------- 7 files changed, 120 insertions(+), 154 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index f53db4d586a..adb20cfa582 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,14 @@ +2003-07-18 Richard Henderson + + * elflink.c (_bfd_elf_dynamic_symbol_p): New. + * elf-bfd.h (_bfd_elf_dynamic_symbol_p): Declare it. + (SYMBOL_REFERENCES_LOCAL, SYMBOL_CALLS_LOCAL): Use it. + * elf32-xtensa.c (xtensa_elf_dynamic_symbol_p): Likewise. + * elf64-alpha.c (alpha_elf_dynamic_symbol_p): Likewise. + * elf64-hppa.c (elf64_hppa_dynamic_symbol_p): Likewise. + * elfxx-ia64.c (elfNN_ia64_dynamic_symbol_p): Likewise. + Update all callers to provide the relocation being resolved. + 2003-07-17 Shaun Jackman * config.bfd (arm-wince-pe): Add -DARM_COFF_BUGFIX to diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index b118524a834..7d154fc735c 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -211,23 +211,12 @@ struct elf_link_hash_entry function symbols not defined in an app are set to their .plt entry, it's necessary for shared libs to also reference the .plt even though the symbol is really local to the shared lib. */ -#define SYMBOL_REFERENCES_LOCAL(INFO, H) \ - (((INFO)->executable \ - || (INFO)->symbolic \ - || (H)->dynindx == -1 \ - || ELF_ST_VISIBILITY ((H)->other) == STV_INTERNAL \ - || ELF_ST_VISIBILITY ((H)->other) == STV_HIDDEN \ - || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0) \ - && ((H)->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0) +#define SYMBOL_REFERENCES_LOCAL(INFO, H) \ + _bfd_elf_dynamic_symbol_p (H, INFO, 1) /* Will _calls_ to this symbol always call the version in this object? */ -#define SYMBOL_CALLS_LOCAL(INFO, H) \ - (((INFO)->executable \ - || (INFO)->symbolic \ - || (H)->dynindx == -1 \ - || ELF_ST_VISIBILITY ((H)->other) != STV_DEFAULT \ - || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0) \ - && ((H)->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0) +#define SYMBOL_CALLS_LOCAL(INFO, H) \ + _bfd_elf_dynamic_symbol_p (H, INFO, 0) /* Records local symbols to be emitted in the dynamic symbol table. */ @@ -1506,6 +1495,9 @@ extern bfd_boolean _bfd_elf_adjust_dynamic_symbol extern bfd_boolean _bfd_elf_link_sec_merge_syms PARAMS ((struct elf_link_hash_entry *, PTR)); +extern bfd_boolean _bfd_elf_dynamic_symbol_p + PARAMS ((struct elf_link_hash_entry *, struct bfd_link_info *, bfd_boolean)); + extern const bfd_target *bfd_elf32_object_p PARAMS ((bfd *)); extern const bfd_target *bfd_elf32_core_file_p diff --git a/bfd/elf32-xtensa.c b/bfd/elf32-xtensa.c index f68f342bf4f..867832f0860 100644 --- a/bfd/elf32-xtensa.c +++ b/bfd/elf32-xtensa.c @@ -1838,38 +1838,9 @@ xtensa_elf_dynamic_symbol_p (info, h) struct bfd_link_info *info; struct elf_link_hash_entry *h; { - if (h == NULL) - 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; - - if (h->dynindx == -1) - return FALSE; - - if (h->root.type == bfd_link_hash_undefweak - || h->root.type == bfd_link_hash_defweak) - return TRUE; - - switch (ELF_ST_VISIBILITY (h->other)) - { - case STV_DEFAULT: - break; - case STV_HIDDEN: - case STV_INTERNAL: - return FALSE; - case STV_PROTECTED: - if (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) - return FALSE; - break; - } - - if ((info->shared && !info->symbolic) - || (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) - return TRUE; - - return FALSE; + /* ??? What, if anything, needs to happen wrt STV_PROTECTED and PLT + entries? For now assume the worst. */ + return _bfd_elf_dynamic_symbol_p (h, info, 1); } diff --git a/bfd/elf64-alpha.c b/bfd/elf64-alpha.c index ca3aa194bf7..625b24398a6 100644 --- a/bfd/elf64-alpha.c +++ b/bfd/elf64-alpha.c @@ -47,7 +47,7 @@ #define ECOFF_64 #include "ecoffswap.h" -static int alpha_elf_dynamic_symbol_p +static bfd_boolean alpha_elf_dynamic_symbol_p PARAMS ((struct elf_link_hash_entry *, struct bfd_link_info *)); static struct bfd_hash_entry * elf64_alpha_link_hash_newfunc PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *)); @@ -269,49 +269,17 @@ struct alpha_elf_link_hash_table #define alpha_elf_sym_hashes(abfd) \ ((struct alpha_elf_link_hash_entry **)elf_sym_hashes(abfd)) -/* Should we do dynamic things to this symbol? */ +/* Should we do dynamic things to this symbol? This differs from the + generic version in that we never need to consider function pointer + equality wrt PLT entries -- we don't create a PLT entry if a symbol's + address is ever taken. */ -static int +static inline bfd_boolean alpha_elf_dynamic_symbol_p (h, info) struct elf_link_hash_entry *h; struct bfd_link_info *info; { - if (h == NULL) - 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; - - if (h->dynindx == -1) - return FALSE; - - if (h->root.type == bfd_link_hash_undefweak - || h->root.type == bfd_link_hash_defweak) - return TRUE; - - switch (ELF_ST_VISIBILITY (h->other)) - { - case STV_DEFAULT: - break; - case STV_HIDDEN: - case STV_INTERNAL: - return FALSE; - case STV_PROTECTED: - if (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) - return FALSE; - break; - } - - if ((info->shared && !info->symbolic) - || ((h->elf_link_hash_flags - & (ELF_LINK_HASH_DEF_DYNAMIC - | ELF_LINK_HASH_DEF_REGULAR - | ELF_LINK_HASH_REF_REGULAR)) - == (ELF_LINK_HASH_DEF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR))) - return TRUE; - - return FALSE; + return _bfd_elf_dynamic_symbol_p (h, info, 0); } /* Create an entry in a Alpha ELF linker hash table. */ diff --git a/bfd/elf64-hppa.c b/bfd/elf64-hppa.c index 4c88a543a37..2cee551d6b6 100644 --- a/bfd/elf64-hppa.c +++ b/bfd/elf64-hppa.c @@ -956,30 +956,19 @@ elf64_hppa_dynamic_symbol_p (h, info) struct elf_link_hash_entry *h; struct bfd_link_info *info; { - if (h == NULL) - 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; - - if (h->dynindx == -1) - return FALSE; - - if (h->root.type == bfd_link_hash_undefweak - || h->root.type == bfd_link_hash_defweak) - return TRUE; + /* ??? What, if anything, needs to happen wrt STV_PROTECTED symbols + and relocations that retrieve a function descriptor? Assume the + worst for now. */ + if (_bfd_elf_dynamic_symbol_p (h, info, 1)) + { + /* ??? Why is this here and not elsewhere is_local_label_name. */ + if (h->root.root.string[0] == '$' && h->root.root.string[1] == '$') + return FALSE; - if (h->root.root.string[0] == '$' && h->root.root.string[1] == '$') + return TRUE; + } + else return FALSE; - - if ((info->shared && (!info->symbolic || info->allow_shlib_undefined)) - || ((h->elf_link_hash_flags - & (ELF_LINK_HASH_DEF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR)) - == (ELF_LINK_HASH_DEF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR))) - return TRUE; - - return FALSE; } /* Mark all funtions exported by this file so that we can later allocate diff --git a/bfd/elflink.c b/bfd/elflink.c index b448367d24e..2fd588ae110 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -2474,3 +2474,63 @@ _bfd_elf_link_sec_merge_syms (h, data) return TRUE; } + +/* Returns false if the symbol referred to by H should be considered + to resolve local to the current module, and true if it should be + considered to bind dynamically. */ + +bfd_boolean +_bfd_elf_dynamic_symbol_p (h, info, ignore_protected) + struct elf_link_hash_entry *h; + struct bfd_link_info *info; + bfd_boolean ignore_protected; +{ + bfd_boolean binding_stays_local_p; + + if (h == NULL) + 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; + + /* If it was forced local, then clearly it's not dynamic. */ + if (h->dynindx == -1) + return FALSE; + if (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) + return FALSE; + + /* Identify the cases where name binding rules say that a + visible symbol resolves locally. */ + binding_stays_local_p = info->executable || info->symbolic; + + switch (ELF_ST_VISIBILITY (h->other)) + { + case STV_INTERNAL: + case STV_HIDDEN: + return FALSE; + + case STV_PROTECTED: + /* Proper resolution for function pointer equality may require + that these symbols perhaps be resolved dynamically, even though + we should be resolving them to the current module. */ + if (!ignore_protected) + binding_stays_local_p = TRUE; + break; + + default: + /* With STV_DEFAULT, weak symbols do not bind locally. */ + if (h->root.type == bfd_link_hash_undefweak + || h->root.type == bfd_link_hash_defweak) + return TRUE; + break; + } + + /* If it isn't defined locally, then clearly it's dynamic. */ + if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) + return TRUE; + + /* Otherwise, the symbol is dynamic if binding rules don't tell + us that it remains local. */ + return !binding_stays_local_p; +} diff --git a/bfd/elfxx-ia64.c b/bfd/elfxx-ia64.c index f98e4ee188d..a061e7d052f 100644 --- a/bfd/elfxx-ia64.c +++ b/bfd/elfxx-ia64.c @@ -200,7 +200,7 @@ static bfd_boolean elfNN_ia64_modify_segment_map static bfd_boolean elfNN_ia64_is_local_label_name PARAMS ((bfd *abfd, const char *name)); static bfd_boolean elfNN_ia64_dynamic_symbol_p - PARAMS ((struct elf_link_hash_entry *h, struct bfd_link_info *info)); + PARAMS ((struct elf_link_hash_entry *h, struct bfd_link_info *info, int)); static bfd_boolean elfNN_ia64_local_hash_table_init PARAMS ((struct elfNN_ia64_local_hash_table *ht, bfd *abfd, new_hash_entry_func new)); @@ -831,7 +831,7 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again) } /* Can't do anything else with dynamic symbols. */ - else if (elfNN_ia64_dynamic_symbol_p (h, link_info)) + else if (elfNN_ia64_dynamic_symbol_p (h, link_info, r_type)) continue; else @@ -1508,38 +1508,16 @@ elfNN_ia64_is_local_label_name (abfd, name) /* Should we do dynamic things to this symbol? */ static bfd_boolean -elfNN_ia64_dynamic_symbol_p (h, info) +elfNN_ia64_dynamic_symbol_p (h, info, r_type) struct elf_link_hash_entry *h; struct bfd_link_info *info; + int r_type; { - if (h == NULL) - 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; + bfd_boolean ignore_protected + = ((r_type & 0xf8) == 0x40 /* FPTR relocs */ + || (r_type & 0xf8) == 0x50); /* LTOFF_FPTR relocs */ - if (h->dynindx == -1) - return FALSE; - switch (ELF_ST_VISIBILITY (h->other)) - { - case STV_INTERNAL: - case STV_HIDDEN: - return FALSE; - default: - break; - } - - if (h->root.type == bfd_link_hash_undefweak - || h->root.type == bfd_link_hash_defweak) - return TRUE; - - /* If it isn't defined locally, then clearly it's dynamic. */ - if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) - return TRUE; - - /* Identify the cases where name binding rules say it resolves local. */ - return !(info->executable || info->symbolic); + return _bfd_elf_dynamic_symbol_p (h, info, ignore_protected); } static bfd_boolean @@ -2415,7 +2393,7 @@ allocate_global_data_got (dyn_i, data) if ((dyn_i->want_got || dyn_i->want_gotx) && ! dyn_i->want_fptr - && elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info)) + && elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info, 0)) { dyn_i->got_offset = x->ofs; x->ofs += 8; @@ -2427,7 +2405,7 @@ allocate_global_data_got (dyn_i, data) } if (dyn_i->want_dtpmod) { - if (elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info)) + if (elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info, 0)) { dyn_i->dtpmod_offset = x->ofs; x->ofs += 8; @@ -2464,7 +2442,7 @@ allocate_global_fptr_got (dyn_i, data) if (dyn_i->want_got && dyn_i->want_fptr - && elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info)) + && elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info, R_IA64_FPTR64LSB)) { dyn_i->got_offset = x->ofs; x->ofs += 8; @@ -2482,7 +2460,7 @@ allocate_local_got (dyn_i, data) struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data; if ((dyn_i->want_got || dyn_i->want_gotx) - && !elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info)) + && !elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info, 0)) { dyn_i->got_offset = x->ofs; x->ofs += 8; @@ -2576,7 +2554,7 @@ allocate_plt_entries (dyn_i, data) h = (struct elf_link_hash_entry *) h->root.u.i.link; /* ??? Versioned symbols seem to lose ELF_LINK_HASH_NEEDS_PLT. */ - if (elfNN_ia64_dynamic_symbol_p (h, x->info)) + if (elfNN_ia64_dynamic_symbol_p (h, x->info, 0)) { bfd_size_type offset = x->ofs; if (offset == 0) @@ -2654,7 +2632,10 @@ allocate_dynrel_entries (dyn_i, data) bfd_boolean dynamic_symbol, shared, resolved_zero; ia64_info = elfNN_ia64_hash_table (x->info); - dynamic_symbol = elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info); + + /* Note that this can't be used in relation to FPTR relocs below. */ + dynamic_symbol = elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info, 0); + shared = x->info->shared; resolved_zero = (dyn_i->h && ELF_ST_VISIBILITY (dyn_i->h->other) @@ -3342,7 +3323,7 @@ set_got_entry (abfd, info, dyn_i, dynindx, addend, value, dyn_r_type) || ELF_ST_VISIBILITY (dyn_i->h->other) == STV_DEFAULT || dyn_i->h->root.type != bfd_link_hash_undefweak) && dyn_r_type != R_IA64_DTPREL64LSB) - || elfNN_ia64_dynamic_symbol_p (dyn_i->h, info) + || elfNN_ia64_dynamic_symbol_p (dyn_i->h, info, dyn_r_type) || (dynindx != -1 && dyn_r_type == R_IA64_FPTR64LSB)) && (!dyn_i->want_ltoff_fptr || !info->pie @@ -3807,7 +3788,6 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, asection *sym_sec; bfd_byte *hit_addr; bfd_boolean dynamic_symbol_p; - bfd_boolean local_symbol_p; bfd_boolean undef_weak_ref; r_type = ELFNN_R_TYPE (rel->r_info); @@ -3918,12 +3898,7 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, hit_addr = contents + rel->r_offset; value += rel->r_addend; - dynamic_symbol_p = elfNN_ia64_dynamic_symbol_p (h, info); - /* Is this symbol locally defined? A protected symbol is locallly - defined. But its function descriptor may not. Use it with - caution. */ - local_symbol_p = (! dynamic_symbol_p - || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT); + dynamic_symbol_p = elfNN_ia64_dynamic_symbol_p (h, info, r_type); switch (r_type) { @@ -3952,7 +3927,7 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, /* If we don't need dynamic symbol lookup, find a matching RELATIVE relocation. */ dyn_r_type = r_type; - if (! local_symbol_p) + if (dynamic_symbol_p) { dynindx = h->dynindx; addend = rel->r_addend; @@ -4300,7 +4275,7 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, /* If we don't need dynamic symbol lookup, install two RELATIVE relocations. */ - if (local_symbol_p) + if (!dynamic_symbol_p) { unsigned int dyn_r_type; -- 2.30.2