aboutsummaryrefslogtreecommitdiff
path: root/ld/ldlang.c
diff options
context:
space:
mode:
Diffstat (limited to 'ld/ldlang.c')
-rw-r--r--ld/ldlang.c271
1 files changed, 209 insertions, 62 deletions
diff --git a/ld/ldlang.c b/ld/ldlang.c
index d3924a0..94f58f9 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -32,6 +32,7 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307
#include "ldmisc.h"
#include "ldctor.h"
#include "ldfile.h"
+#include "fnmatch.h"
/* FORWARDS */
static lang_statement_union_type *new_statement PARAMS ((enum statement_enum,
@@ -64,7 +65,9 @@ static lang_input_statement_type *new_afile
PARAMS ((const char *name, lang_input_file_enum_type file_type,
const char *target, boolean add_to_list));
static void init_os PARAMS ((lang_output_section_statement_type *s));
+static void exp_init_os PARAMS ((etree_type *));
static void section_already_linked PARAMS ((bfd *, asection *, PTR));
+static boolean wildcardp PARAMS ((const char *));
static void wild_section PARAMS ((lang_wild_statement_type *ptr,
const char *section,
lang_input_statement_type *file,
@@ -72,6 +75,9 @@ static void wild_section PARAMS ((lang_wild_statement_type *ptr,
static lang_input_statement_type *lookup_name PARAMS ((const char *name));
static void load_symbols PARAMS ((lang_input_statement_type *entry,
lang_statement_list_type *));
+static void wild_file PARAMS ((lang_wild_statement_type *, const char *,
+ lang_input_statement_type *,
+ lang_output_section_statement_type *));
static void wild PARAMS ((lang_wild_statement_type *s,
const char *section, const char *file,
const char *target,
@@ -283,7 +289,6 @@ new_afile (name, file_type, target, add_to_list)
lang_has_input_file = true;
p->target = target;
- p->complained = false;
switch (file_type)
{
case lang_input_file_is_symbols_only_enum:
@@ -342,7 +347,6 @@ new_afile (name, file_type, target, add_to_list)
p->next_real_file = (lang_statement_union_type *) NULL;
p->next = (lang_statement_union_type *) NULL;
p->symbol_count = 0;
- p->common_output_section = (asection *) NULL;
p->dynamic = config.dynamic_link;
p->whole_archive = whole_archive;
p->loaded = false;
@@ -490,7 +494,7 @@ lang_output_section_statement_lookup (name)
lookup->next = (lang_statement_union_type *) NULL;
lookup->bfd_section = (asection *) NULL;
lookup->processed = false;
- lookup->loadable = 1;
+ lookup->sectype = normal_section;
lookup->addr_tree = (etree_type *) NULL;
lang_list_init (&lookup->children);
@@ -543,15 +547,17 @@ lang_map ()
print_statements ();
}
-/*
- *
- */
+/* Initialize an output section. */
+
static void
init_os (s)
- lang_output_section_statement_type * s;
+ lang_output_section_statement_type *s;
{
section_userdata_type *new;
+ if (s->bfd_section != NULL)
+ return;
+
if (strcmp (s->name, DISCARD_SECTION_NAME) == 0)
einfo ("%P%F: Illegal use of `%s' section", DISCARD_SECTION_NAME);
@@ -572,6 +578,59 @@ init_os (s)
/* vma to allow us to output a section through itself */
s->bfd_section->output_offset = 0;
get_userdata (s->bfd_section) = (PTR) new;
+
+ /* If there is a base address, make sure that any sections it might
+ mention are initialized. */
+ if (s->addr_tree != NULL)
+ exp_init_os (s->addr_tree);
+}
+
+/* Make sure that all output sections mentioned in an expression are
+ initialized. */
+
+static void
+exp_init_os (exp)
+ etree_type *exp;
+{
+ switch (exp->type.node_class)
+ {
+ case etree_assign:
+ exp_init_os (exp->assign.src);
+ break;
+
+ case etree_binary:
+ exp_init_os (exp->binary.lhs);
+ exp_init_os (exp->binary.rhs);
+ break;
+
+ case etree_trinary:
+ exp_init_os (exp->trinary.cond);
+ exp_init_os (exp->trinary.lhs);
+ exp_init_os (exp->trinary.rhs);
+ break;
+
+ case etree_unary:
+ exp_init_os (exp->unary.child);
+ break;
+
+ case etree_name:
+ switch (exp->type.node_code)
+ {
+ case ADDR:
+ case SIZEOF:
+ {
+ lang_output_section_statement_type *os;
+
+ os = lang_output_section_find (exp->name.name);
+ if (os != NULL && os->bfd_section == NULL)
+ init_os (os);
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
}
/* Sections marked with the SEC_LINK_ONCE flag should only be linked
@@ -661,6 +720,23 @@ section_already_linked (abfd, sec, ignore)
explicit actions, like foo.o(.text), bar.o(.text) and
foo.o(.text, .data). */
+/* Return true if the PATTERN argument is a wildcard pattern. */
+
+static boolean
+wildcardp (pattern)
+ const char *pattern;
+{
+ const char *s;
+
+ for (s = pattern; *s != '\0'; ++s)
+ if (*s == '?'
+ || *s == '\\'
+ || *s == '*'
+ || *s == '[')
+ return true;
+ return false;
+}
+
/* Add SECTION to the output section OUTPUT. Do this by creating a
lang_input_section statement which is placed at PTR. FILE is the
input file which holds SECTION. */
@@ -725,15 +801,33 @@ wild_doit (ptr, section, output, file)
SEC_NEVER_LOAD section in the middle of an otherwise loaded
section (I don't know why we want to do this, but we do).
build_link_order in ldwrite.c handles this case by turning
- the embedded SEC_NEVER_LOAD section into a fill. */
+ the embedded SEC_NEVER_LOAD section into a fill.
+
+ If final link, don't copy the SEC_LINK_ONCE flags, they've already
+ been processed. One reason to do this is that on pe format targets,
+ .text$foo sections go into .text and it's odd to see .text with
+ SEC_LINK_ONCE set. */
+
section->output_section->flags |=
- section->flags & (flagword) (~ SEC_NEVER_LOAD);
+ section->flags & (flagword) (~ (SEC_NEVER_LOAD
+ | (! link_info.relocateable
+ ? SEC_LINK_ONCE | SEC_LINK_DUPLICATES
+ : 0)));
- if (! output->loadable)
+ switch (output->sectype)
{
- /* Turn off load flag */
+ case normal_section:
+ break;
+ case dsect_section:
+ case copy_section:
+ case info_section:
+ case overlay_section:
+ output->bfd_section->flags &= ~SEC_ALLOC;
+ break;
+ case noload_section:
output->bfd_section->flags &= ~SEC_LOAD;
output->bfd_section->flags |= SEC_NEVER_LOAD;
+ break;
}
if (section->alignment_power > output->bfd_section->alignment_power)
@@ -758,9 +852,17 @@ wild_section (ptr, section, file, output)
if (file->just_syms_flag == false)
{
register asection *s;
+ boolean wildcard;
+
+ if (section == NULL)
+ wildcard = false;
+ else
+ wildcard = wildcardp (section);
for (s = file->the_bfd->sections; s != NULL; s = s->next)
{
+ boolean match;
+
/* Attach all sections named SECTION. If SECTION is NULL,
then attach all sections.
@@ -769,9 +871,19 @@ wild_section (ptr, section, file, output)
section. I did not understand that, and I took it out.
--ian@cygnus.com. */
- if (section == NULL
- || strcmp (bfd_get_section_name (file->the_bfd, s),
- section) == 0)
+ if (section == NULL)
+ match = true;
+ else
+ {
+ const char *name;
+
+ 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)
wild_doit (&ptr->children, s, output, file);
}
}
@@ -922,6 +1034,44 @@ load_symbols (entry, place)
entry->loaded = true;
}
+/* Handle a wild statement for a single file F. */
+
+static void
+wild_file (s, section, f, output)
+ lang_wild_statement_type *s;
+ const char *section;
+ lang_input_statement_type *f;
+ lang_output_section_statement_type *output;
+{
+ if (f->the_bfd == NULL
+ || ! bfd_check_format (f->the_bfd, bfd_archive))
+ wild_section (s, section, f, output);
+ else
+ {
+ bfd *member;
+
+ /* This is an archive file. We must map each member of the
+ archive separately. */
+ member = bfd_openr_next_archived_file (f->the_bfd, (bfd *) NULL);
+ while (member != NULL)
+ {
+ /* When lookup_name is called, it will call the add_symbols
+ entry point for the archive. For each element of the
+ archive which is included, BFD will call ldlang_add_file,
+ which will set the usrdata field of the member to the
+ lang_input_statement. */
+ if (member->usrdata != NULL)
+ {
+ wild_section (s, section,
+ (lang_input_statement_type *) member->usrdata,
+ output);
+ }
+
+ member = bfd_openr_next_archived_file (f->the_bfd, member);
+ }
+ }
+}
+
/* Handle a wild statement. SECTION or FILE or both may be NULL,
indicating that it is a wildcard. Separate lang_input_section
statements are created for each part of the expansion; they are
@@ -944,40 +1094,24 @@ wild (s, section, file, target, output)
f != (lang_input_statement_type *) NULL;
f = (lang_input_statement_type *) f->next)
{
- wild_section (s, section, f, output);
+ wild_file (s, section, f, output);
+ }
+ }
+ else if (wildcardp (file))
+ {
+ for (f = (lang_input_statement_type *) file_chain.head;
+ f != (lang_input_statement_type *) NULL;
+ f = (lang_input_statement_type *) f->next)
+ {
+ if (fnmatch (file, f->filename, FNM_FILE_NAME) == 0)
+ wild_file (s, section, f, output);
}
}
else
{
/* Perform the iteration over a single file */
f = lookup_name (file);
- if (f->the_bfd == NULL
- || ! bfd_check_format (f->the_bfd, bfd_archive))
- wild_section (s, section, f, output);
- else
- {
- bfd *member;
-
- /* This is an archive file. We must map each member of the
- archive separately. */
- member = bfd_openr_next_archived_file (f->the_bfd, (bfd *) NULL);
- while (member != NULL)
- {
- /* When lookup_name is called, it will call the
- add_symbols entry point for the archive. For each
- element of the archive which is included, BFD will
- call ldlang_add_file, which will set the usrdata
- field of the member to the lang_input_statement. */
- if (member->usrdata != NULL)
- {
- wild_section (s, section,
- (lang_input_statement_type *) member->usrdata,
- output);
- }
-
- member = bfd_openr_next_archived_file (f->the_bfd, member);
- }
- }
+ wild_file (s, section, f, output);
}
if (section != (char *) NULL
@@ -1016,7 +1150,7 @@ open_output (name)
einfo ("%P%F: cannot open output file %s: %E\n", name);
}
- delete_output_file_on_failure = 1;
+ delete_output_file_on_failure = true;
/* output->flags |= D_PAGED;*/
@@ -1089,7 +1223,8 @@ open_input_bfds (s, force)
break;
case lang_wild_statement_enum:
/* Maybe we should load the file's symbols */
- if (s->wild_statement.filename)
+ if (s->wild_statement.filename
+ && ! wildcardp (s->wild_statement.filename))
(void) lookup_name (s->wild_statement.filename);
open_input_bfds (s->wild_statement.children.head, force);
break;
@@ -1269,13 +1404,21 @@ map_input_to_output_sections (s, target, output_section_statement)
case lang_object_symbols_statement_enum:
case lang_data_statement_enum:
case lang_reloc_statement_enum:
- case lang_assignment_statement_enum:
case lang_padding_statement_enum:
case lang_input_statement_enum:
if (output_section_statement != NULL
&& output_section_statement->bfd_section == NULL)
init_os (output_section_statement);
break;
+ case lang_assignment_statement_enum:
+ if (output_section_statement != NULL
+ && output_section_statement->bfd_section == NULL)
+ init_os (output_section_statement);
+
+ /* Make sure that any sections mentioned in the assignment
+ are initialized. */
+ exp_init_os (s->assignment_statement.exp);
+ break;
case lang_afile_asection_pair_statement_enum:
FAIL ();
break;
@@ -1594,7 +1737,7 @@ print_padding_statement (s)
minfo ("0x%V %W", addr, s->size);
if (s->fill != 0)
- minfo (" 0x%x", s->fill);
+ minfo (" %u", s->fill);
print_nl ();
@@ -1746,7 +1889,7 @@ dprint_statement (s, n)
print_statement_list (s, abs_output_section);
else
{
- while (--n >= 0)
+ while (s && --n >= 0)
{
print_statement (s, abs_output_section);
s = s->next;
@@ -2609,19 +2752,22 @@ lang_place_orphans ()
s->output_section = bfd_abs_section_ptr;
s->output_offset = s->vma;
}
- else if (file->common_section == s)
+ else if (strcmp (s->name, "COMMON") == 0)
{
- /* This is a lonely common section which must
- have come from an archive. We attatch to the
- section with the wildcard */
+ /* This is a lonely common section which must have
+ come from an archive. We attach to the section
+ with the wildcard. */
if (! link_info.relocateable
- && ! command_line.force_common_definition)
+ || command_line.force_common_definition)
{
- if (default_common_section ==
- (lang_output_section_statement_type *) NULL)
+ if (default_common_section == NULL)
{
+#if 0
+ /* This message happens when using the
+ svr3.ifile linker script, so I have
+ disabled it. */
info_msg ("%P: no [COMMON] command, defaulting to .bss\n");
-
+#endif
default_common_section =
lang_output_section_statement_lookup (".bss");
@@ -2815,13 +2961,14 @@ topower (x)
return 0;
}
+
void
lang_enter_output_section_statement (output_section_statement_name,
- address_exp, flags, block_value,
+ address_exp, sectype, block_value,
align, subalign, ebase)
const char *output_section_statement_name;
etree_type * address_exp;
- int flags;
+ enum section_type sectype;
bfd_vma block_value;
etree_type *align;
etree_type *subalign;
@@ -2846,11 +2993,11 @@ lang_enter_output_section_statement (output_section_statement_name,
os->addr_tree =
address_exp;
}
- os->flags = flags;
- if (flags & SEC_NEVER_LOAD)
- os->loadable = 0;
+ os->sectype = sectype;
+ if (sectype != noload_section)
+ os->flags = SEC_NO_FLAGS;
else
- os->loadable = 1;
+ os->flags = SEC_NEVER_LOAD;
os->block_value = block_value ? block_value : 1;
stat_ptr = &os->children;
@@ -3404,7 +3551,7 @@ lang_record_phdrs ()
last = pl;
else
{
- if (! os->loadable
+ if (os->sectype == noload_section
|| os->bfd_section == NULL
|| (os->bfd_section->flags & SEC_ALLOC) == 0)
continue;