/* POWER/PowerPC XCOFF linker support.
- Copyright 1995, 1996 Free Software Foundation, Inc.
+ Copyright 1995, 1996, 1997, 1998, 1999 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.
#define STRING_SIZE_SIZE (4)
-/* In order to support linking different object file formats into an
- XCOFF format, we need to be able to determine whether a particular
- bfd_target is an XCOFF vector. FIXME: We need to rethink this
- whole approach. */
-#define XCOFF_XVECP(xv) \
- (strcmp ((xv)->name, "aixcoff-rs6000") == 0 \
- || strcmp ((xv)->name, "xcoff-powermac") == 0)
-
/* Get the XCOFF hash table entries for a BFD. */
#define obj_xcoff_sym_hashes(bfd) \
((struct xcoff_link_hash_entry **) obj_coff_sym_hashes (bfd))
/* The remaining words of global linkage code. */
-static unsigned long xcoff_glink_code[] =
-{
+static unsigned long xcoff_glink_code[] = {
0x90410014, /* stw r2,20(r1) */
0x800c0000, /* lwz r0,0(r12) */
0x804c0004, /* lwz r2,4(r12) */
/* The ldhdr structure. This appears at the start of the .loader
section. */
-struct internal_ldhdr
-{
+struct internal_ldhdr {
/* The version number: currently always 1. */
unsigned long l_version;
/* The number of symbol table entries. */
bfd_size_type l_stoff;
};
-struct external_ldhdr
-{
+struct external_ldhdr {
bfd_byte l_version[4];
bfd_byte l_nsyms[4];
bfd_byte l_nreloc[4];
/* The ldsym structure. This is used to represent a symbol in the
.loader section. */
-struct internal_ldsym
-{
- union
- {
- /* The symbol name if <= SYMNMLEN characters. */
- char _l_name[SYMNMLEN];
- struct
- {
- /* Zero if the symbol name is more than SYMNMLEN characters. */
- long _l_zeroes;
- /* The offset in the string table if the symbol name is more
- than SYMNMLEN characters. */
- long _l_offset;
- } _l_l;
- } _l;
+struct internal_ldsym {
+ union {
+ /* The symbol name if <= SYMNMLEN characters. */
+ char _l_name[SYMNMLEN];
+ struct {
+ /* Zero if the symbol name is more than SYMNMLEN characters. */
+ long _l_zeroes;
+ /* The offset in the string table if the symbol name is more
+ than SYMNMLEN characters. */
+ long _l_offset;
+ } _l_l;
+ } _l;
/* The symbol value. */
bfd_vma l_value;
/* The symbol section number. */
bfd_size_type l_parm;
};
-struct external_ldsym
-{
- union
- {
- bfd_byte _l_name[SYMNMLEN];
- struct
- {
- bfd_byte _l_zeroes[4];
- bfd_byte _l_offset[4];
- } _l_l;
- } _l;
+struct external_ldsym {
+ union {
+ bfd_byte _l_name[SYMNMLEN];
+ struct {
+ bfd_byte _l_zeroes[4];
+ bfd_byte _l_offset[4];
+ } _l_l;
+ } _l;
bfd_byte l_value[4];
bfd_byte l_scnum[2];
bfd_byte l_smtype[1];
/* The ldrel structure. This is used to represent a reloc in the
.loader section. */
-struct internal_ldrel
-{
+struct internal_ldrel {
/* The reloc address. */
bfd_vma l_vaddr;
/* The symbol table index in the .loader section symbol table. */
short l_rsecnm;
};
-struct external_ldrel
-{
+struct external_ldrel {
bfd_byte l_vaddr[4];
bfd_byte l_symndx[4];
bfd_byte l_rtype[2];
/* The list of import files. */
-struct xcoff_import_file
-{
+struct xcoff_import_file {
/* The next entry in the list. */
struct xcoff_import_file *next;
/* The path. */
/* An entry in the XCOFF linker hash table. */
-struct xcoff_link_hash_entry
-{
+struct xcoff_link_hash_entry {
struct bfd_link_hash_entry root;
/* Symbol index in output file. Set to -1 initially. Set to -2 if
section which holds it. */
asection *toc_section;
- union
- {
- /* If we have created a TOC entry (the XCOFF_SET_TOC flag is
- set), this is the offset in toc_section. */
- bfd_vma toc_offset;
- /* If the TOC entry comes from an input file, this is set to the
- symbol index of the C_HIDEXT XMC_TC or XMC_TD symbol. */
- long toc_indx;
- } u;
+ union {
+ /* If we have created a TOC entry (the XCOFF_SET_TOC flag is set),
+ this is the offset in toc_section. */
+ bfd_vma toc_offset;
+ /* If the TOC entry comes from an input file, this is set to the
+ symbol index of the C_HIDEXT XMC_TC or XMC_TD symbol. */
+ long toc_indx;
+ } u;
/* If this symbol is a function entry point which is called, this
field holds a pointer to the function descriptor. If this symbol
/* The .loader symbol table entry, if there is one. */
struct internal_ldsym *ldsym;
- /* The .loader symbol table index. */
+ /* If XCOFF_BUILT_LDSYM is set, this is the .loader symbol table
+ index. If XCOFF_BUILD_LDSYM is clear, and XCOFF_IMPORT is set,
+ this is the l_ifile value. */
long ldindx;
/* Some linker flags. */
#define XCOFF_HAS_SIZE (04000)
/* Symbol is a function descriptor. */
#define XCOFF_DESCRIPTOR (010000)
+ /* Multiple definitions have been for the symbol. */
+#define XCOFF_MULTIPLY_DEFINED (020000)
/* The storage mapping class. */
unsigned char smclas;
/* The XCOFF linker hash table. */
-struct xcoff_link_hash_table
-{
+struct xcoff_link_hash_table {
struct bfd_link_hash_table root;
/* The .debug string hash table. We need to compute this while
boolean gc;
/* A linked list of symbols for which we have size information. */
- struct xcoff_link_size_list
- {
- struct xcoff_link_size_list *next;
- struct xcoff_link_hash_entry *h;
- bfd_size_type size;
- } *size_list;
+ struct xcoff_link_size_list {
+ struct xcoff_link_size_list *next;
+ struct xcoff_link_hash_entry *h;
+ bfd_size_type size;
+ } *size_list;
/* Magic sections: _text, _etext, _data, _edata, _end, end. */
asection *special_sections[6];
/* Information we keep for each section in the output file during the
final link phase. */
-struct xcoff_link_section_info
-{
+struct xcoff_link_section_info {
/* The relocs to be output. */
struct internal_reloc *relocs;
/* For each reloc against a global symbol whose index was not known
index of the TOC symbol is not known when the reloc was handled,
an entry is added to this linked list. This is not an array,
like rel_hashes, because this case is quite uncommon. */
- struct xcoff_toc_rel_hash
- {
- struct xcoff_toc_rel_hash *next;
- struct xcoff_link_hash_entry *h;
- struct internal_reloc *rel;
- } *toc_rel_hashes;
+ struct xcoff_toc_rel_hash {
+ struct xcoff_toc_rel_hash *next;
+ struct xcoff_link_hash_entry *h;
+ struct internal_reloc *rel;
+ } *toc_rel_hashes;
};
/* Information that we pass around while doing the final link step. */
-struct xcoff_final_link_info
-{
+struct xcoff_final_link_info {
/* General link information. */
struct bfd_link_info *info;
/* Output BFD. */
PARAMS ((bfd *, const struct internal_ldrel *, struct external_ldrel *));
static struct bfd_hash_entry *xcoff_link_hash_newfunc
PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
+static boolean xcoff_get_section_contents PARAMS ((bfd *, asection *));
static struct internal_reloc *xcoff_read_internal_relocs
PARAMS ((bfd *, asection *, boolean, bfd_byte *, boolean,
struct internal_reloc *));
static boolean xcoff_link_add_symbols PARAMS ((bfd *, struct bfd_link_info *));
static boolean xcoff_link_add_dynamic_symbols
PARAMS ((bfd *, struct bfd_link_info *));
+static boolean xcoff_mark_symbol
+ PARAMS ((struct bfd_link_info *, struct xcoff_link_hash_entry *));
static boolean xcoff_mark PARAMS ((struct bfd_link_info *, asection *));
static void xcoff_sweep PARAMS ((struct bfd_link_info *));
static boolean xcoff_build_ldsyms
if (coff_section_data (abfd, sec)->contents == NULL)
{
- coff_section_data (abfd, sec)->contents = bfd_malloc (sec->_raw_size);
+ coff_section_data (abfd, sec)->contents =
+ (bfd_byte *) bfd_malloc (sec->_raw_size);
if (coff_section_data (abfd, sec)->contents == NULL)
return false;
if (ldsym._l._l_name[i] == '\0')
break;
if (i < SYMNMLEN)
- symbuf->symbol.name = elsym->_l._l_name;
+ symbuf->symbol.name = (char *) elsym->_l._l_name;
else
{
char *c;
/* The typical dynamic reloc. */
static reloc_howto_type xcoff_dynamic_reloc =
- HOWTO (0, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
- false, /* pc_relative */
- 0, /* bitpos */
+ HOWTO (0, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
- 0, /* special_function */
- "R_POS", /* name */
- true, /* partial_inplace */
- 0xffffffff, /* src_mask */
- 0xffffffff, /* dst_mask */
+ 0, /* special_function */
+ "R_POS", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
false); /* pcrel_offset */
/* Get the dynamic relocs. */
{
case bfd_object:
return xcoff_link_add_object_symbols (abfd, info);
+
case bfd_archive:
- /* We need to look through the archive for stripped dynamic
- objects, because they will not appear in the archive map even
- though they should, perhaps, be included. Also, if the
- linker has no map, we just consider each object file in turn,
- since that apparently is what the AIX native linker does. */
+ /* If the archive has a map, do the usual search. We then need
+ to check the archive for stripped dynamic objects, because
+ they will not appear in the archive map even though they
+ should, perhaps, be included. If the archive has no map, we
+ just consider each object file in turn, since that apparently
+ is what the AIX native linker does. */
+ if (bfd_has_map (abfd))
+ {
+ if (! (_bfd_generic_link_add_archive_symbols
+ (abfd, info, xcoff_link_check_archive_element)))
+ return false;
+ }
+
{
bfd *member;
}
member = bfd_openr_next_archived_file (abfd, member);
}
-
- if (! bfd_has_map (abfd))
- return true;
-
- /* Now do the usual search. */
- return (_bfd_generic_link_add_archive_symbols
- (abfd, info, xcoff_link_check_archive_element));
}
+ return true;
+
default:
bfd_set_error (bfd_error_wrong_format);
return false;
bfd_byte *linenos;
} *reloc_info = NULL;
+ keep_syms = obj_coff_keep_syms (abfd);
+
if ((abfd->flags & DYNAMIC) != 0
&& ! info->static_link)
{
dsec->alignment_power = 2;
}
/* Likewise for the .debug section. */
- if (xcoff_hash_table (info)->debug_section == NULL)
+ if (xcoff_hash_table (info)->debug_section == NULL
+ && info->strip != strip_all)
{
asection *dsec;
}
/* Don't let the linker relocation routines discard the symbols. */
- keep_syms = obj_coff_keep_syms (abfd);
obj_coff_keep_syms (abfd) = true;
csect = NULL;
if (enclosing == NULL)
{
(*_bfd_error_handler)
- ("%s: `%s' has line numbers but no enclosing section",
+ (_("%s: `%s' has line numbers but no enclosing section"),
bfd_get_filename (abfd), name);
bfd_set_error (bfd_error_bad_value);
goto error_return;
if (sym.n_numaux == 0)
{
(*_bfd_error_handler)
- ("%s: class %d symbol `%s' has no aux entries",
+ (_("%s: class %d symbol `%s' has no aux entries"),
bfd_get_filename (abfd), sym.n_sclass, name);
bfd_set_error (bfd_error_bad_value);
goto error_return;
{
default:
(*_bfd_error_handler)
- ("%s: symbol `%s' has unrecognized csect type %d",
+ (_("%s: symbol `%s' has unrecognized csect type %d"),
bfd_get_filename (abfd), name, smtyp);
bfd_set_error (bfd_error_bad_value);
goto error_return;
|| aux.x_csect.x_scnlen.l != 0)
{
(*_bfd_error_handler)
- ("%s: bad XTY_ER symbol `%s': class %d scnum %d scnlen %d",
+ (_("%s: bad XTY_ER symbol `%s': class %d scnum %d scnlen %d"),
bfd_get_filename (abfd), name, sym.n_sclass, sym.n_scnum,
aux.x_csect.x_scnlen.l);
bfd_set_error (bfd_error_bad_value);
|| aux.x_csect.x_scnlen.l != 0)
{
(*_bfd_error_handler)
- ("%s: XMC_TC0 symbol `%s' is class %d scnlen %d",
+ (_("%s: XMC_TC0 symbol `%s' is class %d scnlen %d"),
bfd_get_filename (abfd), name, sym.n_sclass,
aux.x_csect.x_scnlen.l);
bfd_set_error (bfd_error_bad_value);
the csect storage mapping class, so that the linker can
accumulate similar csects together. */
{
- static const char *csect_name_by_class[] =
- {
- ".pr", ".ro", ".db", ".tc", ".ua", ".rw", ".gl", ".xo",
- ".sv", ".bs", ".ds", ".uc", ".ti", ".tb", NULL, ".tc0",
- ".td"
- };
+ static const char *csect_name_by_class[] = {
+ ".pr", ".ro", ".db", ".tc", ".ua", ".rw", ".gl", ".xo",
+ ".sv", ".bs", ".ds", ".uc", ".ti", ".tb", NULL, ".tc0",
+ ".td"
+ };
const char *csect_name;
asection *enclosing;
|| csect_name_by_class[aux.x_csect.x_smclas] == NULL)
{
(*_bfd_error_handler)
- ("%s: symbol `%s' has unrecognized smclas %d",
+ (_("%s: symbol `%s' has unrecognized smclas %d"),
bfd_get_filename (abfd), name, aux.x_csect.x_smclas);
bfd_set_error (bfd_error_bad_value);
goto error_return;
> enclosing->vma + enclosing->_raw_size)))
{
(*_bfd_error_handler)
- ("%s: csect `%s' not in enclosing section",
+ (_("%s: csect `%s' not in enclosing section"),
bfd_get_filename (abfd), name);
bfd_set_error (bfd_error_bad_value);
goto error_return;
/* Record the enclosing section in the tdata for this new
section. */
csect->used_by_bfd =
- ((struct coff_section_tdata *)
- bfd_zalloc (abfd, sizeof (struct coff_section_tdata)));
+ (PTR) bfd_zalloc (abfd, sizeof (struct coff_section_tdata));
if (csect->used_by_bfd == NULL)
goto error_return;
coff_section_data (abfd, csect)->tdata =
if (bad)
{
(*_bfd_error_handler)
- ("%s: misplaced XTY_LD `%s'",
+ (_("%s: misplaced XTY_LD `%s'"),
bfd_get_filename (abfd), name);
bfd_set_error (bfd_error_bad_value);
goto error_return;
case XTY_CM:
/* This is an unitialized csect. We could base the name on
- the storage mapping class, but we don't bother. If this
- csect is externally visible, it is a common symbol. */
+ the storage mapping class, but we don't bother except for
+ an XMC_TD symbol. If this csect is externally visible,
+ it is a common symbol. We put XMC_TD symbols in sections
+ named .tocbss, and rely on the linker script to put that
+ in the TOC area. */
if (csect != NULL)
{
/ symesz);
}
- csect = bfd_make_section_anyway (abfd, ".bss");
+ if (aux.x_csect.x_smclas == XMC_TD)
+ csect = bfd_make_section_anyway (abfd, ".tocbss");
+ else
+ csect = bfd_make_section_anyway (abfd, ".bss");
if (csect == NULL)
goto error_return;
csect->vma = sym.n_value;
/ symesz);
csect->used_by_bfd =
- ((struct coff_section_tdata *)
- bfd_zalloc (abfd, sizeof (struct coff_section_tdata)));
+ (PTR) bfd_zalloc (abfd, sizeof (struct coff_section_tdata));
if (csect->used_by_bfd == NULL)
goto error_return;
coff_section_data (abfd, csect)->tdata =
|| sym._n._n_n._n_offset == 0)
copy = true;
+ /* The AIX linker appears to only detect multiple symbol
+ definitions when there is a reference to the symbol. If
+ a symbol is defined multiple times, and the only
+ references are from the same object file, the AIX linker
+ appears to permit it. It does not merge the different
+ definitions, but handles them independently. On the
+ other hand, if there is a reference, the linker reports
+ an error.
+
+ This matters because the AIX <net/net_globals.h> header
+ file actually defines an initialized array, so we have to
+ actually permit that to work.
+
+ Just to make matters even more confusing, the AIX linker
+ appears to permit multiple symbol definitions whenever
+ the second definition is in an archive rather than an
+ object file. This may be a consequence of the manner in
+ which it handles archives: I think it may load the entire
+ archive in as separate csects, and then let garbage
+ collection discard symbols.
+
+ 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. */
+
if (info->hash->creator == abfd->xvec)
{
- /* If we are statically linking a shared object, it is
- OK for symbol redefinitions to occur. I can't figure
- out just what the XCOFF linker is doing, but
- something like this is required for -bnso to work. */
if (! bfd_is_und_section (section))
*sym_hash = xcoff_link_hash_lookup (xcoff_hash_table (info),
name, true, copy, false);
&& ! bfd_is_und_section (section)
&& ! bfd_is_com_section (section))
{
- /* If the existing symbol is to global linkage code,
- and this symbol is not global linkage code, then
- replace the existing symbol. */
+ /* This is a second definition of a defined symbol. */
if ((abfd->flags & DYNAMIC) != 0
&& ((*sym_hash)->smclas != XMC_GL
|| aux.x_csect.x_smclas == XMC_GL
|| ((*sym_hash)->root.u.def.section->owner->flags
& DYNAMIC) == 0))
{
+ /* The new symbol is from a shared library, and
+ either the existing symbol is not global
+ linkage code or this symbol is global linkage
+ code. If the existing symbol is global
+ linkage code and the new symbol is not, then
+ we want to use the new symbol. */
section = bfd_und_section_ptr;
value = 0;
}
else if (((*sym_hash)->root.u.def.section->owner->flags
& DYNAMIC) != 0)
{
+ /* The existing symbol is from a shared library.
+ Replace it. */
(*sym_hash)->root.type = bfd_link_hash_undefined;
(*sym_hash)->root.u.undef.abfd =
(*sym_hash)->root.u.def.section->owner;
}
+ else if (abfd->my_archive != NULL)
+ {
+ /* This is a redefinition in an object contained
+ in an archive. Just ignore it. See the
+ comment above. */
+ section = bfd_und_section_ptr;
+ value = 0;
+ }
+ else if ((*sym_hash)->root.next != NULL
+ || info->hash->undefs_tail == &(*sym_hash)->root)
+ {
+ /* This symbol has been referenced. In this
+ case, we just continue and permit the
+ multiple definition error. See the comment
+ above about the behaviour of the AIX linker. */
+ }
+ else if ((*sym_hash)->smclas == aux.x_csect.x_smclas)
+ {
+ /* The symbols are both csects of the same
+ class. There is at least a chance that this
+ is a semi-legitimate redefinition. */
+ section = bfd_und_section_ptr;
+ value = 0;
+ (*sym_hash)->flags |= XCOFF_MULTIPLY_DEFINED;
+ }
+ }
+ else if (((*sym_hash)->flags & XCOFF_MULTIPLY_DEFINED) != 0
+ && ((*sym_hash)->root.type == bfd_link_hash_defined
+ || (*sym_hash)->root.type == bfd_link_hash_defweak)
+ && (bfd_is_und_section (section)
+ || bfd_is_com_section (section)))
+ {
+ /* This is a reference to a multiply defined symbol.
+ Report the error now. See the comment above
+ about the behaviour of the AIX linker. We could
+ also do this with warning symbols, but I'm not
+ 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.root.string,
+ (bfd *) NULL, (asection *) NULL, 0,
+ (*sym_hash)->root.u.def.section->owner,
+ (*sym_hash)->root.u.def.section,
+ (*sym_hash)->root.u.def.value)))
+ goto error_return;
+ /* Try not to give this error too many times. */
+ (*sym_hash)->flags &= ~XCOFF_MULTIPLY_DEFINED;
}
}
else
{
(*sym_hash)->root.u.c.p->alignment_power
- = csect->alignment_power;
+ = csect->alignment_power;
}
}
if (*rel_csect == NULL)
{
(*_bfd_error_handler)
- ("%s: reloc %s:%d not in csect",
+ (_("%s: reloc %s:%d not in csect"),
bfd_get_filename (abfd), o->name, i);
bfd_set_error (bfd_error_bad_value);
goto error_return;
/* Reset SEC_RELOC and the reloc_count, since the reloc
information is now attached to the csects. */
- o->flags &=~ SEC_RELOC;
+ o->flags &= ~SEC_RELOC;
o->reloc_count = 0;
/* If we are not keeping memory, free the reloc information. */
if (info->hash->creator != abfd->xvec)
{
(*_bfd_error_handler)
- ("%s: XCOFF shared object when not producing XCOFF output",
+ (_("%s: XCOFF shared object when not producing XCOFF output"),
bfd_get_filename (abfd));
bfd_set_error (bfd_error_invalid_operation);
return false;
if (lsec == NULL)
{
(*_bfd_error_handler)
- ("%s: dynamic object with no .loader section",
+ (_("%s: dynamic object with no .loader section"),
bfd_get_filename (abfd));
bfd_set_error (bfd_error_no_symbols);
return false;
h->root.u.def.section = bfd_abs_section_ptr;
h->root.u.def.value = ldsym.l_value;
}
+
+ /* If this symbol defines a function descriptor, then it
+ implicitly defines the function code as well. */
+ if (h->smclas == XMC_DS
+ || (h->smclas == XMC_XO && name[0] != '.'))
+ h->flags |= XCOFF_DESCRIPTOR;
+ if ((h->flags & XCOFF_DESCRIPTOR) != 0)
+ {
+ struct xcoff_link_hash_entry *hds;
+
+ hds = h->descriptor;
+ if (hds == NULL)
+ {
+ char *dsnm;
+
+ dsnm = bfd_malloc (strlen (name) + 2);
+ if (dsnm == NULL)
+ return false;
+ dsnm[0] = '.';
+ strcpy (dsnm + 1, name);
+ hds = xcoff_link_hash_lookup (xcoff_hash_table (info), dsnm,
+ true, true, true);
+ free (dsnm);
+ if (hds == NULL)
+ return false;
+
+ if (hds->root.type == bfd_link_hash_new)
+ {
+ hds->root.type = bfd_link_hash_undefined;
+ hds->root.u.undef.abfd = abfd;
+ /* We do not want to add this to the undefined
+ symbol list. */
+ }
+
+ hds->descriptor = h;
+ h->descriptor = hds;
+ }
+
+ hds->flags |= XCOFF_DEF_DYNAMIC;
+ if (hds->smclas == XMC_UA)
+ hds->smclas = XMC_PR;
+
+ /* An absolute symbol appears to actually define code, not a
+ function descriptor. This is how some math functions are
+ implemented on AIX 4.1. */
+ if (h->smclas == XMC_XO
+ && (hds->root.type == bfd_link_hash_undefined
+ || hds->root.type == bfd_link_hash_undefweak))
+ {
+ hds->smclas = XMC_XO;
+ hds->root.type = bfd_link_hash_defined;
+ hds->root.u.def.section = bfd_abs_section_ptr;
+ hds->root.u.def.value = ldsym.l_value;
+ }
+ }
}
if (buf != NULL && ! coff_section_data (abfd, lsec)->keep_contents)
asection *hsec;
hsec = h->root.u.def.section;
- if ((hsec->flags & SEC_MARK) == 0)
+ if (! bfd_is_abs_section (hsec)
+ && (hsec->flags & SEC_MARK) == 0)
{
if (! xcoff_mark (info, hsec))
return false;
struct bfd_link_info *info;
asection *sec;
{
- if ((sec->flags & SEC_MARK) != 0)
+ if (bfd_is_abs_section (sec)
+ || (sec->flags & SEC_MARK) != 0)
return true;
sec->flags |= SEC_MARK;
&& h->root.root.string[0] == '.'
&& h->descriptor != NULL
&& ((h->descriptor->flags & XCOFF_DEF_DYNAMIC) != 0
- || info->shared
|| ((h->descriptor->flags & XCOFF_IMPORT) != 0
&& (h->descriptor->flags
& XCOFF_DEF_REGULAR) == 0))))
struct xcoff_link_hash_entry *h = (struct xcoff_link_hash_entry *) harg;
struct xcoff_link_size_list *n;
- if (! XCOFF_XVECP (output_bfd->xvec))
+ if (bfd_get_flavour (output_bfd) != bfd_target_xcoff_flavour)
return true;
/* This will hardly ever be called. I don't want to burn four bytes
{
struct xcoff_link_hash_entry *h = (struct xcoff_link_hash_entry *) harg;
- if (! XCOFF_XVECP (output_bfd->xvec))
+ if (bfd_get_flavour (output_bfd) != bfd_target_xcoff_flavour)
return true;
+ /* A symbol name which starts with a period is the code for a
+ function. If the symbol is undefined, then add an undefined
+ symbol for the function descriptor, and import that instead. */
+ if (h->root.root.string[0] == '.'
+ && h->root.type == bfd_link_hash_undefined
+ && val == (bfd_vma) -1)
+ {
+ struct xcoff_link_hash_entry *hds;
+
+ hds = h->descriptor;
+ if (hds == NULL)
+ {
+ hds = xcoff_link_hash_lookup (xcoff_hash_table (info),
+ h->root.root.string + 1,
+ true, false, true);
+ if (hds == NULL)
+ return false;
+ if (hds->root.type == bfd_link_hash_new)
+ {
+ hds->root.type = bfd_link_hash_undefined;
+ hds->root.u.undef.abfd = h->root.u.undef.abfd;
+ }
+ hds->flags |= XCOFF_DESCRIPTOR;
+ BFD_ASSERT ((hds->flags & XCOFF_CALLED) == 0
+ && (h->flags & XCOFF_DESCRIPTOR) == 0);
+ hds->descriptor = h;
+ h->descriptor = hds;
+ }
+
+ /* Now, if the descriptor is undefined, import the descriptor
+ rather than the symbol we were told to import. FIXME: Is
+ this correct in all cases? */
+ if (hds->root.type == bfd_link_hash_undefined)
+ h = hds;
+ }
+
h->flags |= XCOFF_IMPORT;
if (val != (bfd_vma) -1)
h->root.u.def.value = val;
}
- if (h->ldsym == NULL)
- {
- h->ldsym = ((struct internal_ldsym *)
- bfd_zalloc (output_bfd, sizeof (struct internal_ldsym)));
- if (h->ldsym == NULL)
- return false;
- }
-
+ /* We overload the ldindx field to hold the l_ifile value for this
+ symbol. */
+ BFD_ASSERT (h->ldsym == NULL);
+ BFD_ASSERT ((h->flags & XCOFF_BUILT_LDSYM) == 0);
if (imppath == NULL)
- h->ldsym->l_ifile = (bfd_size_type) -1;
+ h->ldindx = -1;
else
{
unsigned int c;
*pp = n;
}
- h->ldsym->l_ifile = c;
+ h->ldindx = c;
}
return true;
bfd *output_bfd;
struct bfd_link_info *info;
struct bfd_link_hash_entry *harg;
- boolean syscall;
+ boolean syscall ATTRIBUTE_UNUSED;
{
struct xcoff_link_hash_entry *h = (struct xcoff_link_hash_entry *) harg;
- if (! XCOFF_XVECP (output_bfd->xvec))
+ if (bfd_get_flavour (output_bfd) != bfd_target_xcoff_flavour)
return true;
h->flags |= XCOFF_EXPORT;
{
struct xcoff_link_hash_entry *h;
- if (! XCOFF_XVECP (output_bfd->xvec))
+ if (bfd_get_flavour (output_bfd) != bfd_target_xcoff_flavour)
return true;
h = ((struct xcoff_link_hash_entry *)
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;
}
h->flags |= XCOFF_REF_REGULAR | XCOFF_LDREL;
++xcoff_hash_table (info)->ldrel_count;
-
+
/* Mark the symbol to avoid garbage collection. */
if (! xcoff_mark_symbol (info, h))
return false;
{
struct xcoff_link_hash_entry *h;
- if (! XCOFF_XVECP (output_bfd->xvec))
+ if (bfd_get_flavour (output_bfd) != bfd_target_xcoff_flavour)
return true;
h = xcoff_link_hash_lookup (xcoff_hash_table (info), name, true, true,
/* This structure is used to pass information through
xcoff_link_hash_traverse. */
-struct xcoff_loader_info
-{
+struct xcoff_loader_info {
/* Set if a problem occurred. */
boolean failed;
/* Output BFD. */
struct bfd_strtab_hash *debug_strtab;
bfd_byte *debug_contents = NULL;
- if (! XCOFF_XVECP (output_bfd->xvec))
+ if (bfd_get_flavour (output_bfd) != bfd_target_xcoff_flavour)
{
for (i = 0; i < 6; i++)
special_sections[i] = NULL;
xcoff_hash_table (info)->file_align = file_align;
xcoff_hash_table (info)->textro = textro;
- hentry = xcoff_link_hash_lookup (xcoff_hash_table (info), entry,
- false, false, true);
- if (hentry != NULL)
- hentry->flags |= XCOFF_ENTRY;
+ if (entry == NULL)
+ hentry = NULL;
+ else
+ {
+ hentry = xcoff_link_hash_lookup (xcoff_hash_table (info), entry,
+ false, false, true);
+ if (hentry != NULL)
+ hentry->flags |= XCOFF_ENTRY;
+ }
/* Garbage collect unused sections. */
if (info->relocateable
xcoff_data (sub)->debug_indices = debug_index;
/* Grab the contents of the .debug section. We use malloc and
- copy the neams into the debug stringtab, rather than
+ copy the names into the debug stringtab, rather than
bfd_alloc, because I expect that, when linking many files
together, many of the strings will be the same. Storing the
strings in the hash table should save space in this case. */
}
}
- xcoff_hash_table (info)->debug_section->_raw_size =
- _bfd_stringtab_size (debug_strtab);
+ if (info->strip != strip_all)
+ xcoff_hash_table (info)->debug_section->_raw_size =
+ _bfd_stringtab_size (debug_strtab);
return true;
&& (h->flags & XCOFF_DEF_REGULAR) == 0
&& (h->flags & XCOFF_REF_REGULAR) != 0
&& (h->flags & XCOFF_DEF_DYNAMIC) == 0
- && (h->root.u.def.section->owner->flags & DYNAMIC) == 0)
+ && (bfd_is_abs_section (h->root.u.def.section)
+ || (h->root.u.def.section->owner->flags & DYNAMIC) == 0))
h->flags |= XCOFF_DEF_REGULAR;
/* If all defined symbols should be exported, mark them now. We
if (ldinfo->export_defineds
&& (h->flags & XCOFF_DEF_REGULAR) != 0
&& h->root.root.string[0] != '.')
- h->flags |= XCOFF_EXPORT;
+ {
+ boolean export;
+
+ /* We don't export a symbol which is being defined by an object
+ included from an archive which contains a shared object. The
+ rationale is that if an archive contains both an unshared and
+ a shared object, then there must be some reason that the
+ unshared object is unshared, and we don't want to start
+ providing a shared version of it. In particular, this solves
+ a bug involving the _savefNN set of functions. gcc will call
+ those functions without providing a slot to restore the TOC,
+ so it is essential that these functions be linked in directly
+ and not from a shared object, which means that a shared
+ object which also happens to link them in must not export
+ them. This is confusing, but I haven't been able to think of
+ a different approach. Note that the symbols can, of course,
+ be exported explicitly. */
+ export = true;
+ if ((h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ && h->root.u.def.section->owner != NULL
+ && h->root.u.def.section->owner->my_archive != NULL)
+ {
+ bfd *arbfd, *member;
+
+ arbfd = h->root.u.def.section->owner->my_archive;
+ member = bfd_openr_next_archived_file (arbfd, (bfd *) NULL);
+ while (member != NULL)
+ {
+ if ((member->flags & DYNAMIC) != 0)
+ {
+ export = false;
+ break;
+ }
+ member = bfd_openr_next_archived_file (arbfd, member);
+ }
+ }
+
+ if (export)
+ h->flags |= XCOFF_EXPORT;
+ }
/* We don't want to garbage collect symbols which are not defined in
XCOFF files. This is a convenient place to mark them. */
!= ldinfo->info->hash->creator)))
h->flags |= XCOFF_MARK;
- /* If this symbol is called and defined in a dynamic object, or not
- defined at all when building a shared object, or imported, then
- we need to set up global linkage code for it. (Unless we did
- garbage collection and we didn't need this symbol.) */
+ /* If this symbol is called and defined in a dynamic object, or it
+ is imported, then we need to set up global linkage code for it.
+ (Unless we did garbage collection and we didn't need this
+ symbol.) */
if ((h->flags & XCOFF_CALLED) != 0
&& (h->root.type == bfd_link_hash_undefined
|| h->root.type == bfd_link_hash_undefweak)
&& h->root.root.string[0] == '.'
&& h->descriptor != NULL
&& ((h->descriptor->flags & XCOFF_DEF_DYNAMIC) != 0
- || ldinfo->info->shared
|| ((h->descriptor->flags & XCOFF_IMPORT) != 0
&& (h->descriptor->flags & XCOFF_DEF_REGULAR) == 0))
&& (! xcoff_hash_table (ldinfo->info)->gc
else
{
(*_bfd_error_handler)
- ("warning: attempt to export undefined symbol `%s'",
+ (_("warning: attempt to export undefined symbol `%s'"),
h->root.root.string);
h->ldsym = NULL;
return true;
/* We need to add this symbol to the .loader symbols. */
- /* h->ldsym will already have been allocated for an explicitly
- imported symbol. */
+ BFD_ASSERT (h->ldsym == NULL);
+ h->ldsym = ((struct internal_ldsym *)
+ bfd_zalloc (ldinfo->output_bfd,
+ sizeof (struct internal_ldsym)));
if (h->ldsym == NULL)
{
- h->ldsym = ((struct internal_ldsym *)
- bfd_zalloc (ldinfo->output_bfd,
- sizeof (struct internal_ldsym)));
- if (h->ldsym == NULL)
- {
- ldinfo->failed = true;
- return false;
- }
+ ldinfo->failed = true;
+ return false;
}
+ if ((h->flags & XCOFF_IMPORT) != 0)
+ h->ldsym->l_ifile = h->ldindx;
+
/* The first 3 symbol table indices are reserved to indicate the
sections. */
h->ldindx = ldinfo->ldsym_count + 3;
saw_contents = true;
for (op = &abfd->sections; *op != NULL; op = &(*op)->next)
{
- (*op)->target_index = indx;
if (strcmp ((*op)->name, ".pad") == 0)
saw_contents = false;
else if (((*op)->flags & SEC_HAS_CONTENTS) != 0
}
}
- bfd_coff_compute_section_file_positions (abfd);
+ if (! bfd_coff_compute_section_file_positions (abfd))
+ goto error_return;
}
/* Allocate space for the pointers we need to keep for the relocs. */
o->rel_filepos = 0;
else
{
- o->flags |= SEC_RELOC;
- o->rel_filepos = rel_filepos;
- rel_filepos += o->reloc_count * relsz;
+ /* A stripped file has no relocs. However, we still
+ allocate the buffers, so that later code doesn't have to
+ worry about whether we are stripping or not. */
+ if (info->strip == strip_all)
+ o->rel_filepos = 0;
+ else
+ {
+ o->flags |= SEC_RELOC;
+ o->rel_filepos = rel_filepos;
+ rel_filepos += o->reloc_count * relsz;
+ }
/* We don't know the indices of global symbols until we have
written out all the local symbols. For each section in
finfo.section_info[o->target_index].rel_hashes =
((struct xcoff_link_hash_entry **)
bfd_malloc (o->reloc_count
- * sizeof (struct xcoff_link_hash_entry *)));
+ * sizeof (struct xcoff_link_hash_entry *)));
if (finfo.section_info[o->target_index].relocs == NULL
|| finfo.section_info[o->target_index].rel_hashes == NULL)
goto error_return;
/* Figure out the largest number of symbols in an input BFD. Take
the opportunity to clear the output_has_begun fields of all the
- input BFD's. We want at least 4 symbols, since that is the
+ input BFD's. We want at least 6 symbols, since that is the
number which xcoff_write_global_symbol may need. */
- max_sym_count = 4;
+ max_sym_count = 6;
for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
{
size_t sz;
/* Now that we have written out all the global symbols, we know the
symbol indices to use for relocs against them, and we can finally
write out the relocs. */
- external_relocs = (bfd_byte *) malloc (max_output_reloc_count * relsz);
+ external_relocs = (bfd_byte *) bfd_malloc (max_output_reloc_count * relsz);
if (external_relocs == NULL && max_output_reloc_count != 0)
- {
- bfd_set_error (bfd_error_no_memory);
- goto error_return;
- }
+ goto error_return;
for (o = abfd->sections; o != NULL; o = o->next)
{
struct xcoff_toc_rel_hash *toc_rel_hash;
bfd_byte *erel;
+ /* A stripped file has no relocs. */
+ if (info->strip == strip_all)
+ {
+ o->reloc_count = 0;
+ continue;
+ }
+
if (o->reloc_count == 0)
continue;
else
{
bfd_vma tocval, tocend;
+ bfd *inp;
tocval = ((*csectpp)->output_section->vma
+ (*csectpp)->output_offset
+ isym.n_value
- (*csectpp)->vma);
+
/* We want to find out if tocval is a good value to use
as the TOC anchor--that is, whether we can access all
of the TOC using a 16 bit offset from tocval. This
test assumes that the TOC comes at the end of the
output section, as it does in the default linker
script. */
-
tocend = ((*csectpp)->output_section->vma
+ (*csectpp)->output_section->_raw_size);
+ for (inp = finfo->info->input_bfds;
+ inp != NULL;
+ inp = inp->link_next)
+ {
+ asection *o;
+
+ for (o = inp->sections; o != NULL; o = o->next)
+ if (strcmp (o->name, ".tocbss") == 0)
+ {
+ bfd_vma new_toc_end;
+ new_toc_end = (o->output_section->vma
+ + o->output_offset
+ + o->_cooked_size);
+ if (new_toc_end > tocend)
+ tocend = new_toc_end;
+ }
+
+ }
if (tocval + 0x10000 < tocend)
{
(*_bfd_error_handler)
- ("TOC overflow: 0x%lx > 0x10000; try -mminimal-toc when compiling",
+ (_("TOC overflow: 0x%lx > 0x10000; try -mminimal-toc when compiling"),
(unsigned long) (tocend - tocval));
bfd_set_error (bfd_error_file_too_big);
return false;
&& (isym.n_sclass != C_EXT
&& (isym.n_sclass != C_HIDEXT
|| smtyp != XTY_SD))
- && strncmp (name, finfo->info->lprefix,
- finfo->info->lprefix_len) == 0))
+ && bfd_is_local_label_name (input_bfd, name)))
skip = true;
}
{
struct xcoff_link_hash_entry *h = NULL;
struct internal_ldrel ldrel;
+ boolean quiet;
*rel_hash = NULL;
r_symndx = irel->r_symndx;
- if (r_symndx != -1)
+ if (r_symndx == -1)
+ h = NULL;
+ else
+ h = obj_xcoff_sym_hashes (input_bfd)[r_symndx];
+
+ if (r_symndx != -1 && finfo->info->strip != strip_all)
{
- h = obj_xcoff_sym_hashes (input_bfd)[r_symndx];
if (h != NULL
&& h->smclas != XMC_TD
&& (irel->r_type == R_TOC
}
}
+ quiet = false;
switch (irel->r_type)
{
default:
else
{
(*_bfd_error_handler)
- ("%s: loader reloc in unrecognized section `%s'",
+ (_("%s: loader reloc in unrecognized section `%s'"),
bfd_get_filename (input_bfd),
sec->name);
bfd_set_error (bfd_error_nonrepresentable_section);
}
else
{
- if (h->ldindx < 0)
+ if (! finfo->info->relocateable
+ && (h->flags & XCOFF_DEF_DYNAMIC) == 0
+ && (h->flags & XCOFF_IMPORT) == 0)
+ {
+ /* We already called the undefined_symbol
+ callback for this relocation, in
+ _bfd_ppc_xcoff_relocate_section. Don't
+ issue any more warnings. */
+ quiet = true;
+ }
+ if (h->ldindx < 0 && ! quiet)
{
(*_bfd_error_handler)
- ("%s: `%s' in loader reloc but not loader sym",
+ (_("%s: `%s' in loader reloc but not loader sym"),
bfd_get_filename (input_bfd),
h->root.root.string);
bfd_set_error (bfd_error_bad_value);
ldrel.l_rtype = (irel->r_size << 8) | irel->r_type;
ldrel.l_rsecnm = o->output_section->target_index;
if (xcoff_hash_table (finfo->info)->textro
- && strcmp (o->output_section->name, ".text") == 0)
+ && strcmp (o->output_section->name, ".text") == 0
+ && ! quiet)
{
(*_bfd_error_handler)
- ("%s: loader reloc in read-only section %s",
+ (_("%s: loader reloc in read-only section %s"),
bfd_get_filename (input_bfd),
bfd_get_section_name (finfo->output_bfd,
o->output_section));
union internal_auxent aux;
output_bfd = finfo->output_bfd;
+ outsym = finfo->outsyms;
/* If this symbol was garbage collected, just skip it. */
if (xcoff_hash_table (finfo->info)->gc
int oindx;
struct internal_reloc *irel;
struct internal_ldrel ldrel;
+ struct internal_syment irsym;
+ union internal_auxent iraux;
tocsec = h->toc_section;
osec = tocsec->output_section;
ldrel.l_rsecnm = oindx;
xcoff_swap_ldrel_out (output_bfd, &ldrel, finfo->ldrel);
++finfo->ldrel;
+
+ /* We need to emit a symbol to define a csect which holds the
+ reloc. */
+ if (finfo->info->strip != strip_all)
+ {
+ if (strlen (h->root.root.string) <= SYMNMLEN)
+ strncpy (irsym._n._n_name, h->root.root.string, SYMNMLEN);
+ else
+ {
+ boolean hash;
+ bfd_size_type indx;
+
+ hash = true;
+ if ((output_bfd->flags & BFD_TRADITIONAL_FORMAT) != 0)
+ hash = false;
+ indx = _bfd_stringtab_add (finfo->strtab, h->root.root.string,
+ hash, false);
+ if (indx == (bfd_size_type) -1)
+ return false;
+ irsym._n._n_n._n_zeroes = 0;
+ irsym._n._n_n._n_offset = STRING_SIZE_SIZE + indx;
+ }
+
+ irsym.n_value = irel->r_vaddr;
+ irsym.n_scnum = osec->target_index;
+ irsym.n_sclass = C_HIDEXT;
+ irsym.n_type = T_NULL;
+ irsym.n_numaux = 1;
+
+ bfd_coff_swap_sym_out (output_bfd, (PTR) &irsym, (PTR) outsym);
+ outsym += bfd_coff_symesz (output_bfd);
+
+ memset (&iraux, 0, sizeof iraux);
+ iraux.x_csect.x_smtyp = XTY_SD;
+ iraux.x_csect.x_scnlen.l = 4;
+ iraux.x_csect.x_smclas = XMC_TC;
+
+ bfd_coff_swap_aux_out (output_bfd, (PTR) &iraux, T_NULL, C_HIDEXT,
+ 0, 1, (PTR) outsym);
+ outsym += bfd_coff_auxesz (output_bfd);
+
+ if (h->indx >= 0)
+ {
+ /* We aren't going to write out the symbols below, so we
+ need to write them out now. */
+ if (bfd_seek (output_bfd,
+ (obj_sym_filepos (output_bfd)
+ + (obj_raw_syment_count (output_bfd)
+ * bfd_coff_symesz (output_bfd))),
+ SEEK_SET) != 0
+ || (bfd_write (finfo->outsyms, outsym - finfo->outsyms, 1,
+ output_bfd)
+ != (bfd_size_type) (outsym - finfo->outsyms)))
+ return false;
+ obj_raw_syment_count (output_bfd) +=
+ (outsym - finfo->outsyms) / bfd_coff_symesz (output_bfd);
+
+ outsym = finfo->outsyms;
+ }
+ }
}
/* If this symbol is a specially defined function descriptor, write
else
{
(*_bfd_error_handler)
- ("%s: loader reloc in unrecognized section `%s'",
+ (_("%s: loader reloc in unrecognized section `%s'"),
bfd_get_filename (output_bfd),
esec->output_section->name);
bfd_set_error (bfd_error_nonrepresentable_section);
else
{
(*_bfd_error_handler)
- ("%s: loader reloc in unrecognized section `%s'",
+ (_("%s: loader reloc in unrecognized section `%s'"),
bfd_get_filename (output_bfd),
tsec->output_section->name);
bfd_set_error (bfd_error_nonrepresentable_section);
++finfo->ldrel;
}
- if (h->indx >= 0)
- return true;
+ if (h->indx >= 0 || finfo->info->strip == strip_all)
+ {
+ BFD_ASSERT (outsym == finfo->outsyms);
+ return true;
+ }
if (h->indx != -2
&& (finfo->info->strip == strip_all
&& (bfd_hash_lookup (finfo->info->keep_hash,
h->root.root.string, false, false)
== NULL))))
- return true;
+ {
+ BFD_ASSERT (outsym == finfo->outsyms);
+ return true;
+ }
if (h->indx != -2
&& (h->flags & (XCOFF_REF_REGULAR | XCOFF_DEF_REGULAR)) == 0)
- return true;
-
- outsym = finfo->outsyms;
+ {
+ BFD_ASSERT (outsym == finfo->outsyms);
+ return true;
+ }
memset (&aux, 0, sizeof aux);
isym.n_sclass = C_EXT;
aux.x_csect.x_smtyp = XTY_ER;
}
+ else if ((h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ && h->smclas == XMC_XO)
+ {
+ BFD_ASSERT (bfd_is_abs_section (h->root.u.def.section));
+ isym.n_value = h->root.u.def.value;
+ isym.n_scnum = N_UNDEF;
+ isym.n_sclass = C_EXT;
+ aux.x_csect.x_smtyp = XTY_ER;
+ }
else if (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
{
(PTR) outsym);
outsym += bfd_coff_auxesz (output_bfd);
- if (h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak)
+ if ((h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ && h->smclas != XMC_XO)
{
/* We just output an SD symbol. Now output an LD symbol. */
else
{
(*_bfd_error_handler)
- ("%s: loader reloc in unrecognized section `%s'",
+ (_("%s: loader reloc in unrecognized section `%s'"),
bfd_get_filename (output_bfd), secname);
bfd_set_error (bfd_error_nonrepresentable_section);
return false;
if (h->ldindx < 0)
{
(*_bfd_error_handler)
- ("%s: `%s' in loader reloc but not loader sym",
+ (_("%s: `%s' in loader reloc but not loader sym"),
bfd_get_filename (output_bfd),
h->root.root.string);
bfd_set_error (bfd_error_bad_value);
addend = 0;
}
else
- {
+ {
h = obj_xcoff_sym_hashes (input_bfd)[symndx];
sym = syms + symndx;
addend = - sym->n_value;
{
if (! ((*info->callbacks->undefined_symbol)
(info, h->root.root.string, input_bfd, input_section,
- rel->r_vaddr - input_section->vma)))
+ rel->r_vaddr - input_section->vma, true)))
return false;
+
+ /* Don't try to process the reloc. It can't help, and
+ it may generate another error. */
+ continue;
}
}
not defined by the PowerOpen ABI. */
default:
(*_bfd_error_handler)
- ("%s: unsupported relocation type 0x%02x",
+ (_("%s: unsupported relocation type 0x%02x"),
bfd_get_filename (input_bfd), (unsigned int) rel->r_type);
bfd_set_error (bfd_error_bad_value);
return false;
if (h->toc_section == NULL)
{
(*_bfd_error_handler)
- ("%s: TOC reloc at 0x%x to symbol `%s' with no TOC entry",
+ (_("%s: TOC reloc at 0x%x to symbol `%s' with no TOC entry"),
bfd_get_filename (input_bfd), rel->r_vaddr,
h->root.root.string);
bfd_set_error (bfd_error_bad_value);
|| strcmp (h->root.root.string, "._ptrgl") == 0)
{
if (next == 0x4def7b82 /* cror 15,15,15 */
- || next == 0x4ffffb82) /* cror 31,31,31 */
+ || next == 0x4ffffb82 /* cror 31,31,31 */
+ || next == 0x60000000) /* ori r0,r0,0 */
bfd_put_32 (input_bfd, 0x80410014, pnext); /* lwz r1,20(r1) */
}
else
{
if (next == 0x80410014) /* lwz r1,20(r1) */
- bfd_put_32 (input_bfd, 0x4ffffb82, pnext); /* cror 31,31,31 */
+ bfd_put_32 (input_bfd, 0x60000000, pnext); /* ori r0,r0,0 */
}
}