about unset local_sym_name (in which case lookup_name simply adds
the input file again). */
const char *filename = file->local_sym_name;
- if (filename == NULL
- || filename_cmp (filename, file_spec) != 0)
+ lang_input_statement_type *arch_is;
+ if (filename && filename_cmp (filename, file_spec) == 0)
+ ;
+ /* FIXME: see also walk_wild_file_in_exclude_list for why we
+ also check parents BFD (local_sym_)name to match input statements
+ with unadorned archive names. */
+ else if (file->the_bfd
+ && file->the_bfd->my_archive
+ && (arch_is = bfd_usrdata (file->the_bfd->my_archive))
+ && arch_is->local_sym_name
+ && filename_cmp (arch_is->local_sym_name, file_spec) == 0)
+ ;
+ else
return;
}
lang_has_input_file = true;
+ /* PR 30632: It is OK for name to be NULL. For example
+ see the initialization of first_file in lang_init(). */
+ if (name != NULL)
+ {
+ name = ldfile_possibly_remap_input (name);
+ /* But if a name is remapped to NULL, it should be ignored. */
+ if (name == NULL)
+ return NULL;
+ }
+
p = new_stat (lang_input_statement, stat_ptr);
memset (&p->the_bfd, 0,
sizeof (*p) - offsetof (lang_input_statement_type, the_bfd));
lang_finish (void)
{
output_section_statement_table_free ();
+ ldfile_remap_input_free ();
}
/*----------------------------------------------------------------------
lang_memory_region_type *m;
bool dis_header_printed = false;
+ ldfile_print_input_remaps ();
+
LANG_FOR_EACH_INPUT_STATEMENT (file)
{
asection *s;
{
if (! dis_header_printed)
{
- fprintf (config.map_file, _("\nDiscarded input sections\n\n"));
+ minfo (_("\nDiscarded input sections\n\n"));
dis_header_printed = true;
}
print_input_section (s, true);
}
}
+ if (config.print_map_discarded && ! dis_header_printed)
+ minfo (_("\nThere are no discarded input sections\n"));
minfo (_("\nMemory Configuration\n\n"));
fprintf (config.map_file, "%-16s %-18s %-18s %s\n",
print_nl ();
}
- fprintf (config.map_file, _("\nLinker script and memory map\n\n"));
+ minfo (_("\nLinker script and memory map\n\n"));
if (!link_info.reduce_memory_overheads)
{
/* If supplied an alignment, set it. */
if (s->section_alignment != NULL)
- s->bfd_section->alignment_power = exp_get_power (s->section_alignment,
+ s->bfd_section->alignment_power = exp_get_power (s->section_alignment, s,
"section alignment");
}
&& (flags & SEC_DEBUGGING) != 0)
discard = true;
+ /* Discard non-alloc sections if we are stripping section headers. */
+ else if (config.no_section_header && (flags & SEC_ALLOC) == 0)
+ discard = true;
+
return discard;
}
link_info.output_bfd->flags |= BFD_TRADITIONAL_FORMAT;
else
link_info.output_bfd->flags &= ~BFD_TRADITIONAL_FORMAT;
+ if (config.no_section_header)
+ link_info.output_bfd->flags |= BFD_NO_SECTION_HEADER;
+ else
+ link_info.output_bfd->flags &= ~BFD_NO_SECTION_HEADER;
break;
case lang_target_statement_enum:
#endif
static void
-open_input_bfds (lang_statement_union_type *s, enum open_bfd_mode mode)
+open_input_bfds (lang_statement_union_type *s,
+ lang_output_section_statement_type *os,
+ enum open_bfd_mode mode)
{
for (; s != NULL; s = s->header.next)
{
switch (s->header.type)
{
case lang_constructors_statement_enum:
- open_input_bfds (constructor_list.head, mode);
+ open_input_bfds (constructor_list.head, os, mode);
break;
case lang_output_section_statement_enum:
- open_input_bfds (s->output_section_statement.children.head, mode);
+ os = &s->output_section_statement;
+ open_input_bfds (os->children.head, os, mode);
break;
case lang_wild_statement_enum:
/* Maybe we should load the file's symbols. */
&& !wildcardp (s->wild_statement.filename)
&& !archive_path (s->wild_statement.filename))
lookup_name (s->wild_statement.filename);
- open_input_bfds (s->wild_statement.children.head, mode);
+ open_input_bfds (s->wild_statement.children.head, os, mode);
break;
case lang_group_statement_enum:
{
plugin_insert_save = plugin_insert;
#endif
undefs = link_info.hash->undefs_tail;
- open_input_bfds (s->group_statement.children.head,
+ open_input_bfds (s->group_statement.children.head, os,
mode | OPEN_BFD_FORCE);
}
while (undefs != link_info.hash->undefs_tail
break;
case lang_assignment_statement_enum:
if (s->assignment_statement.exp->type.node_class != etree_assert)
- exp_fold_tree_no_dot (s->assignment_statement.exp);
+ exp_fold_tree_no_dot (s->assignment_statement.exp, os);
break;
default:
break;
}
else
{
- exp_fold_tree_no_dot (os->sectype_value);
+ exp_fold_tree_no_dot (os->sectype_value, os);
if (expld.result.valid_p)
type = expld.result.value;
else
if (output_section_statement->update_dot_tree != NULL)
exp_fold_tree (output_section_statement->update_dot_tree,
+ output_section_statement,
bfd_abs_section_ptr, &print_dot);
}
osec = bfd_abs_section_ptr;
if (assignment->exp->type.node_class != etree_provide)
- exp_fold_tree (tree, osec, &print_dot);
+ exp_fold_tree (tree, output_section, osec, &print_dot);
else
expld.result.valid_p = false;
obstack_free (&map_obstack, entries);
}
+/* Returns TRUE if SYM is a symbol suitable for printing
+ in a linker map as a local symbol. */
+
+static bool
+ld_is_local_symbol (asymbol * sym)
+{
+ const char * name = bfd_asymbol_name (sym);
+
+ if (name == NULL || *name == 0)
+ return false;
+
+ if (strcmp (name, "(null)") == 0)
+ return false;
+
+ /* Skip .Lxxx and such like. */
+ if (bfd_is_local_label (link_info.output_bfd, sym))
+ return false;
+
+ /* FIXME: This is intended to skip ARM mapping symbols,
+ which for some reason are not excluded by bfd_is_local_label,
+ but maybe it is wrong for other architectures.
+ It would be better to fix bfd_is_local_label. */
+ if (*name == '$')
+ return false;
+
+ /* Some local symbols, eg _GLOBAL_OFFSET_TABLE_, are present
+ in the hash table, so do not print duplicates here. */
+ struct bfd_link_hash_entry * h;
+ h = bfd_link_hash_lookup (link_info.hash, name, false /* create */,
+ false /* copy */, true /* follow */);
+ if (h == NULL)
+ return true;
+
+ /* Symbols from the plugin owned BFD will not get their own
+ iteration of this function, but can be on the link_info
+ list. So include them here. */
+ if (h->u.def.section->owner != NULL
+ && ((bfd_get_file_flags (h->u.def.section->owner) & (BFD_LINKER_CREATED | BFD_PLUGIN))
+ == (BFD_LINKER_CREATED | BFD_PLUGIN)))
+ return true;
+
+ return false;
+}
+
/* Print information about an input section to the map file. */
static void
later overlay is shorter than an earier one. */
if (addr + TO_ADDR (size) > print_dot)
print_dot = addr + TO_ADDR (size);
+
+ if (config.print_map_locals)
+ {
+ long storage_needed;
+
+ /* FIXME: It would be better to cache this table, rather
+ than recreating it for each output section. */
+ /* FIXME: This call is not working for non-ELF based targets.
+ Find out why. */
+ storage_needed = bfd_get_symtab_upper_bound (link_info.output_bfd);
+ if (storage_needed > 0)
+ {
+ asymbol ** symbol_table;
+ long number_of_symbols;
+ long j;
+
+ symbol_table = xmalloc (storage_needed);
+ number_of_symbols = bfd_canonicalize_symtab (link_info.output_bfd, symbol_table);
+
+ for (j = 0; j < number_of_symbols; j++)
+ {
+ asymbol * sym = symbol_table[j];
+ bfd_vma sym_addr = sym->value + i->output_section->vma;
+
+ if (sym->section == i->output_section
+ && (sym->flags & BSF_LOCAL) != 0
+ && sym_addr >= addr
+ && sym_addr < print_dot
+ && ld_is_local_symbol (sym))
+ {
+ print_spaces (SECTION_NAME_MAP_LENGTH);
+ minfo ("0x%V (local) %s\n", sym_addr, bfd_asymbol_name (sym));
+ }
+ }
+
+ free (symbol_table);
+ }
+ }
}
}
if (output_section_statement->subsection_alignment != NULL)
i->alignment_power
= exp_get_power (output_section_statement->subsection_alignment,
+ output_section_statement,
"subsection alignment");
if (o->alignment_power < i->alignment_power)
static bfd_vma
lang_size_sections_1
(lang_statement_union_type **prev,
- lang_output_section_statement_type *output_section_statement,
+ lang_output_section_statement_type *current_os,
fill_type *fill,
bfd_vma dot,
bool *relax,
lang_statement_union_type *s;
lang_statement_union_type *prev_s = NULL;
bool removed_prev_s = false;
+ lang_output_section_statement_type *os = current_os;
/* Size up the sections from their constituent parts. */
for (s = *prev; s != NULL; prev_s = s, s = s->header.next)
case lang_output_section_statement_enum:
{
bfd_vma newdot, after, dotdelta;
- lang_output_section_statement_type *os;
lang_memory_region_type *r;
int section_alignment = 0;
os->addr_tree = exp_intop (0);
if (os->addr_tree != NULL)
{
- exp_fold_tree (os->addr_tree, bfd_abs_section_ptr, &dot);
+ exp_fold_tree (os->addr_tree, os, bfd_abs_section_ptr, &dot);
if (expld.result.valid_p)
{
section_alignment = os->bfd_section->alignment_power;
}
else
- section_alignment = exp_get_power (os->section_alignment,
+ section_alignment = exp_get_power (os->section_alignment, os,
"section alignment");
/* Align to what the section needs. */
statement. */
if (os->lma_region != os->region)
section_alignment = exp_get_power (os->section_alignment,
+ os,
"section alignment");
if (section_alignment > 0)
lma = align_power (lma, section_alignment);
dot += dotdelta;
if (os->update_dot_tree != 0)
- exp_fold_tree (os->update_dot_tree, bfd_abs_section_ptr, &dot);
+ exp_fold_tree (os->update_dot_tree, os, bfd_abs_section_ptr, &dot);
/* Update dot in the region ?
We only do this if the section is going to be allocated,
break;
case lang_constructors_statement_enum:
- dot = lang_size_sections_1 (&constructor_list.head,
- output_section_statement,
+ dot = lang_size_sections_1 (&constructor_list.head, current_os,
fill, dot, relax, check_regions);
break;
{
unsigned int size = 0;
- s->data_statement.output_offset =
- dot - output_section_statement->bfd_section->vma;
- s->data_statement.output_section =
- output_section_statement->bfd_section;
+ s->data_statement.output_offset = dot - current_os->bfd_section->vma;
+ s->data_statement.output_section = current_os->bfd_section;
/* We might refer to provided symbols in the expression, and
need to mark them as needed. */
- exp_fold_tree (s->data_statement.exp, bfd_abs_section_ptr, &dot);
+ exp_fold_tree (s->data_statement.exp, os,
+ bfd_abs_section_ptr, &dot);
switch (s->data_statement.type)
{
if (size < TO_SIZE ((unsigned) 1))
size = TO_SIZE ((unsigned) 1);
dot += TO_ADDR (size);
- if (!(output_section_statement->bfd_section->flags
- & SEC_FIXED_SIZE))
- output_section_statement->bfd_section->size
- = TO_SIZE (dot - output_section_statement->bfd_section->vma);
+ if (!(current_os->bfd_section->flags & SEC_FIXED_SIZE))
+ current_os->bfd_section->size
+ = TO_SIZE (dot - current_os->bfd_section->vma);
}
break;
{
int size;
- s->reloc_statement.output_offset =
- dot - output_section_statement->bfd_section->vma;
- s->reloc_statement.output_section =
- output_section_statement->bfd_section;
+ s->reloc_statement.output_offset
+ = dot - current_os->bfd_section->vma;
+ s->reloc_statement.output_section
+ = current_os->bfd_section;
size = bfd_get_reloc_size (s->reloc_statement.howto);
dot += TO_ADDR (size);
- if (!(output_section_statement->bfd_section->flags
- & SEC_FIXED_SIZE))
- output_section_statement->bfd_section->size
- = TO_SIZE (dot - output_section_statement->bfd_section->vma);
+ if (!(current_os->bfd_section->flags & SEC_FIXED_SIZE))
+ current_os->bfd_section->size
+ = TO_SIZE (dot - current_os->bfd_section->vma);
}
break;
case lang_wild_statement_enum:
dot = lang_size_sections_1 (&s->wild_statement.children.head,
- output_section_statement,
- fill, dot, relax, check_regions);
+ current_os, fill, dot, relax,
+ check_regions);
break;
case lang_object_symbols_statement_enum:
- link_info.create_object_symbols_section
- = output_section_statement->bfd_section;
- output_section_statement->bfd_section->flags |= SEC_KEEP;
+ link_info.create_object_symbols_section = current_os->bfd_section;
+ current_os->bfd_section->flags |= SEC_KEEP;
break;
case lang_output_statement_enum:
if (again)
*relax = true;
}
- dot = size_input_section (prev, output_section_statement,
- fill, &removed, dot);
+ dot = size_input_section (prev, current_os, fill, &removed, dot);
}
break;
break;
case lang_fill_statement_enum:
- s->fill_statement.output_section =
- output_section_statement->bfd_section;
+ s->fill_statement.output_section = current_os->bfd_section;
fill = s->fill_statement.fill;
break;
expld.dataseg.relro = exp_seg_relro_none;
- exp_fold_tree (tree,
- output_section_statement->bfd_section,
- &newdot);
+ exp_fold_tree (tree, os, current_os->bfd_section, &newdot);
ldlang_check_relro_region (s);
|| tree->type.node_class == etree_assign)
&& (tree->assign.dst [0] != '.'
|| tree->assign.dst [1] != '\0'))
- output_section_statement->update_dot = 1;
+ current_os->update_dot = 1;
- if (!output_section_statement->ignored)
+ if (!current_os->ignored)
{
- if (output_section_statement == abs_output_section)
+ if (current_os == abs_output_section)
{
/* If we don't have an output section, then just adjust
the default memory address. */
put the pad before when relaxing, in case the
assignment references dot. */
insert_pad (&s->header.next, fill, TO_SIZE (newdot - dot),
- output_section_statement->bfd_section, dot);
+ current_os->bfd_section, dot);
/* Don't neuter the pad below when relaxing. */
s = s->header.next;
should have space allocated to it, unless the
user has explicitly stated that the section
should not be allocated. */
- if (output_section_statement->sectype != noalloc_section
- && (output_section_statement->sectype != noload_section
+ if (current_os->sectype != noalloc_section
+ && (current_os->sectype != noload_section
|| (bfd_get_flavour (link_info.output_bfd)
== bfd_target_elf_flavour)))
- output_section_statement->bfd_section->flags |= SEC_ALLOC;
+ current_os->bfd_section->flags |= SEC_ALLOC;
}
dot = newdot;
}
section. bfd_set_section_contents will complain even for
a pad size of zero. */
s->padding_statement.output_offset
- = dot - output_section_statement->bfd_section->vma;
+ = dot - current_os->bfd_section->vma;
break;
case lang_group_statement_enum:
dot = lang_size_sections_1 (&s->group_statement.children.head,
- output_section_statement,
- fill, dot, relax, check_regions);
+ current_os, fill, dot, relax,
+ check_regions);
break;
case lang_insert_statement_enum:
bfd_vma dot,
bool *found_end)
{
+ lang_output_section_statement_type *os = current_os;
+
for (; s != NULL; s = s->header.next)
{
switch (s->header.type)
case lang_output_section_statement_enum:
{
- lang_output_section_statement_type *os;
bfd_vma newdot;
- os = &(s->output_section_statement);
+ os = &s->output_section_statement;
os->after_end = *found_end;
init_opb (os->bfd_section);
newdot = dot;
newdot += TO_ADDR (os->bfd_section->size);
if (os->update_dot_tree != NULL)
- exp_fold_tree (os->update_dot_tree,
+ exp_fold_tree (os->update_dot_tree, os,
bfd_abs_section_ptr, &newdot);
}
dot = newdot;
break;
case lang_data_statement_enum:
- exp_fold_tree (s->data_statement.exp, bfd_abs_section_ptr, &dot);
+ exp_fold_tree (s->data_statement.exp, os, bfd_abs_section_ptr, &dot);
if (expld.result.valid_p)
{
s->data_statement.value = expld.result.value;
break;
case lang_reloc_statement_enum:
- exp_fold_tree (s->reloc_statement.addend_exp,
+ exp_fold_tree (s->reloc_statement.addend_exp, os,
bfd_abs_section_ptr, &dot);
if (expld.result.valid_p)
s->reloc_statement.addend_value = expld.result.value;
if (strcmp (p, "end") == 0)
*found_end = true;
}
- exp_fold_tree (s->assignment_statement.exp,
+ exp_fold_tree (s->assignment_statement.exp, os,
(current_os->bfd_section != NULL
? current_os->bfd_section : bfd_und_section_ptr),
&dot);
/* Create a bfd for each input file. */
current_target = default_target;
lang_statement_iteration++;
- open_input_bfds (statement_list.head, OPEN_BFD_NORMAL);
+ open_input_bfds (statement_list.head, NULL, OPEN_BFD_NORMAL);
/* Now that open_input_bfds has processed assignments and provide
statements we can give values to symbolic origin/length now. */
link_info.lto_all_symbols_read = true;
/* Open any newly added files, updating the file chains. */
plugin_undefs = link_info.hash->undefs_tail;
- open_input_bfds (*added.tail, OPEN_BFD_NORMAL);
+ lang_output_section_statement_type *last_os = NULL;
+ if (lang_os_list.head != NULL)
+ last_os = ((lang_output_section_statement_type *)
+ ((char *) lang_os_list.tail
+ - offsetof (lang_output_section_statement_type, next)));
+ open_input_bfds (*added.tail, last_os, OPEN_BFD_NORMAL);
if (plugin_undefs == link_info.hash->undefs_tail)
plugin_undefs = NULL;
/* Restore the global list pointer now they have all been added. */
/* Rescan archives in case new undefined symbols have appeared. */
files = file_chain;
lang_statement_iteration++;
- open_input_bfds (statement_list.head, OPEN_BFD_RESCAN);
+ open_input_bfds (statement_list.head, NULL, OPEN_BFD_RESCAN);
lang_list_remove_tail (&file_chain, &files);
while (files.head != NULL)
{
n = stat_alloc (sizeof (struct lang_phdr));
n->next = NULL;
n->name = name;
- n->type = exp_get_vma (type, 0, "program header type");
+ n->type = exp_get_vma (type, NULL, 0, "program header type");
n->filehdr = filehdr;
n->phdrs = phdrs;
n->at = at;
if (l->flags == NULL)
flags = 0;
else
- flags = exp_get_vma (l->flags, 0, "phdr flags");
+ flags = exp_get_vma (l->flags, NULL, 0, "phdr flags");
if (l->at == NULL)
at = 0;
else
- at = exp_get_vma (l->at, 0, "phdr load address");
+ at = exp_get_vma (l->at, NULL, 0, "phdr load address");
if (!bfd_record_phdr (link_info.output_bfd, l->type,
l->flags != NULL, flags, l->at != NULL,
{
if (r->origin_exp)
{
- exp_fold_tree_no_dot (r->origin_exp);
+ exp_fold_tree_no_dot (r->origin_exp, NULL);
if (update_regions_p)
{
if (expld.result.valid_p)
}
if (r->length_exp)
{
- exp_fold_tree_no_dot (r->length_exp);
+ exp_fold_tree_no_dot (r->length_exp, NULL);
if (update_regions_p)
{
if (expld.result.valid_p)