summaryrefslogtreecommitdiff
path: root/gcc/unwind-dw2.c
diff options
context:
space:
mode:
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2001-05-16 22:42:36 +0000
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2001-05-16 22:42:36 +0000
commit9b84bf7de848cc4e27b88354c441e4a2bc41abb6 (patch)
tree0115a87b72de59adf0b97d879e1d5d59187631ab /gcc/unwind-dw2.c
parent6a0bf73304d36070da7e0a443ebc5b6a1f503d4f (diff)
downloadgcc-9b84bf7de848cc4e27b88354c441e4a2bc41abb6.tar.gz
* except.c (eh_data_format_name): Move to ...
* dwarf2asm.c: ... here. Use designated initializers if available. (dw2_asm_output_encoded_addr_rtx): Accept varargs commentary. * dwarf2asm.h: Update declarations. * dwarf2out.c (output_cfi) [DW_CFA_set_loc]: If for_eh, mind ASM_PREFERRED_EH_DATA_FORMAT. (output_call_frame_info): Likewise. Use 'L' augmentation for the LSDA encoding. * unwind-dw2-fde.h (struct fde_vector): New. (struct old_object): Rename from struct object. (struct object): New. (__register_frame_info_bases): Declare. (__register_frame_info_table_bases): Declare. (struct dwarf_fde): Remove explicit pc_begin/pc_range members. * unwind-dw2-fde.c (objects): Remove. (unseen_objects, seen_objects): New. (__register_frame_info_bases): New. (__register_frame_info): Use it. (__register_frame_info_table_bases): New. (__register_frame_info_table): Use it. (__deregister_frame_info): Rewrite for changed object struct. (base_from_object, get_cie_encoding, get_fde_encoding): New. (fde_unencoded_compare): Rename from fde_compare; uninline. (fde_single_encoding_compare, fde_mixed_encoding_compare): New. (start_fde_sort): Adjust for new definition of fde_vector. (fde_insert): Likewise. (end_fde_sort): Likewise. Select comparison function based on properties of the object. (fde_split): Take object and fde_compare_t arguments. (frame_heapsort, fde_merge): Likewise. (classify_object_over_fdes): Rename from count_fdes. Handle encoded pointers. Collect encoding, mixed_encoding, and pc_begin for the object. (add_fdes): Handle encoded pointers. (init_object): Rename from frame_init. Update for new struct object. (linear_search_fdes): Rename from search_fdes. Handle encoded pointers. (binary_search_unencoded_fdes): Broken out from _Unwind_Find_FDE. (binary_search_single_encoding_fdes): New. (binary_search_mixed_encoding_fdes): New. (search_object): New. (_Unwind_Find_FDE): Update for new struct object. Fill in the dwarf_eh_bases. * unwind-dw2.c: Include unwind-pe.h. Constify all pointers iterating over EH data. (_Unwind_FrameState): Remove saw_lsda, addr_encoding. Add fde_encoding, lsda_encoding. (read_uleb128, read_sleb128): Remove. (read_encoded_pointer): Remove. All callers use read_encoded_value. (extract_cie_info): Set lsda_encoding from 'L' augmentation. (uw_frame_state_for): Don't set bases.func. Handle encoded fde pointers. * unwind-pe.h: Add "struct" to _Unwind_Context references. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@42176 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/unwind-dw2.c')
-rw-r--r--gcc/unwind-dw2.c205
1 files changed, 46 insertions, 159 deletions
diff --git a/gcc/unwind-dw2.c b/gcc/unwind-dw2.c
index 6eb163d904b..20deb5721f9 100644
--- a/gcc/unwind-dw2.c
+++ b/gcc/unwind-dw2.c
@@ -22,6 +22,7 @@
#include "tsystem.h"
#include "dwarf2.h"
#include "unwind.h"
+#include "unwind-pe.h"
#include "unwind-dw2-fde.h"
#include "gthr.h"
@@ -69,7 +70,7 @@ typedef struct
union {
unsigned int reg;
_Unwind_Sword offset;
- unsigned char *exp;
+ const unsigned char *exp;
} loc;
enum {
REG_UNSAVED,
@@ -87,7 +88,7 @@ typedef struct
location expression. */
_Unwind_Sword cfa_offset;
_Unwind_Word cfa_reg;
- unsigned char *cfa_exp;
+ const unsigned char *cfa_exp;
enum {
CFA_UNSET,
CFA_REG_OFFSET,
@@ -102,57 +103,11 @@ typedef struct
signed int data_align;
unsigned int code_align;
unsigned char retaddr_column;
- unsigned char addr_encoding;
+ unsigned char fde_encoding;
+ unsigned char lsda_encoding;
unsigned char saw_z;
- unsigned char saw_lsda;
} _Unwind_FrameState;
-/* Decode the unsigned LEB128 constant at BUF into the variable pointed to
- by R, and return the new value of BUF. */
-
-static unsigned char *
-read_uleb128 (unsigned char *buf, _Unwind_Word *r)
-{
- unsigned shift = 0;
- _Unwind_Word result = 0;
-
- while (1)
- {
- unsigned char byte = *buf++;
- result |= (byte & 0x7f) << shift;
- if ((byte & 0x80) == 0)
- break;
- shift += 7;
- }
- *r = result;
- return buf;
-}
-
-/* Decode the signed LEB128 constant at BUF into the variable pointed to
- by R, and return the new value of BUF. */
-
-static unsigned char *
-read_sleb128 (unsigned char *buf, _Unwind_Sword *r)
-{
- unsigned shift = 0;
- _Unwind_Sword result = 0;
- unsigned char byte;
-
- while (1)
- {
- byte = *buf++;
- result |= (byte & 0x7f) << shift;
- shift += 7;
- if ((byte & 0x80) == 0)
- break;
- }
- if (shift < (sizeof (*r) * 8) && (byte & 0x40) != 0)
- result |= - (1 << shift);
-
- *r = result;
- return buf;
-}
-
/* Read unaligned data from the instruction buffer. */
union unaligned
@@ -167,107 +122,31 @@ union unaligned
} __attribute__ ((packed));
static inline void *
-read_pointer (void *p) { union unaligned *up = p; return up->p; }
+read_pointer (const void *p) { const union unaligned *up = p; return up->p; }
static inline int
-read_1u (void *p) { return *(unsigned char *)p; }
+read_1u (const void *p) { return *(const unsigned char *)p; }
static inline int
-read_1s (void *p) { return *(signed char *)p; }
+read_1s (const void *p) { return *(const signed char *)p; }
static inline int
-read_2u (void *p) { union unaligned *up = p; return up->u2; }
+read_2u (const void *p) { const union unaligned *up = p; return up->u2; }
static inline int
-read_2s (void *p) { union unaligned *up = p; return up->s2; }
+read_2s (const void *p) { const union unaligned *up = p; return up->s2; }
static inline unsigned int
-read_4u (void *p) { union unaligned *up = p; return up->u4; }
+read_4u (const void *p) { const union unaligned *up = p; return up->u4; }
static inline int
-read_4s (void *p) { union unaligned *up = p; return up->s4; }
+read_4s (const void *p) { const union unaligned *up = p; return up->s4; }
static inline unsigned long
-read_8u (void *p) { union unaligned *up = p; return up->u8; }
+read_8u (const void *p) { const union unaligned *up = p; return up->u8; }
static inline unsigned long
-read_8s (void *p) { union unaligned *up = p; return up->s8; }
-
-static unsigned char *
-read_encoded_pointer (unsigned char *p, unsigned char encoding,
- struct dwarf_eh_bases *bases, void **pptr)
-{
- signed long val;
- unsigned char *ret;
-
- switch (encoding & 0x0f)
- {
- case DW_EH_PE_absptr:
- val = (_Unwind_Ptr) read_pointer (p);
- ret = p + sizeof (void *);
- break;
-
- case DW_EH_PE_uleb128:
- ret = read_uleb128 (p, &val);
- break;
- case DW_EH_PE_sleb128:
- ret = read_sleb128 (p, &val);
- break;
-
- case DW_EH_PE_udata2:
- val = read_2u (p);
- ret = p + 2;
- break;
- case DW_EH_PE_udata4:
- val = read_4u (p);
- ret = p + 4;
- break;
- case DW_EH_PE_udata8:
- val = read_8u (p);
- ret = p + 8;
- break;
-
- case DW_EH_PE_sdata2:
- val = read_2s (p);
- ret = p + 2;
- break;
- case DW_EH_PE_sdata4:
- val = read_4s (p);
- ret = p + 4;
- break;
- case DW_EH_PE_sdata8:
- val = read_8s (p);
- ret = p + 8;
- break;
-
- default:
- abort ();
- }
-
- if (val != 0)
- switch (encoding & 0xf0)
- {
- case DW_EH_PE_absptr:
- break;
- case DW_EH_PE_pcrel:
- val += (_Unwind_Ptr) p;
- break;
- case DW_EH_PE_textrel:
- val += (_Unwind_Ptr) bases->tbase;
- break;
- case DW_EH_PE_datarel:
- val += (_Unwind_Ptr) bases->dbase;
- break;
- case DW_EH_PE_funcrel:
- val += (_Unwind_Ptr) bases->func;
- break;
- default:
- abort ();
- }
-
- *pptr = (void *) (_Unwind_Ptr) val;
- return ret;
-}
+read_8s (const void *p) { const union unaligned *up = p; return up->s8; }
/* Get the value of register REG as saved in CONTEXT. */
@@ -332,13 +211,13 @@ _Unwind_GetTextRelBase (struct _Unwind_Context *context)
unit F belongs to. Return a pointer to the byte after the augmentation,
or NULL if we encountered an undecipherable augmentation. */
-static unsigned char *
+static const unsigned char *
extract_cie_info (struct dwarf_cie *cie, struct _Unwind_Context *context,
_Unwind_FrameState *fs)
{
- unsigned char *aug = cie->augmentation;
- unsigned char *p = aug + strlen (aug) + 1;
- unsigned char *ret = NULL;
+ const unsigned char *aug = cie->augmentation;
+ const unsigned char *p = aug + strlen (aug) + 1;
+ const unsigned char *ret = NULL;
_Unwind_Word code_align;
_Unwind_Sword data_align;
@@ -349,6 +228,7 @@ extract_cie_info (struct dwarf_cie *cie, struct _Unwind_Context *context,
fs->code_align = code_align;
fs->data_align = data_align;
fs->retaddr_column = *p++;
+ fs->lsda_encoding = DW_EH_PE_omit;
/* If the augmentation starts with 'z', then a uleb128 immediately
follows containing the length of the augmentation field following
@@ -373,20 +253,25 @@ extract_cie_info (struct dwarf_cie *cie, struct _Unwind_Context *context,
aug += 2;
}
- /* "R" indicates a byte indicating how addresses are encoded. */
+ /* "L" indicates a byte showing how the LSDA pointer is encoded. */
+ else if (aug[0] == 'L')
+ {
+ fs->lsda_encoding = *p++;
+ aug += 1;
+ }
+
+ /* "R" indicates a byte indicating how FDE addresses are encoded. */
else if (aug[0] == 'R')
{
- fs->addr_encoding = *p++;
+ fs->fde_encoding = *p++;
aug += 1;
}
- /* "P" indicates a personality routine in the CIE augmentation
- and an lsda pointer in the FDE augmentation. */
+ /* "P" indicates a personality routine in the CIE augmentation. */
else if (aug[0] == 'P')
{
- p = read_encoded_pointer (p, fs->addr_encoding, &context->bases,
- (void **) &fs->personality);
- fs->saw_lsda = 1;
+ p = read_encoded_value (context, *p, p + 1,
+ (_Unwind_Ptr *) &fs->personality);
aug += 1;
}
@@ -404,7 +289,7 @@ extract_cie_info (struct dwarf_cie *cie, struct _Unwind_Context *context,
onto the stack to start. */
static _Unwind_Word
-execute_stack_op (unsigned char *op_ptr, unsigned char *op_end,
+execute_stack_op (const unsigned char *op_ptr, const unsigned char *op_end,
struct _Unwind_Context *context, _Unwind_Word initial)
{
_Unwind_Word stack[64]; /* ??? Assume this is enough. */
@@ -800,8 +685,10 @@ execute_stack_op (unsigned char *op_ptr, unsigned char *op_end,
CIE info, and the PC range to evaluate. */
static void
-execute_cfa_program (unsigned char *insn_ptr, unsigned char *insn_end,
- struct _Unwind_Context *context, _Unwind_FrameState *fs)
+execute_cfa_program (const unsigned char *insn_ptr,
+ const unsigned char *insn_end,
+ struct _Unwind_Context *context,
+ _Unwind_FrameState *fs)
{
struct frame_state_reg_info *unused_rs = NULL;
@@ -832,8 +719,8 @@ execute_cfa_program (unsigned char *insn_ptr, unsigned char *insn_end,
else switch (insn)
{
case DW_CFA_set_loc:
- insn_ptr = read_encoded_pointer (insn_ptr, fs->addr_encoding,
- &context->bases, &fs->pc);
+ insn_ptr = read_encoded_value (context, fs->fde_encoding,
+ insn_ptr, (_Unwind_Ptr *) &fs->pc);
break;
case DW_CFA_advance_loc1:
@@ -989,7 +876,7 @@ uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
{
struct dwarf_fde *fde;
struct dwarf_cie *cie;
- unsigned char *aug, *insn, *end;
+ const unsigned char *aug, *insn, *end;
memset (fs, 0, sizeof (*fs));
context->args_size = 0;
@@ -1011,8 +898,7 @@ uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
#endif
}
- context->bases.func = fde->pc_begin;
- fs->pc = fde->pc_begin;
+ fs->pc = context->bases.func;
cie = get_cie (fde);
insn = extract_cie_info (cie, context, fs);
@@ -1026,6 +912,7 @@ uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
/* Locate augmentation for the fde. */
aug = (unsigned char *)fde + sizeof (*fde);
+ aug += 2 * size_of_encoded_value (fs->fde_encoding);
insn = NULL;
if (fs->saw_z)
{
@@ -1033,9 +920,9 @@ uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
aug = read_uleb128 (aug, &i);
insn = aug + i;
}
- if (fs->saw_lsda)
- aug = read_encoded_pointer (aug, fs->addr_encoding,
- &context->bases, &context->lsda);
+ if (fs->lsda_encoding != DW_EH_PE_omit)
+ aug = read_encoded_value (context, fs->lsda_encoding, aug,
+ (_Unwind_Ptr *) &context->lsda);
/* Then the insns in the FDE up to our target PC. */
if (insn == NULL)
@@ -1076,7 +963,7 @@ uw_update_context_1 (struct _Unwind_Context *context, _Unwind_FrameState *fs)
CFA calculation is so complicated as to require a stack program
that this will not be a problem. */
{
- unsigned char *exp = fs->cfa_exp;
+ const unsigned char *exp = fs->cfa_exp;
_Unwind_Word len;
exp = read_uleb128 (exp, &len);
@@ -1104,7 +991,7 @@ uw_update_context_1 (struct _Unwind_Context *context, _Unwind_FrameState *fs)
break;
case REG_SAVED_EXP:
{
- unsigned char *exp = fs->regs.reg[i].loc.exp;
+ const unsigned char *exp = fs->regs.reg[i].loc.exp;
_Unwind_Word len;
_Unwind_Ptr val;