diff options
-rw-r--r-- | bfd/ChangeLog | 20 | ||||
-rw-r--r-- | bfd/bfd-in2.h | 7 | ||||
-rw-r--r-- | bfd/elf-bfd.h | 4 | ||||
-rw-r--r-- | bfd/elf.c | 15 | ||||
-rw-r--r-- | bfd/libbfd-in.h | 2 | ||||
-rw-r--r-- | bfd/libbfd.c | 9 | ||||
-rw-r--r-- | bfd/libbfd.h | 2 | ||||
-rw-r--r-- | bfd/targets.c | 7 | ||||
-rw-r--r-- | ld/ChangeLog | 12 | ||||
-rw-r--r-- | ld/emultempl/elf32.em | 42 | ||||
-rw-r--r-- | ld/ld.texinfo | 17 | ||||
-rw-r--r-- | ld/ldlang.c | 48 |
12 files changed, 168 insertions, 17 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index fdf2809..e940c93 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,23 @@ +2005-10-15 H.J. Lu <hongjiu.lu@intel.com> + + PR ld/1467 + * elf-bfd.h (_bfd_elf_match_sections_by_type): New. + (_bfd_generic_match_sections_by_type): New. Defined. + + * elf.c (_bfd_elf_match_sections_by_type): New. + + * libbfd-in.h (_bfd_generic_match_sections_by_type): New. + + * bfd-in2.h: Regenerated. + * libbfd.h: Likewise. + + * libbfd.c (_bfd_generic_match_sections_by_type): New. + + * targets.c (BFD_JUMP_TABLE_LINK): Initialize + _bfd_match_sections_by_type with + _bfd_generic_match_sections_by_type. + (bfd_target): Add _bfd_match_sections_by_type. + 2005-10-08 Paul Brook <paul@codesourcery.com> * elf32-arm.c: Move #include "elf/arm.h" after libbfd.h. diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 3471081..1d93b0f 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -4926,6 +4926,7 @@ typedef struct bfd_target NAME##_bfd_link_split_section, \ NAME##_bfd_gc_sections, \ NAME##_bfd_merge_sections, \ + _bfd_generic_match_sections_by_type, \ NAME##_bfd_is_group_section, \ NAME##_bfd_discard_group, \ NAME##_section_already_linked \ @@ -4965,6 +4966,12 @@ typedef struct bfd_target /* Attempt to merge SEC_MERGE sections. */ bfd_boolean (*_bfd_merge_sections) (bfd *, struct bfd_link_info *); +#define bfd_match_sections_by_type(abfd, asec, bbfd, bsec) \ + BFD_SEND (abfd, _bfd_match_sections_by_type, (abfd, asec, bbfd, bsec)) + /* Return TRUE if 2 section types are compatible. */ + bfd_boolean (*_bfd_match_sections_by_type) + (bfd *, const asection *, bfd *, const asection *); + /* Is this section a member of a group? */ bfd_boolean (*_bfd_is_group_section) (bfd *, const struct bfd_section *); diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index f4c0ed8..d011a45 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -1474,6 +1474,10 @@ extern bfd_boolean _bfd_elf_slurp_version_tables (bfd *, bfd_boolean); extern bfd_boolean _bfd_elf_merge_sections (bfd *, struct bfd_link_info *); +extern bfd_boolean _bfd_elf_match_sections_by_type + (bfd *, const asection *, bfd *, const asection *); +#define _bfd_generic_match_sections_by_type \ + _bfd_elf_match_sections_by_type extern bfd_boolean bfd_elf_is_group_section (bfd *, const struct bfd_section *); extern void _bfd_elf_section_already_linked @@ -8502,3 +8502,18 @@ asection _bfd_elf_large_com_section = BFD_FAKE_SECTION (_bfd_elf_large_com_section, SEC_IS_COMMON, NULL, NULL, "LARGE_COMMON", 0); + +/* Return TRUE if 2 section types are compatible. */ + +bfd_boolean +_bfd_elf_match_sections_by_type (bfd *abfd, const asection *asec, + bfd *bbfd, const asection *bsec) +{ + if (asec == NULL + || bsec == NULL + || abfd->xvec->flavour != bfd_target_elf_flavour + || bbfd->xvec->flavour != bfd_target_elf_flavour) + return TRUE; + + return elf_section_type (asec) == elf_section_type (bsec); +} diff --git a/bfd/libbfd-in.h b/bfd/libbfd-in.h index 47595c6..0290c84 100644 --- a/bfd/libbfd-in.h +++ b/bfd/libbfd-in.h @@ -399,6 +399,8 @@ extern bfd_boolean _bfd_generic_set_section_contents ((bfd_boolean (*) (bfd *, struct bfd_section *)) bfd_false) #define _bfd_nolink_section_already_linked \ ((void (*) (bfd *, struct bfd_section *)) bfd_void) +extern bfd_boolean _bfd_generic_match_sections_by_type + (bfd *, const asection *, bfd *, const asection *); /* Routines to use for BFD_JUMP_TABLE_DYNAMIC for targets which do not have dynamic symbols or relocs. Use BFD_JUMP_TABLE_DYNAMIC diff --git a/bfd/libbfd.c b/bfd/libbfd.c index 66137bb..3b27e08 100644 --- a/bfd/libbfd.c +++ b/bfd/libbfd.c @@ -1033,3 +1033,12 @@ _bfd_generic_find_line (bfd *abfd ATTRIBUTE_UNUSED, { return FALSE; } + +bfd_boolean +_bfd_generic_match_sections_by_type (bfd *abfd ATTRIBUTE_UNUSED, + const asection *asec ATTRIBUTE_UNUSED, + bfd *bbfd ATTRIBUTE_UNUSED, + const asection *bsec ATTRIBUTE_UNUSED) +{ + return TRUE; +} diff --git a/bfd/libbfd.h b/bfd/libbfd.h index 6f3650b..56ad092 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -404,6 +404,8 @@ extern bfd_boolean _bfd_generic_set_section_contents ((bfd_boolean (*) (bfd *, struct bfd_section *)) bfd_false) #define _bfd_nolink_section_already_linked \ ((void (*) (bfd *, struct bfd_section *)) bfd_void) +extern bfd_boolean _bfd_generic_match_sections_by_type + (bfd *, const asection *, bfd *, const asection *); /* Routines to use for BFD_JUMP_TABLE_DYNAMIC for targets which do not have dynamic symbols or relocs. Use BFD_JUMP_TABLE_DYNAMIC diff --git a/bfd/targets.c b/bfd/targets.c index dd5e097..271954f 100644 --- a/bfd/targets.c +++ b/bfd/targets.c @@ -427,6 +427,7 @@ BFD_JUMP_TABLE macros. . NAME##_bfd_link_split_section, \ . NAME##_bfd_gc_sections, \ . NAME##_bfd_merge_sections, \ +. _bfd_generic_match_sections_by_type, \ . NAME##_bfd_is_group_section, \ . NAME##_bfd_discard_group, \ . NAME##_section_already_linked \ @@ -466,6 +467,12 @@ BFD_JUMP_TABLE macros. . {* Attempt to merge SEC_MERGE sections. *} . bfd_boolean (*_bfd_merge_sections) (bfd *, struct bfd_link_info *); . +.#define bfd_match_sections_by_type(abfd, asec, bbfd, bsec) \ +. BFD_SEND (abfd, _bfd_match_sections_by_type, (abfd, asec, bbfd, bsec)) +. {* Return TRUE if 2 section types are compatible. *} +. bfd_boolean (*_bfd_match_sections_by_type) +. (bfd *, const asection *, bfd *, const asection *); +. . {* Is this section a member of a group? *} . bfd_boolean (*_bfd_is_group_section) (bfd *, const struct bfd_section *); . diff --git a/ld/ChangeLog b/ld/ChangeLog index dfa7317..20c5281 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,15 @@ +2005-10-15 H.J. Lu <hongjiu.lu@intel.com> + + PR ld/1467 + * emultempl/elf32.em: Include "elf-bfd.h". + (gld${EMULATION_NAME}_place_orphan): Check section type and + don't use section name for ELF input sections. + + * ld.texinfo: Document orphan section processing. + + * ldlang.c (lang_output_section_find_by_flags): Match section + types by calling bfd_match_sections_by_type. + 2005-10-13 Mark Mitchell <mark@codesourcery.com> * ld.texino: Describe double-quoted string syntax for version diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em index 15d2722..e1e37f1 100644 --- a/ld/emultempl/elf32.em +++ b/ld/emultempl/elf32.em @@ -53,6 +53,7 @@ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. #include "ldemul.h" #include <ldgram.h> #include "elf/common.h" +#include "elf-bfd.h" /* Declare functions used by various EXTRA_EM_FILEs. */ static void gld${EMULATION_NAME}_before_parse (void); @@ -1324,19 +1325,34 @@ gld${EMULATION_NAME}_place_orphan (lang_input_statement_type *file, asection *s) lang_output_section_statement_type *after; lang_output_section_statement_type *os; int isdyn = 0; + int iself = s->owner->xvec->flavour == bfd_target_elf_flavour; + unsigned int sh_type = iself ? elf_section_type (s) : SHT_NULL; secname = bfd_get_section_name (s->owner, s); if (! link_info.relocatable && link_info.combreloc - && (s->flags & SEC_ALLOC) - && strncmp (secname, ".rel", 4) == 0) + && (s->flags & SEC_ALLOC)) { - if (secname[4] == 'a') - secname = ".rela.dyn"; - else - secname = ".rel.dyn"; - isdyn = 1; + if (iself) + switch (sh_type) + { + case SHT_RELA: + secname = ".rela.dyn"; + isdyn = 1; + break; + case SHT_REL: + secname = ".rel.dyn"; + isdyn = 1; + break; + default: + break; + } + else if (strncmp (secname, ".rel", 4) == 0) + { + secname = secname[4] == 'a' ? ".rela.dyn" : ".rel.dyn"; + isdyn = 1; + } } if (isdyn || (!config.unique_orphan_sections && !unique_section_p (s))) @@ -1347,8 +1363,10 @@ gld${EMULATION_NAME}_place_orphan (lang_input_statement_type *file, asection *s) if (os != NULL && (os->bfd_section == NULL || os->bfd_section->flags == 0 - || ((s->flags ^ os->bfd_section->flags) - & (SEC_LOAD | SEC_ALLOC)) == 0)) + || ((!iself + || sh_type == elf_section_type (os->bfd_section)) + && ((s->flags ^ os->bfd_section->flags) + & (SEC_LOAD | SEC_ALLOC)) == 0))) { /* We already have an output section statement with this name, and its bfd section, if any, has compatible flags. @@ -1395,7 +1413,8 @@ gld${EMULATION_NAME}_place_orphan (lang_input_statement_type *file, asection *s) if ((s->flags & SEC_ALLOC) == 0) ; else if ((s->flags & SEC_LOAD) != 0 - && strncmp (secname, ".note", 5) == 0) + && ((iself && sh_type == SHT_NOTE) + || (!iself && strncmp (secname, ".note", 5) == 0))) place = &hold[orphan_interp]; else if ((s->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0) place = &hold[orphan_bss]; @@ -1403,7 +1422,8 @@ gld${EMULATION_NAME}_place_orphan (lang_input_statement_type *file, asection *s) place = &hold[orphan_sdata]; else if ((s->flags & SEC_READONLY) == 0) place = &hold[orphan_data]; - else if (strncmp (secname, ".rel", 4) == 0 + else if (((iself && (sh_type == SHT_RELA || sh_type == SHT_REL)) + || (!iself && strncmp (secname, ".rel", 4) == 0)) && (s->flags & SEC_LOAD) != 0) place = &hold[orphan_rel]; else if ((s->flags & SEC_CODE) == 0) diff --git a/ld/ld.texinfo b/ld/ld.texinfo index 238fde9..d7673fd 100644 --- a/ld/ld.texinfo +++ b/ld/ld.texinfo @@ -4442,6 +4442,7 @@ expressions. @menu * Constants:: Constants * Symbols:: Symbol Names +* Orphan Sections:: Orphan Sections * Location Counter:: The Location Counter * Operators:: Operators * Evaluation:: Evaluation @@ -4503,6 +4504,22 @@ Since symbols can contain many non-alphabetic characters, it is safest to delimit symbols with spaces. For example, @samp{A-B} is one symbol, whereas @samp{A - B} is an expression involving subtraction. +@node Orphan Sections +@subsection Orphan Sections +@cindex orphan +Orphan sections are sections present in the input files which +are not explicitly placed into the output file by the linker +script. The linker will still copy these sections into the +output file, but it has to guess as to where they should be +placed. The linker uses a simple heuristic to do this. It +attempts to place orphan sections after non-orphan sections of the +same attribute, such as code vs data, loadable vs non-loadable, etc. +If there is not enough room to do this then it places +at the end of the file. + +For ELF targets, the attribute of the section includes section type as +well as section flag. + @node Location Counter @subsection The Location Counter @kindex . diff --git a/ld/ldlang.c b/ld/ldlang.c index 3ff4d81..b82a7e5 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -1149,7 +1149,13 @@ lang_output_section_find_by_flags (const asection *sec, { flags = look->flags; if (look->bfd_section != NULL) - flags = look->bfd_section->flags; + { + flags = look->bfd_section->flags; + if (!bfd_match_sections_by_type (output_bfd, + look->bfd_section, + sec->owner, sec)) + continue; + } flags ^= sec->flags; if (!(flags & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE | SEC_SMALL_DATA | SEC_THREAD_LOCAL))) @@ -1168,7 +1174,13 @@ lang_output_section_find_by_flags (const asection *sec, { flags = look->flags; if (look->bfd_section != NULL) - flags = look->bfd_section->flags; + { + flags = look->bfd_section->flags; + if (!bfd_match_sections_by_type (output_bfd, + look->bfd_section, + sec->owner, sec)) + continue; + } flags ^= sec->flags; if (!(flags & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_SMALL_DATA | SEC_THREAD_LOCAL))) @@ -1184,7 +1196,13 @@ lang_output_section_find_by_flags (const asection *sec, { flags = look->flags; if (look->bfd_section != NULL) - flags = look->bfd_section->flags; + { + flags = look->bfd_section->flags; + if (!bfd_match_sections_by_type (output_bfd, + look->bfd_section, + sec->owner, sec)) + continue; + } flags ^= sec->flags; if (!(flags & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY)) @@ -1201,7 +1219,13 @@ lang_output_section_find_by_flags (const asection *sec, { flags = look->flags; if (look->bfd_section != NULL) - flags = look->bfd_section->flags; + { + flags = look->bfd_section->flags; + if (!bfd_match_sections_by_type (output_bfd, + look->bfd_section, + sec->owner, sec)) + continue; + } flags ^= sec->flags; if (!(flags & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_THREAD_LOCAL)) @@ -1219,7 +1243,13 @@ lang_output_section_find_by_flags (const asection *sec, { flags = look->flags; if (look->bfd_section != NULL) - flags = look->bfd_section->flags; + { + flags = look->bfd_section->flags; + if (!bfd_match_sections_by_type (output_bfd, + look->bfd_section, + sec->owner, sec)) + continue; + } flags ^= sec->flags; if (!(flags & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_SMALL_DATA | SEC_THREAD_LOCAL))) @@ -1233,7 +1263,13 @@ lang_output_section_find_by_flags (const asection *sec, { flags = look->flags; if (look->bfd_section != NULL) - flags = look->bfd_section->flags; + { + flags = look->bfd_section->flags; + if (!bfd_match_sections_by_type (output_bfd, + look->bfd_section, + sec->owner, sec)) + continue; + } flags ^= sec->flags; if (!(flags & SEC_ALLOC)) found = look; |