/* POWER/PowerPC XCOFF linker support.
- Copyright (C) 1995-2014 Free Software Foundation, Inc.
+ Copyright (C) 1995-2018 Free Software Foundation, Inc.
Written by Ian Lance Taylor <ian@cygnus.com>, Cygnus Support.
This file is part of BFD, the Binary File Descriptor library.
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)
ret->debug_strtab = _bfd_xcoff_stringtab_init ();
ret->archive_info = htab_create (37, xcoff_archive_info_hash,
xcoff_archive_info_eq, NULL);
+ 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
output file. */
if (info->output_bfd->xvec != abfd->xvec)
{
- (*_bfd_error_handler)
- (_("%s: XCOFF shared object when not producing XCOFF output"),
- bfd_get_filename (abfd));
+ _bfd_error_handler
+ (_("%pB: XCOFF shared object when not producing XCOFF output"),
+ abfd);
bfd_set_error (bfd_error_invalid_operation);
return FALSE;
}
lsec = bfd_get_section_by_name (abfd, ".loader");
if (lsec == NULL)
{
- (*_bfd_error_handler)
- (_("%s: dynamic object with no .loader section"),
- bfd_get_filename (abfd));
+ _bfd_error_handler
+ (_("%pB: dynamic object with no .loader section"),
+ abfd);
bfd_set_error (bfd_error_no_symbols);
return FALSE;
}
return FALSE;
n->next = NULL;
- if (abfd->my_archive == NULL)
+ if (abfd->my_archive == NULL || bfd_is_thin_archive (abfd->my_archive))
{
if (!bfd_xcoff_split_import_path (abfd, abfd->filename,
&n->path, &n->file))
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 (csect != NULL)
*csect_cache = csect;
else if (first_csect == NULL
- || sym.n_sclass == C_FILE || sym.n_sclass == C_DWARF)
+ || 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;
enclosing = xcoff_section_data (abfd, csect)->enclosing;
if (enclosing == NULL)
{
- (*_bfd_error_handler)
- (_("%B: `%s' has line numbers but no enclosing section"),
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB: `%s' has line numbers but no enclosing section"),
abfd, name);
bfd_set_error (bfd_error_bad_value);
goto error_return;
/* Pick up the csect auxiliary information. */
if (sym.n_numaux == 0)
{
- (*_bfd_error_handler)
- (_("%B: class %d symbol `%s' has no aux entries"),
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB: class %d symbol `%s' has no aux entries"),
abfd, sym.n_sclass, name);
bfd_set_error (bfd_error_bad_value);
goto error_return;
switch (smtyp)
{
default:
- (*_bfd_error_handler)
- (_("%B: symbol `%s' has unrecognized csect type %d"),
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB: symbol `%s' has unrecognized csect type %d"),
abfd, name, smtyp);
bfd_set_error (bfd_error_bad_value);
goto error_return;
|| sym.n_scnum != N_UNDEF
|| aux.x_csect.x_scnlen.l != 0)
{
- (*_bfd_error_handler)
- (_("%B: bad XTY_ER symbol `%s': class %d scnum %d scnlen %d"),
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB: bad XTY_ER symbol `%s': class %d scnum %d "
+ "scnlen %" PRId64),
abfd, name, sym.n_sclass, sym.n_scnum,
- aux.x_csect.x_scnlen.l);
+ (int64_t) aux.x_csect.x_scnlen.l);
bfd_set_error (bfd_error_bad_value);
goto error_return;
}
if (sym.n_sclass != C_HIDEXT
|| aux.x_csect.x_scnlen.l != 0)
{
- (*_bfd_error_handler)
- (_("%B: XMC_TC0 symbol `%s' is class %d scnlen %d"),
- abfd, name, sym.n_sclass, aux.x_csect.x_scnlen.l);
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB: XMC_TC0 symbol `%s' is class %d scnlen %" PRId64),
+ abfd, name, sym.n_sclass, (int64_t) aux.x_csect.x_scnlen.l);
bfd_set_error (bfd_error_bad_value);
goto error_return;
}
|| ((bfd_vma) sym.n_value + aux.x_csect.x_scnlen.l
> enclosing->vma + enclosing->size)))
{
- (*_bfd_error_handler)
- (_("%B: csect `%s' not in enclosing section"),
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB: csect `%s' not in enclosing section"),
abfd, name);
bfd_set_error (bfd_error_bad_value);
goto error_return;
}
if (bad)
{
- (*_bfd_error_handler)
- (_("%B: misplaced XTY_LD `%s'"),
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB: misplaced XTY_LD `%s'"),
abfd, name);
bfd_set_error (bfd_error_bad_value);
goto error_return;
}
- csect = section;
+ csect = section;
value = sym.n_value - csect->vma;
}
break;
We also have to handle the case of statically linking a
shared object, which will cause symbol redefinitions,
although this is an easier case to detect. */
- else if (info->output_bfd->xvec == abfd->xvec)
+ else if (info->output_bfd->xvec == abfd->xvec)
{
if (! bfd_is_und_section (section))
*sym_hash = xcoff_link_hash_lookup (xcoff_hash_table (info),
sure the XCOFF linker is wholly prepared to
handle them, and that would only be a warning,
not an error. */
- if (! ((*info->callbacks->multiple_definition)
- (info, &(*sym_hash)->root, NULL, NULL, (bfd_vma) 0)))
- goto error_return;
+ (*info->callbacks->multiple_definition) (info,
+ &(*sym_hash)->root,
+ NULL, NULL,
+ (bfd_vma) 0);
/* Try not to give this error too many times. */
(*sym_hash)->flags &= ~XCOFF_MULTIPLY_DEFINED;
}
= csect->alignment_power;
}
- if (info->output_bfd->xvec == abfd->xvec)
+ if (info->output_bfd->xvec == abfd->xvec)
{
int flag;
{
/* Debugging sections have no csects. */
if (bfd_get_section_flags (abfd, o) & SEC_DEBUGGING)
- continue;
+ 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
{
if (*rel_csect == NULL)
{
- (*_bfd_error_handler)
- (_("%B: reloc %s:%d not in csect"),
- abfd, o->name, i);
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB: reloc %s:%" PRId64 " not in csect"),
+ abfd, o->name, (int64_t) i);
bfd_set_error (bfd_error_bad_value);
goto error_return;
}
/* We identify all function symbols that are the target
of a relocation, so that we can create glue code for
functions imported from dynamic objects. */
- if (info->output_bfd->xvec == abfd->xvec
+ if (info->output_bfd->xvec == abfd->xvec
&& *rel_csect != bfd_und_section_ptr
&& obj_xcoff_sym_hashes (abfd)[rel->r_symndx] != NULL)
{
{
if (!(*info->callbacks
->add_archive_element) (info, abfd, name, subsbfd))
- return FALSE;
+ continue;
*pneeded = TRUE;
return TRUE;
}
undefined references in shared objects. */
if (h != NULL
&& h->type == bfd_link_hash_undefined
- && (info->output_bfd->xvec != abfd->xvec
+ && (info->output_bfd->xvec != abfd->xvec
|| (((struct xcoff_link_hash_entry *) h)->flags
& XCOFF_DEF_DYNAMIC) == 0))
{
if (!(*info->callbacks
->add_archive_element) (info, abfd, name, subsbfd))
- return FALSE;
+ continue;
*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_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)
+ || (bfd_get_section_flags (sub, o) & SEC_DEBUGGING)
|| strcmp (o->name, ".debug") == 0)
o->flags |= SEC_MARK;
else
if (h->root.type == bfd_link_hash_defined
&& (! bfd_is_abs_section (h->root.u.def.section)
|| h->root.u.def.value != val))
- {
- if (! ((*info->callbacks->multiple_definition)
- (info, &h->root, output_bfd, bfd_abs_section_ptr, val)))
- return FALSE;
- }
+ (*info->callbacks->multiple_definition) (info, &h->root, output_bfd,
+ bfd_abs_section_ptr, val);
h->root.type = bfd_link_hash_defined;
h->root.u.def.section = bfd_abs_section_ptr;
FALSE));
if (h == NULL)
{
- (*_bfd_error_handler) (_("%s: no such symbol"), name);
+ _bfd_error_handler (_("%s: no such symbol"), name);
bfd_set_error (bfd_error_no_symbols);
return FALSE;
}
if ((h->flags & XCOFF_EXPORT) != 0
&& (h->flags & XCOFF_WAS_UNDEFINED) != 0)
{
- (*_bfd_error_handler)
+ _bfd_error_handler
(_("warning: attempt to export undefined symbol `%s'"),
h->root.root.string);
return TRUE;
"__rtinit", FALSE, FALSE, TRUE);
if (hsym == NULL)
{
- (*_bfd_error_handler)
+ _bfd_error_handler
(_("error: undefined symbol __rtinit"));
return FALSE;
}
}
/* 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;
ldrel.l_symndx = 2;
else
{
- (*_bfd_error_handler)
- (_("%B: loader reloc in unrecognized section `%s'"),
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB: loader reloc in unrecognized section `%s'"),
reference_bfd, secname);
bfd_set_error (bfd_error_nonrepresentable_section);
return FALSE;
{
if (h->ldindx < 0)
{
- (*_bfd_error_handler)
- (_("%B: `%s' in loader reloc but not loader sym"),
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB: `%s' in loader reloc but not loader sym"),
reference_bfd, h->root.root.string);
bfd_set_error (bfd_error_bad_value);
return FALSE;
if (xcoff_hash_table (flinfo->info)->textro
&& strcmp (output_section->name, ".text") == 0)
{
- (*_bfd_error_handler)
- (_("%B: loader reloc in read-only section %A"),
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB: loader reloc in read-only section %pA"),
reference_bfd, output_section);
bfd_set_error (bfd_error_invalid_operation);
return FALSE;
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)
flinfo->last_file.n_value = output_index;
bfd_coff_swap_sym_out (output_bfd, (void *) &flinfo->last_file,
(void *) (flinfo->outsyms
- + ((flinfo->last_file_index - syment_base)
- * osymesz)));
+ + ((flinfo->last_file_index - syment_base)
+ * osymesz)));
}
/* Write the modified symbols to the output file. */
this case, but I don't think it's worth it. */
is = flinfo->internal_syms + r_symndx;
- if (is->n_sclass != C_DWARF)
- {
- 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;
- }
+ (*flinfo->info->callbacks->unattached_reloc)
+ (flinfo->info, name,
+ input_bfd, o, irel->r_vaddr);
+ }
}
}
}
if ((o->flags & SEC_DEBUGGING) == 0
- && xcoff_need_ldrel_p (flinfo->info, irel, h))
+ && 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))
{
/* Make sure that the start of the TOC is also within range. */
if (best_address > toc_start + 0x8000)
{
- (*_bfd_error_handler)
- (_("TOC overflow: 0x%lx > 0x10000; try -mminimal-toc "
+ _bfd_error_handler
+ (_("TOC overflow: %#" PRIx64 " > 0x10000; try -mminimal-toc "
"when compiling"),
- (unsigned long) (toc_end - toc_start));
+ (uint64_t) (toc_end - toc_start));
bfd_set_error (bfd_error_file_too_big);
return FALSE;
}
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;
tocoff += h->descriptor->u.toc_offset;
/* The first instruction in the glink code needs to be
- cooked to to hold the correct offset in the toc. The
+ cooked to hold the correct offset in the toc. The
rest are just output raw. */
bfd_put_32 (output_bfd,
bfd_xcoff_glink_code(output_bfd, 0) | (tocoff & 0xffff), p);
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;
FALSE, FALSE, TRUE));
if (h == NULL)
{
- if (! ((*flinfo->info->callbacks->unattached_reloc)
- (flinfo->info, link_order->u.reloc.p->u.name, NULL, NULL, (bfd_vma) 0)))
- return FALSE;
+ (*flinfo->info->callbacks->unattached_reloc)
+ (flinfo->info, link_order->u.reloc.p->u.name, NULL, NULL, (bfd_vma) 0);
return TRUE;
}
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);
case bfd_reloc_outofrange:
abort ();
case bfd_reloc_overflow:
- if (! ((*flinfo->info->callbacks->reloc_overflow)
- (flinfo->info, NULL, link_order->u.reloc.p->u.name,
- howto->name, addend, NULL, NULL, (bfd_vma) 0)))
- {
- free (buf);
- return FALSE;
- }
+ (*flinfo->info->callbacks->reloc_overflow)
+ (flinfo->info, NULL, link_order->u.reloc.p->u.name,
+ howto->name, addend, NULL, NULL, (bfd_vma) 0);
break;
}
ok = bfd_set_section_contents (output_bfd, output_section, (void *) 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;
{
if ((*rel_hash)->indx < 0)
{
- if (! ((*info->callbacks->unattached_reloc)
- (info, (*rel_hash)->root.root.string,
- NULL, o, irel->r_vaddr)))
- goto error_return;
+ (*info->callbacks->unattached_reloc)
+ (info, (*rel_hash)->root.root.string,
+ NULL, o, irel->r_vaddr);
(*rel_hash)->indx = 0;
}
irel->r_symndx = (*rel_hash)->indx;
{
if (toc_rel_hash->h->u.toc_indx < 0)
{
- if (! ((*info->callbacks->unattached_reloc)
- (info, toc_rel_hash->h->root.root.string,
- NULL, o, toc_rel_hash->rel->r_vaddr)))
- goto error_return;
+ (*info->callbacks->unattached_reloc)
+ (info, toc_rel_hash->h->root.root.string,
+ NULL, o, toc_rel_hash->rel->r_vaddr);
toc_rel_hash->h->u.toc_indx = 0;
}
toc_rel_hash->rel->r_symndx = toc_rel_hash->h->u.toc_indx;