From 577a062318714628709c41467904c0cb7b212f94 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Sun, 14 Jan 2001 04:36:35 +0000 Subject: [PATCH] Extend "ld --unique" functionality. --- ld/ChangeLog | 22 +++++++++++++++ ld/emultempl/elf32.em | 44 ++++++++++++++--------------- ld/ld.texinfo | 16 ++++++----- ld/ldlang.c | 65 +++++++++++++++++++++++++++++++------------ ld/ldlang.h | 14 +++++++++- ld/lexsup.c | 9 ++++-- 6 files changed, 119 insertions(+), 51 deletions(-) diff --git a/ld/ChangeLog b/ld/ChangeLog index 1452dec3487..edab167b3cc 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,25 @@ +2001-01-14 Alan Modra + + * emultempl/elf32.em (gld${EMULATION_NAME}_place_orphan): Don't + rummage through the script for sections on the unique list. + Correct length of strncmp for ".note". + (gld${EMULATION_NAME}_check_needed): Rearrange function. + + * ldlang.c (unique_section_list): New var. + (unique_section_p): New function. + (walk_wild_section): Don't match sections on unique_section_list. + (lang_add_unique): New function. + + * ldlang.h (struct unique_sections): Declare. + (unique_section_list): Declare. + (unique_section_p): Declare. + (lang_add_unique): Declare. + + * lexsup.c (ld_options): Allow --unique to take an optional arg. + (parse_args [OPTION_UNIQUE]): Call lang_add_unique. + + * ld.texinfo (--unique): Update. + 2001-01-13 Nick Clifton * lexsup.c (parse_args): Remove spurious white space. diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em index 492953d924b..417ac4ccbfe 100644 --- a/ld/emultempl/elf32.em +++ b/ld/emultempl/elf32.em @@ -7,7 +7,7 @@ cat >e${EMULATION_NAME}.c < ELF support by Ian Lance Taylor @@ -527,11 +527,26 @@ gld${EMULATION_NAME}_check_needed (s) if (global_found) return; - if (s->filename != NULL - && strcmp (s->filename, global_needed->name) == 0) + if (s->filename != NULL) { - global_found = true; - return; + const char *f; + + if (strcmp (s->filename, global_needed->name) == 0) + { + global_found = true; + return; + } + + if (s->search_dirs_flag) + { + f = strrchr (s->filename, '/'); + if (f != NULL + && strcmp (f + 1, global_needed->name) == 0) + { + global_found = true; + return; + } + } } if (s->the_bfd != NULL) @@ -546,21 +561,6 @@ gld${EMULATION_NAME}_check_needed (s) return; } } - - if (s->search_dirs_flag - && s->filename != NULL - && strchr (global_needed->name, '/') == NULL) - { - const char *f; - - f = strrchr (s->filename, '/'); - if (f != NULL - && strcmp (f + 1, global_needed->name) == 0) - { - global_found = true; - return; - } - } } EOF @@ -1030,7 +1030,7 @@ gld${EMULATION_NAME}_place_orphan (file, s) secname = bfd_get_section_name (s->owner, s); - if (! config.unique_orphan_sections) + if (! config.unique_orphan_sections && ! unique_section_p (secname)) { /* Look through the script to see where to place this section. */ os = lang_output_section_find (secname); @@ -1075,7 +1075,7 @@ gld${EMULATION_NAME}_place_orphan (file, s) if ((s->flags & SEC_ALLOC) == 0) ; else if ((s->flags & SEC_LOAD) != 0 - && strncmp (secname, ".note", 4) == 0 + && strncmp (secname, ".note", 5) == 0 && HAVE_SECTION (hold_interp, ".interp")) place = &hold_interp; else if ((s->flags & SEC_HAS_CONTENTS) == 0 diff --git a/ld/ld.texinfo b/ld/ld.texinfo index 5c8a595c429..e897d44a7c0 100644 --- a/ld/ld.texinfo +++ b/ld/ld.texinfo @@ -695,13 +695,15 @@ with @samp{-Ur}; once the constructor table has been built, it cannot be added to. Use @samp{-Ur} only for the last partial link, and @samp{-r} for the others. -@kindex --unique -@item --unique -Creates a separate output section for every orphan input section. This -option prevents the normal merging of orphan input sections with the same -name. An orphan section is one not specifically mentioned in a linker -script, so this option along with a custom linker script allows any -selection of input sections to be merged while others are kept separate. +@kindex --unique[=@var{SECTION}] +@item --unique[=@var{SECTION}] +Creates a separate output section for every input section matching +@var{SECTION}, or if the optional wildcard @var{SECTION} argument is +missing, for every orphan input section. An orphan section is one not +specifically mentioned in a linker script. You may use this option +multiple times on the command line; It prevents the normal merging of +input sections with the same name, overriding output section assignments +in a linker script. @kindex -v @kindex -V diff --git a/ld/ldlang.c b/ld/ldlang.c index 532b23d0e9e..4b822b306e9 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -1,5 +1,5 @@ /* Linker command language support. - Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 98, 99, 2000 + Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 98, 99, 2000, 2001 Free Software Foundation, Inc. This file is part of GLD, the Gnu Linker. @@ -186,6 +186,7 @@ boolean had_output_filename = false; boolean lang_float_flag = false; boolean delete_output_file_on_failure = false; struct lang_nocrossrefs *nocrossref_list; +struct unique_sections *unique_section_list; etree_type *base; /* Relocation base - or null */ @@ -211,6 +212,23 @@ stat_alloc (size) return obstack_alloc (&stat_obstack, size); } +boolean +unique_section_p (secnam) + const char *secnam; +{ + struct unique_sections *unam; + + for (unam = unique_section_list; unam; unam = unam->next) + if (wildcardp (unam->name) + ? fnmatch (unam->name, secnam, 0) == 0 + : strcmp (unam->name, secnam) == 0) + { + return true; + } + + return false; +} + /* Generic traversal routines for finding matching sections. */ static void @@ -242,31 +260,26 @@ walk_wild_section (ptr, section, file, callback, data) if (file->just_syms_flag == false) { register asection *s; - boolean wildcard; + boolean wildcard = false; - if (section == NULL) - wildcard = false; - else + if (section != NULL) wildcard = wildcardp (section); for (s = file->the_bfd->sections; s != NULL; s = s->next) { boolean match; + const char *sname = bfd_get_section_name (file->the_bfd, s); if (section == NULL) match = true; + else if (wildcard) + match = fnmatch (section, sname, 0) == 0 ? true : false; else - { - const char *name; + match = strcmp (section, sname) == 0 ? true : false; - name = bfd_get_section_name (file->the_bfd, s); - if (wildcard) - match = fnmatch (section, name, 0) == 0 ? true : false; - else - match = strcmp (section, name) == 0 ? true : false; - } - - if (match) + /* If this is a wild-card output section statement, exclude + sections that match UNIQUE_SECTION_LIST. */ + if (match && (data == NULL || !unique_section_p (sname))) (*callback) (ptr, s, file, data); } } @@ -925,20 +938,20 @@ section_already_linked (abfd, sec, data) if ((flags & SEC_LINK_ONCE) == 0) return; - /* FIXME: When doing a relocateable link, we may have trouble + /* FIXME: When doing a relocatable link, we may have trouble copying relocations in other sections that refer to local symbols in the section being discarded. Those relocations will have to be converted somehow; as of this writing I'm not sure that any of the backends handle that correctly. It is tempting to instead not discard link once sections when - doing a relocateable link (technically, they should be discarded + doing a relocatable link (technically, they should be discarded whenever we are building constructors). However, that fails, because the linker winds up combining all the link once sections into a single large link once section, which defeats the purpose of having link once sections in the first place. - Also, not merging link once sections in a relocateable link + Also, not merging link once sections in a relocatable link causes trouble for MIPS ELF, which relies in link once semantics to handle the .reginfo section correctly. */ @@ -5044,3 +5057,19 @@ lang_do_version_exports_section () lang_register_vers_node (command_line.version_exports_section, lang_new_vers_node (greg, lreg), NULL); } + +void +lang_add_unique (name) + const char *name; +{ + struct unique_sections *ent; + + for (ent = unique_section_list; ent; ent = ent->next) + if (strcmp (ent->name, name) == 0) + return; + + ent = (struct unique_sections *) xmalloc (sizeof *ent); + ent->name = xstrdup (name); + ent->next = unique_section_list; + unique_section_list = ent; +} diff --git a/ld/ldlang.h b/ld/ldlang.h index d327bd3dec0..ac0fd28ded8 100644 --- a/ld/ldlang.h +++ b/ld/ldlang.h @@ -1,5 +1,5 @@ /* ldlang.h - linker command language support - Copyright 1991, 92, 93, 94, 95, 96, 97, 98, 99, 2000 + Copyright 1991, 92, 93, 94, 95, 96, 97, 98, 99, 2000, 2001 Free Software Foundation, Inc. This file is part of GLD, the Gnu Linker. @@ -340,6 +340,16 @@ struct lang_nocrossrefs { extern struct lang_nocrossrefs *nocrossref_list; +/* This structure is used to hold a list of input section names which + will not match an output section in the linker script. */ + +struct unique_sections { + struct unique_sections *next; + const char *name; +}; + +extern struct unique_sections *unique_section_list; + extern lang_output_section_statement_type *abs_output_section; extern lang_statement_list_type lang_output_section_statement; extern boolean lang_has_input_file; @@ -462,5 +472,7 @@ extern struct bfd_elf_version_deps *lang_add_vers_depend extern void lang_register_vers_node PARAMS ((const char *, struct bfd_elf_version_tree *, struct bfd_elf_version_deps *)); +boolean unique_section_p PARAMS ((const char *)); +extern void lang_add_unique PARAMS ((const char *)); #endif diff --git a/ld/lexsup.c b/ld/lexsup.c index 51ffc447615..f9ef8058d8d 100644 --- a/ld/lexsup.c +++ b/ld/lexsup.c @@ -236,8 +236,8 @@ static const struct ld_option ld_options[] = 'T', N_("FILE"), N_("Read linker script"), TWO_DASHES }, { {"undefined", required_argument, NULL, 'u'}, 'u', N_("SYMBOL"), N_("Start with undefined reference to SYMBOL"), TWO_DASHES }, - { {"unique", no_argument, NULL, OPTION_UNIQUE}, - '\0', NULL, N_("Don't merge orphan sections with the same name"), TWO_DASHES }, + { {"unique", optional_argument, NULL, OPTION_UNIQUE}, + '\0', N_("[=SECTION]"), N_("Don't merge input [SECTION | orphan] sections"), TWO_DASHES }, { {"Ur", no_argument, NULL, OPTION_UR}, '\0', NULL, N_("Build global constructor/destructor tables"), ONE_DASH }, { {"version", no_argument, NULL, OPTION_VERSION}, @@ -965,7 +965,10 @@ parse_args (argc, argv) ldlang_add_undef (optarg); break; case OPTION_UNIQUE: - config.unique_orphan_sections = true; + if (optarg != NULL) + lang_add_unique (optarg); + else + config.unique_orphan_sections = true; break; case OPTION_VERBOSE: ldversion (1); -- 2.30.2