From f37f01cff7bc48542f62a22e47c3e7453b591f13 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 30 May 2003 03:01:12 +0000 Subject: [PATCH] * config/tc-alpha.c (alpha_cur_ent_sym): Remove. (all_frame_data, plast_frame_data, cur_frame_data): New. (s_alpha_ent): Record data for dwarf2 cfi. (s_alpha_end, s_alpha_mask, s_alpha_frame, s_alpha_prologue): Likewise.[ (alpha_elf_md_end): Emit dwarf2 cfi for ecoff unwind directives. * config/tc-alpha.h (md_end): New. (DWARF2_DEFAULT_RETURN_COLUMN): New. (DWARF2_CIE_DATA_ALIGNMENT): New. * gas/alpha/elf-reloc-8.d: Add .eh_frame relocs. * gas/cfi/cfi-alpha-1.d: New. * gas/cfi/cfi-alpha-1.s: New. * gas/cfi/cfi.exp: Run it. --- gas/ChangeLog | 10 ++ gas/config/tc-alpha.c | 218 +++++++++++++++++++++++--- gas/config/tc-alpha.h | 9 +- gas/testsuite/ChangeLog | 7 + gas/testsuite/gas/alpha/elf-reloc-8.d | 21 +++ gas/testsuite/gas/cfi/cfi-alpha-1.d | 26 +++ gas/testsuite/gas/cfi/cfi-alpha-1.s | 28 ++++ gas/testsuite/gas/cfi/cfi.exp | 12 ++ 8 files changed, 311 insertions(+), 20 deletions(-) create mode 100644 gas/testsuite/gas/cfi/cfi-alpha-1.d create mode 100644 gas/testsuite/gas/cfi/cfi-alpha-1.s diff --git a/gas/ChangeLog b/gas/ChangeLog index f4b362749e..fc7d3fdbc0 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,13 @@ +2003-05-29 Richard Henderson + + * config/tc-alpha.c (alpha_cur_ent_sym): Remove. + (all_frame_data, plast_frame_data, cur_frame_data): New. + (s_alpha_ent): Record data for dwarf2 cfi. + (s_alpha_end, s_alpha_mask, s_alpha_frame, s_alpha_prologue): Likewise.[ (alpha_elf_md_end): Emit dwarf2 cfi for ecoff unwind directives. + * config/tc-alpha.h (md_end): New. + (DWARF2_DEFAULT_RETURN_COLUMN): New. + (DWARF2_CIE_DATA_ALIGNMENT): New. + 2003-05-29 Nick Clifton * configure.in: Add i386-*-freebsd* entry. diff --git a/gas/config/tc-alpha.c b/gas/config/tc-alpha.c index fd1a0d8a58..a775c0d597 100644 --- a/gas/config/tc-alpha.c +++ b/gas/config/tc-alpha.c @@ -60,6 +60,7 @@ #ifdef OBJ_ELF #include "elf/alpha.h" #include "dwarf2dbg.h" +#include "dw2gencfi.h" #endif #include "safe-ctype.h" @@ -407,11 +408,6 @@ static symbolS *alpha_lit8_symbol; static offsetT alpha_lit8_literal; #endif -#ifdef OBJ_ELF -/* The active .ent symbol. */ -static symbolS *alpha_cur_ent_sym; -#endif - /* Is the assembler not allowed to use $at? */ static int alpha_noat_on = 0; @@ -4382,6 +4378,25 @@ s_alpha_sdata (ignore) #endif #ifdef OBJ_ELF +struct alpha_elf_frame_data +{ + symbolS *func_sym; + symbolS *func_end_sym; + symbolS *prologue_sym; + unsigned int mask; + unsigned int fmask; + int fp_regno; + int ra_regno; + offsetT frame_size; + offsetT mask_offset; + offsetT fmask_offset; + + struct alpha_elf_frame_data *next; +}; + +static struct alpha_elf_frame_data *all_frame_data; +static struct alpha_elf_frame_data **plast_frame_data = &all_frame_data; +static struct alpha_elf_frame_data *cur_frame_data; /* Handle the .section pseudo-op. This is like the usual one, but it clears alpha_insn_label and restores auto alignment. */ @@ -4418,12 +4433,21 @@ s_alpha_ent (dummy) { symbolS *sym; - if (alpha_cur_ent_sym) + if (cur_frame_data) as_warn (_("nested .ent directives")); sym = symbol_find_or_make (name); symbol_get_bfdsym (sym)->flags |= BSF_FUNCTION; - alpha_cur_ent_sym = sym; + + cur_frame_data = calloc (1, sizeof (*cur_frame_data)); + cur_frame_data->func_sym = sym; + + /* Provide sensible defaults. */ + cur_frame_data->fp_regno = 30; /* sp */ + cur_frame_data->ra_regno = 26; /* ra */ + + *plast_frame_data = cur_frame_data; + plast_frame_data = &cur_frame_data->next; /* The .ent directive is sometimes followed by a number. Not sure what it really means, but ignore it. */ @@ -4463,22 +4487,27 @@ s_alpha_end (dummy) symbolS *sym; sym = symbol_find (name); - if (sym != alpha_cur_ent_sym) + if (!cur_frame_data) + as_warn (_(".end directive without matching .ent")); + else if (sym != cur_frame_data->func_sym) as_warn (_(".end directive names different symbol than .ent")); /* Create an expression to calculate the size of the function. */ if (sym) { - symbol_get_obj (sym)->size = - (expressionS *) xmalloc (sizeof (expressionS)); - symbol_get_obj (sym)->size->X_op = O_subtract; - symbol_get_obj (sym)->size->X_add_symbol - = symbol_new ("L0\001", now_seg, frag_now_fix (), frag_now); - symbol_get_obj (sym)->size->X_op_symbol = sym; - symbol_get_obj (sym)->size->X_add_number = 0; + OBJ_SYMFIELD_TYPE *obj = symbol_get_obj (sym); + expressionS *exp = xmalloc (sizeof (expressionS)); + + obj->size = exp; + exp->X_op = O_subtract; + exp->X_add_symbol = symbol_temp_new_now (); + exp->X_op_symbol = sym; + exp->X_add_number = 0; + + cur_frame_data->func_end_sym = exp->X_add_symbol; } - alpha_cur_ent_sym = NULL; + cur_frame_data = NULL; *input_line_pointer = name_end; } @@ -4498,7 +4527,45 @@ s_alpha_mask (fp) ecoff_directive_mask (0); } else - discard_rest_of_line (); + { + long val; + offsetT offset; + + if (!cur_frame_data) + { + if (fp) + as_warn (_(".fmask outside of .ent")); + else + as_warn (_(".mask outside of .ent")); + discard_rest_of_line (); + return; + } + + if (get_absolute_expression_and_terminator (&val) != ',') + { + if (fp) + as_warn (_("bad .fmask directive")); + else + as_warn (_("bad .mask directive")); + --input_line_pointer; + discard_rest_of_line (); + return; + } + + offset = get_absolute_expression (); + demand_empty_rest_of_line (); + + if (fp) + { + cur_frame_data->fmask = val; + cur_frame_data->fmask_offset = offset; + } + else + { + cur_frame_data->mask = val; + cur_frame_data->mask_offset = offset; + } + } } static void @@ -4508,7 +4575,36 @@ s_alpha_frame (dummy) if (ECOFF_DEBUGGING) ecoff_directive_frame (0); else - discard_rest_of_line (); + { + long val; + + if (!cur_frame_data) + { + as_warn (_(".frame outside of .ent")); + discard_rest_of_line (); + return; + } + + cur_frame_data->fp_regno = tc_get_register (1); + + SKIP_WHITESPACE (); + if (*input_line_pointer++ != ',' + || get_absolute_expression_and_terminator (&val) != ',') + { + as_warn (_("bad .frame directive")); + --input_line_pointer; + discard_rest_of_line (); + return; + } + cur_frame_data->frame_size = val; + + cur_frame_data->ra_regno = tc_get_register (0); + + /* Next comes the "offset of saved $a0 from $sp". In gcc terms + this is current_function_pretend_args_size. There's no place + to put this value, so ignore it. */ + s_ignore (42); + } } static void @@ -4524,7 +4620,7 @@ s_alpha_prologue (ignore) if (ECOFF_DEBUGGING) sym = ecoff_get_cur_proc_sym (); else - sym = alpha_cur_ent_sym; + sym = cur_frame_data ? cur_frame_data->func_sym : NULL; if (sym == NULL) { @@ -4549,6 +4645,9 @@ s_alpha_prologue (ignore) as_bad (_("Invalid argument %d to .prologue."), arg); break; } + + if (cur_frame_data) + cur_frame_data->prologue_sym = symbol_temp_new_now (); } static char *first_file_directive; @@ -4642,6 +4741,87 @@ s_alpha_coff_wrapper (which) ignore_rest_of_line (); } } + +/* Called at the end of assembly. Here we emit unwind info for frames + unless the compiler has done it for us. */ + +void +alpha_elf_md_end (void) +{ + struct alpha_elf_frame_data *p; + + if (cur_frame_data) + as_warn (_(".ent directive without matching .end")); + + /* If someone has generated the unwind info themselves, great. */ + if (bfd_get_section_by_name (stdoutput, ".eh_frame") != NULL) + return; + + /* Generate .eh_frame data for the unwind directives specified. */ + for (p = all_frame_data; p ; p = p->next) + if (p->prologue_sym) + { + /* Create a temporary symbol at the same location as our + function symbol. This prevents problems with globals. */ + cfi_new_fde (symbol_temp_new (S_GET_SEGMENT (p->func_sym), + S_GET_VALUE (p->func_sym), + symbol_get_frag (p->func_sym))); + + cfi_set_return_column (p->ra_regno); + cfi_add_CFA_def_cfa_register (30); + if (p->fp_regno != 30 || p->mask || p->fmask || p->frame_size) + { + unsigned int mask; + offsetT offset; + + cfi_add_advance_loc (p->prologue_sym); + + if (p->fp_regno != 30) + if (p->frame_size != 0) + cfi_add_CFA_def_cfa (p->fp_regno, p->frame_size); + else + cfi_add_CFA_def_cfa_register (p->fp_regno); + else if (p->frame_size != 0) + cfi_add_CFA_def_cfa_offset (p->frame_size); + + mask = p->mask; + offset = p->mask_offset; + + /* Recall that $26 is special-cased and stored first. */ + if ((mask >> 26) & 1) + { + cfi_add_CFA_offset (26, offset); + offset += 8; + mask &= ~(1 << 26); + } + while (mask) + { + unsigned int i; + i = mask & -mask; + mask ^= i; + i = ffs (i) - 1; + + cfi_add_CFA_offset (i, offset); + offset += 8; + } + + mask = p->fmask; + offset = p->fmask_offset; + while (mask) + { + unsigned int i; + i = mask & -mask; + mask ^= i; + i = ffs (i) - 1; + + cfi_add_CFA_offset (i + 32, offset); + offset += 8; + } + } + + cfi_end_fde (p->func_end_sym); + } +} #endif /* OBJ_ELF */ #ifdef OBJ_EVAX diff --git a/gas/config/tc-alpha.h b/gas/config/tc-alpha.h index e126413df6..44ccd4eded 100644 --- a/gas/config/tc-alpha.h +++ b/gas/config/tc-alpha.h @@ -128,6 +128,11 @@ extern flagword alpha_elf_section_flags PARAMS ((flagword, int, int)); #define tc_frob_file_before_fix() alpha_before_fix () extern void alpha_before_fix PARAMS ((void)); +#ifdef OBJ_ELF +#define md_end alpha_elf_md_end +extern void alpha_elf_md_end PARAMS ((void)); +#endif + /* New fields for supporting explicit relocations (such as !literal to mark where a pointer is loaded from the global table, and !lituse_base to track all of the normal uses of that pointer). */ @@ -156,4 +161,6 @@ do { \ (long) FIX->tc_fix_data.next_reloc); \ } while (0) -#define DWARF2_LINE_MIN_INSN_LENGTH 4 +#define DWARF2_LINE_MIN_INSN_LENGTH 4 +#define DWARF2_DEFAULT_RETURN_COLUMN 26 +#define DWARF2_CIE_DATA_ALIGNMENT -8 diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog index 5a7cbe0515..11f87453c4 100644 --- a/gas/testsuite/ChangeLog +++ b/gas/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2003-05-29 Richard Henderson + + * gas/alpha/elf-reloc-8.d: Add .eh_frame relocs. + * gas/cfi/cfi-alpha-1.d: New. + * gas/cfi/cfi-alpha-1.s: New. + * gas/cfi/cfi.exp: Run it. + 2003-05-27 Richard Henderson * gas/cfi/cfi-i386.d: Update for dw2gencfi rewrite. diff --git a/gas/testsuite/gas/alpha/elf-reloc-8.d b/gas/testsuite/gas/alpha/elf-reloc-8.d index e95e8edf2a..de5e0e8859 100644 --- a/gas/testsuite/gas/alpha/elf-reloc-8.d +++ b/gas/testsuite/gas/alpha/elf-reloc-8.d @@ -307,3 +307,24 @@ OFFSET *TYPE *VALUE 0*0000048 REFQUAD \.init\.text\+0x0*00005f0 0*0000050 REFQUAD \.init\.data\+0x0*0000029 0*0000058 REFQUAD \.init\.text\+0x0*0000610 + + +RELOCATION RECORDS FOR \[\.eh_frame\]: +OFFSET *TYPE *VALUE +0*000001c SREL32 \.init\.text\+0xf*ffffff8 +0*0000034 SREL32 \.init\.text\+0x0*0000048 +0*0000048 SREL32 \.init\.text\+0x0*0000078 +0*000005c SREL32 \.init\.text\+0x0*00000a8 +0*0000080 SREL32 \.init\.text\+0x0*00002b8 +0*00000a0 SREL32 \.init\.text\+0x0*0000598 +0*00000b8 SREL32 \.init\.text\+0x0*00005e8 +0*00000cc SREL32 \.init\.text\+0x0*0000608 +0*00000e0 SREL32 \.init\.text\+0x0*0000628 +0*00000fc SREL32 \.init\.text\+0x0*0000748 +0*0000120 SREL32 \.init\.text\+0x0*0000988 +0*000013c SREL32 \.init\.text\+0x0*0000a08 +0*0000150 SREL32 \.init\.text\+0x0*0000a18 +0*0000164 SREL32 \.init\.text\+0x0*0000a38 +0*000017c SREL32 \.init\.text\+0x0*0000a88 +0*0000190 SREL32 \.init\.text\+0x0*0000a98 +0*00001a4 SREL32 \.text\+0xf*ffffff8 diff --git a/gas/testsuite/gas/cfi/cfi-alpha-1.d b/gas/testsuite/gas/cfi/cfi-alpha-1.d new file mode 100644 index 0000000000..32c43079f0 --- /dev/null +++ b/gas/testsuite/gas/cfi/cfi-alpha-1.d @@ -0,0 +1,26 @@ +#readelf: -wf +#name: CFI on alpha +The section .eh_frame contains: + +00000000 00000010 00000000 CIE + Version: 1 + Augmentation: "zR" + Code alignment factor: 4 + Data alignment factor: -8 + Return address column: 26 + Augmentation data: 1b + + DW_CFA_def_cfa_reg: r30 + DW_CFA_nop + +00000014 0000001c 00000018 FDE cie=00000000 pc=0000001c..00000050 + DW_CFA_advance_loc: 24 to 00000034 + DW_CFA_def_cfa: r15 ofs 32 + DW_CFA_offset: r26 at cfa-32 + DW_CFA_offset: r9 at cfa-24 + DW_CFA_offset: r15 at cfa-16 + DW_CFA_offset: r34 at cfa-8 + DW_CFA_nop + DW_CFA_nop + DW_CFA_nop + diff --git a/gas/testsuite/gas/cfi/cfi-alpha-1.s b/gas/testsuite/gas/cfi/cfi-alpha-1.s new file mode 100644 index 0000000000..34e28ce883 --- /dev/null +++ b/gas/testsuite/gas/cfi/cfi-alpha-1.s @@ -0,0 +1,28 @@ + .file 1 "z.c" + .set noat + .set noreorder +.text + .align 4 + .globl f + .ent f +$f..ng: +f: + .frame $15,32,$26,0 + .mask 0x4008200,-32 + .fmask 0x4,-8 + lda $30,-32($30) + stq $26,0($30) + stq $9,8($30) + stq $15,16($30) + stt $f2,24($30) + mov $30,$15 + .prologue 0 + mov $15,$30 + ldq $26,0($30) + ldq $9,8($30) + ldt $f2,24($30) + ldq $15,16($30) + lda $30,32($30) + ret $31,($26),1 + .end f + .ident "GCC: (GNU) 2.96 20000731 (Red Hat Linux 7.2 2.96-112.7.1)" diff --git a/gas/testsuite/gas/cfi/cfi.exp b/gas/testsuite/gas/cfi/cfi.exp index 4d1b95d788..d52803f4dc 100644 --- a/gas/testsuite/gas/cfi/cfi.exp +++ b/gas/testsuite/gas/cfi/cfi.exp @@ -5,3 +5,15 @@ if [istarget "x86_64-*"] then { if [istarget "i?86-*"] then { run_dump_test "cfi-i386" } + +if { [istarget alpha*-*-*] } then { + + set elf [expr [istarget *-*-elf*] \ + || [istarget *-*-linux*] \ + || [istarget *-*-freebsd*] \ + || [istarget *-*-netbsd*] ] + + if $elf { + run_dump_test "cfi-alpha-1" + } +}