From 557debbaef77b05e3206d7bc6ae679e297182573 Mon Sep 17 00:00:00 2001 From: Jim Wilson Date: Fri, 6 Jul 2001 07:32:42 +0000 Subject: [PATCH] 32-bit unwind data for ia64-hpux, from Steve Ellcey * 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. --- gas/ChangeLog | 13 +++++++ gas/config/tc-ia64.c | 106 +++++++++++++++++++++++++++++++++++---------------- 2 files changed, 86 insertions(+), 33 deletions(-) diff --git a/gas/ChangeLog b/gas/ChangeLog index 60484bf..860b8a8 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,16 @@ +2001-07-05 Steve Ellcey + + * 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. + 2001-07-05 Ben Elliston * README (Supported platforms): m88k no longer suffers bitrot. diff --git a/gas/config/tc-ia64.c b/gas/config/tc-ia64.c index a3a9872..4cac5bc 100644 --- a/gas/config/tc-ia64.c +++ b/gas/config/tc-ia64.c @@ -61,13 +61,17 @@ 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 + SPECIAL_SECTION_UNWIND_INFO, + /* HPUX specific section pseudo-ops. */ + SPECIAL_SECTION_INIT_ARRAY, + SPECIAL_SECTION_FINI_ARRAY, }; enum reloc_func @@ -279,6 +283,9 @@ static struct 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; @@ -523,7 +530,8 @@ static const bfd_vma nop[IA64_NUM_UNITS] = static char special_section_name[][20] = { {".bss"}, {".sbss"}, {".sdata"}, {".rodata"}, {".comment"}, - {".IA_64.unwind"}, {".IA_64.unwind_info"} + {".IA_64.unwind"}, {".IA_64.unwind_info"}, + {".init_array"}, {".fini_array"} }; static char *special_linkonce_name[] = @@ -2757,6 +2765,37 @@ fixup_unw_records (list) } } +/* 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. */ @@ -2765,7 +2804,7 @@ output_unw_records (list, ptr) unw_rec_list *list; void **ptr; { - int size, x, extra = 0; + int size, extra; unsigned char *mem; *ptr = NULL; @@ -2774,35 +2813,17 @@ output_unw_records (list, ptr) 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); + extra = setup_unwind_header(size, &mem); 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; + size += extra + 8 + md.pointer_size; } return size; } @@ -3171,9 +3192,9 @@ generate_unwind_image (text_name) /* 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 (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) { @@ -3186,9 +3207,10 @@ generate_unwind_image (text_name) 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); + /* 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 (); @@ -3894,11 +3916,14 @@ dot_endp (dummy) 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); + /* Make sure that section has 4 byte alignment for ILP32 and + 8 byte alignment for LP64. */ + record_alignment (now_seg, md.pointer_size_shift); - ptr = frag_more (24); - where = frag_now_fix () - 24; + /* 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. */ @@ -4606,6 +4631,8 @@ const pseudo_typeS md_pseudo_table[] = { "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 }, @@ -6483,6 +6510,19 @@ md_begin () 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; -- 2.7.4