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]

Unwind support for elf32 on IA64



Here is a change to gas/config/tc-ia64.c to support unwind on elf32 on
ia64.  This is for HP-UX where we support both elf32 and elf64 on IA64.
It also has support for .fini_array and .init_array sections which we
use on HP-UX.  Can someone review it and check it in if it is OK?

Steve Ellcey
sje@cup.hp.com



2001-05-03  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): Modify to use md.pointer_size and
	md.pointer_size_shift.
	(md_begin): Initialize md.pointer_size and md.pointer_size_shift.

*** tc-ia64.c.orig	Thu May  3 17:03:20 2001
--- tc-ia64.c	Thu May  3 17:42:08 2001
*************** enum special_section
*** 65,70 ****
--- 65,72 ----
      SPECIAL_SECTION_SBSS,
      SPECIAL_SECTION_SDATA,
      SPECIAL_SECTION_RODATA,
+     SPECIAL_SECTION_INIT_ARRAY,
+     SPECIAL_SECTION_FINI_ARRAY,
      SPECIAL_SECTION_COMMENT,
      SPECIAL_SECTION_UNWIND,
      SPECIAL_SECTION_UNWIND_INFO
*************** static struct
*** 279,284 ****
--- 281,289 ----
        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]
*** 522,528 ****
     habit of setting temporary sentinels.  */
  static char special_section_name[][20] =
    {
!     {".bss"}, {".sbss"}, {".sdata"}, {".rodata"}, {".comment"},
      {".IA_64.unwind"}, {".IA_64.unwind_info"}
    };
  
--- 527,534 ----
     habit of setting temporary sentinels.  */
  static char special_section_name[][20] =
    {
!     {".bss"}, {".sbss"}, {".sdata"}, {".rodata"},
!     {".init_array"}, {".fini_array"}, {".comment"},
      {".IA_64.unwind"}, {".IA_64.unwind_info"}
    };
  
*************** static int output_unw_records PARAMS ((u
*** 844,849 ****
--- 850,856 ----
  static int convert_expr_to_ab_reg PARAMS ((expressionS *, unsigned int *, unsigned int *));
  static int convert_expr_to_xy_reg PARAMS ((expressionS *, unsigned int *, unsigned int *));
  static int generate_unwind_image PARAMS ((const char *));
+ static int setup_unwind_header PARAMS ((int size, unsigned char **));
  
  /* Build the unwind section name by appending the (possibly stripped)
     text section NAME to the unwind PREFIX.  The resulting string
*************** output_unw_records (list, ptr)
*** 2743,2749 ****
       unw_rec_list *list;
       void **ptr;
  {
!   int size, x, extra = 0;
    unsigned char *mem;
  
    *ptr = NULL;
--- 2750,2756 ----
       unw_rec_list *list;
       void **ptr;
  {
!   int size, extra;
    unsigned char *mem;
  
    *ptr = NULL;
*************** output_unw_records (list, ptr)
*** 2752,2786 ****
    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;
  }
--- 2759,2773 ----
    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);
        process_unw_records (list, output_vbyte_mem);
  
        *ptr = mem;
  
!       size += extra + 8 + md.pointer_size;
      }
    return size;
  }
*************** generate_unwind_image (text_name)
*** 3149,3157 ****
  
    /* 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)
      {
--- 3136,3146 ----
  
    /* 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)
*** 3164,3171 ****
        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);
  
        /* Set expression which points to start of unwind descriptor area.  */
        unwind.info = expr_build_dot ();
--- 3153,3161 ----
        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);
  
        /* Set expression which points to start of unwind descriptor area.  */
        unwind.info = expr_build_dot ();
*************** dot_endp (dummy)
*** 3869,3879 ****
        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. */
--- 3859,3874 ----
        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, 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[] =
*** 4578,4583 ****
--- 4573,4580 ----
      { "sbss", dot_special_section, SPECIAL_SECTION_SBSS },
      { "sdata", dot_special_section, SPECIAL_SECTION_SDATA },
      { "rodata", dot_special_section, SPECIAL_SECTION_RODATA },
+     { "init_array", dot_special_section, SPECIAL_SECTION_INIT_ARRAY },
+     { "fini_array", dot_special_section, SPECIAL_SECTION_FINI_ARRAY },
      { "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 },
*************** md_begin ()
*** 6449,6458 ****
--- 6446,6469 ----
    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;
    md.maxpaths = 0;
    md.entry_labels = NULL;
+ 
  }
  
  /* Set the elf type to 64 bit ABI by default.  Cannot do this in md_begin
*************** ia64_handle_align (fragp)
*** 10158,10161 ****
--- 10169,10202 ----
  
    memcpy (p, (target_big_endian ? be_nop : le_nop), 16);
    fragp->fr_var = 16;
+ }
+ 
+ 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);
+ 
+   vbyte_mem_ptr = *mem + 8;
+ 
+   /* 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;
  }


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