/* Linker command language support.
- Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 98, 1999
+ Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 98, 99, 2000
Free Software Foundation, Inc.
This file is part of GLD, the Gnu Linker.
static void init_os PARAMS ((lang_output_section_statement_type *s));
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 *string));
+static void already_linked_table_init PARAMS ((void));
+static void already_linked_table_free PARAMS ((void));
static boolean wildcardp PARAMS ((const char *));
static lang_statement_union_type *wild_sort
PARAMS ((lang_wild_statement_type *, lang_input_statement_type *,
void *data;
{
/* Don't process sections from files which were excluded. */
- if (ptr->exclude_filename != NULL)
+ if (ptr->exclude_filename_list != NULL)
{
- boolean match;
+ struct name_list *list_tmp;
+ for (list_tmp = ptr->exclude_filename_list; list_tmp; list_tmp = list_tmp->next)
+ {
+ boolean match;
- if (wildcardp (ptr->exclude_filename))
- match = fnmatch (ptr->exclude_filename, file->filename, 0) == 0 ? true : false;
- else
- match = strcmp (ptr->exclude_filename, file->filename) == 0 ? true : false;
+ if (wildcardp (list_tmp->name))
+ match = fnmatch (list_tmp->name, file->filename, 0) == 0 ? true : false;
+ else
+ match = strcmp (list_tmp->name, file->filename) == 0 ? true : false;
- if (match)
- return;
+ if (match)
+ return;
+ }
}
if (file->just_syms_flag == false)
break;
}
}
-
+\f
/* Sections marked with the SEC_LINK_ONCE flag should only be linked
- once into the output. This routine checks each sections, and
- arranges to discard it if a section of the same name has already
+ once into the output. This routine checks each section, and
+ arrange to discard it if a section of the same name has already
been linked. If the section has COMDAT information, then it uses
that to decide whether the section should be included. This code
assumes that all relevant sections have the SEC_LINK_ONCE flag set;
- that is, it does not depend solely upon the section name. This is
- called via bfd_map_over_sections. */
+ that is, it does not depend solely upon the section name.
+ section_already_linked is called via bfd_map_over_sections. */
+
+/* This is the shape of the elements inside the already_linked hash
+ table. It maps a name onto a list of already_linked elements with
+ the same name. It's possible to get more than one element in a
+ list if the COMDAT sections have different names. */
+
+struct already_linked_hash_entry
+{
+ struct bfd_hash_entry root;
+ struct already_linked *entry;
+};
+
+struct already_linked
+{
+ struct already_linked *next;
+ asection *sec;
+};
+
+/* The hash table. */
+
+static struct bfd_hash_table already_linked_table;
/*ARGSUSED*/
static void
PTR data;
{
lang_input_statement_type *entry = (lang_input_statement_type *) data;
- struct sec_link_once
- {
- struct sec_link_once *next;
- asection *sec;
- };
- static struct sec_link_once *sec_link_once_list;
flagword flags;
const char *name;
- struct sec_link_once *l;
+ struct already_linked *l;
+ struct already_linked_hash_entry *already_linked_list;
/* If we are only reading symbols from this object, then we want to
discard all sections. */
name = bfd_get_section_name (abfd, sec);
- for (l = sec_link_once_list; l != NULL; l = l->next)
+ already_linked_list =
+ ((struct already_linked_hash_entry *)
+ bfd_hash_lookup (&already_linked_table, name, true, false));
+
+ for (l = already_linked_list->entry; l != NULL; l = l->next)
{
- if (strcmp (name, bfd_get_section_name (l->sec->owner, l->sec)) == 0
- && (sec->comdat == NULL
- || l->sec->comdat == NULL
- || strcmp (sec->comdat->name, l->sec->comdat->name) == 0))
+ if (sec->comdat == NULL
+ || l->sec->comdat == NULL
+ || strcmp (sec->comdat->name, l->sec->comdat->name) == 0)
{
/* The section has already been linked. See if we should
issue a warning. */
}
}
- /* This is the first section with this name. Record it. */
+ /* This is the first section with this name. Record it. Allocate
+ the memory from the same obstack as the hash table is kept in. */
+
+ l = ((struct already_linked *)
+ bfd_hash_allocate (&already_linked_table, sizeof *l));
- l = (struct sec_link_once *) xmalloc (sizeof *l);
l->sec = sec;
- l->next = sec_link_once_list;
- sec_link_once_list = l;
+ l->next = already_linked_list->entry;
+ already_linked_list->entry = l;
+}
+
+/* Support routines for the hash table used by section_already_linked,
+ initialize the table, fill in an entry and remove the table. */
+
+static struct bfd_hash_entry *
+already_linked_newfunc (entry, table, string)
+ struct bfd_hash_entry *entry ATTRIBUTE_UNUSED;
+ struct bfd_hash_table *table;
+ const char *string ATTRIBUTE_UNUSED;
+{
+ struct already_linked_hash_entry *ret =
+ bfd_hash_allocate (table, sizeof (struct already_linked_hash_entry));
+
+ ret->entry = NULL;
+
+ return (struct bfd_hash_entry *) ret;
+}
+
+static void
+already_linked_table_init ()
+{
+ if (! bfd_hash_table_init_n (&already_linked_table,
+ already_linked_newfunc,
+ 42))
+ einfo (_("%P%F: Failed to create hash table\n"));
+}
+
+static void
+already_linked_table_free ()
+{
+ bfd_hash_table_free (&already_linked_table);
}
\f
/* The wild routines.
if (w->filenames_sorted)
minfo ("SORT(");
- if (w->exclude_filename != NULL)
- minfo ("EXCLUDE_FILE ( %s )", w->exclude_filename);
- if (w->filename != NULL)
+ if (w->exclude_filename_list != NULL)
+ {
+ name_list *tmp;
+ minfo ("EXCLUDE_FILE ( %s", w->exclude_filename_list->name);
+ for (tmp=w->exclude_filename_list->next; tmp; tmp = tmp->next)
+ minfo (", %s", tmp->name);
+ minfo (")");
+ }
+ if (w->filename != NULL)
minfo ("%s", w->filename);
else
minfo ("*");
return dot;
}
+#define IGNORE_SECTION(bfd, s) \
+ (((bfd_get_section_flags (bfd, s) & (SEC_ALLOC | SEC_LOAD)) != (SEC_ALLOC | SEC_LOAD)) \
+ || bfd_section_size (bfd, s) == 0)
+
/* Check to see if any allocated sections overlap with other allocated
sections. This can happen when the linker script specifically specifies
the output section addresses of the two sections. */
/* Scan all sections in the output list. */
for (s = output_bfd->sections; s != NULL; s = s->next)
- /* Ignore sections which are not loaded or which have no contents. */
- if ((bfd_get_section_flags (output_bfd, s) & (SEC_ALLOC | SEC_LOAD))
- && bfd_section_size (output_bfd, s) != 0)
- {
- asection * os;
+ {
+ asection * os;
+
+ /* Ignore sections which are not loaded or which have no contents. */
+ if (IGNORE_SECTION (output_bfd, s))
+ continue;
+
+ /* Once we reach section 's' stop our seach. This prevents two
+ warning messages from being produced, one for 'section A overlaps
+ section B' and one for 'section B overlaps section A'. */
+ for (os = output_bfd->sections; os != s; os = os->next)
+ {
+ bfd_vma s_start;
+ bfd_vma s_end;
+ bfd_vma os_start;
+ bfd_vma os_end;
+
+ /* Only consider loadable sections with real contents. */
+ if (IGNORE_SECTION (output_bfd, os))
+ continue;
- /* Once we reach section 's' stop our seach. This prevents two
- warning messages from being produced, one for 'section A overlaps
- section B' and one for 'section B overlaps section A'. */
- for (os = output_bfd->sections; os != s; os = os->next)
- {
- bfd_vma s_start;
- bfd_vma s_end;
- bfd_vma os_start;
- bfd_vma os_end;
-
- /* Only consider loadable sections with real contents. */
- if (((bfd_get_section_flags (output_bfd, os)
- & (SEC_ALLOC | SEC_LOAD)) == 0)
- || bfd_section_size (output_bfd, os) == 0)
- continue;
-
- /* We must check the sections' LMA addresses not their
- VMA addresses because overlay sections can have
- overlapping VMAs but they must have distinct LMAs. */
- s_start = bfd_section_lma (output_bfd, s);
- os_start = bfd_section_lma (output_bfd, os);
- s_end = s_start + bfd_section_size (output_bfd, s) - 1;
- os_end = os_start + bfd_section_size (output_bfd, os) - 1;
-
- /* Look for an overlap. */
- if ((s_end < os_start) || (s_start > os_end))
- continue;
-
- einfo (
+ /* We must check the sections' LMA addresses not their
+ VMA addresses because overlay sections can have
+ overlapping VMAs but they must have distinct LMAs. */
+ s_start = bfd_section_lma (output_bfd, s);
+ os_start = bfd_section_lma (output_bfd, os);
+ s_end = s_start + bfd_section_size (output_bfd, s) - 1;
+ os_end = os_start + bfd_section_size (output_bfd, os) - 1;
+
+ /* Look for an overlap. */
+ if ((s_end < os_start) || (s_start > os_end))
+ continue;
+
+ einfo (
_("%X%P: section %s [%V -> %V] overlaps section %s [%V -> %V]\n"),
- s->name, s_start, s_end, os->name, os_start, os_end);
-
- /* Once we have found one overlap for this section,
- stop looking for others. */
- break;
- }
- }
+ s->name, s_start, s_end, os->name, os_start, os_end);
+
+ /* Once we have found one overlap for this section,
+ stop looking for others. */
+ break;
+ }
+ }
}
/* This variable indicates whether bfd_relax_section should be called
/* Update dot in the region ?
We only do this if the section is going to be allocated,
since unallocated sections do not contribute to the region's
- overall size in memory. */
+
+ If the SEC_NEVER_LOAD bit is not set, it will affect the
+ addresses of sections after it. We have to update
+ dot. */
if (os->region != (lang_memory_region_type *) NULL
- && (bfd_get_section_flags (output_bfd, os->bfd_section)
- & (SEC_ALLOC | SEC_LOAD)))
+ && ((bfd_get_section_flags (output_bfd, os->bfd_section)
+ & SEC_NEVER_LOAD) == 0
+ || (bfd_get_section_flags (output_bfd, os->bfd_section)
+ & (SEC_ALLOC | SEC_LOAD))))
{
os->region->current = dot;
/* Add to the hash table all undefineds on the command line */
lang_place_undefineds ();
+ already_linked_table_init ();
+
/* Create a bfd for each input file */
current_target = default_target;
open_input_bfds (statement_list.head, false);
ldemul_after_open ();
+ already_linked_table_free ();
+
/* Make sure that we're not mixing architectures. We call this
after all the input files have been opened, but before we do any
other processing, so that any operations merge_private_bfd_data
void
lang_add_wild (section_name, sections_sorted, filename, filenames_sorted,
- keep_sections, exclude_filename)
+ keep_sections, exclude_filename_list)
const char *const section_name;
boolean sections_sorted;
const char *const filename;
boolean filenames_sorted;
boolean keep_sections;
- const char *exclude_filename;
+ struct name_list *exclude_filename_list;
{
lang_wild_statement_type *new = new_stat (lang_wild_statement,
stat_ptr);
new->filename = filename;
new->filenames_sorted = filenames_sorted;
new->keep_sections = keep_sections;
- new->exclude_filename = exclude_filename;
+ new->exclude_filename_list = exclude_filename_list;
lang_list_init (&new->children);
}