This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Match archive:file in linker script filespecs
- From: Alan Modra <amodra at bigpond dot net dot au>
- To: binutils at sourceware dot org
- Date: Fri, 6 Jun 2008 15:01:34 +0930
- Subject: Match archive:file in linker script filespecs
This extends the linker script input section file specification to
match files within archives. I've chosen to enable this only for SPU,
where we need the feature to conveniently specify sections for
overlays. (For instance, libgfortran contains read.o as does
newlib, and we might have read.o on the command line.) If people
think this is a good idea the feature can be enabled on all targets,
and possibly for other filespecs such as those in EXCLUDE_FILE.
"archive:file" matches "file" within "archive"
"archive:" matches the whole "archive"
":file" matches "file" but not one in an archive
Either one or both of "archive" and "file" can contain shell wildcards.
include/
* bfdlink.h (struct bfd_link_info): Add "path_separator".
bfd/
* elf32-spu.c (spu_elf_auto_overlay): Relax requirement that
file names be unique. Specify archive:path in overlay script.
ld/
* ldlang.c (name_match): New function.
(unique_section_p, walk_wild_consider_section): Use it here.
(walk_wild_section_general): And here.
(archive_path): New function.
(walk_wild): Match archive:path filespecs.
(open_input_bfds): Don't load archive:path files.
* emultempl/spuelf.em (choose_target): Set path_separator.
This one is unrelated but didn't seem worth a separate email.
* emulparams/elf32_spu.sh: Add ._ea.* sections to ._ea output.
Index: include/bfdlink.h
===================================================================
RCS file: /cvs/src/src/include/bfdlink.h,v
retrieving revision 1.71
diff -u -p -r1.71 bfdlink.h
--- include/bfdlink.h 15 Feb 2008 03:35:51 -0000 1.71
+++ include/bfdlink.h 6 Jun 2008 01:53:15 -0000
@@ -372,6 +372,9 @@ struct bfd_link_info
wrap_hash. Used by PowerPC Linux for 'dot' symbols. */
char wrap_char;
+ /* Separator between archive and filename in linker script filespecs. */
+ char path_separator;
+
/* Function callbacks. */
const struct bfd_link_callbacks *callbacks;
Index: bfd/elf32-spu.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-spu.c,v
retrieving revision 1.43
diff -u -p -r1.43 elf32-spu.c
--- bfd/elf32-spu.c 4 Jun 2008 07:07:19 -0000 1.43
+++ bfd/elf32-spu.c 6 Jun 2008 02:09:39 -0000
@@ -3544,37 +3544,20 @@ spu_elf_auto_overlay (struct bfd_link_in
for (i = 1; i < bfd_count; ++i)
if (strcmp (bfd_arr[i - 1]->filename, bfd_arr[i]->filename) == 0)
{
- if (bfd_arr[i - 1]->my_archive && bfd_arr[i]->my_archive)
+ if (bfd_arr[i - 1]->my_archive == bfd_arr[i]->my_archive)
{
- if (bfd_arr[i - 1]->my_archive == bfd_arr[i]->my_archive)
+ if (bfd_arr[i - 1]->my_archive && bfd_arr[i]->my_archive)
info->callbacks->einfo (_("%s duplicated in %s\n"),
- bfd_arr[i - 1]->filename,
- bfd_arr[i - 1]->my_archive->filename);
- else
- info->callbacks->einfo (_("%s in both %s and %s\n"),
- bfd_arr[i - 1]->filename,
- bfd_arr[i - 1]->my_archive->filename,
+ bfd_arr[i]->filename,
bfd_arr[i]->my_archive->filename);
+ else
+ info->callbacks->einfo (_("%s duplicated\n"),
+ bfd_arr[i]->filename);
+ ok = FALSE;
}
- else if (bfd_arr[i - 1]->my_archive)
- info->callbacks->einfo (_("%s in %s and as an object\n"),
- bfd_arr[i - 1]->filename,
- bfd_arr[i - 1]->my_archive->filename);
- else if (bfd_arr[i]->my_archive)
- info->callbacks->einfo (_("%s in %s and as an object\n"),
- bfd_arr[i]->filename,
- bfd_arr[i]->my_archive->filename);
- else
- info->callbacks->einfo (_("%s duplicated\n"),
- bfd_arr[i]->filename);
- ok = FALSE;
}
if (!ok)
{
- /* FIXME: modify plain object files from foo.o to ./foo.o
- and emit EXCLUDE_FILE to handle the duplicates in
- archives. There is a pathological case we can't handle:
- We may have duplicate file names within a single archive. */
info->callbacks->einfo (_("sorry, no support for duplicate "
"object files in auto-overlay script\n"));
bfd_set_error (bfd_error_bad_value);
@@ -3750,9 +3733,11 @@ spu_elf_auto_overlay (struct bfd_link_in
{
asection *sec = ovly_sections[2 * j];
- if (fprintf (script, " [%c]%s (%s)\n",
- sec->owner->filename[0],
- sec->owner->filename + 1,
+ if (fprintf (script, " %s%c%s (%s)\n",
+ (sec->owner->my_archive != NULL
+ ? sec->owner->my_archive->filename : ""),
+ info->path_separator,
+ sec->owner->filename,
sec->name) <= 0)
goto file_err;
if (sec->segment_mark)
@@ -3762,9 +3747,11 @@ spu_elf_auto_overlay (struct bfd_link_in
{
struct function_info *call_fun = call->fun;
sec = call_fun->sec;
- if (fprintf (script, " [%c]%s (%s)\n",
- sec->owner->filename[0],
- sec->owner->filename + 1,
+ if (fprintf (script, " %s%c%s (%s)\n",
+ (sec->owner->my_archive != NULL
+ ? sec->owner->my_archive->filename : ""),
+ info->path_separator,
+ sec->owner->filename,
sec->name) <= 0)
goto file_err;
for (call = call_fun->call_list; call; call = call->next)
@@ -3777,10 +3764,13 @@ spu_elf_auto_overlay (struct bfd_link_in
for (j = base; j < i; j++)
{
asection *sec = ovly_sections[2 * j + 1];
- if (sec != NULL && fprintf (script, " [%c]%s (%s)\n",
- sec->owner->filename[0],
- sec->owner->filename + 1,
- sec->name) <= 0)
+ if (sec != NULL
+ && fprintf (script, " %s%c%s (%s)\n",
+ (sec->owner->my_archive != NULL
+ ? sec->owner->my_archive->filename : ""),
+ info->path_separator,
+ sec->owner->filename,
+ sec->name) <= 0)
goto file_err;
sec = ovly_sections[2 * j];
@@ -3791,10 +3781,13 @@ spu_elf_auto_overlay (struct bfd_link_in
{
struct function_info *call_fun = call->fun;
sec = call_fun->rodata;
- if (sec != NULL && fprintf (script, " [%c]%s (%s)\n",
- sec->owner->filename[0],
- sec->owner->filename + 1,
- sec->name) <= 0)
+ if (sec != NULL
+ && fprintf (script, " %s%c%s (%s)\n",
+ (sec->owner->my_archive != NULL
+ ? sec->owner->my_archive->filename : ""),
+ info->path_separator,
+ sec->owner->filename,
+ sec->name) <= 0)
goto file_err;
for (call = call_fun->call_list; call; call = call->next)
if (call->is_pasted)
Index: ld/ldlang.c
===================================================================
RCS file: /cvs/src/src/ld/ldlang.c,v
retrieving revision 1.286
diff -u -p -r1.286 ldlang.c
--- ld/ldlang.c 31 May 2008 16:35:56 -0000 1.286
+++ ld/ldlang.c 6 Jun 2008 01:53:19 -0000
@@ -134,6 +134,38 @@ stat_alloc (size_t size)
return obstack_alloc (&stat_obstack, size);
}
+static int
+name_match (const char *pattern, const char *name)
+{
+ if (wildcardp (pattern))
+ return fnmatch (pattern, name, 0);
+ return strcmp (pattern, name);
+}
+
+/* If PATTERN is of the form archive:file, return a pointer to the
+ separator. If not, return NULL. */
+
+static char *
+archive_path (const char *pattern)
+{
+ char *p = NULL;
+
+ if (link_info.path_separator == 0)
+ return p;
+
+ p = strchr (pattern, link_info.path_separator);
+#ifdef HAVE_DOS_BASED_FILE_SYSTEM
+ if (p == NULL || link_info.path_separator != ':')
+ return p;
+
+ /* Assume a match on the second char is part of drive specifier,
+ as in "c:\silly.dos". */
+ if (p == pattern + 1)
+ p = strchr (p + 1, link_info.path_separator);
+#endif
+ return p;
+}
+
bfd_boolean
unique_section_p (const asection *sec)
{
@@ -147,12 +179,8 @@ unique_section_p (const asection *sec)
secnam = sec->name;
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;
- }
+ if (name_match (unam->name, secnam) == 0)
+ return TRUE;
return FALSE;
}
@@ -175,17 +203,12 @@ walk_wild_consider_section (lang_wild_st
bfd_boolean skip = FALSE;
struct name_list *list_tmp;
- /* Don't process sections from files which were
- excluded. */
+ /* Don't process sections from files which were excluded. */
for (list_tmp = sec->spec.exclude_name_list;
list_tmp;
list_tmp = list_tmp->next)
{
- bfd_boolean is_wildcard = wildcardp (list_tmp->name);
- if (is_wildcard)
- skip = fnmatch (list_tmp->name, file->filename, 0) == 0;
- else
- skip = strcmp (list_tmp->name, file->filename) == 0;
+ skip = name_match (list_tmp->name, file->filename) == 0;
/* If this file is part of an archive, and the archive is
excluded, exclude this file. */
@@ -193,13 +216,8 @@ walk_wild_consider_section (lang_wild_st
&& file->the_bfd->my_archive != NULL
&& file->the_bfd->my_archive->filename != NULL)
{
- if (is_wildcard)
- skip = fnmatch (list_tmp->name,
- file->the_bfd->my_archive->filename,
- 0) == 0;
- else
- skip = strcmp (list_tmp->name,
- file->the_bfd->my_archive->filename) == 0;
+ skip = name_match (list_tmp->name,
+ file->the_bfd->my_archive->filename) == 0;
}
if (skip)
@@ -236,10 +254,7 @@ walk_wild_section_general (lang_wild_sta
{
const char *sname = bfd_get_section_name (file->the_bfd, s);
- if (wildcardp (sec->spec.name))
- skip = fnmatch (sec->spec.name, sname, 0) != 0;
- else
- skip = strcmp (sec->spec.name, sname) != 0;
+ skip = name_match (sec->spec.name, sname) != 0;
}
if (!skip)
@@ -780,6 +795,7 @@ static void
walk_wild (lang_wild_statement_type *s, callback_t callback, void *data)
{
const char *file_spec = s->filename;
+ char *p;
if (file_spec == NULL)
{
@@ -789,6 +805,29 @@ walk_wild (lang_wild_statement_type *s,
walk_wild_file (s, f, callback, data);
}
}
+ else if ((p = archive_path (file_spec)) != NULL)
+ {
+ LANG_FOR_EACH_INPUT_STATEMENT (f)
+ {
+ if ((*(p + 1) == 0
+ || name_match (p + 1, f->filename) == 0)
+ && ((p != file_spec)
+ == (f->the_bfd != NULL && f->the_bfd->my_archive != NULL)))
+ {
+ bfd_boolean skip = FALSE;
+
+ if (p != file_spec)
+ {
+ const char *aname = f->the_bfd->my_archive->filename;
+ *p = 0;
+ skip = name_match (file_spec, aname) != 0;
+ *p = link_info.path_separator;
+ }
+ if (!skip)
+ walk_wild_file (s, f, callback, data);
+ }
+ }
+ }
else if (wildcardp (file_spec))
{
LANG_FOR_EACH_INPUT_STATEMENT (f)
@@ -2931,7 +2970,8 @@ open_input_bfds (lang_statement_union_ty
case lang_wild_statement_enum:
/* Maybe we should load the file's symbols. */
if (s->wild_statement.filename
- && ! wildcardp (s->wild_statement.filename))
+ && !wildcardp (s->wild_statement.filename)
+ && !archive_path (s->wild_statement.filename))
lookup_name (s->wild_statement.filename);
open_input_bfds (s->wild_statement.children.head, force);
break;
Index: ld/emulparams/elf32_spu.sh
===================================================================
RCS file: /cvs/src/src/ld/emulparams/elf32_spu.sh,v
retrieving revision 1.4
diff -u -p -r1.4 elf32_spu.sh
--- ld/emulparams/elf32_spu.sh 7 May 2008 14:46:44 -0000 1.4
+++ ld/emulparams/elf32_spu.sh 6 Jun 2008 01:53:19 -0000
@@ -18,4 +18,4 @@ MAXPAGESIZE=0x80
DATA_ADDR="ALIGN(${MAXPAGESIZE})"
OTHER_BSS_SECTIONS=".toe ALIGN(128) : { *(.toe) } = 0"
OTHER_SECTIONS=".note.spu_name 0 : { KEEP(*(.note.spu_name)) }
- ._ea 0 : { KEEP(*(._ea)) }"
+ ._ea 0 : { KEEP(*(._ea)) KEEP(*(._ea.*)) }"
Index: ld/emultempl/spuelf.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/spuelf.em,v
retrieving revision 1.20
diff -u -p -r1.20 spuelf.em
--- ld/emultempl/spuelf.em 4 Jun 2008 07:08:01 -0000 1.20
+++ ld/emultempl/spuelf.em 6 Jun 2008 01:53:22 -0000
@@ -350,6 +350,7 @@ gld${EMULATION_NAME}_finish (void)
static char *
gld${EMULATION_NAME}_choose_target (int argc, char *argv[])
{
+ link_info.path_separator = ':';
my_argc = argc;
my_argv = argv;
return ldemul_default_target (argc, argv);
--
Alan Modra
Australia Development Lab, IBM