From 199af1503922ce2134d774a78be0d9e2ae055ab1 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Wed, 28 Oct 2015 17:18:13 +1030 Subject: [PATCH] Orphan output section with multiple input sections If given input sections with differing flags, we'd like to place the section according to the final output section flags. bfd/ PR ld/19162 * elflink.c (_bfd_elf_gc_mark_reloc): Move code iterating over linker input bfds.. * section.c (bfd_get_next_section_by_name): ..to here. Add ibfd param. (bfd_get_linker_section): Adjust bfd_get_next_section_by_name call. * tekhex.c (first_phase): Likewise. * elflink.c (bfd_elf_gc_sections): Likewise. * bfd-in2.h: Regenerate. ld/ PR ld/19162 * emultempl/elf32.em (gld${EMULATION_NAME}_place_orphan): Check flags before calling _bfd_elf_match_sections_by_type. Merge flags for any other input sections that might match a new output section to decide placement. --- bfd/ChangeLog | 11 +++++++++++ bfd/bfd-in2.h | 2 +- bfd/elflink.c | 21 ++------------------- bfd/section.c | 20 ++++++++++++++++---- bfd/tekhex.c | 6 ++++-- ld/ChangeLog | 8 ++++++++ ld/emultempl/elf32.em | 43 +++++++++++++++++++++++++++++-------------- 7 files changed, 71 insertions(+), 40 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 1ef747ea52..3f9a3de15c 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,14 @@ +2015-10-28 Alan Modra + + PR ld/19162 + * elflink.c (_bfd_elf_gc_mark_reloc): Move code iterating over + linker input bfds.. + * section.c (bfd_get_next_section_by_name): ..to here. Add ibfd param. + (bfd_get_linker_section): Adjust bfd_get_next_section_by_name call. + * tekhex.c (first_phase): Likewise. + * elflink.c (bfd_elf_gc_sections): Likewise. + * bfd-in2.h: Regenerate. + 2015-10-27 Laurent Alfonsi Christophe Monat diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index f381f06f3f..85fa3abd17 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -1810,7 +1810,7 @@ void bfd_section_list_clear (bfd *); asection *bfd_get_section_by_name (bfd *abfd, const char *name); -asection *bfd_get_next_section_by_name (asection *sec); +asection *bfd_get_next_section_by_name (bfd *ibfd, asection *sec); asection *bfd_get_linker_section (bfd *abfd, const char *name); diff --git a/bfd/elflink.c b/bfd/elflink.c index 1cfdd31356..1b41c793a9 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -12179,8 +12179,6 @@ _bfd_elf_gc_mark_reloc (struct bfd_link_info *info, rsec = _bfd_elf_gc_mark_rsec (info, sec, gc_mark_hook, cookie, &start_stop); while (rsec != NULL) { - asection *s; - if (!rsec->gc_mark) { if (bfd_get_flavour (rsec->owner) != bfd_target_elf_flavour @@ -12191,22 +12189,7 @@ _bfd_elf_gc_mark_reloc (struct bfd_link_info *info, } if (!start_stop) break; - s = bfd_get_next_section_by_name (rsec); - if (s == NULL) - { - bfd *i = rsec->owner; - - if (i != NULL) - { - while ((i = i->link.next) != NULL) - { - s = bfd_get_section_by_name (i, rsec->name); - if (s != NULL) - break; - } - } - } - rsec = s; + rsec = bfd_get_next_section_by_name (rsec->owner, rsec); } return TRUE; } @@ -12757,7 +12740,7 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info) && (sec->flags & SEC_LINKER_CREATED) == 0) elf_eh_frame_section (sub) = sec; fini_reloc_cookie_for_section (&cookie, sec); - sec = bfd_get_next_section_by_name (sec); + sec = bfd_get_next_section_by_name (NULL, sec); } } diff --git a/bfd/section.c b/bfd/section.c index 834a9ab0b4..247d98ad14 100644 --- a/bfd/section.c +++ b/bfd/section.c @@ -903,16 +903,18 @@ FUNCTION bfd_get_next_section_by_name SYNOPSIS - asection *bfd_get_next_section_by_name (asection *sec); + asection *bfd_get_next_section_by_name (bfd *ibfd, asection *sec); DESCRIPTION Given @var{sec} is a section returned by @code{bfd_get_section_by_name}, return the next most recently created section attached to the same - BFD with the same name. Return NULL if no such section exists. + BFD with the same name, or if no such section exists in the same BFD and + IBFD is non-NULL, the next section with the same name in any input + BFD following IBFD. Return NULL on finding no section. */ asection * -bfd_get_next_section_by_name (asection *sec) +bfd_get_next_section_by_name (bfd *ibfd, asection *sec) { struct section_hash_entry *sh; const char *name; @@ -930,6 +932,16 @@ bfd_get_next_section_by_name (asection *sec) && strcmp (sh->root.string, name) == 0) return &sh->section; + if (ibfd != NULL) + { + while ((ibfd = ibfd->link.next) != NULL) + { + asection *s = bfd_get_section_by_name (ibfd, name); + if (s != NULL) + return s; + } + } + return NULL; } @@ -951,7 +963,7 @@ bfd_get_linker_section (bfd *abfd, const char *name) asection *sec = bfd_get_section_by_name (abfd, name); while (sec != NULL && (sec->flags & SEC_LINKER_CREATED) == 0) - sec = bfd_get_next_section_by_name (sec); + sec = bfd_get_next_section_by_name (NULL, sec); return sec; } diff --git a/bfd/tekhex.c b/bfd/tekhex.c index ccc68f92d3..951c327e70 100644 --- a/bfd/tekhex.c +++ b/bfd/tekhex.c @@ -459,7 +459,8 @@ first_phase (bfd *abfd, int type, char *src, char * src_end) else { if (alt_section == NULL) - alt_section = bfd_get_next_section_by_name (section); + alt_section + = bfd_get_next_section_by_name (NULL, section); if (alt_section == NULL) alt_section = bfd_make_section_anyway_with_flags (abfd, section->name, @@ -476,7 +477,8 @@ first_phase (bfd *abfd, int type, char *src, char * src_end) else { if (alt_section == NULL) - alt_section = bfd_get_next_section_by_name (section); + alt_section + = bfd_get_next_section_by_name (NULL, section); if (alt_section == NULL) alt_section = bfd_make_section_anyway_with_flags (abfd, section->name, diff --git a/ld/ChangeLog b/ld/ChangeLog index 359fc19d20..5b9ac97a04 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,11 @@ +2015-10-28 Alan Modra + + PR ld/19162 + * emultempl/elf32.em (gld${EMULATION_NAME}_place_orphan): Check flags + before calling _bfd_elf_match_sections_by_type. Merge flags for + any other input sections that might match a new output section to + decide placement. + 2015-10-27 Laurent Alfonsi Christophe Monat diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em index 1dc215f80f..629c414b48 100644 --- a/ld/emultempl/elf32.em +++ b/ld/emultempl/elf32.em @@ -1852,6 +1852,8 @@ gld${EMULATION_NAME}_place_orphan (asection *s, int isdyn = 0; int iself = s->owner->xvec->flavour == bfd_target_elf_flavour; unsigned int sh_type = iself ? elf_section_type (s) : SHT_NULL; + flagword flags; + asection *nexts; if (!bfd_link_relocatable (&link_info) && link_info.combreloc @@ -1890,11 +1892,11 @@ gld${EMULATION_NAME}_place_orphan (asection *s, if (os->bfd_section != NULL && (os->bfd_section->flags == 0 - || (_bfd_elf_match_sections_by_type (link_info.output_bfd, - os->bfd_section, - s->owner, s) - && ((s->flags ^ os->bfd_section->flags) - & (SEC_LOAD | SEC_ALLOC)) == 0))) + || (((s->flags ^ os->bfd_section->flags) + & (SEC_LOAD | SEC_ALLOC)) == 0 + && _bfd_elf_match_sections_by_type (link_info.output_bfd, + os->bfd_section, + s->owner, s)))) { /* We already have an output section statement with this name, and its bfd section has compatible flags. @@ -1950,28 +1952,41 @@ gld${EMULATION_NAME}_place_orphan (asection *s, stored right after the program headers where the OS can read it in the first page. */ + flags = s->flags; + nexts = s; + while ((nexts = bfd_get_next_section_by_name (nexts->owner, nexts)) != NULL) + if (nexts->output_section == NULL + && (nexts->flags & SEC_EXCLUDE) == 0 + && ((nexts->flags ^ flags) & (SEC_LOAD | SEC_ALLOC)) == 0 + && (nexts->owner->flags & DYNAMIC) == 0 + && nexts->owner->usrdata != NULL + && !(((lang_input_statement_type *) nexts->owner->usrdata) + ->flags.just_syms) + && _bfd_elf_match_sections_by_type (nexts->owner, nexts, s->owner, s)) + flags = (((flags ^ SEC_READONLY) | (nexts->flags ^ SEC_READONLY)) + ^ SEC_READONLY); place = NULL; - if ((s->flags & (SEC_ALLOC | SEC_DEBUGGING)) == 0) + if ((flags & (SEC_ALLOC | SEC_DEBUGGING)) == 0) place = &hold[orphan_nonalloc]; - else if ((s->flags & SEC_ALLOC) == 0) + else if ((flags & SEC_ALLOC) == 0) ; - else if ((s->flags & SEC_LOAD) != 0 + else if ((flags & SEC_LOAD) != 0 && ((iself && sh_type == SHT_NOTE) || (!iself && CONST_STRNEQ (secname, ".note")))) place = &hold[orphan_interp]; - else if ((s->flags & (SEC_LOAD | SEC_HAS_CONTENTS | SEC_THREAD_LOCAL)) == 0) + else if ((flags & (SEC_LOAD | SEC_HAS_CONTENTS | SEC_THREAD_LOCAL)) == 0) place = &hold[orphan_bss]; - else if ((s->flags & SEC_SMALL_DATA) != 0) + else if ((flags & SEC_SMALL_DATA) != 0) place = &hold[orphan_sdata]; - else if ((s->flags & SEC_THREAD_LOCAL) != 0) + else if ((flags & SEC_THREAD_LOCAL) != 0) place = &hold[orphan_tdata]; - else if ((s->flags & SEC_READONLY) == 0) + else if ((flags & SEC_READONLY) == 0) place = &hold[orphan_data]; else if (((iself && (sh_type == SHT_RELA || sh_type == SHT_REL)) || (!iself && CONST_STRNEQ (secname, ".rel"))) - && (s->flags & SEC_LOAD) != 0) + && (flags & SEC_LOAD) != 0) place = &hold[orphan_rel]; - else if ((s->flags & SEC_CODE) == 0) + else if ((flags & SEC_CODE) == 0) place = &hold[orphan_rodata]; else place = &hold[orphan_text]; -- 2.34.1