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)