/* Assume a match on the second char is part of drive specifier,
as in "c:\silly.dos". */
- if (p == pattern + 1)
+ if (p == pattern + 1 && ISALPHA (*pattern))
p = strchr (p + 1, link_info.path_separator);
#endif
return p;
}
-bfd_boolean
+/* Given that FILE_SPEC results in a non-NULL SEP result from archive_path,
+ return whether F matches FILE_SPEC. */
+
+static bfd_boolean
+input_statement_is_archive_path (const char *file_spec, char *sep,
+ lang_input_statement_type *f)
+{
+ bfd_boolean match = FALSE;
+
+ if ((*(sep + 1) == 0
+ || name_match (sep + 1, f->filename) == 0)
+ && ((sep != file_spec)
+ == (f->the_bfd != NULL && f->the_bfd->my_archive != NULL)))
+ {
+ match = TRUE;
+
+ if (sep != file_spec)
+ {
+ const char *aname = f->the_bfd->my_archive->filename;
+ *sep = 0;
+ match = name_match (file_spec, aname) == 0;
+ *sep = link_info.path_separator;
+ }
+ }
+ return match;
+}
+
+static bfd_boolean
unique_section_p (const asection *sec)
{
struct unique_sections *unam;
callback_t callback,
void *data)
{
- bfd_boolean skip = FALSE;
struct name_list *list_tmp;
/* Don't process sections from files which were excluded. */
list_tmp;
list_tmp = list_tmp->next)
{
- skip = name_match (list_tmp->name, file->filename) == 0;
+ char *p = archive_path (list_tmp->name);
- /* If this file is part of an archive, and the archive is
- excluded, exclude this file. */
- if (! skip && file->the_bfd != NULL
- && file->the_bfd->my_archive != NULL
- && file->the_bfd->my_archive->filename != NULL)
+ if (p != NULL)
{
- skip = name_match (list_tmp->name,
- file->the_bfd->my_archive->filename) == 0;
+ if (input_statement_is_archive_path (list_tmp->name, p, file))
+ return;
}
- if (skip)
- break;
+ else if (name_match (list_tmp->name, file->filename) == 0)
+ return;
+
+ /* FIXME: Perhaps remove the following at some stage? Matching
+ unadorned archives like this was never documented and has
+ been superceded by the archive:path syntax. */
+ else if (file->the_bfd != NULL
+ && file->the_bfd->my_archive != NULL
+ && name_match (list_tmp->name,
+ file->the_bfd->my_archive->filename) == 0)
+ return;
}
- if (!skip)
- (*callback) (ptr, sec, s, file, data);
+ (*callback) (ptr, sec, s, file, data);
}
/* Lowest common denominator routine that can handle everything correctly,
{
LANG_FOR_EACH_INPUT_STATEMENT (f)
{
- if ((*(p + 1) == 0
- || name_match (p + 1, f->filename) == 0)
- && ((p != file_spec)
- == (f->the_bfd != NULL && f->the_bfd->my_archive != NULL)))
- {
- bfd_boolean skip = FALSE;
-
- if (p != file_spec)
- {
- const char *aname = f->the_bfd->my_archive->filename;
- *p = 0;
- skip = name_match (file_spec, aname) != 0;
- *p = link_info.path_separator;
- }
- if (!skip)
- walk_wild_file (s, f, callback, data);
- }
+ if (input_statement_is_archive_path (file_spec, p, f))
+ walk_wild_file (s, f, callback, data);
}
}
else if (wildcardp (file_spec))
FAIL ();
}
p->the_bfd = NULL;
- p->asymbols = NULL;
p->next_real_file = NULL;
p->next = NULL;
- p->symbol_count = 0;
p->dynamic = config.dynamic_link;
p->add_needed = add_needed;
p->as_needed = as_needed;
first_file = lang_add_input_file (NULL, lang_input_file_is_marker_enum,
NULL);
abs_output_section =
- lang_output_section_statement_lookup (BFD_ABS_SECTION_NAME);
+ lang_output_section_statement_lookup (BFD_ABS_SECTION_NAME, 0, TRUE);
abs_output_section->bfd_section = bfd_abs_section_ptr;
}
lang_output_section_statement_type *
-lang_output_section_find (const char *const name)
-{
- struct out_section_hash_entry *entry;
- unsigned long hash;
-
- entry = ((struct out_section_hash_entry *)
- bfd_hash_lookup (&output_section_statement_table, name,
- FALSE, FALSE));
- if (entry == NULL)
- return NULL;
-
- hash = entry->root.hash;
- do
- {
- if (entry->s.output_section_statement.constraint != -1)
- return &entry->s.output_section_statement;
- entry = (struct out_section_hash_entry *) entry->root.next;
- }
- while (entry != NULL
- && entry->root.hash == hash
- && strcmp (name, entry->s.output_section_statement.name) == 0);
-
- return NULL;
-}
-
-static lang_output_section_statement_type *
-lang_output_section_statement_lookup_1 (const char *const name, int constraint)
+lang_output_section_statement_lookup (const char *const name,
+ int constraint,
+ bfd_boolean create)
{
struct out_section_hash_entry *entry;
- struct out_section_hash_entry *last_ent;
- unsigned long hash;
entry = ((struct out_section_hash_entry *)
bfd_hash_lookup (&output_section_statement_table, name,
- TRUE, FALSE));
+ create, FALSE));
if (entry == NULL)
{
- einfo (_("%P%F: failed creating section `%s': %E\n"), name);
+ if (create)
+ einfo (_("%P%F: failed creating section `%s': %E\n"), name);
return NULL;
}
{
/* We have a section of this name, but it might not have the correct
constraint. */
- hash = entry->root.hash;
- do
- {
- if (entry->s.output_section_statement.constraint != -1
- && (constraint == 0
- || (constraint == entry->s.output_section_statement.constraint
- && constraint != SPECIAL)))
- return &entry->s.output_section_statement;
- last_ent = entry;
- entry = (struct out_section_hash_entry *) entry->root.next;
- }
- while (entry != NULL
- && entry->root.hash == hash
- && strcmp (name, entry->s.output_section_statement.name) == 0);
+ struct out_section_hash_entry *last_ent;
+ unsigned long hash = entry->root.hash;
+
+ if (create && constraint == SPECIAL)
+ /* Not traversing to the end reverses the order of the second
+ and subsequent SPECIAL sections in the hash table chain,
+ but that shouldn't matter. */
+ last_ent = entry;
+ else
+ do
+ {
+ if (entry->s.output_section_statement.constraint >= 0
+ && (constraint == 0
+ || (constraint
+ == entry->s.output_section_statement.constraint)))
+ return &entry->s.output_section_statement;
+ last_ent = entry;
+ entry = (struct out_section_hash_entry *) entry->root.next;
+ }
+ while (entry != NULL
+ && entry->root.hash == hash
+ && strcmp (name, entry->s.output_section_statement.name) == 0);
+
+ if (!create)
+ return NULL;
entry
= ((struct out_section_hash_entry *)
return &entry->s.output_section_statement;
}
-lang_output_section_statement_type *
-lang_output_section_statement_lookup (const char *const name)
-{
- return lang_output_section_statement_lookup_1 (name, 0);
-}
-
/* A variant of lang_output_section_find used by place_orphan.
Returns the output statement that should precede a new output
statement for SEC. If an exact match is found on certain flags,
return found;
}
- if (sec->flags & SEC_CODE)
+ if ((sec->flags & SEC_CODE) != 0
+ && (sec->flags & SEC_ALLOC) != 0)
{
/* Try for a rw code section. */
for (look = first; look; look = look->next)
found = look;
}
}
- else if (sec->flags & (SEC_READONLY | SEC_THREAD_LOCAL))
+ else if ((sec->flags & (SEC_READONLY | SEC_THREAD_LOCAL)) != 0
+ && (sec->flags & SEC_ALLOC) != 0)
{
/* .rodata can go after .text, .sdata2 after .rodata. */
for (look = first; look; look = look->next)
found = look;
}
}
- else if (sec->flags & SEC_SMALL_DATA)
+ else if ((sec->flags & SEC_SMALL_DATA) != 0
+ && (sec->flags & SEC_ALLOC) != 0)
{
/* .sdata goes after .data, .sbss after .sdata. */
for (look = first; look; look = look->next)
found = look;
}
}
- else if (sec->flags & SEC_HAS_CONTENTS)
+ else if ((sec->flags & SEC_HAS_CONTENTS) != 0
+ && (sec->flags & SEC_ALLOC) != 0)
{
/* .data goes after .rodata. */
for (look = first; look; look = look->next)
found = look;
}
}
- else
+ else if ((sec->flags & SEC_ALLOC) != 0)
{
- /* .bss goes last. */
+ /* .bss goes after any other alloc section. */
for (look = first; look; look = look->next)
{
flags = look->flags;
found = look;
}
}
+ else
+ {
+ /* non-alloc go last. */
+ for (look = first; look; look = look->next)
+ {
+ flags = look->flags;
+ if (look->bfd_section != NULL)
+ flags = look->bfd_section->flags;
+ flags ^= sec->flags;
+ if (!(flags & SEC_DEBUGGING))
+ found = look;
+ }
+ return found;
+ }
if (found || !match_type)
return found;
for (lookup = os->prev; lookup != NULL; lookup = lookup->prev)
{
- if (lookup->constraint == -1)
+ if (lookup->constraint < 0)
continue;
if (lookup->bfd_section != NULL && lookup->bfd_section->owner != NULL)
lang_output_section_statement_type *
lang_insert_orphan (asection *s,
const char *secname,
+ int constraint,
lang_output_section_statement_type *after,
struct orphan_save *place,
etree_type *address,
os_tail = ((lang_output_section_statement_type **)
lang_output_section_statement.tail);
os = lang_enter_output_section_statement (secname, address, 0, NULL, NULL,
- NULL, 0);
+ NULL, constraint);
if (add_child == NULL)
add_child = &os->children;
}
static void
-init_map_userdata (abfd, sec, data)
- bfd *abfd ATTRIBUTE_UNUSED;
- asection *sec;
- void *data ATTRIBUTE_UNUSED;
+init_map_userdata (bfd *abfd ATTRIBUTE_UNUSED,
+ asection *sec,
+ void *data ATTRIBUTE_UNUSED)
{
fat_section_userdata_type *new_data
= ((fat_section_userdata_type *) (stat_alloc
}
static bfd_boolean
-sort_def_symbol (hash_entry, info)
- struct bfd_link_hash_entry *hash_entry;
- void *info ATTRIBUTE_UNUSED;
+sort_def_symbol (struct bfd_link_hash_entry *hash_entry,
+ void *info ATTRIBUTE_UNUSED)
{
if (hash_entry->type == bfd_link_hash_defined
|| hash_entry->type == bfd_link_hash_defweak)
if (strcmp (s->name, DISCARD_SECTION_NAME) == 0)
einfo (_("%P%F: Illegal use of `%s' section\n"), DISCARD_SECTION_NAME);
- s->bfd_section = bfd_get_section_by_name (link_info.output_bfd, s->name);
+ if (s->constraint != SPECIAL)
+ s->bfd_section = bfd_get_section_by_name (link_info.output_bfd, s->name);
if (s->bfd_section == NULL)
- s->bfd_section = bfd_make_section_with_flags (link_info.output_bfd,
- s->name, flags);
+ s->bfd_section = bfd_make_section_anyway_with_flags (link_info.output_bfd,
+ s->name, flags);
if (s->bfd_section == NULL)
{
einfo (_("%P%F: output format %s cannot represent section called %s\n"),
}
else if (err != bfd_error_file_not_recognized
|| place == NULL)
- einfo (_("%F%B: file not recognized: %E\n"), entry->the_bfd);
+ einfo (_("%F%B: file not recognized: %E\n"), entry->the_bfd);
else
bad_load = FALSE;
return 0;
/* Ignore generic big and little endian elf vectors. */
- if ( strcmp (target->name, "elf32-big") == 0
+ if (strcmp (target->name, "elf32-big") == 0
|| strcmp (target->name, "elf64-big") == 0
|| strcmp (target->name, "elf32-little") == 0
|| strcmp (target->name, "elf64-little") == 0)
for (; s != (lang_statement_union_type *) NULL; s = s->header.next)
{
switch (s->header.type)
- {
- case lang_wild_statement_enum:
- walk_wild (&s->wild_statement, check_section_callback,
- output_section_statement);
- if (! output_section_statement->all_input_readonly)
- return;
- break;
- case lang_constructors_statement_enum:
- check_input_sections (constructor_list.head,
- output_section_statement);
- if (! output_section_statement->all_input_readonly)
- return;
- break;
- case lang_group_statement_enum:
- check_input_sections (s->group_statement.children.head,
- output_section_statement);
- if (! output_section_statement->all_input_readonly)
- return;
- break;
- default:
- break;
- }
+ {
+ case lang_wild_statement_enum:
+ walk_wild (&s->wild_statement, check_section_callback,
+ output_section_statement);
+ if (! output_section_statement->all_input_readonly)
+ return;
+ break;
+ case lang_constructors_statement_enum:
+ check_input_sections (constructor_list.head,
+ output_section_statement);
+ if (! output_section_statement->all_input_readonly)
+ return;
+ break;
+ case lang_group_statement_enum:
+ check_input_sections (s->group_statement.children.head,
+ output_section_statement);
+ if (! output_section_statement->all_input_readonly)
+ return;
+ break;
+ default:
+ break;
+ }
}
}
break;
case lang_address_statement_enum:
/* Mark the specified section with the supplied address.
-
If this section was actually a segment marker, then the
directive is ignored if the linker script explicitly
processed the segment marker. Originally, the linker
{
lang_output_section_statement_type *aos
= (lang_output_section_statement_lookup
- (s->address_statement.section_name));
+ (s->address_statement.section_name, 0, TRUE));
if (aos->bfd_section == NULL)
init_os (aos, NULL, 0);
lang_statement_union_type **s;
lang_output_section_statement_type *first_os = NULL;
lang_output_section_statement_type *last_os = NULL;
+ lang_output_section_statement_type *os;
/* "start of list" is actually the statement immediately after
the special abs_section output statement, so that it isn't
/* Keep pointers to the first and last output section
statement in the sequence we may be about to move. */
last_os = &(*s)->output_section_statement;
+
+ /* Set constraint negative so that lang_output_section_find
+ won't match this output section statement. At this
+ stage in linking constraint has values in the range
+ [-1, ONLY_IN_RW]. */
+ last_os->constraint = -2 - last_os->constraint;
if (first_os == NULL)
first_os = last_os;
}
{
lang_insert_statement_type *i = &(*s)->insert_statement;
lang_output_section_statement_type *where;
- lang_output_section_statement_type *os;
lang_statement_union_type **ptr;
lang_statement_union_type *first;
where = lang_output_section_find (i->where);
if (where != NULL && i->is_before)
{
- do
+ do
where = where->prev;
- while (where != NULL && where->constraint == -1);
+ while (where != NULL && where->constraint < 0);
}
if (where == NULL)
{
- einfo (_("%X%P: %s not found for insert\n"), i->where);
- continue;
- }
- /* You can't insert into the list you are moving. */
- for (os = first_os; os != NULL; os = os->next)
- if (os == where || os == last_os)
- break;
- if (os == where)
- {
- einfo (_("%X%P: %s not found for insert\n"), i->where);
- continue;
+ einfo (_("%F%P: %s not found for insert\n"), i->where);
+ return;
}
/* Deal with reordering the output section statement list. */
last_sec = NULL;
for (os = first_os; os != NULL; os = os->next)
{
+ os->constraint = -2 - os->constraint;
if (os->bfd_section != NULL
&& os->bfd_section->owner != NULL)
{
s = &lang_output_section_statement.head;
}
}
+
+ /* Undo constraint twiddling. */
+ for (os = first_os; os != NULL; os = os->next)
+ {
+ os->constraint = -2 - os->constraint;
+ if (os == last_os)
+ break;
+ }
}
/* An output section might have been removed after its statement was
asection *output_section;
bfd_boolean exclude;
- if (os->constraint == -1)
+ if (os->constraint < 0)
continue;
output_section = os->bfd_section;
if (section->vma != section->lma)
minfo (_(" load address 0x%V"), section->lma);
+
+ if (output_section_statement->update_dot_tree != NULL)
+ exp_fold_tree (output_section_statement->update_dot_tree,
+ bfd_abs_section_ptr, &print_dot);
}
print_nl ();
static void
print_input_statement (lang_input_statement_type *statm)
{
- if ((statm->filename != NULL)
- && ((statm->the_bfd == NULL)
- ||
- ((statm->the_bfd->flags & BFD_LINKER_CREATED) == 0)))
+ if (statm->filename != NULL
+ && (statm->the_bfd == NULL
+ || (statm->the_bfd->flags & BFD_LINKER_CREATED) == 0))
fprintf (config.map_file, "LOAD %s\n", statm->filename);
}
else
print_all_symbols (i);
- print_dot = addr + TO_ADDR (size);
+ /* Update print_dot, but make sure that we do not move it
+ backwards - this could happen if we have overlays and a
+ later overlay is shorter than an earier one. */
+ if (addr + TO_ADDR (size) > print_dot)
+ print_dot = addr + TO_ADDR (size);
}
}
os->name, (unsigned long) (newdot - savedot));
}
- bfd_set_section_vma (0, os->bfd_section, newdot);
+ /* PR 6945: Do not update the vma's of output sections
+ when performing a relocatable link on COFF objects. */
+ if (! link_info.relocatable
+ || (bfd_get_flavour (link_info.output_bfd)
+ != bfd_target_coff_flavour))
+ bfd_set_section_vma (0, os->bfd_section, newdot);
os->bfd_section->output_offset = 0;
}
{
/* If DATA_SEGMENT_ALIGN DATA_SEGMENT_RELRO_END pair was seen, try
to put expld.dataseg.relro on a (common) page boundary. */
- bfd_vma old_min_base, relro_end, maxpage;
+ bfd_vma min_base, old_base, relro_end, maxpage;
expld.dataseg.phase = exp_dataseg_relro_adjust;
- old_min_base = expld.dataseg.min_base;
maxpage = expld.dataseg.maxpagesize;
+ /* MIN_BASE is the absolute minimum address we are allowed to start the
+ read-write segment (byte before will be mapped read-only). */
+ min_base = (expld.dataseg.min_base + maxpage - 1) & ~(maxpage - 1);
+ /* OLD_BASE is the address for a feasible minimum address which will
+ still not cause a data overlap inside MAXPAGE causing file offset skip
+ by MAXPAGE. */
+ old_base = expld.dataseg.base;
expld.dataseg.base += (-expld.dataseg.relro_end
& (expld.dataseg.pagesize - 1));
/* Compute the expected PT_GNU_RELRO segment end. */
- relro_end = (expld.dataseg.relro_end + expld.dataseg.pagesize - 1)
- & ~(expld.dataseg.pagesize - 1);
- if (old_min_base + maxpage < expld.dataseg.base)
+ relro_end = ((expld.dataseg.relro_end + expld.dataseg.pagesize - 1)
+ & ~(expld.dataseg.pagesize - 1));
+ if (min_base + maxpage < expld.dataseg.base)
{
expld.dataseg.base -= maxpage;
relro_end -= maxpage;
{
/* The alignment of sections between DATA_SEGMENT_ALIGN
and DATA_SEGMENT_RELRO_END caused huge padding to be
- inserted at DATA_SEGMENT_RELRO_END. Try some other base. */
+ inserted at DATA_SEGMENT_RELRO_END. Try to start a bit lower so
+ that the section alignments will fit in. */
asection *sec;
unsigned int max_alignment_power = 0;
if (((bfd_vma) 1 << max_alignment_power) < expld.dataseg.pagesize)
{
- if (expld.dataseg.base - (1 << max_alignment_power)
- < old_min_base)
+ if (expld.dataseg.base - (1 << max_alignment_power) < old_base)
expld.dataseg.base += expld.dataseg.pagesize;
expld.dataseg.base -= (1 << max_alignment_power);
lang_reset_memory_regions ();
|| (os->bfd_section->flags & SEC_THREAD_LOCAL) == 0
|| link_info.relocatable)
dot += TO_ADDR (os->bfd_section->size);
+
+ if (os->update_dot_tree != NULL)
+ exp_fold_tree (os->update_dot_tree, bfd_abs_section_ptr, &dot);
}
}
break;
unsigned int power;
if (config.sort_common == sort_descending)
- {
- for (power = 4; power > 0; power--)
- bfd_link_hash_traverse (link_info.hash, lang_one_common, &power);
-
- power = 0;
- bfd_link_hash_traverse (link_info.hash, lang_one_common, &power);
- }
+ {
+ for (power = 4; power > 0; power--)
+ bfd_link_hash_traverse (link_info.hash, lang_one_common, &power);
+
+ power = 0;
+ bfd_link_hash_traverse (link_info.hash, lang_one_common, &power);
+ }
else
- {
- for (power = 0; power <= 4; power++)
- bfd_link_hash_traverse (link_info.hash, lang_one_common, &power);
+ {
+ for (power = 0; power <= 4; power++)
+ bfd_link_hash_traverse (link_info.hash, lang_one_common, &power);
- power = UINT_MAX;
+ power = UINT_MAX;
bfd_link_hash_traverse (link_info.hash, lang_one_common, &power);
}
}
&& power_of_two < *(unsigned int *) info)
return TRUE;
else if (config.sort_common == sort_ascending
- && power_of_two > *(unsigned int *) info)
+ && power_of_two > *(unsigned int *) info)
return TRUE;
section = h->u.c.p->section;
|| command_line.force_common_definition)
{
if (default_common_section == NULL)
- {
- default_common_section =
- lang_output_section_statement_lookup (".bss");
-
- }
+ default_common_section
+ = lang_output_section_statement_lookup (".bss", 0,
+ TRUE);
lang_add_section (&default_common_section->children, s,
default_common_section);
}
}
- else if (ldemul_place_orphan (s))
- ;
else
{
- lang_output_section_statement_type *os;
+ const char *name = s->name;
+ int constraint = 0;
- os = lang_output_section_statement_lookup (s->name);
- lang_add_section (&os->children, s, os);
+ if (config.unique_orphan_sections || unique_section_p (s))
+ constraint = SPECIAL;
+
+ if (!ldemul_place_orphan (s, name, constraint))
+ {
+ lang_output_section_statement_type *os;
+ os = lang_output_section_statement_lookup (name,
+ constraint,
+ TRUE);
+ lang_add_section (&os->children, s, os);
+ }
}
}
}
{
lang_output_section_statement_type *os;
- os = lang_output_section_statement_lookup_1 (output_section_statement_name,
- constraint);
- current_section = os;
-
- /* Make next things chain into subchain of this. */
+ os = lang_output_section_statement_lookup (output_section_statement_name,
+ constraint, TRUE);
+ current_section = os;
if (os->addr_tree == NULL)
{
else
os->flags = SEC_NEVER_LOAD;
os->block_value = 1;
+
+ /* Make next things chain into subchain of this. */
stat_ptr = &os->children;
os->subsection_alignment =
{
lang_output_section_phdr_list *pl;
- if (os->constraint == -1)
+ if (os->constraint < 0)
continue;
pl = os->phdrs;
|| (os->bfd_section->flags & SEC_ALLOC) == 0)
continue;
+ /* Don't add orphans to PT_INTERP header. */
+ if (l->type == 3)
+ continue;
+
if (last == NULL)
{
lang_output_section_statement_type * tmp_os;
{
lang_output_section_phdr_list *pl;
- if (os->constraint == -1
+ if (os->constraint < 0
|| os->bfd_section == NULL)
continue;
java_sym = sym;
}
- if (head->htab && (prev == NULL || prev->symbol))
+ if (head->htab && (prev == NULL || prev->literal))
{
struct bfd_elf_version_expr e;
switch (prev ? prev->mask : 0)
{
- case 0:
- if (head->mask & BFD_ELF_VERSION_C_TYPE)
- {
- e.symbol = sym;
- expr = htab_find (head->htab, &e);
- while (expr && strcmp (expr->symbol, sym) == 0)
- if (expr->mask == BFD_ELF_VERSION_C_TYPE)
- goto out_ret;
- else
- expr = expr->next;
- }
- /* Fallthrough */
- case BFD_ELF_VERSION_C_TYPE:
- if (head->mask & BFD_ELF_VERSION_CXX_TYPE)
- {
- e.symbol = cxx_sym;
- expr = htab_find (head->htab, &e);
- while (expr && strcmp (expr->symbol, cxx_sym) == 0)
- if (expr->mask == BFD_ELF_VERSION_CXX_TYPE)
- goto out_ret;
- else
- expr = expr->next;
- }
- /* Fallthrough */
- case BFD_ELF_VERSION_CXX_TYPE:
- if (head->mask & BFD_ELF_VERSION_JAVA_TYPE)
- {
- e.symbol = java_sym;
- expr = htab_find (head->htab, &e);
- while (expr && strcmp (expr->symbol, java_sym) == 0)
- if (expr->mask == BFD_ELF_VERSION_JAVA_TYPE)
- goto out_ret;
- else
- expr = expr->next;
- }
- /* Fallthrough */
- default:
- break;
+ case 0:
+ if (head->mask & BFD_ELF_VERSION_C_TYPE)
+ {
+ e.pattern = sym;
+ expr = htab_find (head->htab, &e);
+ while (expr && strcmp (expr->pattern, sym) == 0)
+ if (expr->mask == BFD_ELF_VERSION_C_TYPE)
+ goto out_ret;
+ else
+ expr = expr->next;
+ }
+ /* Fallthrough */
+ case BFD_ELF_VERSION_C_TYPE:
+ if (head->mask & BFD_ELF_VERSION_CXX_TYPE)
+ {
+ e.pattern = cxx_sym;
+ expr = htab_find (head->htab, &e);
+ while (expr && strcmp (expr->pattern, cxx_sym) == 0)
+ if (expr->mask == BFD_ELF_VERSION_CXX_TYPE)
+ goto out_ret;
+ else
+ expr = expr->next;
+ }
+ /* Fallthrough */
+ case BFD_ELF_VERSION_CXX_TYPE:
+ if (head->mask & BFD_ELF_VERSION_JAVA_TYPE)
+ {
+ e.pattern = java_sym;
+ expr = htab_find (head->htab, &e);
+ while (expr && strcmp (expr->pattern, java_sym) == 0)
+ if (expr->mask == BFD_ELF_VERSION_JAVA_TYPE)
+ goto out_ret;
+ else
+ expr = expr->next;
+ }
+ /* Fallthrough */
+ default:
+ break;
}
}
/* Finally, try the wildcards. */
- if (prev == NULL || prev->symbol)
+ if (prev == NULL || prev->literal)
expr = head->remaining;
else
expr = prev->next;
break;
}
-out_ret:
+ out_ret:
if (cxx_sym != sym)
free ((char *) cxx_sym);
if (java_sym != sym)
}
/* Return NULL if the PATTERN argument is a glob pattern, otherwise,
- return a string pointing to the symbol name. */
+ return a pointer to the symbol name with any backslash quotes removed. */
static const char *
realsymbol (const char *pattern)
{
/* It is a glob pattern only if there is no preceding
backslash. */
- if (! backslash && (*p == '?' || *p == '*' || *p == '['))
- {
- free (symbol);
- return NULL;
- }
-
if (backslash)
{
/* Remove the preceding backslash. */
*(s - 1) = *p;
+ backslash = FALSE;
changed = TRUE;
}
else
- *s++ = *p;
+ {
+ if (*p == '?' || *p == '*' || *p == '[')
+ {
+ free (symbol);
+ return NULL;
+ }
- backslash = *p == '\\';
+ *s++ = *p;
+ backslash = *p == '\\';
+ }
}
if (changed)
ret = xmalloc (sizeof *ret);
ret->next = orig;
- ret->pattern = literal_p ? NULL : new;
ret->symver = 0;
ret->script = 0;
- ret->symbol = literal_p ? new : realsymbol (new);
+ ret->literal = TRUE;
+ ret->pattern = literal_p ? new : realsymbol (new);
+ if (ret->pattern == NULL)
+ {
+ ret->pattern = new;
+ ret->literal = FALSE;
+ }
if (lang == NULL || strcasecmp (lang, "C") == 0)
ret->mask = BFD_ELF_VERSION_C_TYPE;
{
const struct bfd_elf_version_expr *e = p;
- return htab_hash_string (e->symbol);
+ return htab_hash_string (e->pattern);
}
static int
const struct bfd_elf_version_expr *e1 = p1;
const struct bfd_elf_version_expr *e2 = p2;
- return strcmp (e1->symbol, e2->symbol) == 0;
+ return strcmp (e1->pattern, e2->pattern) == 0;
}
static void
for (e = head->list; e; e = e->next)
{
- if (e->symbol)
+ if (e->literal)
count++;
head->mask |= e->mask;
}
for (e = head->list; e; e = next)
{
next = e->next;
- if (!e->symbol)
+ if (!e->literal)
{
*remaining_loc = e;
remaining_loc = &e->next;
last = e1;
e1 = e1->next;
}
- while (e1 && strcmp (e1->symbol, e->symbol) == 0);
+ while (e1 && strcmp (e1->pattern, e->pattern) == 0);
if (last == NULL)
{
/* This is a duplicate. */
/* FIXME: Memory leak. Sometimes pattern is not
xmalloced alone, but in larger chunk of memory. */
- /* free (e->symbol); */
+ /* free (e->pattern); */
free (e);
}
else
{
struct bfd_elf_version_expr *e2;
- if (t->locals.htab && e1->symbol)
+ if (t->locals.htab && e1->literal)
{
e2 = htab_find (t->locals.htab, e1);
- while (e2 && strcmp (e1->symbol, e2->symbol) == 0)
+ while (e2 && strcmp (e1->pattern, e2->pattern) == 0)
{
if (e1->mask == e2->mask)
einfo (_("%X%P: duplicate expression `%s'"
- " in version information\n"), e1->symbol);
+ " in version information\n"), e1->pattern);
e2 = e2->next;
}
}
- else if (!e1->symbol)
+ else if (!e1->literal)
for (e2 = t->locals.remaining; e2 != NULL; e2 = e2->next)
if (strcmp (e1->pattern, e2->pattern) == 0
&& e1->mask == e2->mask)
{
struct bfd_elf_version_expr *e2;
- if (t->globals.htab && e1->symbol)
+ if (t->globals.htab && e1->literal)
{
e2 = htab_find (t->globals.htab, e1);
- while (e2 && strcmp (e1->symbol, e2->symbol) == 0)
+ while (e2 && strcmp (e1->pattern, e2->pattern) == 0)
{
if (e1->mask == e2->mask)
einfo (_("%X%P: duplicate expression `%s'"
" in version information\n"),
- e1->symbol);
+ e1->pattern);
e2 = e2->next;
}
}
- else if (!e1->symbol)
+ else if (!e1->literal)
for (e2 = t->globals.remaining; e2 != NULL; e2 = e2->next)
if (strcmp (e1->pattern, e2->pattern) == 0
&& e1->mask == e2->mask)