alpha dwarf2 cfi support

Richard Henderson rth@twiddle.net
Fri May 30 07:28:00 GMT 2003


I should, I suppose, eventually add the .cfi directives as well,
since they allow more freedom.  However, for most purposes 
re-using the ecoff directives is easier for users, and also
automatically works with lots of extant assembly files.


r~


        * 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.

Index: config/tc-alpha.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-alpha.c,v
retrieving revision 1.56
diff -c -p -d -r1.56 tc-alpha.c
*** config/tc-alpha.c	3 May 2003 16:04:11 -0000	1.56
--- config/tc-alpha.c	30 May 2003 02:55:40 -0000
***************
*** 60,65 ****
--- 60,66 ----
  #ifdef OBJ_ELF
  #include "elf/alpha.h"
  #include "dwarf2dbg.h"
+ #include "dw2gencfi.h"
  #endif
  
  #include "safe-ctype.h"
*************** static symbolS *alpha_lit8_symbol;
*** 407,417 ****
  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;
  
--- 408,413 ----
*************** s_alpha_sdata (ignore)
*** 4382,4387 ****
--- 4378,4402 ----
  #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.  */
*************** s_alpha_ent (dummy)
*** 4418,4429 ****
  	{
  	  symbolS *sym;
  
! 	  if (alpha_cur_ent_sym)
  	    as_warn (_("nested .ent directives"));
  
  	  sym = symbol_find_or_make (name);
  	  symbol_get_bfdsym (sym)->flags |= BSF_FUNCTION;
! 	  alpha_cur_ent_sym = sym;
  
  	  /* The .ent directive is sometimes followed by a number.  Not sure
  	     what it really means, but ignore it.  */
--- 4433,4453 ----
  	{
  	  symbolS *sym;
  
! 	  if (cur_frame_data)
  	    as_warn (_("nested .ent directives"));
  
  	  sym = symbol_find_or_make (name);
  	  symbol_get_bfdsym (sym)->flags |= BSF_FUNCTION;
! 
! 	  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.  */
*************** s_alpha_end (dummy)
*** 4463,4484 ****
  	  symbolS *sym;
  
  	  sym = symbol_find (name);
! 	  if (sym != alpha_cur_ent_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;
  	    }
  
! 	  alpha_cur_ent_sym = NULL;
  
  	  *input_line_pointer = name_end;
  	}
--- 4487,4513 ----
  	  symbolS *sym;
  
  	  sym = symbol_find (name);
! 	  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)
  	    {
! 	      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;
  	    }
  
! 	  cur_frame_data = NULL;
  
  	  *input_line_pointer = name_end;
  	}
*************** s_alpha_mask (fp)
*** 4498,4504 ****
  	ecoff_directive_mask (0);
      }
    else
!     discard_rest_of_line ();
  }
  
  static void
--- 4527,4571 ----
  	ecoff_directive_mask (0);
      }
    else
!     {
!       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
*************** s_alpha_frame (dummy)
*** 4508,4514 ****
    if (ECOFF_DEBUGGING)
      ecoff_directive_frame (0);
    else
!     discard_rest_of_line ();
  }
  
  static void
--- 4575,4610 ----
    if (ECOFF_DEBUGGING)
      ecoff_directive_frame (0);
    else
!     {
!       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
*************** s_alpha_prologue (ignore)
*** 4524,4530 ****
    if (ECOFF_DEBUGGING)
      sym = ecoff_get_cur_proc_sym ();
    else
!     sym = alpha_cur_ent_sym;
  
    if (sym == NULL)
      {
--- 4620,4626 ----
    if (ECOFF_DEBUGGING)
      sym = ecoff_get_cur_proc_sym ();
    else
!     sym = cur_frame_data ? cur_frame_data->func_sym : NULL;
  
    if (sym == NULL)
      {
*************** s_alpha_prologue (ignore)
*** 4549,4554 ****
--- 4645,4653 ----
        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;
*************** s_alpha_coff_wrapper (which)
*** 4641,4646 ****
--- 4740,4826 ----
        as_bad (_("ECOFF debugging is disabled."));
        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 */
  
Index: config/tc-alpha.h
===================================================================
RCS file: /cvs/src/src/gas/config/tc-alpha.h,v
retrieving revision 1.16
diff -c -p -d -r1.16 tc-alpha.h
*** config/tc-alpha.h	7 Nov 2002 00:42:18 -0000	1.16
--- config/tc-alpha.h	30 May 2003 02:55:40 -0000
*************** extern flagword alpha_elf_section_flags 
*** 128,133 ****
--- 128,138 ----
  #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).  */
*************** do {									\
*** 156,159 ****
  	     (long) FIX->tc_fix_data.next_reloc);			\
  } while (0)
  
! #define DWARF2_LINE_MIN_INSN_LENGTH 4
--- 161,166 ----
  	     (long) FIX->tc_fix_data.next_reloc);			\
  } while (0)
  
! #define DWARF2_LINE_MIN_INSN_LENGTH	4
! #define DWARF2_DEFAULT_RETURN_COLUMN	26
! #define DWARF2_CIE_DATA_ALIGNMENT	-8
Index: testsuite/gas/alpha/elf-reloc-8.d
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/alpha/elf-reloc-8.d,v
retrieving revision 1.1
diff -c -p -d -r1.1 elf-reloc-8.d
*** testsuite/gas/alpha/elf-reloc-8.d	7 Nov 2002 00:42:19 -0000	1.1
--- testsuite/gas/alpha/elf-reloc-8.d	30 May 2003 02:55:41 -0000
*************** OFFSET *TYPE *VALUE 
*** 307,309 ****
--- 307,330 ----
  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
Index: testsuite/gas/cfi/cfi-alpha-1.d
===================================================================
RCS file: testsuite/gas/cfi/cfi-alpha-1.d
diff -N testsuite/gas/cfi/cfi-alpha-1.d
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/gas/cfi/cfi-alpha-1.d	30 May 2003 02:55:41 -0000
***************
*** 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
+ 
Index: testsuite/gas/cfi/cfi-alpha-1.s
===================================================================
RCS file: testsuite/gas/cfi/cfi-alpha-1.s
diff -N testsuite/gas/cfi/cfi-alpha-1.s
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/gas/cfi/cfi-alpha-1.s	30 May 2003 02:55:41 -0000
***************
*** 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)"
Index: testsuite/gas/cfi/cfi.exp
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/cfi/cfi.exp,v
retrieving revision 1.1
diff -c -p -d -r1.1 cfi.exp
*** testsuite/gas/cfi/cfi.exp	20 May 2003 08:01:19 -0000	1.1
--- testsuite/gas/cfi/cfi.exp	30 May 2003 02:55:41 -0000
*************** if [istarget "x86_64-*"] then {
*** 5,7 ****
--- 5,19 ----
  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"
+     }
+ }



More information about the Binutils mailing list