Unwind support for elf32 on IA64
Steve Ellcey
sje@cup.hp.com
Thu May 3 17:57:00 GMT 2001
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;
}
More information about the Binutils
mailing list