* NEWS: Mention archive:path patterns.

* ld.texinfo: Likewise.
	* ldlang.c: Formatting throughout.
	(archive_path): Only assume "[A-Za-z]:" is a dos drive.
	(input_statement_is_archive_path): New function, extracted from..
	(walk_wild): ..here.
	(walk_wild_consider_section): Match archive:path here too.
	(init_map_userdata, sort_def_symbol): Convert to ISO C.
	* ldmain.c (main): Set link_info.path_separator.
	* emultempl/spuelf.em (choose_target): Don't set it here.
This commit is contained in:
Alan Modra
2008-06-07 11:35:46 +00:00
parent 6efef468be
commit 967928e916
6 changed files with 178 additions and 127 deletions

View File

@ -1,3 +1,16 @@
2008-06-07 Alan Modra <amodra@bigpond.net.au>
* NEWS: Mention archive:path patterns.
* ld.texinfo: Likewise.
* ldlang.c: Formatting throughout.
(archive_path): Only assume "[A-Za-z]:" is a dos drive.
(input_statement_is_archive_path): New function, extracted from..
(walk_wild): ..here.
(walk_wild_consider_section): Match archive:path here too.
(init_map_userdata, sort_def_symbol): Convert to ISO C.
* ldmain.c (main): Set link_info.path_separator.
* emultempl/spuelf.em (choose_target): Don't set it here.
2008-06-06 Alan Modra <amodra@bigpond.net.au> 2008-06-06 Alan Modra <amodra@bigpond.net.au>
* ldlang.c (name_match): New function. * ldlang.c (name_match): New function.

View File

@ -1,4 +1,7 @@
-*- text -*- -*- text -*-
* Linker script input section filespecs may now specify a file within an
archive by writing "archive:file".
* The --sort-common switch now has an optional argument which specifies the * The --sort-common switch now has an optional argument which specifies the
direction of sorting. direction of sorting.

View File

@ -350,7 +350,6 @@ gld${EMULATION_NAME}_finish (void)
static char * static char *
gld${EMULATION_NAME}_choose_target (int argc, char *argv[]) gld${EMULATION_NAME}_choose_target (int argc, char *argv[])
{ {
link_info.path_separator = ':';
my_argc = argc; my_argc = argc;
my_argv = argv; my_argv = argv;
return ldemul_default_target (argc, argv); return ldemul_default_target (argc, argv);

View File

@ -3431,6 +3431,29 @@ needs to be at a particular location in memory. For example:
data.o(.data) data.o(.data)
@end smallexample @end smallexample
You can also specify files within archives by writing a pattern
matching the archive, a colon, then the pattern matching the file,
with no whitespace around the colon.
@table @samp
@item archive:file
matches file within archive
@item archive:
matches the whole archive
@item :file
matches file but not one in an archive
@end table
Either one or both of @samp{archive} and @samp{file} can contain shell
wildcards. On DOS based file systems, the linker will assume that a
single letter followed by a colon is a drive specifier, so
@samp{c:myfile.o} is a simple file specification, not @samp{myfile.o}
within an archive called @samp{c}. @samp{archive:file} filespecs may
also be used within an @code{EXCLUDE_FILE} list, but may not appear in
other linker script contexts. For instance, you cannot extract a file
from an archive by using @samp{archive:file} in an @code{INPUT}
command.
If you use a file name without a list of sections, then all sections in If you use a file name without a list of sections, then all sections in
the input file will be included in the output section. This is not the input file will be included in the output section. This is not
commonly done, but it may by useful on occasion. For example: commonly done, but it may by useful on occasion. For example:
@ -3438,7 +3461,8 @@ commonly done, but it may by useful on occasion. For example:
data.o data.o
@end smallexample @end smallexample
When you use a file name which does not contain any wild card When you use a file name which is not an @samp{archive:file} specifier
and does not contain any wild card
characters, the linker will first see if you also specified the file characters, the linker will first see if you also specified the file
name on the linker command line or in an @code{INPUT} command. If you name on the linker command line or in an @code{INPUT} command. If you
did not, the linker will attempt to open the file as an input file, as did not, the linker will attempt to open the file as an input file, as

View File

@ -160,12 +160,39 @@ archive_path (const char *pattern)
/* Assume a match on the second char is part of drive specifier, /* Assume a match on the second char is part of drive specifier,
as in "c:\silly.dos". */ as in "c:\silly.dos". */
if (p == pattern + 1) if (p == pattern + 1 && ISALPHA (*pattern))
p = strchr (p + 1, link_info.path_separator); p = strchr (p + 1, link_info.path_separator);
#endif #endif
return p; return p;
} }
/* Given that FILE_SPEC results in a non-NULL SEP result from archive_path,
return whether F matches FILE_SPEC. */
static bfd_boolean
input_statement_is_archive_path (const char *file_spec, char *sep,
lang_input_statement_type *f)
{
bfd_boolean match = FALSE;
if ((*(sep + 1) == 0
|| name_match (sep + 1, f->filename) == 0)
&& ((sep != file_spec)
== (f->the_bfd != NULL && f->the_bfd->my_archive != NULL)))
{
match = TRUE;
if (sep != file_spec)
{
const char *aname = f->the_bfd->my_archive->filename;
*sep = 0;
match = name_match (file_spec, aname) == 0;
*sep = link_info.path_separator;
}
}
return match;
}
bfd_boolean bfd_boolean
unique_section_p (const asection *sec) unique_section_p (const asection *sec)
{ {
@ -200,7 +227,6 @@ walk_wild_consider_section (lang_wild_statement_type *ptr,
callback_t callback, callback_t callback,
void *data) void *data)
{ {
bfd_boolean skip = FALSE;
struct name_list *list_tmp; struct name_list *list_tmp;
/* Don't process sections from files which were excluded. */ /* Don't process sections from files which were excluded. */
@ -208,24 +234,28 @@ walk_wild_consider_section (lang_wild_statement_type *ptr,
list_tmp; list_tmp;
list_tmp = list_tmp->next) list_tmp = list_tmp->next)
{ {
skip = name_match (list_tmp->name, file->filename) == 0; char *p = archive_path (list_tmp->name);
/* If this file is part of an archive, and the archive is if (p != NULL)
excluded, exclude this file. */
if (! skip && file->the_bfd != NULL
&& file->the_bfd->my_archive != NULL
&& file->the_bfd->my_archive->filename != NULL)
{ {
skip = name_match (list_tmp->name, if (input_statement_is_archive_path (list_tmp->name, p, file))
file->the_bfd->my_archive->filename) == 0; return;
} }
if (skip) else if (name_match (list_tmp->name, file->filename) == 0)
break; return;
/* FIXME: Perhaps remove the following at some stage? Matching
unadorned archives like this was never documented and has
been superceded by the archive:path syntax. */
else if (file->the_bfd != NULL
&& file->the_bfd->my_archive != NULL
&& name_match (list_tmp->name,
file->the_bfd->my_archive->filename) == 0)
return;
} }
if (!skip) (*callback) (ptr, sec, s, file, data);
(*callback) (ptr, sec, s, file, data);
} }
/* Lowest common denominator routine that can handle everything correctly, /* Lowest common denominator routine that can handle everything correctly,
@ -809,23 +839,8 @@ walk_wild (lang_wild_statement_type *s, callback_t callback, void *data)
{ {
LANG_FOR_EACH_INPUT_STATEMENT (f) LANG_FOR_EACH_INPUT_STATEMENT (f)
{ {
if ((*(p + 1) == 0 if (input_statement_is_archive_path (file_spec, p, f))
|| name_match (p + 1, f->filename) == 0) walk_wild_file (s, f, callback, data);
&& ((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)) else if (wildcardp (file_spec))
@ -1873,10 +1888,9 @@ lang_map (void)
} }
static void static void
init_map_userdata (abfd, sec, data) init_map_userdata (bfd *abfd ATTRIBUTE_UNUSED,
bfd *abfd ATTRIBUTE_UNUSED; asection *sec,
asection *sec; void *data ATTRIBUTE_UNUSED)
void *data ATTRIBUTE_UNUSED;
{ {
fat_section_userdata_type *new_data fat_section_userdata_type *new_data
= ((fat_section_userdata_type *) (stat_alloc = ((fat_section_userdata_type *) (stat_alloc
@ -1888,9 +1902,8 @@ init_map_userdata (abfd, sec, data)
} }
static bfd_boolean static bfd_boolean
sort_def_symbol (hash_entry, info) sort_def_symbol (struct bfd_link_hash_entry *hash_entry,
struct bfd_link_hash_entry *hash_entry; void *info ATTRIBUTE_UNUSED)
void *info ATTRIBUTE_UNUSED;
{ {
if (hash_entry->type == bfd_link_hash_defined if (hash_entry->type == bfd_link_hash_defined
|| hash_entry->type == bfd_link_hash_defweak) || hash_entry->type == bfd_link_hash_defweak)
@ -2493,7 +2506,7 @@ load_symbols (lang_input_statement_type *entry,
} }
else if (err != bfd_error_file_not_recognized else if (err != bfd_error_file_not_recognized
|| place == NULL) || place == NULL)
einfo (_("%F%B: file not recognized: %E\n"), entry->the_bfd); einfo (_("%F%B: file not recognized: %E\n"), entry->the_bfd);
else else
bad_load = FALSE; bad_load = FALSE;
@ -2741,7 +2754,7 @@ closest_target_match (const bfd_target *target, void *data)
return 0; return 0;
/* Ignore generic big and little endian elf vectors. */ /* Ignore generic big and little endian elf vectors. */
if ( strcmp (target->name, "elf32-big") == 0 if (strcmp (target->name, "elf32-big") == 0
|| strcmp (target->name, "elf64-big") == 0 || strcmp (target->name, "elf64-big") == 0
|| strcmp (target->name, "elf32-little") == 0 || strcmp (target->name, "elf32-little") == 0
|| strcmp (target->name, "elf64-little") == 0) || strcmp (target->name, "elf64-little") == 0)
@ -3175,28 +3188,28 @@ check_input_sections
for (; s != (lang_statement_union_type *) NULL; s = s->header.next) for (; s != (lang_statement_union_type *) NULL; s = s->header.next)
{ {
switch (s->header.type) switch (s->header.type)
{ {
case lang_wild_statement_enum: case lang_wild_statement_enum:
walk_wild (&s->wild_statement, check_section_callback, walk_wild (&s->wild_statement, check_section_callback,
output_section_statement); output_section_statement);
if (! output_section_statement->all_input_readonly) if (! output_section_statement->all_input_readonly)
return; return;
break; break;
case lang_constructors_statement_enum: case lang_constructors_statement_enum:
check_input_sections (constructor_list.head, check_input_sections (constructor_list.head,
output_section_statement); output_section_statement);
if (! output_section_statement->all_input_readonly) if (! output_section_statement->all_input_readonly)
return; return;
break; break;
case lang_group_statement_enum: case lang_group_statement_enum:
check_input_sections (s->group_statement.children.head, check_input_sections (s->group_statement.children.head,
output_section_statement); output_section_statement);
if (! output_section_statement->all_input_readonly) if (! output_section_statement->all_input_readonly)
return; return;
break; break;
default: default:
break; break;
} }
} }
} }
@ -3354,7 +3367,6 @@ map_input_to_output_sections
break; break;
case lang_address_statement_enum: case lang_address_statement_enum:
/* Mark the specified section with the supplied address. /* Mark the specified section with the supplied address.
If this section was actually a segment marker, then the If this section was actually a segment marker, then the
directive is ignored if the linker script explicitly directive is ignored if the linker script explicitly
processed the segment marker. Originally, the linker processed the segment marker. Originally, the linker
@ -3778,10 +3790,9 @@ print_assignment (lang_assignment_statement_type *assignment,
static void static void
print_input_statement (lang_input_statement_type *statm) print_input_statement (lang_input_statement_type *statm)
{ {
if ((statm->filename != NULL) if (statm->filename != NULL
&& ((statm->the_bfd == NULL) && (statm->the_bfd == NULL
|| || (statm->the_bfd->flags & BFD_LINKER_CREATED) == 0))
((statm->the_bfd->flags & BFD_LINKER_CREATED) == 0)))
fprintf (config.map_file, "LOAD %s\n", statm->filename); fprintf (config.map_file, "LOAD %s\n", statm->filename);
} }
@ -5047,8 +5058,8 @@ lang_size_sections (bfd_boolean *relax, bfd_boolean check_regions)
expld.dataseg.base += (-expld.dataseg.relro_end expld.dataseg.base += (-expld.dataseg.relro_end
& (expld.dataseg.pagesize - 1)); & (expld.dataseg.pagesize - 1));
/* Compute the expected PT_GNU_RELRO segment end. */ /* Compute the expected PT_GNU_RELRO segment end. */
relro_end = (expld.dataseg.relro_end + expld.dataseg.pagesize - 1) relro_end = ((expld.dataseg.relro_end + expld.dataseg.pagesize - 1)
& ~(expld.dataseg.pagesize - 1); & ~(expld.dataseg.pagesize - 1));
if (old_min_base + maxpage < expld.dataseg.base) if (old_min_base + maxpage < expld.dataseg.base)
{ {
expld.dataseg.base -= maxpage; expld.dataseg.base -= maxpage;
@ -5486,19 +5497,19 @@ lang_common (void)
unsigned int power; unsigned int power;
if (config.sort_common == sort_descending) if (config.sort_common == sort_descending)
{ {
for (power = 4; power > 0; power--) for (power = 4; power > 0; power--)
bfd_link_hash_traverse (link_info.hash, lang_one_common, &power); bfd_link_hash_traverse (link_info.hash, lang_one_common, &power);
power = 0; power = 0;
bfd_link_hash_traverse (link_info.hash, lang_one_common, &power); bfd_link_hash_traverse (link_info.hash, lang_one_common, &power);
} }
else else
{ {
for (power = 0; power <= 4; power++) for (power = 0; power <= 4; power++)
bfd_link_hash_traverse (link_info.hash, lang_one_common, &power); bfd_link_hash_traverse (link_info.hash, lang_one_common, &power);
power = UINT_MAX; power = UINT_MAX;
bfd_link_hash_traverse (link_info.hash, lang_one_common, &power); bfd_link_hash_traverse (link_info.hash, lang_one_common, &power);
} }
} }
@ -5523,7 +5534,7 @@ lang_one_common (struct bfd_link_hash_entry *h, void *info)
&& power_of_two < *(unsigned int *) info) && power_of_two < *(unsigned int *) info)
return TRUE; return TRUE;
else if (config.sort_common == sort_ascending else if (config.sort_common == sort_ascending
&& power_of_two > *(unsigned int *) info) && power_of_two > *(unsigned int *) info)
return TRUE; return TRUE;
section = h->u.c.p->section; section = h->u.c.p->section;
@ -5801,9 +5812,9 @@ lang_enter_output_section_statement (const char *output_section_statement_name,
{ {
lang_output_section_statement_type *os; lang_output_section_statement_type *os;
os = lang_output_section_statement_lookup_1 (output_section_statement_name, os = lang_output_section_statement_lookup_1 (output_section_statement_name,
constraint); constraint);
current_section = os; current_section = os;
/* Make next things chain into subchain of this. */ /* Make next things chain into subchain of this. */
@ -6948,44 +6959,44 @@ lang_vers_match (struct bfd_elf_version_expr_head *head,
switch (prev ? prev->mask : 0) switch (prev ? prev->mask : 0)
{ {
case 0: case 0:
if (head->mask & BFD_ELF_VERSION_C_TYPE) if (head->mask & BFD_ELF_VERSION_C_TYPE)
{ {
e.symbol = sym; e.symbol = sym;
expr = htab_find (head->htab, &e); expr = htab_find (head->htab, &e);
while (expr && strcmp (expr->symbol, sym) == 0) while (expr && strcmp (expr->symbol, sym) == 0)
if (expr->mask == BFD_ELF_VERSION_C_TYPE) if (expr->mask == BFD_ELF_VERSION_C_TYPE)
goto out_ret; goto out_ret;
else else
expr = expr->next; expr = expr->next;
} }
/* Fallthrough */ /* Fallthrough */
case BFD_ELF_VERSION_C_TYPE: case BFD_ELF_VERSION_C_TYPE:
if (head->mask & BFD_ELF_VERSION_CXX_TYPE) if (head->mask & BFD_ELF_VERSION_CXX_TYPE)
{ {
e.symbol = cxx_sym; e.symbol = cxx_sym;
expr = htab_find (head->htab, &e); expr = htab_find (head->htab, &e);
while (expr && strcmp (expr->symbol, cxx_sym) == 0) while (expr && strcmp (expr->symbol, cxx_sym) == 0)
if (expr->mask == BFD_ELF_VERSION_CXX_TYPE) if (expr->mask == BFD_ELF_VERSION_CXX_TYPE)
goto out_ret; goto out_ret;
else else
expr = expr->next; expr = expr->next;
} }
/* Fallthrough */ /* Fallthrough */
case BFD_ELF_VERSION_CXX_TYPE: case BFD_ELF_VERSION_CXX_TYPE:
if (head->mask & BFD_ELF_VERSION_JAVA_TYPE) if (head->mask & BFD_ELF_VERSION_JAVA_TYPE)
{ {
e.symbol = java_sym; e.symbol = java_sym;
expr = htab_find (head->htab, &e); expr = htab_find (head->htab, &e);
while (expr && strcmp (expr->symbol, java_sym) == 0) while (expr && strcmp (expr->symbol, java_sym) == 0)
if (expr->mask == BFD_ELF_VERSION_JAVA_TYPE) if (expr->mask == BFD_ELF_VERSION_JAVA_TYPE)
goto out_ret; goto out_ret;
else else
expr = expr->next; expr = expr->next;
} }
/* Fallthrough */ /* Fallthrough */
default: default:
break; break;
} }
} }
@ -7014,7 +7025,7 @@ lang_vers_match (struct bfd_elf_version_expr_head *head,
break; break;
} }
out_ret: out_ret:
if (cxx_sym != sym) if (cxx_sym != sym)
free ((char *) cxx_sym); free ((char *) cxx_sym);
if (java_sym != sym) if (java_sym != sym)

View File

@ -276,6 +276,7 @@ main (int argc, char **argv)
link_info.relax_pass = 1; link_info.relax_pass = 1;
link_info.pei386_auto_import = -1; link_info.pei386_auto_import = -1;
link_info.spare_dynamic_tags = 5; link_info.spare_dynamic_tags = 5;
link_info.path_separator = ':';
ldfile_add_arch (""); ldfile_add_arch ("");
emulation = get_emulation (argc, argv); emulation = get_emulation (argc, argv);