Re: CFI directives support in binutils

2017-04-17 Thread Joerg Sonnenberger
On Mon, Apr 17, 2017 at 10:45:37PM +0200, Mark Kettenis wrote:
> This diff extends the support for CFI in binutils with a few
> directives emitted by clang.  Most of the code is stolen from
> FreeBSD's GPLv2 binutils.  Support for the .cfi_sections directive is
> incomplete; basically we just ignore it.  Our binutils only support
> emitting frame info in the .eh_frame section.  Debuggers tend to fall
> back on .eh_frame if .dwarf_frame is missing, so this shouldn't be a
> problem.

The primary difference is that you can't easily strip .eh_frame from a
binary, so it adds overhead.

> This diff is necessary to build/use clang on sparc64 as there
> currently isn't an integrated assembler for the sparc64 target in
> llvm.

It exists, but it is missing parsing for a couple of tricky
instructions. Given that some central headers on NetBSD use inline
assembler with those, it never was very useful for me to enable IAS as
default on sparc64.

Joerg



CFI directives support in binutils

2017-04-17 Thread Mark Kettenis
This diff extends the support for CFI in binutils with a few
directives emitted by clang.  Most of the code is stolen from
FreeBSD's GPLv2 binutils.  Support for the .cfi_sections directive is
incomplete; basically we just ignore it.  Our binutils only support
emitting frame info in the .eh_frame section.  Debuggers tend to fall
back on .eh_frame if .dwarf_frame is missing, so this shouldn't be a
problem.  There is a small chance that a port will do an autoconf
check for this directive and make the wrong decision as the result of
this incomplete implementation.  The only autoconf check I can find
was in glibc though, so I'm not really worried.

This diff is necessary to build/use clang on sparc64 as there
currently isn't an integrated assembler for the sparc64 target in
llvm.

ok?


Index: gnu/usr.bin/binutils-2.17/gas/dw2gencfi.c
===
RCS file: /cvs/src/gnu/usr.bin/binutils-2.17/gas/dw2gencfi.c,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 dw2gencfi.c
--- gnu/usr.bin/binutils-2.17/gas/dw2gencfi.c   24 Apr 2011 20:14:44 -  
1.1.1.1
+++ gnu/usr.bin/binutils-2.17/gas/dw2gencfi.c   17 Apr 2017 20:32:56 -
@@ -21,6 +21,7 @@
 
 #include "as.h"
 #include "dw2gencfi.h"
+#include "subsegs.h"
 
 
 /* We re-use DWARF2_LINE_MIN_INSN_LENGTH for the code alignment field
@@ -87,6 +88,10 @@ struct fde_entry
   symbolS *end_address;
   struct cfi_insn_data *data;
   struct cfi_insn_data **last;
+  unsigned char per_encoding;
+  unsigned char lsda_encoding;
+  expressionS personality;
+  expressionS lsda;
   unsigned int return_column;
   unsigned int signal_frame;
 };
@@ -97,15 +102,13 @@ struct cie_entry
   symbolS *start_address;
   unsigned int return_column;
   unsigned int signal_frame;
+  unsigned char per_encoding;
+  unsigned char lsda_encoding;
+  expressionS personality;
   struct cfi_insn_data *first, *last;
 };
 
 
-/* Current open FDE entry.  */
-static struct fde_entry *cur_fde_data;
-static symbolS *last_address;
-static offsetT cur_cfa_offset;
-
 /* List of FDE entries.  */
 static struct fde_entry *all_fde_data;
 static struct fde_entry **last_fde_data = &all_fde_data;
@@ -120,7 +123,14 @@ struct cfa_save_data
   offsetT cfa_offset;
 };
 
-static struct cfa_save_data *cfa_save_stack;
+/* Current open FDE entry.  */
+struct frch_cfi_data
+{
+  struct fde_entry *cur_fde_data;
+  symbolS *last_address;
+  offsetT cur_cfa_offset;
+  struct cfa_save_data *cfa_save_stack;
+};
 
 /* Construct a new FDE structure and add it to the end of the fde list.  */
 
@@ -129,12 +139,15 @@ alloc_fde_entry (void)
 {
   struct fde_entry *fde = xcalloc (1, sizeof (struct fde_entry));
 
-  cur_fde_data = fde;
+  frchain_now->frch_cfi_data = xcalloc (1, sizeof (struct frch_cfi_data));
+  frchain_now->frch_cfi_data->cur_fde_data = fde;
   *last_fde_data = fde;
   last_fde_data = &fde->next;
 
   fde->last = &fde->data;
   fde->return_column = DWARF2_DEFAULT_RETURN_COLUMN;
+  fde->per_encoding = DW_EH_PE_omit;
+  fde->lsda_encoding = DW_EH_PE_omit;
 
   return fde;
 }
@@ -149,6 +162,7 @@ static struct cfi_insn_data *
 alloc_cfi_insn_data (void)
 {
   struct cfi_insn_data *insn = xcalloc (1, sizeof (struct cfi_insn_data));
+  struct fde_entry *cur_fde_data = frchain_now->frch_cfi_data->cur_fde_data;
 
   *cur_fde_data->last = insn;
   cur_fde_data->last = &insn->next;
@@ -163,7 +177,7 @@ cfi_new_fde (symbolS *label)
 {
   struct fde_entry *fde = alloc_fde_entry ();
   fde->start_address = label;
-  last_address = label;
+  frchain_now->frch_cfi_data->last_address = label;
 }
 
 /* End the currently open FDE.  */
@@ -171,8 +185,9 @@ cfi_new_fde (symbolS *label)
 void 
 cfi_end_fde (symbolS *label)
 {
-  cur_fde_data->end_address = label;
-  cur_fde_data = NULL;
+  frchain_now->frch_cfi_data->cur_fde_data->end_address = label;
+  free (frchain_now->frch_cfi_data);
+  frchain_now->frch_cfi_data = NULL;
 }
 
 /* Set the return column for the current FDE.  */
@@ -180,7 +195,7 @@ cfi_end_fde (symbolS *label)
 void
 cfi_set_return_column (unsigned regno)
 {
-  cur_fde_data->return_column = regno;
+  frchain_now->frch_cfi_data->cur_fde_data->return_column = regno;
 }
 
 /* Universal functions to store new instructions.  */
@@ -239,10 +254,10 @@ cfi_add_advance_loc (symbolS *label)
   struct cfi_insn_data *insn = alloc_cfi_insn_data ();
 
   insn->insn = DW_CFA_advance_loc;
-  insn->u.ll.lab1 = last_address;
+  insn->u.ll.lab1 = frchain_now->frch_cfi_data->last_address;
   insn->u.ll.lab2 = label;
 
-  last_address = label;
+  frchain_now->frch_cfi_data->last_address = label;
 }
 
 /* Add a DW_CFA_offset record to the CFI data.  */
@@ -252,6 +267,7 @@ cfi_add_CFA_offset (unsigned regno, offs
 {
   unsigned int abs_data_align;
 
+  assert (DWARF2_CIE_DATA_ALIGNMENT != 0);
   cfi_add_CFA_insn_reg_offset (DW_CFA_offset, regno, offset);
 
   abs_data_align = (DWARF2_CIE_DATA_ALIGNMENT < 0
@@ -266,7 +282,7 @@ void
 cfi_add_CFA_def_cfa (unsigned regno, offsetT offset)