/* POWER/PowerPC XCOFF linker support.
- Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
- 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+ Copyright (C) 1995-2016 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
struct xcoff_link_size_list *next;
struct xcoff_link_hash_entry *h;
bfd_size_type size;
- }
+ }
*size_list;
/* Information about archives. */
return (struct bfd_hash_entry *) ret;
}
-/* Create a XCOFF link hash table. */
+/* Destroy an XCOFF link hash table. */
+
+static void
+_bfd_xcoff_bfd_link_hash_table_free (bfd *obfd)
+{
+ struct xcoff_link_hash_table *ret;
+
+ ret = (struct xcoff_link_hash_table *) obfd->link.hash;
+ if (ret->archive_info)
+ htab_delete (ret->archive_info);
+ if (ret->debug_strtab)
+ _bfd_stringtab_free (ret->debug_strtab);
+ _bfd_generic_link_hash_table_free (obfd);
+}
+
+/* Create an XCOFF link hash table. */
struct bfd_link_hash_table *
_bfd_xcoff_bfd_link_hash_table_create (bfd *abfd)
struct xcoff_link_hash_table *ret;
bfd_size_type amt = sizeof (* ret);
- ret = bfd_malloc (amt);
+ ret = bfd_zmalloc (amt);
if (ret == NULL)
return NULL;
if (!_bfd_link_hash_table_init (&ret->root, abfd, xcoff_link_hash_newfunc,
}
ret->debug_strtab = _bfd_xcoff_stringtab_init ();
- ret->debug_section = NULL;
- ret->loader_section = NULL;
- ret->ldrel_count = 0;
- memset (&ret->ldhdr, 0, sizeof (struct internal_ldhdr));
- ret->linkage_section = NULL;
- ret->toc_section = NULL;
- ret->descriptor_section = NULL;
- ret->imports = NULL;
- ret->file_align = 0;
- ret->textro = FALSE;
- ret->gc = FALSE;
ret->archive_info = htab_create (37, xcoff_archive_info_hash,
xcoff_archive_info_eq, NULL);
- memset (ret->special_sections, 0, sizeof ret->special_sections);
+ if (!ret->debug_strtab || !ret->archive_info)
+ {
+ _bfd_xcoff_bfd_link_hash_table_free (abfd);
+ return NULL;
+ }
+ ret->root.hash_table_free = _bfd_xcoff_bfd_link_hash_table_free;
/* The linker will always generate a full a.out header. We need to
record that fact now, before the sizeof_headers routine could be
return &ret->root;
}
-
-/* Free a XCOFF link hash table. */
-
-void
-_bfd_xcoff_bfd_link_hash_table_free (struct bfd_link_hash_table *hash)
-{
- struct xcoff_link_hash_table *ret = (struct xcoff_link_hash_table *) hash;
-
- _bfd_stringtab_free (ret->debug_strtab);
- bfd_hash_table_free (&ret->root.table);
- free (ret);
-}
\f
/* Read internal relocs for an XCOFF csect. This is a wrapper around
_bfd_coff_read_internal_relocs which tries to take advantage of any
*pp != NULL;
pp = &(*pp)->next, ++c)
{
- if (strcmp ((*pp)->path, imppath) == 0
- && strcmp ((*pp)->file, impfile) == 0
- && strcmp ((*pp)->member, impmember) == 0)
+ if (filename_cmp ((*pp)->path, imppath) == 0
+ && filename_cmp ((*pp)->file, impfile) == 0
+ && filename_cmp ((*pp)->member, impmember) == 0)
break;
}
won't work if we're producing an XCOFF output file with no
XCOFF input files. FIXME. */
- if (!info->relocatable
+ if (!bfd_link_relocatable (info)
&& xcoff_hash_table (info)->loader_section == NULL)
{
asection *lsec;
If C_FILE or first time, handle special
Advance esym, sym_hash, csect_hash ptrs. */
- if (sym.n_sclass == C_FILE)
+ if (sym.n_sclass == C_FILE || sym.n_sclass == C_DWARF)
csect = NULL;
if (csect != NULL)
*csect_cache = csect;
- else if (first_csect == NULL || sym.n_sclass == C_FILE)
+ else if (first_csect == NULL
+ || sym.n_sclass == C_FILE || sym.n_sclass == C_DWARF)
*csect_cache = coff_section_from_bfd_index (abfd, sym.n_scnum);
else
*csect_cache = NULL;
handle them, and that would only be a warning,
not an error. */
if (! ((*info->callbacks->multiple_definition)
- (info, (*sym_hash)->root.root.string,
- NULL, NULL, (bfd_vma) 0,
- (*sym_hash)->root.u.def.section->owner,
- (*sym_hash)->root.u.def.section,
- (*sym_hash)->root.u.def.value)))
+ (info, &(*sym_hash)->root, NULL, NULL, (bfd_vma) 0)))
goto error_return;
/* Try not to give this error too many times. */
(*sym_hash)->flags &= ~XCOFF_MULTIPLY_DEFINED;
/* Make sure that we have seen all the relocs. */
for (o = abfd->sections; o != first_csect; o = o->next)
{
+ /* Debugging sections have no csects. */
+ if (bfd_get_section_flags (abfd, o) & SEC_DEBUGGING)
+ continue;
+
/* Reset the section size and the line number count, since the
data is now attached to the csects. Don't reset the size of
the .debug section, since we need to read it below in
&& (((struct xcoff_link_hash_entry *) h)->flags
& XCOFF_DEF_DYNAMIC) == 0)
{
- if (! (*info->callbacks->add_archive_element)
- (info, abfd, name, subsbfd))
+ if (!(*info->callbacks
+ ->add_archive_element) (info, abfd, name, subsbfd))
return FALSE;
*pneeded = TRUE;
return TRUE;
|| (((struct xcoff_link_hash_entry *) h)->flags
& XCOFF_DEF_DYNAMIC) == 0))
{
- if (! (*info->callbacks->add_archive_element)
- (info, abfd, name, subsbfd))
+ if (!(*info->callbacks
+ ->add_archive_element) (info, abfd, name, subsbfd))
return FALSE;
*pneeded = TRUE;
return TRUE;
static bfd_boolean
xcoff_link_check_archive_element (bfd *abfd,
struct bfd_link_info *info,
+ struct bfd_link_hash_entry *h ATTRIBUTE_UNUSED,
+ const char *name ATTRIBUTE_UNUSED,
bfd_boolean *pneeded)
{
bfd_boolean keep_syms_p;
- bfd *subsbfd = NULL;
+ bfd *oldbfd;
keep_syms_p = (obj_coff_external_syms (abfd) != NULL);
- if (! _bfd_coff_get_external_symbols (abfd))
+ if (!_bfd_coff_get_external_symbols (abfd))
return FALSE;
- if (! xcoff_link_check_ar_symbols (abfd, info, pneeded, &subsbfd))
+ oldbfd = abfd;
+ if (!xcoff_link_check_ar_symbols (abfd, info, pneeded, &abfd))
return FALSE;
if (*pneeded)
{
/* Potentially, the add_archive_element hook may have set a
substitute BFD for us. */
- if (subsbfd && !_bfd_coff_get_external_symbols (subsbfd))
- return FALSE;
- if (! xcoff_link_add_symbols (subsbfd ? subsbfd : abfd, info))
+ if (abfd != oldbfd)
+ {
+ if (!keep_syms_p
+ && !_bfd_coff_free_symbols (oldbfd))
+ return FALSE;
+ keep_syms_p = (obj_coff_external_syms (abfd) != NULL);
+ if (!_bfd_coff_get_external_symbols (abfd))
+ return FALSE;
+ }
+ if (!xcoff_link_add_symbols (abfd, info))
return FALSE;
if (info->keep_memory)
keep_syms_p = TRUE;
if (!keep_syms_p)
{
- if (! _bfd_coff_free_symbols (abfd))
+ if (!_bfd_coff_free_symbols (abfd))
return FALSE;
}
bfd_boolean needed;
if (! xcoff_link_check_archive_element (member, info,
- &needed))
+ NULL, NULL, &needed))
return FALSE;
if (needed)
member->archive_pass = -1;
/* If we're marking an undefined symbol, try find some way of
defining it. */
- if (!info->relocatable
+ if (!bfd_link_relocatable (info)
&& (h->flags & XCOFF_IMPORT) == 0
&& (h->flags & XCOFF_DEF_REGULAR) == 0
&& (h->root.type == bfd_link_hash_undefined
{
bfd *sub;
- for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
+ for (sub = info->input_bfds; sub != NULL; sub = sub->link.next)
{
asection *o;
|| o == xcoff_hash_table (info)->loader_section
|| o == xcoff_hash_table (info)->linkage_section
|| o == xcoff_hash_table (info)->descriptor_section
+ || (bfd_get_section_flags (sub, o) & SEC_DEBUGGING)
|| strcmp (o->name, ".debug") == 0)
o->flags |= SEC_MARK;
else
|| h->root.u.def.value != val))
{
if (! ((*info->callbacks->multiple_definition)
- (info, h->root.root.string, h->root.u.def.section->owner,
- h->root.u.def.section, h->root.u.def.value,
- output_bfd, bfd_abs_section_ptr, val)))
+ (info, &h->root, output_bfd, bfd_abs_section_ptr, val)))
return FALSE;
}
{
struct xcoff_loader_info *ldinfo = (struct xcoff_loader_info *) p;
- if (h->root.type == bfd_link_hash_warning)
- h = (struct xcoff_link_hash_entry *) h->root.u.i.link;
-
/* __rtinit, this symbol has special handling. */
if (h->flags & XCOFF_RTINIT)
return TRUE;
}
/* Garbage collect unused sections. */
- if (info->relocatable || !gc)
+ if (bfd_link_relocatable (info) || !gc)
{
gc = FALSE;
xcoff_hash_table (info)->gc = FALSE;
/* We still need to call xcoff_mark, in order to set ldrel_count
correctly. */
- for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
+ for (sub = info->input_bfds; sub != NULL; sub = sub->link.next)
{
asection *o;
and figure out the contents of the .debug section. */
debug_strtab = xcoff_hash_table (info)->debug_strtab;
- for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
+ for (sub = info->input_bfds; sub != NULL; sub = sub->link.next)
{
asection *subdeb;
bfd_size_type symcount;
bim->size = 0;
bim->buffer = 0;
- abfd->link_next = 0;
+ abfd->link.next = 0;
abfd->format = bfd_object;
abfd->iostream = (void *) bim;
abfd->flags = BFD_IN_MEMORY;
if (! flinfo->info->keep_memory)
copy = TRUE;
hash = TRUE;
- if ((output_bfd->flags & BFD_TRADITIONAL_FORMAT) != 0)
+ if (flinfo->info->traditional_format)
hash = FALSE;
if (! _bfd_coff_get_external_symbols (input_bfd))
if (strings == NULL)
return FALSE;
}
- filename = strings + aux.x_file.x_n.x_offset;
+ if ((bfd_size_type) aux.x_file.x_n.x_offset >= obj_coff_strings_len (input_bfd))
+ filename = _("<corrupt>");
+ else
+ filename = strings + aux.x_file.x_n.x_offset;
indx = _bfd_stringtab_add (flinfo->strtab, filename,
hash, copy);
if (indx == (bfd_size_type) -1)
this case, but I don't think it's worth it. */
is = flinfo->internal_syms + r_symndx;
- name = (_bfd_coff_internal_syment_name
- (input_bfd, is, buf));
+ if (is->n_sclass != C_DWARF)
+ {
+ name = (_bfd_coff_internal_syment_name
+ (input_bfd, is, buf));
- if (name == NULL)
- return FALSE;
+ if (name == NULL)
+ return FALSE;
- if (! ((*flinfo->info->callbacks->unattached_reloc)
- (flinfo->info, name, input_bfd, o,
- irel->r_vaddr)))
- return FALSE;
+ if (!(*flinfo->info->callbacks->unattached_reloc)
+ (flinfo->info, name, input_bfd, o,
+ irel->r_vaddr))
+ return FALSE;
+ }
}
}
}
- if (xcoff_need_ldrel_p (flinfo->info, irel, h))
+ if ((o->flags & SEC_DEBUGGING) == 0
+ && xcoff_need_ldrel_p (flinfo->info, irel, h))
{
asection *sec;
section_index = -1;
for (input_bfd = flinfo->info->input_bfds;
input_bfd != NULL;
- input_bfd = input_bfd->link_next)
+ input_bfd = input_bfd->link.next)
for (sec = input_bfd->sections; sec != NULL; sec = sec->next)
if ((sec->flags & SEC_MARK) != 0 && xcoff_toc_section_p (sec))
{
best_address = toc_end;
for (input_bfd = flinfo->info->input_bfds;
input_bfd != NULL;
- input_bfd = input_bfd->link_next)
+ input_bfd = input_bfd->link.next)
for (sec = input_bfd->sections; sec != NULL; sec = sec->next)
if ((sec->flags & SEC_MARK) != 0 && xcoff_toc_section_p (sec))
{
xcoff_data (output_bfd)->sntoc = section_index;
/* Fill out the TC0 symbol. */
- if (!bfd_xcoff_put_symbol_name (output_bfd, flinfo->strtab, &irsym, "TOC"))
+ if (!bfd_xcoff_put_symbol_name (output_bfd, flinfo->info, flinfo->strtab,
+ &irsym, "TOC"))
return FALSE;
irsym.n_value = best_address;
irsym.n_scnum = section_index;
/* Write out a non-XCOFF global symbol. */
static bfd_boolean
-xcoff_write_global_symbol (struct xcoff_link_hash_entry *h, void * inf)
+xcoff_write_global_symbol (struct bfd_hash_entry *bh, void * inf)
{
+ struct xcoff_link_hash_entry *h = (struct xcoff_link_hash_entry *) bh;
struct xcoff_final_link_info *flinfo = (struct xcoff_final_link_info *) inf;
bfd *output_bfd;
bfd_byte *outsym;
the reloc. */
if (flinfo->info->strip != strip_all)
{
- result = bfd_xcoff_put_symbol_name (output_bfd, flinfo->strtab,
+ result = bfd_xcoff_put_symbol_name (output_bfd, flinfo->info,
+ flinfo->strtab,
&irsym, h->root.root.string);
if (!result)
return FALSE;
h->indx = obj_raw_syment_count (output_bfd);
- result = bfd_xcoff_put_symbol_name (output_bfd, flinfo->strtab, &isym,
- h->root.root.string);
+ result = bfd_xcoff_put_symbol_name (output_bfd, flinfo->info, flinfo->strtab,
+ &isym, h->root.root.string);
if (!result)
return FALSE;
size = bfd_get_reloc_size (howto);
buf = bfd_zmalloc (size);
- if (buf == NULL)
+ if (buf == NULL && size != 0)
return FALSE;
rstat = _bfd_relocate_contents (howto, output_bfd, addend, buf);
file_ptr pos;
bfd_size_type amt;
- if (info->shared)
+ if (bfd_link_pic (info))
abfd->flags |= DYNAMIC;
symesz = bfd_coff_symesz (abfd);
input BFD's. We want at least 6 symbols, since that is the
number which xcoff_write_global_symbol may need. */
max_sym_count = 6;
- for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
+ for (sub = info->input_bfds; sub != NULL; sub = sub->link.next)
{
bfd_size_type sz;
/* Write out all the global symbols which do not come from XCOFF
input files. */
- xcoff_link_hash_traverse (xcoff_hash_table (info),
- xcoff_write_global_symbol,
- (void *) &flinfo);
+ bfd_hash_traverse (&info->hash->table, xcoff_write_global_symbol, &flinfo);
if (flinfo.outsyms != NULL)
{
irel = flinfo.section_info[o->target_index].relocs;
irelend = irel + o->reloc_count;
rel_hash = flinfo.section_info[o->target_index].rel_hashes;
- for (; irel < irelend; irel++, rel_hash++, erel += relsz)
+ for (; irel < irelend; irel++, rel_hash++)
{
if (*rel_hash != NULL)
{