/* BFD back-end for IBM RS/6000 "XCOFF" files.
- Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001
+ Copyright 1990-1999, 2000, 2001, 2002
Free Software Foundation, Inc.
FIXME: Can someone provide a transliteration of this name into ASCII?
Using the following chars caused a compiler warning on HIUX (so I replaced
extern const bfd_target *_bfd_xcoff_archive_p PARAMS ((bfd *));
extern PTR _bfd_xcoff_read_ar_hdr PARAMS ((bfd *));
extern bfd *_bfd_xcoff_openr_next_archived_file PARAMS ((bfd *, bfd *));
-extern int _bfd_xcoff_generic_stat_arch_elt PARAMS ((bfd *, struct stat *));
+extern int _bfd_xcoff_stat_arch_elt PARAMS ((bfd *, struct stat *));
extern boolean _bfd_xcoff_write_armap
PARAMS ((bfd *, unsigned int, struct orl *, unsigned int, int));
extern boolean _bfd_xcoff_write_archive_contents PARAMS ((bfd *));
#define coff_bfd_is_local_label_name _bfd_xcoff_is_local_label_name
#define coff_bfd_reloc_type_lookup _bfd_xcoff_reloc_type_lookup
#ifdef AIX_CORE
-extern const bfd_target * rs6000coff_core_p ();
-extern boolean rs6000coff_core_file_matches_executable_p ();
+extern const bfd_target * rs6000coff_core_p PARAMS ((bfd *abfd));
+extern boolean rs6000coff_core_file_matches_executable_p
+ PARAMS ((bfd *cbfd, bfd *ebfd));
extern char *rs6000coff_core_file_failing_command PARAMS ((bfd *abfd));
extern int rs6000coff_core_file_failing_signal PARAMS ((bfd *abfd));
#define CORE_FILE_P rs6000coff_core_p
static const char *normalize_filename PARAMS ((bfd *));
static boolean xcoff_write_armap_old
PARAMS ((bfd *, unsigned int, struct orl *, unsigned int, int));
-static boolean xcoff_write_one_armap_big
- PARAMS ((bfd *, struct orl *, unsigned int, unsigned int, unsigned int,
- int, const char *, char *));
static boolean xcoff_write_armap_big
PARAMS ((bfd *, unsigned int, struct orl *, unsigned int, int));
static boolean xcoff_write_archive_contents_old PARAMS ((bfd *));
PARAMS ((bfd *, struct internal_ldhdr *));
static bfd_vma xcoff_loader_reloc_offset
PARAMS ((bfd *, struct internal_ldhdr *));
+static boolean xcoff_generate_rtinit
+ PARAMS((bfd *, const char *, const char *, boolean));
+static boolean do_pad PARAMS((bfd *, unsigned int));
+static boolean do_copy PARAMS((bfd *, bfd *));
+static boolean do_shared_object_padding PARAMS ((bfd *, bfd *, ufile_ptr *, int));
/* We use our own tdata type. Its first field is the COFF tdata type,
so the COFF routines are compatible. */
reloc_howto_type xcoff_howto_table[] =
{
/* Standard 32 bit relocation. */
- HOWTO (0, /* type */
+ HOWTO (R_POS, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
false), /* pcrel_offset */
/* 32 bit relocation, but store negative value. */
- HOWTO (1, /* type */
+ HOWTO (R_NEG, /* type */
0, /* rightshift */
-2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
false), /* pcrel_offset */
/* 32 bit PC relative relocation. */
- HOWTO (2, /* type */
+ HOWTO (R_REL, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
false), /* pcrel_offset */
/* 16 bit TOC relative relocation. */
- HOWTO (3, /* type */
+ HOWTO (R_TOC, /* type */
0, /* rightshift */
1, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
false), /* pcrel_offset */
/* I don't really know what this is. */
- HOWTO (4, /* type */
+ HOWTO (R_RTB, /* type */
1, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
false), /* pcrel_offset */
/* External TOC relative symbol. */
- HOWTO (5, /* type */
+ HOWTO (R_GL, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
false), /* pcrel_offset */
/* Local TOC relative symbol. */
- HOWTO (6, /* type */
+ HOWTO (R_TCL, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
EMPTY_HOWTO (7),
/* Non modifiable absolute branch. */
- HOWTO (8, /* type */
+ HOWTO (R_BA, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
26, /* bitsize */
EMPTY_HOWTO (9),
/* Non modifiable relative branch. */
- HOWTO (0xa, /* type */
+ HOWTO (R_BR, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
26, /* bitsize */
EMPTY_HOWTO (0xb),
/* Indirect load. */
- HOWTO (0xc, /* type */
+ HOWTO (R_RL, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
false), /* pcrel_offset */
/* Load address. */
- HOWTO (0xd, /* type */
+ HOWTO (R_RLA, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
EMPTY_HOWTO (0xe),
/* Non-relocating reference. */
- HOWTO (0xf, /* type */
+ HOWTO (R_REF, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
EMPTY_HOWTO (0x11),
/* TOC relative indirect load. */
- HOWTO (0x12, /* type */
+ HOWTO (R_TRL, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
false), /* pcrel_offset */
/* TOC relative load address. */
- HOWTO (0x13, /* type */
+ HOWTO (R_TRLA, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
false), /* pcrel_offset */
/* Modifiable relative branch. */
- HOWTO (0x14, /* type */
+ HOWTO (R_RRTBI, /* type */
1, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
false), /* pcrel_offset */
/* Modifiable absolute branch. */
- HOWTO (0x15, /* type */
+ HOWTO (R_RRTBA, /* type */
1, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
false), /* pcrel_offset */
/* Modifiable call absolute indirect. */
- HOWTO (0x16, /* type */
+ HOWTO (R_CAI, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
false), /* pcrel_offset */
/* Modifiable call relative. */
- HOWTO (0x17, /* type */
+ HOWTO (R_CREL, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
false), /* pcrel_offset */
/* Modifiable branch absolute. */
- HOWTO (0x18, /* type */
+ HOWTO (R_RBA, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
26, /* bitsize */
false), /* pcrel_offset */
/* Modifiable branch absolute. */
- HOWTO (0x19, /* type */
+ HOWTO (R_RBAC, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
false), /* pcrel_offset */
/* Modifiable branch relative. */
- HOWTO (0x1a, /* type */
+ HOWTO (R_RBR, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
26, /* bitsize */
false), /* pcrel_offset */
/* Modifiable branch absolute. */
- HOWTO (0x1b, /* type */
+ HOWTO (R_RBRC, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
0xffff, /* dst_mask */
false), /* pcrel_offset */
- HOWTO (0, /* type */
+ HOWTO (R_POS, /* type */
0, /* rightshift */
4, /* size (0 = byte, 1 = short, 2 = long) */
64, /* bitsize */
true, /* partial_inplace */
MINUS_ONE, /* src_mask */
MINUS_ONE, /* dst_mask */
- false) /* pcrel_offset */
+ false), /* pcrel_offset */
+ /* 16 bit Non modifiable absolute branch. */
+ HOWTO (R_BA, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_BA", /* name */
+ true, /* partial_inplace */
+ 0xfffc, /* src_mask */
+ 0xfffc, /* dst_mask */
+ false), /* pcrel_offset */
};
void
{
case BFD_RELOC_PPC_B26:
return &xcoff_howto_table[0xa];
+ case BFD_RELOC_PPC_BA16:
+ return &xcoff_howto_table[0x1d];
case BFD_RELOC_PPC_BA26:
return &xcoff_howto_table[8];
case BFD_RELOC_PPC_TOC16:
/* XCOFF archives use this as a magic string. Note that both strings
have the same length. */
+/* Set the magic for archive. */
+boolean
+bfd_xcoff_ar_archive_set_magic (abfd, magic)
+ bfd *abfd ATTRIBUTE_UNUSED;
+ char *magic ATTRIBUTE_UNUSED;
+{
+ /* Not supported yet. */
+ return false;
+ /* bfd_xcoff_archive_set_magic (abfd, magic); */
+}
/* Read in the armap of an XCOFF archive. */
/* Stat an element in an XCOFF archive. */
int
-_bfd_xcoff_generic_stat_arch_elt (abfd, s)
+_bfd_xcoff_stat_arch_elt (abfd, s)
bfd *abfd;
struct stat *s;
{
return -1;
}
- if (! xcoff_big_format_p (abfd))
+ if (! xcoff_big_format_p (abfd->my_archive))
{
struct xcoff_ar_hdr *hdrp = arch_xhdr (abfd);
memset (&hdr, 0, sizeof hdr);
sprintf (hdr.size, "%ld", (long) (4 + orl_count * 4 + stridx));
sprintf (hdr.nextoff, "%d", 0);
- memcpy (hdr.prevoff, xcoff_ardata (abfd)->memoff, 12);
+ memcpy (hdr.prevoff, xcoff_ardata (abfd)->memoff, XCOFFARMAG_ELEMENT_SIZE);
sprintf (hdr.date, "%d", 0);
sprintf (hdr.uid, "%d", 0);
sprintf (hdr.gid, "%d", 0);
return true;
}
-/* Write a single armap in the big format. */
+static char buff20[XCOFFARMAGBIG_ELEMENT_SIZE + 1];
+#define FMT20 "%-20lld"
+#define FMT12 "%-12d"
+#define FMT12_OCTAL "%-12o"
+#define FMT4 "%-4d"
+#define PRINT20(d, v) \
+ sprintf (buff20, FMT20, (long long)(v)), \
+ memcpy ((void *) (d), buff20, 20)
+
+#define PRINT12(d, v) \
+ sprintf (buff20, FMT12, (int)(v)), \
+ memcpy ((void *) (d), buff20, 12)
+
+#define PRINT12_OCTAL(d, v) \
+ sprintf (buff20, FMT12_OCTAL, (unsigned int)(v)), \
+ memcpy ((void *) (d), buff20, 12)
+
+#define PRINT4(d, v) \
+ sprintf (buff20, FMT4, (int)(v)), \
+ memcpy ((void *) (d), buff20, 4)
+
+#define READ20(d, v) \
+ buff20[20] = 0, \
+ memcpy (buff20, (d), 20), \
+ (v) = bfd_scan_vma (buff20, (const char **) NULL, 10)
static boolean
-xcoff_write_one_armap_big (abfd, map, orl_count, orl_ccount, stridx, bits64,
- prevoff, nextoff)
+do_pad (abfd, number)
bfd *abfd;
- struct orl *map;
- unsigned int orl_count;
- unsigned int orl_ccount;
- unsigned int stridx;
- int bits64;
- const char *prevoff;
- char *nextoff;
+ unsigned int number;
{
- struct xcoff_ar_hdr_big hdr;
- char *p;
- unsigned char buf[4];
- bfd *sub;
- file_ptr fileoff;
- const bfd_arch_info_type *arch_info = NULL;
- bfd *object_bfd;
- unsigned int i;
+ bfd_byte b = 0;
- memset (&hdr, 0, sizeof hdr);
- /* XXX This call actually should use %lld (at least on 32-bit
- machines) since the fields's width is 20 and there numbers with
- more than 32 bits can be represented. */
- sprintf (hdr.size, "%ld", (long) (4 + orl_ccount * 4 + stridx));
- if (bits64)
- {
- sprintf (hdr.nextoff, "%d", 0);
- }
- else
- {
- /* Do explict cast to long to remove compiler warning. */
- sprintf (hdr.nextoff, "%ld", (strtol (prevoff, (char **) NULL, 10)
- + (long) (4 + orl_ccount * 4 + stridx)));
- }
+ /* Limit pad to <= 4096. */
+ if (number > 4096)
+ return false;
- memcpy (hdr.prevoff, prevoff, sizeof (hdr.prevoff));
- sprintf (hdr.date, "%d", 0);
- sprintf (hdr.uid, "%d", 0);
- sprintf (hdr.gid, "%d", 0);
- sprintf (hdr.mode, "%d", 0);
- sprintf (hdr.namlen, "%d", 0);
+ while (number--)
+ if (bfd_bwrite (&b, (bfd_size_type) 1, abfd) != 1)
+ return false;
- /* We need spaces, not null bytes, in the header. */
- for (p = (char *) &hdr; p < (char *) &hdr + SIZEOF_AR_HDR_BIG; p++)
- if (*p == '\0')
- *p = ' ';
+ return true;
+}
- memcpy (nextoff, hdr.nextoff, sizeof (hdr.nextoff));
+static boolean
+do_copy (out_bfd, in_bfd)
+ bfd *out_bfd;
+ bfd *in_bfd;
+{
+ bfd_size_type remaining;
+ bfd_byte buffer[DEFAULT_BUFFERSIZE];
- if ((bfd_bwrite ((PTR) &hdr, (bfd_size_type) SIZEOF_AR_HDR_BIG, abfd)
- != SIZEOF_AR_HDR_BIG)
- || (bfd_bwrite (XCOFFARFMAG, (bfd_size_type) SXCOFFARFMAG, abfd)
- != SXCOFFARFMAG))
+ if (bfd_seek (in_bfd, (file_ptr) 0, SEEK_SET) != 0)
return false;
- H_PUT_32 (abfd, orl_ccount, buf);
- if (bfd_bwrite (buf, (bfd_size_type) 4, abfd) != 4)
- return false;
+ remaining = arelt_size (in_bfd);
- sub = abfd->archive_head;
- fileoff = SIZEOF_AR_FILE_HDR_BIG;
- i = 0;
- while (sub != NULL && i < orl_count)
+ while (remaining >= DEFAULT_BUFFERSIZE)
{
- size_t namlen;
-
- if ((bfd_arch_bits_per_address (map[i].u.abfd) == 64) == bits64)
- while (map[i].u.abfd == sub)
- {
- H_PUT_32 (abfd, fileoff, buf);
- if (bfd_bwrite (buf, (bfd_size_type) 4, abfd) != 4)
- return false;
- i++;
- }
- else
- while (map[i].u.abfd == sub)
- i++;
+ if (bfd_bread (buffer, DEFAULT_BUFFERSIZE, in_bfd) != DEFAULT_BUFFERSIZE
+ || bfd_bwrite (buffer, DEFAULT_BUFFERSIZE, out_bfd) != DEFAULT_BUFFERSIZE)
+ return false;
- namlen = strlen (normalize_filename (sub));
- namlen = (namlen + 1) &~ (size_t) 1;
- fileoff += (SIZEOF_AR_HDR_BIG
- + namlen
- + SXCOFFARFMAG
- + arelt_size (sub));
- fileoff = (fileoff + 1) &~ 1;
- sub = sub->next;
+ remaining -= DEFAULT_BUFFERSIZE;
}
- object_bfd = NULL;
- for (i = 0; i < orl_count; i++)
+ if (remaining)
{
- const char *name;
- size_t namlen;
- bfd *ob = map[i].u.abfd;
-
- if (ob != object_bfd)
- arch_info = bfd_get_arch_info (ob);
- if ((arch_info->bits_per_address == 64) != bits64)
- continue;
-
- name = *map[i].name;
- namlen = strlen (name);
- if (bfd_bwrite (name, (bfd_size_type) (namlen + 1), abfd) != namlen + 1)
+ if (bfd_bread (buffer, remaining, in_bfd) != remaining
+ || bfd_bwrite (buffer, remaining, out_bfd) != remaining)
return false;
}
- if ((stridx & 1) != 0)
+ return true;
+}
+
+static boolean
+do_shared_object_padding (out_bfd, in_bfd, offset, ar_header_size)
+ bfd *out_bfd;
+ bfd *in_bfd;
+ ufile_ptr *offset;
+ int ar_header_size;
+{
+ if (bfd_check_format (in_bfd, bfd_object)
+ && bfd_get_flavour (in_bfd) == bfd_target_xcoff_flavour
+ && (in_bfd->flags & DYNAMIC) != 0)
{
- char b;
+ bfd_size_type pad = 0;
+ int text_align_power;
- b = '\0';
- if (bfd_bwrite (&b, (bfd_size_type) 1, abfd) != 1)
+ text_align_power = bfd_xcoff_text_align_power (in_bfd);
+ BFD_ASSERT (2 < text_align_power);
+
+ pad = 1 << text_align_power;
+ pad -= (*offset + ar_header_size) & (pad - 1);
+
+ if (! do_pad (out_bfd, pad))
return false;
+
+ *offset += pad;
}
return true;
unsigned int orl_count;
int stridx;
{
- unsigned int i;
- unsigned int orl_count_32, orl_count_64;
- unsigned int stridx_32, stridx_64;
+ struct xcoff_ar_file_hdr_big *fhdr;
+ bfd_vma i, sym_32, sym_64, str_32, str_64;
const bfd_arch_info_type *arch_info = NULL;
- bfd *object_bfd;
-
+ bfd *current_bfd;
+ size_t string_length;
+ ufile_ptr nextoff, prevoff;
+
/* First, we look through the symbols and work out which are
from 32-bit objects and which from 64-bit ones. */
- orl_count_32 = 0;
- orl_count_64 = 0;
- stridx_32 = 0;
- stridx_64 = 0;
- object_bfd = NULL;
- for (i = 0; i < orl_count; i++)
+ sym_32 = sym_64 = str_32 = str_64 = 0;
+
+ current_bfd = abfd->archive_head;
+ if (current_bfd != NULL)
+ arch_info = bfd_get_arch_info (current_bfd);
+ i = 0;
+ while (current_bfd != NULL && i < orl_count)
{
- bfd *ob = map[i].u.abfd;
- unsigned int len;
- if (ob != object_bfd)
- arch_info = bfd_get_arch_info (ob);
- len = strlen (*map[i].name) + 1;
- if (arch_info->bits_per_address == 64)
+ while (map[i].u.abfd == current_bfd)
{
- orl_count_64++;
- stridx_64 += len;
+ string_length = strlen (*map[i].name) + 1;
+
+ if (arch_info->bits_per_address == 64)
+ {
+ sym_64++;
+ str_64 += string_length;
+ }
+ else
+ {
+ sym_32++;
+ str_32 += string_length;
+ }
+ i++;
}
+ current_bfd = current_bfd->next;
+ if (current_bfd != NULL)
+ arch_info = bfd_get_arch_info (current_bfd);
+ }
+
+ /* A quick sanity check... */
+ BFD_ASSERT (sym_64 + sym_32 == orl_count);
+ /* Explicit cast to int for compiler. */
+ BFD_ASSERT ((int)(str_64 + str_32) == stridx);
+
+ fhdr = xcoff_ardata_big (abfd);
+
+ /* xcoff_write_archive_contents_big passes nextoff in symoff. */
+ READ20 (fhdr->memoff, prevoff);
+ READ20 (fhdr->symoff, nextoff);
+
+ BFD_ASSERT (nextoff == bfd_tell (abfd));
+
+ /* Write out the symbol table.
+ Layout :
+
+ standard big archive header
+ 0x0000 ar_size [0x14]
+ 0x0014 ar_nxtmem [0x14]
+ 0x0028 ar_prvmem [0x14]
+ 0x003C ar_date [0x0C]
+ 0x0048 ar_uid [0x0C]
+ 0x0054 ar_gid [0x0C]
+ 0x0060 ar_mod [0x0C]
+ 0x006C ar_namelen[0x04]
+ 0x0070 ar_fmag [SXCOFFARFMAG]
+
+ Symbol table
+ 0x0072 num_syms [0x08], binary
+ 0x0078 offsets [0x08 * num_syms], binary
+ 0x0086 + 0x08 * num_syms names [??]
+ ?? pad to even bytes.
+ */
+
+ if (sym_32)
+ {
+ struct xcoff_ar_hdr_big *hdr;
+ bfd_byte *symbol_table;
+ bfd_byte *st;
+ file_ptr fileoff;
+
+ bfd_vma symbol_table_size =
+ SIZEOF_AR_HDR_BIG
+ + SXCOFFARFMAG
+ + 8
+ + 8 * sym_32
+ + str_32 + (str_32 & 1);
+
+ symbol_table = NULL;
+ symbol_table = (bfd_byte *) bfd_malloc (symbol_table_size);
+ if (symbol_table == NULL)
+ return false;
+ memset (symbol_table, 0, symbol_table_size);
+
+ hdr = (struct xcoff_ar_hdr_big *) symbol_table;
+
+ PRINT20 (hdr->size, 8 + 8 * sym_32 + str_32 + (str_32 & 1));
+
+ if (sym_64)
+ PRINT20 (hdr->nextoff, nextoff + symbol_table_size);
else
+ PRINT20 (hdr->nextoff, 0);
+
+ PRINT20 (hdr->prevoff, prevoff);
+ PRINT12 (hdr->date, 0);
+ PRINT12 (hdr->uid, 0);
+ PRINT12 (hdr->gid, 0);
+ PRINT12 (hdr->mode, 0);
+ PRINT4 (hdr->namlen, 0) ;
+
+ st = symbol_table + SIZEOF_AR_HDR_BIG;
+ memcpy (st, XCOFFARFMAG, SXCOFFARFMAG);
+ st += SXCOFFARFMAG;
+
+ bfd_h_put_64 (abfd, sym_32, st);
+ st += 8;
+
+ /* loop over the 32 bit offsets */
+ current_bfd = abfd->archive_head;
+ if (current_bfd != NULL)
+ arch_info = bfd_get_arch_info (current_bfd);
+ fileoff = SIZEOF_AR_FILE_HDR_BIG;
+ i = 0;
+ while (current_bfd != NULL && i < orl_count)
+ {
+ while (map[i].u.abfd == current_bfd)
+ {
+ if (arch_info->bits_per_address == 32)
+ {
+ bfd_h_put_64 (abfd, fileoff, st);
+ st += 8;
+ }
+ i++;
+ }
+ string_length = strlen (normalize_filename (current_bfd));
+ string_length += string_length & 1;
+ fileoff += (SIZEOF_AR_HDR_BIG
+ + string_length
+ + SXCOFFARFMAG
+ + arelt_size (current_bfd));
+ fileoff += fileoff & 1;
+ current_bfd = current_bfd->next;
+ if (current_bfd != NULL)
+ arch_info = bfd_get_arch_info (current_bfd);
+ }
+
+ /* loop over the 32 bit symbol names */
+ current_bfd = abfd->archive_head;
+ if (current_bfd != NULL)
+ arch_info = bfd_get_arch_info (current_bfd);
+ i = 0;
+ while (current_bfd != NULL && i < orl_count)
{
- orl_count_32++;
- stridx_32 += len;
+ while (map[i].u.abfd == current_bfd)
+ {
+ if (arch_info->bits_per_address == 32)
+ {
+ string_length = sprintf (st, "%s", *map[i].name);
+ st += string_length + 1;
+ }
+ i++;
+ }
+ current_bfd = current_bfd->next;
+ if (current_bfd != NULL)
+ arch_info = bfd_get_arch_info (current_bfd);
}
- object_bfd = ob;
+
+ bfd_bwrite (symbol_table, symbol_table_size, abfd);
+
+ free (symbol_table);
+ symbol_table = NULL;
+
+ prevoff = nextoff;
+ nextoff = nextoff + symbol_table_size;
}
- /* A quick sanity check... */
- BFD_ASSERT (orl_count_64 + orl_count_32 == orl_count);
- /* Explicit cast to int for compiler. */
- BFD_ASSERT ((int)(stridx_64 + stridx_32) == stridx);
+ else
+ PRINT20 (fhdr->symoff, 0);
+
+ if (sym_64)
+ {
+ struct xcoff_ar_hdr_big *hdr;
+ bfd_byte *symbol_table;
+ bfd_byte *st;
+ file_ptr fileoff;
+
+ bfd_vma symbol_table_size =
+ SIZEOF_AR_HDR_BIG
+ + SXCOFFARFMAG
+ + 8
+ + 8 * sym_64
+ + str_64 + (str_64 & 1);
+
+ symbol_table = NULL;
+ symbol_table = (bfd_byte *) bfd_malloc (symbol_table_size);
+ if (symbol_table == NULL)
+ return false;
+ memset (symbol_table, 0, symbol_table_size);
+
+ hdr = (struct xcoff_ar_hdr_big *) symbol_table;
+
+ PRINT20 (hdr->size, 8 + 8 * sym_64 + str_64 + (str_64 & 1));
+ PRINT20 (hdr->nextoff, 0);
+ PRINT20 (hdr->prevoff, prevoff);
+ PRINT12 (hdr->date, 0);
+ PRINT12 (hdr->uid, 0);
+ PRINT12 (hdr->gid, 0);
+ PRINT12 (hdr->mode, 0);
+ PRINT4 (hdr->namlen, 0);
+
+ st = symbol_table + SIZEOF_AR_HDR_BIG;
+ memcpy (st, XCOFFARFMAG, SXCOFFARFMAG);
+ st += SXCOFFARFMAG;
+
+ bfd_h_put_64 (abfd, sym_64, st);
+ st += 8;
+
+ /* loop over the 64 bit offsets */
+ current_bfd = abfd->archive_head;
+ if (current_bfd != NULL)
+ arch_info = bfd_get_arch_info (current_bfd);
+ fileoff = SIZEOF_AR_FILE_HDR_BIG;
+ i = 0;
+ while (current_bfd != NULL && i < orl_count)
+ {
+ while (map[i].u.abfd == current_bfd)
+ {
+ if (arch_info->bits_per_address == 64)
+ {
+ bfd_h_put_64 (abfd, fileoff, st);
+ st += 8;
+ }
+ i++;
+ }
+ string_length = strlen (normalize_filename (current_bfd));
+ string_length += string_length & 1;
+ fileoff += (SIZEOF_AR_HDR_BIG
+ + string_length
+ + SXCOFFARFMAG
+ + arelt_size (current_bfd));
+ fileoff += fileoff & 1;
+ current_bfd = current_bfd->next;
+ if (current_bfd != NULL)
+ arch_info = bfd_get_arch_info (current_bfd);
+ }
- /* Now write out each map. */
- if (! xcoff_write_one_armap_big (abfd, map, orl_count, orl_count_32,
- stridx_32, false,
- xcoff_ardata_big (abfd)->memoff,
- xcoff_ardata_big (abfd)->symoff))
- return false;
- if (! xcoff_write_one_armap_big (abfd, map, orl_count, orl_count_64,
- stridx_64, true,
- xcoff_ardata_big (abfd)->symoff,
- xcoff_ardata_big (abfd)->symoff64))
- return false;
+ /* loop over the 64 bit symbol names */
+ current_bfd = abfd->archive_head;
+ if (current_bfd != NULL)
+ arch_info = bfd_get_arch_info (current_bfd);
+ i = 0;
+ while (current_bfd != NULL && i < orl_count)
+ {
+ while (map[i].u.abfd == current_bfd)
+ {
+ if (arch_info->bits_per_address == 64)
+ {
+ string_length = sprintf (st, "%s", *map[i].name);
+ st += string_length + 1;
+ }
+ i++;
+ }
+ current_bfd = current_bfd->next;
+ if (current_bfd != NULL)
+ arch_info = bfd_get_arch_info (current_bfd);
+ }
+
+ bfd_bwrite (symbol_table, symbol_table_size, abfd);
+
+ free (symbol_table);
+ symbol_table = NULL;
+ PRINT20 (fhdr->symoff64, nextoff);
+ }
+ else
+ PRINT20 (fhdr->symoff64, 0);
+
return true;
}
struct xcoff_ar_hdr ahdr;
bfd_size_type size;
char *p;
- char decbuf[13];
+ char decbuf[XCOFFARMAG_ELEMENT_SIZE + 1];
memset (&fhdr, 0, sizeof fhdr);
strncpy (fhdr.magic, XCOFFARMAG, SXCOFFARMAG);
if (bfd_seek (sub, (file_ptr) 0, SEEK_SET) != 0)
return false;
- while (remaining != 0)
- {
- bfd_size_type amt;
- bfd_byte buffer[DEFAULT_BUFFERSIZE];
-
- amt = sizeof buffer;
- if (amt > remaining)
- amt = remaining;
- if (bfd_bread (buffer, amt, sub) != amt
- || bfd_bwrite (buffer, amt, abfd) != amt)
- return false;
- remaining -= amt;
- }
- if ((size & 1) != 0)
- {
- bfd_byte b;
-
- b = '\0';
- if (bfd_bwrite (&b, (bfd_size_type) 1, abfd) != 1)
- return false;
- }
+ if (! do_copy (abfd, sub))
+ return false;
+
+ if (! do_pad (abfd, size & 1))
+ return false;
}
sprintf (fhdr.lastmemoff, "%ld", (long) prevoff);
sprintf (fhdr.memoff, "%ld", (long) nextoff);
memset (&ahdr, 0, sizeof ahdr);
- sprintf (ahdr.size, "%ld", (long) (12 + count * 12 + total_namlen));
+ sprintf (ahdr.size, "%ld", (long) (XCOFFARMAG_ELEMENT_SIZE +
+ count * XCOFFARMAG_ELEMENT_SIZE +
+ total_namlen));
sprintf (ahdr.prevoff, "%ld", (long) prevoff);
sprintf (ahdr.date, "%d", 0);
sprintf (ahdr.uid, "%d", 0);
sprintf (ahdr.namlen, "%d", 0);
size = (SIZEOF_AR_HDR
- + 12
- + count * 12
+ + XCOFFARMAG_ELEMENT_SIZE
+ + count * XCOFFARMAG_ELEMENT_SIZE
+ total_namlen
+ SXCOFFARFMAG);
return false;
sprintf (decbuf, "%-12ld", (long) count);
- if (bfd_bwrite ((PTR) decbuf, (bfd_size_type) 12, abfd) != 12)
+ if (bfd_bwrite ((PTR) decbuf, (bfd_size_type) XCOFFARMAG_ELEMENT_SIZE, abfd)
+ != XCOFFARMAG_ELEMENT_SIZE)
return false;
for (i = 0; i < (size_t) count; i++)
{
sprintf (decbuf, "%-12ld", (long) offsets[i]);
- if (bfd_bwrite ((PTR) decbuf, (bfd_size_type) 12, abfd) != 12)
+ if (bfd_bwrite ((PTR) decbuf, (bfd_size_type) XCOFFARMAG_ELEMENT_SIZE,
+ abfd) != XCOFFARMAG_ELEMENT_SIZE)
return false;
}
for (sub = abfd->archive_head; sub != NULL; sub = sub->next)
if (bfd_bwrite ((PTR) name, namlen + 1, abfd) != namlen + 1)
return false;
}
- if ((size & 1) != 0)
- {
- bfd_byte b;
- b = '\0';
- if (bfd_bwrite ((PTR) &b, (bfd_size_type) 1, abfd) != 1)
- return false;
- }
+ if (! do_pad (abfd, size & 1))
+ return false;
/* Write out the armap, if appropriate. */
-
if (! makemap || ! hasobjects)
sprintf (fhdr.symoff, "%d", 0);
else
boolean makemap;
boolean hasobjects;
ufile_ptr prevoff, nextoff;
- bfd *sub;
+ bfd *current_bfd;
size_t i;
- struct xcoff_ar_hdr_big ahdr;
+ struct xcoff_ar_hdr_big *hdr, ahdr;
bfd_size_type size;
- char *p;
- char decbuf[13];
+ bfd_byte *member_table, *mt;
+ bfd_vma member_table_size;
- memset (&fhdr, 0, sizeof fhdr);
- strncpy (fhdr.magic, XCOFFARMAGBIG, SXCOFFARMAG);
- sprintf (fhdr.firstmemoff, "%d", SIZEOF_AR_FILE_HDR_BIG);
- sprintf (fhdr.freeoff, "%d", 0);
-
- count = 0;
- total_namlen = 0;
- for (sub = abfd->archive_head; sub != NULL; sub = sub->next)
- {
- ++count;
- total_namlen += strlen (normalize_filename (sub)) + 1;
- }
- offsets = (file_ptr *) bfd_alloc (abfd, count * sizeof (file_ptr));
- if (offsets == NULL)
- return false;
+ memset (&fhdr, 0, SIZEOF_AR_FILE_HDR_BIG);
+ memcpy (fhdr.magic, XCOFFARMAGBIG, SXCOFFARMAG);
if (bfd_seek (abfd, (file_ptr) SIZEOF_AR_FILE_HDR_BIG, SEEK_SET) != 0)
return false;
-
+
+ /* Calculate count and total_namlen. */
makemap = bfd_has_map (abfd);
hasobjects = false;
+ for (current_bfd = abfd->archive_head, count = 0, total_namlen = 0;
+ current_bfd != NULL;
+ current_bfd = current_bfd->next, count++)
+ {
+ total_namlen += strlen (normalize_filename (current_bfd)) + 1;
+
+ if (makemap
+ && ! hasobjects
+ && bfd_check_format (current_bfd, bfd_object))
+ hasobjects = true;
+ }
+
+ offsets = NULL;
+ if (count)
+ {
+ offsets = (file_ptr *) bfd_malloc (count * sizeof (file_ptr));
+ if (offsets == NULL)
+ return false;
+ }
+
prevoff = 0;
nextoff = SIZEOF_AR_FILE_HDR_BIG;
- for (sub = abfd->archive_head, i = 0; sub != NULL; sub = sub->next, i++)
+ for (current_bfd = abfd->archive_head, i = 0;
+ current_bfd != NULL;
+ current_bfd = current_bfd->next, i++)
{
const char *name;
bfd_size_type namlen;
struct xcoff_ar_hdr_big *ahdrp;
bfd_size_type remaining;
- if (makemap && ! hasobjects)
- {
- if (bfd_check_format (sub, bfd_object))
- hasobjects = true;
- }
-
- name = normalize_filename (sub);
+ name = normalize_filename (current_bfd);
namlen = strlen (name);
- if (sub->arelt_data != NULL)
- ahdrp = arch_xhdr_big (sub);
+ if (current_bfd->arelt_data != NULL)
+ ahdrp = arch_xhdr_big (current_bfd);
else
ahdrp = NULL;
{
struct stat s;
- memset (&ahdr, 0, sizeof ahdr);
ahdrp = &ahdr;
/* XXX This should actually be a call to stat64 (at least on
- 32-bit machines). */
- if (stat (bfd_get_filename (sub), &s) != 0)
+ 32-bit machines).
+ XXX This call will fail if the original object is not found. */
+ if (stat (bfd_get_filename (current_bfd), &s) != 0)
{
bfd_set_error (bfd_error_system_call);
return false;
}
- /* XXX This call actually should use %lld (at least on 32-bit
- machines) since the fields's width is 20 and there numbers with
- more than 32 bits can be represented. */
- sprintf (ahdrp->size, "%ld", (long) s.st_size);
- sprintf (ahdrp->date, "%ld", (long) s.st_mtime);
- sprintf (ahdrp->uid, "%ld", (long) s.st_uid);
- sprintf (ahdrp->gid, "%ld", (long) s.st_gid);
- sprintf (ahdrp->mode, "%o", (unsigned int) s.st_mode);
+ PRINT20 (ahdrp->size, s.st_size);
+ PRINT12 (ahdrp->date, s.st_mtime);
+ PRINT12 (ahdrp->uid, s.st_uid);
+ PRINT12 (ahdrp->gid, s.st_gid);
+ PRINT12_OCTAL (ahdrp->mode, s.st_mode);
- if (sub->arelt_data == NULL)
+ if (current_bfd->arelt_data == NULL)
{
size = sizeof (struct areltdata);
- sub->arelt_data = bfd_alloc (sub, size);
- if (sub->arelt_data == NULL)
+ current_bfd->arelt_data = bfd_alloc (current_bfd, size);
+ if (current_bfd->arelt_data == NULL)
return false;
}
- arch_eltdata (sub)->parsed_size = s.st_size;
+ arch_eltdata (current_bfd)->parsed_size = s.st_size;
}
- /* XXX These calls actually should use %lld (at least on 32-bit
- machines) since the fields's width is 20 and there numbers with
- more than 32 bits can be represented. */
- sprintf (ahdrp->prevoff, "%ld", (long) prevoff);
- sprintf (ahdrp->namlen, "%ld", (long) namlen);
+ PRINT20 (ahdrp->prevoff, prevoff);
+ PRINT4 (ahdrp->namlen, namlen);
/* If the length of the name is odd, we write out the null byte
after the name as well. */
namlen = (namlen + 1) &~ (bfd_size_type) 1;
- remaining = arelt_size (sub);
+ remaining = arelt_size (current_bfd);
size = (SIZEOF_AR_HDR_BIG
+ namlen
+ SXCOFFARFMAG
BFD_ASSERT (nextoff == bfd_tell (abfd));
+ /* Check for xcoff shared objects.
+ Their text section needs to be aligned wrt the archive file position.
+ This requires extra padding before the archive header. */
+ if (! do_shared_object_padding (abfd, current_bfd, & nextoff,
+ SIZEOF_AR_HDR_BIG + namlen
+ + SXCOFFARFMAG))
+ return false;
+
offsets[i] = nextoff;
prevoff = nextoff;
nextoff += size + (size & 1);
- sprintf (ahdrp->nextoff, "%ld", (long) nextoff);
-
- /* We need spaces, not null bytes, in the header. */
- for (p = (char *) ahdrp; p < (char *) ahdrp + SIZEOF_AR_HDR_BIG; p++)
- if (*p == '\0')
- *p = ' ';
+ PRINT20 (ahdrp->nextoff, nextoff);
if ((bfd_bwrite ((PTR) ahdrp, (bfd_size_type) SIZEOF_AR_HDR_BIG, abfd)
!= SIZEOF_AR_HDR_BIG)
|| bfd_bwrite ((PTR) name, (bfd_size_type) namlen, abfd) != namlen
- || (bfd_bwrite ((PTR) XCOFFARFMAG, (bfd_size_type) SXCOFFARFMAG, abfd)
- != SXCOFFARFMAG))
+ || (bfd_bwrite ((PTR) XCOFFARFMAG, (bfd_size_type) SXCOFFARFMAG,
+ abfd) != SXCOFFARFMAG))
return false;
- if (bfd_seek (sub, (file_ptr) 0, SEEK_SET) != 0)
+ if (bfd_seek (current_bfd, (file_ptr) 0, SEEK_SET) != 0)
return false;
- while (remaining != 0)
- {
- bfd_size_type amt;
- bfd_byte buffer[DEFAULT_BUFFERSIZE];
-
- amt = sizeof buffer;
- if (amt > remaining)
- amt = remaining;
- if (bfd_bread (buffer, amt, sub) != amt
- || bfd_bwrite (buffer, amt, abfd) != amt)
- return false;
- remaining -= amt;
- }
- if ((size & 1) != 0)
- {
- bfd_byte b;
-
- b = '\0';
- if (bfd_bwrite (&b, (bfd_size_type) 1, abfd) != 1)
- return false;
- }
+ if (! do_copy (abfd, current_bfd))
+ return false;
+
+ if (! do_pad (abfd, size & 1))
+ return false;
}
- /* XXX This call actually should use %lld (at least on 32-bit
- machines) since the fields's width is 20 and there numbers with
- more than 32 bits can be represented. */
- sprintf (fhdr.lastmemoff, "%ld", (long) prevoff);
+ if (count)
+ {
+ PRINT20 (fhdr.firstmemoff, offsets[0]);
+ PRINT20 (fhdr.lastmemoff, prevoff);
+ }
- /* Write out the member table. */
+ /* Write out the member table.
+ Layout :
+
+ standard big archive header
+ 0x0000 ar_size [0x14]
+ 0x0014 ar_nxtmem [0x14]
+ 0x0028 ar_prvmem [0x14]
+ 0x003C ar_date [0x0C]
+ 0x0048 ar_uid [0x0C]
+ 0x0054 ar_gid [0x0C]
+ 0x0060 ar_mod [0x0C]
+ 0x006C ar_namelen[0x04]
+ 0x0070 ar_fmag [0x02]
+
+ Member table
+ 0x0072 count [0x14]
+ 0x0086 offsets [0x14 * counts]
+ 0x0086 + 0x14 * counts names [??]
+ ?? pad to even bytes.
+ */
BFD_ASSERT (nextoff == bfd_tell (abfd));
- /* XXX This call actually should use %lld (at least on 32-bit
- machines) since the fields's width is 20 and there numbers with
- more than 32 bits can be represented. */
- sprintf (fhdr.memoff, "%ld", (long) nextoff);
- memset (&ahdr, 0, sizeof ahdr);
- /* XXX The next two calls actually should use %lld (at least on 32-bit
- machines) since the fields's width is 20 and there numbers with
- more than 32 bits can be represented. */
- sprintf (ahdr.size, "%ld", (long) (12 + count * 12 + total_namlen));
- sprintf (ahdr.prevoff, "%ld", (long) prevoff);
- sprintf (ahdr.date, "%d", 0);
- sprintf (ahdr.uid, "%d", 0);
- sprintf (ahdr.gid, "%d", 0);
- sprintf (ahdr.mode, "%d", 0);
- sprintf (ahdr.namlen, "%d", 0);
+ member_table_size = (SIZEOF_AR_HDR_BIG
+ + SXCOFFARFMAG
+ + XCOFFARMAGBIG_ELEMENT_SIZE
+ + count * XCOFFARMAGBIG_ELEMENT_SIZE
+ + total_namlen);
- size = (SIZEOF_AR_HDR_BIG
- + 12
- + count * 12
- + total_namlen
- + SXCOFFARFMAG);
+ member_table_size += member_table_size & 1;
+ member_table = NULL;
+ member_table = (bfd_byte *) bfd_malloc (member_table_size);
+ if (member_table == NULL)
+ return false;
+ memset (member_table, 0, member_table_size);
- prevoff = nextoff;
- nextoff += size + (size & 1);
+ hdr = (struct xcoff_ar_hdr_big *) member_table;
- if (makemap && hasobjects)
- /* XXX This call actually should use %lld (at least on 32-bit
- machines) since the fields's width is 20 and there numbers with
- more than 32 bits can be represented. */
- sprintf (ahdr.nextoff, "%ld", (long) nextoff);
+ PRINT20 (hdr->size, (XCOFFARMAGBIG_ELEMENT_SIZE +
+ count * XCOFFARMAGBIG_ELEMENT_SIZE +
+ total_namlen + (total_namlen & 1)));
+ if (makemap && hasobjects)
+ PRINT20 (hdr->nextoff, nextoff + member_table_size);
else
- sprintf (ahdr.nextoff, "%d", 0);
-
- /* We need spaces, not null bytes, in the header. */
- for (p = (char *) &ahdr; p < (char *) &ahdr + SIZEOF_AR_HDR_BIG; p++)
- if (*p == '\0')
- *p = ' ';
-
- if ((bfd_bwrite ((PTR) &ahdr, (bfd_size_type) SIZEOF_AR_HDR_BIG, abfd)
- != SIZEOF_AR_HDR_BIG)
- || (bfd_bwrite ((PTR) XCOFFARFMAG, (bfd_size_type) SXCOFFARFMAG, abfd)
- != SXCOFFARFMAG))
- return false;
-
- sprintf (decbuf, "%-12ld", (long) count);
- if (bfd_bwrite ((PTR) decbuf, (bfd_size_type) 12, abfd) != 12)
- return false;
+ PRINT20 (hdr->nextoff, 0);
+ PRINT20 (hdr->prevoff, prevoff);
+ PRINT12 (hdr->date, 0);
+ PRINT12 (hdr->uid, 0);
+ PRINT12 (hdr->gid, 0);
+ PRINT12 (hdr->mode, 0);
+ PRINT4 (hdr->namlen, 0);
+
+ mt = member_table + SIZEOF_AR_HDR_BIG;
+ memcpy (mt, XCOFFARFMAG, SXCOFFARFMAG);
+ mt += SXCOFFARFMAG;
+
+ PRINT20 (mt, count);
+ mt += XCOFFARMAGBIG_ELEMENT_SIZE;
for (i = 0; i < (size_t) count; i++)
{
- sprintf (decbuf, "%-12ld", (long) offsets[i]);
- if (bfd_bwrite ((PTR) decbuf, (bfd_size_type) 12, abfd) != 12)
- return false;
+ PRINT20 (mt, offsets[i]);
+ mt += XCOFFARMAGBIG_ELEMENT_SIZE;
}
- for (sub = abfd->archive_head; sub != NULL; sub = sub->next)
+
+ if (count)
+ {
+ free (offsets);
+ offsets = NULL;
+ }
+
+ for (current_bfd = abfd->archive_head; current_bfd != NULL;
+ current_bfd = current_bfd->next)
{
const char *name;
size_t namlen;
- name = normalize_filename (sub);
- namlen = strlen (name);
- if (bfd_bwrite ((PTR) name, (bfd_size_type) (namlen + 1), abfd)
- != namlen + 1)
- return false;
+ name = normalize_filename (current_bfd);
+ namlen = sprintf(mt, "%s", name);
+ mt += namlen + 1;
}
- if ((size & 1) != 0)
- {
- bfd_byte b;
+
+ if (bfd_bwrite (member_table, member_table_size, abfd) != member_table_size)
+ return false;
- b = '\0';
- if (bfd_bwrite ((PTR) &b, (bfd_size_type) 1, abfd) != 1)
- return false;
- }
+ free (member_table);
+ member_table = NULL;
+
+ PRINT20 (fhdr.memoff, nextoff);
+
+ prevoff = nextoff;
+ nextoff += member_table_size;
/* Write out the armap, if appropriate. */
- if (! makemap || ! hasobjects)
- sprintf (fhdr.symoff, "%d", 0);
+ if (! makemap || ! hasobjects)
+ PRINT20 (fhdr.symoff, 0);
else
{
BFD_ASSERT (nextoff == bfd_tell (abfd));
- /* XXX This call actually should use %lld (at least on 32-bit
- machines) since the fields's width is 20 and there numbers with
- more than 32 bits can be represented. */
+
+ /* Save nextoff in fhdr.symoff so the armap routine can use it. */
+ PRINT20 (fhdr.symoff, nextoff);
+
bfd_ardata (abfd)->tdata = (PTR) &fhdr;
if (! _bfd_compute_and_write_armap (abfd, 0))
return false;
/* Write out the archive file header. */
- /* We need spaces, not null bytes, in the header. */
- for (p = (char *) &fhdr; p < (char *) &fhdr + SIZEOF_AR_FILE_HDR_BIG; p++)
- if (*p == '\0')
- *p = ' ';
-
if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
- || (bfd_bwrite ((PTR) &fhdr, (bfd_size_type) SIZEOF_AR_FILE_HDR_BIG, abfd)
- != SIZEOF_AR_FILE_HDR_BIG))
+ || (bfd_bwrite ((PTR) &fhdr, (bfd_size_type) SIZEOF_AR_FILE_HDR_BIG,
+ abfd) != SIZEOF_AR_FILE_HDR_BIG))
return false;
-
+
return true;
}
(ldhdr->l_nsyms * bfd_xcoff_ldsymsz(abfd));
}
+static boolean
+xcoff_generate_rtinit (abfd, init, fini, rtld)
+ bfd *abfd;
+ const char *init;
+ const char *fini;
+ boolean rtld;
+{
+ bfd_byte filehdr_ext[FILHSZ];
+ bfd_byte scnhdr_ext[SCNHSZ];
+ bfd_byte syment_ext[SYMESZ * 10];
+ bfd_byte reloc_ext[RELSZ * 3];
+ bfd_byte *data_buffer;
+ bfd_size_type data_buffer_size;
+ bfd_byte *string_table = NULL, *st_tmp = NULL;
+ bfd_size_type string_table_size;
+ bfd_vma val;
+ size_t initsz, finisz;
+ struct internal_filehdr filehdr;
+ struct internal_scnhdr scnhdr;
+ struct internal_syment syment;
+ union internal_auxent auxent;
+ struct internal_reloc reloc;
+
+ char *data_name = ".data";
+ char *rtinit_name = "__rtinit";
+ char *rtld_name = "__rtld";
+
+ if (! bfd_xcoff_rtinit_size (abfd))
+ return false;
+
+ initsz = (init == NULL ? 0 : 1 + strlen (init));
+ finisz = (fini == NULL ? 0 : 1 + strlen (fini));
+
+ /* file header */
+ memset (filehdr_ext, 0, FILHSZ);
+ memset (&filehdr, 0, sizeof (struct internal_filehdr));
+ filehdr.f_magic = bfd_xcoff_magic_number (abfd);
+ filehdr.f_nscns = 1;
+ filehdr.f_timdat = 0;
+ filehdr.f_nsyms = 0; /* at least 6, no more than 10 */
+ filehdr.f_symptr = 0; /* set below */
+ filehdr.f_opthdr = 0;
+ filehdr.f_flags = 0;
+
+ /* section header */
+ memset (scnhdr_ext, 0, SCNHSZ);
+ memset (&scnhdr, 0, sizeof (struct internal_scnhdr));
+ memcpy (scnhdr.s_name, data_name, strlen (data_name));
+ scnhdr.s_paddr = 0;
+ scnhdr.s_vaddr = 0;
+ scnhdr.s_size = 0; /* set below */
+ scnhdr.s_scnptr = FILHSZ + SCNHSZ;
+ scnhdr.s_relptr = 0; /* set below */
+ scnhdr.s_lnnoptr = 0;
+ scnhdr.s_nreloc = 0; /* either 1 or 2 */
+ scnhdr.s_nlnno = 0;
+ scnhdr.s_flags = STYP_DATA;
+
+ /* .data
+ 0x0000 0x00000000 : rtl
+ 0x0004 0x00000010 : offset to init, or 0
+ 0x0008 0x00000028 : offset to fini, or 0
+ 0x000C 0x0000000C : size of descriptor
+ 0x0010 0x00000000 : init, needs a reloc
+ 0x0014 0x00000040 : offset to init name
+ 0x0018 0x00000000 : flags, padded to a word
+ 0x001C 0x00000000 : empty init
+ 0x0020 0x00000000 :
+ 0x0024 0x00000000 :
+ 0x0028 0x00000000 : fini, needs a reloc
+ 0x002C 0x00000??? : offset to fini name
+ 0x0030 0x00000000 : flags, padded to a word
+ 0x0034 0x00000000 : empty fini
+ 0x0038 0x00000000 :
+ 0x003C 0x00000000 :
+ 0x0040 init name
+ 0x0040 + initsz fini name */
+
+ data_buffer_size = 0x0040 + initsz + finisz;
+ data_buffer_size += (data_buffer_size & 7) ? 8 - (data_buffer_size & 7) : 0;
+ data_buffer = NULL;
+ data_buffer = (bfd_byte *) bfd_malloc (data_buffer_size);
+ if (data_buffer == NULL)
+ return false;
+
+ memset (data_buffer, 0, data_buffer_size);
+
+ if (initsz)
+ {
+ val = 0x10;
+ bfd_h_put_32 (abfd, val, &data_buffer[0x04]);
+ val = 0x40;
+ bfd_h_put_32 (abfd, val, &data_buffer[0x14]);
+ memcpy (&data_buffer[val], init, initsz);
+ }
+
+ if (finisz)
+ {
+ val = 0x28;
+ bfd_h_put_32 (abfd, val, &data_buffer[0x08]);
+ val = 0x40 + initsz;
+ bfd_h_put_32 (abfd, val, &data_buffer[0x2C]);
+ memcpy (&data_buffer[val], fini, finisz);
+ }
+
+ val = 0x0C;
+ bfd_h_put_32 (abfd, val, &data_buffer[0x0C]);
+
+ scnhdr.s_size = data_buffer_size;
+
+ /* string table */
+ string_table_size = 0;
+ if (initsz > 9)
+ string_table_size += initsz;
+ if (finisz > 9)
+ string_table_size += finisz;
+ if (string_table_size)
+ {
+ string_table_size += 4;
+ string_table = (bfd_byte *)bfd_malloc (string_table_size);
+ memset (string_table, 0, string_table_size);
+ val = string_table_size;
+ bfd_h_put_32 (abfd, val, &string_table[0]);
+ st_tmp = string_table + 4;
+ }
+
+ /* symbols
+ 0. .data csect
+ 2. __rtinit
+ 4. init function
+ 6. fini function
+ 8. __rtld */
+ memset (syment_ext, 0, 10 * SYMESZ);
+ memset (reloc_ext, 0, 3 * RELSZ);
+
+ /* .data csect */
+ memset (&syment, 0, sizeof (struct internal_syment));
+ memset (&auxent, 0, sizeof (union internal_auxent));
+ memcpy (syment._n._n_name, data_name, strlen (data_name));
+ syment.n_scnum = 1;
+ syment.n_sclass = C_HIDEXT;
+ syment.n_numaux = 1;
+ auxent.x_csect.x_scnlen.l = data_buffer_size;
+ auxent.x_csect.x_smtyp = 3 << 3 | XTY_SD;
+ auxent.x_csect.x_smclas = XMC_RW;
+ bfd_coff_swap_sym_out (abfd, &syment,
+ &syment_ext[filehdr.f_nsyms * SYMESZ]);
+ bfd_coff_swap_aux_out (abfd, &auxent, syment.n_type, syment.n_sclass, 0,
+ syment.n_numaux,
+ &syment_ext[(filehdr.f_nsyms + 1) * SYMESZ]);
+ filehdr.f_nsyms += 2;
+
+ /* __rtinit */
+ memset (&syment, 0, sizeof (struct internal_syment));
+ memset (&auxent, 0, sizeof (union internal_auxent));
+ memcpy (syment._n._n_name, rtinit_name, strlen (rtinit_name));
+ syment.n_scnum = 1;
+ syment.n_sclass = C_EXT;
+ syment.n_numaux = 1;
+ auxent.x_csect.x_smtyp = XTY_LD;
+ auxent.x_csect.x_smclas = XMC_RW;
+ bfd_coff_swap_sym_out (abfd, &syment,
+ &syment_ext[filehdr.f_nsyms * SYMESZ]);
+ bfd_coff_swap_aux_out (abfd, &auxent, syment.n_type, syment.n_sclass, 0,
+ syment.n_numaux,
+ &syment_ext[(filehdr.f_nsyms + 1) * SYMESZ]);
+ filehdr.f_nsyms += 2;
+
+ /* init */
+ if (initsz)
+ {
+ memset (&syment, 0, sizeof (struct internal_syment));
+ memset (&auxent, 0, sizeof (union internal_auxent));
+
+ if (initsz > 9)
+ {
+ syment._n._n_n._n_offset = st_tmp - string_table;
+ memcpy (st_tmp, init, initsz);
+ st_tmp += initsz;
+ }
+ else
+ memcpy (syment._n._n_name, init, initsz - 1);
+
+ syment.n_sclass = C_EXT;
+ syment.n_numaux = 1;
+ bfd_coff_swap_sym_out (abfd, &syment,
+ &syment_ext[filehdr.f_nsyms * SYMESZ]);
+ bfd_coff_swap_aux_out (abfd, &auxent, syment.n_type, syment.n_sclass, 0,
+ syment.n_numaux,
+ &syment_ext[(filehdr.f_nsyms + 1) * SYMESZ]);
+
+ /* reloc */
+ memset (&reloc, 0, sizeof (struct internal_reloc));
+ reloc.r_vaddr = 0x0010;
+ reloc.r_symndx = filehdr.f_nsyms;
+ reloc.r_type = R_POS;
+ reloc.r_size = 31;
+ bfd_coff_swap_reloc_out (abfd, &reloc, &reloc_ext[0]);
+
+ filehdr.f_nsyms += 2;
+ scnhdr.s_nreloc += 1;
+ }
+
+ /* fini */
+ if (finisz)
+ {
+ memset (&syment, 0, sizeof (struct internal_syment));
+ memset (&auxent, 0, sizeof (union internal_auxent));
+
+ if (finisz > 9)
+ {
+ syment._n._n_n._n_offset = st_tmp - string_table;
+ memcpy (st_tmp, fini, finisz);
+ st_tmp += finisz;
+ }
+ else
+ memcpy (syment._n._n_name, fini, finisz - 1);
+
+ syment.n_sclass = C_EXT;
+ syment.n_numaux = 1;
+ bfd_coff_swap_sym_out (abfd, &syment,
+ &syment_ext[filehdr.f_nsyms * SYMESZ]);
+ bfd_coff_swap_aux_out (abfd, &auxent, syment.n_type, syment.n_sclass, 0,
+ syment.n_numaux,
+ &syment_ext[(filehdr.f_nsyms + 1) * SYMESZ]);
+
+ /* reloc */
+ memset (&reloc, 0, sizeof (struct internal_reloc));
+ reloc.r_vaddr = 0x0028;
+ reloc.r_symndx = filehdr.f_nsyms;
+ reloc.r_type = R_POS;
+ reloc.r_size = 31;
+ bfd_coff_swap_reloc_out (abfd, &reloc,
+ &reloc_ext[scnhdr.s_nreloc * RELSZ]);
+
+ filehdr.f_nsyms += 2;
+ scnhdr.s_nreloc += 1;
+ }
+
+ if (rtld)
+ {
+ memset (&syment, 0, sizeof (struct internal_syment));
+ memset (&auxent, 0, sizeof (union internal_auxent));
+ memcpy (syment._n._n_name, rtld_name, strlen (rtld_name));
+ syment.n_sclass = C_EXT;
+ syment.n_numaux = 1;
+ bfd_coff_swap_sym_out (abfd, &syment,
+ &syment_ext[filehdr.f_nsyms * SYMESZ]);
+ bfd_coff_swap_aux_out (abfd, &auxent, syment.n_type, syment.n_sclass, 0,
+ syment.n_numaux,
+ &syment_ext[(filehdr.f_nsyms + 1) * SYMESZ]);
+
+ /* reloc */
+ memset (&reloc, 0, sizeof (struct internal_reloc));
+ reloc.r_vaddr = 0x0000;
+ reloc.r_symndx = filehdr.f_nsyms;
+ reloc.r_type = R_POS;
+ reloc.r_size = 31;
+ bfd_coff_swap_reloc_out (abfd, &reloc,
+ &reloc_ext[scnhdr.s_nreloc * RELSZ]);
+
+ filehdr.f_nsyms += 2;
+ scnhdr.s_nreloc += 1;
+ }
+
+ scnhdr.s_relptr = scnhdr.s_scnptr + data_buffer_size;
+ filehdr.f_symptr = scnhdr.s_relptr + scnhdr.s_nreloc * RELSZ;
+
+ bfd_coff_swap_filehdr_out (abfd, &filehdr, filehdr_ext);
+ bfd_bwrite (filehdr_ext, FILHSZ, abfd);
+ bfd_coff_swap_scnhdr_out (abfd, &scnhdr, scnhdr_ext);
+ bfd_bwrite (scnhdr_ext, SCNHSZ, abfd);
+ bfd_bwrite (data_buffer, data_buffer_size, abfd);
+ bfd_bwrite (reloc_ext, scnhdr.s_nreloc * RELSZ, abfd);
+ bfd_bwrite (syment_ext, filehdr.f_nsyms * SYMESZ, abfd);
+ bfd_bwrite (string_table, string_table_size, abfd);
+
+ free (data_buffer);
+ data_buffer = NULL;
+
+ return true;
+}
+
static reloc_howto_type xcoff_dynamic_reloc =
HOWTO (0, /* type */
SMALL_AOUTSZ, /* _xcoff_small_aout_header_size */
/* Versions. */
- 1, /* _xcoff_ldhdr_version */
+ 1, /* _xcoff_ldhdr_version */
- /* Xcoff vs xcoff64 putting symbol names. */
_bfd_xcoff_put_symbol_name, /* _xcoff_put_symbol_name */
- _bfd_xcoff_put_ldsymbol_name, /* _xcoff_put_ldsymbol_name */
-
- & xcoff_dynamic_reloc, /* dynamic reloc howto */
-
+ _bfd_xcoff_put_ldsymbol_name, /* _xcoff_put_ldsymbol_name */
+ & xcoff_dynamic_reloc, /* dynamic reloc howto */
xcoff_create_csect_from_smclas, /* _xcoff_create_csect_from_smclas */
/* Lineno and reloc count overflow. */
/* glink. */
& xcoff_glink_code[0],
(36), /* _xcoff_glink_size */
+
+ /* rtinit */
+ 64, /* _xcoff_rtinit_size */
+ xcoff_generate_rtinit, /* _xcoff_generate_rtinit */
};
-/* The transfer vector that leads the outside world to all of the above. */
+/* The transfer vector that leads the outside world to all of the above. */
const bfd_target rs6000coff_vec =
{
"aixcoff-rs6000",
_bfd_xcoff_read_ar_hdr, /* _read_ar_hdr */
_bfd_xcoff_openr_next_archived_file, /* _openr_next_archived_file */
_bfd_generic_get_elt_at_index, /* _get_elt_at_index */
- _bfd_xcoff_generic_stat_arch_elt, /* _generic_dtat_arch_elt */
+ _bfd_xcoff_stat_arch_elt, /* _generic_stat_arch_elt */
/* XCOFF archives do not have
a timestamp. */
bfd_true, /* _update_armap_timestamp */
bfd_generic_get_relocated_section_contents,
bfd_generic_relax_section, /* _bfd_relax_section */
_bfd_xcoff_bfd_link_hash_table_create, /* _bfd_link_hash_table_create */
+ _bfd_generic_link_hash_table_free, /* _bfd_link_hash_table_free */
_bfd_xcoff_bfd_link_add_symbols, /* _bfd_link_add_symbols */
_bfd_xcoff_bfd_final_link, /* _bfd_filnal_link */
_bfd_generic_link_split_section, /* _bfd_link_split_section */
&xcoff_glink_code[0],
(36), /* _xcoff_glink_size */
+ /* rtinit */
+ 0, /* _xcoff_rtinit_size */
+ xcoff_generate_rtinit, /* _xcoff_generate_rtinit */
};
/* The transfer vector that leads the outside world to all of the above. */
_bfd_xcoff_read_ar_hdr, /* _read_ar_hdr */
_bfd_xcoff_openr_next_archived_file, /* _openr_next_archived_file */
_bfd_generic_get_elt_at_index, /* _get_elt_at_index */
- _bfd_xcoff_generic_stat_arch_elt, /* _generic_dtat_arch_elt */
+ _bfd_xcoff_stat_arch_elt, /* _generic_stat_arch_elt */
/* XCOFF archives do not have
a timestamp. */
bfd_true, /* _update_armap_timestamp */
bfd_generic_get_relocated_section_contents,
bfd_generic_relax_section, /* _bfd_relax_section */
_bfd_xcoff_bfd_link_hash_table_create, /* _bfd_link_hash_table_create */
+ _bfd_generic_link_hash_table_free, /* _bfd_link_hash_table_free */
_bfd_xcoff_bfd_link_add_symbols, /* _bfd_link_add_symbols */
_bfd_xcoff_bfd_final_link, /* _bfd_filnal_link */
_bfd_generic_link_split_section, /* _bfd_link_split_section */