-binitfini emulation, put __rtinit symbol generation into linker.
This commit is contained in:
parent
f398918085
commit
9a4c7f1669
|
@ -1,3 +1,16 @@
|
|||
2001-12-21 Tom Rix <trix@redhat.com>
|
||||
|
||||
* xcofflink.c (bfd_xcoff_link_generate_rtinit): New function.
|
||||
Interface to linker for generation of __rtinit.
|
||||
* libxcoff.h (struct xcoff_backend_data_rec): Add new ops to xcoff
|
||||
backend to generate special linker symbol __rtinit.
|
||||
* coff-rs6000.c (bfd_xcoff_backend_data, bfd_pmac_xcoff_backend_data)
|
||||
: Add new rtinit ops
|
||||
* coff64-rs6000.c (bfd_xcoff_aix5_backend_data,
|
||||
bfd_xcoff_backend_data): Same.
|
||||
* bfd-in.h: Add bfd_xcoff_link_generate_rtinit.
|
||||
* bfd-in2.h : Regenerate.
|
||||
|
||||
2001-12-21 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* elf32-sparc.c (_bfd_sparc_elf_howto_table): Fix dst_mask for
|
||||
|
|
|
@ -724,6 +724,8 @@ extern boolean bfd_xcoff_size_dynamic_sections
|
|||
PARAMS ((bfd *, struct bfd_link_info *, const char *, const char *,
|
||||
unsigned long, unsigned long, unsigned long, boolean,
|
||||
int, boolean, boolean, struct sec **));
|
||||
extern boolean bfd_xcoff_link_generate_rtinit
|
||||
PARAMS ((bfd *, const char *, const char *));
|
||||
|
||||
/* Externally visible COFF routines. */
|
||||
|
||||
|
|
|
@ -730,6 +730,8 @@ extern boolean bfd_xcoff_size_dynamic_sections
|
|||
PARAMS ((bfd *, struct bfd_link_info *, const char *, const char *,
|
||||
unsigned long, unsigned long, unsigned long, boolean,
|
||||
int, boolean, boolean, struct sec **));
|
||||
extern boolean bfd_xcoff_link_generate_rtinit
|
||||
PARAMS ((bfd *, const char *, const char *));
|
||||
|
||||
/* Externally visible COFF routines. */
|
||||
|
||||
|
|
|
@ -2918,6 +2918,254 @@ xcoff_loader_reloc_offset (abfd, ldhdr)
|
|||
(ldhdr->l_nsyms * bfd_xcoff_ldsymsz(abfd));
|
||||
}
|
||||
|
||||
static boolean
|
||||
xcoff_generate_rtinit (abfd, init, fini)
|
||||
bfd *abfd;
|
||||
const char *init;
|
||||
const char *fini;
|
||||
{
|
||||
bfd_byte filehdr_ext[FILHSZ];
|
||||
bfd_byte scnhdr_ext[SCNHSZ];
|
||||
bfd_byte syment_ext[SYMESZ * 8];
|
||||
bfd_byte reloc_ext[RELSZ * 2];
|
||||
bfd_byte *data_buffer;
|
||||
bfd_size_type data_buffer_size;
|
||||
bfd_byte *string_table, *st_tmp;
|
||||
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";
|
||||
|
||||
if (! bfd_xcoff_rtinit_size (abfd)
|
||||
|| (init == NULL && fini == NULL))
|
||||
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 8 */
|
||||
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 = (bfd_byte *)bfd_malloc (data_buffer_size);
|
||||
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 */
|
||||
memset (syment_ext, 0, 8 * SYMESZ);
|
||||
memset (reloc_ext, 0, 2 * 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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static reloc_howto_type xcoff_dynamic_reloc =
|
||||
HOWTO (0, /* type */
|
||||
|
@ -3045,6 +3293,10 @@ static const struct xcoff_backend_data_rec bfd_xcoff_backend_data =
|
|||
/* 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. */
|
||||
|
@ -3302,6 +3554,10 @@ static const struct xcoff_backend_data_rec bfd_pmac_xcoff_backend_data =
|
|||
&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. */
|
||||
|
|
|
@ -2094,6 +2094,252 @@ xcoff64_loader_reloc_offset (abfd, ldhdr)
|
|||
return (ldhdr->l_rldoff);
|
||||
}
|
||||
|
||||
static boolean
|
||||
xcoff64_generate_rtinit (abfd, init, fini)
|
||||
bfd *abfd;
|
||||
const char *init;
|
||||
const char *fini;
|
||||
{
|
||||
bfd_byte filehdr_ext[FILHSZ];
|
||||
bfd_byte scnhdr_ext[SCNHSZ];
|
||||
bfd_byte syment_ext[SYMESZ * 8];
|
||||
bfd_byte reloc_ext[RELSZ * 2];
|
||||
bfd_byte *data_buffer;
|
||||
bfd_size_type data_buffer_size;
|
||||
bfd_byte *string_table, *st_tmp;
|
||||
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";
|
||||
|
||||
if (! bfd_xcoff_rtinit_size (abfd)
|
||||
|| (init == NULL && fini == NULL))
|
||||
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 8 */
|
||||
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 0x00000000 :
|
||||
0x0008 0x00000018 : offset to init, or 0
|
||||
0x000C 0x00000038 : offset to fini, or 0
|
||||
0x0010 0x00000010 : size of descriptor
|
||||
0x0014 0x00000000 : pad
|
||||
0x0018 0x00000000 : init, needs a reloc
|
||||
0x001C 0x00000000 :
|
||||
0x0020 0x00000058 : offset to init name
|
||||
0x0024 0x00000000 : flags, padded to a word
|
||||
0x0028 0x00000000 : empty init
|
||||
0x002C 0x00000000 :
|
||||
0x0030 0x00000000 :
|
||||
0x0034 0x00000000 :
|
||||
0x0038 0x00000000 : fini, needs a reloc
|
||||
0x003C 0x00000000 :
|
||||
0x0040 0x00000??? : offset to fini name
|
||||
0x0044 0x00000000 : flags, padded to a word
|
||||
0x0048 0x00000000 : empty fini
|
||||
0x004C 0x00000000 :
|
||||
0x0050 0x00000000 :
|
||||
0x0054 0x00000000 :
|
||||
0x0058 init name
|
||||
0x0058 + initsz fini name */
|
||||
|
||||
data_buffer_size = 0x0058 + initsz + finisz;
|
||||
data_buffer_size += (data_buffer_size & 7) ? 8 - (data_buffer_size & 7) : 0;
|
||||
data_buffer = (bfd_byte *)bfd_malloc (data_buffer_size);
|
||||
memset (data_buffer, 0, data_buffer_size);
|
||||
|
||||
if (initsz)
|
||||
{
|
||||
val = 0x18;
|
||||
bfd_put_32 (abfd, val, &data_buffer[0x08]);
|
||||
val = 0x58;
|
||||
bfd_put_32 (abfd, val, &data_buffer[0x20]);
|
||||
memcpy (&data_buffer[val], init, initsz);
|
||||
}
|
||||
|
||||
if (finisz)
|
||||
{
|
||||
val = 0x38;
|
||||
bfd_put_32 (abfd, val, &data_buffer[0x0C]);
|
||||
val = 0x58 + initsz;
|
||||
bfd_put_32 (abfd, val, &data_buffer[0x40]);
|
||||
memcpy (&data_buffer[val], fini, finisz);
|
||||
}
|
||||
|
||||
val = 0x10;
|
||||
bfd_put_32 (abfd, val, &data_buffer[0x10]);
|
||||
scnhdr.s_size = data_buffer_size;
|
||||
|
||||
/* string table */
|
||||
string_table_size = 4;
|
||||
string_table_size += strlen (data_name) + 1;
|
||||
string_table_size += strlen (rtinit_name) + 1;
|
||||
string_table_size += initsz;
|
||||
string_table_size += finisz;
|
||||
|
||||
string_table = (bfd_byte *)bfd_malloc (string_table_size);
|
||||
memset (string_table, 0, string_table_size);
|
||||
val = string_table_size;
|
||||
bfd_put_32 (abfd, val, &string_table[0]);
|
||||
st_tmp = string_table + 4;
|
||||
|
||||
/* symbols
|
||||
0. .data csect
|
||||
2. __rtinit
|
||||
4. init function
|
||||
6. fini function */
|
||||
memset (syment_ext, 0, 8 * SYMESZ);
|
||||
memset (reloc_ext, 0, 2 * RELSZ);
|
||||
|
||||
/* .data csect */
|
||||
memset (&syment, 0, sizeof (struct internal_syment));
|
||||
memset (&auxent, 0, sizeof (union internal_auxent));
|
||||
|
||||
syment._n._n_n._n_offset = st_tmp - string_table;
|
||||
memcpy (st_tmp, data_name, strlen (data_name));
|
||||
st_tmp += strlen (data_name) + 1;
|
||||
|
||||
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));
|
||||
syment._n._n_n._n_offset = st_tmp - string_table;
|
||||
memcpy (st_tmp, rtinit_name, strlen (rtinit_name));
|
||||
st_tmp += strlen (rtinit_name) + 1;
|
||||
|
||||
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));
|
||||
|
||||
syment._n._n_n._n_offset = st_tmp - string_table;
|
||||
memcpy (st_tmp, init, initsz);
|
||||
st_tmp += initsz;
|
||||
|
||||
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 = 0x0018;
|
||||
reloc.r_symndx = filehdr.f_nsyms;
|
||||
reloc.r_type = R_POS;
|
||||
reloc.r_size = 63;
|
||||
bfd_coff_swap_reloc_out (abfd, &reloc, &reloc_ext[0]);
|
||||
|
||||
filehdr.f_nsyms += 2;
|
||||
scnhdr.s_nreloc += 1;
|
||||
}
|
||||
|
||||
/* finit */
|
||||
if (finisz)
|
||||
{
|
||||
memset (&syment, 0, sizeof (struct internal_syment));
|
||||
memset (&auxent, 0, sizeof (union internal_auxent));
|
||||
|
||||
syment._n._n_n._n_offset = st_tmp - string_table;
|
||||
memcpy (st_tmp, fini, finisz);
|
||||
st_tmp += finisz;
|
||||
|
||||
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 = 0x0038;
|
||||
reloc.r_symndx = filehdr.f_nsyms;
|
||||
reloc.r_type = R_POS;
|
||||
reloc.r_size = 63;
|
||||
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);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* The typical dynamic reloc. */
|
||||
|
||||
static reloc_howto_type xcoff64_dynamic_reloc =
|
||||
|
@ -2219,6 +2465,10 @@ static const struct xcoff_backend_data_rec bfd_xcoff_backend_data =
|
|||
&xcoff64_glink_code[0],
|
||||
40, /* _xcoff_glink_size */
|
||||
|
||||
/* rtinit */
|
||||
88, /* _xcoff_rtinit_size */
|
||||
xcoff64_generate_rtinit, /* _xcoff_generate_rtinit */
|
||||
|
||||
};
|
||||
|
||||
/* The transfer vector that leads the outside world to all of the above. */
|
||||
|
|
|
@ -112,6 +112,9 @@ struct xcoff_backend_data_rec
|
|||
*/
|
||||
unsigned long _xcoff_glink_size;
|
||||
|
||||
/* rtinit */
|
||||
unsigned int _xcoff_rtinit_size;
|
||||
boolean (*_xcoff_generate_rtinit)(bfd *, const char *, const char *);
|
||||
};
|
||||
|
||||
/* Look up an entry in an XCOFF link hash table. */
|
||||
|
@ -201,9 +204,15 @@ struct xcoff_backend_data_rec
|
|||
#define bfd_xcoff_glink_code(a, b) ((xcoff_backend(a)->_xcoff_glink_code[(b)]))
|
||||
#define bfd_xcoff_glink_code_size(a) ((xcoff_backend(a)->_xcoff_glink_size))
|
||||
|
||||
/* Check for the magic number U803XTOCMAGIC for 64 bit targets. */
|
||||
#define bfd_xcoff_is_xcoff64(a) (0x01EF == (bfd_xcoff_magic_number(a)))
|
||||
|
||||
/* Check for the magic number U802TOMAGIC for 32 bit targets. */
|
||||
#define bfd_xcoff_is_xcoff32(a) (0x01DF == (bfd_xcoff_magic_number(a)))
|
||||
|
||||
#define bfd_xcoff_rtinit_size(a) ((xcoff_backend(a)->_xcoff_rtinit_size))
|
||||
#define bfd_xcoff_generate_rtinit(a, b, c) ((xcoff_backend(a)->_xcoff_generate_rtinit ((a), (b), (c))))
|
||||
|
||||
/* Functions in xcofflink.c. */
|
||||
|
||||
extern long _bfd_xcoff_get_dynamic_symtab_upper_bound PARAMS ((bfd *));
|
||||
|
|
|
@ -3219,6 +3219,41 @@ bfd_xcoff_size_dynamic_sections (output_bfd, info, libpath, entry,
|
|||
return false;
|
||||
}
|
||||
|
||||
boolean
|
||||
bfd_xcoff_link_generate_rtinit (abfd, init, fini)
|
||||
bfd *abfd;
|
||||
const char *init;
|
||||
const char *fini;
|
||||
{
|
||||
struct bfd_in_memory *bim;
|
||||
|
||||
bim = ((struct bfd_in_memory *)
|
||||
bfd_malloc ((bfd_size_type) sizeof (struct bfd_in_memory)));
|
||||
if (bim == NULL)
|
||||
return false;
|
||||
|
||||
bim->size = 0;
|
||||
bim->buffer = 0;
|
||||
|
||||
abfd->link_next = 0;
|
||||
abfd->format = bfd_object;
|
||||
abfd->iostream = (PTR) bim;
|
||||
abfd->flags = BFD_IN_MEMORY;
|
||||
abfd->direction = write_direction;
|
||||
abfd->where = 0;
|
||||
|
||||
if (false == bfd_xcoff_generate_rtinit (abfd, init, fini))
|
||||
return false;
|
||||
|
||||
/* need to reset to unknown or it will not be read back in correctly */
|
||||
abfd->format = bfd_unknown;
|
||||
abfd->direction = read_direction;
|
||||
abfd->where = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* Add a symbol to the .loader symbols, if necessary. */
|
||||
|
||||
static boolean
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
2001-12-21 Tom Rix <trix@redhat.com>
|
||||
|
||||
(gld*_create_output_section_statements): New function.
|
||||
For -binitfini support.
|
||||
* emultempl/aix.em (gld*_before_parse): Fix comment.
|
||||
* emultempl/aix.em (gld*_parse_args): Fix comment.
|
||||
|
||||
2001-12-20 Jason Thorpe <thorpej@wasabisystems.com>
|
||||
|
||||
* configure.tgt (mips*-dec-netbsd*): Delete alias for
|
||||
|
|
|
@ -67,6 +67,8 @@ static void gld${EMULATION_NAME}_find_exp_assignment PARAMS ((etree_type *));
|
|||
static char *gld${EMULATION_NAME}_get_script PARAMS ((int *isfile));
|
||||
static boolean gld${EMULATION_NAME}_unrecognized_file
|
||||
PARAMS ((lang_input_statement_type *));
|
||||
static void gld${EMULATION_NAME}_create_output_section_statements
|
||||
PARAMS((void));
|
||||
static int is_syscall PARAMS ((char *, unsigned int *));
|
||||
static int change_symbol_mode PARAMS ((char *));
|
||||
|
||||
|
@ -126,6 +128,9 @@ static int is_64bit = 0;
|
|||
/* Which syscalls from import file are valid */
|
||||
static unsigned int syscall_mask = 0x77;
|
||||
|
||||
/* fake file for -binitfini support */
|
||||
static lang_input_statement_type *initfini_file;
|
||||
|
||||
/* This routine is called before anything else is done. */
|
||||
|
||||
static void
|
||||
|
@ -144,11 +149,10 @@ gld${EMULATION_NAME}_before_parse ()
|
|||
#endif /* not TARGET_ */
|
||||
config.has_shared = true;
|
||||
|
||||
/*
|
||||
* The link_info.[init|fini]_functions are initialized in ld/lexsup.c.
|
||||
* Override them here so we can use the link_info.init_function as a
|
||||
* state flag that lets the backend know that -binitfini has been done.
|
||||
*/
|
||||
/* The link_info.[init|fini]_functions are initialized in ld/lexsup.c.
|
||||
Override them here so we can use the link_info.init_function as a
|
||||
state flag that lets the backend know that -binitfini has been done. */
|
||||
|
||||
link_info.init_function = NULL;
|
||||
link_info.fini_function = NULL;
|
||||
|
||||
|
@ -192,51 +196,14 @@ gld${EMULATION_NAME}_parse_args (argc, argv)
|
|||
OPTION_64,
|
||||
};
|
||||
|
||||
/*
|
||||
binitfini has special handling in the linker backend. The native linker
|
||||
uses the arguemnts to generate a table of init and fini functions for
|
||||
the executable. The important use for this option is to support aix 4.2+
|
||||
c++ constructors and destructors. This is tied into gcc via collect2.c.
|
||||
The function table is accessed by the runtime linker/loader by checking if
|
||||
the first symbol in the loader symbol table is "__rtinit". The native
|
||||
linker generates this table and the loader symbol. The gnu linker looks
|
||||
for the symbol "__rtinit" and makes it the first loader symbol. It is the
|
||||
responsiblity of the user to define the __rtinit symbol. The format for
|
||||
__rtinit is given by the aix system file /usr/include/rtinit.h. You can
|
||||
look at collect2.c to see an example of how this is done for 32 and 64 bit.
|
||||
Below is an exmaple of a 32 bit assembly file that defines __rtinit.
|
||||
|
||||
.file "my_rtinit.s"
|
||||
|
||||
.csect .data[RW],3
|
||||
.globl __rtinit
|
||||
.extern init_function
|
||||
.extern fini_function
|
||||
|
||||
__rtinit:
|
||||
.long 0
|
||||
.long f1i - __rtinit
|
||||
.long f1f - __rtinit
|
||||
.long f2i - f1i
|
||||
.align 3
|
||||
f1i: .long init_function
|
||||
.long s1i - __rtinit
|
||||
.long 0
|
||||
f2i: .long 0
|
||||
.long 0
|
||||
.long 0
|
||||
f1f: .long fini_function
|
||||
.long s1f - __rtinit
|
||||
.long 0
|
||||
f2f: .long 0
|
||||
.long 0
|
||||
.long 0
|
||||
.align 3
|
||||
s1i: .string "init_function"
|
||||
.align 3
|
||||
s1f: .string "fini_function"
|
||||
|
||||
*/
|
||||
/* -binitfini has special handling in the linker backend. The native linker
|
||||
uses the arguemnts to generate a table of init and fini functions for
|
||||
the executable. The important use for this option is to support aix 4.2+
|
||||
c++ constructors and destructors. This is tied into gcc via collect2.c.
|
||||
|
||||
The function table is accessed by the runtime linker/loader by checking if
|
||||
the first symbol in the loader symbol table is __rtinit. The gnu linker
|
||||
generates this symbol and makes it the first loader symbol. */
|
||||
|
||||
static const struct option longopts[] = {
|
||||
{"basis", no_argument, NULL, OPTION_IGNORE},
|
||||
|
@ -1319,6 +1286,39 @@ fi
|
|||
|
||||
cat >>e${EMULATION_NAME}.c <<EOF
|
||||
|
||||
static void
|
||||
gld${EMULATION_NAME}_create_output_section_statements()
|
||||
{
|
||||
/* __rtinit */
|
||||
if ((bfd_get_flavour (output_bfd) == bfd_target_xcoff_flavour)
|
||||
&& (link_info.init_function != NULL || link_info.fini_function != NULL))
|
||||
{
|
||||
|
||||
initfini_file = lang_add_input_file ("initfini",
|
||||
lang_input_file_is_file_enum,
|
||||
NULL);
|
||||
|
||||
initfini_file->the_bfd = bfd_create ("initfini", output_bfd);
|
||||
if (initfini_file->the_bfd == NULL
|
||||
|| ! bfd_set_arch_mach (initfini_file->the_bfd,
|
||||
bfd_get_arch (output_bfd),
|
||||
bfd_get_mach (output_bfd)))
|
||||
{
|
||||
einfo ("%X%P: can not create BFD %E\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Call backend to fill in the rest */
|
||||
if (false == bfd_xcoff_link_generate_rtinit (initfini_file->the_bfd,
|
||||
link_info.init_function,
|
||||
link_info.fini_function))
|
||||
{
|
||||
einfo ("%X%P: can not create BFD %E\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = {
|
||||
gld${EMULATION_NAME}_before_parse,
|
||||
syslib_default,
|
||||
|
@ -1333,7 +1333,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = {
|
|||
"${EMULATION_NAME}",
|
||||
"${OUTPUT_FORMAT}",
|
||||
0, /* finish */
|
||||
0, /* create_output_section_statements */
|
||||
gld${EMULATION_NAME}_create_output_section_statements,
|
||||
0, /* open_dynamic_archive */
|
||||
0, /* place_orphan */
|
||||
0, /* set_symbols */
|
||||
|
|
Loading…
Reference in New Issue