/* Linker command language support.
Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+ 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
This file is part of the GNU Binutils.
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
-#include <limits.h>
-
#include "sysdep.h"
#include "bfd.h"
#include "libiberty.h"
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
static const char *startup_file;
+static const char *entry_symbol_default = "start";
static bfd_boolean placed_commons = FALSE;
static bfd_boolean stripped_excluded_sections = FALSE;
static lang_output_section_statement_type *default_common_section;
static bfd_vma print_dot;
static lang_input_statement_type *first_file;
static const char *current_target;
-static const char *output_target;
static lang_statement_list_type statement_list;
static struct bfd_hash_table lang_definedness_table;
static lang_statement_list_type *stat_save[10];
static lang_statement_list_type **stat_save_ptr = &stat_save[0];
+static struct unique_sections *unique_section_list;
+static bfd_boolean ldlang_sysrooted_script = FALSE;
/* Forward declarations. */
static void exp_init_os (etree_type *);
static void print_statement_list (lang_statement_union_type *,
lang_output_section_statement_type *);
static void print_statements (void);
-static void print_input_section (asection *);
+static void print_input_section (asection *, bfd_boolean);
static bfd_boolean lang_one_common (struct bfd_link_hash_entry *, void *);
static void lang_record_phdrs (void);
static void lang_do_version_exports_section (void);
(struct bfd_elf_version_expr_head *);
/* Exported variables. */
+const char *output_target;
lang_output_section_statement_type *abs_output_section;
lang_statement_list_type lang_output_section_statement;
lang_statement_list_type *stat_ptr = &statement_list;
lang_statement_list_type file_chain = { NULL, NULL };
lang_statement_list_type input_file_chain;
struct bfd_sym_chain entry_symbol = { NULL, NULL };
-static const char *entry_symbol_default = "start";
const char *entry_section = ".text";
bfd_boolean entry_from_cmdline;
bfd_boolean lang_has_input_file = FALSE;
bfd_boolean delete_output_file_on_failure = FALSE;
struct lang_phdr *lang_phdr_list;
struct lang_nocrossrefs *nocrossref_list;
-static struct unique_sections *unique_section_list;
-static bfd_boolean ldlang_sysrooted_script = FALSE;
+bfd_boolean missing_file = FALSE;
/* Functions that traverse the linker script and might evaluate
DEFINED() need to increment this. */
}
static bfd_boolean
-unique_section_p (const asection *sec)
+unique_section_p (const asection *sec,
+ const lang_output_section_statement_type *os)
{
struct unique_sections *unam;
const char *secnam;
if (link_info.relocatable
&& sec->owner != NULL
&& bfd_is_group_section (sec->owner, sec))
- return TRUE;
+ return !(os != NULL
+ && strcmp (os->name, DISCARD_SECTION_NAME) == 0);
secnam = sec->name;
for (unam = unique_section_list; unam; unam = unam->next)
} section_iterator_callback_data;
static bfd_boolean
-section_iterator_callback (bfd *bfd ATTRIBUTE_UNUSED, asection *s, void *data)
+section_iterator_callback (bfd *abfd ATTRIBUTE_UNUSED, asection *s, void *data)
{
- section_iterator_callback_data *d = data;
+ section_iterator_callback_data *d = (section_iterator_callback_data *) data;
if (d->found_section != NULL)
{
struct wildcard_list *sec,
asection *section,
lang_input_statement_type *file,
- void *output ATTRIBUTE_UNUSED)
+ void *output)
{
lang_section_bst_type *node;
lang_section_bst_type **tree;
+ lang_output_section_statement_type *os;
- if (unique_section_p (section))
+ os = (lang_output_section_statement_type *) output;
+
+ if (unique_section_p (section, os))
return;
- node = xmalloc (sizeof (lang_section_bst_type));
+ node = (lang_section_bst_type *) xmalloc (sizeof (lang_section_bst_type));
node->left = 0;
node->right = 0;
node->section = section;
lang_input_statement. */
if (member->usrdata != NULL)
{
- walk_wild_section (s, member->usrdata, callback, data);
+ walk_wild_section (s,
+ (lang_input_statement_type *) member->usrdata,
+ callback, data);
}
member = bfd_openr_next_archived_file (f->the_bfd, member);
size_t size,
lang_statement_list_type *list)
{
- lang_statement_union_type *new;
+ lang_statement_union_type *new_stmt;
- new = stat_alloc (size);
- new->header.type = type;
- new->header.next = NULL;
- lang_statement_append (list, new, &new->header.next);
- return new;
+ new_stmt = (lang_statement_union_type *) stat_alloc (size);
+ new_stmt->header.type = type;
+ new_stmt->header.next = NULL;
+ lang_statement_append (list, new_stmt, &new_stmt->header.next);
+ return new_stmt;
}
/* Build a new input file node for the language. There are several
lang_input_statement_type *p;
if (add_to_list)
- p = new_stat (lang_input_statement, stat_ptr);
+ p = (lang_input_statement_type *) new_stat (lang_input_statement, stat_ptr);
else
{
- p = stat_alloc (sizeof (lang_input_statement_type));
+ p = (lang_input_statement_type *)
+ stat_alloc (sizeof (lang_input_statement_type));
p->header.type = lang_input_statement_enum;
p->header.next = NULL;
}
p->next_real_file = NULL;
p->next = NULL;
p->dynamic = config.dynamic_link;
- p->add_needed = add_needed;
- p->as_needed = as_needed;
+ p->add_DT_NEEDED_for_dynamic = add_DT_NEEDED_for_dynamic;
+ p->add_DT_NEEDED_for_regular = add_DT_NEEDED_for_regular;
p->whole_archive = whole_archive;
p->loaded = FALSE;
+ p->missing_file = FALSE;
+
lang_statement_append (&input_file_chain,
(lang_statement_union_type *) p,
&p->next_real_file);
if (entry == NULL)
{
- entry = bfd_hash_allocate (table, sizeof (*ret));
+ entry = (struct bfd_hash_entry *) bfd_hash_allocate (table,
+ sizeof (*ret));
if (entry == NULL)
return entry;
}
{
lang_memory_region_name *n;
lang_memory_region_type *r;
- lang_memory_region_type *new;
+ lang_memory_region_type *new_region;
/* NAME is NULL for LMA memspecs if no region was specified. */
if (name == NULL)
if (!create && strcmp (name, DEFAULT_MEMORY_REGION))
einfo (_("%P:%S: warning: memory region `%s' not declared\n"), name);
- new = stat_alloc (sizeof (lang_memory_region_type));
+ new_region = (lang_memory_region_type *)
+ stat_alloc (sizeof (lang_memory_region_type));
- new->name_list.name = xstrdup (name);
- new->name_list.next = NULL;
- new->next = NULL;
- new->origin = 0;
- new->length = ~(bfd_size_type) 0;
- new->current = 0;
- new->last_os = NULL;
- new->flags = 0;
- new->not_flags = 0;
- new->had_full_message = FALSE;
+ new_region->name_list.name = xstrdup (name);
+ new_region->name_list.next = NULL;
+ new_region->next = NULL;
+ new_region->origin = 0;
+ new_region->length = ~(bfd_size_type) 0;
+ new_region->current = 0;
+ new_region->last_os = NULL;
+ new_region->flags = 0;
+ new_region->not_flags = 0;
+ new_region->had_full_message = FALSE;
- *lang_memory_region_list_tail = new;
- lang_memory_region_list_tail = &new->next;
+ *lang_memory_region_list_tail = new_region;
+ lang_memory_region_list_tail = &new_region->next;
- return new;
+ return new_region;
}
void
alias);
/* Add alias to region name list. */
- n = stat_alloc (sizeof (lang_memory_region_name));
+ n = (lang_memory_region_name *) stat_alloc (sizeof (lang_memory_region_name));
n->name = xstrdup (alias);
n->next = region->name_list.next;
region->name_list.next = n;
return lang_memory_region_lookup (DEFAULT_MEMORY_REGION, FALSE);
}
+/* Find or create an output_section_statement with the given NAME.
+ If CONSTRAINT is non-zero match one with that constraint, otherwise
+ match any non-negative constraint. If CREATE, always make a
+ new output_section_statement for SPECIAL CONSTRAINT. */
+
lang_output_section_statement_type *
-lang_output_section_statement_lookup (const char *const name,
+lang_output_section_statement_lookup (const char *name,
int constraint,
bfd_boolean create)
{
/* We have a section of this name, but it might not have the correct
constraint. */
struct out_section_hash_entry *last_ent;
- unsigned long hash = entry->root.hash;
+ name = entry->s.output_section_statement.name;
if (create && constraint == SPECIAL)
/* Not traversing to the end reverses the order of the second
and subsequent SPECIAL sections in the hash table chain,
else
do
{
- if (entry->s.output_section_statement.constraint >= 0
- && (constraint == 0
- || (constraint
- == entry->s.output_section_statement.constraint)))
+ if (constraint == entry->s.output_section_statement.constraint
+ || (constraint == 0
+ && entry->s.output_section_statement.constraint >= 0))
return &entry->s.output_section_statement;
last_ent = entry;
entry = (struct out_section_hash_entry *) entry->root.next;
}
while (entry != NULL
- && entry->root.hash == hash
- && strcmp (name, entry->s.output_section_statement.name) == 0);
+ && name == entry->s.output_section_statement.name);
if (!create)
return NULL;
return &entry->s.output_section_statement;
}
+/* Find the next output_section_statement with the same name as OS.
+ If CONSTRAINT is non-zero, find one with that constraint otherwise
+ match any non-negative constraint. */
+
+lang_output_section_statement_type *
+next_matching_output_section_statement (lang_output_section_statement_type *os,
+ int constraint)
+{
+ /* All output_section_statements are actually part of a
+ struct out_section_hash_entry. */
+ struct out_section_hash_entry *entry = (struct out_section_hash_entry *)
+ ((char *) os
+ - offsetof (struct out_section_hash_entry, s.output_section_statement));
+ const char *name = os->name;
+
+ ASSERT (name == entry->root.string);
+ do
+ {
+ entry = (struct out_section_hash_entry *) entry->root.next;
+ if (entry == NULL
+ || name != entry->s.output_section_statement.name)
+ return NULL;
+ }
+ while (constraint != entry->s.output_section_statement.constraint
+ && (constraint != 0
+ || entry->s.output_section_statement.constraint < 0));
+
+ return &entry->s.output_section_statement;
+}
+
/* A variant of lang_output_section_find used by place_orphan.
Returns the output statement that should precede a new output
statement for SEC. If an exact match is found on certain flags,
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. 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. */
+ are assumed to belong to it, except in two cases; The first
+ assignment to dot, and assignments before non-alloc sections.
+ Otherwise we might put an orphan before . = . + SIZEOF_HEADERS or
+ similar assignments that set the initial address, or we might
+ insert non-alloc note sections among assignments setting end of
+ image symbols. */
static lang_statement_union_type **
insert_os_after (lang_output_section_statement_type *after)
continue;
case lang_output_section_statement_enum:
if (assign != NULL)
- where = assign;
+ {
+ asection *s = (*where)->output_section_statement.bfd_section;
+
+ if (s == NULL
+ || s->map_head.s == NULL
+ || (s->flags & SEC_ALLOC) != 0)
+ where = assign;
+ }
break;
case lang_input_statement_enum:
case lang_address_statement_enum:
push_stat_ptr (&add);
}
+ if (link_info.relocatable || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0)
+ address = exp_intop (0);
+
+ os_tail = ((lang_output_section_statement_type **)
+ lang_output_section_statement.tail);
+ os = lang_enter_output_section_statement (secname, address, normal_section,
+ NULL, NULL, NULL, constraint);
+
ps = NULL;
- if (config.build_constructors)
+ if (config.build_constructors && *os_tail == os)
{
/* If the name of the section is representable in C, then create
symbols to mark the start and the end of the section. */
exp_intop ((bfd_vma) 1 << s->alignment_power));
lang_add_assignment (exp_assop ('=', ".", e_align));
lang_add_assignment (exp_provide (symname,
- exp_nameop (NAME, "."),
+ exp_unop (ABSOLUTE,
+ exp_nameop (NAME, ".")),
FALSE));
}
}
- if (link_info.relocatable || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0)
- address = exp_intop (0);
-
- os_tail = ((lang_output_section_statement_type **)
- lang_output_section_statement.tail);
- os = lang_enter_output_section_statement (secname, address, 0, NULL, NULL,
- NULL, constraint);
-
if (add_child == NULL)
add_child = &os->children;
lang_add_section (add_child, s, os);
- lang_leave_output_section_statement (0, "*default*", NULL, NULL);
+ if (after && (s->flags & (SEC_LOAD | SEC_ALLOC)) != 0)
+ {
+ const char *region = (after->region
+ ? after->region->name_list.name
+ : DEFAULT_MEMORY_REGION);
+ const char *lma_region = (after->lma_region
+ ? after->lma_region->name_list.name
+ : NULL);
+ lang_leave_output_section_statement (NULL, region, after->phdrs,
+ lma_region);
+ }
+ else
+ lang_leave_output_section_statement (NULL, DEFAULT_MEMORY_REGION, NULL,
+ NULL);
- if (config.build_constructors && *ps == '\0')
+ if (ps != NULL && *ps == '\0')
{
char *symname;
dis_header_printed = TRUE;
}
- print_input_section (s);
+ print_input_section (s, TRUE);
}
}
ASSERT (get_userdata (sec) == NULL);
get_userdata (sec) = new_data;
new_data->map_symbol_def_tail = &new_data->map_symbol_def_head;
+ new_data->map_symbol_def_count = 0;
}
static bfd_boolean
struct fat_user_section_struct *ud;
struct map_symbol_def *def;
- ud = get_userdata (hash_entry->u.def.section);
+ ud = (struct fat_user_section_struct *)
+ get_userdata (hash_entry->u.def.section);
if (! ud)
{
/* ??? What do we have to do to initialize this beforehand? */
/* The first time we get here is bfd_abs_section... */
init_map_userdata (0, hash_entry->u.def.section, 0);
- ud = get_userdata (hash_entry->u.def.section);
+ ud = (struct fat_user_section_struct *)
+ get_userdata (hash_entry->u.def.section);
}
else if (!ud->map_symbol_def_tail)
ud->map_symbol_def_tail = &ud->map_symbol_def_head;
- def = obstack_alloc (&map_obstack, sizeof *def);
+ def = (struct map_symbol_def *) obstack_alloc (&map_obstack, sizeof *def);
def->entry = hash_entry;
*(ud->map_symbol_def_tail) = def;
ud->map_symbol_def_tail = &def->next;
+ ud->map_symbol_def_count++;
}
return TRUE;
}
/* Initialize an output section. */
static void
-init_os (lang_output_section_statement_type *s, asection *isec,
- flagword flags)
+init_os (lang_output_section_statement_type *s, flagword flags)
{
- if (s->bfd_section != NULL)
- return;
-
if (strcmp (s->name, DISCARD_SECTION_NAME) == 0)
einfo (_("%P%F: Illegal use of `%s' section\n"), DISCARD_SECTION_NAME);
if (!link_info.reduce_memory_overheads)
{
- fat_section_userdata_type *new
- = stat_alloc (sizeof (fat_section_userdata_type));
- memset (new, 0, sizeof (fat_section_userdata_type));
- get_userdata (s->bfd_section) = new;
+ fat_section_userdata_type *new_userdata = (fat_section_userdata_type *)
+ stat_alloc (sizeof (fat_section_userdata_type));
+ memset (new_userdata, 0, sizeof (fat_section_userdata_type));
+ get_userdata (s->bfd_section) = new_userdata;
}
/* If there is a base address, make sure that any sections it might
/* 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,
- link_info.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, NULL, 0);
+ init_os (os, 0);
}
}
break;
static void
section_already_linked (bfd *abfd, asection *sec, void *data)
{
- lang_input_statement_type *entry = data;
+ lang_input_statement_type *entry = (lang_input_statement_type *) data;
/* If we are only reading symbols from this object, then we want to
discard all sections. */
{
flagword flags = section->flags;
bfd_boolean discard;
+ lang_input_section_type *new_section;
/* Discard sections marked with SEC_EXCLUDE. */
discard = (flags & SEC_EXCLUDE) != 0;
return;
}
- if (section->output_section == NULL)
- {
- bfd_boolean first;
- lang_input_section_type *new;
- flagword flags;
-
- flags = section->flags;
-
- /* We don't copy the SEC_NEVER_LOAD flag from an input section
- to an output section, because we want to be able to include a
- 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. */
-
- flags &= ~ SEC_NEVER_LOAD;
-
- switch (output->sectype)
- {
- case normal_section:
- case overlay_section:
- break;
- case noalloc_section:
- flags &= ~SEC_ALLOC;
- break;
- case noload_section:
- flags &= ~SEC_LOAD;
- flags |= SEC_NEVER_LOAD;
- break;
- }
-
- if (output->bfd_section == NULL)
- init_os (output, section, flags);
+ if (section->output_section != NULL)
+ return;
- first = ! output->bfd_section->linker_has_input;
- output->bfd_section->linker_has_input = 1;
+ /* We don't copy the SEC_NEVER_LOAD flag from an input section
+ to an output section, because we want to be able to include a
+ 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. */
+ flags &= ~ SEC_NEVER_LOAD;
- if (!link_info.relocatable
- && !stripped_excluded_sections)
- {
- asection *s = output->bfd_section->map_tail.s;
- output->bfd_section->map_tail.s = section;
- section->map_head.s = NULL;
- section->map_tail.s = s;
- if (s != NULL)
- s->map_head.s = section;
- else
- output->bfd_section->map_head.s = section;
- }
-
- /* Add a section reference to the list. */
- new = new_stat (lang_input_section, ptr);
+ /* 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. */
- new->section = section;
- section->output_section = output->bfd_section;
+ if (!link_info.relocatable)
+ flags &= ~ (SEC_LINK_ONCE | SEC_LINK_DUPLICATES);
- /* 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. */
+ switch (output->sectype)
+ {
+ case normal_section:
+ case overlay_section:
+ break;
+ case noalloc_section:
+ flags &= ~SEC_ALLOC;
+ break;
+ case noload_section:
+ flags &= ~SEC_LOAD;
+ flags |= SEC_NEVER_LOAD;
+ break;
+ }
- if (! link_info.relocatable)
- flags &= ~ (SEC_LINK_ONCE | SEC_LINK_DUPLICATES);
+ if (output->bfd_section == NULL)
+ init_os (output, flags);
- /* If this is not the first input section, and the SEC_READONLY
- flag is not currently set, then don't set it just because the
- input section has it set. */
+ /* If SEC_READONLY is not set in the input section, then clear
+ it from the output section. */
+ output->bfd_section->flags &= flags | ~SEC_READONLY;
- if (! first && (output->bfd_section->flags & SEC_READONLY) == 0)
- flags &= ~ SEC_READONLY;
+ if (output->bfd_section->linker_has_input)
+ {
+ /* Only set SEC_READONLY flag on the first input section. */
+ flags &= ~ SEC_READONLY;
/* Keep SEC_MERGE and SEC_STRINGS only if they are the same. */
- if (! first
- && ((output->bfd_section->flags & (SEC_MERGE | SEC_STRINGS))
- != (flags & (SEC_MERGE | SEC_STRINGS))
- || ((flags & SEC_MERGE)
- && output->bfd_section->entsize != section->entsize)))
+ if ((output->bfd_section->flags & (SEC_MERGE | SEC_STRINGS))
+ != (flags & (SEC_MERGE | SEC_STRINGS))
+ || ((flags & SEC_MERGE) != 0
+ && output->bfd_section->entsize != section->entsize))
{
output->bfd_section->flags &= ~ (SEC_MERGE | SEC_STRINGS);
flags &= ~ (SEC_MERGE | SEC_STRINGS);
}
+ }
+ output->bfd_section->flags |= flags;
- output->bfd_section->flags |= flags;
-
- if (flags & SEC_MERGE)
+ if (!output->bfd_section->linker_has_input)
+ {
+ output->bfd_section->linker_has_input = 1;
+ /* This must happen after flags have been updated. The output
+ section may have been created before we saw its first input
+ section, eg. for a data statement. */
+ bfd_init_private_section_data (section->owner, section,
+ link_info.output_bfd,
+ output->bfd_section,
+ &link_info);
+ if ((flags & SEC_MERGE) != 0)
output->bfd_section->entsize = section->entsize;
+ }
- /* If SEC_READONLY is not set in the input section, then clear
- it from the output section. */
- if ((section->flags & SEC_READONLY) == 0)
- output->bfd_section->flags &= ~SEC_READONLY;
+ if ((flags & SEC_TIC54X_BLOCK) != 0
+ && bfd_get_arch (section->owner) == bfd_arch_tic54x)
+ {
+ /* FIXME: This value should really be obtained from the bfd... */
+ output->block_value = 128;
+ }
- /* Copy over SEC_SMALL_DATA. */
- if (section->flags & SEC_SMALL_DATA)
- output->bfd_section->flags |= SEC_SMALL_DATA;
+ if (section->alignment_power > output->bfd_section->alignment_power)
+ output->bfd_section->alignment_power = section->alignment_power;
- if (section->alignment_power > output->bfd_section->alignment_power)
- output->bfd_section->alignment_power = section->alignment_power;
+ section->output_section = output->bfd_section;
- if (bfd_get_arch (section->owner) == bfd_arch_tic54x
- && (section->flags & SEC_TIC54X_BLOCK) != 0)
- {
- output->bfd_section->flags |= SEC_TIC54X_BLOCK;
- /* FIXME: This value should really be obtained from the bfd... */
- output->block_value = 128;
- }
+ if (!link_info.relocatable
+ && !stripped_excluded_sections)
+ {
+ asection *s = output->bfd_section->map_tail.s;
+ output->bfd_section->map_tail.s = section;
+ section->map_head.s = NULL;
+ section->map_tail.s = s;
+ if (s != NULL)
+ s->map_head.s = section;
+ else
+ output->bfd_section->map_head.s = section;
}
+
+ /* Add a section reference to the list. */
+ new_section = new_stat (lang_input_section, ptr);
+ new_section->section = section;
}
/* Handle wildcard sorting. This returns the lang_input_section which
lang_input_statement_type *file,
asection *section)
{
- const char *section_name;
lang_statement_union_type *l;
if (!wild->filenames_sorted
&& (sec == NULL || sec->spec.sorted == none))
return NULL;
- section_name = bfd_get_section_name (file->the_bfd, section);
for (l = wild->children.head; l != NULL; l = l->header.next)
{
lang_input_section_type *ls;
void *output)
{
lang_statement_union_type *before;
+ lang_output_section_statement_type *os;
+
+ os = (lang_output_section_statement_type *) output;
/* Exclude sections that match UNIQUE_SECTION_LIST. */
- if (unique_section_p (section))
+ if (unique_section_p (section, os))
return;
before = wild_sort (ptr, sec, file, section);
of the current list. */
if (before == NULL)
- lang_add_section (&ptr->children, section,
- (lang_output_section_statement_type *) output);
+ lang_add_section (&ptr->children, section, os);
else
{
lang_statement_list_type list;
lang_statement_union_type **pp;
lang_list_init (&list);
- lang_add_section (&list, section,
- (lang_output_section_statement_type *) output);
+ lang_add_section (&list, section, os);
/* If we are discarding the section, LIST.HEAD will
be NULL. */
struct wildcard_list *sec ATTRIBUTE_UNUSED,
asection *section,
lang_input_statement_type *file ATTRIBUTE_UNUSED,
- void *data)
+ void *output)
{
+ lang_output_section_statement_type *os;
+
+ os = (lang_output_section_statement_type *) output;
+
/* Exclude sections that match UNIQUE_SECTION_LIST. */
- if (unique_section_p (section))
+ if (unique_section_p (section, os))
return;
if (section->output_section == NULL && (section->flags & SEC_READONLY) == 0)
- ((lang_output_section_statement_type *) data)->all_input_readonly = FALSE;
+ os->all_input_readonly = FALSE;
}
/* This is passed a file name which must have been seen already and
end = strpbrk (p, ",:");
if (end == NULL)
end = p + strlen (p);
- entry = xmalloc (sizeof (*entry));
+ entry = (struct excluded_lib *) xmalloc (sizeof (*entry));
entry->next = excluded_libs;
- entry->name = xmalloc (end - p + 1);
+ entry->name = (char *) xmalloc (end - p + 1);
memcpy (entry->name, p, end - p);
entry->name[end - p] = '\0';
excluded_libs = entry;
ldfile_open_file (entry);
+ /* Do not process further if the file was missing. */
+ if (entry->missing_file)
+ return TRUE;
+
if (! bfd_check_format (entry->the_bfd, bfd_archive)
&& ! bfd_check_format_matches (entry->the_bfd, bfd_object, &matching))
{
bfd_error_type err;
bfd_boolean save_ldlang_sysrooted_script;
- bfd_boolean save_as_needed, save_add_needed;
+ bfd_boolean save_add_DT_NEEDED_for_regular;
+ bfd_boolean save_add_DT_NEEDED_for_dynamic;
+ bfd_boolean save_whole_archive;
err = bfd_get_error ();
push_stat_ptr (place);
save_ldlang_sysrooted_script = ldlang_sysrooted_script;
ldlang_sysrooted_script = entry->sysrooted;
- save_as_needed = as_needed;
- as_needed = entry->as_needed;
- save_add_needed = add_needed;
- add_needed = entry->add_needed;
+ save_add_DT_NEEDED_for_regular = add_DT_NEEDED_for_regular;
+ add_DT_NEEDED_for_regular = entry->add_DT_NEEDED_for_regular;
+ save_add_DT_NEEDED_for_dynamic = add_DT_NEEDED_for_dynamic;
+ add_DT_NEEDED_for_dynamic = entry->add_DT_NEEDED_for_dynamic;
+ save_whole_archive = whole_archive;
+ whole_archive = entry->whole_archive;
ldfile_assumed_script = TRUE;
parser_input = input_script;
ldfile_assumed_script = FALSE;
ldlang_sysrooted_script = save_ldlang_sysrooted_script;
- as_needed = save_as_needed;
- add_needed = save_add_needed;
+ add_DT_NEEDED_for_regular = save_add_DT_NEEDED_for_regular;
+ add_DT_NEEDED_for_dynamic = save_add_DT_NEEDED_for_dynamic;
+ whole_archive = save_whole_archive;
pop_stat_ptr ();
return TRUE;
static int
get_target (const bfd_target *target, void *data)
{
- const char *sought = data;
+ const char *sought = (const char *) data;
return strcmp (target->name, sought) == 0;
}
char *copy2;
int result;
- copy1 = xmalloc (strlen (first) + 1);
- copy2 = xmalloc (strlen (second) + 1);
+ copy1 = (char *) xmalloc (strlen (first) + 1);
+ copy2 = (char *) xmalloc (strlen (second) + 1);
/* Convert the names to lower case. */
stricpy (copy1, first);
static int
closest_target_match (const bfd_target *target, void *data)
{
- const bfd_target *original = data;
+ const bfd_target *original = (const bfd_target *) data;
if (command_line.endian == ENDIAN_BIG
&& target->byteorder != BFD_ENDIAN_BIG)
break;
}
}
+
+ /* Exit if any of the files were missing. */
+ if (missing_file)
+ einfo ("%F");
}
/* Add a symbol to a hash of symbols used in DEFINED (NAME) expressions. */
void
ldlang_add_undef (const char *const name)
{
- ldlang_undef_chain_list_type *new =
- stat_alloc (sizeof (ldlang_undef_chain_list_type));
+ ldlang_undef_chain_list_type *new_undef = (ldlang_undef_chain_list_type *)
+ stat_alloc (sizeof (ldlang_undef_chain_list_type));
- new->next = ldlang_undef_chain_list_head;
- ldlang_undef_chain_list_head = new;
+ new_undef->next = ldlang_undef_chain_list_head;
+ ldlang_undef_chain_list_head = new_undef;
- new->name = xstrdup (name);
+ new_undef->name = xstrdup (name);
if (link_info.output_bfd != NULL)
- insert_undefined (new->name);
+ insert_undefined (new_undef->name);
}
/* Insert NAME as undefined in the symbol table. */
(lang_statement_union_type *s, const char *target,
lang_output_section_statement_type *os)
{
- flagword flags;
-
for (; s != NULL; s = s->header.next)
{
+ lang_output_section_statement_type *tos;
+ flagword flags;
+
switch (s->header.type)
{
case lang_wild_statement_enum:
os);
break;
case lang_output_section_statement_enum:
- if (s->output_section_statement.constraint)
+ tos = &s->output_section_statement;
+ if (tos->constraint != 0)
{
- if (s->output_section_statement.constraint != ONLY_IF_RW
- && s->output_section_statement.constraint != ONLY_IF_RO)
+ if (tos->constraint != ONLY_IF_RW
+ && tos->constraint != ONLY_IF_RO)
break;
- s->output_section_statement.all_input_readonly = TRUE;
- check_input_sections (s->output_section_statement.children.head,
- &s->output_section_statement);
- if ((s->output_section_statement.all_input_readonly
- && s->output_section_statement.constraint == ONLY_IF_RW)
- || (!s->output_section_statement.all_input_readonly
- && s->output_section_statement.constraint == ONLY_IF_RO))
+ tos->all_input_readonly = TRUE;
+ check_input_sections (tos->children.head, tos);
+ if (tos->all_input_readonly != (tos->constraint == ONLY_IF_RO))
{
- s->output_section_statement.constraint = -1;
+ tos->constraint = -1;
break;
}
}
-
- map_input_to_output_sections (s->output_section_statement.children.head,
+ map_input_to_output_sections (tos->children.head,
target,
- &s->output_section_statement);
+ tos);
break;
case lang_output_statement_enum:
break;
/* Make sure that any sections mentioned in the expression
are initialized. */
exp_init_os (s->data_statement.exp);
- flags = SEC_HAS_CONTENTS;
- /* The output section gets contents, and then we inspect for
- any flags set in the input script which override any ALLOC. */
- if (!(os->flags & SEC_NEVER_LOAD))
- flags |= SEC_ALLOC | SEC_LOAD;
+ /* The output section gets CONTENTS, and usually ALLOC and
+ LOAD, but the latter two may be overridden by the script. */
+ flags = SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD;
+ switch (os->sectype)
+ {
+ case normal_section:
+ case overlay_section:
+ break;
+ case noalloc_section:
+ flags = SEC_HAS_CONTENTS;
+ break;
+ case noload_section:
+ flags = SEC_HAS_CONTENTS | SEC_NEVER_LOAD;
+ break;
+ }
if (os->bfd_section == NULL)
- init_os (os, NULL, flags);
+ init_os (os, flags);
else
os->bfd_section->flags |= flags;
break;
case lang_padding_statement_enum:
case lang_input_statement_enum:
if (os != NULL && os->bfd_section == NULL)
- init_os (os, NULL, 0);
+ init_os (os, 0);
break;
case lang_assignment_statement_enum:
if (os != NULL && os->bfd_section == NULL)
- init_os (os, NULL, 0);
+ init_os (os, 0);
/* Make sure that any sections mentioned in the assignment
are initialized. */
if (!s->address_statement.segment
|| !s->address_statement.segment->used)
{
- lang_output_section_statement_type *aos
- = (lang_output_section_statement_lookup
- (s->address_statement.section_name, 0, TRUE));
-
- if (aos->bfd_section == NULL)
- init_os (aos, NULL, 0);
- aos->addr_tree = s->address_statement.address;
+ const char *name = s->address_statement.section_name;
+
+ /* Create the output section statement here so that
+ orphans with a set address will be placed after other
+ script sections. If we let the orphan placement code
+ place them in amongst other sections then the address
+ will affect following script sections, which is
+ likely to surprise naive users. */
+ tos = lang_output_section_statement_lookup (name, 0, TRUE);
+ tos->addr_tree = s->address_statement.address;
+ if (tos->bfd_section == NULL)
+ init_os (tos, 0);
}
break;
case lang_insert_statement_enum:
static bfd_boolean
print_one_symbol (struct bfd_link_hash_entry *hash_entry, void *ptr)
{
- asection *sec = ptr;
+ asection *sec = (asection *) ptr;
if ((hash_entry->type == bfd_link_hash_defined
|| hash_entry->type == bfd_link_hash_defweak)
return TRUE;
}
+static int
+hash_entry_addr_cmp (const void *a, const void *b)
+{
+ const struct bfd_link_hash_entry *l = *(const struct bfd_link_hash_entry **)a;
+ const struct bfd_link_hash_entry *r = *(const struct bfd_link_hash_entry **)b;
+
+ if (l->u.def.value < r->u.def.value)
+ return -1;
+ else if (l->u.def.value > r->u.def.value)
+ return 1;
+ else
+ return 0;
+}
+
static void
print_all_symbols (asection *sec)
{
- struct fat_user_section_struct *ud = get_userdata (sec);
+ struct fat_user_section_struct *ud =
+ (struct fat_user_section_struct *) get_userdata (sec);
struct map_symbol_def *def;
+ struct bfd_link_hash_entry **entries;
+ unsigned int i;
if (!ud)
return;
*ud->map_symbol_def_tail = 0;
- for (def = ud->map_symbol_def_head; def; def = def->next)
- print_one_symbol (def->entry, sec);
+
+ /* Sort the symbols by address. */
+ entries = (struct bfd_link_hash_entry **)
+ obstack_alloc (&map_obstack, ud->map_symbol_def_count * sizeof (*entries));
+
+ for (i = 0, def = ud->map_symbol_def_head; def; def = def->next, i++)
+ entries[i] = def->entry;
+
+ qsort (entries, ud->map_symbol_def_count, sizeof (*entries),
+ hash_entry_addr_cmp);
+
+ /* Print the symbols. */
+ for (i = 0; i < ud->map_symbol_def_count; i++)
+ print_one_symbol (entries[i], sec);
+
+ obstack_free (&map_obstack, entries);
}
/* Print information about an input section to the map file. */
static void
-print_input_section (asection *i)
+print_input_section (asection *i, bfd_boolean is_discarded)
{
bfd_size_type size = i->size;
int len;
else
{
addr = print_dot;
- size = 0;
+ if (!is_discarded)
+ size = 0;
}
minfo ("0x%V %W %B\n", addr, TO_ADDR (size), i->owner);
print_reloc_statement (&s->reloc_statement);
break;
case lang_input_section_enum:
- print_input_section (s->input_section.section);
+ print_input_section (s->input_section.section, FALSE);
break;
case lang_padding_statement_enum:
print_padding_statement (&s->padding_statement);
else
{
/* Make a new padding statement, linked into existing chain. */
- pad = stat_alloc (sizeof (lang_padding_statement_type));
+ pad = (lang_statement_union_type *)
+ stat_alloc (sizeof (lang_padding_statement_type));
pad->header.next = *ptr;
*ptr = pad;
pad->header.type = lang_padding_statement_enum;
return;
amt = bfd_count_sections (link_info.output_bfd) * sizeof (asection *);
- sections = xmalloc (amt);
+ sections = (asection **) xmalloc (amt);
/* Scan all sections in the output list. */
count = 0;
for (s = link_info.output_bfd->sections; s != NULL; s = s->next)
{
/* Only consider loadable sections with real contents. */
- if (IGNORE_SECTION (s) || s->size == 0)
+ if ((s->flags & SEC_NEVER_LOAD)
+ || !(s->flags & SEC_LOAD)
+ || !(s->flags & SEC_ALLOC)
+ || s->size == 0)
continue;
sections[count] = s;
/* Look for an overlap. */
if (s_end >= os_start && s_start <= os_end)
- einfo (_("%X%P: section %s [%V -> %V] overlaps section %s [%V -> %V]\n"),
+ einfo (_("%X%P: section %s loaded at [%V,%V] overlaps section %s loaded at [%V,%V]\n"),
s->name, s_start, s_end, os->name, os_start, os_end);
}
os_region_check (lang_output_section_statement_type *os,
lang_memory_region_type *region,
etree_type *tree,
- bfd_vma base)
+ bfd_vma rbase)
{
if ((region->current < region->origin
|| (region->current - region->origin > region->length))
&& ((region->current != region->origin + region->length)
- || base == 0))
+ || rbase == 0))
{
if (tree != NULL)
{
static bfd_vma
lang_size_sections_1
- (lang_statement_union_type *s,
+ (lang_statement_union_type **prev,
lang_output_section_statement_type *output_section_statement,
- lang_statement_union_type **prev,
fill_type *fill,
bfd_vma dot,
bfd_boolean *relax,
bfd_boolean check_regions)
{
+ lang_statement_union_type *s;
+
/* Size up the sections from their constituent parts. */
- for (; s != NULL; s = s->header.next)
+ for (s = *prev; s != NULL; s = s->header.next)
{
switch (s->header.type)
{
lang_memory_region_type *r;
os = &s->output_section_statement;
+ /* FIXME: We shouldn't need to zero section vmas for ld -r
+ here, in lang_insert_orphan, or in the default linker scripts.
+ This is covering for coff backend linker bugs. See PR6945. */
+ if (os->addr_tree == NULL
+ && link_info.relocatable
+ && (bfd_get_flavour (link_info.output_bfd)
+ == bfd_target_coff_flavour))
+ os->addr_tree = exp_intop (0);
if (os->addr_tree != NULL)
{
os->processed_vma = FALSE;
os->name, (unsigned long) (newdot - savedot));
}
- /* PR 6945: Do not update the vma's of output sections
- when performing a relocatable link on COFF objects. */
- if (! link_info.relocatable
- || (bfd_get_flavour (link_info.output_bfd)
- != bfd_target_coff_flavour))
- bfd_set_section_vma (0, os->bfd_section, newdot);
+ 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,
+ lang_size_sections_1 (&os->children.head, os,
os->fill, newdot, relax, check_regions);
os->processed_vma = TRUE;
break;
case lang_constructors_statement_enum:
- dot = lang_size_sections_1 (constructor_list.head,
+ dot = lang_size_sections_1 (&constructor_list.head,
output_section_statement,
- &s->wild_statement.children.head,
fill, dot, relax, check_regions);
break;
break;
case lang_wild_statement_enum:
- dot = lang_size_sections_1 (s->wild_statement.children.head,
+ dot = lang_size_sections_1 (&s->wild_statement.children.head,
output_section_statement,
- &s->wild_statement.children.head,
fill, dot, relax, check_regions);
break;
{
asection *i;
- i = (*prev)->input_section.section;
+ i = s->input_section.section;
if (relax)
{
bfd_boolean again;
break;
case lang_group_statement_enum:
- dot = lang_size_sections_1 (s->group_statement.children.head,
+ dot = lang_size_sections_1 (&s->group_statement.children.head,
output_section_statement,
- &s->group_statement.children.head,
fill, dot, relax, check_regions);
break;
one_lang_size_sections_pass (bfd_boolean *relax, bfd_boolean check_regions)
{
lang_statement_iteration++;
- lang_size_sections_1 (statement_list.head, abs_output_section,
- &statement_list.head, 0, 0, relax, check_regions);
+ lang_size_sections_1 (&statement_list.head, abs_output_section,
+ 0, 0, relax, check_regions);
}
void
struct bfd_link_hash_entry *h;
secname = bfd_get_section_name (link_info.output_bfd, s);
- buf = xmalloc (10 + strlen (secname));
+ buf = (char *) xmalloc (10 + strlen (secname));
sprintf (buf, ".startof.%s", secname);
h = bfd_link_hash_lookup (link_info.hash, buf, FALSE, FALSE, TRUE);
return TRUE;
section = h->u.c.p->section;
-
- /* Increase the size of the section to align the common sym. */
- section->size += ((bfd_vma) 1 << (power_of_two + opb_shift)) - 1;
- section->size &= (- (bfd_vma) 1 << (power_of_two + opb_shift));
-
- /* Adjust the alignment if necessary. */
- if (power_of_two > section->alignment_power)
- section->alignment_power = power_of_two;
-
- /* Change the symbol from common to defined. */
- h->type = bfd_link_hash_defined;
- h->u.def.section = section;
- h->u.def.value = section->size;
-
- /* Increase the size of the section. */
- section->size += size;
-
- /* Make sure the section is allocated in memory, and make sure that
- it is no longer a common section. */
- section->flags |= SEC_ALLOC;
- section->flags &= ~SEC_IS_COMMON;
+ if (!bfd_define_common_symbol (link_info.output_bfd, &link_info, h))
+ einfo (_("%P%F: Could not define common symbol `%T': %E\n"),
+ h->root.string);
if (config.map_file != NULL)
{
const char *name = s->name;
int constraint = 0;
- if (config.unique_orphan_sections || unique_section_p (s))
+ if (config.unique_orphan_sections
+ || unique_section_p (s, NULL))
constraint = SPECIAL;
if (!ldemul_place_orphan (s, name, constraint))
void
lang_final (void)
{
- lang_output_statement_type *new;
+ lang_output_statement_type *new_stmt;
+
+ new_stmt = new_stat (lang_output_statement, stat_ptr);
+ new_stmt->name = output_filename;
- new = new_stat (lang_output_statement, stat_ptr);
- new->name = output_filename;
}
/* Reset the current counters in the regions. */
/* Relax all sections until bfd_relax_section gives up. */
-static void
-relax_sections (void)
+void
+lang_relax_sections (bfd_boolean need_layout)
{
- /* Keep relaxing until bfd_relax_section gives up. */
- bfd_boolean relax_again;
-
- link_info.relax_trip = -1;
- do
+ if (RELAXATION_ENABLED)
{
- relax_again = FALSE;
- link_info.relax_trip++;
+ /* We may need more than one relaxation pass. */
+ int i = link_info.relax_pass;
- /* Note: pe-dll.c does something like this also. If you find
- you need to change this code, you probably need to change
- pe-dll.c also. DJ */
+ /* The backend can use it to determine the current pass. */
+ link_info.relax_pass = 0;
- /* Do all the assignments with our current guesses as to
- section sizes. */
- lang_do_assignments ();
+ while (i--)
+ {
+ /* Keep relaxing until bfd_relax_section gives up. */
+ bfd_boolean relax_again;
- /* We must do this after lang_do_assignments, because it uses
- size. */
- lang_reset_memory_regions ();
+ link_info.relax_trip = -1;
+ do
+ {
+ link_info.relax_trip++;
+
+ /* Note: pe-dll.c does something like this also. If you find
+ you need to change this code, you probably need to change
+ pe-dll.c also. DJ */
+
+ /* Do all the assignments with our current guesses as to
+ section sizes. */
+ lang_do_assignments ();
+
+ /* We must do this after lang_do_assignments, because it uses
+ size. */
+ lang_reset_memory_regions ();
+
+ /* Perform another relax pass - this time we know where the
+ globals are, so can make a better guess. */
+ relax_again = FALSE;
+ lang_size_sections (&relax_again, FALSE);
+ }
+ while (relax_again);
- /* Perform another relax pass - this time we know where the
- globals are, so can make a better guess. */
- lang_size_sections (&relax_again, FALSE);
+ link_info.relax_pass++;
+ }
+ need_layout = TRUE;
+ }
+
+ if (need_layout)
+ {
+ /* Final extra sizing to report errors. */
+ lang_do_assignments ();
+ lang_reset_memory_regions ();
+ lang_size_sections (NULL, TRUE);
}
- while (relax_again);
}
void
lang_find_relro_sections ();
/* Size up the sections. */
- lang_size_sections (NULL, !command_line.relax);
-
- /* Now run around and relax if we can. */
- if (command_line.relax)
- {
- /* We may need more than one relaxation pass. */
- int i = link_info.relax_pass;
-
- /* The backend can use it to determine the current pass. */
- link_info.relax_pass = 0;
-
- while (i--)
- {
- relax_sections ();
- link_info.relax_pass++;
- }
-
- /* Final extra sizing to report errors. */
- lang_do_assignments ();
- lang_reset_memory_regions ();
- lang_size_sections (NULL, TRUE);
- }
+ lang_size_sections (NULL, ! RELAXATION_ENABLED);
/* See if anything special should be done now we know how big
- everything is. */
+ everything is. This is where relaxation is done. */
ldemul_after_allocation ();
/* Fix any .startof. or .sizeof. symbols. */
bfd_boolean keep_sections)
{
struct wildcard_list *curr, *next;
- lang_wild_statement_type *new;
+ lang_wild_statement_type *new_stmt;
/* Reverse the list as the parser puts it back to front. */
for (curr = section_list, section_list = NULL;
lang_has_input_file = TRUE;
}
- new = new_stat (lang_wild_statement, stat_ptr);
- new->filename = NULL;
- new->filenames_sorted = FALSE;
+ new_stmt = new_stat (lang_wild_statement, stat_ptr);
+ new_stmt->filename = NULL;
+ new_stmt->filenames_sorted = FALSE;
if (filespec != NULL)
{
- new->filename = filespec->name;
- new->filenames_sorted = filespec->sorted == by_name;
+ new_stmt->filename = filespec->name;
+ new_stmt->filenames_sorted = filespec->sorted == by_name;
}
- new->section_list = section_list;
- new->keep_sections = keep_sections;
- lang_list_init (&new->children);
- analyze_walk_wild_section_handler (new);
+ new_stmt->section_list = section_list;
+ new_stmt->keep_sections = keep_sections;
+ lang_list_init (&new_stmt->children);
+ analyze_walk_wild_section_handler (new_stmt);
}
void
void
lang_add_target (const char *name)
{
- lang_target_statement_type *new;
+ lang_target_statement_type *new_stmt;
- new = new_stat (lang_target_statement, stat_ptr);
- new->target = name;
+ new_stmt = new_stat (lang_target_statement, stat_ptr);
+ new_stmt->target = name;
}
void
void
lang_add_fill (fill_type *fill)
{
- lang_fill_statement_type *new;
+ lang_fill_statement_type *new_stmt;
- new = new_stat (lang_fill_statement, stat_ptr);
- new->fill = fill;
+ new_stmt = new_stat (lang_fill_statement, stat_ptr);
+ new_stmt->fill = fill;
}
void
lang_add_data (int type, union etree_union *exp)
{
- lang_data_statement_type *new;
+ lang_data_statement_type *new_stmt;
- new = new_stat (lang_data_statement, stat_ptr);
- new->exp = exp;
- new->type = type;
+ new_stmt = new_stat (lang_data_statement, stat_ptr);
+ new_stmt->exp = exp;
+ new_stmt->type = type;
}
/* Create a new reloc statement. RELOC is the BFD relocation type to
lang_assignment_statement_type *
lang_add_assignment (etree_type *exp)
{
- lang_assignment_statement_type *new;
+ lang_assignment_statement_type *new_stmt;
- new = new_stat (lang_assignment_statement, stat_ptr);
- new->exp = exp;
- return new;
+ new_stmt = new_stat (lang_assignment_statement, stat_ptr);
+ new_stmt->exp = exp;
+ return new_stmt;
}
void
void
lang_add_insert (const char *where, int is_before)
{
- lang_insert_statement_type *new;
+ lang_insert_statement_type *new_stmt;
- new = new_stat (lang_insert_statement, stat_ptr);
- new->where = where;
- new->is_before = is_before;
+ new_stmt = new_stat (lang_insert_statement, stat_ptr);
+ new_stmt->where = where;
+ new_stmt->is_before = is_before;
saved_script_handle = previous_script_handle;
}
etree_type *flags)
{
struct lang_phdr *n, **pp;
+ bfd_boolean hdrs;
- n = stat_alloc (sizeof (struct lang_phdr));
+ n = (struct lang_phdr *) stat_alloc (sizeof (struct lang_phdr));
n->next = NULL;
n->name = name;
n->type = exp_get_value_int (type, 0, "program header type");
n->phdrs = phdrs;
n->at = at;
n->flags = flags;
+
+ hdrs = n->type == 1 && (phdrs || filehdr);
for (pp = &lang_phdr_list; *pp != NULL; pp = &(*pp)->next)
- ;
+ if (hdrs
+ && (*pp)->type == 1
+ && !((*pp)->filehdr || (*pp)->phdrs))
+ {
+ einfo (_("%X%P:%S: PHDRS and FILEHDR are not supported when prior PT_LOAD headers lack them\n"));
+ hdrs = FALSE;
+ }
+
*pp = n;
}
lang_output_section_statement_type *os;
alc = 10;
- secs = xmalloc (alc * sizeof (asection *));
+ secs = (asection **) xmalloc (alc * sizeof (asection *));
last = NULL;
for (l = lang_phdr_list; l != NULL; l = l->next)
if (c >= alc)
{
alc *= 2;
- secs = xrealloc (secs, alc * sizeof (asection *));
+ secs = (asection **) xrealloc (secs,
+ alc * sizeof (asection *));
}
secs[c] = os->bfd_section;
++c;
{
struct lang_nocrossrefs *n;
- n = xmalloc (sizeof *n);
+ n = (struct lang_nocrossrefs *) xmalloc (sizeof *n);
n->next = nocrossref_list;
n->list = l;
nocrossref_list = n;
overlay_vma = exp_nameop (ADDR, name);
/* Remember the section. */
- n = xmalloc (sizeof *n);
+ n = (struct overlay_list *) xmalloc (sizeof *n);
n->os = current_section;
n->next = overlay_list;
overlay_list = n;
/* Define the magic symbols. */
- clean = xmalloc (strlen (name) + 1);
+ clean = (char *) xmalloc (strlen (name) + 1);
s2 = clean;
for (s1 = name; *s1 != '\0'; s1++)
if (ISALNUM (*s1) || *s1 == '_')
*s2++ = *s1;
*s2 = '\0';
- buf = xmalloc (strlen (clean) + sizeof "__load_start_");
+ buf = (char *) xmalloc (strlen (clean) + sizeof "__load_start_");
sprintf (buf, "__load_start_%s", clean);
lang_add_assignment (exp_provide (buf,
exp_nameop (LOADADDR, name),
FALSE));
- buf = xmalloc (strlen (clean) + sizeof "__load_stop_");
+ buf = (char *) xmalloc (strlen (clean) + sizeof "__load_stop_");
sprintf (buf, "__load_stop_%s", clean);
lang_add_assignment (exp_provide (buf,
exp_binop ('+',
{
lang_nocrossref_type *nc;
- nc = xmalloc (sizeof *nc);
+ nc = (lang_nocrossref_type *) xmalloc (sizeof *nc);
nc->name = l->os->name;
nc->next = nocrossref;
nocrossref = nc;
if (head->mask & BFD_ELF_VERSION_C_TYPE)
{
e.pattern = sym;
- expr = htab_find (head->htab, &e);
+ expr = (struct bfd_elf_version_expr *)
+ htab_find ((htab_t) head->htab, &e);
while (expr && strcmp (expr->pattern, sym) == 0)
if (expr->mask == BFD_ELF_VERSION_C_TYPE)
goto out_ret;
if (head->mask & BFD_ELF_VERSION_CXX_TYPE)
{
e.pattern = cxx_sym;
- expr = htab_find (head->htab, &e);
+ expr = (struct bfd_elf_version_expr *)
+ htab_find ((htab_t) head->htab, &e);
while (expr && strcmp (expr->pattern, cxx_sym) == 0)
if (expr->mask == BFD_ELF_VERSION_CXX_TYPE)
goto out_ret;
if (head->mask & BFD_ELF_VERSION_JAVA_TYPE)
{
e.pattern = java_sym;
- expr = htab_find (head->htab, &e);
+ expr = (struct bfd_elf_version_expr *)
+ htab_find ((htab_t) head->htab, &e);
while (expr && strcmp (expr->pattern, java_sym) == 0)
if (expr->mask == BFD_ELF_VERSION_JAVA_TYPE)
goto out_ret;
{
const char *p;
bfd_boolean changed = FALSE, backslash = FALSE;
- char *s, *symbol = xmalloc (strlen (pattern) + 1);
+ char *s, *symbol = (char *) xmalloc (strlen (pattern) + 1);
for (p = pattern, s = symbol; *p != '\0'; ++p)
{
}
}
-/* This is called for each variable name or match expression. NEW is
+/* This is called for each variable name or match expression. NEW_NAME 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 *new_name,
const char *lang,
bfd_boolean literal_p)
{
struct bfd_elf_version_expr *ret;
- ret = xmalloc (sizeof *ret);
+ ret = (struct bfd_elf_version_expr *) xmalloc (sizeof *ret);
ret->next = orig;
ret->symver = 0;
ret->script = 0;
ret->literal = TRUE;
- ret->pattern = literal_p ? new : realsymbol (new);
+ ret->pattern = literal_p ? new_name : realsymbol (new_name);
if (ret->pattern == NULL)
{
- ret->pattern = new;
+ ret->pattern = new_name;
ret->literal = FALSE;
}
{
struct bfd_elf_version_tree *ret;
- ret = xcalloc (1, sizeof *ret);
+ ret = (struct bfd_elf_version_tree *) xcalloc (1, sizeof *ret);
ret->globals.list = globals;
ret->locals.list = locals;
ret->match = lang_vers_match;
static hashval_t
version_expr_head_hash (const void *p)
{
- const struct bfd_elf_version_expr *e = p;
+ const struct bfd_elf_version_expr *e =
+ (const struct bfd_elf_version_expr *) p;
return htab_hash_string (e->pattern);
}
static int
version_expr_head_eq (const void *p1, const void *p2)
{
- const struct bfd_elf_version_expr *e1 = p1;
- const struct bfd_elf_version_expr *e2 = p2;
+ const struct bfd_elf_version_expr *e1 =
+ (const struct bfd_elf_version_expr *) p1;
+ const struct bfd_elf_version_expr *e2 =
+ (const struct bfd_elf_version_expr *) p2;
return strcmp (e1->pattern, e2->pattern) == 0;
}
}
else
{
- void **loc = htab_find_slot (head->htab, e, INSERT);
+ void **loc = htab_find_slot ((htab_t) head->htab, e, INSERT);
if (*loc)
{
struct bfd_elf_version_expr *e1, *last;
- e1 = *loc;
+ e1 = (struct bfd_elf_version_expr *) *loc;
last = NULL;
do
{
if (t->locals.htab && e1->literal)
{
- e2 = htab_find (t->locals.htab, e1);
+ e2 = (struct bfd_elf_version_expr *)
+ htab_find ((htab_t) t->locals.htab, e1);
while (e2 && strcmp (e1->pattern, e2->pattern) == 0)
{
if (e1->mask == e2->mask)
if (t->globals.htab && e1->literal)
{
- e2 = htab_find (t->globals.htab, e1);
+ e2 = (struct bfd_elf_version_expr *)
+ htab_find ((htab_t) t->globals.htab, e1);
while (e2 && strcmp (e1->pattern, e2->pattern) == 0)
{
if (e1->mask == e2->mask)
struct bfd_elf_version_deps *ret;
struct bfd_elf_version_tree *t;
- ret = xmalloc (sizeof *ret);
+ ret = (struct bfd_elf_version_deps *) xmalloc (sizeof *ret);
ret->next = list;
for (t = lang_elf_version_info; t != NULL; t = t->next)
continue;
len = sec->size;
- contents = xmalloc (len);
+ contents = (char *) xmalloc (len);
if (!bfd_get_section_contents (is->the_bfd, sec, contents, 0, len))
einfo (_("%X%P: unable to read .exports section contents\n"), sec);
if (strcmp (ent->name, name) == 0)
return;
- ent = xmalloc (sizeof *ent);
+ ent = (struct unique_sections *) xmalloc (sizeof *ent);
ent->name = xstrdup (name);
ent->next = unique_section_list;
unique_section_list = ent;
{
struct bfd_elf_dynamic_list *d;
- d = xcalloc (1, sizeof *d);
+ d = (struct bfd_elf_dynamic_list *) xcalloc (1, sizeof *d);
d->head.list = dynamic;
d->match = lang_vers_match;
link_info.dynamic_list = d;