This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
xcoff64 bfd-xcofflink.c.patch
- To: "binutils" <binutils at sources dot redhat dot com>
- Subject: xcoff64 bfd-xcofflink.c.patch
- From: "Tom Rix" <trix at redhat dot com>
- Date: Mon, 29 Jan 2001 13:40:03 -0600
xcofflink.c :
Many changes for xcoff64 support
Move common structures to include/coff/xcoff.h
Move specific structure to backends coff-rs6000.c and coff64-rs6000.c
Use new backend functions, defined in libxcoff.h, to isolate 32/64
dependencies.
(bfd_xcoff_size_dynamic_sections) : special __rtinit symbol for
aix4.2+ -binitfini.
(xcoff_build_ldsyms) : handle special __rtinit symbol.
----------------------------------------------------------------------------
-
diff -rcp sources-original/src/bfd/xcofflink.c sources/src/bfd/xcofflink.c
*** sources-original/src/bfd/xcofflink.c Sat Jan 20 00:28:28 2001
--- sources/src/bfd/xcofflink.c Mon Jan 29 11:48:33 2001
*************** Foundation, Inc., 59 Temple Place - Suit
*** 23,208 ****
#include "bfdlink.h"
#include "libbfd.h"
#include "coff/internal.h"
#include "libcoff.h"
/* This file holds the XCOFF linker code. */
#define STRING_SIZE_SIZE (4)
- /* 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))
-
- /* XCOFF relocation types. These probably belong in a header file
- somewhere. The relocations are described in the function
- _bfd_ppc_xcoff_relocate_section in this file. */
-
- #define R_POS (0x00)
- #define R_NEG (0x01)
- #define R_REL (0x02)
- #define R_TOC (0x03)
- #define R_RTB (0x04)
- #define R_GL (0x05)
- #define R_TCL (0x06)
- #define R_BA (0x08)
- #define R_BR (0x0a)
- #define R_RL (0x0c)
- #define R_RLA (0x0d)
- #define R_REF (0x0f)
- #define R_TRL (0x12)
- #define R_TRLA (0x13)
- #define R_RRTBI (0x14)
- #define R_RRTBA (0x15)
- #define R_CAI (0x16)
- #define R_CREL (0x17)
- #define R_RBA (0x18)
- #define R_RBAC (0x19)
- #define R_RBR (0x1a)
- #define R_RBRC (0x1b)
-
- /* The first word of global linkage code. This must be modified by
- filling in the correct TOC offset. */
-
- #define XCOFF_GLINK_FIRST (0x81820000) /* lwz r12,0(r2) */
-
- /* The remaining words of global linkage code. */
-
- static unsigned long xcoff_glink_code[] = {
- 0x90410014, /* stw r2,20(r1) */
- 0x800c0000, /* lwz r0,0(r12) */
- 0x804c0004, /* lwz r2,4(r12) */
- 0x7c0903a6, /* mtctr r0 */
- 0x4e800420, /* bctr */
- 0x0, /* start of traceback table */
- 0x000c8000, /* traceback table */
- 0x0 /* traceback table */
- };
-
- #define XCOFF_GLINK_SIZE \
- (((sizeof xcoff_glink_code / sizeof xcoff_glink_code[0]) * 4) + 4)
-
/* We reuse the SEC_ROM flag as a mark flag for garbage collection.
This flag will only be used on input sections. */
#define SEC_MARK (SEC_ROM)
- /* The ldhdr structure. This appears at the start of the .loader
- section. */
-
- struct internal_ldhdr {
- /* The version number: currently always 1. */
- unsigned long l_version;
- /* The number of symbol table entries. */
- bfd_size_type l_nsyms;
- /* The number of relocation table entries. */
- bfd_size_type l_nreloc;
- /* The length of the import file string table. */
- bfd_size_type l_istlen;
- /* The number of import files. */
- bfd_size_type l_nimpid;
- /* The offset from the start of the .loader section to the first
- entry in the import file table. */
- bfd_size_type l_impoff;
- /* The length of the string table. */
- bfd_size_type l_stlen;
- /* The offset from the start of the .loader section to the first
- entry in the string table. */
- bfd_size_type l_stoff;
- };
-
- struct external_ldhdr {
- bfd_byte l_version[4];
- bfd_byte l_nsyms[4];
- bfd_byte l_nreloc[4];
- bfd_byte l_istlen[4];
- bfd_byte l_nimpid[4];
- bfd_byte l_impoff[4];
- bfd_byte l_stlen[4];
- bfd_byte l_stoff[4];
- };
-
- #define LDHDRSZ (8 * 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;
- /* The symbol value. */
- bfd_vma l_value;
- /* The symbol section number. */
- short l_scnum;
- /* The symbol type and flags. */
- char l_smtype;
- /* The symbol storage class. */
- char l_smclas;
- /* The import file ID. */
- bfd_size_type l_ifile;
- /* Offset to the parameter type check string. */
- 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;
- bfd_byte l_value[4];
- bfd_byte l_scnum[2];
- bfd_byte l_smtype[1];
- bfd_byte l_smclas[1];
- bfd_byte l_ifile[4];
- bfd_byte l_parm[4];
- };
-
- #define LDSYMSZ (8 + 3 * 4 + 2 + 2)
-
- /* These flags are for the l_smtype field (the lower three bits are an
- XTY_* value). */
-
- /* Imported symbol. */
- #define L_IMPORT (0x40)
- /* Entry point. */
- #define L_ENTRY (0x20)
- /* Exported symbol. */
- #define L_EXPORT (0x10)
-
- /* The ldrel structure. This is used to represent a reloc in the
- .loader section. */
-
- struct internal_ldrel {
- /* The reloc address. */
- bfd_vma l_vaddr;
- /* The symbol table index in the .loader section symbol table. */
- bfd_size_type l_symndx;
- /* The relocation type and size. */
- short l_rtype;
- /* The section number this relocation applies to. */
- short l_rsecnm;
- };
-
- struct external_ldrel {
- bfd_byte l_vaddr[4];
- bfd_byte l_symndx[4];
- bfd_byte l_rtype[2];
- bfd_byte l_rsecnm[2];
- };
-
- #define LDRELSZ (2 * 4 + 2 * 2)
-
/* The list of import files. */
struct xcoff_import_file {
--- 23,41 ----
#include "bfdlink.h"
#include "libbfd.h"
#include "coff/internal.h"
+ #include "coff/xcoff.h"
#include "libcoff.h"
+ #include "libxcoff.h"
/* This file holds the XCOFF linker code. */
#define STRING_SIZE_SIZE (4)
/* We reuse the SEC_ROM flag as a mark flag for garbage collection.
This flag will only be used on input sections. */
#define SEC_MARK (SEC_ROM)
/* The list of import files. */
struct xcoff_import_file {
*************** struct xcoff_import_file {
*** 216,349 ****
const char *member;
};
- /* An entry in the XCOFF linker hash table. */
-
- struct xcoff_link_hash_entry {
- struct bfd_link_hash_entry root;
-
- /* Symbol index in output file. Set to -1 initially. Set to -2 if
- there is a reloc against this symbol. */
- long indx;
-
- /* If we have created a TOC entry for this symbol, this is the .tc
- 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;
-
- /* If this symbol is a function entry point which is called, this
- field holds a pointer to the function descriptor. If this symbol
- is a function descriptor, this field holds a pointer to the
- function entry point. */
- struct xcoff_link_hash_entry *descriptor;
-
- /* The .loader symbol table entry, if there is one. */
- struct internal_ldsym *ldsym;
-
- /* 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. */
- unsigned short flags;
- /* Symbol is referenced by a regular object. */
- #define XCOFF_REF_REGULAR (01)
- /* Symbol is defined by a regular object. */
- #define XCOFF_DEF_REGULAR (02)
- /* Symbol is defined by a dynamic object. */
- #define XCOFF_DEF_DYNAMIC (04)
- /* Symbol is used in a reloc being copied into the .loader section. */
- #define XCOFF_LDREL (010)
- /* Symbol is the entry point. */
- #define XCOFF_ENTRY (020)
- /* Symbol is called; this is, it appears in a R_BR reloc. */
- #define XCOFF_CALLED (040)
- /* Symbol needs the TOC entry filled in. */
- #define XCOFF_SET_TOC (0100)
- /* Symbol is explicitly imported. */
- #define XCOFF_IMPORT (0200)
- /* Symbol is explicitly exported. */
- #define XCOFF_EXPORT (0400)
- /* Symbol has been processed by xcoff_build_ldsyms. */
- #define XCOFF_BUILT_LDSYM (01000)
- /* Symbol is mentioned by a section which was not garbage collected. */
- #define XCOFF_MARK (02000)
- /* Symbol size is recorded in size_list list from hash table. */
- #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 bfd_link_hash_table root;
-
- /* The .debug string hash table. We need to compute this while
- reading the input files, so that we know how large the .debug
- section will be before we assign section positions. */
- struct bfd_strtab_hash *debug_strtab;
-
- /* The .debug section we will use for the final output. */
- asection *debug_section;
-
- /* The .loader section we will use for the final output. */
- asection *loader_section;
-
- /* A count of non TOC relative relocs which will need to be
- allocated in the .loader section. */
- size_t ldrel_count;
-
- /* The .loader section header. */
- struct internal_ldhdr ldhdr;
-
- /* The .gl section we use to hold global linkage code. */
- asection *linkage_section;
-
- /* The .tc section we use to hold toc entries we build for global
- linkage code. */
- asection *toc_section;
-
- /* The .ds section we use to hold function descriptors which we
- create for exported symbols. */
- asection *descriptor_section;
-
- /* The list of import files. */
- struct xcoff_import_file *imports;
-
- /* Required alignment of sections within the output file. */
- unsigned long file_align;
-
- /* Whether the .text section must be read-only. */
- boolean textro;
-
- /* Whether garbage collection was done. */
- 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;
-
- /* 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. */
--- 49,54 ----
*************** struct xcoff_final_link_info {
*** 383,391 ****
/* Symbol index of TOC symbol. */
long toc_symindx;
/* Start of .loader symbols. */
! struct external_ldsym *ldsym;
/* Next .loader reloc to swap out. */
! struct external_ldrel *ldrel;
/* File position of start of line numbers. */
file_ptr line_filepos;
/* Buffer large enough to hold swapped symbols of any input file. */
--- 88,96 ----
/* Symbol index of TOC symbol. */
long toc_symindx;
/* Start of .loader symbols. */
! bfd_byte *ldsym;
/* Next .loader reloc to swap out. */
! bfd_byte *ldrel;
/* File position of start of line numbers. */
file_ptr line_filepos;
/* Buffer large enough to hold swapped symbols of any input file. */
*************** struct xcoff_final_link_info {
*** 404,421 ****
bfd_byte *external_relocs;
};
- static void xcoff_swap_ldhdr_in
- PARAMS ((bfd *, const struct external_ldhdr *, struct internal_ldhdr
*));
- static void xcoff_swap_ldhdr_out
- PARAMS ((bfd *, const struct internal_ldhdr *, struct external_ldhdr
*));
- static void xcoff_swap_ldsym_in
- PARAMS ((bfd *, const struct external_ldsym *, struct internal_ldsym
*));
- static void xcoff_swap_ldsym_out
- PARAMS ((bfd *, const struct internal_ldsym *, struct external_ldsym
*));
- static void xcoff_swap_ldrel_in
- PARAMS ((bfd *, const struct external_ldrel *, struct internal_ldrel
*));
- static void xcoff_swap_ldrel_out
- 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 *));
--- 109,114 ----
*************** static boolean xcoff_reloc_link_order
*** 450,570 ****
struct bfd_link_order *));
static int xcoff_sort_relocs PARAMS ((const PTR, const PTR));
- /* Routines to swap information in the XCOFF .loader section. If we
- ever need to write an XCOFF loader, this stuff will need to be
- moved to another file shared by the linker (which XCOFF calls the
- ``binder'') and the loader. */
-
- /* Swap in the ldhdr structure. */
-
- static void
- xcoff_swap_ldhdr_in (abfd, src, dst)
- bfd *abfd;
- const struct external_ldhdr *src;
- struct internal_ldhdr *dst;
- {
- dst->l_version = bfd_get_32 (abfd, src->l_version);
- dst->l_nsyms = bfd_get_32 (abfd, src->l_nsyms);
- dst->l_nreloc = bfd_get_32 (abfd, src->l_nreloc);
- dst->l_istlen = bfd_get_32 (abfd, src->l_istlen);
- dst->l_nimpid = bfd_get_32 (abfd, src->l_nimpid);
- dst->l_impoff = bfd_get_32 (abfd, src->l_impoff);
- dst->l_stlen = bfd_get_32 (abfd, src->l_stlen);
- dst->l_stoff = bfd_get_32 (abfd, src->l_stoff);
- }
-
- /* Swap out the ldhdr structure. */
-
- static void
- xcoff_swap_ldhdr_out (abfd, src, dst)
- bfd *abfd;
- const struct internal_ldhdr *src;
- struct external_ldhdr *dst;
- {
- bfd_put_32 (abfd, src->l_version, dst->l_version);
- bfd_put_32 (abfd, src->l_nsyms, dst->l_nsyms);
- bfd_put_32 (abfd, src->l_nreloc, dst->l_nreloc);
- bfd_put_32 (abfd, src->l_istlen, dst->l_istlen);
- bfd_put_32 (abfd, src->l_nimpid, dst->l_nimpid);
- bfd_put_32 (abfd, src->l_impoff, dst->l_impoff);
- bfd_put_32 (abfd, src->l_stlen, dst->l_stlen);
- bfd_put_32 (abfd, src->l_stoff, dst->l_stoff);
- }
-
- /* Swap in the ldsym structure. */
-
- static void
- xcoff_swap_ldsym_in (abfd, src, dst)
- bfd *abfd;
- const struct external_ldsym *src;
- struct internal_ldsym *dst;
- {
- if (bfd_get_32 (abfd, src->_l._l_l._l_zeroes) != 0)
- memcpy (dst->_l._l_name, src->_l._l_name, SYMNMLEN);
- else
- {
- dst->_l._l_l._l_zeroes = 0;
- dst->_l._l_l._l_offset = bfd_get_32 (abfd, src->_l._l_l._l_offset);
- }
- dst->l_value = bfd_get_32 (abfd, src->l_value);
- dst->l_scnum = bfd_get_16 (abfd, src->l_scnum);
- dst->l_smtype = bfd_get_8 (abfd, src->l_smtype);
- dst->l_smclas = bfd_get_8 (abfd, src->l_smclas);
- dst->l_ifile = bfd_get_32 (abfd, src->l_ifile);
- dst->l_parm = bfd_get_32 (abfd, src->l_parm);
- }
-
- /* Swap out the ldsym structure. */
-
- static void
- xcoff_swap_ldsym_out (abfd, src, dst)
- bfd *abfd;
- const struct internal_ldsym *src;
- struct external_ldsym *dst;
- {
- if (src->_l._l_l._l_zeroes != 0)
- memcpy (dst->_l._l_name, src->_l._l_name, SYMNMLEN);
- else
- {
- bfd_put_32 (abfd, 0, dst->_l._l_l._l_zeroes);
- bfd_put_32 (abfd, src->_l._l_l._l_offset, dst->_l._l_l._l_offset);
- }
- bfd_put_32 (abfd, src->l_value, dst->l_value);
- bfd_put_16 (abfd, src->l_scnum, dst->l_scnum);
- bfd_put_8 (abfd, src->l_smtype, dst->l_smtype);
- bfd_put_8 (abfd, src->l_smclas, dst->l_smclas);
- bfd_put_32 (abfd, src->l_ifile, dst->l_ifile);
- bfd_put_32 (abfd, src->l_parm, dst->l_parm);
- }
-
- /* Swap in the ldrel structure. */
-
- static void
- xcoff_swap_ldrel_in (abfd, src, dst)
- bfd *abfd;
- const struct external_ldrel *src;
- struct internal_ldrel *dst;
- {
- dst->l_vaddr = bfd_get_32 (abfd, src->l_vaddr);
- dst->l_symndx = bfd_get_32 (abfd, src->l_symndx);
- dst->l_rtype = bfd_get_16 (abfd, src->l_rtype);
- dst->l_rsecnm = bfd_get_16 (abfd, src->l_rsecnm);
- }
-
- /* Swap out the ldrel structure. */
- static void
- xcoff_swap_ldrel_out (abfd, src, dst)
- bfd *abfd;
- const struct internal_ldrel *src;
- struct external_ldrel *dst;
- {
- bfd_put_32 (abfd, src->l_vaddr, dst->l_vaddr);
- bfd_put_32 (abfd, src->l_symndx, dst->l_symndx);
- bfd_put_16 (abfd, src->l_rtype, dst->l_rtype);
- bfd_put_16 (abfd, src->l_rsecnm, dst->l_rsecnm);
- }
-
/* Routines to read XCOFF dynamic information. This don't really
belong here, but we already have the ldsym manipulation routines
here. */
--- 143,149 ----
*************** _bfd_xcoff_get_dynamic_symtab_upper_boun
*** 627,633 ****
return -1;
contents = coff_section_data (abfd, lsec)->contents;
! xcoff_swap_ldhdr_in (abfd, (struct external_ldhdr *) contents, &ldhdr);
return (ldhdr.l_nsyms + 1) * sizeof (asymbol *);
}
--- 206,212 ----
return -1;
contents = coff_section_data (abfd, lsec)->contents;
! bfd_xcoff_swap_ldhdr_in (abfd, (PTR) contents, &ldhdr);
return (ldhdr.l_nsyms + 1) * sizeof (asymbol *);
}
*************** _bfd_xcoff_canonicalize_dynamic_symtab (
*** 643,649 ****
bfd_byte *contents;
struct internal_ldhdr ldhdr;
const char *strings;
! struct external_ldsym *elsym, *elsymend;
coff_symbol_type *symbuf;
if ((abfd->flags & DYNAMIC) == 0)
--- 222,228 ----
bfd_byte *contents;
struct internal_ldhdr ldhdr;
const char *strings;
! bfd_byte *elsym, *elsymend;
coff_symbol_type *symbuf;
if ((abfd->flags & DYNAMIC) == 0)
*************** _bfd_xcoff_canonicalize_dynamic_symtab (
*** 665,671 ****
coff_section_data (abfd, lsec)->keep_contents = true;
! xcoff_swap_ldhdr_in (abfd, (struct external_ldhdr *) contents, &ldhdr);
strings = (char *) contents + ldhdr.l_stoff;
--- 244,250 ----
coff_section_data (abfd, lsec)->keep_contents = true;
! bfd_xcoff_swap_ldhdr_in (abfd, contents, &ldhdr);
strings = (char *) contents + ldhdr.l_stoff;
*************** _bfd_xcoff_canonicalize_dynamic_symtab (
*** 674,686 ****
if (symbuf == NULL)
return -1;
! elsym = (struct external_ldsym *) (contents + LDHDRSZ);
! elsymend = elsym + ldhdr.l_nsyms;
! for (; elsym < elsymend; elsym++, symbuf++, psyms++)
{
struct internal_ldsym ldsym;
! xcoff_swap_ldsym_in (abfd, elsym, &ldsym);
symbuf->symbol.the_bfd = abfd;
--- 253,266 ----
if (symbuf == NULL)
return -1;
! elsym = contents + bfd_xcoff_loader_symbol_offset(abfd, &ldhdr);
!
! elsymend = elsym + ldhdr.l_nsyms * bfd_xcoff_ldsymsz(abfd);
! for (; elsym < elsymend; elsym += bfd_xcoff_ldsymsz(abfd), symbuf++,
psyms++)
{
struct internal_ldsym ldsym;
! bfd_xcoff_swap_ldsym_in (abfd, elsym, &ldsym);
symbuf->symbol.the_bfd = abfd;
*************** _bfd_xcoff_canonicalize_dynamic_symtab (
*** 688,711 ****
symbuf->symbol.name = strings + ldsym._l._l_l._l_offset;
else
{
! int i;
!
! for (i = 0; i < SYMNMLEN; i++)
! if (ldsym._l._l_name[i] == '\0')
! break;
! if (i < SYMNMLEN)
! symbuf->symbol.name = (char *) elsym->_l._l_name;
! else
! {
! char *c;
! c = bfd_alloc (abfd, SYMNMLEN + 1);
! if (c == NULL)
! return -1;
! memcpy (c, ldsym._l._l_name, SYMNMLEN);
! c[SYMNMLEN] = '\0';
! symbuf->symbol.name = c;
! }
}
if (ldsym.l_smclas == XMC_XO)
--- 268,281 ----
symbuf->symbol.name = strings + ldsym._l._l_l._l_offset;
else
{
! char *c;
! c = bfd_alloc (abfd, SYMNMLEN + 1);
! if (c == NULL)
! return -1;
! memcpy (c, ldsym._l._l_name, SYMNMLEN);
! c[SYMNMLEN] = '\0';
! symbuf->symbol.name = c;
}
if (ldsym.l_smclas == XMC_XO)
*************** _bfd_xcoff_get_dynamic_reloc_upper_bound
*** 757,784 ****
return -1;
contents = coff_section_data (abfd, lsec)->contents;
! xcoff_swap_ldhdr_in (abfd, (struct external_ldhdr *) contents, &ldhdr);
return (ldhdr.l_nreloc + 1) * sizeof (arelent *);
}
- /* 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 */
- complain_overflow_bitfield, /* complain_on_overflow */
- 0, /* special_function */
- "R_POS", /* name */
- true, /* partial_inplace */
- 0xffffffff, /* src_mask */
- 0xffffffff, /* dst_mask */
- false); /* pcrel_offset */
-
/* Get the dynamic relocs. */
long
--- 327,337 ----
return -1;
contents = coff_section_data (abfd, lsec)->contents;
! bfd_xcoff_swap_ldhdr_in (abfd, (struct external_ldhdr *) contents,
&ldhdr);
return (ldhdr.l_nreloc + 1) * sizeof (arelent *);
}
/* Get the dynamic relocs. */
long
*************** _bfd_xcoff_canonicalize_dynamic_reloc (a
*** 791,797 ****
bfd_byte *contents;
struct internal_ldhdr ldhdr;
arelent *relbuf;
! struct external_ldrel *elrel, *elrelend;
if ((abfd->flags & DYNAMIC) == 0)
{
--- 344,350 ----
bfd_byte *contents;
struct internal_ldhdr ldhdr;
arelent *relbuf;
! bfd_byte *elrel, *elrelend;
if ((abfd->flags & DYNAMIC) == 0)
{
*************** _bfd_xcoff_canonicalize_dynamic_reloc (a
*** 810,829 ****
return -1;
contents = coff_section_data (abfd, lsec)->contents;
! xcoff_swap_ldhdr_in (abfd, (struct external_ldhdr *) contents, &ldhdr);
relbuf = (arelent *) bfd_alloc (abfd, ldhdr.l_nreloc * sizeof
(arelent));
if (relbuf == NULL)
return -1;
! elrel = ((struct external_ldrel *)
! (contents + LDHDRSZ + ldhdr.l_nsyms * LDSYMSZ));
! elrelend = elrel + ldhdr.l_nreloc;
! for (; elrel < elrelend; elrel++, relbuf++, prelocs++)
{
struct internal_ldrel ldrel;
! xcoff_swap_ldrel_in (abfd, elrel, &ldrel);
if (ldrel.l_symndx >= 3)
relbuf->sym_ptr_ptr = syms + (ldrel.l_symndx - 3);
--- 363,383 ----
return -1;
contents = coff_section_data (abfd, lsec)->contents;
! bfd_xcoff_swap_ldhdr_in (abfd, contents, &ldhdr);
relbuf = (arelent *) bfd_alloc (abfd, ldhdr.l_nreloc * sizeof
(arelent));
if (relbuf == NULL)
return -1;
! elrel = contents + bfd_xcoff_loader_reloc_offset(abfd, &ldhdr);
!
! elrelend = elrel + ldhdr.l_nreloc * bfd_xcoff_ldrelsz(abfd);
! for (; elrel < elrelend; elrel += bfd_xcoff_ldrelsz(abfd), relbuf++,
! prelocs++)
{
struct internal_ldrel ldrel;
! bfd_xcoff_swap_ldrel_in (abfd, elrel, &ldrel);
if (ldrel.l_symndx >= 3)
relbuf->sym_ptr_ptr = syms + (ldrel.l_symndx - 3);
*************** _bfd_xcoff_canonicalize_dynamic_reloc (a
*** 864,870 ****
/* Most dynamic relocs have the same type. FIXME: This is only
correct if ldrel.l_rtype == 0. In other cases, we should use
a different howto. */
! relbuf->howto = &xcoff_dynamic_reloc;
/* FIXME: We have no way to record the l_rsecnm field. */
--- 418,424 ----
/* Most dynamic relocs have the same type. FIXME: This is only
correct if ldrel.l_rtype == 0. In other cases, we should use
a different howto. */
! relbuf->howto = bfd_xcoff_dynamic_reloc_howto(abfd);
/* FIXME: We have no way to record the l_rsecnm field. */
*************** _bfd_xcoff_bfd_link_hash_table_create (a
*** 954,978 ****
return &ret->root;
}
- /* Look up an entry in an XCOFF link hash table. */
-
- #define xcoff_link_hash_lookup(table, string, create, copy, follow) \
- ((struct xcoff_link_hash_entry *) \
- bfd_link_hash_lookup (&(table)->root, (string), (create), (copy),\
- (follow)))
-
- /* Traverse an XCOFF link hash table. */
-
- #define xcoff_link_hash_traverse(table, func, info) \
- (bfd_link_hash_traverse \
- (&(table)->root, \
- (boolean (*) PARAMS ((struct bfd_link_hash_entry *, PTR))) (func), \
- (info)))
-
- /* Get the XCOFF link hash table from the info structure. This is
- just a cast. */
-
- #define xcoff_hash_table(p) ((struct xcoff_link_hash_table *) ((p)->hash))
/* Read internal relocs for an XCOFF csect. This is a wrapper around
_bfd_coff_read_internal_relocs which tries to take advantage of any
--- 508,513 ----
*************** xcoff_link_check_ar_symbols (abfd, info,
*** 1177,1182 ****
--- 712,718 ----
object file. */
name = _bfd_coff_internal_syment_name (abfd, &sym, buf);
+
if (name == NULL)
return false;
h = bfd_link_hash_lookup (info->hash, name, false, false, true);
*************** xcoff_link_check_ar_symbols (abfd, info,
*** 1188,1194 ****
undefined references in shared objects. */
if (h != (struct bfd_link_hash_entry *) NULL
&& h->type == bfd_link_hash_undefined
! && (info->hash->creator != abfd->xvec
|| (((struct xcoff_link_hash_entry *) h)->flags
& XCOFF_DEF_DYNAMIC) == 0))
{
--- 724,730 ----
undefined references in shared objects. */
if (h != (struct bfd_link_hash_entry *) NULL
&& h->type == bfd_link_hash_undefined
! && (info->hash->creator != abfd->xvec
|| (((struct xcoff_link_hash_entry *) h)->flags
& XCOFF_DEF_DYNAMIC) == 0))
{
*************** xcoff_link_check_dynamic_ar_symbols (abf
*** 1217,1226 ****
boolean *pneeded;
{
asection *lsec;
! bfd_byte *buf;
struct internal_ldhdr ldhdr;
const char *strings;
! struct external_ldsym *elsym, *elsymend;
*pneeded = false;
--- 753,762 ----
boolean *pneeded;
{
asection *lsec;
! bfd_byte *contents;
struct internal_ldhdr ldhdr;
const char *strings;
! bfd_byte *elsym, *elsymend;
*pneeded = false;
*************** xcoff_link_check_dynamic_ar_symbols (abf
*** 1233,1254 ****
if (! xcoff_get_section_contents (abfd, lsec))
return false;
! buf = coff_section_data (abfd, lsec)->contents;
! xcoff_swap_ldhdr_in (abfd, (struct external_ldhdr *) buf, &ldhdr);
! strings = (char *) buf + ldhdr.l_stoff;
! elsym = (struct external_ldsym *) (buf + LDHDRSZ);
! elsymend = elsym + ldhdr.l_nsyms;
! for (; elsym < elsymend; elsym++)
{
struct internal_ldsym ldsym;
char nambuf[SYMNMLEN + 1];
const char *name;
struct bfd_link_hash_entry *h;
! xcoff_swap_ldsym_in (abfd, elsym, &ldsym);
/* We are only interested in exported symbols. */
if ((ldsym.l_smtype & L_EXPORT) == 0)
--- 769,791 ----
if (! xcoff_get_section_contents (abfd, lsec))
return false;
! contents = coff_section_data (abfd, lsec)->contents;
!
! bfd_xcoff_swap_ldhdr_in (abfd, contents, &ldhdr);
! strings = (char *) contents + ldhdr.l_stoff;
! elsym = contents + bfd_xcoff_loader_symbol_offset(abfd, &ldhdr);
! elsymend = elsym + ldhdr.l_nsyms * bfd_xcoff_ldsymsz(abfd);
! for (; elsym < elsymend; elsym += bfd_xcoff_ldsymsz(abfd))
{
struct internal_ldsym ldsym;
char nambuf[SYMNMLEN + 1];
const char *name;
struct bfd_link_hash_entry *h;
! bfd_xcoff_swap_ldsym_in (abfd, elsym, &ldsym);
/* We are only interested in exported symbols. */
if ((ldsym.l_smtype & L_EXPORT) == 0)
*************** xcoff_link_check_dynamic_ar_symbols (abf
*** 1282,1288 ****
/* We do not need this shared object. */
! if (buf != NULL && ! coff_section_data (abfd, lsec)->keep_contents)
{
free (coff_section_data (abfd, lsec)->contents);
coff_section_data (abfd, lsec)->contents = NULL;
--- 819,825 ----
/* We do not need this shared object. */
! if (contents != NULL && ! coff_section_data (abfd, lsec)->keep_contents)
{
free (coff_section_data (abfd, lsec)->contents);
coff_section_data (abfd, lsec)->contents = NULL;
*************** xcoff_find_reloc (relocs, count, address
*** 1341,1346 ****
--- 878,977 ----
return min;
}
+
+ /*
+ * xcoff_link_create_extra_sections
+ *
+ * Takes care of creating the .loader, .gl, .ds, .debug and sections
+ */
+ static boolean
+ xcoff_link_create_extra_sections(bfd * abfd, struct bfd_link_info *info) {
+
+ boolean return_value = false;
+
+ if (info->hash->creator == abfd->xvec)
+
+ /* We need to build a .loader section, so we do it here. This
+ won't work if we're producing an XCOFF output file with no
+ XCOFF input files. FIXME. */
+
+ if (xcoff_hash_table (info)->loader_section == NULL) {
+ asection *lsec;
+
+ lsec = bfd_make_section_anyway (abfd, ".loader");
+ if (lsec == NULL) {
+ goto end_return;
+ }
+ xcoff_hash_table (info)->loader_section = lsec;
+ lsec->flags |= SEC_HAS_CONTENTS | SEC_IN_MEMORY;
+ }
+
+ /* Likewise for the linkage section. */
+ if (xcoff_hash_table (info)->linkage_section == NULL) {
+ asection *lsec;
+
+ lsec = bfd_make_section_anyway (abfd, ".gl");
+ if (lsec == NULL) {
+ goto end_return;
+ }
+
+ xcoff_hash_table (info)->linkage_section = lsec;
+ lsec->flags |= (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
+ | SEC_IN_MEMORY);
+ lsec->alignment_power = 2;
+ }
+
+ /* Likewise for the TOC section. */
+ if (xcoff_hash_table (info)->toc_section == NULL) {
+ asection *tsec;
+
+ tsec = bfd_make_section_anyway (abfd, ".tc");
+ if (tsec == NULL) {
+ goto end_return;
+ }
+
+ xcoff_hash_table (info)->toc_section = tsec;
+ tsec->flags |= (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
+ | SEC_IN_MEMORY);
+ tsec->alignment_power = 2;
+ }
+
+ /* Likewise for the descriptor section. */
+ if (xcoff_hash_table (info)->descriptor_section == NULL) {
+ asection *dsec;
+
+ dsec = bfd_make_section_anyway (abfd, ".ds");
+ if (dsec == NULL) {
+ goto end_return;
+ }
+
+ xcoff_hash_table (info)->descriptor_section = dsec;
+ dsec->flags |= (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
+ | SEC_IN_MEMORY);
+ dsec->alignment_power = 2;
+ }
+
+ /* Likewise for the .debug section. */
+ if (xcoff_hash_table (info)->debug_section == NULL
+ && info->strip != strip_all) {
+ asection *dsec;
+
+ dsec = bfd_make_section_anyway (abfd, ".debug");
+ if (dsec == NULL) {
+ goto end_return;
+ }
+ xcoff_hash_table (info)->debug_section = dsec;
+ dsec->flags |= SEC_HAS_CONTENTS | SEC_IN_MEMORY;
+ }
+ }
+
+ return_value = true;
+
+ end_return:
+
+ return return_value;
+ }
+
/* Add all the symbols from an object file to the hash table.
XCOFF is a weird format. A normal XCOFF .o files will have three
*************** xcoff_link_add_symbols (abfd, info)
*** 1380,1468 ****
bfd_size_type symesz;
bfd_byte *esym;
bfd_byte *esym_end;
! struct reloc_info_struct
! {
! struct internal_reloc *relocs;
! asection **csects;
! bfd_byte *linenos;
! } *reloc_info = NULL;
!
keep_syms = obj_coff_keep_syms (abfd);
if ((abfd->flags & DYNAMIC) != 0
! && ! info->static_link)
! {
! if (! xcoff_link_add_dynamic_symbols (abfd, info))
! return false;
}
! if (info->hash->creator == abfd->xvec)
! {
! /* We need to build a .loader section, so we do it here. This
! won't work if we're producing an XCOFF output file with no
! XCOFF input files. FIXME. */
! if (xcoff_hash_table (info)->loader_section == NULL)
! {
! asection *lsec;
!
! lsec = bfd_make_section_anyway (abfd, ".loader");
! if (lsec == NULL)
! goto error_return;
! xcoff_hash_table (info)->loader_section = lsec;
! lsec->flags |= SEC_HAS_CONTENTS | SEC_IN_MEMORY;
! }
! /* Likewise for the linkage section. */
! if (xcoff_hash_table (info)->linkage_section == NULL)
! {
! asection *lsec;
!
! lsec = bfd_make_section_anyway (abfd, ".gl");
! if (lsec == NULL)
! goto error_return;
! xcoff_hash_table (info)->linkage_section = lsec;
! lsec->flags |= (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
! | SEC_IN_MEMORY);
! lsec->alignment_power = 2;
! }
! /* Likewise for the TOC section. */
! if (xcoff_hash_table (info)->toc_section == NULL)
! {
! asection *tsec;
!
! tsec = bfd_make_section_anyway (abfd, ".tc");
! if (tsec == NULL)
! goto error_return;
! xcoff_hash_table (info)->toc_section = tsec;
! tsec->flags |= (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
! | SEC_IN_MEMORY);
! tsec->alignment_power = 2;
! }
! /* Likewise for the descriptor section. */
! if (xcoff_hash_table (info)->descriptor_section == NULL)
! {
! asection *dsec;
!
! dsec = bfd_make_section_anyway (abfd, ".ds");
! if (dsec == NULL)
! goto error_return;
! xcoff_hash_table (info)->descriptor_section = dsec;
! dsec->flags |= (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
! | SEC_IN_MEMORY);
! dsec->alignment_power = 2;
! }
! /* Likewise for the .debug section. */
! if (xcoff_hash_table (info)->debug_section == NULL
! && info->strip != strip_all)
! {
! asection *dsec;
!
! dsec = bfd_make_section_anyway (abfd, ".debug");
! if (dsec == NULL)
! goto error_return;
! xcoff_hash_table (info)->debug_section = dsec;
! dsec->flags |= SEC_HAS_CONTENTS | SEC_IN_MEMORY;
! }
! }
if ((abfd->flags & DYNAMIC) != 0
&& ! info->static_link)
--- 1011,1036 ----
bfd_size_type symesz;
bfd_byte *esym;
bfd_byte *esym_end;
! struct reloc_info_struct
! {
! struct internal_reloc *relocs;
! asection **csects;
! bfd_byte *linenos;
! } *reloc_info = NULL;
!
keep_syms = obj_coff_keep_syms (abfd);
if ((abfd->flags & DYNAMIC) != 0
! && ! info->static_link) {
! if (! xcoff_link_add_dynamic_symbols (abfd, info)) {
! return false;
}
+ }
! /* create the loader, toc, gl, ds and debug sections, if needed */
! if (false == xcoff_link_create_extra_sections(abfd, info)) {
! goto error_return;
! }
if ((abfd->flags & DYNAMIC) != 0
&& ! info->static_link)
*************** xcoff_link_add_symbols (abfd, info)
*** 1480,1486 ****
else
default_copy = true;
! symcount = obj_raw_syment_count (abfd);
/* We keep a list of the linker hash table entries that correspond
to each external symbol. */
--- 1048,1054 ----
else
default_copy = true;
! symcount = obj_raw_syment_count (abfd);
/* We keep a list of the linker hash table entries that correspond
to each external symbol. */
*************** xcoff_link_add_symbols (abfd, info)
*** 1520,1556 ****
/* Read in the relocs and line numbers for each section. */
linesz = bfd_coff_linesz (abfd);
last_real = NULL;
! for (o = abfd->sections; o != NULL; o = o->next)
! {
! last_real = o;
! if ((o->flags & SEC_RELOC) != 0)
! {
! reloc_info[o->target_index].relocs =
! xcoff_read_internal_relocs (abfd, o, true, (bfd_byte *) NULL,
! false, (struct internal_reloc *) NULL);
! reloc_info[o->target_index].csects =
! (asection **) bfd_malloc (o->reloc_count * sizeof (asection *));
! if (reloc_info[o->target_index].csects == NULL)
! goto error_return;
! memset (reloc_info[o->target_index].csects, 0,
! o->reloc_count * sizeof (asection *));
! }
! if ((info->strip == strip_none || info->strip == strip_some)
! && o->lineno_count > 0)
! {
! bfd_byte *linenos;
! linenos = (bfd_byte *) bfd_malloc (o->lineno_count * linesz);
! if (linenos == NULL)
! goto error_return;
! reloc_info[o->target_index].linenos = linenos;
! if (bfd_seek (abfd, o->line_filepos, SEEK_SET) != 0
! || (bfd_read (linenos, linesz, o->lineno_count, abfd)
! != linesz * o->lineno_count))
! goto error_return;
! }
}
/* Don't let the linker relocation routines discard the symbols. */
obj_coff_keep_syms (abfd) = true;
--- 1088,1127 ----
/* Read in the relocs and line numbers for each section. */
linesz = bfd_coff_linesz (abfd);
last_real = NULL;
! for (o = abfd->sections; o != NULL; o = o->next) {
! last_real = o;
! if ((o->flags & SEC_RELOC) != 0) {
! reloc_info[o->target_index].relocs =
! xcoff_read_internal_relocs (abfd, o, true, (bfd_byte *) NULL,
! false, (struct internal_reloc *) NULL);
! reloc_info[o->target_index].csects =
! (asection **) bfd_malloc (o->reloc_count * sizeof (asection *));
! if (reloc_info[o->target_index].csects == NULL)
! goto error_return;
! memset (reloc_info[o->target_index].csects, 0,
! o->reloc_count * sizeof (asection *));
!
! }
!
! if ((info->strip == strip_none || info->strip == strip_some)
! && o->lineno_count > 0) {
!
! bfd_byte *linenos;
!
! linenos = (bfd_byte *) bfd_malloc (o->lineno_count * linesz);
! if (linenos == NULL)
! goto error_return;
! reloc_info[o->target_index].linenos = linenos;
! if (bfd_seek (abfd, o->line_filepos, SEEK_SET) != 0
! || (bfd_read (linenos, linesz, o->lineno_count, abfd)
! != linesz * o->lineno_count))
! goto error_return;
!
}
+ }
+
/* Don't let the linker relocation routines discard the symbols. */
obj_coff_keep_syms (abfd) = true;
*************** xcoff_link_add_symbols (abfd, info)
*** 1563,1610 ****
BFD_ASSERT (symesz == bfd_coff_auxesz (abfd));
esym = (bfd_byte *) obj_coff_external_syms (abfd);
esym_end = esym + symcount * symesz;
- while (esym < esym_end)
- {
- struct internal_syment sym;
- union internal_auxent aux;
- const char *name;
- char buf[SYMNMLEN + 1];
- int smtyp;
- flagword flags;
- asection *section;
- bfd_vma value;
- struct xcoff_link_hash_entry *set_toc;
! bfd_coff_swap_sym_in (abfd, (PTR) esym, (PTR) &sym);
! /* In this pass we are only interested in symbols with csect
! information. */
! if (sym.n_sclass != C_EXT && sym.n_sclass != C_HIDEXT)
! {
! if (sym.n_sclass == C_FILE && csect != NULL)
! {
! xcoff_section_data (abfd, csect)->last_symndx =
! ((esym
! - (bfd_byte *) obj_coff_external_syms (abfd))
! / symesz);
! csect = NULL;
! }
! if (csect != NULL)
! *csect_cache = csect;
! else if (first_csect == NULL || sym.n_sclass == C_FILE)
! *csect_cache = coff_section_from_bfd_index (abfd, sym.n_scnum);
! else
! *csect_cache = NULL;
! esym += (sym.n_numaux + 1) * symesz;
! sym_hash += sym.n_numaux + 1;
! csect_cache += sym.n_numaux + 1;
! continue;
! }
! name = _bfd_coff_internal_syment_name (abfd, &sym, buf);
! if (name == NULL)
! goto error_return;
/* If this symbol has line number information attached to it,
and we're not stripping it, count the number of entries and
--- 1134,1190 ----
BFD_ASSERT (symesz == bfd_coff_auxesz (abfd));
esym = (bfd_byte *) obj_coff_external_syms (abfd);
esym_end = esym + symcount * symesz;
! while (esym < esym_end) {
! struct internal_syment sym;
! union internal_auxent aux;
! const char *name;
! char buf[SYMNMLEN + 1];
! int smtyp;
! flagword flags;
! asection *section;
! bfd_vma value;
! struct xcoff_link_hash_entry *set_toc;
!
! bfd_coff_swap_sym_in (abfd, (PTR) esym, (PTR) &sym);
!
! /* In this pass we are only interested in symbols with csect
! information. */
! if (sym.n_sclass != C_EXT && sym.n_sclass != C_HIDEXT) {
!
! /*
! * Set csect_cache,
! * Normally csect is a .pr, .rw etc. created in the loop
! * If C_FILE or first time, handle special
! *
! * Advance esym, sym_hash, csect_hash ptr's
! * Keep track of the last_symndx for the current file
! */
! if (sym.n_sclass == C_FILE && csect != NULL) {
! xcoff_section_data (abfd, csect)->last_symndx =
! ((esym
! - (bfd_byte *) obj_coff_external_syms (abfd))
! / symesz);
! csect = NULL;
! }
! if (csect != NULL)
! *csect_cache = csect;
! else if (first_csect == NULL || sym.n_sclass == C_FILE)
! *csect_cache = coff_section_from_bfd_index (abfd, sym.n_scnum);
! else
! *csect_cache = NULL;
! esym += (sym.n_numaux + 1) * symesz;
! sym_hash += sym.n_numaux + 1;
! csect_cache += sym.n_numaux + 1;
!
! continue;
! }
! name = _bfd_coff_internal_syment_name (abfd, &sym, buf);
! if (name == NULL)
! goto error_return;
/* If this symbol has line number information attached to it,
and we're not stripping it, count the number of entries and
*************** xcoff_link_add_symbols (abfd, info)
*** 1612,1697 ****
we are going to attach line number information by symbol,
rather than by section, in order to more easily handle
garbage collection. */
! if ((info->strip == strip_none || info->strip == strip_some)
! && sym.n_numaux > 1
! && csect != NULL
! && ISFCN (sym.n_type))
! {
! union internal_auxent auxlin;
!
! bfd_coff_swap_aux_in (abfd, (PTR) (esym + symesz),
! sym.n_type, sym.n_sclass,
! 0, sym.n_numaux, (PTR) &auxlin);
! if (auxlin.x_sym.x_fcnary.x_fcn.x_lnnoptr != 0)
! {
! asection *enclosing;
! bfd_size_type linoff;
!
! enclosing = xcoff_section_data (abfd, csect)->enclosing;
! if (enclosing == NULL)
! {
! (*_bfd_error_handler)
! (_("%s: `%s' has line numbers but no enclosing section"),
! bfd_get_filename (abfd), name);
! bfd_set_error (bfd_error_bad_value);
! goto error_return;
! }
! linoff = (auxlin.x_sym.x_fcnary.x_fcn.x_lnnoptr
! - enclosing->line_filepos);
! if (linoff < enclosing->lineno_count * linesz)
! {
! struct internal_lineno lin;
! bfd_byte *linpstart;
!
! linpstart = (reloc_info[enclosing->target_index].linenos
! + linoff);
! bfd_coff_swap_lineno_in (abfd, (PTR) linpstart, (PTR) &lin);
! if (lin.l_lnno == 0
! && ((bfd_size_type) lin.l_addr.l_symndx
! == ((esym
! - (bfd_byte *) obj_coff_external_syms (abfd))
! / symesz)))
! {
! bfd_byte *linpend, *linp;
! linpend = (reloc_info[enclosing->target_index].linenos
! + enclosing->lineno_count * linesz);
! for (linp = linpstart + linesz;
! linp < linpend;
! linp += linesz)
! {
! bfd_coff_swap_lineno_in (abfd, (PTR) linp,
! (PTR) &lin);
! if (lin.l_lnno == 0)
! break;
! }
! csect->lineno_count += (linp - linpstart) / linesz;
! /* The setting of line_filepos will only be
! useful if all the line number entries for a
! csect are contiguous; this only matters for
! error reporting. */
! if (csect->line_filepos == 0)
! csect->line_filepos =
! auxlin.x_sym.x_fcnary.x_fcn.x_lnnoptr;
! }
! }
! }
! }
! /* Pick up the csect auxiliary information. */
! if (sym.n_numaux == 0)
! {
(*_bfd_error_handler)
! (_("%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;
}
! bfd_coff_swap_aux_in (abfd,
! (PTR) (esym + symesz * sym.n_numaux),
! sym.n_type, sym.n_sclass,
sym.n_numaux - 1, sym.n_numaux,
(PTR) &aux);
--- 1192,1270 ----
we are going to attach line number information by symbol,
rather than by section, in order to more easily handle
garbage collection. */
! if ((info->strip == strip_none || info->strip == strip_some) &&
! (sym.n_numaux > 1) &&
! (csect != NULL) &&
! (ISFCN (sym.n_type))) {
! union internal_auxent auxlin;
! bfd_coff_swap_aux_in (abfd, (PTR) (esym + symesz),
! sym.n_type, sym.n_sclass,
! 0, sym.n_numaux, (PTR) &auxlin);
! if (auxlin.x_sym.x_fcnary.x_fcn.x_lnnoptr != 0) {
! asection *enclosing;
! bfd_signed_vma linoff;
!
! enclosing = xcoff_section_data (abfd, csect)->enclosing;
! if (enclosing == NULL) {
(*_bfd_error_handler)
! (_("%s: `%s' has line numbers but no enclosing section"),
! bfd_get_filename (abfd), name);
bfd_set_error (bfd_error_bad_value);
goto error_return;
}
+ linoff = (auxlin.x_sym.x_fcnary.x_fcn.x_lnnoptr
+ - enclosing->line_filepos);
+ if (linoff < enclosing->lineno_count * linesz) {
+ struct internal_lineno lin;
+ bfd_byte *linpstart;
+
+ linpstart = (reloc_info[enclosing->target_index].linenos
+ + linoff);
+ bfd_coff_swap_lineno_in (abfd, (PTR) linpstart, (PTR) &lin);
+ if (lin.l_lnno == 0
+ && ((bfd_size_type) lin.l_addr.l_symndx
+ == ((esym
+ - (bfd_byte *) obj_coff_external_syms (abfd))
+ / symesz))) {
+ bfd_byte *linpend, *linp;
+
+ linpend = (reloc_info[enclosing->target_index].linenos
+ + enclosing->lineno_count * linesz);
+ for (linp = linpstart + linesz; linp < linpend; linp += linesz) {
+ bfd_coff_swap_lineno_in (abfd, (PTR) linp,
+ (PTR) &lin);
+ if (lin.l_lnno == 0)
+ break;
+ }
+ csect->lineno_count += (linp - linpstart) / linesz;
+ /* The setting of line_filepos will only be
+ useful if all the line number entries for a
+ csect are contiguous; this only matters for
+ error reporting. */
+ if (csect->line_filepos == 0)
+ csect->line_filepos =
+ auxlin.x_sym.x_fcnary.x_fcn.x_lnnoptr;
+ }
+ }
+ }
+ }
! /* Pick up the csect auxiliary information. */
!
! if (sym.n_numaux == 0) {
! (*_bfd_error_handler)
! (_("%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;
! }
!
! bfd_coff_swap_aux_in (abfd,
! (PTR) (esym + symesz * sym.n_numaux),
! sym.n_type, sym.n_sclass,
sym.n_numaux - 1, sym.n_numaux,
(PTR) &aux);
*************** xcoff_link_add_symbols (abfd, info)
*** 1738,1744 ****
case XTY_SD:
/* This is a csect definition. */
-
if (csect != NULL)
{
xcoff_section_data (abfd, csect)->last_symndx =
--- 1311,1316 ----
*************** xcoff_link_add_symbols (abfd, info)
*** 1766,1909 ****
xcoff_data (abfd)->toc = sym.n_value;
}
! /* We must merge TOC entries for the same symbol. We can
! merge two TOC entries if they are both C_HIDEXT, they
! both have the same name, they are both 4 bytes long, and
! they both have a relocation table entry for an external
! symbol with the same name. Unfortunately, this means
! that we must look through the relocations. Ick. */
! if (aux.x_csect.x_smclas == XMC_TC
! && sym.n_sclass == C_HIDEXT
! && aux.x_csect.x_scnlen.l == 4
! && info->hash->creator == abfd->xvec)
! {
! asection *enclosing;
! struct internal_reloc *relocs;
! bfd_size_type relindx;
! struct internal_reloc *rel;
!
! enclosing = coff_section_from_bfd_index (abfd, sym.n_scnum);
! if (enclosing == NULL)
! goto error_return;
!
! relocs = reloc_info[enclosing->target_index].relocs;
! relindx = xcoff_find_reloc (relocs, enclosing->reloc_count,
! sym.n_value);
! rel = relocs + relindx;
! if (relindx < enclosing->reloc_count
! && rel->r_vaddr == (bfd_vma) sym.n_value
! && rel->r_size == 31
! && rel->r_type == R_POS)
! {
! bfd_byte *erelsym;
! struct internal_syment relsym;
!
! erelsym = ((bfd_byte *) obj_coff_external_syms (abfd)
! + rel->r_symndx * symesz);
! bfd_coff_swap_sym_in (abfd, (PTR) erelsym, (PTR) &relsym);
! if (relsym.n_sclass == C_EXT)
! {
! const char *relname;
! char relbuf[SYMNMLEN + 1];
! boolean copy;
! struct xcoff_link_hash_entry *h;
!
! /* At this point we know that the TOC entry is
! for an externally visible symbol. */
! relname = _bfd_coff_internal_syment_name (abfd, &relsym,
! relbuf);
! if (relname == NULL)
! goto error_return;
!
! /* We only merge TOC entries if the TC name is
! the same as the symbol name. This handles
! the normal case, but not common cases like
! SYM.P4 which gcc generates to store SYM + 4
! in the TOC. FIXME. */
! if (strcmp (name, relname) == 0)
! {
! copy = (! info->keep_memory
! || relsym._n._n_n._n_zeroes != 0
! || relsym._n._n_n._n_offset == 0);
! h = xcoff_link_hash_lookup (xcoff_hash_table (info),
! relname, true, copy,
! false);
! if (h == NULL)
! goto error_return;
!
! /* At this point h->root.type could be
! bfd_link_hash_new. That should be OK,
! since we know for sure that we will come
! across this symbol as we step through the
! file. */
!
! /* We store h in *sym_hash for the
! convenience of the relocate_section
! function. */
! *sym_hash = h;
! if (h->toc_section != NULL)
! {
! asection **rel_csects;
! /* We already have a TOC entry for this
! symbol, so we can just ignore this
! one. */
! rel_csects =
! reloc_info[enclosing->target_index].csects;
! rel_csects[relindx] = bfd_und_section_ptr;
! break;
! }
! /* We are about to create a TOC entry for
! this symbol. */
! set_toc = h;
! }
! }
! }
! }
- /* We need to create a new section. We get the name from
- 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"
! };
! const char *csect_name;
asection *enclosing;
! if ((aux.x_csect.x_smclas >=
! sizeof csect_name_by_class / sizeof csect_name_by_class[0])
! || csect_name_by_class[aux.x_csect.x_smclas] == NULL)
! {
! (*_bfd_error_handler)
! (_("%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;
! }
! csect_name = csect_name_by_class[aux.x_csect.x_smclas];
! csect = bfd_make_section_anyway (abfd, csect_name);
! if (csect == NULL)
goto error_return;
enclosing = coff_section_from_bfd_index (abfd, sym.n_scnum);
if (enclosing == NULL)
goto error_return;
! if (! bfd_is_abs_section (enclosing)
! && ((bfd_vma) sym.n_value < enclosing->vma
! || ((bfd_vma) sym.n_value + aux.x_csect.x_scnlen.l
! > enclosing->vma + enclosing->_raw_size)))
! {
! (*_bfd_error_handler)
! (_("%s: csect `%s' not in enclosing section"),
! bfd_get_filename (abfd), name);
! bfd_set_error (bfd_error_bad_value);
! goto error_return;
! }
csect->vma = sym.n_value;
csect->filepos = (enclosing->filepos
+ sym.n_value
--- 1338,1492 ----
xcoff_data (abfd)->toc = sym.n_value;
}
! /*
! * We must merge TOC entries for the same symbol. We can
! * merge two TOC entries if they are both C_HIDEXT, they
! * both have the same name, they are both 4 or 8 bytes long, and
! * they both have a relocation table entry for an external
! * symbol with the same name. Unfortunately, this means
! * that we must look through the relocations. Ick.
! *
! * Logic for 32 bit vs 64 bit.
! * 32 bit has a csect length of 4 for TOC
! * 64 bit has a csect length of 8 for TOC
! *
! * The conditions to get past the if-check are not that bad.
! * They are what is used to create the TOC csects in the first
! * place
! */
! if ((aux.x_csect.x_smclas == XMC_TC) &&
! (sym.n_sclass == C_HIDEXT) &&
! (info->hash->creator == abfd->xvec) &&
! (((bfd_xcoff_is_xcoff32(abfd)) &&
! (aux.x_csect.x_scnlen.l == 4)) ||
! ((bfd_xcoff_is_xcoff64(abfd)) &&
! (aux.x_csect.x_scnlen.l == 8)))) {
! asection *enclosing;
! struct internal_reloc *relocs;
! bfd_size_type relindx;
! struct internal_reloc *rel;
! enclosing = coff_section_from_bfd_index (abfd, sym.n_scnum);
! if (enclosing == NULL)
! goto error_return;
! relocs = reloc_info[enclosing->target_index].relocs;
! relindx = xcoff_find_reloc (relocs, enclosing->reloc_count,
! sym.n_value);
! rel = relocs + relindx;
!
! /*
! * 32 bit R_POS r_size is 31
! * 64 bit R_POS r_size is 63
! */
! if ((relindx < enclosing->reloc_count) &&
! (rel->r_vaddr == (bfd_vma) sym.n_value) &&
! (rel->r_type == R_POS) &&
! (((bfd_xcoff_is_xcoff32(abfd)) &&
! (rel->r_size == 31)) ||
! ((bfd_xcoff_is_xcoff64(abfd)) &&
! (rel->r_size == 63)))) {
!
! bfd_byte *erelsym;
!
! struct internal_syment relsym;
!
! erelsym = ((bfd_byte *) obj_coff_external_syms (abfd)
! + rel->r_symndx * symesz);
! bfd_coff_swap_sym_in (abfd, (PTR) erelsym, (PTR) &relsym);
! if (relsym.n_sclass == C_EXT) {
! const char *relname;
! char relbuf[SYMNMLEN + 1];
! boolean copy;
! struct xcoff_link_hash_entry *h;
!
! /* At this point we know that the TOC entry is
! for an externally visible symbol. */
!
! relname = _bfd_coff_internal_syment_name (abfd, &relsym,
! relbuf);
! if (relname == NULL)
! goto error_return;
!
! /* We only merge TOC entries if the TC name is
! the same as the symbol name. This handles
! the normal case, but not common cases like
! SYM.P4 which gcc generates to store SYM + 4
! in the TOC. FIXME. */
!
! if (strcmp (name, relname) == 0) {
! copy = (! info->keep_memory
! || relsym._n._n_n._n_zeroes != 0
! || relsym._n._n_n._n_offset == 0);
! h = xcoff_link_hash_lookup (xcoff_hash_table (info),
! relname, true, copy,
! false);
! if (h == NULL)
! goto error_return;
!
! /* At this point h->root.type could be
! bfd_link_hash_new. That should be OK,
! since we know for sure that we will come
! across this symbol as we step through the
! file. */
!
! /* We store h in *sym_hash for the
! convenience of the relocate_section
! function. */
! *sym_hash = h;
!
! if (h->toc_section != NULL) {
! asection **rel_csects;
!
! /* We already have a TOC entry for this
! symbol, so we can just ignore this
! one. */
! rel_csects =
! reloc_info[enclosing->target_index].csects;
! rel_csects[relindx] = bfd_und_section_ptr;
! break;
! }
!
! /* We are about to create a TOC entry for
! this symbol. */
! set_toc = h;
! } /* merge toc reloc */
! } /* c_ext */
! } /* reloc */
! } /* merge toc */
{
!
asection *enclosing;
! /* We need to create a new section. We get the name from
! the csect storage mapping class, so that the linker can
! accumulate similar csects together. */
! csect = bfd_xcoff_create_csect_from_smclas(abfd, &aux, name);
! if (NULL == csect) {
goto error_return;
+ }
+
+ /*
+ * The enclosing section is the main section : .data, .text
+ * or .bss that the csect is coming from
+ */
enclosing = coff_section_from_bfd_index (abfd, sym.n_scnum);
if (enclosing == NULL)
goto error_return;
!
! if (! bfd_is_abs_section (enclosing) &&
! ((bfd_vma) sym.n_value < enclosing->vma ||
! ((bfd_vma) sym.n_value + aux.x_csect.x_scnlen.l
! > enclosing->vma + enclosing->_raw_size))) {
! (*_bfd_error_handler)
! (_("%s: csect `%s' not in enclosing section"),
! bfd_get_filename (abfd), name);
! bfd_set_error (bfd_error_bad_value);
! goto error_return;
! }
csect->vma = sym.n_value;
csect->filepos = (enclosing->filepos
+ sym.n_value
*************** xcoff_link_add_symbols (abfd, info)
*** 1926,1958 ****
xcoff_section_data (abfd, csect)->lineno_count =
enclosing->lineno_count;
! if (enclosing->owner == abfd)
! {
! struct internal_reloc *relocs;
! bfd_size_type relindx;
! struct internal_reloc *rel;
! asection **rel_csect;
!
! relocs = reloc_info[enclosing->target_index].relocs;
! relindx = xcoff_find_reloc (relocs, enclosing->reloc_count,
! csect->vma);
! rel = relocs + relindx;
! rel_csect = (reloc_info[enclosing->target_index].csects
! + relindx);
! csect->rel_filepos = (enclosing->rel_filepos
! + relindx * bfd_coff_relsz (abfd));
! while (relindx < enclosing->reloc_count
! && *rel_csect == NULL
! && rel->r_vaddr < csect->vma + csect->_raw_size)
! {
! *rel_csect = csect;
! csect->flags |= SEC_RELOC;
! ++csect->reloc_count;
! ++relindx;
! ++rel;
! ++rel_csect;
! }
}
/* There are a number of other fields and section flags
which we do not bother to set. */
--- 1509,1542 ----
xcoff_section_data (abfd, csect)->lineno_count =
enclosing->lineno_count;
! if (enclosing->owner == abfd) {
! struct internal_reloc *relocs;
! bfd_size_type relindx;
! struct internal_reloc *rel;
! asection **rel_csect;
!
! relocs = reloc_info[enclosing->target_index].relocs;
! relindx = xcoff_find_reloc (relocs, enclosing->reloc_count,
! csect->vma);
!
! rel = relocs + relindx;
! rel_csect = (reloc_info[enclosing->target_index].csects
! + relindx);
!
! csect->rel_filepos = (enclosing->rel_filepos
! + relindx * bfd_coff_relsz (abfd));
! while (relindx < enclosing->reloc_count &&
! *rel_csect == NULL &&
! rel->r_vaddr < csect->vma + csect->_raw_size) {
!
! *rel_csect = csect;
! csect->flags |= SEC_RELOC;
! ++csect->reloc_count;
! ++relindx;
! ++rel;
! ++rel_csect;
}
+ }
/* There are a number of other fields and section flags
which we do not bother to set. */
*************** xcoff_link_add_symbols (abfd, info)
*** 2029,2038 ****
/ symesz);
}
! 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;
--- 1613,1628 ----
/ symesz);
}
! if (aux.x_csect.x_smclas == XMC_TD) {
! /*
! * The linker script puts the .td section in the data
! * section after the .tc section
! */
! csect = bfd_make_section_anyway (abfd, ".td");
!
! } else {
csect = bfd_make_section_anyway (abfd, ".bss");
+ }
if (csect == NULL)
goto error_return;
csect->vma = sym.n_value;
*************** xcoff_link_add_symbols (abfd, info)
*** 2071,2102 ****
}
/* Check for magic symbol names. */
! if ((smtyp == XTY_SD || smtyp == XTY_CM)
! && aux.x_csect.x_smclas != XMC_TC
! && aux.x_csect.x_smclas != XMC_TD)
! {
! int i;
!
! i = -1;
! if (name[0] == '_')
! {
! if (strcmp (name, "_text") == 0)
! i = 0;
! else if (strcmp (name, "_etext") == 0)
! i = 1;
! else if (strcmp (name, "_data") == 0)
! i = 2;
! else if (strcmp (name, "_edata") == 0)
! i = 3;
! else if (strcmp (name, "_end") == 0)
! i = 4;
! }
! else if (name[0] == 'e' && strcmp (name, "end") == 0)
! i = 5;
!
! if (i != -1)
! xcoff_hash_table (info)->special_sections[i] = csect;
! }
/* Now we have enough information to add the symbol to the
linker hash table. */
--- 1661,1691 ----
}
/* Check for magic symbol names. */
! if ((smtyp == XTY_SD || smtyp == XTY_CM) &&
! (aux.x_csect.x_smclas != XMC_TC) &&
! (aux.x_csect.x_smclas != XMC_TD)) {
!
! int i = -1;
!
! if (name[0] == '_') {
! if (strcmp (name, "_text") == 0)
! i = XCOFF_SPECIAL_SECTION_TEXT;
! else if (strcmp (name, "_etext") == 0)
! i = XCOFF_SPECIAL_SECTION_ETEXT;
! else if (strcmp (name, "_data") == 0)
! i = XCOFF_SPECIAL_SECTION_DATA;
! else if (strcmp (name, "_edata") == 0)
! i = XCOFF_SPECIAL_SECTION_EDATA;
! else if (strcmp (name, "_end") == 0)
! i = XCOFF_SPECIAL_SECTION_END;
! } else if (name[0] == 'e' && strcmp (name, "end") == 0) {
! i = XCOFF_SPECIAL_SECTION_END2;
! }
!
! if (i != -1) {
! xcoff_hash_table (info)->special_sections[i] = csect;
! }
! }
/* Now we have enough information to add the symbol to the
linker hash table. */
*************** xcoff_link_add_symbols (abfd, info)
*** 2139,2145 ****
shared object, which will cause symbol redefinitions,
although this is an easier case to detect. */
! if (info->hash->creator == abfd->xvec)
{
if (! bfd_is_und_section (section))
*sym_hash = xcoff_link_hash_lookup (xcoff_hash_table (info),
--- 1728,1734 ----
shared object, which will cause symbol redefinitions,
although this is an easier case to detect. */
! if (info->hash->creator == abfd->xvec)
{
if (! bfd_is_und_section (section))
*sym_hash = xcoff_link_hash_lookup (xcoff_hash_table (info),
*************** xcoff_link_add_symbols (abfd, info)
*** 2261,2271 ****
else
{
(*sym_hash)->root.u.c.p->alignment_power
! = csect->alignment_power;
}
}
! if (info->hash->creator == abfd->xvec)
{
int flag;
--- 1850,1860 ----
else
{
(*sym_hash)->root.u.c.p->alignment_power
! = csect->alignment_power;
}
}
! if (info->hash->creator == abfd->xvec)
{
int flag;
*************** xcoff_link_add_symbols (abfd, info)
*** 2309,2316 ****
--- 1898,1907 ----
rel = reloc_info[o->target_index].relocs;
rel_csect = reloc_info[o->target_index].csects;
+
for (i = 0; i < o->reloc_count; i++, rel++, rel_csect++)
{
+
if (*rel_csect == NULL)
{
(*_bfd_error_handler)
*************** xcoff_link_add_symbols (abfd, info)
*** 2323,2329 ****
/* We identify all symbols which are called, so that we
can create glue code for calls to functions imported
from dynamic objects. */
! if (info->hash->creator == abfd->xvec
&& *rel_csect != bfd_und_section_ptr
&& (rel->r_type == R_BR
|| rel->r_type == R_RBR)
--- 1914,1920 ----
/* We identify all symbols which are called, so that we
can create glue code for calls to functions imported
from dynamic objects. */
! if (info->hash->creator == abfd->xvec
&& *rel_csect != bfd_und_section_ptr
&& (rel->r_type == R_BR
|| rel->r_type == R_RBR)
*************** xcoff_link_add_symbols (abfd, info)
*** 2376,2382 ****
/* Reset SEC_RELOC and the reloc_count, since the reloc
information is now attached to the csects. */
! o->flags &= ~SEC_RELOC;
o->reloc_count = 0;
/* If we are not keeping memory, free the reloc information. */
--- 1967,1973 ----
/* Reset SEC_RELOC and the reloc_count, since the reloc
information is now attached to the csects. */
! o->flags &=~ SEC_RELOC;
o->reloc_count = 0;
/* If we are not keeping memory, free the reloc information. */
*************** xcoff_link_add_dynamic_symbols (abfd, in
*** 2433,2442 ****
struct bfd_link_info *info;
{
asection *lsec;
! bfd_byte *buf;
struct internal_ldhdr ldhdr;
const char *strings;
! struct external_ldsym *elsym, *elsymend;
struct xcoff_import_file *n;
const char *bname;
const char *mname;
--- 2024,2033 ----
struct bfd_link_info *info;
{
asection *lsec;
! bfd_byte *contents;
struct internal_ldhdr ldhdr;
const char *strings;
! bfd_byte *elsym, *elsymend;
struct xcoff_import_file *n;
const char *bname;
const char *mname;
*************** xcoff_link_add_dynamic_symbols (abfd, in
*** 2446,2460 ****
/* We can only handle a dynamic object if we are generating an XCOFF
output file. */
! if (info->hash->creator != abfd->xvec)
{
(*_bfd_error_handler)
(_("%s: XCOFF shared object when not producing XCOFF output"),
bfd_get_filename (abfd));
! bfd_set_error (bfd_error_invalid_operation);
return false;
}
!
/* The symbols we use from a dynamic object are not the symbols in
the normal symbol table, but, rather, the symbols in the export
table. If there is a global symbol in a dynamic object which is
--- 2037,2051 ----
/* We can only handle a dynamic object if we are generating an XCOFF
output file. */
! if (info->hash->creator != abfd->xvec)
{
(*_bfd_error_handler)
(_("%s: XCOFF shared object when not producing XCOFF output"),
bfd_get_filename (abfd));
! bfd_set_error (bfd_error_invalid_operation);
return false;
}
!
/* The symbols we use from a dynamic object are not the symbols in
the normal symbol table, but, rather, the symbols in the export
table. If there is a global symbol in a dynamic object which is
*************** xcoff_link_add_dynamic_symbols (abfd, in
*** 2476,2504 ****
return false;
}
if (! xcoff_get_section_contents (abfd, lsec))
return false;
! buf = coff_section_data (abfd, lsec)->contents;
/* Remove the sections from this object, so that they do not get
included in the link. */
abfd->sections = NULL;
! xcoff_swap_ldhdr_in (abfd, (struct external_ldhdr *) buf, &ldhdr);
! strings = (char *) buf + ldhdr.l_stoff;
! elsym = (struct external_ldsym *) (buf + LDHDRSZ);
! elsymend = elsym + ldhdr.l_nsyms;
! BFD_ASSERT (sizeof (struct external_ldsym) == LDSYMSZ);
! for (; elsym < elsymend; elsym++)
{
struct internal_ldsym ldsym;
char nambuf[SYMNMLEN + 1];
const char *name;
struct xcoff_link_hash_entry *h;
! xcoff_swap_ldsym_in (abfd, elsym, &ldsym);
/* We are only interested in exported symbols. */
if ((ldsym.l_smtype & L_EXPORT) == 0)
--- 2067,2097 ----
return false;
}
+
if (! xcoff_get_section_contents (abfd, lsec))
return false;
! contents = coff_section_data (abfd, lsec)->contents;
/* Remove the sections from this object, so that they do not get
included in the link. */
abfd->sections = NULL;
! bfd_xcoff_swap_ldhdr_in (abfd, contents, &ldhdr);
! strings = (char *) contents + ldhdr.l_stoff;
!
! elsym = contents + bfd_xcoff_loader_symbol_offset(abfd, &ldhdr);
! elsymend = elsym + ldhdr.l_nsyms * bfd_xcoff_ldsymsz(abfd);
!
! for (; elsym < elsymend; elsym += bfd_xcoff_ldsymsz(abfd))
{
struct internal_ldsym ldsym;
char nambuf[SYMNMLEN + 1];
const char *name;
struct xcoff_link_hash_entry *h;
! bfd_xcoff_swap_ldsym_in (abfd, elsym, &ldsym);
/* We are only interested in exported symbols. */
if ((ldsym.l_smtype & L_EXPORT) == 0)
*************** xcoff_link_add_dynamic_symbols (abfd, in
*** 2617,2623 ****
}
}
! if (buf != NULL && ! coff_section_data (abfd, lsec)->keep_contents)
{
free (coff_section_data (abfd, lsec)->contents);
coff_section_data (abfd, lsec)->contents = NULL;
--- 2210,2216 ----
}
}
! if (contents != NULL && ! coff_section_data (abfd, lsec)->keep_contents)
{
free (coff_section_data (abfd, lsec)->contents);
coff_section_data (abfd, lsec)->contents = NULL;
*************** xcoff_mark_symbol (info, h)
*** 2675,2680 ****
--- 2268,2274 ----
struct bfd_link_info *info;
struct xcoff_link_hash_entry *h;
{
+
if ((h->flags & XCOFF_MARK) != 0)
return true;
*************** xcoff_mark (info, sec)
*** 2714,2719 ****
--- 2308,2314 ----
struct bfd_link_info *info;
asection *sec;
{
+
if (bfd_is_abs_section (sec)
|| (sec->flags & SEC_MARK) != 0)
return true;
*************** bfd_xcoff_record_link_assignment (output
*** 3149,3176 ****
return true;
}
- /* This structure is used to pass information through
- xcoff_link_hash_traverse. */
-
- struct xcoff_loader_info {
- /* Set if a problem occurred. */
- boolean failed;
- /* Output BFD. */
- bfd *output_bfd;
- /* Link information structure. */
- struct bfd_link_info *info;
- /* Whether all defined symbols should be exported. */
- boolean export_defineds;
- /* Number of ldsym structures. */
- size_t ldsym_count;
- /* Size of string table. */
- size_t string_size;
- /* String table. */
- bfd_byte *strings;
- /* Allocated size of string table. */
- size_t string_alc;
- };
-
/* Build the .loader section. This is called by the XCOFF linker
emulation before_allocation routine. We must set the size of the
.loader section before the linker lays out the output file.
--- 2744,2749 ----
*************** bfd_xcoff_size_dynamic_sections (output_
*** 3220,3231 ****
struct bfd_strtab_hash *debug_strtab;
bfd_byte *debug_contents = NULL;
! if (bfd_get_flavour (output_bfd) != bfd_target_xcoff_flavour)
! {
! for (i = 0; i < 6; i++)
! special_sections[i] = NULL;
! return true;
! }
ldinfo.failed = false;
ldinfo.output_bfd = output_bfd;
--- 2793,2805 ----
struct bfd_strtab_hash *debug_strtab;
bfd_byte *debug_contents = NULL;
!
! if (bfd_get_flavour (output_bfd) != bfd_target_xcoff_flavour) {
!
! for (i = 0; i < XCOFF_NUMBER_OF_SPECIAL_SECTIONS; i++)
! special_sections[i] = NULL;
! return true;
! }
ldinfo.failed = false;
ldinfo.output_bfd = output_bfd;
*************** bfd_xcoff_size_dynamic_sections (output_
*** 3243,3258 ****
xcoff_hash_table (info)->file_align = file_align;
xcoff_hash_table (info)->textro = textro;
! 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
|| ! gc
--- 2817,2895 ----
xcoff_hash_table (info)->file_align = file_align;
xcoff_hash_table (info)->textro = textro;
! 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;
! }
!
! /* __rtinit */
! if (info->init_function || info->fini_function) {
! struct xcoff_link_hash_entry *hrtinit;
! struct internal_ldsym *ldsym;
!
! hrtinit = xcoff_link_hash_lookup (xcoff_hash_table (info),
! "__rtinit",
! false, false, true);
! if (hrtinit != NULL) {
! xcoff_mark_symbol (info, hrtinit);
! hrtinit->flags |= (XCOFF_DEF_REGULAR | XCOFF_RTINIT);
! } else {
! (*_bfd_error_handler)
! (_("error: undefined symbol __rtinit"));
!
! return false;
! }
!
! /*
! *
! * __rtinit initalized here
! * Some information, like the location of the .initfini seciton will
! * be filled in later
! *
! * name or offset taken case of below with bfd_xcoff_put_ldsymbol_name
! */
! ldsym = (struct internal_ldsym *)
! bfd_malloc(sizeof (struct internal_ldsym));
!
! ldsym->l_value = 0; /* will be filled in later */
! ldsym->l_scnum = 2; /* data section */
! ldsym->l_smtype = XTY_SD; /* csect section definition */
! ldsym->l_smclas = 5; /* .rw */
! ldsym->l_ifile = 0; /* special system loader symbol
*/
! ldsym->l_parm = 0; /* NA */
!
! /*
! * Force __rtinit to be the first symbol in the loader symbol table
! * See xcoff_build_ldsyms
! *
! * The first 3 symbol table indices are reserved to indicate the data,
! * text and bss sections.
! */
! BFD_ASSERT (0 == ldinfo.ldsym_count);
!
! hrtinit->ldindx = 3;
! ldinfo.ldsym_count = 1;
! hrtinit->ldsym = ldsym;
!
! if (false == bfd_xcoff_put_ldsymbol_name (ldinfo.output_bfd, &ldinfo,
! hrtinit->ldsym,
! hrtinit->root.root.string)) {
! return false;
}
+ /*
+ * This symbol is written out by xcoff_write_global_symbol
+ * Set stuff up so xcoff_write_global_symbol logic works.
+ */
+ hrtinit->flags |= XCOFF_DEF_REGULAR | XCOFF_MARK;
+ hrtinit->root.type = bfd_link_hash_defined;
+ hrtinit->root.u.def.value = 0;
+ }
+
/* Garbage collect unused sections. */
if (info->relocateable
|| ! gc
*************** bfd_xcoff_size_dynamic_sections (output_
*** 3288,3310 ****
}
/* Return special sections to the caller. */
! for (i = 0; i < 6; i++)
! {
! asection *sec;
!
! sec = xcoff_hash_table (info)->special_sections[i];
! if (sec != NULL
! && gc
! && (sec->flags & SEC_MARK) == 0)
! sec = NULL;
! special_sections[i] = sec;
}
! if (info->input_bfds == NULL)
! {
! /* I'm not sure what to do in this bizarre case. */
! return true;
! }
xcoff_link_hash_traverse (xcoff_hash_table (info), xcoff_build_ldsyms,
(PTR) &ldinfo);
--- 2925,2946 ----
}
/* Return special sections to the caller. */
! for (i = 0; i < XCOFF_NUMBER_OF_SPECIAL_SECTIONS; i++) {
! asection *sec;
!
! sec = xcoff_hash_table (info)->special_sections[i];
!
! if ((sec != NULL) &&
! (gc && (sec->flags & SEC_MARK) == 0)) {
! sec = NULL;
}
+ special_sections[i] = sec;
+ }
! if (info->input_bfds == NULL) {
! /* I'm not sure what to do in this bizarre case. */
! return true;
! }
xcoff_link_hash_traverse (xcoff_hash_table (info), xcoff_build_ldsyms,
(PTR) &ldinfo);
*************** bfd_xcoff_size_dynamic_sections (output_
*** 3330,3343 ****
/* Set up the .loader section header. */
ldhdr = &xcoff_hash_table (info)->ldhdr;
! ldhdr->l_version = 1;
ldhdr->l_nsyms = ldinfo.ldsym_count;
ldhdr->l_nreloc = xcoff_hash_table (info)->ldrel_count;
ldhdr->l_istlen = impsize;
ldhdr->l_nimpid = impcount;
! ldhdr->l_impoff = (LDHDRSZ
! + ldhdr->l_nsyms * LDSYMSZ
! + ldhdr->l_nreloc * LDRELSZ);
ldhdr->l_stlen = ldinfo.string_size;
stoff = ldhdr->l_impoff + impsize;
if (ldinfo.string_size == 0)
--- 2966,2979 ----
/* Set up the .loader section header. */
ldhdr = &xcoff_hash_table (info)->ldhdr;
! ldhdr->l_version = bfd_xcoff_ldhdr_version(output_bfd);
ldhdr->l_nsyms = ldinfo.ldsym_count;
ldhdr->l_nreloc = xcoff_hash_table (info)->ldrel_count;
ldhdr->l_istlen = impsize;
ldhdr->l_nimpid = impcount;
! ldhdr->l_impoff = (bfd_xcoff_ldhdrsz(output_bfd)
! + ldhdr->l_nsyms * bfd_xcoff_ldsymsz(output_bfd)
! + ldhdr->l_nreloc * bfd_xcoff_ldrelsz(output_bfd));
ldhdr->l_stlen = ldinfo.string_size;
stoff = ldhdr->l_impoff + impsize;
if (ldinfo.string_size == 0)
*************** bfd_xcoff_size_dynamic_sections (output_
*** 3345,3350 ****
--- 2981,2995 ----
else
ldhdr->l_stoff = stoff;
+ /*
+ * 64 bit elements to ldhdr
+ * The swap out routine for 32 bit will ignore them.
+ * Nothing fancy, symbols come after the header and relocs come after
symbols
+ */
+ ldhdr->l_symoff = bfd_xcoff_ldhdrsz(output_bfd);
+ ldhdr->l_rldoff = bfd_xcoff_ldhdrsz(output_bfd) +
+ (ldhdr->l_nsyms * bfd_xcoff_ldsymsz(output_bfd));
+
/* We now know the final size of the .loader section. Allocate
space for it. */
lsec = xcoff_hash_table (info)->loader_section;
*************** bfd_xcoff_size_dynamic_sections (output_
*** 3354,3361 ****
goto error_return;
/* Set up the header. */
! xcoff_swap_ldhdr_out (output_bfd, ldhdr,
! (struct external_ldhdr *) lsec->contents);
/* Set up the import file names. */
out = (char *) lsec->contents + ldhdr->l_impoff;
--- 2999,3005 ----
goto error_return;
/* Set up the header. */
! bfd_xcoff_swap_ldhdr_out (output_bfd, ldhdr, lsec->contents);
/* Set up the import file names. */
out = (char *) lsec->contents + ldhdr->l_impoff;
*************** bfd_xcoff_size_dynamic_sections (output_
*** 3394,3400 ****
symbols are written out in xcoff_link_input_bfd or
xcoff_write_global_symbol. The .loader relocs are written out
when the corresponding normal relocs are handled in
! xcoff_link_input_bfd. */
/* Allocate space for the magic sections. */
sec = xcoff_hash_table (info)->linkage_section;
--- 3038,3045 ----
symbols are written out in xcoff_link_input_bfd or
xcoff_write_global_symbol. The .loader relocs are written out
when the corresponding normal relocs are handled in
! xcoff_link_input_bfd.
! */
/* Allocate space for the magic sections. */
sec = xcoff_hash_table (info)->linkage_section;
*************** xcoff_build_ldsyms (h, p)
*** 3539,3545 ****
PTR p;
{
struct xcoff_loader_info *ldinfo = (struct xcoff_loader_info *) p;
! size_t len;
/* If this is a final link, and the symbol was defined as a common
symbol in a regular object file, and there was no definition in
--- 3184,3198 ----
PTR p;
{
struct xcoff_loader_info *ldinfo = (struct xcoff_loader_info *) p;
!
! /*
! * __rtinit
! * Special handling of this symbol to make is the first symbol in the
! * loader symbol table. Make sure this pass through does not undo it
! */
! if (h->flags & XCOFF_RTINIT) {
! return true;
! }
/* If this is a final link, and the symbol was defined as a common
symbol in a regular object file, and there was no definition in
*************** xcoff_build_ldsyms (h, p)
*** 3637,3643 ****
h->root.u.def.value = sec->_raw_size;
h->smclas = XMC_GL;
h->flags |= XCOFF_DEF_REGULAR;
! sec->_raw_size += XCOFF_GLINK_SIZE;
/* The global linkage code requires a TOC entry for the
descriptor. */
--- 3290,3296 ----
h->root.u.def.value = sec->_raw_size;
h->smclas = XMC_GL;
h->flags |= XCOFF_DEF_REGULAR;
! sec->_raw_size += bfd_xcoff_glink_code_size(ldinfo->output_bfd);
/* The global linkage code requires a TOC entry for the
descriptor. */
*************** xcoff_build_ldsyms (h, p)
*** 3646,3665 ****
|| hds->root.type == bfd_link_hash_undefweak)
&& (hds->flags & XCOFF_DEF_REGULAR) == 0);
hds->flags |= XCOFF_MARK;
! if (hds->toc_section == NULL)
! {
! hds->toc_section = xcoff_hash_table (ldinfo->info)->toc_section;
! hds->u.toc_offset = hds->toc_section->_raw_size;
! hds->toc_section->_raw_size += 4;
! ++xcoff_hash_table (ldinfo->info)->ldrel_count;
! ++hds->toc_section->reloc_count;
! hds->indx = -2;
! hds->flags |= XCOFF_SET_TOC | XCOFF_LDREL;
!
! /* We need to call xcoff_build_ldsyms recursively here,
! because we may already have passed hds on the traversal. */
! xcoff_build_ldsyms (hds, p);
}
}
/* If this symbol is exported, but not defined, we need to try to
--- 3299,3334 ----
|| hds->root.type == bfd_link_hash_undefweak)
&& (hds->flags & XCOFF_DEF_REGULAR) == 0);
hds->flags |= XCOFF_MARK;
! if (hds->toc_section == NULL) {
! int byte_size;
!
! /*
! * 32 vs 64
! * xcoff32 uses 4 bytes in the toc
! * xcoff64 uses 8 bytes in the toc
! */
! if (bfd_xcoff_is_xcoff64(ldinfo->output_bfd)) {
! byte_size = 8;
! } else if (bfd_xcoff_is_xcoff32(ldinfo->output_bfd)) {
! byte_size = 4;
! } else {
! return false;
}
+
+ hds->toc_section = xcoff_hash_table (ldinfo->info)->toc_section;
+ hds->u.toc_offset = hds->toc_section->_raw_size;
+ hds->toc_section->_raw_size += byte_size;
+ ++xcoff_hash_table (ldinfo->info)->ldrel_count;
+ ++hds->toc_section->reloc_count;
+ hds->indx = -2;
+ hds->flags |= XCOFF_SET_TOC | XCOFF_LDREL;
+
+ /*
+ * We need to call xcoff_build_ldsyms recursively here,
+ * because we may already have passed hds on the traversal.
+ */
+ xcoff_build_ldsyms (hds, p);
+ }
}
/* If this symbol is exported, but not defined, we need to try to
*************** xcoff_build_ldsyms (h, p)
*** 3688,3702 ****
h->root.u.def.value = sec->_raw_size;
h->smclas = XMC_DS;
h->flags |= XCOFF_DEF_REGULAR;
- sec->_raw_size += 12;
! /* A function descriptor uses two relocs: one for the
! associated code, and one for the TOC address. */
xcoff_hash_table (ldinfo->info)->ldrel_count += 2;
sec->reloc_count += 2;
! /* We handle writing out the contents of the descriptor in
! xcoff_write_global_symbol. */
}
else
{
--- 3357,3381 ----
h->root.u.def.value = sec->_raw_size;
h->smclas = XMC_DS;
h->flags |= XCOFF_DEF_REGULAR;
! /*
! * The size of the function descriptor depends if this is an
! * xcoff32 (12) or xcoff64 (24)
! */
! sec->_raw_size +=
! bfd_xcoff_function_descriptor_size(ldinfo->output_bfd);
!
! /*
! * A function descriptor uses two relocs: one for the
! * associated code, and one for the TOC address.
! */
xcoff_hash_table (ldinfo->info)->ldrel_count += 2;
sec->reloc_count += 2;
! /*
! * We handle writing out the contents of the descriptor in
! * xcoff_write_global_symbol.
! */
}
else
{
*************** xcoff_build_ldsyms (h, p)
*** 3765,3810 ****
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;
++ldinfo->ldsym_count;
! len = strlen (h->root.root.string);
! if (len <= SYMNMLEN)
! strncpy (h->ldsym->_l._l_name, h->root.root.string, SYMNMLEN);
! else
! {
! if (ldinfo->string_size + len + 3 > ldinfo->string_alc)
! {
! size_t newalc;
! bfd_byte *newstrings;
!
! newalc = ldinfo->string_alc * 2;
! if (newalc == 0)
! newalc = 32;
! while (ldinfo->string_size + len + 3 > newalc)
! newalc *= 2;
!
! newstrings = ((bfd_byte *)
! bfd_realloc ((PTR) ldinfo->strings, newalc));
! if (newstrings == NULL)
! {
! ldinfo->failed = true;
! return false;
! }
! ldinfo->string_alc = newalc;
! ldinfo->strings = newstrings;
! }
!
! bfd_put_16 (ldinfo->output_bfd, len + 1,
! ldinfo->strings + ldinfo->string_size);
! strcpy (ldinfo->strings + ldinfo->string_size + 2,
h->root.root.string);
! h->ldsym->_l._l_l._l_zeroes = 0;
! h->ldsym->_l._l_l._l_offset = ldinfo->string_size + 2;
! ldinfo->string_size += len + 3;
! }
h->flags |= XCOFF_BUILT_LDSYM;
--- 3444,3462 ----
if ((h->flags & XCOFF_IMPORT) != 0)
h->ldsym->l_ifile = h->ldindx;
! /*
! * The first 3 symbol table indices are reserved to indicate the data,
! * text and bss sections.
! */
h->ldindx = ldinfo->ldsym_count + 3;
++ldinfo->ldsym_count;
! if (false == bfd_xcoff_put_ldsymbol_name (ldinfo->output_bfd, ldinfo,
! h->ldsym,
! h->root.root.string)) {
! return false;
! }
h->flags |= XCOFF_BUILT_LDSYM;
*************** _bfd_xcoff_bfd_final_link (abfd, info)
*** 3853,3865 ****
finfo.contents = NULL;
finfo.external_relocs = NULL;
! finfo.ldsym = ((struct external_ldsym *)
! (xcoff_hash_table (info)->loader_section->contents
! + LDHDRSZ));
! finfo.ldrel = ((struct external_ldrel *)
! (xcoff_hash_table (info)->loader_section->contents
! + LDHDRSZ
! + xcoff_hash_table (info)->ldhdr.l_nsyms * LDSYMSZ));
xcoff_data (abfd)->coff.link_info = info;
--- 3505,3515 ----
finfo.contents = NULL;
finfo.external_relocs = NULL;
! finfo.ldsym = xcoff_hash_table (info)->loader_section->contents +
! bfd_xcoff_ldhdrsz(abfd);
! finfo.ldrel = xcoff_hash_table (info)->loader_section->contents +
! bfd_xcoff_ldhdrsz(abfd) +
! xcoff_hash_table (info)->ldhdr.l_nsyms * bfd_xcoff_ldsymsz(abfd);
xcoff_data (abfd)->coff.link_info = info;
*************** _bfd_xcoff_bfd_final_link (abfd, info)
*** 3979,3988 ****
sofar = bfd_coff_filhsz (abfd);
sofar += bfd_coff_aoutsz (abfd);
sofar += abfd->section_count * bfd_coff_scnhsz (abfd);
! for (o = abfd->sections; o != NULL; o = o->next)
! if (o->reloc_count >= 0xffff || o->lineno_count >= 0xffff)
! sofar += bfd_coff_scnhsz (abfd);
for (o = abfd->sections; o != NULL; o = o->next)
{
if (strcmp (o->name, ".pad") == 0)
--- 3629,3644 ----
sofar = bfd_coff_filhsz (abfd);
sofar += bfd_coff_aoutsz (abfd);
sofar += abfd->section_count * bfd_coff_scnhsz (abfd);
! for (o = abfd->sections; o != NULL; o = o->next) {
! if ((true ==
! bfd_xcoff_is_reloc_count_overflow(abfd, o->reloc_count)) ||
! (true ==
! bfd_xcoff_is_lineno_count_overflow(abfd, o->lineno_count))) {
+ /* 64 does not overflow, need to check if 32 does */
+ sofar += bfd_coff_scnhsz (abfd);
+ }
+ }
for (o = abfd->sections; o != NULL; o = o->next)
{
if (strcmp (o->name, ".pad") == 0)
*************** _bfd_xcoff_bfd_final_link (abfd, info)
*** 4124,4129 ****
--- 3780,3786 ----
finfo.internal_syms = ((struct internal_syment *)
bfd_malloc (max_sym_count
* sizeof (struct internal_syment)));
+
finfo.sym_indices = (long *) bfd_malloc (max_sym_count * sizeof (long));
finfo.outsyms = ((bfd_byte *)
bfd_malloc ((size_t) ((max_sym_count + 1) * symesz)));
*************** _bfd_xcoff_bfd_final_link (abfd, info)
*** 4176,4223 ****
}
}
/* Free up the buffers used by xcoff_link_input_bfd. */
! if (finfo.internal_syms != NULL)
! {
! free (finfo.internal_syms);
! finfo.internal_syms = NULL;
! }
! if (finfo.sym_indices != NULL)
! {
! free (finfo.sym_indices);
! finfo.sym_indices = NULL;
! }
! if (finfo.linenos != NULL)
! {
! free (finfo.linenos);
! finfo.linenos = NULL;
! }
! if (finfo.contents != NULL)
! {
! free (finfo.contents);
! finfo.contents = NULL;
! }
! if (finfo.external_relocs != NULL)
! {
! free (finfo.external_relocs);
! finfo.external_relocs = NULL;
! }
/* The value of the last C_FILE symbol is supposed to be -1. Write
it out again. */
! if (finfo.last_file_index != -1)
! {
! finfo.last_file.n_value = -1;
! bfd_coff_swap_sym_out (abfd, (PTR) &finfo.last_file,
! (PTR) finfo.outsyms);
! if (bfd_seek (abfd,
! (obj_sym_filepos (abfd)
! + finfo.last_file_index * symesz),
! SEEK_SET) != 0
! || bfd_write (finfo.outsyms, symesz, 1, abfd) != symesz)
! goto error_return;
! }
/* Write out all the global symbols which do not come from XCOFF
input files. */
--- 3833,3875 ----
}
}
+
/* Free up the buffers used by xcoff_link_input_bfd. */
! if (finfo.internal_syms != NULL) {
! free (finfo.internal_syms);
! finfo.internal_syms = NULL;
! }
! if (finfo.sym_indices != NULL) {
! free (finfo.sym_indices);
! finfo.sym_indices = NULL;
! }
! if (finfo.linenos != NULL) {
! free (finfo.linenos);
! finfo.linenos = NULL;
! }
! if (finfo.contents != NULL) {
! free (finfo.contents);
! finfo.contents = NULL;
! }
! if (finfo.external_relocs != NULL) {
! free (finfo.external_relocs);
! finfo.external_relocs = NULL;
! }
/* The value of the last C_FILE symbol is supposed to be -1. Write
it out again. */
! if (finfo.last_file_index != -1) {
! finfo.last_file.n_value = -1;
! bfd_coff_swap_sym_out (abfd, (PTR) &finfo.last_file,
! (PTR) finfo.outsyms);
! if (bfd_seek (abfd,
! (obj_sym_filepos (abfd)
! + finfo.last_file_index * symesz),
! SEEK_SET) != 0
! || bfd_write (finfo.outsyms, symesz, 1, abfd) != symesz)
! goto error_return;
! }
/* Write out all the global symbols which do not come from XCOFF
input files. */
*************** _bfd_xcoff_bfd_final_link (abfd, info)
*** 4238,4337 ****
if (external_relocs == NULL && max_output_reloc_count != 0)
goto error_return;
! for (o = abfd->sections; o != NULL; o = o->next)
! {
! struct internal_reloc *irel;
! struct internal_reloc *irelend;
! struct xcoff_link_hash_entry **rel_hash;
! 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;
!
! irel = finfo.section_info[o->target_index].relocs;
! irelend = irel + o->reloc_count;
! rel_hash = finfo.section_info[o->target_index].rel_hashes;
! for (; irel < irelend; irel++, rel_hash++, erel += relsz)
! {
! if (*rel_hash != NULL)
! {
! if ((*rel_hash)->indx < 0)
! {
! if (! ((*info->callbacks->unattached_reloc)
! (info, (*rel_hash)->root.root.string,
! (bfd *) NULL, o, irel->r_vaddr)))
! goto error_return;
! (*rel_hash)->indx = 0;
! }
! irel->r_symndx = (*rel_hash)->indx;
! }
! }
!
! for (toc_rel_hash =
finfo.section_info[o->target_index].toc_rel_hashes;
! toc_rel_hash != NULL;
! toc_rel_hash = toc_rel_hash->next)
! {
! if (toc_rel_hash->h->u.toc_indx < 0)
! {
! if (! ((*info->callbacks->unattached_reloc)
! (info, toc_rel_hash->h->root.root.string,
! (bfd *) NULL, o, toc_rel_hash->rel->r_vaddr)))
! goto error_return;
! toc_rel_hash->h->u.toc_indx = 0;
! }
! toc_rel_hash->rel->r_symndx = toc_rel_hash->h->u.toc_indx;
}
!
! /* XCOFF requires that the relocs be sorted by address. We tend
! to produce them in the order in which their containing csects
! appear in the symbol table, which is not necessarily by
! address. So we sort them here. There may be a better way to
! do this. */
! qsort ((PTR) finfo.section_info[o->target_index].relocs,
! o->reloc_count, sizeof (struct internal_reloc),
! xcoff_sort_relocs);
!
! irel = finfo.section_info[o->target_index].relocs;
! irelend = irel + o->reloc_count;
! erel = external_relocs;
! for (; irel < irelend; irel++, rel_hash++, erel += relsz)
! bfd_coff_swap_reloc_out (abfd, (PTR) irel, (PTR) erel);
!
! if (bfd_seek (abfd, o->rel_filepos, SEEK_SET) != 0
! || bfd_write ((PTR) external_relocs, relsz, o->reloc_count,
! abfd) != relsz * o->reloc_count)
! goto error_return;
}
! if (external_relocs != NULL)
! {
! free (external_relocs);
! external_relocs = NULL;
}
/* Free up the section information. */
! if (finfo.section_info != NULL)
! {
! unsigned int i;
! for (i = 0; i < abfd->section_count; i++)
! {
! if (finfo.section_info[i].relocs != NULL)
! free (finfo.section_info[i].relocs);
! if (finfo.section_info[i].rel_hashes != NULL)
! free (finfo.section_info[i].rel_hashes);
! }
! free (finfo.section_info);
! finfo.section_info = NULL;
}
/* Write out the loader section contents. */
BFD_ASSERT ((bfd_byte *) finfo.ldrel
--- 3890,3979 ----
if (external_relocs == NULL && max_output_reloc_count != 0)
goto error_return;
! for (o = abfd->sections; o != NULL; o = o->next) {
! struct internal_reloc *irel;
! struct internal_reloc *irelend;
! struct xcoff_link_hash_entry **rel_hash;
! 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;
!
! irel = finfo.section_info[o->target_index].relocs;
! irelend = irel + o->reloc_count;
! rel_hash = finfo.section_info[o->target_index].rel_hashes;
! for (; irel < irelend; irel++, rel_hash++, erel += relsz) {
! if (*rel_hash != NULL) {
! if ((*rel_hash)->indx < 0) {
! if (! ((*info->callbacks->unattached_reloc)
! (info, (*rel_hash)->root.root.string,
! (bfd *) NULL, o, irel->r_vaddr)))
! goto error_return;
! (*rel_hash)->indx = 0;
}
! irel->r_symndx = (*rel_hash)->indx;
! }
}
! for (toc_rel_hash =
finfo.section_info[o->target_index].toc_rel_hashes;
! toc_rel_hash != NULL;
! toc_rel_hash = toc_rel_hash->next) {
! if (toc_rel_hash->h->u.toc_indx < 0) {
! if (! ((*info->callbacks->unattached_reloc)
! (info, toc_rel_hash->h->root.root.string,
! (bfd *) NULL, o, toc_rel_hash->rel->r_vaddr)))
! goto error_return;
! toc_rel_hash->h->u.toc_indx = 0;
! }
! toc_rel_hash->rel->r_symndx = toc_rel_hash->h->u.toc_indx;
}
+ /* XCOFF requires that the relocs be sorted by address. We tend
+ to produce them in the order in which their containing csects
+ appear in the symbol table, which is not necessarily by
+ address. So we sort them here. There may be a better way to
+ do this. */
+ qsort ((PTR) finfo.section_info[o->target_index].relocs,
+ o->reloc_count, sizeof (struct internal_reloc),
+ xcoff_sort_relocs);
+
+ irel = finfo.section_info[o->target_index].relocs;
+ irelend = irel + o->reloc_count;
+ erel = external_relocs;
+ for (; irel < irelend; irel++, rel_hash++, erel += relsz)
+ bfd_coff_swap_reloc_out (abfd, (PTR) irel, (PTR) erel);
+
+ if (bfd_seek (abfd, o->rel_filepos, SEEK_SET) != 0
+ || bfd_write ((PTR) external_relocs, relsz, o->reloc_count,
+ abfd) != relsz * o->reloc_count)
+ goto error_return;
+ }
+
+ if (external_relocs != NULL) {
+ free (external_relocs);
+ external_relocs = NULL;
+ }
+
/* Free up the section information. */
! if (finfo.section_info != NULL) {
! unsigned int i;
! for (i = 0; i < abfd->section_count; i++) {
! if (finfo.section_info[i].relocs != NULL)
! free (finfo.section_info[i].relocs);
! if (finfo.section_info[i].rel_hashes != NULL)
! free (finfo.section_info[i].rel_hashes);
}
+ free (finfo.section_info);
+ finfo.section_info = NULL;
+ }
/* Write out the loader section contents. */
BFD_ASSERT ((bfd_byte *) finfo.ldrel
*************** _bfd_xcoff_bfd_final_link (abfd, info)
*** 4378,4420 ****
/* Write out the debugging string table. */
o = xcoff_hash_table (info)->debug_section;
! if (o != NULL)
! {
! struct bfd_strtab_hash *debug_strtab;
!
! debug_strtab = xcoff_hash_table (info)->debug_strtab;
! BFD_ASSERT (o->output_section->_raw_size - o->output_offset
! >= _bfd_stringtab_size (debug_strtab));
! if (bfd_seek (abfd,
! o->output_section->filepos + o->output_offset,
! SEEK_SET) != 0)
! goto error_return;
! if (! _bfd_stringtab_emit (abfd, debug_strtab))
! goto error_return;
! }
!
/* Setting bfd_get_symcount to 0 will cause write_object_contents to
not try to write out the symbols. */
bfd_get_symcount (abfd) = 0;
!
return true;
error_return:
if (finfo.strtab != NULL)
_bfd_stringtab_free (finfo.strtab);
! if (finfo.section_info != NULL)
! {
! unsigned int i;
!
! for (i = 0; i < abfd->section_count; i++)
! {
! if (finfo.section_info[i].relocs != NULL)
! free (finfo.section_info[i].relocs);
! if (finfo.section_info[i].rel_hashes != NULL)
! free (finfo.section_info[i].rel_hashes);
! }
! free (finfo.section_info);
}
if (finfo.internal_syms != NULL)
free (finfo.internal_syms);
if (finfo.sym_indices != NULL)
--- 4020,4061 ----
/* Write out the debugging string table. */
o = xcoff_hash_table (info)->debug_section;
! if (o != NULL) {
! struct bfd_strtab_hash *debug_strtab;
!
! debug_strtab = xcoff_hash_table (info)->debug_strtab;
! BFD_ASSERT (o->output_section->_raw_size - o->output_offset
! >= _bfd_stringtab_size (debug_strtab));
! if (bfd_seek (abfd,
! o->output_section->filepos + o->output_offset,
! SEEK_SET) != 0)
! goto error_return;
! if (! _bfd_stringtab_emit (abfd, debug_strtab))
! goto error_return;
! }
!
/* Setting bfd_get_symcount to 0 will cause write_object_contents to
not try to write out the symbols. */
bfd_get_symcount (abfd) = 0;
!
return true;
error_return:
if (finfo.strtab != NULL)
_bfd_stringtab_free (finfo.strtab);
!
! if (finfo.section_info != NULL) {
! unsigned int i;
!
! for (i = 0; i < abfd->section_count; i++) {
! if (finfo.section_info[i].relocs != NULL)
! free (finfo.section_info[i].relocs);
! if (finfo.section_info[i].rel_hashes != NULL)
! free (finfo.section_info[i].rel_hashes);
}
+ free (finfo.section_info);
+ }
+
if (finfo.internal_syms != NULL)
free (finfo.internal_syms);
if (finfo.sym_indices != NULL)
*************** xcoff_link_input_bfd (finfo, input_bfd)
*** 4509,4514 ****
--- 4150,4156 ----
while (esym < esym_end)
{
+
struct internal_syment isym;
union internal_auxent aux;
int smtyp = 0;
*************** xcoff_link_input_bfd (finfo, input_bfd)
*** 4528,4533 ****
--- 4170,4176 ----
isymp->n_type, isymp->n_sclass,
isymp->n_numaux - 1, isymp->n_numaux,
(PTR) &aux);
+
smtyp = SMTYP_SMTYP (aux.x_csect.x_smtyp);
}
*************** xcoff_link_input_bfd (finfo, input_bfd)
*** 4612,4628 ****
ldsym->l_parm = 0;
BFD_ASSERT (h->ldindx >= 0);
! BFD_ASSERT (LDSYMSZ == sizeof (struct external_ldsym));
! xcoff_swap_ldsym_out (finfo->output_bfd, ldsym,
! finfo->ldsym + h->ldindx - 3);
h->ldsym = NULL;
/* Fill in snentry now that we know the target_index. */
! if ((h->flags & XCOFF_ENTRY) != 0
! && (h->root.type == bfd_link_hash_defined
! || h->root.type == bfd_link_hash_defweak))
xcoff_data (output_bfd)->snentry =
h->root.u.def.section->output_section->target_index;
}
*indexp = -1;
--- 4255,4272 ----
ldsym->l_parm = 0;
BFD_ASSERT (h->ldindx >= 0);
! bfd_xcoff_swap_ldsym_out (finfo->output_bfd, ldsym,
! finfo->ldsym + (h->ldindx - 3) *
! bfd_xcoff_ldsymsz(finfo->output_bfd));
h->ldsym = NULL;
/* Fill in snentry now that we know the target_index. */
! if ((h->flags & XCOFF_ENTRY) != 0 &&
! (h->root.type == bfd_link_hash_defined
! || h->root.type == bfd_link_hash_defweak)) {
xcoff_data (output_bfd)->snentry =
h->root.u.def.section->output_section->target_index;
+ }
}
*indexp = -1;
*************** xcoff_link_input_bfd (finfo, input_bfd)
*** 4715,4720 ****
--- 4359,4365 ----
xcoff_data (finfo->output_bfd)->sntoc =
(*csectpp)->output_section->target_index;
require = true;
+
}
}
*************** xcoff_link_input_bfd (finfo, input_bfd)
*** 4770,4775 ****
--- 4415,4421 ----
char buf[SYMNMLEN + 1];
name = _bfd_coff_internal_syment_name (input_bfd, &isym, buf);
+
if (name == NULL)
return false;
*************** xcoff_link_input_bfd (finfo, input_bfd)
*** 4810,4815 ****
--- 4456,4462 ----
name = _bfd_coff_internal_syment_name (input_bfd, &isym,
(char *) NULL);
+
if (name == NULL)
return false;
indx = _bfd_stringtab_add (finfo->strtab, name, hash, copy);
*************** xcoff_link_input_bfd (finfo, input_bfd)
*** 4955,4961 ****
if (isymp->n_sclass == C_BSTAT)
{
struct internal_syment isym;
! unsigned long indx;
/* The value of a C_BSTAT symbol is the symbol table
index of the containing csect. */
--- 4602,4609 ----
if (isymp->n_sclass == C_BSTAT)
{
struct internal_syment isym;
!
! bfd_vma indx;
/* The value of a C_BSTAT symbol is the symbol table
index of the containing csect. */
*************** xcoff_link_input_bfd (finfo, input_bfd)
*** 5017,5022 ****
--- 4665,4671 ----
|| isymp->n_sclass == C_HIDEXT)
&& i + 1 == isymp->n_numaux)
{
+
/* We don't support type checking. I don't know if
anybody does. */
aux.x_csect.x_parmhash = 0;
*************** xcoff_link_input_bfd (finfo, input_bfd)
*** 5024,5043 ****
better clobber them just in case. */
aux.x_csect.x_stab = 0;
aux.x_csect.x_snstab = 0;
if (SMTYP_SMTYP (aux.x_csect.x_smtyp) == XTY_LD)
{
! unsigned long indx;
! indx = aux.x_csect.x_scnlen.l;
if (indx < obj_raw_syment_count (input_bfd))
{
long symindx;
symindx = finfo->sym_indices[indx];
! if (symindx < 0)
! aux.x_sym.x_tagndx.l = 0;
! else
! aux.x_sym.x_tagndx.l = symindx;
}
}
}
--- 4673,4695 ----
better clobber them just in case. */
aux.x_csect.x_stab = 0;
aux.x_csect.x_snstab = 0;
+
if (SMTYP_SMTYP (aux.x_csect.x_smtyp) == XTY_LD)
{
! bfd_signed_vma indx;
!
! indx = aux.x_csect.x_scnlen.l;
if (indx < obj_raw_syment_count (input_bfd))
{
long symindx;
symindx = finfo->sym_indices[indx];
! if (symindx < 0) {
! aux.x_csect.x_scnlen.l = 0;
! } else {
! aux.x_csect.x_scnlen.l = symindx;
! }
}
}
}
*************** xcoff_link_input_bfd (finfo, input_bfd)
*** 5066,5071 ****
--- 4718,4724 ----
else
indx = finfo->sym_indices[indx];
aux.x_sym.x_fcnary.x_fcn.x_endndx.l = indx;
+
}
}
*************** xcoff_link_input_bfd (finfo, input_bfd)
*** 5080,5085 ****
--- 4733,4739 ----
else
aux.x_sym.x_tagndx.l = symindx;
}
+
}
/* Copy over the line numbers, unless we are stripping
*************** xcoff_link_input_bfd (finfo, input_bfd)
*** 5099,5105 ****
{
asection *enclosing;
unsigned int enc_count;
! bfd_size_type linoff;
struct internal_lineno lin;
o = *csectpp;
--- 4753,4759 ----
{
asection *enclosing;
unsigned int enc_count;
! bfd_signed_vma linoff;
struct internal_lineno lin;
o = *csectpp;
*************** xcoff_link_input_bfd (finfo, input_bfd)
*** 5280,5598 ****
obj_coff_keep_syms (input_bfd) = true;
/* Relocate the contents of each section. */
! for (o = input_bfd->sections; o != NULL; o = o->next)
! {
! bfd_byte *contents;
!
! if (! o->linker_mark)
! {
! /* This section was omitted from the link. */
! continue;
! }
! if ((o->flags & SEC_HAS_CONTENTS) == 0
! || o->_raw_size == 0
! || (o->flags & SEC_IN_MEMORY) != 0)
! continue;
! /* We have set filepos correctly for the sections we created to
! represent csects, so bfd_get_section_contents should work. */
! if (coff_section_data (input_bfd, o) != NULL
! && coff_section_data (input_bfd, o)->contents != NULL)
! contents = coff_section_data (input_bfd, o)->contents;
! else
! {
! if (! bfd_get_section_contents (input_bfd, o, finfo->contents,
! (file_ptr) 0, o->_raw_size))
! return false;
! contents = finfo->contents;
! }
! if ((o->flags & SEC_RELOC) != 0)
! {
! int target_index;
! struct internal_reloc *internal_relocs;
! struct internal_reloc *irel;
! bfd_vma offset;
! struct internal_reloc *irelend;
! struct xcoff_link_hash_entry **rel_hash;
! long r_symndx;
!
! /* Read in the relocs. */
! target_index = o->output_section->target_index;
! internal_relocs = (xcoff_read_internal_relocs
! (input_bfd, o, false, finfo->external_relocs,
! true,
! (finfo->section_info[target_index].relocs
! + o->output_section->reloc_count)));
! if (internal_relocs == NULL)
! return false;
! /* Call processor specific code to relocate the section
! contents. */
! if (! bfd_coff_relocate_section (output_bfd, finfo->info,
! input_bfd, o,
! contents,
! internal_relocs,
! finfo->internal_syms,
! xcoff_data (input_bfd)->csects))
! return false;
! offset = o->output_section->vma + o->output_offset - o->vma;
! irel = internal_relocs;
! irelend = irel + o->reloc_count;
! rel_hash = (finfo->section_info[target_index].rel_hashes
! + o->output_section->reloc_count);
! for (; irel < irelend; irel++, rel_hash++)
! {
! struct xcoff_link_hash_entry *h = NULL;
! struct internal_ldrel ldrel;
! boolean quiet;
! *rel_hash = NULL;
! /* Adjust the reloc address and symbol index. */
! irel->r_vaddr += offset;
! r_symndx = irel->r_symndx;
! 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)
! {
! if (h != NULL
! && h->smclas != XMC_TD
! && (irel->r_type == R_TOC
! || irel->r_type == R_GL
! || irel->r_type == R_TCL
! || irel->r_type == R_TRL
! || irel->r_type == R_TRLA))
! {
! /* This is a TOC relative reloc with a symbol
! attached. The symbol should be the one which
! this reloc is for. We want to make this
! reloc against the TOC address of the symbol,
! not the symbol itself. */
! BFD_ASSERT (h->toc_section != NULL);
! BFD_ASSERT ((h->flags & XCOFF_SET_TOC) == 0);
! if (h->u.toc_indx != -1)
! irel->r_symndx = h->u.toc_indx;
! else
! {
! struct xcoff_toc_rel_hash *n;
! struct xcoff_link_section_info *si;
! n = ((struct xcoff_toc_rel_hash *)
! bfd_alloc (finfo->output_bfd,
! sizeof (struct xcoff_toc_rel_hash)));
! if (n == NULL)
! return false;
! si = finfo->section_info + target_index;
! n->next = si->toc_rel_hashes;
! n->h = h;
! n->rel = irel;
! si->toc_rel_hashes = n;
! }
! }
! else if (h != NULL)
! {
! /* This is a global symbol. */
! if (h->indx >= 0)
! irel->r_symndx = h->indx;
! else
! {
! /* This symbol is being written at the end
! of the file, and we do not yet know the
! symbol index. We save the pointer to the
! hash table entry in the rel_hash list.
! We set the indx field to -2 to indicate
! that this symbol must not be stripped. */
! *rel_hash = h;
! h->indx = -2;
! }
! }
! else
! {
! long indx;
! indx = finfo->sym_indices[r_symndx];
! if (indx == -1)
! {
! struct internal_syment *is;
! /* Relocations against a TC0 TOC anchor are
! automatically transformed to be against
! the TOC anchor in the output file. */
! is = finfo->internal_syms + r_symndx;
! if (is->n_sclass == C_HIDEXT
! && is->n_numaux > 0)
! {
! PTR auxptr;
! union internal_auxent aux;
! auxptr = ((PTR)
! (((bfd_byte *)
! obj_coff_external_syms (input_bfd))
! + ((r_symndx + is->n_numaux)
! * isymesz)));
! bfd_coff_swap_aux_in (input_bfd, auxptr,
! is->n_type, is->n_sclass,
! is->n_numaux - 1,
! is->n_numaux,
! (PTR) &aux);
! if (SMTYP_SMTYP (aux.x_csect.x_smtyp) == XTY_SD
! && aux.x_csect.x_smclas == XMC_TC0)
! indx = finfo->toc_symindx;
! }
! }
! if (indx != -1)
! irel->r_symndx = indx;
! else
! {
! struct internal_syment *is;
! const char *name;
! char buf[SYMNMLEN + 1];
!
! /* This reloc is against a symbol we are
! stripping. It would be possible to handle
! this case, but I don't think it's worth it. */
! is = finfo->internal_syms + r_symndx;
!
! name = (_bfd_coff_internal_syment_name
! (input_bfd, is, buf));
! if (name == NULL)
! return false;
! if (! ((*finfo->info->callbacks->unattached_reloc)
! (finfo->info, name, input_bfd, o,
! irel->r_vaddr)))
! return false;
! }
! }
! }
! quiet = false;
! switch (irel->r_type)
! {
! default:
! if (h == NULL
! || h->root.type == bfd_link_hash_defined
! || h->root.type == bfd_link_hash_defweak
! || h->root.type == bfd_link_hash_common)
! break;
! /* Fall through. */
! case R_POS:
! case R_NEG:
! case R_RL:
! case R_RLA:
! /* This reloc needs to be copied into the .loader
! section. */
! ldrel.l_vaddr = irel->r_vaddr;
! if (r_symndx == -1)
! ldrel.l_symndx = -1;
! else if (h == NULL
! || (h->root.type == bfd_link_hash_defined
! || h->root.type == bfd_link_hash_defweak
! || h->root.type == bfd_link_hash_common))
! {
! asection *sec;
! if (h == NULL)
! sec = xcoff_data (input_bfd)->csects[r_symndx];
! else if (h->root.type == bfd_link_hash_common)
! sec = h->root.u.c.p->section;
! else
! sec = h->root.u.def.section;
! sec = sec->output_section;
! if (strcmp (sec->name, ".text") == 0)
! ldrel.l_symndx = 0;
! else if (strcmp (sec->name, ".data") == 0)
! ldrel.l_symndx = 1;
! else if (strcmp (sec->name, ".bss") == 0)
! ldrel.l_symndx = 2;
! else
! {
! (*_bfd_error_handler)
! (_("%s: loader reloc in unrecognized section `%s'"),
! bfd_get_filename (input_bfd),
! sec->name);
! bfd_set_error (bfd_error_nonrepresentable_section);
! return false;
! }
! }
! else
! {
! 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"),
! bfd_get_filename (input_bfd),
! h->root.root.string);
! bfd_set_error (bfd_error_bad_value);
! return false;
! }
! ldrel.l_symndx = h->ldindx;
! }
! 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
! && ! quiet)
! {
! (*_bfd_error_handler)
! (_("%s: loader reloc in read-only section %s"),
! bfd_get_filename (input_bfd),
! bfd_get_section_name (finfo->output_bfd,
! o->output_section));
! bfd_set_error (bfd_error_invalid_operation);
return false;
! }
! xcoff_swap_ldrel_out (output_bfd, &ldrel,
! finfo->ldrel);
! BFD_ASSERT (sizeof (struct external_ldrel) == LDRELSZ);
! ++finfo->ldrel;
! break;
! case R_TOC:
! case R_GL:
! case R_TCL:
! case R_TRL:
! case R_TRLA:
! /* We should never need a .loader reloc for a TOC
! relative reloc. */
! break;
! }
! }
! o->output_section->reloc_count += o->reloc_count;
! }
! /* Write out the modified section contents. */
! if (! bfd_set_section_contents (output_bfd, o->output_section,
! contents, o->output_offset,
! (o->_cooked_size != 0
! ? o->_cooked_size
! : o->_raw_size)))
! return false;
}
obj_coff_keep_syms (input_bfd) = keep_syms;
if (! finfo->info->keep_memory)
--- 4934,5251 ----
obj_coff_keep_syms (input_bfd) = true;
/* Relocate the contents of each section. */
! for (o = input_bfd->sections; o != NULL; o = o->next) {
!
! bfd_byte *contents;
!
! if (! o->linker_mark){
! /* This section was omitted from the link. */
! continue;
! }
!
! if ((o->flags & SEC_HAS_CONTENTS) == 0
! || o->_raw_size == 0
! || (o->flags & SEC_IN_MEMORY) != 0)
! continue;
!
! /* We have set filepos correctly for the sections we created to
! represent csects, so bfd_get_section_contents should work. */
! if (coff_section_data (input_bfd, o) != NULL
! && coff_section_data (input_bfd, o)->contents != NULL)
! contents = coff_section_data (input_bfd, o)->contents;
! else {
! if (! bfd_get_section_contents (input_bfd, o, finfo->contents,
! (file_ptr) 0, o->_raw_size))
! return false;
! contents = finfo->contents;
! }
! if ((o->flags & SEC_RELOC) != 0) {
! int target_index;
! struct internal_reloc *internal_relocs;
! struct internal_reloc *irel;
! bfd_vma offset;
! struct internal_reloc *irelend;
! struct xcoff_link_hash_entry **rel_hash;
! long r_symndx;
!
! /* Read in the relocs. */
! target_index = o->output_section->target_index;
! internal_relocs = (xcoff_read_internal_relocs
! (input_bfd, o, false, finfo->external_relocs,
! true,
! (finfo->section_info[target_index].relocs
! + o->output_section->reloc_count)));
! if (internal_relocs == NULL)
! return false;
! /* Call processor specific code to relocate the section
! contents. */
! if (! bfd_coff_relocate_section (output_bfd, finfo->info,
! input_bfd, o,
! contents,
! internal_relocs,
! finfo->internal_syms,
! xcoff_data (input_bfd)->csects))
! return false;
! offset = o->output_section->vma + o->output_offset - o->vma;
! irel = internal_relocs;
! irelend = irel + o->reloc_count;
! rel_hash = (finfo->section_info[target_index].rel_hashes
! + o->output_section->reloc_count);
! for (; irel < irelend; irel++, rel_hash++) {
! struct xcoff_link_hash_entry *h = NULL;
! struct internal_ldrel ldrel;
! boolean quiet;
! *rel_hash = NULL;
! /* Adjust the reloc address and symbol index. */
! irel->r_vaddr += offset;
! r_symndx = irel->r_symndx;
! 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)
! {
! if (h != NULL
! && h->smclas != XMC_TD
! && (irel->r_type == R_TOC
! || irel->r_type == R_GL
! || irel->r_type == R_TCL
! || irel->r_type == R_TRL
! || irel->r_type == R_TRLA))
! {
! /* This is a TOC relative reloc with a symbol
! attached. The symbol should be the one which
! this reloc is for. We want to make this
! reloc against the TOC address of the symbol,
! not the symbol itself. */
! BFD_ASSERT (h->toc_section != NULL);
! BFD_ASSERT ((h->flags & XCOFF_SET_TOC) == 0);
! if (h->u.toc_indx != -1)
! irel->r_symndx = h->u.toc_indx;
! else
! {
! struct xcoff_toc_rel_hash *n;
! struct xcoff_link_section_info *si;
! n = ((struct xcoff_toc_rel_hash *)
! bfd_alloc (finfo->output_bfd,
! sizeof (struct xcoff_toc_rel_hash)));
! if (n == NULL)
! return false;
! si = finfo->section_info + target_index;
! n->next = si->toc_rel_hashes;
! n->h = h;
! n->rel = irel;
! si->toc_rel_hashes = n;
! }
! }
! else if (h != NULL)
! {
! /* This is a global symbol. */
! if (h->indx >= 0)
! irel->r_symndx = h->indx;
! else
! {
! /* This symbol is being written at the end
! of the file, and we do not yet know the
! symbol index. We save the pointer to the
! hash table entry in the rel_hash list.
! We set the indx field to -2 to indicate
! that this symbol must not be stripped. */
! *rel_hash = h;
! h->indx = -2;
! }
! }
! else
! {
! long indx;
! indx = finfo->sym_indices[r_symndx];
! if (indx == -1)
! {
! struct internal_syment *is;
! /* Relocations against a TC0 TOC anchor are
! automatically transformed to be against
! the TOC anchor in the output file. */
! is = finfo->internal_syms + r_symndx;
! if (is->n_sclass == C_HIDEXT
! && is->n_numaux > 0)
! {
! PTR auxptr;
! union internal_auxent aux;
! auxptr = ((PTR)
! (((bfd_byte *)
! obj_coff_external_syms (input_bfd))
! + ((r_symndx + is->n_numaux)
! * isymesz)));
! bfd_coff_swap_aux_in (input_bfd, auxptr,
! is->n_type, is->n_sclass,
! is->n_numaux - 1,
! is->n_numaux,
! (PTR) &aux);
! if (SMTYP_SMTYP (aux.x_csect.x_smtyp) == XTY_SD
! && aux.x_csect.x_smclas == XMC_TC0)
! indx = finfo->toc_symindx;
! }
! }
! if (indx != -1)
! irel->r_symndx = indx;
! else
! {
! struct internal_syment *is;
! const char *name;
! char buf[SYMNMLEN + 1];
! /* This reloc is against a symbol we are
! stripping. It would be possible to handle
! this case, but I don't think it's worth it. */
! is = finfo->internal_syms + r_symndx;
! name = (_bfd_coff_internal_syment_name
! (input_bfd, is, buf));
! if (name == NULL)
! return false;
! if (! ((*finfo->info->callbacks->unattached_reloc)
! (finfo->info, name, input_bfd, o,
! irel->r_vaddr)))
return false;
! }
! }
! }
! quiet = false;
! switch (irel->r_type)
! {
! default:
! if (h == NULL
! || h->root.type == bfd_link_hash_defined
! || h->root.type == bfd_link_hash_defweak
! || h->root.type == bfd_link_hash_common)
! break;
! /* Fall through. */
! case R_POS:
! case R_NEG:
! case R_RL:
! case R_RLA:
! /* This reloc needs to be copied into the .loader
! section. */
! ldrel.l_vaddr = irel->r_vaddr;
! if (r_symndx == -1)
! ldrel.l_symndx = -1;
! else if (h == NULL
! || (h->root.type == bfd_link_hash_defined
! || h->root.type == bfd_link_hash_defweak
! || h->root.type == bfd_link_hash_common))
! {
! asection *sec;
! if (h == NULL)
! sec = xcoff_data (input_bfd)->csects[r_symndx];
! else if (h->root.type == bfd_link_hash_common)
! sec = h->root.u.c.p->section;
! else
! sec = h->root.u.def.section;
! sec = sec->output_section;
!
! if (strcmp (sec->name, ".text") == 0)
! ldrel.l_symndx = 0;
! else if (strcmp (sec->name, ".data") == 0)
! ldrel.l_symndx = 1;
! else if (strcmp (sec->name, ".bss") == 0)
! ldrel.l_symndx = 2;
! else
! {
! (*_bfd_error_handler)
! (_("%s: loader reloc in unrecognized section `%s'"),
! bfd_get_filename (input_bfd),
! sec->name);
! bfd_set_error (bfd_error_nonrepresentable_section);
! return false;
! }
! }
! else
! {
! 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"),
! bfd_get_filename (input_bfd),
! h->root.root.string);
! bfd_set_error (bfd_error_bad_value);
! return false;
! }
! ldrel.l_symndx = h->ldindx;
! }
! 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
! && ! quiet)
! {
! (*_bfd_error_handler)
! (_("%s: loader reloc in read-only section %s"),
! bfd_get_filename (input_bfd),
! bfd_get_section_name (finfo->output_bfd,
! o->output_section));
! bfd_set_error (bfd_error_invalid_operation);
! return false;
! }
! bfd_xcoff_swap_ldrel_out (output_bfd, &ldrel,
! finfo->ldrel);
! finfo->ldrel += bfd_xcoff_ldrelsz(output_bfd);
! break;
!
! case R_TOC:
! case R_GL:
! case R_TCL:
! case R_TRL:
! case R_TRLA:
! /* We should never need a .loader reloc for a TOC
! relative reloc. */
! break;
! }
! }
!
! o->output_section->reloc_count += o->reloc_count;
}
+ /* Write out the modified section contents. */
+ if (! bfd_set_section_contents (output_bfd, o->output_section,
+ contents, o->output_offset,
+ (o->_cooked_size != 0
+ ? o->_cooked_size
+ : o->_raw_size)))
+ return false;
+ }
+
obj_coff_keep_syms (input_bfd) = keep_syms;
if (! finfo->info->keep_memory)
*************** xcoff_link_input_bfd (finfo, input_bfd)
*** 5609,5614 ****
--- 5262,5268 ----
/* Write out a non-XCOFF global symbol. */
+
static boolean
xcoff_write_global_symbol (h, p)
struct xcoff_link_hash_entry *h;
*************** xcoff_write_global_symbol (h, p)
*** 5619,5624 ****
--- 5273,5279 ----
bfd_byte *outsym;
struct internal_syment isym;
union internal_auxent aux;
+ boolean result;
output_bfd = finfo->output_bfd;
outsym = finfo->outsyms;
*************** xcoff_write_global_symbol (h, p)
*** 5629,5725 ****
return true;
/* If we need a .loader section entry, write it out. */
! if (h->ldsym != NULL)
! {
! struct internal_ldsym *ldsym;
! bfd *impbfd;
!
! ldsym = h->ldsym;
! if (h->root.type == bfd_link_hash_undefined
! || h->root.type == bfd_link_hash_undefweak)
! {
! ldsym->l_value = 0;
! ldsym->l_scnum = N_UNDEF;
! ldsym->l_smtype = XTY_ER;
! impbfd = h->root.u.undef.abfd;
! }
! else if (h->root.type == bfd_link_hash_defined
! || h->root.type == bfd_link_hash_defweak)
! {
! asection *sec;
! sec = h->root.u.def.section;
! ldsym->l_value = (sec->output_section->vma
! + sec->output_offset
! + h->root.u.def.value);
! ldsym->l_scnum = sec->output_section->target_index;
! ldsym->l_smtype = XTY_SD;
! impbfd = sec->owner;
! }
! else
! abort ();
! if (((h->flags & XCOFF_DEF_REGULAR) == 0
! && (h->flags & XCOFF_DEF_DYNAMIC) != 0)
! || (h->flags & XCOFF_IMPORT) != 0)
! ldsym->l_smtype |= L_IMPORT;
! if (((h->flags & XCOFF_DEF_REGULAR) != 0
! && (h->flags & XCOFF_DEF_DYNAMIC) != 0)
! || (h->flags & XCOFF_EXPORT) != 0)
! ldsym->l_smtype |= L_EXPORT;
! if ((h->flags & XCOFF_ENTRY) != 0)
! ldsym->l_smtype |= L_ENTRY;
! ldsym->l_smclas = h->smclas;
! if (ldsym->l_ifile == (bfd_size_type) -1)
! ldsym->l_ifile = 0;
! else if (ldsym->l_ifile == 0)
! {
! if ((ldsym->l_smtype & L_IMPORT) == 0)
! ldsym->l_ifile = 0;
! else if (impbfd == NULL)
! ldsym->l_ifile = 0;
! else
! {
! BFD_ASSERT (impbfd->xvec == output_bfd->xvec);
! ldsym->l_ifile = xcoff_data (impbfd)->import_file_id;
! }
! }
! ldsym->l_parm = 0;
! BFD_ASSERT (h->ldindx >= 0);
! BFD_ASSERT (LDSYMSZ == sizeof (struct external_ldsym));
! xcoff_swap_ldsym_out (output_bfd, ldsym, finfo->ldsym + h->ldindx -
3);
! h->ldsym = NULL;
}
/* If this symbol needs global linkage code, write it out. */
! if (h->root.type == bfd_link_hash_defined
! && (h->root.u.def.section
! == xcoff_hash_table (finfo->info)->linkage_section))
! {
! bfd_byte *p;
! bfd_vma tocoff;
! unsigned int i;
! p = h->root.u.def.section->contents + h->root.u.def.value;
! /* The first instruction in the global linkage code loads a
! specific TOC element. */
! tocoff = (h->descriptor->toc_section->output_section->vma
! + h->descriptor->toc_section->output_offset
! - xcoff_data (output_bfd)->toc);
! if ((h->descriptor->flags & XCOFF_SET_TOC) != 0)
! tocoff += h->descriptor->u.toc_offset;
! bfd_put_32 (output_bfd, XCOFF_GLINK_FIRST | (tocoff & 0xffff), p);
! for (i = 0, p += 4;
! i < sizeof xcoff_glink_code / sizeof xcoff_glink_code[0];
! i++, p += 4)
! bfd_put_32 (output_bfd, xcoff_glink_code[i], p);
}
/* If we created a TOC entry for this symbol, write out the required
relocs. */
--- 5284,5406 ----
return true;
/* If we need a .loader section entry, write it out. */
! if (h->ldsym != NULL) {
! struct internal_ldsym *ldsym;
! bfd *impbfd;
!
! ldsym = h->ldsym;
!
! if (h->root.type == bfd_link_hash_undefined ||
! h->root.type == bfd_link_hash_undefweak) {
!
! ldsym->l_value = 0;
! ldsym->l_scnum = N_UNDEF;
! ldsym->l_smtype = XTY_ER;
! impbfd = h->root.u.undef.abfd;
! } else if (h->root.type == bfd_link_hash_defined ||
! h->root.type == bfd_link_hash_defweak) {
! asection *sec;
!
! sec = h->root.u.def.section;
! ldsym->l_value = (sec->output_section->vma
! + sec->output_offset
! + h->root.u.def.value);
! ldsym->l_scnum = sec->output_section->target_index;
! ldsym->l_smtype = XTY_SD;
! impbfd = sec->owner;
! } else {
! abort ();
! }
! if (((h->flags & XCOFF_DEF_REGULAR) == 0 &&
! (h->flags & XCOFF_DEF_DYNAMIC) != 0) ||
! (h->flags & XCOFF_IMPORT) != 0) {
! ldsym->l_smtype |= L_IMPORT;
! }
! if (((h->flags & XCOFF_DEF_REGULAR) != 0 &&
! (h->flags & XCOFF_DEF_DYNAMIC) != 0) ||
! (h->flags & XCOFF_EXPORT) != 0) {
! ldsym->l_smtype |= L_EXPORT;
! }
! if ((h->flags & XCOFF_ENTRY) != 0) {
! ldsym->l_smtype |= L_ENTRY;
! }
! if ((h->flags & XCOFF_RTINIT) != 0) {
! ldsym->l_smtype = XTY_SD;
}
+ ldsym->l_smclas = h->smclas;
+
+ if (ldsym->l_ifile == (bfd_size_type) -1) {
+ ldsym->l_ifile = 0;
+
+ } else if (ldsym->l_ifile == 0) {
+ if ((ldsym->l_smtype & L_IMPORT) == 0) {
+ ldsym->l_ifile = 0;
+ } else if (impbfd == NULL) {
+ ldsym->l_ifile = 0;
+ } else {
+ BFD_ASSERT (impbfd->xvec == output_bfd->xvec);
+ ldsym->l_ifile = xcoff_data (impbfd)->import_file_id;
+ }
+ }
+
+ ldsym->l_parm = 0;
+
+ BFD_ASSERT (h->ldindx >= 0);
+
+ bfd_xcoff_swap_ldsym_out (output_bfd, ldsym, finfo->ldsym +
+ (h->ldindx - 3) *
+ bfd_xcoff_ldsymsz(finfo->output_bfd));
+ h->ldsym = NULL;
+ }
+
/* If this symbol needs global linkage code, write it out. */
! if (h->root.type == bfd_link_hash_defined &&
! (h->root.u.def.section ==
! xcoff_hash_table (finfo->info)->linkage_section)) {
! bfd_byte *p;
! bfd_vma tocoff;
! unsigned int i;
!
! p = h->root.u.def.section->contents + h->root.u.def.value;
! /* The first instruction in the global linkage code loads a
! specific TOC element. */
! tocoff = (h->descriptor->toc_section->output_section->vma
! + h->descriptor->toc_section->output_offset
! - xcoff_data (output_bfd)->toc);
!
! if ((h->descriptor->flags & XCOFF_SET_TOC) != 0) {
! 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 rest are just outputted
! * raw.
! */
! bfd_put_32 (output_bfd,
! bfd_xcoff_glink_code(output_bfd, 0) | (tocoff & 0xffff), p);
!
! /*
! * Start with i == 1 to get past the first instruction done above
! * The /4 is because the glink code is in bytes and we are going 4
! * at a pop
! */
! for (i = 1; i < bfd_xcoff_glink_code_size(output_bfd) / 4; i++) {
! bfd_put_32 (output_bfd, bfd_xcoff_glink_code(output_bfd, i),
! &p[4 * i]);
}
+ }
/* If we created a TOC entry for this symbol, write out the required
relocs. */
*************** xcoff_write_global_symbol (h, p)
*** 5740,5808 ****
irel->r_vaddr = (osec->vma
+ tocsec->output_offset
+ h->u.toc_offset);
! if (h->indx >= 0)
irel->r_symndx = h->indx;
! else
! {
! h->indx = -2;
! irel->r_symndx = obj_raw_syment_count (output_bfd);
! }
irel->r_type = R_POS;
- irel->r_size = 31;
finfo->section_info[oindx].rel_hashes[osec->reloc_count] = NULL;
++osec->reloc_count;
- BFD_ASSERT (h->ldindx >= 0);
ldrel.l_vaddr = irel->r_vaddr;
ldrel.l_symndx = h->ldindx;
! ldrel.l_rtype = (31 << 8) | R_POS;
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)
--- 5421,5502 ----
irel->r_vaddr = (osec->vma
+ tocsec->output_offset
+ h->u.toc_offset);
!
!
! if (h->indx >= 0) {
irel->r_symndx = h->indx;
! } else {
! h->indx = -2;
! irel->r_symndx = obj_raw_syment_count (output_bfd);
! }
!
! BFD_ASSERT (h->ldindx >= 0);
!
! /*
! * Initialize the aux union here instead of closer to when it is
! * written out below because the length of the csect depends on
! * whether the output is 32 or 64 bit
! */
! memset (&iraux, 0, sizeof iraux);
! iraux.x_csect.x_smtyp = XTY_SD;
! /* iraux.x_csect.x_scnlen.l = 4 or 8, see below */
! iraux.x_csect.x_smclas = XMC_TC;
!
!
! /*
! * 32 bit uses a 32 bit R_POS to do the relocations
! * 64 bit uses a 64 bit R_POS to do the relocations
! *
! * Also needs to change the csect size : 4 for 32 bit, 8 for 64 bit
! *
! * Which one is determined by the backend
! */
! if (bfd_xcoff_is_xcoff64(output_bfd)) {
! irel->r_size = 63;
! iraux.x_csect.x_scnlen.l = 8;
! } else if (bfd_xcoff_is_xcoff32(output_bfd)) {
! irel->r_size = 31;
! iraux.x_csect.x_scnlen.l = 4;
! } else {
! return false;
! }
irel->r_type = R_POS;
finfo->section_info[oindx].rel_hashes[osec->reloc_count] = NULL;
++osec->reloc_count;
ldrel.l_vaddr = irel->r_vaddr;
ldrel.l_symndx = h->ldindx;
! ldrel.l_rtype = (irel->r_size << 8) | R_POS;
ldrel.l_rsecnm = oindx;
! bfd_xcoff_swap_ldrel_out (output_bfd, &ldrel, finfo->ldrel);
! finfo->ldrel += bfd_xcoff_ldrelsz(output_bfd);
! /* We need to emit a symbol to define a csect which holds the reloc.
*/
! if (finfo->info->strip != strip_all) {
! result = bfd_xcoff_put_symbol_name (output_bfd, finfo->strtab, &irsym,
! h->root.root.string);
! if (false == result) {
! return false;
! }
! 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);
!
! /* note : iraux is initialized above */
! 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)
*************** xcoff_write_global_symbol (h, p)
*** 5821,5830 ****
}
}
! /* If this symbol is a specially defined function descriptor, write
! it out. The first word is the address of the function code
! itself, the second word is the address of the TOC, and the third
! word is zero. */
if ((h->flags & XCOFF_DESCRIPTOR) != 0
&& h->root.type == bfd_link_hash_defined
&& (h->root.u.def.section
--- 5515,5532 ----
}
}
! /*
! * If this symbol is a specially defined function descriptor, write
! * it out. The first word is the address of the function code
! * itself, the second word is the address of the TOC, and the third
! * word is zero.
! *
! * 32 bit vs 64 bit
! * The addresses for the 32 bit will take 4 bytes and the addresses
! * for 64 bit will take 8 bytes. Similar for the relocs. This type
! * of logic was also done above to create a TOC entry in
! * xcoff_write_global_symbol
! */
if ((h->flags & XCOFF_DESCRIPTOR) != 0
&& h->root.type == bfd_link_hash_defined
&& (h->root.u.def.section
*************** xcoff_write_global_symbol (h, p)
*** 5839,5844 ****
--- 5541,5557 ----
struct internal_reloc *irel;
struct internal_ldrel ldrel;
asection *tsec;
+ unsigned int reloc_size, byte_size;
+
+ if (bfd_xcoff_is_xcoff64(output_bfd)) {
+ reloc_size = 63;
+ byte_size = 8;
+ } else if (bfd_xcoff_is_xcoff32(output_bfd)) {
+ reloc_size = 31;
+ byte_size = 4;
+ } else {
+ return false;
+ }
sec = h->root.u.def.section;
osec = sec->output_section;
*************** xcoff_write_global_symbol (h, p)
*** 5850,5860 ****
&& (hentry->root.type == bfd_link_hash_defined
|| hentry->root.type == bfd_link_hash_defweak));
esec = hentry->root.u.def.section;
- bfd_put_32 (output_bfd,
- (esec->output_section->vma
- + esec->output_offset
- + hentry->root.u.def.value),
- p);
irel = finfo->section_info[oindx].relocs + osec->reloc_count;
irel->r_vaddr = (osec->vma
--- 5563,5568 ----
*************** xcoff_write_global_symbol (h, p)
*** 5862,5868 ****
+ h->root.u.def.value);
irel->r_symndx = esec->output_section->target_index;
irel->r_type = R_POS;
! irel->r_size = 31;
finfo->section_info[oindx].rel_hashes[osec->reloc_count] = NULL;
++osec->reloc_count;
--- 5570,5576 ----
+ h->root.u.def.value);
irel->r_symndx = esec->output_section->target_index;
irel->r_type = R_POS;
! irel->r_size = reloc_size;
finfo->section_info[oindx].rel_hashes[osec->reloc_count] = NULL;
++osec->reloc_count;
*************** xcoff_write_global_symbol (h, p)
*** 5882,5894 ****
bfd_set_error (bfd_error_nonrepresentable_section);
return false;
}
! ldrel.l_rtype = (31 << 8) | R_POS;
ldrel.l_rsecnm = oindx;
! xcoff_swap_ldrel_out (output_bfd, &ldrel, finfo->ldrel);
! ++finfo->ldrel;
!
! bfd_put_32 (output_bfd, xcoff_data (output_bfd)->toc, p + 4);
tsec = coff_section_from_bfd_index (output_bfd,
xcoff_data (output_bfd)->sntoc);
--- 5590,5627 ----
bfd_set_error (bfd_error_nonrepresentable_section);
return false;
}
! ldrel.l_rtype = (reloc_size << 8) | R_POS;
ldrel.l_rsecnm = oindx;
! bfd_xcoff_swap_ldrel_out (output_bfd, &ldrel, finfo->ldrel);
! finfo->ldrel += bfd_xcoff_ldrelsz(output_bfd);
+ /*
+ * There are three items to write out,
+ * the address of the code
+ * the address of the toc anchor
+ * the environment pointer.
+ * We are ignoring the environment pointer. So set it to zero
+ */
+ if (bfd_xcoff_is_xcoff64(output_bfd)) {
+ bfd_put_64 (output_bfd, (esec->output_section->vma +
+ esec->output_offset +
+ hentry->root.u.def.value), p);
+ bfd_put_64 (output_bfd, xcoff_data (output_bfd)->toc, p + 8);
+ bfd_put_64 (output_bfd, 0, p + 16);
+ } else {
+ /*
+ * 32 bit backend
+ *
+ * This logic was already called above so the error case where
+ * the backend is neither has already been checked
+ */
+ bfd_put_32 (output_bfd, (esec->output_section->vma +
+ esec->output_offset +
+ hentry->root.u.def.value), p);
+ bfd_put_32 (output_bfd, xcoff_data (output_bfd)->toc, p + 4);
+ bfd_put_32 (output_bfd, 0, p + 8);
+ }
+
tsec = coff_section_from_bfd_index (output_bfd,
xcoff_data (output_bfd)->sntoc);
*************** xcoff_write_global_symbol (h, p)
*** 5896,5905 ****
irel->r_vaddr = (osec->vma
+ sec->output_offset
+ h->root.u.def.value
! + 4);
irel->r_symndx = tsec->output_section->target_index;
irel->r_type = R_POS;
! irel->r_size = 31;
finfo->section_info[oindx].rel_hashes[osec->reloc_count] = NULL;
++osec->reloc_count;
--- 5629,5638 ----
irel->r_vaddr = (osec->vma
+ sec->output_offset
+ h->root.u.def.value
! + byte_size);
irel->r_symndx = tsec->output_section->target_index;
irel->r_type = R_POS;
! irel->r_size = reloc_size;
finfo->section_info[oindx].rel_hashes[osec->reloc_count] = NULL;
++osec->reloc_count;
*************** xcoff_write_global_symbol (h, p)
*** 5919,5928 ****
bfd_set_error (bfd_error_nonrepresentable_section);
return false;
}
! ldrel.l_rtype = (31 << 8) | R_POS;
ldrel.l_rsecnm = oindx;
! xcoff_swap_ldrel_out (output_bfd, &ldrel, finfo->ldrel);
! ++finfo->ldrel;
}
if (h->indx >= 0 || finfo->info->strip == strip_all)
--- 5652,5661 ----
bfd_set_error (bfd_error_nonrepresentable_section);
return false;
}
! ldrel.l_rtype = (reloc_size << 8) | R_POS;
ldrel.l_rsecnm = oindx;
! bfd_xcoff_swap_ldrel_out (output_bfd, &ldrel, finfo->ldrel);
! finfo->ldrel += bfd_xcoff_ldrelsz(output_bfd);
}
if (h->indx >= 0 || finfo->info->strip == strip_all)
*************** xcoff_write_global_symbol (h, p)
*** 5953,5975 ****
h->indx = obj_raw_syment_count (output_bfd);
! if (strlen (h->root.root.string) <= SYMNMLEN)
! strncpy (isym._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;
! isym._n._n_n._n_zeroes = 0;
! isym._n._n_n._n_offset = STRING_SIZE_SIZE + indx;
! }
if (h->root.type == bfd_link_hash_undefined
|| h->root.type == bfd_link_hash_undefweak)
--- 5686,5696 ----
h->indx = obj_raw_syment_count (output_bfd);
! result = bfd_xcoff_put_symbol_name (output_bfd, finfo->strtab, &isym,
! h->root.root.string);
! if (false == result) {
! return false;
! }
if (h->root.type == bfd_link_hash_undefined
|| h->root.type == bfd_link_hash_undefweak)
*************** xcoff_write_global_symbol (h, p)
*** 6034,6040 ****
outsym += bfd_coff_symesz (output_bfd);
aux.x_csect.x_smclas = h->smclas;
-
bfd_coff_swap_aux_out (output_bfd, (PTR) &aux, T_NULL, isym.n_sclass, 0,
1,
(PTR) outsym);
outsym += bfd_coff_auxesz (output_bfd);
--- 5755,5760 ----
*************** xcoff_write_global_symbol (h, p)
*** 6053,6059 ****
aux.x_csect.x_smtyp = XTY_LD;
aux.x_csect.x_scnlen.l = obj_raw_syment_count (output_bfd);
-
bfd_coff_swap_aux_out (output_bfd, (PTR) &aux, T_NULL, C_EXT, 0, 1,
(PTR) outsym);
outsym += bfd_coff_auxesz (output_bfd);
--- 5773,5778 ----
*************** xcoff_reloc_link_order (output_bfd, finf
*** 6252,6259 ****
ldrel.l_rtype = (irel->r_size << 8) | irel->r_type;
ldrel.l_rsecnm = output_section->target_index;
! xcoff_swap_ldrel_out (output_bfd, &ldrel, finfo->ldrel);
! ++finfo->ldrel;
return true;
}
--- 5971,5978 ----
ldrel.l_rtype = (irel->r_size << 8) | irel->r_type;
ldrel.l_rsecnm = output_section->target_index;
! bfd_xcoff_swap_ldrel_out (output_bfd, &ldrel, finfo->ldrel);
! finfo->ldrel += bfd_xcoff_ldrelsz(output_bfd);
return true;
}
*************** xcoff_sort_relocs (p1, p2)
*** 6276,6630 ****
return 0;
}
- /* This is the relocation function for the RS/6000/POWER/PowerPC.
- This is currently the only processor which uses XCOFF; I hope that
- will never change. */
-
- boolean
- _bfd_ppc_xcoff_relocate_section (output_bfd, info, input_bfd,
- input_section, contents, relocs, syms,
- sections)
- bfd *output_bfd;
- struct bfd_link_info *info;
- bfd *input_bfd;
- asection *input_section;
- bfd_byte *contents;
- struct internal_reloc *relocs;
- struct internal_syment *syms;
- asection **sections;
- {
- struct internal_reloc *rel;
- struct internal_reloc *relend;
-
- rel = relocs;
- relend = rel + input_section->reloc_count;
- for (; rel < relend; rel++)
- {
- long symndx;
- struct xcoff_link_hash_entry *h;
- struct internal_syment *sym;
- bfd_vma addend;
- bfd_vma val;
- struct reloc_howto_struct howto;
- bfd_reloc_status_type rstat;
-
- /* Relocation type R_REF is a special relocation type which is
- merely used to prevent garbage collection from occurring for
- the csect including the symbol which it references. */
- if (rel->r_type == R_REF)
- continue;
-
- symndx = rel->r_symndx;
-
- if (symndx == -1)
- {
- h = NULL;
- sym = NULL;
- addend = 0;
- }
- else
- {
- h = obj_xcoff_sym_hashes (input_bfd)[symndx];
- sym = syms + symndx;
- addend = - sym->n_value;
- }
-
- /* We build the howto information on the fly. */
-
- howto.type = rel->r_type;
- howto.rightshift = 0;
- howto.size = 2;
- howto.bitsize = (rel->r_size & 0x1f) + 1;
- howto.pc_relative = false;
- howto.bitpos = 0;
- if ((rel->r_size & 0x80) != 0)
- howto.complain_on_overflow = complain_overflow_signed;
- else
- howto.complain_on_overflow = complain_overflow_bitfield;
- howto.special_function = NULL;
- howto.name = "internal";
- howto.partial_inplace = true;
- if (howto.bitsize == 32)
- howto.src_mask = howto.dst_mask = 0xffffffff;
- else
- {
- howto.src_mask = howto.dst_mask = (1 << howto.bitsize) - 1;
- if (howto.bitsize == 16)
- howto.size = 1;
- }
- howto.pcrel_offset = false;
-
- val = 0;
- if (h == NULL)
- {
- asection *sec;
-
- if (symndx == -1)
- {
- sec = bfd_abs_section_ptr;
- val = 0;
- }
- else
- {
- sec = sections[symndx];
- /* Hack to make sure we use the right TOC anchor value
- if this reloc is against the TOC anchor. */
- if (sec->name[3] == '0'
- && strcmp (sec->name, ".tc0") == 0)
- val = xcoff_data (output_bfd)->toc;
- else
- val = (sec->output_section->vma
- + sec->output_offset
- + sym->n_value
- - sec->vma);
- }
- }
- else
- {
- if (h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak)
- {
- asection *sec;
- sec = h->root.u.def.section;
- val = (h->root.u.def.value
- + sec->output_section->vma
- + sec->output_offset);
- }
- else if (h->root.type == bfd_link_hash_common)
- {
- asection *sec;
- sec = h->root.u.c.p->section;
- val = (sec->output_section->vma
- + sec->output_offset);
- }
- else if ((h->flags & XCOFF_DEF_DYNAMIC) != 0
- || (h->flags & XCOFF_IMPORT) != 0)
- {
- /* Every symbol in a shared object is defined somewhere. */
- val = 0;
- }
- else if (! info->relocateable)
- {
- if (! ((*info->callbacks->undefined_symbol)
- (info, h->root.root.string, input_bfd, input_section,
- 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;
- }
- }
-
- /* I took the relocation type definitions from two documents:
- the PowerPC AIX Version 4 Application Binary Interface, First
- Edition (April 1992), and the PowerOpen ABI, Big-Endian
- 32-Bit Hardware Implementation (June 30, 1994). Differences
- between the documents are noted below. */
-
- switch (rel->r_type)
- {
- case R_RTB:
- case R_RRTBI:
- case R_RRTBA:
- /* These relocs are defined by the PowerPC ABI to be
- relative branches which use half of the difference
- between the symbol and the program counter. I can't
- quite figure out when this is useful. These relocs are
- not defined by the PowerOpen ABI. */
- default:
- (*_bfd_error_handler)
- (_("%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;
- case R_POS:
- /* Simple positive relocation. */
- break;
- case R_NEG:
- /* Simple negative relocation. */
- val = - val;
- break;
- case R_REL:
- /* Simple PC relative relocation. */
- howto.pc_relative = true;
- break;
- case R_TOC:
- /* TOC relative relocation. The value in the instruction in
- the input file is the offset from the input file TOC to
- the desired location. We want the offset from the final
- TOC to the desired location. We have:
- isym = iTOC + in
- iinsn = in + o
- osym = oTOC + on
- oinsn = on + o
- so we must change insn by on - in.
- */
- case R_GL:
- /* Global linkage relocation. The value of this relocation
- is the address of the entry in the TOC section. */
- case R_TCL:
- /* Local object TOC address. I can't figure out the
- difference between this and case R_GL. */
- case R_TRL:
- /* TOC relative relocation. A TOC relative load instruction
- which may be changed to a load address instruction.
- FIXME: We don't currently implement this optimization. */
- case R_TRLA:
- /* TOC relative relocation. This is a TOC relative load
- address instruction which may be changed to a load
- instruction. FIXME: I don't know if this is the correct
- implementation. */
- if (h != NULL && h->smclas != XMC_TD)
- {
- if (h->toc_section == NULL)
- {
- (*_bfd_error_handler)
- (_("%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);
- return false;
- }
-
- BFD_ASSERT ((h->flags & XCOFF_SET_TOC) == 0);
- val = (h->toc_section->output_section->vma
- + h->toc_section->output_offset);
- }
-
- val = ((val - xcoff_data (output_bfd)->toc)
- - (sym->n_value - xcoff_data (input_bfd)->toc));
- addend = 0;
- break;
- case R_BA:
- /* Absolute branch. We don't want to mess with the lower
- two bits of the instruction. */
- case R_CAI:
- /* The PowerPC ABI defines this as an absolute call which
- may be modified to become a relative call. The PowerOpen
- ABI does not define this relocation type. */
- case R_RBA:
- /* Absolute branch which may be modified to become a
- relative branch. */
- case R_RBAC:
- /* The PowerPC ABI defines this as an absolute branch to a
- fixed address which may be modified to an absolute branch
- to a symbol. The PowerOpen ABI does not define this
- relocation type. */
- case R_RBRC:
- /* The PowerPC ABI defines this as an absolute branch to a
- fixed address which may be modified to a relative branch.
- The PowerOpen ABI does not define this relocation type. */
- howto.src_mask &= ~3;
- howto.dst_mask = howto.src_mask;
- break;
- case R_BR:
- /* Relative branch. We don't want to mess with the lower
- two bits of the instruction. */
- case R_CREL:
- /* The PowerPC ABI defines this as a relative call which may
- be modified to become an absolute call. The PowerOpen
- ABI does not define this relocation type. */
- case R_RBR:
- /* A relative branch which may be modified to become an
- absolute branch. FIXME: We don't implement this,
- although we should for symbols of storage mapping class
- XMC_XO. */
- howto.pc_relative = true;
- howto.src_mask &= ~3;
- howto.dst_mask = howto.src_mask;
- break;
- case R_RL:
- /* The PowerPC AIX ABI describes this as a load which may be
- changed to a load address. The PowerOpen ABI says this
- is the same as case R_POS. */
- break;
- case R_RLA:
- /* The PowerPC AIX ABI describes this as a load address
- which may be changed to a load. The PowerOpen ABI says
- this is the same as R_POS. */
- break;
- }
-
- /* If we see an R_BR or R_RBR reloc which is jumping to global
- linkage code, and it is followed by an appropriate cror nop
- instruction, we replace the cror with lwz r2,20(r1). This
- restores the TOC after the glink code. Contrariwise, if the
- call is followed by a lwz r2,20(r1), but the call is not
- going to global linkage code, we can replace the load with a
- cror. */
- if ((rel->r_type == R_BR || rel->r_type == R_RBR)
- && h != NULL
- && h->root.type == bfd_link_hash_defined
- && (rel->r_vaddr - input_section->vma + 8
- <= input_section->_cooked_size))
- {
- bfd_byte *pnext;
- unsigned long next;
-
- pnext = contents + (rel->r_vaddr - input_section->vma) + 4;
- next = bfd_get_32 (input_bfd, pnext);
-
- /* The _ptrgl function is magic. It is used by the AIX
- compiler to call a function through a pointer. */
- if (h->smclas == XMC_GL
- || strcmp (h->root.root.string, "._ptrgl") == 0)
- {
- if (next == 0x4def7b82 /* cror 15,15,15 */
- || 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, 0x60000000, pnext); /* ori r0,r0,0 */
- }
- }
-
- /* A PC relative reloc includes the section address. */
- if (howto.pc_relative)
- addend += input_section->vma;
-
- rstat = _bfd_final_link_relocate (&howto, input_bfd, input_section,
- contents,
- rel->r_vaddr - input_section->vma,
- val, addend);
-
- switch (rstat)
- {
- default:
- abort ();
- case bfd_reloc_ok:
- break;
- case bfd_reloc_overflow:
- {
- const char *name;
- char buf[SYMNMLEN + 1];
- char howto_name[10];
-
- if (symndx == -1)
- name = "*ABS*";
- else if (h != NULL)
- name = h->root.root.string;
- else
- {
- name = _bfd_coff_internal_syment_name (input_bfd, sym, buf);
- if (name == NULL)
- return false;
- }
- sprintf (howto_name, "0x%02x", rel->r_type);
-
- if (! ((*info->callbacks->reloc_overflow)
- (info, name, howto_name, (bfd_vma) 0, input_bfd,
- input_section, rel->r_vaddr - input_section->vma)))
- return false;
- }
- }
- }
-
- return true;
- }
--- 5995,6000 ----