Extend "ld --unique" functionality.

This commit is contained in:
Alan Modra
2001-01-14 04:36:35 +00:00
parent b9d79e0379
commit 577a062318
6 changed files with 119 additions and 51 deletions

View File

@ -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> 2001-01-13 Nick Clifton <nickc@redhat.com>
* lexsup.c (parse_args): Remove spurious white space. * lexsup.c (parse_args): Remove spurious white space.

View File

@ -7,7 +7,7 @@ cat >e${EMULATION_NAME}.c <<EOF
/* This file is is generated by a shell script. DO NOT EDIT! */ /* This file is is generated by a shell script. DO NOT EDIT! */
/* ${ELFSIZE} bit ELF emulation code for ${EMULATION_NAME} /* ${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. Free Software Foundation, Inc.
Written by Steve Chamberlain <sac@cygnus.com> Written by Steve Chamberlain <sac@cygnus.com>
ELF support by Ian Lance Taylor <ian@cygnus.com> ELF support by Ian Lance Taylor <ian@cygnus.com>
@ -527,13 +527,28 @@ gld${EMULATION_NAME}_check_needed (s)
if (global_found) if (global_found)
return; return;
if (s->filename != NULL if (s->filename != NULL)
&& strcmp (s->filename, global_needed->name) == 0) {
const char *f;
if (strcmp (s->filename, global_needed->name) == 0)
{ {
global_found = true; global_found = true;
return; 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) if (s->the_bfd != NULL)
{ {
const char *soname; const char *soname;
@ -546,21 +561,6 @@ gld${EMULATION_NAME}_check_needed (s)
return; 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 EOF
@ -1030,7 +1030,7 @@ gld${EMULATION_NAME}_place_orphan (file, s)
secname = bfd_get_section_name (s->owner, 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. */ /* Look through the script to see where to place this section. */
os = lang_output_section_find (secname); os = lang_output_section_find (secname);
@ -1075,7 +1075,7 @@ gld${EMULATION_NAME}_place_orphan (file, s)
if ((s->flags & SEC_ALLOC) == 0) if ((s->flags & SEC_ALLOC) == 0)
; ;
else if ((s->flags & SEC_LOAD) != 0 else if ((s->flags & SEC_LOAD) != 0
&& strncmp (secname, ".note", 4) == 0 && strncmp (secname, ".note", 5) == 0
&& HAVE_SECTION (hold_interp, ".interp")) && HAVE_SECTION (hold_interp, ".interp"))
place = &hold_interp; place = &hold_interp;
else if ((s->flags & SEC_HAS_CONTENTS) == 0 else if ((s->flags & SEC_HAS_CONTENTS) == 0

View File

@ -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 be added to. Use @samp{-Ur} only for the last partial link, and
@samp{-r} for the others. @samp{-r} for the others.
@kindex --unique @kindex --unique[=@var{SECTION}]
@item --unique @item --unique[=@var{SECTION}]
Creates a separate output section for every orphan input section. This Creates a separate output section for every input section matching
option prevents the normal merging of orphan input sections with the same @var{SECTION}, or if the optional wildcard @var{SECTION} argument is
name. An orphan section is one not specifically mentioned in a linker missing, for every orphan input section. An orphan section is one not
script, so this option along with a custom linker script allows any specifically mentioned in a linker script. You may use this option
selection of input sections to be merged while others are kept separate. 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
@kindex -V @kindex -V

View File

@ -1,5 +1,5 @@
/* Linker command language support. /* 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. Free Software Foundation, Inc.
This file is part of GLD, the Gnu Linker. This file is part of GLD, the Gnu Linker.
@ -186,6 +186,7 @@ boolean had_output_filename = false;
boolean lang_float_flag = false; boolean lang_float_flag = false;
boolean delete_output_file_on_failure = false; boolean delete_output_file_on_failure = false;
struct lang_nocrossrefs *nocrossref_list; struct lang_nocrossrefs *nocrossref_list;
struct unique_sections *unique_section_list;
etree_type *base; /* Relocation base - or null */ etree_type *base; /* Relocation base - or null */
@ -211,6 +212,23 @@ stat_alloc (size)
return obstack_alloc (&stat_obstack, 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. */ /* Generic traversal routines for finding matching sections. */
static void static void
@ -242,31 +260,26 @@ walk_wild_section (ptr, section, file, callback, data)
if (file->just_syms_flag == false) if (file->just_syms_flag == false)
{ {
register asection *s; register asection *s;
boolean wildcard; boolean wildcard = false;
if (section == NULL) if (section != NULL)
wildcard = false;
else
wildcard = wildcardp (section); wildcard = wildcardp (section);
for (s = file->the_bfd->sections; s != NULL; s = s->next) for (s = file->the_bfd->sections; s != NULL; s = s->next)
{ {
boolean match; boolean match;
const char *sname = bfd_get_section_name (file->the_bfd, s);
if (section == NULL) if (section == NULL)
match = true; match = true;
else if (wildcard)
match = fnmatch (section, sname, 0) == 0 ? true : false;
else else
{ match = strcmp (section, sname) == 0 ? true : false;
const char *name;
name = bfd_get_section_name (file->the_bfd, s); /* If this is a wild-card output section statement, exclude
if (wildcard) sections that match UNIQUE_SECTION_LIST. */
match = fnmatch (section, name, 0) == 0 ? true : false; if (match && (data == NULL || !unique_section_p (sname)))
else
match = strcmp (section, name) == 0 ? true : false;
}
if (match)
(*callback) (ptr, s, file, data); (*callback) (ptr, s, file, data);
} }
} }
@ -925,20 +938,20 @@ section_already_linked (abfd, sec, data)
if ((flags & SEC_LINK_ONCE) == 0) if ((flags & SEC_LINK_ONCE) == 0)
return; 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 copying relocations in other sections that refer to local symbols
in the section being discarded. Those relocations will have to in the section being discarded. Those relocations will have to
be converted somehow; as of this writing I'm not sure that any of be converted somehow; as of this writing I'm not sure that any of
the backends handle that correctly. the backends handle that correctly.
It is tempting to instead not discard link once sections when 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, whenever we are building constructors). However, that fails,
because the linker winds up combining all the link once sections because the linker winds up combining all the link once sections
into a single large link once section, which defeats the purpose into a single large link once section, which defeats the purpose
of having link once sections in the first place. 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 causes trouble for MIPS ELF, which relies in link once semantics
to handle the .reginfo section correctly. */ 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_register_vers_node (command_line.version_exports_section,
lang_new_vers_node (greg, lreg), NULL); 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;
}

View File

@ -1,5 +1,5 @@
/* ldlang.h - linker command language support /* 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. Free Software Foundation, Inc.
This file is part of GLD, the Gnu Linker. This file is part of GLD, the Gnu Linker.
@ -340,6 +340,16 @@ struct lang_nocrossrefs {
extern struct lang_nocrossrefs *nocrossref_list; 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_output_section_statement_type *abs_output_section;
extern lang_statement_list_type lang_output_section_statement; extern lang_statement_list_type lang_output_section_statement;
extern boolean lang_has_input_file; 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 extern void lang_register_vers_node
PARAMS ((const char *, struct bfd_elf_version_tree *, PARAMS ((const char *, struct bfd_elf_version_tree *,
struct bfd_elf_version_deps *)); struct bfd_elf_version_deps *));
boolean unique_section_p PARAMS ((const char *));
extern void lang_add_unique PARAMS ((const char *));
#endif #endif

View File

@ -236,8 +236,8 @@ static const struct ld_option ld_options[] =
'T', N_("FILE"), N_("Read linker script"), TWO_DASHES }, 'T', N_("FILE"), N_("Read linker script"), TWO_DASHES },
{ {"undefined", required_argument, NULL, 'u'}, { {"undefined", required_argument, NULL, 'u'},
'u', N_("SYMBOL"), N_("Start with undefined reference to SYMBOL"), TWO_DASHES }, 'u', N_("SYMBOL"), N_("Start with undefined reference to SYMBOL"), TWO_DASHES },
{ {"unique", no_argument, NULL, OPTION_UNIQUE}, { {"unique", optional_argument, NULL, OPTION_UNIQUE},
'\0', NULL, N_("Don't merge orphan sections with the same name"), TWO_DASHES }, '\0', N_("[=SECTION]"), N_("Don't merge input [SECTION | orphan] sections"), TWO_DASHES },
{ {"Ur", no_argument, NULL, OPTION_UR}, { {"Ur", no_argument, NULL, OPTION_UR},
'\0', NULL, N_("Build global constructor/destructor tables"), ONE_DASH }, '\0', NULL, N_("Build global constructor/destructor tables"), ONE_DASH },
{ {"version", no_argument, NULL, OPTION_VERSION}, { {"version", no_argument, NULL, OPTION_VERSION},
@ -965,6 +965,9 @@ parse_args (argc, argv)
ldlang_add_undef (optarg); ldlang_add_undef (optarg);
break; break;
case OPTION_UNIQUE: case OPTION_UNIQUE:
if (optarg != NULL)
lang_add_unique (optarg);
else
config.unique_orphan_sections = true; config.unique_orphan_sections = true;
break; break;
case OPTION_VERBOSE: case OPTION_VERBOSE: