-binitfini emulation, put __rtinit symbol generation into linker.
authorTom Rix <trix@redhat.com>
Sat, 22 Dec 2001 17:18:34 +0000 (17:18 +0000)
committerTom Rix <trix@redhat.com>
Sat, 22 Dec 2001 17:18:34 +0000 (17:18 +0000)
bfd/ChangeLog
bfd/bfd-in.h
bfd/bfd-in2.h
bfd/coff-rs6000.c
bfd/coff64-rs6000.c
bfd/libxcoff.h
bfd/xcofflink.c
ld/ChangeLog
ld/emultempl/aix.em

index f0c7fe71163fd29ced750beb28abf68cc6c60883..27bab56be62f3f7855886fdf818c04882d323a6d 100644 (file)
@@ -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
index c578614201bdf63e9bc4ae4f926accc7548488db..c6f2b4162d4bfa4a0266b88cdabe2f7d18afc73d 100644 (file)
@@ -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.  */
 
index 920df8de488df8bc6317abddc3612e08856090f5..298313864963ef850c25241b66fb3c4937a682cb 100644 (file)
@@ -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.  */
 
index d97cb030ae989b8f68ce0d98578e440aa59ad1cf..932e437626d01f800dc12fd6446144df25f475da 100644 (file)
@@ -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. */
index bc972418db9910c11c893d1bc9ec4e54e24cf47d..52d7a226a7a802891b47ce50d4ebb74c4104f84d 100644 (file)
@@ -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. */
index b0ac0501f582fcfb86bbd85289bcf851d0ac7d66..257e9e40309444da99814e7995026238ee467a79 100644 (file)
@@ -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 *));
index af6ebb1818e95c186ffb2ac8a0b09e3039e8be1d..e27f648d048994455cdac0d6000f0614565b242e 100644 (file)
@@ -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
index 4f01c884b70e00bbe3581fe4cda9f127876924ce..3f6c7fef13634afdcefe5d029f4f39c53955ac8b 100644 (file)
@@ -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
index 1bc643b548bd50ca2795c0620412a1f424932f34..e5db1b9c36b3aebed34a33e2b05441d5e893661a 100644 (file)
@@ -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 */