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]

Re: Unwind support for elf32 on IA64


This is a response to
<http://sources.redhat.com/ml/binutils/2001-05/msg00058.html>

Overall the patch looks OK, but I have a number of minor issues with it.

You put .init_array and .fini_array in the middle of the current list of
sections.  The existing sections are mostly specified by the assembler
reference manual explicitly, except the unwind sections which are there by
popular agreement.  There is no justification for .init_array/.fini_array
other than the fact that HPUX needs them, and it wasn't stated why HPUX needs
them.  However, I'm assuming they are for DT_INIT_ARRAY/DT_FINI_ARRAY, and
hence are generally useful.  I moved them to the end, and added a comment to
document that they are needed by HPUX.  If they cause problems, they will
have to be enabled only for HPUX.

You put the new function setup_unwind_header at the end of the file.  However,
it is only called by one function.  It makes more sense to put it immediately
before the function that calls it.  This eliminates the need for the prototype.
I also added an explanatory comment as required by GNU coding conventions.

You put the store to vbyte_mem_ptr into setup_unwind_header.  However, this is
part of the call to output_vbyte_mem which wasn't moved, so I put it back in
output_unw_records immediately before the output_vbyte_mem call.

Your patch modifies dot_endp, but you did not mention this in your ChangeLog
entry.

The patch needed a few modifications to apply to current sources.

I don't have access to ia64-hpux, so I can't test that.  I did test the
patch against the ia64-linux binutils testsuites (no regressions) and the
g++ testsuite (no regressions).

Here is the patch I checked in.

2001-06-05  Steve Ellcey  <sje@cup.hp.com>

	* config/tc-ia64.c (special_section): Add SPECIAL_SECTION_INIT_ARRAY
	and SPECIAL_SECTION_FINI_ARRAY.
	(special_section_name): Add .init_array and .fini_array.
	(md_pseudo_table): Add init_array and fini_array.
	(md): Add pointer_size and pointer_size_shift fields.
	(setup_unwind_header): New static function.
	(output_unw_records): Modify to use setup_unwind_header.
	(generate_unwind_image, dot_endp): Modify to use md.pointer_size and
	md.pointer_size_shift.
	(md_begin): Initialize md.pointer_size and md.pointer_size_shift.

Index: tc-ia64.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-ia64.c,v
retrieving revision 1.53
diff -p -r1.53 tc-ia64.c
*** tc-ia64.c	2001/07/05 03:34:42	1.53
--- tc-ia64.c	2001/07/06 01:37:33
***************
*** 61,73 ****
  
  enum special_section
    {
      SPECIAL_SECTION_BSS = 0,
      SPECIAL_SECTION_SBSS,
      SPECIAL_SECTION_SDATA,
      SPECIAL_SECTION_RODATA,
      SPECIAL_SECTION_COMMENT,
      SPECIAL_SECTION_UNWIND,
!     SPECIAL_SECTION_UNWIND_INFO
    };
  
  enum reloc_func
--- 61,77 ----
  
  enum special_section
    {
+     /* IA-64 ABI section pseudo-ops.  */
      SPECIAL_SECTION_BSS = 0,
      SPECIAL_SECTION_SBSS,
      SPECIAL_SECTION_SDATA,
      SPECIAL_SECTION_RODATA,
      SPECIAL_SECTION_COMMENT,
      SPECIAL_SECTION_UNWIND,
!     SPECIAL_SECTION_UNWIND_INFO,
!     /* HPUX specific section pseudo-ops.  */
!     SPECIAL_SECTION_INIT_ARRAY,
!     SPECIAL_SECTION_FINI_ARRAY,
    };
  
  enum reloc_func
*************** static struct
*** 279,284 ****
--- 283,291 ----
        int g_reg_set_conditionally[128];
      } last_groups[3];
      int group_idx;
+ 
+     int pointer_size;       /* size in bytes of a pointer */
+     int pointer_size_shift; /* shift size of a pointer for alignment */
    }
  md;
  
*************** static const bfd_vma nop[IA64_NUM_UNITS]
*** 523,529 ****
  static char special_section_name[][20] =
    {
      {".bss"}, {".sbss"}, {".sdata"}, {".rodata"}, {".comment"},
!     {".IA_64.unwind"}, {".IA_64.unwind_info"}
    };
  
  static char *special_linkonce_name[] =
--- 530,537 ----
  static char special_section_name[][20] =
    {
      {".bss"}, {".sbss"}, {".sdata"}, {".rodata"}, {".comment"},
!     {".IA_64.unwind"}, {".IA_64.unwind_info"},
!     {".init_array"}, {".fini_array"}
    };
  
  static char *special_linkonce_name[] =
*************** fixup_unw_records (list)
*** 2757,2762 ****
--- 2765,2801 ----
      }
  }
  
+ /* Helper routine for output_unw_records.  Emits the header for the unwind
+    info.  */
+ 
+ static int
+ setup_unwind_header(int size, unsigned char **mem)
+ {
+   int x, extra = 0;
+ 
+   /* pad to pointer-size boundry.  */
+   x = size % md.pointer_size;
+   if (x != 0)
+     extra = md.pointer_size - x;
+ 
+   /* Add 8 for the header + a pointer for the 
+      personality offset.  */
+   *mem = xmalloc (size + extra + 8 + md.pointer_size);
+ 
+   /* Clear the padding area and personality.  */
+   memset (*mem + 8 + size, 0 , extra + md.pointer_size);
+   /* Initialize the header area.  */
+ 
+   md_number_to_chars (*mem, (((bfd_vma) 1 << 48)     /* version */
+ 			     | (unwind.personality_routine
+ 				? ((bfd_vma) 3 << 32) /* U & E handler flags */
+ 				: 0)
+ 			     | ((size + extra) / md.pointer_size)), /* length */
+ 		      8);
+ 
+   return extra;
+ }
+ 
  /* Generate an unwind image from a record list.  Returns the number of
     bytes in the resulting image. The memory image itselof is returned
     in the 'ptr' parameter.  */
*************** output_unw_records (list, ptr)
*** 2765,2771 ****
       unw_rec_list *list;
       void **ptr;
  {
!   int size, x, extra = 0;
    unsigned char *mem;
  
    *ptr = NULL;
--- 2804,2810 ----
       unw_rec_list *list;
       void **ptr;
  {
!   int size, extra;
    unsigned char *mem;
  
    *ptr = NULL;
*************** output_unw_records (list, ptr)
*** 2774,2808 ****
    fixup_unw_records (list);
    size = calc_record_size (list);
  
-   /* pad to 8 byte boundry.  */
-   x = size % 8;
-   if (x != 0)
-     extra = 8 - x;
- 
    if (size > 0 || unwind.force_unwind_entry)
      {
        unwind.force_unwind_entry = 0;
  
-       /* Add 8 for the header + 8 more bytes for the personality offset.  */
-       mem = xmalloc (size + extra + 16);
- 
        vbyte_mem_ptr = mem + 8;
-       /* Clear the padding area and personality.  */
-       memset (mem + 8 + size, 0 , extra + 8);
-       /* Initialize the header area.  */
-       md_number_to_chars (mem,
- 			  (((bfd_vma) 1 << 48)     /* version */
- 			   | (unwind.personality_routine
- 			      ? ((bfd_vma) 3 << 32) /* U & E handler flags */
- 			      : 0)
- 			   | ((size + extra) / 8)),  /* length (dwords) */
- 			  8);
- 
        process_unw_records (list, output_vbyte_mem);
  
        *ptr = mem;
  
!       size += extra + 16;
      }
    return size;
  }
--- 2813,2829 ----
    fixup_unw_records (list);
    size = calc_record_size (list);
  
    if (size > 0 || unwind.force_unwind_entry)
      {
        unwind.force_unwind_entry = 0;
+       extra = setup_unwind_header(size, &mem);
  
        vbyte_mem_ptr = mem + 8;
        process_unw_records (list, output_vbyte_mem);
  
        *ptr = mem;
  
!       size += extra + 8 + md.pointer_size;
      }
    return size;
  }
*************** generate_unwind_image (text_name)
*** 3171,3179 ****
  
    /* Generate the unwind record.  */
    size = output_unw_records (unwind.list, (void **) &unw_rec);
!   if (size % 8 != 0)
!     as_bad ("Unwind record is not a multiple of 8 bytes.");
! 
    /* If there are unwind records, switch sections, and output the info.  */
    if (size != 0)
      {
--- 3192,3200 ----
  
    /* Generate the unwind record.  */
    size = output_unw_records (unwind.list, (void **) &unw_rec);
!   if (size % md.pointer_size != 0)
!     as_bad ("Unwind record is not a multiple of %d bytes.", md.pointer_size);
!                       
    /* If there are unwind records, switch sections, and output the info.  */
    if (size != 0)
      {
*************** generate_unwind_image (text_name)
*** 3186,3194 ****
        bfd_set_section_flags (stdoutput, now_seg,
  			     SEC_LOAD | SEC_ALLOC | SEC_READONLY);
  
!       /* Make sure the section has 8 byte alignment.  */
!       frag_align (3, 0, 0);
!       record_alignment (now_seg, 3);
  
        /* Set expression which points to start of unwind descriptor area.  */
        unwind.info = expr_build_dot ();
--- 3207,3216 ----
        bfd_set_section_flags (stdoutput, now_seg,
  			     SEC_LOAD | SEC_ALLOC | SEC_READONLY);
  
!       /* Make sure the section has 4 byte alignment for ILP32 and
! 	 8 byte alignment for LP64.  */
!       frag_align (md.pointer_size_shift, 0, 0);
!       record_alignment (now_seg, md.pointer_size_shift);
  
        /* Set expression which points to start of unwind descriptor area.  */
        unwind.info = expr_build_dot ();
*************** dot_endp (dummy)
*** 3894,3904 ****
        bfd_set_section_flags (stdoutput, now_seg,
  			     SEC_LOAD | SEC_ALLOC | SEC_READONLY);
  
!       /* Make sure the section has 8 byte alignment.  */
!       record_alignment (now_seg, 3);
! 
!       ptr = frag_more (24);
!       where = frag_now_fix () - 24;
        bytes_per_address = bfd_arch_bits_per_address (stdoutput) / 8;
  
        /* Issue the values of  a) Proc Begin, b) Proc End, c) Unwind Record. */
--- 3916,3929 ----
        bfd_set_section_flags (stdoutput, now_seg,
  			     SEC_LOAD | SEC_ALLOC | SEC_READONLY);
  
!       /* Make sure that section has 4 byte alignment for ILP32 and
!          8 byte alignment for LP64.  */
!       record_alignment (now_seg, md.pointer_size_shift);
! 
!       /* Need space for 3 pointers for procedure start, procedure end,
! 	 and unwind info.  */
!       ptr = frag_more (3 * md.pointer_size);
!       where = frag_now_fix () - (3 * md.pointer_size);
        bytes_per_address = bfd_arch_bits_per_address (stdoutput) / 8;
  
        /* Issue the values of  a) Proc Begin, b) Proc End, c) Unwind Record. */
*************** const pseudo_typeS md_pseudo_table[] =
*** 4606,4611 ****
--- 4631,4638 ----
      { "comment", dot_special_section, SPECIAL_SECTION_COMMENT },
      { "ia_64.unwind", dot_special_section, SPECIAL_SECTION_UNWIND },
      { "ia_64.unwind_info", dot_special_section, SPECIAL_SECTION_UNWIND_INFO },
+     { "init_array", dot_special_section, SPECIAL_SECTION_INIT_ARRAY },
+     { "fini_array", dot_special_section, SPECIAL_SECTION_FINI_ARRAY },
      { "proc", dot_proc, 0 },
      { "body", dot_body, 0 },
      { "prologue", dot_prologue, 0 },
*************** md_begin ()
*** 6482,6487 ****
--- 6509,6527 ----
  
    if (! ok)
       as_warn (_("Could not set architecture and machine"));
+ 
+   /* Set the pointer size and pointer shift size depending on md.flags */
+ 
+   if (md.flags & EF_IA_64_ABI64)
+     {
+       md.pointer_size = 8;         /* pointers are 8 bytes */
+       md.pointer_size_shift = 3;   /* alignment is 8 bytes = 2^2 */
+     }
+   else
+     {
+       md.pointer_size = 4;         /* pointers are 4 bytes */
+       md.pointer_size_shift = 2;   /* alignment is 4 bytes = 2^2 */
+     }
  
    md.mem_offset.hint = 0;
    md.path = 0;


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