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>
* 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! */
/* ${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

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
@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

View File

@ -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;
}

View File

@ -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

View File

@ -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);