From a6a4679fc0ad12e99e0d8374752ecce9ef097ec2 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Wed, 27 Apr 2016 12:53:05 +0930 Subject: [PATCH] Cache result of scan for __start_* and __stop_* sections include/ * bfdlink.h (struct bfd_link_hash_entry): Add "section" field to undef. Formatting. bfd/ * elflink.c (_bfd_elf_is_start_stop): New function. (_bfd_elf_gc_mark_rsec): Use it. * elf-bfd.h (_bfd_elf_is_start_stop): Declare. --- bfd/ChangeLog | 6 +++++ bfd/elf-bfd.h | 3 +++ bfd/elflink.c | 74 ++++++++++++++++++++++++++++++++++++++++--------------- include/ChangeLog | 5 ++++ include/bfdlink.h | 21 +++++++++++----- 5 files changed, 83 insertions(+), 26 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 8f4de69..f67db84 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,9 @@ +2016-04-27 Alan Modra + + * elflink.c (_bfd_elf_is_start_stop): New function. + (_bfd_elf_gc_mark_rsec): Use it. + * elf-bfd.h (_bfd_elf_is_start_stop): Declare. + 2016-04-26 Trevor Saunders * elf32-rx.c (rx_set_section_contents): Avoid arithmetic on void *. diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index 7447629..6c05b55 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -2336,6 +2336,9 @@ extern bfd_boolean bfd_elf_gc_common_finalize_got_offsets extern bfd_boolean bfd_elf_gc_common_final_link (bfd *, struct bfd_link_info *); +extern asection *_bfd_elf_is_start_stop + (const struct bfd_link_info *, struct elf_link_hash_entry *); + extern bfd_boolean bfd_elf_reloc_symbol_deleted_p (bfd_vma, void *); diff --git a/bfd/elflink.c b/bfd/elflink.c index a6b3c94..b6ff6b6 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -12230,6 +12230,55 @@ _bfd_elf_gc_mark_hook (asection *sec, return NULL; } +/* For undefined __start_ and __stop_ symbols, return the + first input section matching . Return NULL otherwise. */ + +asection * +_bfd_elf_is_start_stop (const struct bfd_link_info *info, + struct elf_link_hash_entry *h) +{ + asection *s; + const char *sec_name; + + 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 (s == (asection *) 0 - 1) + return NULL; + return s; + } + + sec_name = NULL; + if (strncmp (h->root.root.string, "__start_", 8) == 0) + sec_name = h->root.root.string + 8; + else if (strncmp (h->root.root.string, "__stop_", 7) == 0) + sec_name = h->root.root.string + 7; + + if (sec_name != NULL && *sec_name != '\0') + { + bfd *i; + + 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 (s == NULL) + h->root.u.undef.section = (asection *) 0 - 1; + + return s; +} + /* COOKIE->rel describes a relocation against section SEC, which is a section we've decided to keep. Return the section that contains the relocation symbol, or NULL if no section contains it. */ @@ -12268,34 +12317,19 @@ _bfd_elf_gc_mark_rsec (struct bfd_link_info *info, asection *sec, if (h->u.weakdef != NULL) h->u.weakdef->mark = 1; - if (start_stop != NULL - && (h->root.type == bfd_link_hash_undefined - || h->root.type == bfd_link_hash_undefweak)) + if (start_stop != NULL) { /* To work around a glibc bug, mark all XXX input sections when there is an as yet undefined reference to __start_XXX or __stop_XXX symbols. The linker will later define such symbols for orphan input sections that have a name representable as a C identifier. */ - const char *sec_name = NULL; - if (strncmp (h->root.root.string, "__start_", 8) == 0) - sec_name = h->root.root.string + 8; - else if (strncmp (h->root.root.string, "__stop_", 7) == 0) - sec_name = h->root.root.string + 7; + asection *s = _bfd_elf_is_start_stop (info, h); - if (sec_name != NULL && *sec_name != '\0') + if (s != NULL) { - bfd *i; - - for (i = info->input_bfds; i != NULL; i = i->link.next) - { - asection *s = bfd_get_section_by_name (i, sec_name); - if (s != NULL && !s->gc_mark) - { - *start_stop = TRUE; - return s; - } - } + *start_stop = !s->gc_mark; + return s; } } diff --git a/include/ChangeLog b/include/ChangeLog index c73bdf4..1390d42 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,8 @@ +2016-04-27 Alan Modra + + * bfdlink.h (struct bfd_link_hash_entry): Add "section" field to + undef. Formatting. + 2016-04-21 Nick Clifton * bfdlink.h: Add prototype for bfd_link_check_relocs. diff --git a/include/bfdlink.h b/include/bfdlink.h index 728fbe7..56ab038 100644 --- a/include/bfdlink.h +++ b/include/bfdlink.h @@ -135,21 +135,29 @@ struct bfd_link_hash_entry automatically be non-NULL since the symbol will have been on the undefined symbol list. */ struct bfd_link_hash_entry *next; - bfd *abfd; /* BFD symbol was found in. */ + /* BFD symbol was found in. */ + bfd *abfd; + /* For __start_ and __stop_ symbols, the first + input section matching the name. */ + asection *section; } undef; /* bfd_link_hash_defined, bfd_link_hash_defweak. */ struct { struct bfd_link_hash_entry *next; - asection *section; /* Symbol section. */ - bfd_vma value; /* Symbol value. */ + /* Symbol section. */ + asection *section; + /* Symbol value. */ + bfd_vma value; } def; /* bfd_link_hash_indirect, bfd_link_hash_warning. */ struct { struct bfd_link_hash_entry *next; - struct bfd_link_hash_entry *link; /* Real symbol. */ - const char *warning; /* Warning (bfd_link_hash_warning only). */ + /* Real symbol. */ + struct bfd_link_hash_entry *link; + /* Warning message (bfd_link_hash_warning only). */ + const char *warning; } i; /* bfd_link_hash_common. */ struct @@ -165,7 +173,8 @@ struct bfd_link_hash_entry the union; this structure is a major space user in the linker. */ struct bfd_link_hash_common_entry *p; - bfd_size_type size; /* Common symbol size. */ + /* Common symbol size. */ + bfd_size_type size; } c; } u; }; -- 2.7.4