#define obstack_chunk_free free
static CONST char *startup_file;
static lang_statement_list_type input_file_chain;
-
-/* Points to the last statement in the .data section, so we can add
- stuff to the data section without pain */
-static lang_statement_list_type end_of_data_section_statement_list;
-
static boolean placed_commons = false;
static lang_output_section_statement_type *default_common_section;
static boolean map_option_f;
const char *target, boolean add_to_list));
static void print_flags PARAMS ((int *ignore_flags));
static void init_os PARAMS ((lang_output_section_statement_type *s));
-static void wild_doit PARAMS ((lang_statement_list_type *ptr,
- asection *section,
- lang_output_section_statement_type *output,
- lang_input_statement_type *file));
-static asection *our_bfd_get_section_by_name PARAMS ((bfd *abfd,
- const char *section));
static void wild_section PARAMS ((lang_wild_statement_type *ptr,
const char *section,
lang_input_statement_type *file,
lang_output_section_statement_type *output));
static lang_input_statement_type *lookup_name PARAMS ((const char *name));
-static void load_symbols PARAMS ((lang_input_statement_type *entry));
+static void load_symbols PARAMS ((lang_input_statement_type *entry,
+ lang_statement_list_type *));
static void wild PARAMS ((lang_wild_statement_type *s,
const char *section, const char *file,
const char *target,
lang_output_section_statement_type *output));
static bfd *open_output PARAMS ((const char *name));
static void ldlang_open_output PARAMS ((lang_statement_union_type *statement));
-static void open_input_bfds PARAMS ((lang_statement_union_type *statement));
+static void open_input_bfds
+ PARAMS ((lang_statement_union_type *statement, boolean));
static void lang_reasonable_defaults PARAMS ((void));
static void lang_place_undefineds PARAMS ((void));
-static void lang_create_output_section_statements PARAMS ((void));
static void map_input_to_output_sections
PARAMS ((lang_statement_union_type *s,
const char *target,
static void print_wild_statement
PARAMS ((lang_wild_statement_type *w,
lang_output_section_statement_type *os));
+static void print_group
+ PARAMS ((lang_group_statement_type *, lang_output_section_statement_type *));
static void print_statement PARAMS ((lang_statement_union_type *s,
lang_output_section_statement_type *os));
static void print_statements PARAMS ((void));
PARAMS ((lang_statement_union_type **this_ptr,
lang_output_section_statement_type *output_section_statement,
fill_type fill, bfd_vma dot, boolean relax));
-static bfd_vma lang_do_assignments
- PARAMS ((lang_statement_union_type * s,
- lang_output_section_statement_type *output_section_statement,
- fill_type fill,
- bfd_vma dot));
static void lang_finish PARAMS ((void));
static void lang_check PARAMS ((void));
static void lang_common PARAMS ((void));
/* EXPORTS */
lang_output_section_statement_type *abs_output_section;
lang_statement_list_type *stat_ptr = &statement_list;
-lang_statement_list_type file_chain =
-{0};
-CONST char *entry_symbol = 0;
+lang_statement_list_type file_chain = { 0 };
+static const char *entry_symbol = 0;
boolean lang_has_input_file = false;
boolean had_output_filename = false;
boolean lang_float_flag = false;
(func,
s->wild_statement.children.head);
break;
+ case lang_group_statement_enum:
+ lang_for_each_statement_worker (func,
+ s->group_statement.children.head);
+ break;
case lang_data_statement_enum:
case lang_reloc_statement_enum:
case lang_object_symbols_statement_enum:
}
p->the_bfd = (bfd *) NULL;
p->asymbols = (asymbol **) NULL;
- p->superfile = (lang_input_statement_type *) NULL;
p->next_real_file = (lang_statement_union_type *) NULL;
p->next = (lang_statement_union_type *) NULL;
p->symbol_count = 0;
lang_input_file_enum_type file_type;
CONST char *target;
{
- /* Look it up or build a new one */
lang_has_input_file = true;
-
-#if 0
- lang_input_statement_type *p;
-
- for (p = (lang_input_statement_type *) input_file_chain.head;
- p != (lang_input_statement_type *) NULL;
- p = (lang_input_statement_type *) (p->next_real_file))
- {
- /* Sometimes we have incomplete entries in here */
- if (p->filename != (char *) NULL)
- {
- if (strcmp (name, p->filename) == 0)
- return p;
- }
-
- }
-#endif
return new_afile (name, file_type, target, true);
}
(char *) NULL);
abs_output_section = lang_output_section_statement_lookup (BFD_ABS_SECTION_NAME);
- abs_output_section->bfd_section = &bfd_abs_section;
+ abs_output_section->bfd_section = bfd_abs_section_ptr;
}
*/
-static void
+void
wild_doit (ptr, section, output, file)
lang_statement_list_type * ptr;
asection * section;
lang_input_statement_type * file;
{
if (output->bfd_section == (asection *) NULL)
- {
init_os (output);
- /* Initialize the vma and size to the existing section. This will
- be overriden in lang_size_sections unless SEC_NEVER_LOAD gets
- set. */
- if (section != (asection *) NULL)
- {
- bfd_set_section_vma (0, output->bfd_section,
- bfd_section_vma (0, section));
- output->bfd_section->_raw_size = section->_raw_size;
- }
- }
if (section != (asection *) NULL
&& section->output_section == (asection *) NULL)
new->ifile = file;
section->output_section = output->bfd_section;
- /* Be selective about what the output section inherits from the
- input section */
-
- if ((section->flags & SEC_SHARED_LIBRARY) != 0)
- section->output_section->flags |= section->flags;
- else
- section->output_section->flags |=
- section->flags & (flagword) (~ SEC_NEVER_LOAD);
+ /* 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. */
+ section->output_section->flags |=
+ section->flags & (flagword) (~ SEC_NEVER_LOAD);
if (!output->loadable)
{
}
}
-static asection *
-our_bfd_get_section_by_name (abfd, section)
- bfd * abfd;
- CONST char *section;
-{
- return bfd_get_section_by_name (abfd, section);
-}
-
static void
wild_section (ptr, section, file, output)
- lang_wild_statement_type * ptr;
- CONST char *section;
- lang_input_statement_type * file;
- lang_output_section_statement_type * output;
+ lang_wild_statement_type *ptr;
+ const char *section;
+ lang_input_statement_type *file;
+ lang_output_section_statement_type *output;
{
- asection *s;
-
if (file->just_syms_flag == false)
{
- if (section == (char *) NULL)
- {
- /* Do the creation to all sections in the file */
- for (s = file->the_bfd->sections; s != (asection *) NULL; s = s->next)
- {
- /* except for bss */
- if ((s->flags & SEC_IS_COMMON) == 0)
- {
- wild_doit (&ptr->children, s, output, file);
- }
- }
- }
- else
+ register asection *s;
+
+ for (s = file->the_bfd->sections; s != NULL; s = s->next)
{
- /* Do the creation to the named section only */
- wild_doit (&ptr->children,
- our_bfd_get_section_by_name (file->the_bfd, section),
- output, file);
+ /* Attach all sections named SECTION. If SECTION is NULL,
+ then attach all sections.
+
+ Previously, if SECTION was NULL, this code did not call
+ wild_doit if the SEC_IS_COMMON flag was set for the
+ section. I did not understand that, and I took it out.
+
+ if (section == NULL
+ || strcmp (bfd_get_section_name (file->the_bfd, s),
+ section) == 0)
+ wild_doit (&ptr->children, s, output, file);
}
}
}
Archives are pecuilar here. We may open them once, but if they do
not define anything we need at the time, they won't have all their
- symbols read. If we need them later, we'll have to redo it.
- */
+ symbols read. If we need them later, we'll have to redo it. */
static lang_input_statement_type *
lookup_name (name)
CONST char *name;
|| search->filename == (const char *) NULL)
return search;
- load_symbols (search);
+ load_symbols (search, (lang_statement_list_type *) NULL);
return search;
}
/* Get the symbols for an input file. */
static void
-load_symbols (entry)
+load_symbols (entry, place)
lang_input_statement_type *entry;
+ lang_statement_list_type *place;
{
+ char **matching;
+
if (entry->loaded)
return;
ldfile_open_file (entry);
- if (bfd_check_format (entry->the_bfd, bfd_object))
+ if (! bfd_check_format (entry->the_bfd, bfd_archive)
+ && ! bfd_check_format_matches (entry->the_bfd, bfd_object, &matching))
+ {
+ bfd_error_type err;
+ lang_statement_list_type *hold;
+
+ err = bfd_get_error ();
+ if (err == bfd_error_file_ambiguously_recognized)
+ {
+ char **p;
+
+ einfo ("%B: file not recognized: %E\n", entry->the_bfd);
+ einfo ("%B: matching formats:", entry->the_bfd);
+ for (p = matching; *p != NULL; p++)
+ einfo (" %s", *p);
+ einfo ("%F\n");
+ }
+ else if (err != bfd_error_file_not_recognized
+ || place == NULL)
+ einfo ("%F%B: file not recognized: %E\n", entry->the_bfd);
+
+ /* Try to interpret the file as a linker script. */
+
+ bfd_close (entry->the_bfd);
+ entry->the_bfd = NULL;
+
+ ldfile_open_command_file (entry->filename);
+
+ hold = stat_ptr;
+ stat_ptr = place;
+
+ ldfile_assumed_script = true;
+ parser_input = input_script;
+ yyparse ();
+ ldfile_assumed_script = false;
+
+ stat_ptr = hold;
+
+ return;
+ }
+
+ /* We don't call ldlang_add_file for an archive. Instead, the
+ add_symbols entry point will call ldlang_add_file, via the
+ add_archive_element callback, for each element of the archive
+ which is used. */
+ if (bfd_get_format (entry->the_bfd) == bfd_object)
{
ldlang_add_file (entry);
if (trace_files || trace_file_tries)
info_msg ("%I\n", entry);
}
- else if (bfd_check_format (entry->the_bfd, bfd_archive))
- {
- /* There is nothing to do here; the add_symbols routine will
- call ldlang_add_file (via the add_archive_element callback)
- for each element of the archive which is used. */
- }
- else
- einfo ("%F%B: file not recognized: %E\n", entry->the_bfd);
- if (bfd_link_add_symbols (entry->the_bfd, &link_info) == false)
+ if (! bfd_link_add_symbols (entry->the_bfd, &link_info))
einfo ("%F%B: could not read symbols: %E\n", entry->the_bfd);
entry->loaded = true;
output_bfd->flags |= WP_TEXT;
else
output_bfd->flags &= ~WP_TEXT;
+ if (config.traditional_format)
+ output_bfd->flags |= BFD_TRADITIONAL_FORMAT;
+ else
+ output_bfd->flags &= ~BFD_TRADITIONAL_FORMAT;
break;
case lang_target_statement_enum:
}
}
+/* Open all the input files. */
+
static void
-open_input_bfds (statement)
- lang_statement_union_type * statement;
+open_input_bfds (s, force)
+ lang_statement_union_type *s;
+ boolean force;
{
- switch (statement->header.type)
+ for (; s != (lang_statement_union_type *) NULL; s = s->next)
{
- case lang_target_statement_enum:
- current_target = statement->target_statement.target;
- break;
- case lang_wild_statement_enum:
- /* Maybe we should load the file's symbols */
- if (statement->wild_statement.filename)
- {
- (void) lookup_name (statement->wild_statement.filename);
- }
- break;
- case lang_input_statement_enum:
- if (statement->input_statement.real == true)
+ switch (s->header.type)
{
- statement->input_statement.target = current_target;
- load_symbols (&statement->input_statement);
+ case lang_constructors_statement_enum:
+ open_input_bfds (constructor_list.head, force);
+ break;
+ case lang_output_section_statement_enum:
+ open_input_bfds (s->output_section_statement.children.head, force);
+ break;
+ case lang_wild_statement_enum:
+ /* Maybe we should load the file's symbols */
+ if (s->wild_statement.filename)
+ (void) lookup_name (s->wild_statement.filename);
+ open_input_bfds (s->wild_statement.children.head, force);
+ break;
+ case lang_group_statement_enum:
+ {
+ struct bfd_link_hash_entry *undefs;
+
+ /* We must continually search the entries in the group
+ until no new symbols are added to the list of undefined
+ symbols. */
+
+ do
+ {
+ undefs = link_info.hash->undefs_tail;
+ open_input_bfds (s->group_statement.children.head, true);
+ }
+ while (undefs != link_info.hash->undefs_tail);
+ }
+ break;
+ case lang_target_statement_enum:
+ current_target = s->target_statement.target;
+ break;
+ case lang_input_statement_enum:
+ if (s->input_statement.real == true)
+ {
+ lang_statement_list_type add;
+
+ s->input_statement.target = current_target;
+
+ /* If we are being called from within a group, and this
+ is an archive which has already been searched, then
+ force it to be researched. */
+ if (force
+ && s->input_statement.loaded
+ && bfd_check_format (s->input_statement.the_bfd,
+ bfd_archive))
+ s->input_statement.loaded = false;
+
+ lang_list_init (&add);
+
+ load_symbols (&s->input_statement, &add);
+
+ if (add.head != NULL)
+ {
+ *add.tail = s->next;
+ s->next = add.head;
+ }
+ }
+ break;
+ default:
+ break;
}
- break;
- default:
- break;
}
}
}
}
-/* Copy important data from out internal form to the bfd way. Also
- create a section for the dummy file
- */
-
-static void
-lang_create_output_section_statements ()
-{
- lang_statement_union_type *os;
-
- for (os = lang_output_section_statement.head;
- os != (lang_statement_union_type *) NULL;
- os = os->output_section_statement.next)
- {
- lang_output_section_statement_type *s =
- &os->output_section_statement;
-
- init_os (s);
- }
-
-}
-
/* Open input files and attatch to output sections */
static void
map_input_to_output_sections (s, target, output_section_statement)
case lang_target_statement_enum:
target = s->target_statement.target;
break;
+ case lang_group_statement_enum:
+ map_input_to_output_sections (s->group_statement.children.head,
+ target,
+ output_section_statement);
+ break;
case lang_fill_statement_enum:
case lang_input_section_enum:
case lang_object_symbols_statement_enum:
case lang_reloc_statement_enum:
case lang_assignment_statement_enum:
case lang_padding_statement_enum:
+ case lang_input_statement_enum:
+ if (output_section_statement != NULL
+ && output_section_statement->bfd_section == NULL)
+ init_os (output_section_statement);
break;
case lang_afile_asection_pair_statement_enum:
FAIL ();
/* Mark the specified section with the supplied address */
{
lang_output_section_statement_type *os =
- lang_output_section_statement_lookup
- (s->address_statement.section_name);
+ lang_output_section_statement_lookup
+ (s->address_statement.section_name);
+ if (os->bfd_section == NULL)
+ init_os (os);
os->addr_tree = s->address_statement.address;
- if (os->bfd_section == (asection *) NULL)
- {
- einfo ("%P%F: cannot set the address of undefined section %s\n",
- s->address_statement.section_name);
- }
}
break;
- case lang_input_statement_enum:
- /* A standard input statement, has no wildcards */
- break;
}
}
}
print_address (section->vma);
print_space ();
print_size (section->_raw_size);
- print_space();
+ print_space ();
print_size(section->_cooked_size);
print_space ();
print_alignment (section->alignment_power);
}
else
{
- fprintf (config.map_file, "No attached output section");
+ fprintf (config.map_file, " (no attached output section)");
}
print_nl ();
if (output_section_statement->load_base)
{
- int b = exp_get_value_int(output_section_statement->load_base,
+ int b = exp_get_abs_int(output_section_statement->load_base,
0, "output base", lang_final_phase_enum);
- printf("Output address %08x\n", b);
+ fprintf (config.map_file, "Output address %08x\n", b);
}
if (output_section_statement->section_alignment >= 0
|| output_section_statement->section_alignment >= 0)
{
- printf("\t\t\t\t\tforced alignment ");
- if ( output_section_statement->section_alignment >= 0)
+ fprintf (config.map_file, "\t\t\t\t\tforced alignment ");
+ if (output_section_statement->section_alignment >= 0)
{
- printf("section 2**%d ",output_section_statement->section_alignment );
+ fprintf (config.map_file, "section 2**%d ",output_section_statement->section_alignment );
}
if ( output_section_statement->subsection_alignment >= 0)
{
- printf("subsection 2**%d ",output_section_statement->subsection_alignment );
+ fprintf (config.map_file, "subsection 2**%d ",output_section_statement->subsection_alignment );
}
print_nl ();
print_statement (w->children.head, os);
}
+
+/* Print a group statement. */
+
+static void
+print_group (s, os)
+ lang_group_statement_type *s;
+ lang_output_section_statement_type *os;
+{
+ fprintf (config.map_file, "START GROUP\n");
+ print_statement (s->children.head, os);
+ fprintf (config.map_file, "END GROUP\n");
+}
+
static void
print_statement (s, os)
lang_statement_union_type * s;
case lang_input_statement_enum:
print_input_statement (&s->input_statement);
break;
+ case lang_group_statement_enum:
+ print_group (&s->group_statement, os);
+ break;
case lang_afile_asection_pair_statement_enum:
FAIL ();
break;
bfd_vma after;
lang_output_section_statement_type *os = &s->output_section_statement;
- /* If this is a shared library section, don't change the size
- and address. */
- if (os->bfd_section->flags & SEC_SHARED_LIBRARY)
- break;
+ if (os->bfd_section == NULL)
+ {
+ /* This section was never actually created. */
+ break;
+ }
+
+ /* If this is a COFF shared library section, use the size and
+ address from the input section. FIXME: This is COFF
+ specific; it would be cleaner if there were some other way
+ to do this, but nothing simple comes to mind. */
+ if ((os->bfd_section->flags & SEC_COFF_SHARED_LIBRARY) != 0)
+ {
+ asection *input;
- if (os->bfd_section == &bfd_abs_section)
+ if (os->children.head == NULL
+ || os->children.head->next != NULL
+ || os->children.head->header.type != lang_input_section_enum)
+ einfo ("%P%X: Internal error on COFF shared library section %s",
+ os->name);
+
+ input = os->children.head->input_section.section;
+ bfd_set_section_vma (os->bfd_section->owner,
+ os->bfd_section,
+ bfd_section_vma (input->owner, input));
+ os->bfd_section->_raw_size = input->_raw_size;
+ break;
+ }
+
+ if (bfd_is_abs_section (os->bfd_section))
{
/* No matter what happens, an abs section starts at zero */
- bfd_set_section_vma (0, os->bfd_section, 0);
+ ASSERT (os->bfd_section->vma == 0);
}
else
{
bfd_set_section_vma (0, os->bfd_section, dot);
- if (os->load_base) {
- os->bfd_section->lma
- = exp_get_value_int(os->load_base, 0,"load base", lang_final_phase_enum);
- }
+ os->bfd_section->output_offset = 0;
}
-
- os->bfd_section->output_offset = 0;
-
(void) lang_size_sections (os->children.head, os, &os->children.head,
os->fill, dot, relax);
/* Ignore the size of the input sections, use the vma and size to */
/* The coercion here is important, see ld.h. */
(bfd_vma) os->block_value);
- os->bfd_section->_raw_size = after - os->bfd_section->vma;
+ if (bfd_is_abs_section (os->bfd_section))
+ ASSERT (after == os->bfd_section->vma);
+ else
+ os->bfd_section->_raw_size = after - os->bfd_section->vma;
dot = os->bfd_section->vma + os->bfd_section->_raw_size;
os->processed = true;
/* Replace into region ? */
- if (os->addr_tree == (etree_type *) NULL
- && os->region != (lang_memory_region_type *) NULL)
+ if (os->region != (lang_memory_region_type *) NULL)
{
os->region->current = dot;
/* Make sure this isn't silly */
}
}
+
+
}
break;
&newdot);
if (newdot != dot && !relax)
- /* We've been moved ! so insert a pad */
- {
- lang_statement_union_type *new =
- (lang_statement_union_type *)
- stat_alloc ((bfd_size_type) (sizeof (lang_padding_statement_type)));
-
- /* Link into existing chain */
- new->header.next = *prev;
- *prev = new;
- new->header.type = lang_padding_statement_enum;
- new->padding_statement.output_section =
- output_section_statement->bfd_section;
- new->padding_statement.output_offset =
- dot - output_section_statement->bfd_section->vma;
- new->padding_statement.fill = fill;
- new->padding_statement.size = newdot - dot;
- output_section_statement->bfd_section->_raw_size +=
- new->padding_statement.size;
- dot = newdot;
- }
+ {
+ /* The assignment changed dot. Insert a pad. */
+ if (output_section_statement == abs_output_section)
+ {
+ /* If we don't have an output section, then just adjust
+ the default memory address. */
+ lang_memory_region_lookup ("*default*")->current = newdot;
+ }
+ else
+ {
+ lang_statement_union_type *new =
+ ((lang_statement_union_type *)
+ stat_alloc (sizeof (lang_padding_statement_type)));
+
+ /* Link into existing chain */
+ new->header.next = *prev;
+ *prev = new;
+ new->header.type = lang_padding_statement_enum;
+ new->padding_statement.output_section =
+ output_section_statement->bfd_section;
+ new->padding_statement.output_offset =
+ dot - output_section_statement->bfd_section->vma;
+ new->padding_statement.fill = fill;
+ new->padding_statement.size = newdot - dot;
+ output_section_statement->bfd_section->_raw_size +=
+ new->padding_statement.size;
+ }
+
+ dot = newdot;
+ }
}
-
- break;
+ break;
case lang_padding_statement_enum:
/* If we are relaxing, and this is not the first pass, some
dot += s->padding_statement.size;
break;
+ case lang_group_statement_enum:
+ dot = lang_size_sections (s->group_statement.children.head,
+ output_section_statement,
+ &s->group_statement.children.head,
+ fill, dot, relax);
+ break;
+
default:
FAIL ();
break;
return dot;
}
-static bfd_vma
+bfd_vma
lang_do_assignments (s, output_section_statement, fill, dot)
lang_statement_union_type * s;
lang_output_section_statement_type * output_section_statement;
case lang_output_section_statement_enum:
{
lang_output_section_statement_type *os =
- &(s->output_section_statement);
+ &(s->output_section_statement);
- dot = os->bfd_section->vma;
- (void) lang_do_assignments (os->children.head, os, os->fill, dot);
- dot = os->bfd_section->vma + os->bfd_section->_raw_size;
+ if (os->bfd_section != NULL)
+ {
+ dot = os->bfd_section->vma;
+ (void) lang_do_assignments (os->children.head, os,
+ os->fill, dot);
+ dot = os->bfd_section->vma + os->bfd_section->_raw_size;
+ }
+ if (os->load_base)
+ {
+ /* If nothing has been placed into the output section then
+ it won't have a bfd_section. */
+ if (os->bfd_section)
+ {
+ os->bfd_section->lma
+ = exp_get_abs_int(os->load_base, 0,"load base", lang_final_phase_enum);
+ }
+ }
}
break;
case lang_wild_statement_enum:
case lang_padding_statement_enum:
dot += s->padding_statement.size;
break;
+
+ case lang_group_statement_enum:
+ dot = lang_do_assignments (s->group_statement.children.head,
+ output_section_statement,
+ fill, dot);
+
+ break;
+
default:
FAIL ();
break;
lang_finish ()
{
struct bfd_link_hash_entry *h;
- boolean warn = link_info.relocateable ? false : true;
+ boolean warn;
+
+ if (link_info.relocateable || link_info.shared)
+ warn = false;
+ else
+ warn = true;
if (entry_symbol == (char *) NULL)
{
}
}
-/* By now we know the target architecture, and we may have an */
-/* ldfile_output_machine_name */
+/* Check that the architecture of all the input files is compatible
+ with the output file. */
+
static void
lang_check ()
{
lang_statement_union_type *file;
bfd *input_bfd;
- unsigned long input_machine;
- enum bfd_architecture input_architecture;
CONST bfd_arch_info_type *compatible;
for (file = file_chain.head;
file = file->input_statement.next)
{
input_bfd = file->input_statement.the_bfd;
-
- input_machine = bfd_get_mach (input_bfd);
- input_architecture = bfd_get_arch (input_bfd);
-
-
- /* Inspect the architecture and ensure we're linking like with
- like */
-
compatible = bfd_arch_get_compatible (input_bfd,
output_bfd);
-
- if (compatible)
- {
- ldfile_output_machine = compatible->mach;
- ldfile_output_architecture = compatible->arch;
- }
- else
- {
-
- einfo ("%P: warning: %s architecture of input file `%B' is incompatible with %s output\n",
- bfd_printable_name (input_bfd), input_bfd,
- bfd_printable_name (output_bfd));
-
- if (! bfd_set_arch_mach (output_bfd,
- input_architecture,
- input_machine))
- einfo ("%P%F:%s: can't set architecture: %E\n",
- bfd_get_filename (output_bfd));
- }
-
+ if (compatible == NULL)
+ einfo ("%P: warning: %s architecture of input file `%B' is incompatible with %s output\n",
+ bfd_printable_name (input_bfd), input_bfd,
+ bfd_printable_name (output_bfd));
}
}
{
unsigned int power;
- for (power = 1; power <= 16; power <<= 1)
+ for (power = 1; power < 4; power++)
bfd_link_hash_traverse (link_info.hash, lang_one_common,
(PTR) &power);
}
{
unsigned int power_of_two;
bfd_vma size;
- size_t align;
asection *section;
if (h->type != bfd_link_hash_common)
return true;
size = h->u.c.size;
- switch (size)
- {
- case 0:
- case 1:
- power_of_two = 0;
- align = 1;
- break;
- case 2:
- power_of_two = 1;
- align = 2;
- break;
- case 3:
- case 4:
- power_of_two = 2;
- align = 4;
- break;
- case 5:
- case 6:
- case 7:
- case 8:
- power_of_two = 3;
- align = 8;
- break;
- default:
- power_of_two = 4;
- align = 16;
- break;
- }
-
- if (config.sort_common && align != *(unsigned int *) info)
+ power_of_two = h->u.c.alignment_power;
+
+ if (config.sort_common
+ && power_of_two < *(unsigned int *) info
+ && *(unsigned int *) info < 4)
return true;
section = h->u.c.section;
/* Increase the size of the section. */
- section->_raw_size = ALIGN_N (section->_raw_size, align);
+ section->_raw_size = ALIGN_N (section->_raw_size,
+ (bfd_size_type) (1 << power_of_two));
/* Adjust the alignment if necessary. */
if (power_of_two > section->alignment_power)
/* Increase the size of the section. */
section->_raw_size += size;
+ /* Make sure the section is allocated in memory. */
+ section->flags |= SEC_ALLOC;
+
if (config.map_file != NULL)
fprintf (config.map_file, "Allocating common %s: %lx at %lx %s\n",
h->root.string, (unsigned long) size,
{
asection *s;
+ if (file->just_syms_flag)
+ continue;
+
for (s = file->the_bfd->sections;
s != (asection *) NULL;
s = s->next)
default_common_section, file);
}
}
+ else if (ldemul_place_orphan (file, s))
+ ;
else
{
lang_output_section_statement_type *os =
}
}
+/* Call a function on each input file. This function will be called
+ on an archive, but not on the elements. */
+
+void
+lang_for_each_input_file (func)
+ void (*func) PARAMS ((lang_input_statement_type *));
+{
+ lang_input_statement_type *f;
+
+ for (f = (lang_input_statement_type *) input_file_chain.head;
+ f != NULL;
+ f = (lang_input_statement_type *) f->next_real_file)
+ func (f);
+}
+/* Call a function on each file. The function will be called on all
+ the elements of an archive which are included in the link, but will
+ not be called on the archive file itself. */
void
lang_for_each_file (func)
current_target = default_target;
lang_for_each_statement (ldlang_open_output); /* Open the output file */
- /* For each output section statement, create a section in the output
- file */
- lang_create_output_section_statements ();
ldemul_create_output_section_statements ();
/* Create a bfd for each input file */
current_target = default_target;
- lang_for_each_statement (open_input_bfds);
+ open_input_bfds (statement_list.head, false);
+
+ ldemul_after_open ();
/* Build all sets based on the information gathered from the input
files. */
ad->address = address;
}
+/* Set the start symbol to NAME. CMDLINE is nonzero if this is called
+ because of a -e argument on the command line, or zero if this is
+ called by ENTRY in a linker script. Command line arguments take
+ precedence. */
+
void
-lang_add_entry (name)
+lang_add_entry (name, cmdline)
CONST char *name;
+ int cmdline;
{
- entry_symbol = name;
+ static int from_cmdline;
+
+ if (entry_symbol == NULL
+ || cmdline
+ || ! from_cmdline)
+ {
+ entry_symbol = name;
+ from_cmdline = cmdline;
+ }
}
void
void
lang_add_reloc (reloc, howto, section, name, addend)
bfd_reloc_code_real_type reloc;
- const reloc_howto_type *howto;
+ reloc_howto_type *howto;
asection *section;
const char *name;
union etree_union *addend;
current_section->fill = fill;
current_section->region = lang_memory_region_lookup (memspec);
stat_ptr = &statement_list;
-
- /* We remember if we are closing a .data section, since we use it to
- store constructors in */
- if (strcmp (current_section->name, ".data") == 0)
- {
- end_of_data_section_statement_list = statement_list;
-
- }
}
/*
else
h->u.def.value = bfd_get_section_vma (output_bfd, sec);
- h->u.def.section = &bfd_abs_section;
+ h->u.def.section = bfd_abs_section_ptr;
}
}
h->u.def.value = (bfd_get_section_vma (output_bfd, sec)
+ bfd_section_size (output_bfd, sec));
- h->u.def.section = &bfd_abs_section;
+ h->u.def.section = bfd_abs_section_ptr;
}
}
}
/* Set the output format type. -oformat overrides scripts. */
+
void
-lang_add_output_format (format, from_script)
- CONST char *format;
+lang_add_output_format (format, big, little, from_script)
+ const char *format;
+ const char *big;
+ const char *little;
int from_script;
{
if (output_target == NULL || !from_script)
- output_target = format;
+ {
+ if (command_line.endian == ENDIAN_BIG
+ && big != NULL)
+ format = big;
+ else if (command_line.endian == ENDIAN_LITTLE
+ && little != NULL)
+ format = little;
+
+ output_target = format;
+ }
+}
+
+/* Enter a group. This creates a new lang_group_statement, and sets
+ stat_ptr to build new statements within the group. */
+
+void
+lang_enter_group ()
+{
+ lang_group_statement_type *g;
+
+ g = new_stat (lang_group_statement, stat_ptr);
+ lang_list_init (&g->children);
+ stat_ptr = &g->children;
+}
+
+/* Leave a group. This just resets stat_ptr to start writing to the
+ regular list of statements again. Note that this will not work if
+ groups can occur inside anything else which can adjust stat_ptr,
+ but currently they can't. */
+
+void
+lang_leave_group ()
+{
+ stat_ptr = &statement_list;
}