/* Linker command language support.
Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002
+ 2001, 2002, 2003
Free Software Foundation, Inc.
-This file is part of GLD, the Gnu Linker.
+ This file is part of GLD, the Gnu Linker.
-GLD is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+ GLD is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
-GLD is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+ GLD is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
-You should have received a copy of the GNU General Public License
-along with GLD; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+ You should have received a copy of the GNU General Public License
+ along with GLD; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
#include "bfd.h"
#include "sysdep.h"
#include "ldmain.h"
#include "ldexp.h"
#include "ldlang.h"
-#include "ldgram.h"
+#include <ldgram.h>
#include "ldlex.h"
#include "ldmisc.h"
#include "ldctor.h"
#include "fnmatch.h"
#include "demangle.h"
-/* FORWARDS */
-static lang_statement_union_type *new_statement
- PARAMS ((enum statement_enum, size_t, lang_statement_list_type *));
+#ifndef offsetof
+#define offsetof(TYPE, MEMBER) ((size_t) & (((TYPE*) 0)->MEMBER))
+#endif
-/* LOCALS */
+/* Locals variables. */
static struct obstack stat_obstack;
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
static const char *startup_file;
static lang_statement_list_type input_file_chain;
-static boolean placed_commons = false;
+static bfd_boolean placed_commons = FALSE;
static lang_output_section_statement_type *default_common_section;
-static boolean map_option_f;
+static bfd_boolean map_option_f;
static bfd_vma print_dot;
static lang_input_statement_type *first_file;
static const char *current_target;
static lang_statement_list_type statement_list;
static struct lang_phdr *lang_phdr_list;
+/* Forward declarations. */
+static lang_statement_union_type *new_statement
+ PARAMS ((enum statement_enum, size_t, lang_statement_list_type *));
static void lang_for_each_statement_worker
PARAMS ((void (*) (lang_statement_union_type *),
lang_statement_union_type *));
static lang_input_statement_type *new_afile
- PARAMS ((const char *, lang_input_file_enum_type, const char *, boolean));
-static lang_memory_region_type *lang_memory_default PARAMS ((asection *));
-static void lang_map_flags PARAMS ((flagword));
-static void init_os PARAMS ((lang_output_section_statement_type *));
-static void exp_init_os PARAMS ((etree_type *));
-static void section_already_linked PARAMS ((bfd *, asection *, PTR));
+ PARAMS ((const char *, lang_input_file_enum_type, const char *,
+ bfd_boolean));
+static lang_memory_region_type *lang_memory_default
+ PARAMS ((asection *));
+static void lang_map_flags
+ PARAMS ((flagword));
+static void init_os
+ PARAMS ((lang_output_section_statement_type *));
+static void exp_init_os
+ PARAMS ((etree_type *));
+static void section_already_linked
+ PARAMS ((bfd *, asection *, PTR));
static struct bfd_hash_entry *already_linked_newfunc
PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
-static void already_linked_table_init PARAMS ((void));
-static void already_linked_table_free PARAMS ((void));
-static boolean wildcardp PARAMS ((const char *));
+static void already_linked_table_init
+ PARAMS ((void));
+static void already_linked_table_free
+ PARAMS ((void));
+static bfd_boolean wildcardp
+ PARAMS ((const char *));
static lang_statement_union_type *wild_sort
PARAMS ((lang_wild_statement_type *, struct wildcard_list *,
lang_input_statement_type *, asection *));
static void output_section_callback
PARAMS ((lang_wild_statement_type *, struct wildcard_list *, asection *,
lang_input_statement_type *, PTR));
-static lang_input_statement_type *lookup_name PARAMS ((const char *));
-static boolean load_symbols
+static lang_input_statement_type *lookup_name
+ PARAMS ((const char *));
+static bfd_boolean load_symbols
PARAMS ((lang_input_statement_type *, lang_statement_list_type *));
static void wild
PARAMS ((lang_wild_statement_type *,
const char *, lang_output_section_statement_type *));
-static bfd *open_output PARAMS ((const char *));
-static void ldlang_open_output PARAMS ((lang_statement_union_type *));
-static void open_input_bfds PARAMS ((lang_statement_union_type *, boolean));
-static void lang_reasonable_defaults PARAMS ((void));
-static void insert_undefined PARAMS ((const char *));
-static void lang_place_undefineds PARAMS ((void));
+static bfd *open_output
+ PARAMS ((const char *));
+static void ldlang_open_output
+ PARAMS ((lang_statement_union_type *));
+static void open_input_bfds
+ PARAMS ((lang_statement_union_type *, bfd_boolean));
+static void lang_reasonable_defaults
+ PARAMS ((void));
+static void insert_undefined
+ PARAMS ((const char *));
+static void lang_place_undefineds
+ PARAMS ((void));
static void map_input_to_output_sections
PARAMS ((lang_statement_union_type *, const char *,
lang_output_section_statement_type *));
+static void strip_excluded_output_sections
+ PARAMS ((void));
static void print_output_section_statement
PARAMS ((lang_output_section_statement_type *));
static void print_assignment
PARAMS ((lang_assignment_statement_type *,
lang_output_section_statement_type *));
-static void print_input_statement PARAMS ((lang_input_statement_type *));
-static boolean print_one_symbol PARAMS ((struct bfd_link_hash_entry *, PTR));
-static void print_input_section PARAMS ((lang_input_section_type *));
-static void print_fill_statement PARAMS ((lang_fill_statement_type *));
-static void print_data_statement PARAMS ((lang_data_statement_type *));
-static void print_address_statement PARAMS ((lang_address_statement_type *));
-static void print_reloc_statement PARAMS ((lang_reloc_statement_type *));
-static void print_padding_statement PARAMS ((lang_padding_statement_type *));
+static void print_input_statement
+ PARAMS ((lang_input_statement_type *));
+static bfd_boolean print_one_symbol
+ PARAMS ((struct bfd_link_hash_entry *, PTR));
+static void print_input_section
+ PARAMS ((lang_input_section_type *));
+static void print_fill_statement
+ PARAMS ((lang_fill_statement_type *));
+static void print_data_statement
+ PARAMS ((lang_data_statement_type *));
+static void print_address_statement
+ PARAMS ((lang_address_statement_type *));
+static void print_reloc_statement
+ PARAMS ((lang_reloc_statement_type *));
+static void print_padding_statement
+ PARAMS ((lang_padding_statement_type *));
static void print_wild_statement
PARAMS ((lang_wild_statement_type *, lang_output_section_statement_type *));
static void print_group
PARAMS ((lang_statement_union_type *, lang_output_section_statement_type *));
static void print_statement_list
PARAMS ((lang_statement_union_type *, lang_output_section_statement_type *));
-static void print_statements PARAMS ((void));
+static void print_statements
+ PARAMS ((void));
static void insert_pad
PARAMS ((lang_statement_union_type **, fill_type *,
unsigned int, asection *, bfd_vma));
static bfd_vma size_input_section
PARAMS ((lang_statement_union_type **, lang_output_section_statement_type *,
fill_type *, bfd_vma));
-static void lang_finish PARAMS ((void));
-static void ignore_bfd_errors PARAMS ((const char *, ...));
-static void lang_check PARAMS ((void));
-static void lang_common PARAMS ((void));
-static boolean lang_one_common PARAMS ((struct bfd_link_hash_entry *, PTR));
-static void lang_place_orphans PARAMS ((void));
-static int topower PARAMS ((int));
-static void lang_set_startof PARAMS ((void));
+static void lang_finish
+ PARAMS ((void));
+static void ignore_bfd_errors
+ PARAMS ((const char *, ...));
+static void lang_check
+ PARAMS ((void));
+static void lang_common
+ PARAMS ((void));
+static bfd_boolean lang_one_common
+ PARAMS ((struct bfd_link_hash_entry *, PTR));
+static void lang_place_orphans
+ PARAMS ((void));
+static int topower
+ PARAMS ((int));
+static void lang_set_startof
+ PARAMS ((void));
static void gc_section_callback
PARAMS ((lang_wild_statement_type *, struct wildcard_list *, asection *,
lang_input_statement_type *, PTR));
-static void lang_record_phdrs PARAMS ((void));
-static void lang_gc_wild PARAMS ((lang_wild_statement_type *));
-static void lang_gc_sections_1 PARAMS ((lang_statement_union_type *));
-static void lang_gc_sections PARAMS ((void));
+static void lang_get_regions
+ PARAMS ((struct memory_region_struct **, struct memory_region_struct **,
+ const char *, const char *, int));
+static void lang_record_phdrs
+ PARAMS ((void));
+static void lang_gc_wild
+ PARAMS ((lang_wild_statement_type *));
+static void lang_gc_sections_1
+ PARAMS ((lang_statement_union_type *));
+static void lang_gc_sections
+ PARAMS ((void));
static int lang_vers_match_lang_c
PARAMS ((struct bfd_elf_version_expr *, const char *));
static int lang_vers_match_lang_cplusplus
PARAMS ((struct bfd_elf_version_expr *, const char *));
static int lang_vers_match_lang_java
PARAMS ((struct bfd_elf_version_expr *, const char *));
-static void lang_do_version_exports_section PARAMS ((void));
-static void lang_check_section_addresses PARAMS ((void));
+static void lang_do_version_exports_section
+ PARAMS ((void));
+static void lang_check_section_addresses
+ PARAMS ((void));
static void os_region_check
PARAMS ((lang_output_section_statement_type *,
struct memory_region_struct *, etree_type *, bfd_vma));
static bfd_vma lang_size_sections_1
PARAMS ((lang_statement_union_type *, lang_output_section_statement_type *,
- lang_statement_union_type **, fill_type *, bfd_vma, boolean *));
-
-typedef void (*callback_t) PARAMS ((lang_wild_statement_type *,
- struct wildcard_list *,
- asection *,
- lang_input_statement_type *,
- PTR));
+ lang_statement_union_type **, fill_type *, bfd_vma, bfd_boolean *,
+ bfd_boolean));
+typedef void (*callback_t)
+ PARAMS ((lang_wild_statement_type *, struct wildcard_list *, asection *,
+ lang_input_statement_type *, PTR));
static void walk_wild
PARAMS ((lang_wild_statement_type *, callback_t, PTR));
static void walk_wild_section
static void walk_wild_file
PARAMS ((lang_wild_statement_type *, lang_input_statement_type *,
callback_t, PTR));
-
-static int get_target PARAMS ((const bfd_target *, PTR));
-static void stricpy PARAMS ((char *, char *));
-static void strcut PARAMS ((char *, char *));
-static int name_compare PARAMS ((char *, char *));
-static int closest_target_match PARAMS ((const bfd_target *, PTR));
-static char * get_first_input_target PARAMS ((void));
-
-/* EXPORTS */
+static int get_target
+ PARAMS ((const bfd_target *, PTR));
+static void stricpy
+ PARAMS ((char *, char *));
+static void strcut
+ PARAMS ((char *, char *));
+static int name_compare
+ PARAMS ((char *, char *));
+static int closest_target_match
+ PARAMS ((const bfd_target *, PTR));
+static char * get_first_input_target
+ PARAMS ((void));
+
+/* Exported variables. */
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 };
-const char *entry_symbol = NULL;
+struct bfd_sym_chain entry_symbol = { NULL, NULL };
const char *entry_section = ".text";
-boolean entry_from_cmdline;
-boolean lang_has_input_file = false;
-boolean had_output_filename = false;
-boolean lang_float_flag = false;
-boolean delete_output_file_on_failure = false;
+bfd_boolean entry_from_cmdline;
+bfd_boolean lang_has_input_file = FALSE;
+bfd_boolean had_output_filename = FALSE;
+bfd_boolean lang_float_flag = FALSE;
+bfd_boolean delete_output_file_on_failure = FALSE;
struct lang_nocrossrefs *nocrossref_list;
struct unique_sections *unique_section_list;
+static bfd_boolean ldlang_sysrooted_script = FALSE;
etree_type *base; /* Relocation base - or null */
return obstack_alloc (&stat_obstack, size);
}
-boolean
+bfd_boolean
unique_section_p (secnam)
const char *secnam;
{
? fnmatch (unam->name, secnam, 0) == 0
: strcmp (unam->name, secnam) == 0)
{
- return true;
+ return TRUE;
}
- return false;
+ return FALSE;
}
/* Generic traversal routines for finding matching sections. */
while (sec != NULL)
{
- boolean skip = false;
+ bfd_boolean skip = FALSE;
struct name_list *list_tmp;
/* Don't process sections from files which were
or prefix it with a -l etc.
We can be supplied with requests for input files more than once;
- they may, for example be split over serveral lines like foo.o(.text)
+ they may, for example be split over several lines like foo.o(.text)
foo.o(.data) etc, so when asked for a file we check that we haven't
got it already so we don't duplicate the bfd. */
const char *name;
lang_input_file_enum_type file_type;
const char *target;
- boolean add_to_list;
+ bfd_boolean add_to_list;
{
lang_input_statement_type *p;
p->header.next = NULL;
}
- lang_has_input_file = true;
+ lang_has_input_file = TRUE;
p->target = target;
+ p->sysrooted = FALSE;
switch (file_type)
{
case lang_input_file_is_symbols_only_enum:
p->filename = name;
- p->is_archive = false;
- p->real = true;
+ p->is_archive = FALSE;
+ p->real = TRUE;
p->local_sym_name = name;
- p->just_syms_flag = true;
- p->search_dirs_flag = false;
+ p->just_syms_flag = TRUE;
+ p->search_dirs_flag = FALSE;
break;
case lang_input_file_is_fake_enum:
p->filename = name;
- p->is_archive = false;
- p->real = false;
+ p->is_archive = FALSE;
+ p->real = FALSE;
p->local_sym_name = name;
- p->just_syms_flag = false;
- p->search_dirs_flag = false;
+ p->just_syms_flag = FALSE;
+ p->search_dirs_flag = FALSE;
break;
case lang_input_file_is_l_enum:
- p->is_archive = true;
+ p->is_archive = TRUE;
p->filename = name;
- p->real = true;
+ p->real = TRUE;
p->local_sym_name = concat ("-l", name, (const char *) NULL);
- p->just_syms_flag = false;
- p->search_dirs_flag = true;
+ p->just_syms_flag = FALSE;
+ p->search_dirs_flag = TRUE;
break;
case lang_input_file_is_marker_enum:
p->filename = name;
- p->is_archive = false;
- p->real = false;
+ p->is_archive = FALSE;
+ p->real = FALSE;
p->local_sym_name = name;
- p->just_syms_flag = false;
- p->search_dirs_flag = true;
+ p->just_syms_flag = FALSE;
+ p->search_dirs_flag = TRUE;
break;
case lang_input_file_is_search_file_enum:
+ p->sysrooted = ldlang_sysrooted_script;
p->filename = name;
- p->is_archive = false;
- p->real = true;
+ p->is_archive = FALSE;
+ p->real = TRUE;
p->local_sym_name = name;
- p->just_syms_flag = false;
- p->search_dirs_flag = true;
+ p->just_syms_flag = FALSE;
+ p->search_dirs_flag = TRUE;
break;
case lang_input_file_is_file_enum:
p->filename = name;
- p->is_archive = false;
- p->real = true;
+ p->is_archive = FALSE;
+ p->real = TRUE;
p->local_sym_name = name;
- p->just_syms_flag = false;
- p->search_dirs_flag = false;
+ p->just_syms_flag = FALSE;
+ p->search_dirs_flag = FALSE;
break;
default:
FAIL ();
p->symbol_count = 0;
p->dynamic = config.dynamic_link;
p->whole_archive = whole_archive;
- p->loaded = false;
+ p->loaded = FALSE;
lang_statement_append (&input_file_chain,
(lang_statement_union_type *) p,
&p->next_real_file);
lang_input_file_enum_type file_type;
const char *target;
{
- lang_has_input_file = true;
- return new_afile (name, file_type, target, true);
+ lang_has_input_file = TRUE;
+ return new_afile (name, file_type, target, TRUE);
}
/* Build enough state so that the parser can build its tree. */
{
lang_memory_region_type *p;
+ /* NAME is NULL for LMA memspecs if no region was specified. */
+ if (name == NULL)
+ return NULL;
+
for (p = lang_memory_region_list;
p != (lang_memory_region_type *) NULL;
p = p->next)
new->not_flags = 0;
new->length = ~(bfd_size_type) 0;
new->current = 0;
- new->had_full_message = false;
+ new->had_full_message = FALSE;
return new;
}
lookup->next = (lang_statement_union_type *) NULL;
lookup->bfd_section = (asection *) NULL;
- lookup->processed = false;
+ lookup->processed = FALSE;
lookup->sectype = normal_section;
lookup->addr_tree = (etree_type *) NULL;
lang_list_init (&lookup->children);
lookup->subsection_alignment = -1;
lookup->section_alignment = -1;
lookup->load_base = (union etree_union *) NULL;
+ lookup->update_dot_tree = NULL;
lookup->phdrs = NULL;
lang_statement_append (&lang_output_section_statement,
mention are initialized. */
if (s->addr_tree != NULL)
exp_init_os (s->addr_tree);
+
+ if (s->load_base != NULL)
+ exp_init_os (s->load_base);
}
/* Make sure that all output sections mentioned in an expression are
discard all sections. */
if (entry->just_syms_flag)
{
- sec->output_section = bfd_abs_section_ptr;
- sec->output_offset = sec->vma;
+ bfd_link_just_syms (sec, &link_info);
return;
}
of having link once sections in the first place.
Also, not merging link once sections in a relocatable link
- causes trouble for MIPS ELF, which relies in link once semantics
+ causes trouble for MIPS ELF, which relies on link once semantics
to handle the .reginfo section correctly. */
name = bfd_get_section_name (abfd, sec);
already_linked_list =
((struct already_linked_hash_entry *)
- bfd_hash_lookup (&already_linked_table, name, true, false));
+ bfd_hash_lookup (&already_linked_table, name, TRUE, FALSE));
for (l = already_linked_list->entry; l != NULL; l = l->next)
{
/* Set the output_section field so that lang_add_section
does not create a lang_input_section structure for this
- section. */
+ section. Since there might be a symbol in the section
+ being discarded, we must retain a pointer to the section
+ which we are really going to use. */
sec->output_section = bfd_abs_section_ptr;
+ sec->kept_section = l->sec;
+
+ if (flags & SEC_GROUP)
+ bfd_discard_group (abfd, sec);
return;
}
explicit actions, like foo.o(.text), bar.o(.text) and
foo.o(.text, .data). */
-/* Return true if the PATTERN argument is a wildcard pattern.
+/* Return TRUE if the PATTERN argument is a wildcard pattern.
Although backslashes are treated specially if a pattern contains
wildcards, we do not consider the mere presence of a backslash to
be enough to cause the pattern to be treated as a wildcard.
That lets us handle DOS filenames more naturally. */
-static boolean
+static bfd_boolean
wildcardp (pattern)
const char *pattern;
{
if (*s == '?'
|| *s == '*'
|| *s == '[')
- return true;
- return false;
+ return TRUE;
+ return FALSE;
}
/* Add SECTION to the output section OUTPUT. Do this by creating a
lang_input_statement_type *file;
{
flagword flags;
- boolean discard;
+ bfd_boolean discard;
flags = bfd_get_section_flags (section->owner, section);
- discard = false;
+ discard = FALSE;
- /* If we are doing a final link, discard sections marked with
- SEC_EXCLUDE. */
- if (! link_info.relocateable
- && (flags & SEC_EXCLUDE) != 0)
- discard = true;
+ /* Discard sections marked with SEC_EXCLUDE if we are doing a final
+ link. Discard debugging sections marked with SEC_EXCLUDE on a
+ relocatable link too. */
+ if ((flags & SEC_EXCLUDE) != 0
+ && ((flags & SEC_DEBUGGING) != 0 || !link_info.relocateable))
+ discard = TRUE;
/* Discard input sections which are assigned to a section named
DISCARD_SECTION_NAME. */
if (strcmp (output->name, DISCARD_SECTION_NAME) == 0)
- discard = true;
+ discard = TRUE;
/* Discard debugging sections if we are stripping debugging
information. */
if ((link_info.strip == strip_debugger || link_info.strip == strip_all)
&& (flags & SEC_DEBUGGING) != 0)
- discard = true;
+ discard = TRUE;
if (discard)
{
if (section->output_section == NULL)
{
- boolean first;
+ bfd_boolean first;
lang_input_section_type *new;
flagword flags;
flags &= ~ (SEC_MERGE | SEC_STRINGS);
}
+ /* For now make .tbss normal section. */
+ if ((flags & SEC_THREAD_LOCAL) && ! link_info.relocateable)
+ flags |= SEC_LOAD;
+
section->output_section->flags |= flags;
if (flags & SEC_MERGE)
if (section->alignment_power > output->bfd_section->alignment_power)
output->bfd_section->alignment_power = section->alignment_power;
- /* If supplied an aligment, then force it. */
+ /* If supplied an alignment, then force it. */
if (output->section_alignment != -1)
output->bfd_section->alignment_power = output->section_alignment;
if (wild->filenames_sorted)
{
const char *fn, *ln;
- boolean fa, la;
+ bfd_boolean fa, la;
int i;
/* The PE support for the .idata section as generated by
&& bfd_my_archive (file->the_bfd) != NULL)
{
fn = bfd_get_filename (bfd_my_archive (file->the_bfd));
- fa = true;
+ fa = TRUE;
}
else
{
fn = file->filename;
- fa = false;
+ fa = FALSE;
}
if (ls->ifile->the_bfd != NULL
&& bfd_my_archive (ls->ifile->the_bfd) != NULL)
{
ln = bfd_get_filename (bfd_my_archive (ls->ifile->the_bfd));
- la = true;
+ la = TRUE;
}
else
{
ln = ls->ifile->filename;
- la = false;
+ la = FALSE;
}
i = strcmp (fn, ln);
if (search == (lang_input_statement_type *) NULL)
search = new_afile (name, lang_input_file_is_file_enum, default_target,
- false);
+ FALSE);
/* If we have already added this file, or this file is not real
(FIXME: can that ever actually happen?) or the name is NULL
/* Get the symbols for an input file. */
-static boolean
+static bfd_boolean
load_symbols (entry, place)
lang_input_statement_type *entry;
lang_statement_list_type *place;
char **matching;
if (entry->loaded)
- return true;
+ return TRUE;
ldfile_open_file (entry);
{
bfd_error_type err;
lang_statement_list_type *hold;
- boolean bad_load = true;
-
+ bfd_boolean bad_load = TRUE;
+ bfd_boolean save_ldlang_sysrooted_script;
+
err = bfd_get_error ();
/* See if the emulation has some special knowledge. */
if (ldemul_unrecognized_file (entry))
- return true;
+ return TRUE;
if (err == bfd_error_file_ambiguously_recognized)
{
|| place == NULL)
einfo (_("%F%B: file not recognized: %E\n"), entry->the_bfd);
else
- bad_load = false;
-
+ bad_load = FALSE;
+
bfd_close (entry->the_bfd);
entry->the_bfd = NULL;
hold = stat_ptr;
stat_ptr = place;
+ save_ldlang_sysrooted_script = ldlang_sysrooted_script;
+ ldlang_sysrooted_script = entry->sysrooted;
- ldfile_assumed_script = true;
+ ldfile_assumed_script = TRUE;
parser_input = input_script;
yyparse ();
- ldfile_assumed_script = false;
+ ldfile_assumed_script = FALSE;
+ ldlang_sysrooted_script = save_ldlang_sysrooted_script;
stat_ptr = hold;
return ! bad_load;
}
if (ldemul_recognized_file (entry))
- return true;
+ return TRUE;
/* We don't call ldlang_add_file for an archive. Instead, the
add_symbols entry point will call ldlang_add_file, via the
case bfd_archive:
if (entry->whole_archive)
{
- bfd * member = NULL;
- boolean loaded = true;
+ bfd *member = NULL;
+ bfd_boolean loaded = TRUE;
for (;;)
{
if (member == NULL)
break;
-
+
if (! bfd_check_format (member, bfd_object))
{
einfo (_("%F%B: member %B in archive is not an object\n"),
entry->the_bfd, member);
- loaded = false;
+ loaded = FALSE;
}
if (! ((*link_info.callbacks->add_archive_element)
if (! bfd_link_add_symbols (member, &link_info))
{
einfo (_("%F%B: could not read symbols: %E\n"), member);
- loaded = false;
+ loaded = FALSE;
}
}
}
if (bfd_link_add_symbols (entry->the_bfd, &link_info))
- entry->loaded = true;
+ entry->loaded = TRUE;
else
einfo (_("%F%B: could not read symbols: %E\n"), entry->the_bfd);
if (sec->spec.name != NULL && strcmp (sec->spec.name, "COMMON") == 0)
{
/* Remember the section that common is going to in case we
- later get something which doesn't know where to put it. */
+ later get something which doesn't know where to put it. */
default_common_section = output;
}
}
}
-/* Return true iff target is the sought target. */
+/* Return TRUE iff target is the sought target. */
static int
get_target (target, data)
*dest = 0;
}
-/* Remove the first occurance of needle (if any) in haystack
+/* Remove the first occurrence of needle (if any) in haystack
from haystack. */
static void
return target;
}
+const char *
+lang_get_output_target ()
+{
+ const char *target;
+
+ /* Has the user told us which output format to use? */
+ if (output_target != (char *) NULL)
+ return output_target;
+
+ /* No - has the current target been set to something other than
+ the default? */
+ if (current_target != default_target)
+ return current_target;
+
+ /* No - can we determine the format of the first input file? */
+ target = get_first_input_target ();
+ if (target != NULL)
+ return target;
+
+ /* Failed - use the default output target. */
+ return default_target;
+}
+
/* Open the output file. */
static bfd *
{
bfd *output;
- /* Has the user told us which output format to use? */
- if (output_target == (char *) NULL)
- {
- /* No - has the current target been set to something other than
- the default? */
- if (current_target != default_target)
- output_target = current_target;
-
- /* No - can we determine the format of the first input file? */
- else
- {
- output_target = get_first_input_target ();
-
- /* Failed - use the default output target. */
- if (output_target == NULL)
- output_target = default_target;
- }
- }
+ output_target = lang_get_output_target ();
/* Has the user requested a particular endianness on the command
line? */
einfo (_("%P%F: cannot open output file %s: %E\n"), name);
}
- delete_output_file_on_failure = true;
+ delete_output_file_on_failure = TRUE;
#if 0
output->flags |= D_PAGED;
static void
open_input_bfds (s, force)
lang_statement_union_type *s;
- boolean force;
+ bfd_boolean force;
{
for (; s != (lang_statement_union_type *) NULL; s = s->header.next)
{
do
{
undefs = link_info.hash->undefs_tail;
- open_input_bfds (s->group_statement.children.head, true);
+ open_input_bfds (s->group_statement.children.head, TRUE);
}
while (undefs != link_info.hash->undefs_tail);
}
&& s->input_statement.loaded
&& bfd_check_format (s->input_statement.the_bfd,
bfd_archive))
- s->input_statement.loaded = false;
+ s->input_statement.loaded = FALSE;
lang_list_init (&add);
if (! load_symbols (&s->input_statement, &add))
- config.make_executable = false;
+ config.make_executable = FALSE;
if (add.head != NULL)
{
default_common_section = lang_output_section_statement_lookup (".bss");
- if (placed_commons == false)
+ if (!placed_commons)
{
lang_wild_statement_type *new =
new_stat (lang_wild_statement,
on a list, then, once the output file has been opened, transfer the
name to the symbol table. */
-typedef struct ldlang_undef_chain_list
-{
- struct ldlang_undef_chain_list *next;
- char *name;
-} ldlang_undef_chain_list_type;
+typedef struct bfd_sym_chain ldlang_undef_chain_list_type;
-static ldlang_undef_chain_list_type *ldlang_undef_chain_list_head;
+#define ldlang_undef_chain_list_head entry_symbol.next
void
ldlang_add_undef (name)
{
struct bfd_link_hash_entry *h;
- h = bfd_link_hash_lookup (link_info.hash, name, true, false, true);
+ h = bfd_link_hash_lookup (link_info.hash, name, TRUE, FALSE, TRUE);
if (h == (struct bfd_link_hash_entry *) NULL)
einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n"));
if (h->type == bfd_link_hash_new)
}
}
-/* Open input files and attatch to output sections. */
+/* Open input files and attach to output sections. */
static void
map_input_to_output_sections (s, target, output_section_statement)
}
}
+/* An output section might have been removed after its statement was
+ added. For example, ldemul_before_allocation can remove dynamic
+ sections if they turn out to be not needed. Clean them up here. */
+
+static void
+strip_excluded_output_sections ()
+{
+ lang_statement_union_type *u;
+
+ for (u = lang_output_section_statement.head;
+ u != NULL;
+ u = u->output_section_statement.next)
+ {
+ lang_output_section_statement_type *os;
+ asection *s;
+
+ os = &u->output_section_statement;
+ s = os->bfd_section;
+ if (s != NULL && (s->flags & SEC_EXCLUDE) != 0)
+ {
+ asection **p;
+
+ os->bfd_section = NULL;
+
+ for (p = &output_bfd->sections; *p; p = &(*p)->next)
+ if (*p == s)
+ {
+ bfd_section_list_remove (output_bfd, p);
+ output_bfd->section_count--;
+ break;
+ }
+ }
+ }
+}
+
static void
print_output_section_statement (output_section_statement)
lang_output_section_statement_type *output_section_statement;
/* Print all symbols defined in a particular section. This is called
via bfd_link_hash_traverse. */
-static boolean
+static bfd_boolean
print_one_symbol (hash_entry, ptr)
struct bfd_link_hash_entry *hash_entry;
PTR ptr;
minfo (" %T\n", hash_entry->root.string);
}
- return true;
+ return TRUE;
}
/* Print information about an input section to the map file. */
if (sec->spec.exclude_name_list != NULL)
{
name_list *tmp;
- minfo ("EXCLUDE_FILE ( %s", sec->spec.exclude_name_list->name);
+ minfo ("EXCLUDE_FILE(%s", sec->spec.exclude_name_list->name);
for (tmp = sec->spec.exclude_name_list->next; tmp; tmp = tmp->next)
- minfo (", %s", tmp->name);
- minfo (")");
+ minfo (" %s", tmp->name);
+ minfo (") ");
}
if (sec->spec.name != NULL)
minfo ("%s", sec->spec.name);
minfo ("*");
if (sec->spec.sorted)
minfo (")");
+ if (sec->next)
+ minfo (" ");
}
minfo (")");
lang_input_section_type *is = &((*this_ptr)->input_section);
asection *i = is->section;
- if (is->ifile->just_syms_flag == false)
+ if (!is->ifile->just_syms_flag)
{
unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture,
ldfile_output_machine);
if ((region->current < region->origin
|| (region->current - region->origin > region->length))
&& ((region->current != region->origin + region->length)
- || base == 0))
+ || base == 0))
{
if (tree != (etree_type *) NULL)
- {
- einfo (_("%X%P: address 0x%v of %B section %s is not within region %s\n"),
- region->current,
- os->bfd_section->owner,
- os->bfd_section->name,
- region->name);
- }
+ {
+ einfo (_("%X%P: address 0x%v of %B section %s is not within region %s\n"),
+ region->current,
+ os->bfd_section->owner,
+ os->bfd_section->name,
+ region->name);
+ }
else
- {
- einfo (_("%X%P: region %s is full (%B section %s)\n"),
- region->name,
- os->bfd_section->owner,
- os->bfd_section->name);
- }
+ {
+ einfo (_("%X%P: region %s is full (%B section %s)\n"),
+ region->name,
+ os->bfd_section->owner,
+ os->bfd_section->name);
+ }
/* Reset the region pointer. */
region->current = region->origin;
}
/* Set the sizes for all the output sections. */
static bfd_vma
-lang_size_sections_1 (s, output_section_statement, prev, fill, dot, relax)
+lang_size_sections_1 (s, output_section_statement, prev, fill, dot, relax,
+ check_regions)
lang_statement_union_type *s;
lang_output_section_statement_type *output_section_statement;
lang_statement_union_type **prev;
fill_type *fill;
bfd_vma dot;
- boolean *relax;
+ bfd_boolean *relax;
+ bfd_boolean check_regions;
{
unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture,
ldfile_output_machine);
/* If a loadable section is using the default memory
region, and some non default memory regions were
- defined, issue a warning. */
+ defined, issue an error message. */
if ((bfd_get_section_flags (output_bfd, os->bfd_section)
& (SEC_ALLOC | SEC_LOAD)) != 0
&& (bfd_get_section_flags (output_bfd, os->bfd_section)
& SEC_NEVER_LOAD) == 0
&& ! link_info.relocateable
+ && check_regions
&& strcmp (os->region->name, "*default*") == 0
&& lang_memory_region_list != NULL
&& (strcmp (lang_memory_region_list->name,
"*default*") != 0
|| lang_memory_region_list->next != NULL))
- einfo (_("%P: warning: no memory region specified for section `%s'\n"),
- bfd_get_section_name (output_bfd,
- os->bfd_section));
+ {
+ /* By default this is an error rather than just a
+ warning because if we allocate the section to the
+ default memory region we can end up creating an
+ excessivly large binary, or even seg faulting when
+ attmepting to perform a negative seek. See
+ http://sources.redhat.com/ml/binutils/2003-04/msg00423.html
+ for an example of this. This behaviour can be
+ overridden by the using the --no-check-sections
+ switch. */
+ if (command_line.check_section_addresses)
+ einfo (_("%P%F: error: no memory region specified for loadable section `%s'\n"),
+ bfd_get_section_name (output_bfd,
+ os->bfd_section));
+ else
+ einfo (_("%P: warning: no memory region specified for loadable section `%s'\n"),
+ bfd_get_section_name (output_bfd,
+ os->bfd_section));
+ }
dot = os->region->current;
abs_output_section,
lang_allocating_phase_enum,
dot, &dot);
- if (r.valid_p == false)
- {
- einfo (_("%F%S: non constant address expression for section %s\n"),
- os->name);
- }
+ if (!r.valid_p)
+ einfo (_("%F%S: non constant address expression for section %s\n"),
+ os->name);
+
dot = r.value + r.section->bfd_section->vma;
}
}
lang_size_sections_1 (os->children.head, os, &os->children.head,
- os->fill, dot, relax);
+ os->fill, dot, relax, check_regions);
/* Put the section within the requested block size, or
align at the block boundary. */
- after = ALIGN_N (os->bfd_section->vma
+ after = align_n (os->bfd_section->vma
+ os->bfd_section->_raw_size / opb,
- /* The coercion here is important, see ld.h. */
(bfd_vma) os->block_value);
if (bfd_is_abs_section (os->bfd_section))
ASSERT (after == os->bfd_section->vma);
+ else if ((os->bfd_section->flags & SEC_HAS_CONTENTS) == 0
+ && (os->bfd_section->flags & SEC_THREAD_LOCAL)
+ && ! link_info.relocateable)
+ os->bfd_section->_raw_size = 0;
else
os->bfd_section->_raw_size =
(after - os->bfd_section->vma) * opb;
+
dot = os->bfd_section->vma + os->bfd_section->_raw_size / opb;
- os->processed = true;
+ os->processed = TRUE;
+
+ if (os->update_dot_tree != 0)
+ exp_fold_tree (os->update_dot_tree, abs_output_section,
+ lang_allocating_phase_enum, dot, &dot);
/* Update dot in the region ?
We only do this if the section is going to be allocated,
{
os->region->current = dot;
- /* Make sure the new address is within the region. */
- os_region_check (os, os->region, os->addr_tree,
- os->bfd_section->vma);
+ if (check_regions)
+ /* Make sure the new address is within the region. */
+ os_region_check (os, os->region, os->addr_tree,
+ os->bfd_section->vma);
/* If there's no load address specified, use the run
region as the load region. */
if (os->lma_region == NULL && os->load_base == NULL)
os->lma_region = os->region;
- if (os->lma_region != NULL)
+ if (os->lma_region != NULL && os->lma_region != os->region)
{
- if (os->load_base != NULL)
- {
- einfo (_("%X%P: use an absolute load address or a load memory region, not both\n"));
- }
- else
- {
- /* Don't allocate twice. */
- if (os->lma_region != os->region)
- {
- /* Set load_base, which will be handled later. */
- os->load_base =
- exp_intop (os->lma_region->current);
- os->lma_region->current +=
- os->bfd_section->_raw_size / opb;
- os_region_check (os, os->lma_region, NULL,
- os->bfd_section->lma);
- }
- }
+ /* Set load_base, which will be handled later. */
+ os->load_base = exp_intop (os->lma_region->current);
+ os->lma_region->current +=
+ os->bfd_section->_raw_size / opb;
+ if (check_regions)
+ os_region_check (os, os->lma_region, NULL,
+ os->bfd_section->lma);
}
}
}
dot = lang_size_sections_1 (constructor_list.head,
output_section_statement,
&s->wild_statement.children.head,
- fill, dot, relax);
+ fill, dot, relax, check_regions);
break;
case lang_data_statement_enum:
dot = lang_size_sections_1 (s->wild_statement.children.head,
output_section_statement,
&s->wild_statement.children.head,
- fill, dot, relax);
+ fill, dot, relax, check_regions);
break;
}
else
{
- boolean again;
+ bfd_boolean again;
if (! bfd_relax_section (i->owner, i, &link_info, &again))
einfo (_("%P%F: can't relax section: %E\n"));
if (again)
- *relax = true;
+ *relax = TRUE;
}
dot = size_input_section (prev, output_section_statement,
output_section_statement->fill, dot);
dot = lang_size_sections_1 (s->group_statement.children.head,
output_section_statement,
&s->group_statement.children.head,
- fill, dot, relax);
+ fill, dot, relax, check_regions);
break;
default:
}
bfd_vma
-lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
+lang_size_sections (s, output_section_statement, prev, fill, dot, relax,
+ check_regions)
lang_statement_union_type *s;
lang_output_section_statement_type *output_section_statement;
lang_statement_union_type **prev;
fill_type *fill;
bfd_vma dot;
- boolean *relax;
+ bfd_boolean *relax;
+ bfd_boolean check_regions;
{
bfd_vma result;
exp_data_seg.phase = exp_dataseg_none;
result = lang_size_sections_1 (s, output_section_statement, prev, fill,
- dot, relax);
+ dot, relax, check_regions);
if (exp_data_seg.phase == exp_dataseg_end_seen)
{
/* If DATA_SEGMENT_ALIGN DATA_SEGMENT_END pair was seen, check whether
{
exp_data_seg.phase = exp_dataseg_adjust;
result = lang_size_sections_1 (s, output_section_statement, prev,
- fill, dot, relax);
+ fill, dot, relax, check_regions);
}
}
abs_output_section,
lang_final_phase_enum, dot, &dot);
s->data_statement.value = value.value;
- if (value.valid_p == false)
+ if (!value.valid_p)
einfo (_("%F%P: invalid data statement\n"));
}
- {
- unsigned int size;
+ {
+ unsigned int size;
switch (s->data_statement.type)
{
default:
abs_output_section,
lang_final_phase_enum, dot, &dot);
s->reloc_statement.addend_value = value.value;
- if (value.valid_p == false)
+ if (!value.valid_p)
einfo (_("%F%P: invalid reloc statement\n"));
}
dot += bfd_get_reloc_size (s->reloc_statement.howto) / opb;
buf = xmalloc (10 + strlen (secname));
sprintf (buf, ".startof.%s", secname);
- h = bfd_link_hash_lookup (link_info.hash, buf, false, false, true);
+ h = bfd_link_hash_lookup (link_info.hash, buf, FALSE, FALSE, TRUE);
if (h != NULL && h->type == bfd_link_hash_undefined)
{
h->type = bfd_link_hash_defined;
}
sprintf (buf, ".sizeof.%s", secname);
- h = bfd_link_hash_lookup (link_info.hash, buf, false, false, true);
+ h = bfd_link_hash_lookup (link_info.hash, buf, FALSE, FALSE, TRUE);
if (h != NULL && h->type == bfd_link_hash_undefined)
{
- unsigned opb;
+ unsigned opb;
- opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture,
+ opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture,
ldfile_output_machine);
h->type = bfd_link_hash_defined;
if (s->_cooked_size != 0)
lang_finish ()
{
struct bfd_link_hash_entry *h;
- boolean warn;
+ bfd_boolean warn;
if (link_info.relocateable || link_info.shared)
- warn = false;
+ warn = FALSE;
else
- warn = true;
+ warn = TRUE;
- if (entry_symbol == (char *) NULL)
+ if (entry_symbol.name == (const char *) NULL)
{
/* No entry has been specified. Look for start, but don't warn
if we don't find it. */
- entry_symbol = "start";
- warn = false;
+ entry_symbol.name = "start";
+ warn = FALSE;
}
- h = bfd_link_hash_lookup (link_info.hash, entry_symbol, false, false, true);
+ h = bfd_link_hash_lookup (link_info.hash, entry_symbol.name,
+ FALSE, FALSE, TRUE);
if (h != (struct bfd_link_hash_entry *) NULL
&& (h->type == bfd_link_hash_defined
|| h->type == bfd_link_hash_defweak)
h->u.def.section->output_section)
+ h->u.def.section->output_offset);
if (! bfd_set_start_address (output_bfd, val))
- einfo (_("%P%F:%s: can't set start address\n"), entry_symbol);
+ einfo (_("%P%F:%s: can't set start address\n"), entry_symbol.name);
}
else
{
/* We couldn't find the entry symbol. Try parsing it as a
number. */
- val = bfd_scan_vma (entry_symbol, &send, 0);
+ val = bfd_scan_vma (entry_symbol.name, &send, 0);
if (*send == '\0')
{
if (! bfd_set_start_address (output_bfd, val))
{
if (warn)
einfo (_("%P: warning: cannot find entry symbol %s; defaulting to %V\n"),
- entry_symbol, bfd_get_section_vma (output_bfd, ts));
+ entry_symbol.name,
+ bfd_get_section_vma (output_bfd, ts));
if (! bfd_set_start_address (output_bfd,
bfd_get_section_vma (output_bfd,
ts)))
{
if (warn)
einfo (_("%P: warning: cannot find entry symbol %s; not setting start address\n"),
- entry_symbol);
+ entry_symbol.name);
}
}
}
file = file->input_statement.next)
{
input_bfd = file->input_statement.the_bfd;
- compatible = bfd_arch_get_compatible (input_bfd, output_bfd);
+ compatible = bfd_arch_get_compatible (input_bfd, output_bfd,
+ command_line.accept_unknown_input_arch);
/* In general it is not possible to perform a relocatable
link between differing object formats when the input
else if (bfd_count_sections (input_bfd))
{
/* If the input bfd has no contents, it shouldn't set the
- private data of the output bfd. */
+ private data of the output bfd. */
bfd_error_handler_type pfn = NULL;
/* Place one common symbol in the correct section. */
-static boolean
+static bfd_boolean
lang_one_common (h, info)
struct bfd_link_hash_entry *h;
PTR info;
ldfile_output_machine);
if (h->type != bfd_link_hash_common)
- return true;
+ return TRUE;
size = h->u.c.size;
power_of_two = h->u.c.p->alignment_power;
if (config.sort_common
&& power_of_two < (unsigned int) *(int *) info)
- return true;
+ return TRUE;
section = h->u.c.p->section;
/* Increase the size of the section. */
- section->_cooked_size = ALIGN_N ((section->_cooked_size + opb - 1) / opb,
- (bfd_size_type) (1 << power_of_two)) * opb;
+ section->_cooked_size = align_n ((section->_cooked_size + opb - 1) / opb,
+ (bfd_vma) 1 << power_of_two) * opb;
/* Adjust the alignment if necessary. */
if (power_of_two > section->alignment_power)
if (config.map_file != NULL)
{
- static boolean header_printed;
+ static bfd_boolean header_printed;
int len;
char *name;
char buf[50];
{
minfo (_("\nAllocating common symbols\n"));
minfo (_("Common symbol size file\n\n"));
- header_printed = true;
+ header_printed = TRUE;
}
name = demangle (h->root.string);
minfo ("%B\n", section->owner);
}
- return true;
+ return TRUE;
}
/* Run through the input files and ensure that every input section has
{
if (s->output_section == (asection *) NULL)
{
- /* This section of the file is not attatched, root
+ /* This section of the file is not attached, root
around for a sensible place for it to go. */
if (file->just_syms_flag)
{
- /* We are only retrieving symbol values from this
- file. We want the symbols to act as though the
- values in the file are absolute. */
- s->output_section = bfd_abs_section_ptr;
- s->output_offset = s->vma;
+ abort ();
}
else if (strcmp (s->name, "COMMON") == 0)
{
int from_script;
{
/* Make -o on command line override OUTPUT in script. */
- if (had_output_filename == false || !from_script)
+ if (!had_output_filename || !from_script)
{
output_filename = name;
- had_output_filename = true;
+ had_output_filename = TRUE;
}
}
lang_gc_sections ()
{
struct bfd_link_hash_entry *h;
- ldlang_undef_chain_list_type *ulist, fake_list_start;
+ ldlang_undef_chain_list_type *ulist;
/* Keep all sections so marked in the link script. */
lang_gc_sections_1 (statement_list.head);
- /* Keep all sections containing symbols undefined on the command-line.
- Handle the entry symbol at the same time. */
+ /* Keep all sections containing symbols undefined on the command-line,
+ and the section containing the entry symbol. */
- if (entry_symbol != NULL)
- {
- fake_list_start.next = ldlang_undef_chain_list_head;
- fake_list_start.name = (char *) entry_symbol;
- ulist = &fake_list_start;
- }
- else
- ulist = ldlang_undef_chain_list_head;
-
- for (; ulist; ulist = ulist->next)
+ for (ulist = link_info.gc_sym_list; ulist; ulist = ulist->next)
{
h = bfd_link_hash_lookup (link_info.hash, ulist->name,
- false, false, false);
+ FALSE, FALSE, FALSE);
if (h != (struct bfd_link_hash_entry *) NULL
&& (h->type == bfd_link_hash_defined
/* Create a bfd for each input file. */
current_target = default_target;
- open_input_bfds (statement_list.head, false);
+ open_input_bfds (statement_list.head, FALSE);
+
+ link_info.gc_sym_list = &entry_symbol;
+ if (entry_symbol.name == NULL)
+ link_info.gc_sym_list = ldlang_undef_chain_list_head;
ldemul_after_open ();
and other back-ends size dynamic sections. */
ldemul_before_allocation ();
+ if (!link_info.relocateable)
+ strip_excluded_output_sections ();
+
/* We must record the program headers before we try to fix the
section positions, since they will affect SIZEOF_HEADERS. */
lang_record_phdrs ();
/* Size up the sections. */
lang_size_sections (statement_list.head,
abs_output_section,
- &statement_list.head, 0, (bfd_vma) 0, NULL);
+ &statement_list.head, 0, (bfd_vma) 0, NULL,
+ command_line.relax ? FALSE : TRUE);
/* Now run around and relax if we can. */
if (command_line.relax)
{
/* Keep relaxing until bfd_relax_section gives up. */
- boolean relax_again;
+ bfd_boolean relax_again;
do
{
lang_reset_memory_regions ();
- relax_again = false;
+ relax_again = FALSE;
/* Note: pe-dll.c does something like this also. If you find
you need to change this code, you probably need to change
(fill_type *) 0, (bfd_vma) 0);
/* Perform another relax pass - this time we know where the
- globals are, so can make better guess. */
+ globals are, so can make a better guess. */
lang_size_sections (statement_list.head,
abs_output_section,
- &(statement_list.head), 0, (bfd_vma) 0,
- &relax_again);
+ &statement_list.head, 0, (bfd_vma) 0,
+ &relax_again, FALSE);
+
+ /* If the normal relax is done and the relax finalize pass
+ is not performed yet, we perform another relax pass. */
+ if (!relax_again && !link_info.relax_finalizing)
+ {
+ link_info.relax_finalizing = TRUE;
+ relax_again = TRUE;
+ }
}
while (relax_again);
+
+ /* Final extra sizing to report errors. */
+ lang_reset_memory_regions ();
+ lang_do_assignments (statement_list.head,
+ abs_output_section,
+ (fill_type *) 0, (bfd_vma) 0);
+ lang_size_sections (statement_list.head,
+ abs_output_section,
+ & statement_list.head, 0, (bfd_vma) 0,
+ NULL, TRUE);
}
/* See if anything special should be done now we know how big
lang_add_wild (filespec, section_list, keep_sections)
struct wildcard_spec *filespec;
struct wildcard_list *section_list;
- boolean keep_sections;
+ bfd_boolean keep_sections;
{
struct wildcard_list *curr, *next;
lang_wild_statement_type *new;
section_list = curr, curr = next)
{
if (curr->spec.name != NULL && strcmp (curr->spec.name, "COMMON") == 0)
- placed_commons = true;
+ placed_commons = TRUE;
next = curr->next;
curr->next = section_list;
if (strcmp (filespec->name, "*") == 0)
filespec->name = NULL;
else if (! wildcardp (filespec->name))
- lang_has_input_file = true;
+ lang_has_input_file = TRUE;
}
new = new_stat (lang_wild_statement, stat_ptr);
new->filename = NULL;
- new->filenames_sorted = false;
+ new->filenames_sorted = FALSE;
if (filespec != NULL)
{
new->filename = filespec->name;
void
lang_add_entry (name, cmdline)
const char *name;
- boolean cmdline;
+ bfd_boolean cmdline;
{
- if (entry_symbol == NULL
+ if (entry_symbol.name == NULL
|| cmdline
|| ! entry_from_cmdline)
{
- entry_symbol = name;
+ entry_symbol.name = name;
entry_from_cmdline = cmdline;
}
}
switch (*name)
{
case 'F':
- map_option_f = true;
+ map_option_f = TRUE;
break;
}
name++;
}
first_file->filename = name;
first_file->local_sym_name = name;
- first_file->real = true;
+ first_file->real = TRUE;
startup_file = name;
}
void
lang_float (maybe)
- boolean maybe;
+ bfd_boolean maybe;
{
lang_float_flag = maybe;
}
+
+/* Work out the load- and run-time regions from a script statement, and
+ store them in *LMA_REGION and *REGION respectively.
+
+ MEMSPEC is the name of the run-time region, or "*default*" if the
+ statement didn't specify one. LMA_MEMSPEC is the name of the
+ load-time region, or null if the statement didn't specify one.
+ HAVE_LMA_P is TRUE if the statement had an explicit load address.
+
+ It is an error to specify both a load region and a load address. */
+
+static void
+lang_get_regions (region, lma_region, memspec, lma_memspec, have_lma_p)
+ struct memory_region_struct **region, **lma_region;
+ const char *memspec, *lma_memspec;
+ int have_lma_p;
+{
+ *lma_region = lang_memory_region_lookup (lma_memspec);
+
+ /* If no runtime region has been given, but the load region has
+ been, use the load region. */
+ if (lma_memspec != 0 && strcmp (memspec, "*default*") == 0)
+ *region = *lma_region;
+ else
+ *region = lang_memory_region_lookup (memspec);
+
+ if (have_lma_p && lma_memspec != 0)
+ einfo (_("%X%P:%S: section has both a load address and a load region\n"));
+}
+
void
lang_leave_output_section_statement (fill, memspec, phdrs, lma_memspec)
fill_type *fill;
struct lang_output_section_phdr_list *phdrs;
const char *lma_memspec;
{
+ lang_get_regions (¤t_section->region,
+ ¤t_section->lma_region,
+ memspec, lma_memspec,
+ current_section->load_base != 0);
current_section->fill = fill;
- current_section->region = lang_memory_region_lookup (memspec);
- if (strcmp (lma_memspec, "*default*") != 0)
- {
- current_section->lma_region = lang_memory_region_lookup (lma_memspec);
- /* If no runtime region has been given, but the load region has
- been, use the load region. */
- if (strcmp (memspec, "*default*") == 0)
- current_section->region = lang_memory_region_lookup (lma_memspec);
- }
current_section->phdrs = phdrs;
stat_ptr = &statement_list;
}
{
struct bfd_link_hash_entry *h;
- h = bfd_link_hash_lookup (link_info.hash, name, true, true, true);
+ h = bfd_link_hash_lookup (link_info.hash, name, TRUE, TRUE, TRUE);
if (h == (struct bfd_link_hash_entry *) NULL)
einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n"));
{
struct bfd_link_hash_entry *h;
- h = bfd_link_hash_lookup (link_info.hash, name, true, true, true);
+ h = bfd_link_hash_lookup (link_info.hash, name, TRUE, TRUE, TRUE);
if (h == (struct bfd_link_hash_entry *) NULL)
einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n"));
lang_new_phdr (name, type, filehdr, phdrs, at, flags)
const char *name;
etree_type *type;
- boolean filehdr;
- boolean phdrs;
+ bfd_boolean filehdr;
+ bfd_boolean phdrs;
etree_type *at;
etree_type *flags;
{
}
secs[c] = os->bfd_section;
++c;
- pl->used = true;
+ pl->used = TRUE;
}
}
}
nocrossref_list = n;
/* Set notice_all so that we get informed about all symbols. */
- link_info.notice_all = true;
+ link_info.notice_all = TRUE;
}
\f
/* Overlay handling. We handle overlays with some static variables. */
/* The overlay virtual address. */
static etree_type *overlay_vma;
-/* The overlay load address. */
-static etree_type *overlay_lma;
-
-/* Whether nocrossrefs is set for this overlay. */
-static int overlay_nocrossrefs;
-
/* An expression for the maximum section size seen so far. */
static etree_type *overlay_max;
/* Start handling an overlay. */
void
-lang_enter_overlay (vma_expr, lma_expr, nocrossrefs)
+lang_enter_overlay (vma_expr)
etree_type *vma_expr;
- etree_type *lma_expr;
- int nocrossrefs;
{
/* The grammar should prevent nested overlays from occurring. */
- ASSERT (overlay_vma == NULL
- && overlay_lma == NULL
- && overlay_list == NULL
- && overlay_max == NULL);
+ ASSERT (overlay_vma == NULL && overlay_max == NULL);
overlay_vma = vma_expr;
- overlay_lma = lma_expr;
- overlay_nocrossrefs = nocrossrefs;
}
/* Start a section in an overlay. We handle this by calling
- lang_enter_output_section_statement with the correct VMA and LMA. */
+ lang_enter_output_section_statement with the correct VMA.
+ lang_leave_overlay sets up the LMA and memory regions. */
void
lang_enter_overlay_section (name)
etree_type *size;
lang_enter_output_section_statement (name, overlay_vma, normal_section,
- 0, 0, 0, overlay_lma);
+ 0, 0, 0, 0);
- /* If this is the first section, then base the VMA and LMA of future
+ /* If this is the first section, then base the VMA of future
sections on this one. This will work correctly even if `.' is
used in the addresses. */
if (overlay_list == NULL)
- {
- overlay_vma = exp_nameop (ADDR, name);
- overlay_lma = exp_nameop (LOADADDR, name);
- }
+ overlay_vma = exp_nameop (ADDR, name);
/* Remember the section. */
n = (struct overlay_list *) xmalloc (sizeof *n);
size = exp_nameop (SIZEOF, name);
- /* Adjust the LMA for the next section. */
- overlay_lma = exp_binop ('+', overlay_lma, size);
-
/* Arrange to work out the maximum section end address. */
if (overlay_max == NULL)
overlay_max = size;
name = current_section->name;
- lang_leave_output_section_statement (fill, "*default*",
- phdrs, "*default*");
+ /* For now, assume that "*default*" is the run-time memory region and
+ that no load-time region has been specified. It doesn't really
+ matter what we say here, since lang_leave_overlay will override it. */
+ lang_leave_output_section_statement (fill, "*default*", phdrs, 0);
/* Define the magic symbols. */
looks through all the sections in the overlay and sets them. */
void
-lang_leave_overlay (fill, memspec, phdrs, lma_memspec)
+lang_leave_overlay (lma_expr, nocrossrefs, fill, memspec, phdrs, lma_memspec)
+ etree_type *lma_expr;
+ int nocrossrefs;
fill_type *fill;
const char *memspec;
struct lang_output_section_phdr_list *phdrs;
const char *lma_memspec;
{
lang_memory_region_type *region;
- lang_memory_region_type * default_region;
lang_memory_region_type *lma_region;
struct overlay_list *l;
struct lang_nocrossref *nocrossref;
- default_region = lang_memory_region_lookup ("*default*");
-
- if (memspec == NULL)
- region = NULL;
- else
- region = lang_memory_region_lookup (memspec);
-
- if (lma_memspec == NULL)
- lma_region = NULL;
- else
- lma_region = lang_memory_region_lookup (lma_memspec);
+ lang_get_regions (®ion, &lma_region,
+ memspec, lma_memspec,
+ lma_expr != 0);
nocrossref = NULL;
+ /* After setting the size of the last section, set '.' to end of the
+ overlay region. */
+ if (overlay_list != NULL)
+ overlay_list->os->update_dot_tree
+ = exp_assop ('=', ".", exp_binop ('+', overlay_vma, overlay_max));
+
l = overlay_list;
while (l != NULL)
{
if (fill != (fill_type *) 0 && l->os->fill == (fill_type *) 0)
l->os->fill = fill;
- /* Assign a region to the sections, if one has been specified.
- Override the assignment of the default section, but not
- other sections. */
- if (region != NULL &&
- (l->os->region == NULL ||
- l->os->region == default_region))
- l->os->region = region;
-
- /* We only set lma_region for the first overlay section, as
- subsequent overlay sections will have load_base set relative
- to the first section. Also, don't set lma_region if
- load_base is specified. FIXME: There should really be a test
- that `AT ( LDADDR )' doesn't conflict with `AT >LMA_REGION'
- rather than letting LDADDR simply override LMA_REGION. */
- if (lma_region != NULL && l->os->lma_region == NULL
- && l->next == NULL && l->os->load_base == NULL)
- l->os->lma_region = lma_region;
+ l->os->region = region;
+ l->os->lma_region = lma_region;
+
+ /* The first section has the load address specified in the
+ OVERLAY statement. The rest are worked out from that.
+ The base address is not needed (and should be null) if
+ an LMA region was specified. */
+ if (l->next == 0)
+ l->os->load_base = lma_expr;
+ else if (lma_region == 0)
+ l->os->load_base = exp_binop ('+',
+ exp_nameop (LOADADDR, l->next->os->name),
+ exp_nameop (SIZEOF, l->next->os->name));
if (phdrs != NULL && l->os->phdrs == NULL)
l->os->phdrs = phdrs;
- if (overlay_nocrossrefs)
+ if (nocrossrefs)
{
struct lang_nocrossref *nc;
if (nocrossref != NULL)
lang_add_nocrossref (nocrossref);
- /* Update . for the end of the overlay. */
- lang_add_assignment (exp_assop ('=', ".",
- exp_binop ('+', overlay_vma, overlay_max)));
-
overlay_vma = NULL;
- overlay_lma = NULL;
- overlay_nocrossrefs = 0;
overlay_list = NULL;
overlay_max = NULL;
}
if (!alt_sym)
{
/* cplus_demangle (also) returns NULL when it is not a C++ symbol.
- Should we early out false in this case? */
+ Should we early out FALSE in this case? */
result = fnmatch (expr->pattern, sym, 0) == 0;
}
else
if (!alt_sym)
{
/* cplus_demangle (also) returns NULL when it is not a Java symbol.
- Should we early out false in this case? */
+ Should we early out FALSE in this case? */
result = fnmatch (expr->pattern, sym, 0) == 0;
}
else
ret = (struct bfd_elf_version_expr *) xmalloc (sizeof *ret);
ret->next = orig;
ret->pattern = new;
+ ret->symver = 0;
+ ret->script = 0;
if (lang == NULL || strcasecmp (lang, "C") == 0)
ret->match = lang_vers_match_lang_c;
ret->match = lang_vers_match_lang_c;
}
- return ret;
+ return ldemul_new_vers_pattern (ret);
}
/* This is called for each set of variable names and match
|| (lang_elf_version_info && lang_elf_version_info->name[0] == '\0'))
{
einfo (_("%X%P: anonymous version tag cannot be combined with other version tags\n"));
+ free (version);
return;
}
bfd_size_type len;
if (sec == NULL)
- continue;
+ continue;
len = bfd_section_size (is->the_bfd, sec);
contents = xmalloc (len);