diff options
author | Alan Modra <amodra@gmail.com> | 2014-08-12 10:43:33 +0930 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2014-08-12 20:47:36 +0930 |
commit | 4613510308cea27713e8c7424b2afee9b99f6226 (patch) | |
tree | 50a2534571a7e765830e335172d4f2fdfd6ff4fc /bfd | |
parent | 88d3f0870bdcb030d1b9f56f48e389860ff41918 (diff) | |
download | gdb-4613510308cea27713e8c7424b2afee9b99f6226.zip gdb-4613510308cea27713e8c7424b2afee9b99f6226.tar.gz gdb-4613510308cea27713e8c7424b2afee9b99f6226.tar.bz2 |
Change ld "notice" interface for better handling of indirect symbols
The main aim of this change was to have non_ir_ref set correctly on
new indirect symbols. I could have added a "copy" param to the "notice"
function, so that indirect symbols could be created in plugin_notice,
but it seemed cleaner to create indirect syms earlier and pass them
rather than "string" to "notice".
include/
* bfdlink.h (struct bfd_link_callbacks <notice>): Remove "string"
param, add "inh".
bfd/
* coff-aux.c (coff_m68k_aux_link_add_one_symbol): Only call "notice"
here when not calling the generic add_symbol function. Formatting.
Correct handling of indirect symbols. Update notice call.
* elflink.c (_bfd_elf_notice_as_needed): Update notice call.
* linker.c (_bfd_generic_link_add_one_symbol): Create indirect
symbols early. Update notice call. Add comments regarding weak
symbols vs. indirect.
ld/
* ldmain.c (notice): Update args.
* plugin.c (plugin_notice): Likewise. Follow warning sym link.
Handle new indirect symbol.
Diffstat (limited to 'bfd')
-rw-r--r-- | bfd/ChangeLog | 10 | ||||
-rw-r--r-- | bfd/coff-aux.c | 62 | ||||
-rw-r--r-- | bfd/elflink.c | 2 | ||||
-rw-r--r-- | bfd/linker.c | 82 |
4 files changed, 89 insertions, 67 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index e2855ad..8fda279 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,5 +1,15 @@ 2014-08-12 Alan Modra <amodra@gmail.com> + * coff-aux.c (coff_m68k_aux_link_add_one_symbol): Only call "notice" + here when not calling the generic add_symbol function. Formatting. + Correct handling of indirect symbols. Update notice call. + * elflink.c (_bfd_elf_notice_as_needed): Update notice call. + * linker.c (_bfd_generic_link_add_one_symbol): Create indirect + symbols early. Update notice call. Add comments regarding weak + symbols vs. indirect. + +2014-08-12 Alan Modra <amodra@gmail.com> + PR ld/16746 * linker.c (_bfd_generic_link_add_one_symbol <WARN>): Handle !lto_plugin_active. diff --git a/bfd/coff-aux.c b/bfd/coff-aux.c index e79c77a..d95b98b 100644 --- a/bfd/coff-aux.c +++ b/bfd/coff-aux.c @@ -73,20 +73,17 @@ coff_m68k_aux_link_add_one_symbol (struct bfd_link_info *info, bfd_boolean collect, struct bfd_link_hash_entry **hashp) { - struct bfd_link_hash_entry *h; + struct bfd_link_hash_entry *h, *inh, *t; - if ((flags & (BSF_WARNING | BSF_CONSTRUCTOR | BSF_WEAK)) == 0 && - !bfd_is_und_section (section) && - !bfd_is_com_section (section)) + if ((flags & (BSF_WARNING | BSF_CONSTRUCTOR | BSF_WEAK)) == 0 + && !bfd_is_und_section (section) + && !bfd_is_com_section (section)) { /* The new symbol is a definition or an indirect definition */ /* This bit copied from linker.c */ if (hashp != NULL && *hashp != NULL) - { - h = *hashp; - BFD_ASSERT (strcmp (h->root.string, name) == 0); - } + h = *hashp; else { h = bfd_link_hash_lookup (info->hash, name, TRUE, copy, FALSE); @@ -98,37 +95,46 @@ coff_m68k_aux_link_add_one_symbol (struct bfd_link_info *info, } } - if (info->notice_hash != (struct bfd_hash_table *) NULL - && (bfd_hash_lookup (info->notice_hash, name, FALSE, FALSE) - != (struct bfd_hash_entry *) NULL)) - { - if (! (*info->callbacks->notice) (info, h, abfd, section, value, - flags, string)) - return FALSE; - } - if (hashp != (struct bfd_link_hash_entry **) NULL) *hashp = h; /* end duplication from linker.c */ - if (h->type == bfd_link_hash_defined - || h->type == bfd_link_hash_indirect) + t = h; + inh = NULL; + if (h->type == bfd_link_hash_indirect) { - asection *msec; + inh = h->u.i.link; + t = inh; + } - if (h->type == bfd_link_hash_defined) - msec = h->u.def.section; - else - msec = bfd_ind_section_ptr; + if (t->type == bfd_link_hash_defined) + { + asection *msec = t->u.def.section; + bfd_boolean special = FALSE; if (bfd_is_abs_section (msec) && !bfd_is_abs_section (section)) { - h->u.def.section = section; - h->u.def.value = value; - return TRUE; + t->u.def.section = section; + t->u.def.value = value; + special = TRUE; } else if (bfd_is_abs_section (section) && !bfd_is_abs_section (msec)) - return TRUE; + special = TRUE; + + if (special) + { + if (info->notice_all + || (info->notice_hash != NULL + && bfd_hash_lookup (info->notice_hash, name, + FALSE, FALSE) != NULL)) + { + if (!(*info->callbacks->notice) (info, h, inh, + abfd, section, value, flags)) + return FALSE; + } + + return TRUE; + } } } diff --git a/bfd/elflink.c b/bfd/elflink.c index 69a87a6..de0a734 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -3299,7 +3299,7 @@ _bfd_elf_notice_as_needed (bfd *ibfd, struct bfd_link_info *info, enum notice_asneeded_action act) { - return (*info->callbacks->notice) (info, NULL, ibfd, NULL, act, 0, NULL); + return (*info->callbacks->notice) (info, NULL, NULL, ibfd, NULL, act, 0); } /* Add symbols from an ELF object file to the linker hash table. */ diff --git a/bfd/linker.c b/bfd/linker.c index 1a5ecef..abdf5b0 100644 --- a/bfd/linker.c +++ b/bfd/linker.c @@ -1442,13 +1442,23 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info, { enum link_row row; struct bfd_link_hash_entry *h; + struct bfd_link_hash_entry *inh = NULL; bfd_boolean cycle; BFD_ASSERT (section != NULL); if (bfd_is_ind_section (section) || (flags & BSF_INDIRECT) != 0) - row = INDR_ROW; + { + row = INDR_ROW; + /* Create the indirect symbol here. This is for the benefit of + the plugin "notice" function. + STRING is the name of the symbol we want to indirect to. */ + inh = bfd_wrapped_link_hash_lookup (abfd, info, string, TRUE, + copy, FALSE); + if (inh == NULL) + return FALSE; + } else if ((flags & BSF_WARNING) != 0) row = WARN_ROW; else if ((flags & BSF_CONSTRUCTOR) != 0) @@ -1493,8 +1503,8 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info, || (info->notice_hash != NULL && bfd_hash_lookup (info->notice_hash, name, FALSE, FALSE) != NULL)) { - if (! (*info->callbacks->notice) (info, h, - abfd, section, value, flags, string)) + if (! (*info->callbacks->notice) (info, h, inh, + abfd, section, value, flags)) return FALSE; } @@ -1728,44 +1738,40 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info, return FALSE; /* Fall through. */ case IND: - /* Create an indirect symbol. */ - { - struct bfd_link_hash_entry *inh; - - /* STRING is the name of the symbol we want to indirect - to. */ - inh = bfd_wrapped_link_hash_lookup (abfd, info, string, TRUE, - copy, FALSE); - if (inh == NULL) + if (inh->type == bfd_link_hash_indirect + && inh->u.i.link == h) + { + (*_bfd_error_handler) + (_("%B: indirect symbol `%s' to `%s' is a loop"), + abfd, name, string); + bfd_set_error (bfd_error_invalid_operation); return FALSE; - if (inh->type == bfd_link_hash_indirect - && inh->u.i.link == h) - { - (*_bfd_error_handler) - (_("%B: indirect symbol `%s' to `%s' is a loop"), - abfd, name, string); - bfd_set_error (bfd_error_invalid_operation); - return FALSE; - } - if (inh->type == bfd_link_hash_new) - { - inh->type = bfd_link_hash_undefined; - inh->u.undef.abfd = abfd; - bfd_link_add_undef (info->hash, inh); - } + } + if (inh->type == bfd_link_hash_new) + { + inh->type = bfd_link_hash_undefined; + inh->u.undef.abfd = abfd; + bfd_link_add_undef (info->hash, inh); + } - /* If the indirect symbol has been referenced, we need to - push the reference down to the symbol we are - referencing. */ - if (h->type != bfd_link_hash_new) - { - row = UNDEF_ROW; - cycle = TRUE; - } + /* If the indirect symbol has been referenced, we need to + push the reference down to the symbol we are referencing. */ + if (h->type != bfd_link_hash_new) + { + /* ??? If inh->type == bfd_link_hash_undefweak this + converts inh to bfd_link_hash_undefined. */ + row = UNDEF_ROW; + cycle = TRUE; + } - h->type = bfd_link_hash_indirect; - h->u.i.link = inh; - } + h->type = bfd_link_hash_indirect; + h->u.i.link = inh; + /* Not setting h = h->u.i.link here means that when cycle is + set above we'll always go to REFC, and then cycle again + to the indirected symbol. This means that any successful + change of an existing symbol to indirect counts as a + reference. ??? That may not be correct when the existing + symbol was defweak. */ break; case SET: |