/* Linker command language support.
Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004, 2005
+ 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
This file is part of GLD, the Gnu Linker.
else
{
p = stat_alloc (sizeof (lang_input_statement_type));
+ p->header.type = lang_input_statement_enum;
p->header.next = NULL;
}
return new_afile (name, file_type, target, TRUE);
}
+struct output_statement_hash_entry
+{
+ struct bfd_hash_entry root;
+ lang_output_section_statement_type os;
+};
+
+/* The hash table. */
+
+static struct bfd_hash_table output_statement_table;
+
+/* Support routines for the hash table used by lang_output_section_find,
+ initialize the table, fill in an entry and remove the table. */
+
+static struct bfd_hash_entry *
+output_statement_newfunc (struct bfd_hash_entry *entry,
+ struct bfd_hash_table *table,
+ const char *string)
+{
+ lang_output_section_statement_type **nextp;
+ struct output_statement_hash_entry *ret;
+
+ if (entry == NULL)
+ {
+ entry = bfd_hash_allocate (table, sizeof (*ret));
+ if (entry == NULL)
+ return entry;
+ }
+
+ entry = bfd_hash_newfunc (entry, table, string);
+ if (entry == NULL)
+ return entry;
+
+ ret = (struct output_statement_hash_entry *) entry;
+ memset (&ret->os, 0, sizeof (ret->os));
+ ret->os.header.type = lang_output_section_statement_enum;
+ ret->os.subsection_alignment = -1;
+ ret->os.section_alignment = -1;
+ ret->os.block_value = 1;
+ lang_list_init (&ret->os.children);
+ lang_statement_append (stat_ptr,
+ (lang_statement_union_type *) &ret->os,
+ &ret->os.header.next);
+
+ /* For every output section statement added to the list, except the
+ first one, lang_output_section_statement.tail points to the "next"
+ field of the last element of the list. */
+ if (lang_output_section_statement.head != NULL)
+ ret->os.prev = (lang_output_section_statement_type *)
+ ((char *) lang_output_section_statement.tail
+ - offsetof (lang_output_section_statement_type, next));
+
+ /* GCC's strict aliasing rules prevent us from just casting the
+ address, so we store the pointer in a variable and cast that
+ instead. */
+ nextp = &ret->os.next;
+ lang_statement_append (&lang_output_section_statement,
+ (lang_statement_union_type *) &ret->os,
+ (lang_statement_union_type **) nextp);
+ return &ret->root;
+}
+
+static void
+output_statement_table_init (void)
+{
+ if (!bfd_hash_table_init_n (&output_statement_table,
+ output_statement_newfunc,
+ sizeof (struct output_statement_hash_entry),
+ 61))
+ einfo (_("%P%F: can not create hash table: %E\n"));
+}
+
+static void
+output_statement_table_free (void)
+{
+ bfd_hash_table_free (&output_statement_table);
+}
+
/* Build enough state so that the parser can build its tree. */
void
stat_ptr = &statement_list;
+ output_statement_table_init ();
+
lang_list_init (stat_ptr);
lang_list_init (&input_file_chain);
of code-complexity here in ld, besides the initialization which just
looks like other code here. */
if (!bfd_hash_table_init_n (&lang_definedness_table,
- lang_definedness_newfunc, 3))
- einfo (_("%P%F: out of memory during initialization"));
+ lang_definedness_newfunc,
+ sizeof (struct lang_definedness_hash_entry),
+ 3))
+ einfo (_("%P%F: can not create hash table: %E\n"));
+}
+
+void
+lang_finish (void)
+{
+ output_statement_table_free ();
}
/*----------------------------------------------------------------------
return lang_memory_region_lookup (DEFAULT_MEMORY_REGION, FALSE);
}
-static lang_output_section_statement_type *
-lang_output_section_find_1 (const char *const name, int constraint)
+lang_output_section_statement_type *
+lang_output_section_find (const char *const name)
{
- lang_output_section_statement_type *lookup;
+ struct output_statement_hash_entry *entry;
+ unsigned long hash;
+
+ entry = ((struct output_statement_hash_entry *)
+ bfd_hash_lookup (&output_statement_table, name, FALSE, FALSE));
+ if (entry == NULL)
+ return NULL;
- for (lookup = &lang_output_section_statement.head->output_section_statement;
- lookup != NULL;
- lookup = lookup->next)
+ hash = entry->root.hash;
+ do
{
- if (strcmp (name, lookup->name) == 0
- && lookup->constraint != -1
- && (constraint == 0
- || (constraint == lookup->constraint
- && constraint != SPECIAL)))
- return lookup;
+ if (entry->os.constraint != -1)
+ return &entry->os;
+ entry = (struct output_statement_hash_entry *) entry->root.next;
}
- return NULL;
-}
+ while (entry != NULL
+ && entry->root.hash == hash
+ && strcmp (name, entry->os.name) == 0);
-lang_output_section_statement_type *
-lang_output_section_find (const char *const name)
-{
- return lang_output_section_find_1 (name, 0);
+ return NULL;
}
static lang_output_section_statement_type *
lang_output_section_statement_lookup_1 (const char *const name, int constraint)
{
- lang_output_section_statement_type *lookup;
- lang_output_section_statement_type **nextp;
+ struct output_statement_hash_entry *entry;
+ struct output_statement_hash_entry *last_ent;
+ unsigned long hash;
+
+ entry = ((struct output_statement_hash_entry *)
+ bfd_hash_lookup (&output_statement_table, name, TRUE, FALSE));
+ if (entry == NULL)
+ {
+ einfo (_("%P%F: failed creating section `%s': %E\n"), name);
+ return NULL;
+ }
- lookup = lang_output_section_find_1 (name, constraint);
- if (lookup == NULL)
- {
- lookup = new_stat (lang_output_section_statement, stat_ptr);
- lookup->region = NULL;
- lookup->lma_region = NULL;
- lookup->fill = 0;
- lookup->block_value = 1;
- lookup->name = name;
-
- lookup->next = NULL;
- lookup->bfd_section = NULL;
- lookup->processed = 0;
- lookup->constraint = constraint;
- lookup->ignored = FALSE;
- lookup->sectype = normal_section;
- lookup->addr_tree = NULL;
- lang_list_init (&lookup->children);
-
- lookup->memspec = NULL;
- lookup->flags = 0;
- lookup->subsection_alignment = -1;
- lookup->section_alignment = -1;
- lookup->load_base = NULL;
- lookup->update_dot_tree = NULL;
- lookup->phdrs = NULL;
-
- /* GCC's strict aliasing rules prevent us from just casting the
- address, so we store the pointer in a variable and cast that
- instead. */
- nextp = &lookup->next;
- lang_statement_append (&lang_output_section_statement,
- (lang_statement_union_type *) lookup,
- (lang_statement_union_type **) nextp);
- }
- return lookup;
+ if (entry->os.name != NULL)
+ {
+ /* We have a section of this name, but it might not have the correct
+ constraint. */
+ hash = entry->root.hash;
+ do
+ {
+ if (entry->os.constraint != -1
+ && (constraint == 0
+ || (constraint == entry->os.constraint
+ && constraint != SPECIAL)))
+ return &entry->os;
+ last_ent = entry;
+ entry = (struct output_statement_hash_entry *) entry->root.next;
+ }
+ while (entry != NULL
+ && entry->root.hash == hash
+ && strcmp (name, entry->os.name) == 0);
+
+ entry = ((struct output_statement_hash_entry *)
+ output_statement_newfunc (NULL, &output_statement_table, name));
+ if (entry == NULL)
+ {
+ einfo (_("%P%F: failed creating section `%s': %E\n"), name);
+ return NULL;
+ }
+ entry->root = last_ent->root;
+ last_ent->root.next = &entry->root;
+ }
+
+ entry->os.name = name;
+ entry->os.constraint = constraint;
+ return &entry->os;
}
lang_output_section_statement_type *
lang_output_section_statement_type *
lang_output_section_find_by_flags (const asection *sec,
- lang_output_section_statement_type **exact)
+ lang_output_section_statement_type **exact,
+ lang_match_sec_type_func match_type)
{
lang_output_section_statement_type *first, *look, *found;
flagword flags;
{
flags = look->flags;
if (look->bfd_section != NULL)
- flags = look->bfd_section->flags;
+ {
+ flags = look->bfd_section->flags;
+ if (match_type && !match_type (output_bfd, look->bfd_section,
+ sec->owner, sec))
+ continue;
+ }
flags ^= sec->flags;
if (!(flags & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY
| SEC_CODE | SEC_SMALL_DATA | SEC_THREAD_LOCAL)))
}
if (found != NULL)
{
- *exact = found;
+ if (exact != NULL)
+ *exact = found;
return found;
}
{
flags = look->flags;
if (look->bfd_section != NULL)
- flags = look->bfd_section->flags;
+ {
+ flags = look->bfd_section->flags;
+ if (match_type && !match_type (output_bfd, look->bfd_section,
+ sec->owner, sec))
+ continue;
+ }
flags ^= sec->flags;
if (!(flags & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD
| SEC_CODE | SEC_SMALL_DATA | SEC_THREAD_LOCAL)))
found = look;
}
- return found;
}
-
- if (sec->flags & (SEC_READONLY | SEC_THREAD_LOCAL))
+ else if (sec->flags & (SEC_READONLY | SEC_THREAD_LOCAL))
{
/* .rodata can go after .text, .sdata2 after .rodata. */
for (look = first; look; look = look->next)
{
flags = look->flags;
if (look->bfd_section != NULL)
- flags = look->bfd_section->flags;
+ {
+ flags = look->bfd_section->flags;
+ if (match_type && !match_type (output_bfd, look->bfd_section,
+ sec->owner, sec))
+ continue;
+ }
flags ^= sec->flags;
if (!(flags & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD
| SEC_READONLY))
&& !(look->flags & (SEC_SMALL_DATA | SEC_THREAD_LOCAL)))
found = look;
}
- return found;
}
-
- if (sec->flags & SEC_SMALL_DATA)
+ else if (sec->flags & SEC_SMALL_DATA)
{
/* .sdata goes after .data, .sbss after .sdata. */
for (look = first; look; look = look->next)
{
flags = look->flags;
if (look->bfd_section != NULL)
- flags = look->bfd_section->flags;
+ {
+ flags = look->bfd_section->flags;
+ if (match_type && !match_type (output_bfd, look->bfd_section,
+ sec->owner, sec))
+ continue;
+ }
flags ^= sec->flags;
if (!(flags & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD
| SEC_THREAD_LOCAL))
&& !(sec->flags & SEC_HAS_CONTENTS)))
found = look;
}
- return found;
}
-
- if (sec->flags & SEC_HAS_CONTENTS)
+ else if (sec->flags & SEC_HAS_CONTENTS)
{
/* .data goes after .rodata. */
for (look = first; look; look = look->next)
{
flags = look->flags;
if (look->bfd_section != NULL)
- flags = look->bfd_section->flags;
+ {
+ flags = look->bfd_section->flags;
+ if (match_type && !match_type (output_bfd, look->bfd_section,
+ sec->owner, sec))
+ continue;
+ }
flags ^= sec->flags;
if (!(flags & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD
| SEC_SMALL_DATA | SEC_THREAD_LOCAL)))
found = look;
}
- return found;
}
-
- /* .bss goes last. */
- for (look = first; look; look = look->next)
+ else
{
- flags = look->flags;
- if (look->bfd_section != NULL)
- flags = look->bfd_section->flags;
- flags ^= sec->flags;
- if (!(flags & SEC_ALLOC))
- found = look;
+ /* .bss goes last. */
+ for (look = first; look; look = look->next)
+ {
+ flags = look->flags;
+ if (look->bfd_section != NULL)
+ {
+ flags = look->bfd_section->flags;
+ if (match_type && !match_type (output_bfd, look->bfd_section,
+ sec->owner, sec))
+ continue;
+ }
+ flags ^= sec->flags;
+ if (!(flags & SEC_ALLOC))
+ found = look;
+ }
}
- return found;
+ if (found || !match_type)
+ return found;
+
+ return lang_output_section_find_by_flags (sec, NULL, NULL);
}
/* Find the last output section before given output statement.
static asection *
output_prev_sec_find (lang_output_section_statement_type *os)
{
- asection *s = (asection *) NULL;
lang_output_section_statement_type *lookup;
- for (lookup = &lang_output_section_statement.head->output_section_statement;
- lookup != NULL;
- lookup = lookup->next)
+ for (lookup = os->prev; lookup != NULL; lookup = lookup->prev)
{
if (lookup->constraint == -1)
continue;
- if (lookup == os)
- return s;
if (lookup->bfd_section != NULL && lookup->bfd_section->owner != NULL)
- s = lookup->bfd_section;
+ return lookup->bfd_section;
}
return NULL;
}
lang_output_section_statement_type *
-lang_insert_orphan (lang_input_statement_type *file,
- asection *s,
+lang_insert_orphan (asection *s,
const char *secname,
lang_output_section_statement_type *after,
struct orphan_save *place,
if (add_child == NULL)
add_child = &os->children;
- lang_add_section (add_child, s, os, file);
+ lang_add_section (add_child, s, os);
lang_leave_output_section_statement (0, "*default*", NULL, NULL);
{
lang_statement_union_type **where;
lang_statement_union_type **assign = NULL;
+ bfd_boolean ignore_first;
/* Look for a suitable place for the new statement list.
The idea is to skip over anything that might be inside
a SECTIONS {} statement in a script, before we find
another output_section_statement. Assignments to "dot"
before an output section statement are assumed to
- belong to it. */
+ belong to it. An exception to this rule is made for
+ the first assignment to dot, otherwise we might put an
+ orphan before . = . + SIZEOF_HEADERS or similar
+ assignments that set the initial address. */
+
+ ignore_first = after == (&lang_output_section_statement.head
+ ->output_section_statement);
for (where = &after->header.next;
*where != NULL;
where = &(*where)->header.next)
ass = &(*where)->assignment_statement;
if (ass->exp->type.node_class != etree_assert
&& ass->exp->assign.dst[0] == '.'
- && ass->exp->assign.dst[1] == 0)
+ && ass->exp->assign.dst[1] == 0
+ && !ignore_first)
assign = where;
}
+ ignore_first = FALSE;
continue;
case lang_wild_statement_enum:
case lang_input_section_enum:
/* Do the same for the list of output section statements. */
newly_added_os = *os_tail;
*os_tail = NULL;
+ newly_added_os->prev = (lang_output_section_statement_type *)
+ ((char *) place->os_tail
+ - offsetof (lang_output_section_statement_type, next));
newly_added_os->next = *place->os_tail;
+ if (newly_added_os->next != NULL)
+ newly_added_os->next->prev = newly_added_os;
*place->os_tail = newly_added_os;
place->os_tail = &newly_added_os->next;
/* Initialize an output section. */
static void
-init_os (lang_output_section_statement_type *s)
+init_os (lang_output_section_statement_type *s, asection *isec)
{
if (s->bfd_section != NULL)
return;
output_bfd->xvec->name, s->name);
}
s->bfd_section->output_section = s->bfd_section;
-
- /* We initialize an output sections output offset to minus its own
- vma to allow us to output a section through itself. */
s->bfd_section->output_offset = 0;
if (!command_line.reduce_memory_overheads)
{
if (s->load_base != NULL)
exp_init_os (s->load_base);
+
+ /* If supplied an alignment, set it. */
+ if (s->section_alignment != -1)
+ s->bfd_section->alignment_power = s->section_alignment;
+
+ if (isec)
+ bfd_init_private_section_data (isec->owner, isec,
+ output_bfd, s->bfd_section,
+ &link_info);
}
/* Make sure that all output sections mentioned in an expression are
os = lang_output_section_find (exp->name.name);
if (os != NULL && os->bfd_section == NULL)
- init_os (os);
+ init_os (os, NULL);
}
}
break;
void
lang_add_section (lang_statement_list_type *ptr,
asection *section,
- lang_output_section_statement_type *output,
- lang_input_statement_type *file)
+ lang_output_section_statement_type *output)
{
flagword flags = section->flags;
bfd_boolean discard;
flagword flags;
if (output->bfd_section == NULL)
- init_os (output);
+ init_os (output, section);
first = ! output->bfd_section->linker_has_input;
output->bfd_section->linker_has_input = 1;
new = new_stat (lang_input_section, ptr);
new->section = section;
- new->ifile = file;
section->output_section = output->bfd_section;
flags = section->flags;
if (section->alignment_power > output->bfd_section->alignment_power)
output->bfd_section->alignment_power = section->alignment_power;
- /* If supplied an alignment, then force it. */
- if (output->section_alignment != -1)
- output->bfd_section->alignment_power = output->section_alignment;
-
if (bfd_get_arch (section->owner) == bfd_arch_tic54x
&& (section->flags & SEC_TIC54X_BLOCK) != 0)
{
fa = FALSE;
}
- if (ls->ifile->the_bfd != NULL
- && bfd_my_archive (ls->ifile->the_bfd) != NULL)
+ if (bfd_my_archive (ls->section->owner) != NULL)
{
- ln = bfd_get_filename (bfd_my_archive (ls->ifile->the_bfd));
+ ln = bfd_get_filename (bfd_my_archive (ls->section->owner));
la = TRUE;
}
else
{
- ln = ls->ifile->filename;
+ ln = ls->section->owner->filename;
la = FALSE;
}
if (fa)
fn = file->filename;
if (la)
- ln = ls->ifile->filename;
+ ln = ls->section->owner->filename;
i = strcmp (fn, ln);
if (i > 0)
if (before == NULL)
lang_add_section (&ptr->children, section,
- (lang_output_section_statement_type *) output,
- file);
+ (lang_output_section_statement_type *) output);
else
{
lang_statement_list_type list;
lang_list_init (&list);
lang_add_section (&list, section,
- (lang_output_section_statement_type *) output,
- file);
+ (lang_output_section_statement_type *) output);
/* If we are discarding the section, LIST.HEAD will
be NULL. */
link_info.hash = bfd_link_hash_table_create (output);
if (link_info.hash == NULL)
- einfo (_("%P%F: can not create link hash table: %E\n"));
+ einfo (_("%P%F: can not create hash table: %E\n"));
bfd_set_gp_size (output, g_switch_value);
return output;
are initialized. */
exp_init_os (s->data_statement.exp);
if (os != NULL && os->bfd_section == NULL)
- init_os (os);
+ init_os (os, NULL);
/* The output section gets contents, and then we inspect for
any flags set in the input script which override any ALLOC. */
os->bfd_section->flags |= SEC_HAS_CONTENTS;
case lang_padding_statement_enum:
case lang_input_statement_enum:
if (os != NULL && os->bfd_section == NULL)
- init_os (os);
+ init_os (os, NULL);
break;
case lang_assignment_statement_enum:
if (os != NULL && os->bfd_section == NULL)
- init_os (os);
+ init_os (os, NULL);
/* Make sure that any sections mentioned in the assignment
are initialized. */
(s->address_statement.section_name));
if (aos->bfd_section == NULL)
- init_os (aos);
+ init_os (aos, NULL);
aos->addr_tree = s->address_statement.address;
}
break;
for (i = 0; i < SECTION_NAME_MAP_LENGTH; i++)
print_space ();
- addr = data->output_vma;
+ addr = data->output_offset;
if (data->output_section != NULL)
addr += data->output_section->vma;
for (i = 0; i < SECTION_NAME_MAP_LENGTH; i++)
print_space ();
- addr = reloc->output_vma;
+ addr = reloc->output_offset;
if (reloc->output_section != NULL)
addr += reloc->output_section->vma;
lang_input_section_type *is = &((*this_ptr)->input_section);
asection *i = is->section;
- if (!is->ifile->just_syms_flag && (i->flags & SEC_EXCLUDE) == 0)
+ if (!((lang_input_statement_type *) i->owner->usrdata)->just_syms_flag
+ && (i->flags & SEC_EXCLUDE) == 0)
{
unsigned int alignment_needed;
asection *o;
lang_output_section_statement_type *os;
os = &s->output_section_statement;
+ if (os->addr_tree != NULL)
+ {
+ os->processed = FALSE;
+ exp_fold_tree (os->addr_tree, bfd_abs_section_ptr, &dot);
+
+ if (!expld.result.valid_p
+ && expld.phase != lang_mark_phase_enum)
+ einfo (_("%F%S: non constant or forward reference"
+ " address expression for section %s\n"),
+ os->name);
+
+ dot = expld.result.value + expld.result.section->vma;
+ }
+
if (os->bfd_section == NULL)
/* This section was removed or never actually created. */
break;
break;
}
+ newdot = dot;
if (bfd_is_abs_section (os->bfd_section))
{
/* No matter what happens, an abs section starts at zero. */
}
else
{
+ int align;
+
if (os->addr_tree == NULL)
{
/* No address specified for this section, get one
}
newdot = os->region->current;
-
- if (os->section_alignment == -1)
- {
- bfd_vma savedot = newdot;
- newdot = align_power (newdot,
- os->bfd_section->alignment_power);
-
- if (newdot != savedot
- && config.warn_section_align
- && expld.phase != lang_mark_phase_enum)
- einfo (_("%P: warning: changing start of section"
- " %s by %lu bytes\n"),
- os->name, (unsigned long) (newdot - savedot));
- }
+ align = os->bfd_section->alignment_power;
}
else
+ align = os->section_alignment;
+
+ /* Align to what the section needs. */
+ if (align > 0)
{
- newdot = dot;
- os->processed = -1;
- exp_fold_tree (os->addr_tree, bfd_abs_section_ptr,
- &newdot);
- os->processed = 0;
+ bfd_vma savedot = newdot;
+ newdot = align_power (newdot, align);
- if (!expld.result.valid_p
+ if (newdot != savedot
+ && (config.warn_section_align
+ || os->addr_tree != NULL)
&& expld.phase != lang_mark_phase_enum)
- einfo (_("%F%S: non constant or forward reference"
- " address expression for section %s\n"),
- os->name);
-
- newdot = expld.result.value + expld.result.section->vma;
+ einfo (_("%P: warning: changing start of section"
+ " %s by %lu bytes\n"),
+ os->name, (unsigned long) (newdot - savedot));
}
- /* The section starts here.
- First, align to what the section needs. */
-
- if (os->section_alignment != -1)
- newdot = align_power (newdot, os->section_alignment);
-
bfd_set_section_vma (0, os->bfd_section, newdot);
os->bfd_section->output_offset = 0;
lang_size_sections_1 (os->children.head, os, &os->children.head,
os->fill, newdot, relax, check_regions);
- os->processed = 1;
+ os->processed = TRUE;
if (bfd_is_abs_section (os->bfd_section) || os->ignored)
{
{
unsigned int size = 0;
- s->data_statement.output_vma =
+ s->data_statement.output_offset =
dot - output_section_statement->bfd_section->vma;
s->data_statement.output_section =
output_section_statement->bfd_section;
{
int size;
- s->reloc_statement.output_vma =
+ s->reloc_statement.output_offset =
dot - output_section_statement->bfd_section->vma;
s->reloc_statement.output_section =
output_section_statement->bfd_section;
}
static void
-lang_finish (void)
+lang_end (void)
{
struct bfd_link_hash_entry *h;
bfd_boolean warn;
}
lang_add_section (&default_common_section->children, s,
- default_common_section, file);
+ default_common_section);
}
}
- else if (ldemul_place_orphan (file, s))
+ else if (ldemul_place_orphan (s))
;
else
{
lang_output_section_statement_type *os;
os = lang_output_section_statement_lookup (s->name);
- lang_add_section (&os->children, s, os, file);
+ lang_add_section (&os->children, s, os);
}
}
}
{
lang_output_section_statement_type *os;
- current_section =
- os =
- lang_output_section_statement_lookup_1 (output_section_statement_name,
- constraint);
+ os = lang_output_section_statement_lookup_1 (output_section_statement_name,
+ constraint);
+ current_section = os;
/* Make next things chain into subchain of this. */
void
lang_final (void)
{
- lang_output_statement_type *new =
- new_stat (lang_output_statement, stat_ptr);
+ lang_output_statement_type *new;
+ new = new_stat (lang_output_statement, stat_ptr);
new->name = output_filename;
}
for (os = &lang_output_section_statement.head->output_section_statement;
os != NULL;
os = os->next)
- os->processed = 0;
+ os->processed = FALSE;
for (o = output_bfd->sections; o != NULL; o = o->next)
{
/* Final stuffs. */
ldemul_finish ();
- lang_finish ();
+ lang_end ();
}
/* EXPORTED TO YACC */
void
lang_add_target (const char *name)
{
- lang_target_statement_type *new = new_stat (lang_target_statement,
- stat_ptr);
+ lang_target_statement_type *new;
+ new = new_stat (lang_target_statement, stat_ptr);
new->target = name;
-
}
void
void
lang_add_fill (fill_type *fill)
{
- lang_fill_statement_type *new = new_stat (lang_fill_statement,
- stat_ptr);
+ lang_fill_statement_type *new;
+ new = new_stat (lang_fill_statement, stat_ptr);
new->fill = fill;
}
void
lang_add_data (int type, union etree_union *exp)
{
+ lang_data_statement_type *new;
- lang_data_statement_type *new = new_stat (lang_data_statement,
- stat_ptr);
-
+ new = new_stat (lang_data_statement, stat_ptr);
new->exp = exp;
new->type = type;
-
}
/* Create a new reloc statement. RELOC is the BFD relocation type to
p->addend_value = 0;
p->output_section = NULL;
- p->output_vma = 0;
+ p->output_offset = 0;
}
lang_assignment_statement_type *
lang_add_assignment (etree_type *exp)
{
- lang_assignment_statement_type *new = new_stat (lang_assignment_statement,
- stat_ptr);
+ lang_assignment_statement_type *new;
+ new = new_stat (lang_assignment_statement, stat_ptr);
new->exp = exp;
return new;
}
void
lang_add_attribute (enum statement_enum attribute)
{
- new_statement (attribute, sizeof (lang_statement_union_type), stat_ptr);
+ new_statement (attribute, sizeof (lang_statement_header_type), stat_ptr);
}
void
{
if (startup_file != NULL)
{
- einfo (_("%P%Fmultiple STARTUP files\n"));
+ einfo (_("%P%F: multiple STARTUP files\n"));
}
first_file->filename = name;
first_file->local_sym_name = name;
while (expr && strcmp (expr->symbol, sym) == 0)
if (expr->mask == BFD_ELF_VERSION_C_TYPE)
goto out_ret;
- else
- expr = expr->next;
+ else
+ expr = expr->next;
}
/* Fallthrough */
case BFD_ELF_VERSION_C_TYPE:
while (expr && strcmp (expr->symbol, cxx_sym) == 0)
if (expr->mask == BFD_ELF_VERSION_CXX_TYPE)
goto out_ret;
- else
- expr = expr->next;
+ else
+ expr = expr->next;
}
/* Fallthrough */
case BFD_ELF_VERSION_CXX_TYPE:
while (expr && strcmp (expr->symbol, java_sym) == 0)
if (expr->mask == BFD_ELF_VERSION_JAVA_TYPE)
goto out_ret;
- else
- expr = expr->next;
+ else
+ expr = expr->next;
}
/* Fallthrough */
default:
expr = head->remaining;
else
expr = prev->next;
- while (expr)
+ for (; expr; expr = expr->next)
{
const char *s;
+ if (!expr->pattern)
+ continue;
+
if (expr->pattern[0] == '*' && expr->pattern[1] == '\0')
break;
s = sym;
if (fnmatch (expr->pattern, s, 0) == 0)
break;
- expr = expr->next;
}
out_ret:
}
}
-/* This is called for each variable name or match expression. */
+/* This is called for each variable name or match expression. NEW is
+ the name of the symbol to match, or, if LITERAL_P is FALSE, a glob
+ pattern to be matched against symbol names. */
struct bfd_elf_version_expr *
lang_new_vers_pattern (struct bfd_elf_version_expr *orig,
const char *new,
- const char *lang)
+ const char *lang,
+ bfd_boolean literal_p)
{
struct bfd_elf_version_expr *ret;
ret = xmalloc (sizeof *ret);
ret->next = orig;
- ret->pattern = new;
+ ret->pattern = literal_p ? NULL : new;
ret->symver = 0;
ret->script = 0;
- ret->symbol = realsymbol (new);
+ ret->symbol = literal_p ? new : realsymbol (new);
if (lang == NULL || strcasecmp (lang, "C") == 0)
ret->mask = BFD_ELF_VERSION_C_TYPE;
p = contents;
while (p < contents + len)
{
- greg = lang_new_vers_pattern (greg, p, NULL);
+ greg = lang_new_vers_pattern (greg, p, NULL, FALSE);
p = strchr (p, '\0') + 1;
}
sec->flags |= SEC_EXCLUDE;
}
- lreg = lang_new_vers_pattern (NULL, "*", NULL);
+ lreg = lang_new_vers_pattern (NULL, "*", NULL, FALSE);
lang_register_vers_node (command_line.version_exports_section,
lang_new_vers_node (greg, lreg), NULL);
}