aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ld/ChangeLog22
-rw-r--r--ld/emultempl/elf32.em44
-rw-r--r--ld/ld.texinfo16
-rw-r--r--ld/ldlang.c65
-rw-r--r--ld/ldlang.h14
-rw-r--r--ld/lexsup.c9
6 files changed, 119 insertions, 51 deletions
diff --git a/ld/ChangeLog b/ld/ChangeLog
index 1452dec..edab167 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,25 @@
+2001-01-14 Alan Modra <alan@linuxcare.com.au>
+
+ * 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 <nickc@redhat.com>
* lexsup.c (parse_args): Remove spurious white space.
diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em
index 492953d..417ac4c 100644
--- a/ld/emultempl/elf32.em
+++ b/ld/emultempl/elf32.em
@@ -7,7 +7,7 @@ cat >e${EMULATION_NAME}.c <<EOF
/* This file is is generated by a shell script. DO NOT EDIT! */
/* ${ELFSIZE} bit ELF emulation code for ${EMULATION_NAME}
- Copyright (C) 1991, 93, 94, 95, 96, 97, 98, 99, 2000
+ Copyright (C) 1991, 93, 94, 95, 96, 97, 98, 99, 2000, 2001
Free Software Foundation, Inc.
Written by Steve Chamberlain <sac@cygnus.com>
ELF support by Ian Lance Taylor <ian@cygnus.com>
@@ -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 5c8a595..e897d44 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 532b23d..4b822b3 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 d327bd3..ac0fd28 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 51ffc44..f9ef805 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);