From b6809eeed88f48dcbe71c1e4ce1213748b0bfe22 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Thu, 28 Apr 2016 06:38:41 -0700 Subject: [PATCH] Add _bfd_elf_record_start_stop --- bfd/elf-bfd.h | 3 ++ bfd/elflink.c | 87 ++++++++++++++++++++++++++++++++++++++++----------- ld/emultempl/elf32.em | 4 +++ 3 files changed, 75 insertions(+), 19 deletions(-) diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index 6c05b55..49dc70b 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -2339,6 +2339,9 @@ extern bfd_boolean bfd_elf_gc_common_final_link extern asection *_bfd_elf_is_start_stop (const struct bfd_link_info *, struct elf_link_hash_entry *); +extern void _bfd_elf_record_start_stop + (struct bfd_link_info *); + extern bfd_boolean bfd_elf_reloc_symbol_deleted_p (bfd_vma, void *); diff --git a/bfd/elflink.c b/bfd/elflink.c index b6ff6b6..9395052 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -12230,8 +12230,9 @@ _bfd_elf_gc_mark_hook (asection *sec, return NULL; } -/* For undefined __start_ and __stop_ symbols, return the - first input section matching . Return NULL otherwise. */ +/* For __start_ and __stop_ symbols, return the first + input section matching in a regular object. Return NULL + otherwise. */ asection * _bfd_elf_is_start_stop (const struct bfd_link_info *info, @@ -12239,17 +12240,28 @@ _bfd_elf_is_start_stop (const struct bfd_link_info *info, { asection *s; const char *sec_name; + bfd_boolean undefined = (h->root.type == bfd_link_hash_undefined + || h->root.type == bfd_link_hash_undefweak); - if (h->root.type != bfd_link_hash_undefined - && h->root.type != bfd_link_hash_undefweak) - return NULL; - - s = h->root.u.undef.section; - if (s != NULL) + if (undefined) + { + s = h->root.u.undef.section; + if (s != NULL) + { + if (s == (asection *) 0 - 1) + return NULL; + return s; + } + } + else { - if (s == (asection *) 0 - 1) + /* Symbol is defined. Check if it is also defined in a regular + input file only when it is currently defined in a dynamic + object, since otherwise, it can't be a __start_ nor + __stop_ symbol. */ + if (!h->def_dynamic) return NULL; - return s; + s = NULL; } sec_name = NULL; @@ -12262,18 +12274,21 @@ _bfd_elf_is_start_stop (const struct bfd_link_info *info, { bfd *i; + /* Only check regular input files. */ for (i = info->input_bfds; i != NULL; i = i->link.next) - { - s = bfd_get_section_by_name (i, sec_name); - if (s != NULL) - { - h->root.u.undef.section = s; - break; - } - } + if ((i->flags + & (DYNAMIC | BFD_LINKER_CREATED | BFD_PLUGIN)) == 0) + { + s = bfd_get_section_by_name (i, sec_name); + if (s != NULL) + { + h->root.u.undef.section = s; + break; + } + } } - if (s == NULL) + if (undefined && s == NULL) h->root.u.undef.section = (asection *) 0 - 1; return s; @@ -13791,3 +13806,37 @@ elf_append_rel (bfd *abfd, asection *s, Elf_Internal_Rela *rel) BFD_ASSERT (loc + bed->s->sizeof_rel <= s->contents + s->size); bed->s->swap_reloc_out (abfd, rel, loc); } + +/* Record __start_ and __stop_ symbols referenced by + regular objects. This is called via elf_link_hash_traverse. */ + +static bfd_boolean +elf_link_record_start_stop (struct elf_link_hash_entry *h, void *data) +{ + if (!h->def_regular && h->ref_regular) + { + asection *sec + = _bfd_elf_is_start_stop ((struct bfd_link_info *) data, h); + if (sec != NULL) + { + h->def_regular = 1; + h->type = STT_OBJECT; + /* If it is currently defined by a dynamic object, but not + by a regular object, then mark it as undefined so that + the generic linker will force the correct value. */ + if (h->def_dynamic) + h->root.type = bfd_link_hash_undefined; + } + } + return TRUE; +} + +/* Record all __start_ and __stop_ symbols referenced by + regular objects. */ + +void +_bfd_elf_record_start_stop (struct bfd_link_info * info) +{ + elf_link_hash_traverse (elf_hash_table (info), + elf_link_record_start_stop, info); +} diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em index cc2f056..86105fe 100644 --- a/ld/emultempl/elf32.em +++ b/ld/emultempl/elf32.em @@ -1445,6 +1445,10 @@ gld${EMULATION_NAME}_record_link_assignments (lang_phase_type phase) let the ELF backend know about them in case the variables are referred to by dynamic objects. */ lang_for_each_statement (gld${EMULATION_NAME}_find_statement_assignment); + + /* Also let the ELF backend know about __start_ and + __stop_ symbols. */ + _bfd_elf_record_start_stop (&link_info); } } -- 2.5.5