This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

PATCH, AIX -binitfini emulation in ld


This patch moves all of the -binitfini support into the linker.
Previously,  it was left to the user to generate the __rtinit symbol,
now the linker generates it.

I will check this in shortly.
Tom

--
Tom Rix
GCC Engineer
trix@redhat.com


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.
 
diff -rcp src-old/bfd/bfd-in.h src/bfd/bfd-in.h
*** src-old/bfd/bfd-in.h	Fri Dec 21 16:25:38 2001
--- src/bfd/bfd-in.h	Fri Dec 21 16:31:32 2001
*************** extern boolean bfd_xcoff_size_dynamic_se
*** 724,729 ****
--- 724,731 ----
    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.  */
  
diff -rcp src-old/bfd/bfd-in2.h src/bfd/bfd-in2.h
*** src-old/bfd/bfd-in2.h	Fri Dec 21 16:25:38 2001
--- src/bfd/bfd-in2.h	Fri Dec 21 16:52:48 2001
*************** extern boolean bfd_xcoff_size_dynamic_se
*** 730,735 ****
--- 730,737 ----
    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.  */
  
diff -rcp src-old/bfd/coff-rs6000.c src/bfd/coff-rs6000.c
*** src-old/bfd/coff-rs6000.c	Fri Dec 21 16:25:39 2001
--- src/bfd/coff-rs6000.c	Fri Dec 21 16:36:25 2001
*************** xcoff_loader_reloc_offset (abfd, ldhdr)
*** 2918,2923 ****
--- 2918,3171 ----
      (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 */
*************** static const struct xcoff_backend_data_r
*** 3045,3050 ****
--- 3293,3302 ----
      /* 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. */
*************** static const struct xcoff_backend_data_r
*** 3301,3306 ****
--- 3553,3562 ----
    /* glink */
    &xcoff_glink_code[0],
    (36),           /* _xcoff_glink_size */
+ 
+   /* rtinit */
+   0,           /* _xcoff_rtinit_size */
+   xcoff_generate_rtinit,  /* _xcoff_generate_rtinit */
  
  };
  
diff -rcp src-old/bfd/coff64-rs6000.c src/bfd/coff64-rs6000.c
*** src-old/bfd/coff64-rs6000.c	Fri Dec 21 16:25:39 2001
--- src/bfd/coff64-rs6000.c	Fri Dec 21 16:40:59 2001
*************** xcoff64_loader_reloc_offset (abfd, ldhdr
*** 2094,2099 ****
--- 2094,2345 ----
    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 =
*************** static const struct xcoff_backend_data_r
*** 2218,2223 ****
--- 2464,2473 ----
    /* glink */
    &xcoff64_glink_code[0],
    40,           /* _xcoff_glink_size */
+ 
+   /* rtinit */
+   88,           /* _xcoff_rtinit_size */
+   xcoff64_generate_rtinit,  /* _xcoff_generate_rtinit */
  
  };
  
diff -rcp src-old/bfd/libxcoff.h src/bfd/libxcoff.h
*** src-old/bfd/libxcoff.h	Fri Dec 21 16:25:42 2001
--- src/bfd/libxcoff.h	Fri Dec 21 16:42:47 2001
*************** struct xcoff_backend_data_rec
*** 112,117 ****
--- 112,120 ----
     */
    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.  */
*************** struct xcoff_backend_data_rec
*** 201,208 ****
--- 204,217 ----
  #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.  */
  
diff -rcp src-old/bfd/xcofflink.c src/bfd/xcofflink.c
*** src-old/bfd/xcofflink.c	Fri Dec 21 16:25:43 2001
--- src/bfd/xcofflink.c	Fri Dec 21 16:45:30 2001
*************** bfd_xcoff_size_dynamic_sections (output_
*** 3219,3224 ****
--- 3219,3259 ----
    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

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.
 
diff -rcp src-old/ld/emultempl/aix.em src/ld/emultempl/aix.em
*** src-old/ld/emultempl/aix.em	Fri Dec 21 16:26:15 2001
--- src/ld/emultempl/aix.em	Fri Dec 21 16:50:26 2001
*************** static void gld${EMULATION_NAME}_find_ex
*** 67,72 ****
--- 67,74 ----
  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 *));
  
*************** static int is_64bit = 0;
*** 126,131 ****
--- 128,136 ----
  /* 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
*************** gld${EMULATION_NAME}_before_parse ()
*** 144,154 ****
  #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.
!    */
    link_info.init_function = NULL;
    link_info.fini_function = NULL;
  
--- 149,158 ----
  #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.  */ 
! 
    link_info.init_function = NULL;
    link_info.fini_function = NULL;
  
*************** gld${EMULATION_NAME}_parse_args (argc, a
*** 192,242 ****
      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"
! 
!    */
  
    static const struct option longopts[] = {
      {"basis", no_argument, NULL, OPTION_IGNORE},
--- 196,209 ----
      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 gnu linker
!      generates this symbol and makes it the first loader symbol.  */
  
    static const struct option longopts[] = {
      {"basis", no_argument, NULL, OPTION_IGNORE},
*************** fi
*** 1319,1324 ****
--- 1286,1324 ----
  
  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,
*************** struct ld_emulation_xfer_struct ld_${EMU
*** 1333,1339 ****
    "${EMULATION_NAME}",
    "${OUTPUT_FORMAT}",
    0,				/* finish */
!   0,				/* create_output_section_statements */
    0,				/* open_dynamic_archive */
    0,				/* place_orphan */
    0,				/* set_symbols */
--- 1333,1339 ----
    "${EMULATION_NAME}",
    "${OUTPUT_FORMAT}",
    0,				/* finish */
!   gld${EMULATION_NAME}_create_output_section_statements,
    0,				/* open_dynamic_archive */
    0,				/* place_orphan */
    0,				/* set_symbols */

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]