summaryrefslogtreecommitdiff
path: root/gcc/frame-dwarf2.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/frame-dwarf2.c')
-rw-r--r--gcc/frame-dwarf2.c116
1 files changed, 116 insertions, 0 deletions
diff --git a/gcc/frame-dwarf2.c b/gcc/frame-dwarf2.c
index fb2e9fb6159..52db16f577e 100644
--- a/gcc/frame-dwarf2.c
+++ b/gcc/frame-dwarf2.c
@@ -466,6 +466,108 @@ extract_cie_info (fde *f, struct cie_info *c)
return p;
}
+/* Decode a DW_OP stack operation. */
+
+static void *
+decode_stack_op (unsigned char *buf, struct frame_state *state)
+{
+ enum dwarf_location_atom op;
+ int offset;
+
+ op = *buf++;
+ switch (op)
+ {
+ case DW_OP_reg0:
+ case DW_OP_reg1:
+ case DW_OP_reg2:
+ case DW_OP_reg3:
+ case DW_OP_reg4:
+ case DW_OP_reg5:
+ case DW_OP_reg6:
+ case DW_OP_reg7:
+ case DW_OP_reg8:
+ case DW_OP_reg9:
+ case DW_OP_reg10:
+ case DW_OP_reg11:
+ case DW_OP_reg12:
+ case DW_OP_reg13:
+ case DW_OP_reg14:
+ case DW_OP_reg15:
+ case DW_OP_reg16:
+ case DW_OP_reg17:
+ case DW_OP_reg18:
+ case DW_OP_reg19:
+ case DW_OP_reg20:
+ case DW_OP_reg21:
+ case DW_OP_reg22:
+ case DW_OP_reg23:
+ case DW_OP_reg24:
+ case DW_OP_reg25:
+ case DW_OP_reg26:
+ case DW_OP_reg27:
+ case DW_OP_reg28:
+ case DW_OP_reg29:
+ case DW_OP_reg30:
+ case DW_OP_reg31:
+ state->cfa_reg = op - DW_OP_reg0;
+ break;
+ case DW_OP_regx:
+ buf = decode_sleb128 (buf, &offset);
+ state->cfa_reg = offset;
+ case DW_OP_breg0:
+ case DW_OP_breg1:
+ case DW_OP_breg2:
+ case DW_OP_breg3:
+ case DW_OP_breg4:
+ case DW_OP_breg5:
+ case DW_OP_breg6:
+ case DW_OP_breg7:
+ case DW_OP_breg8:
+ case DW_OP_breg9:
+ case DW_OP_breg10:
+ case DW_OP_breg11:
+ case DW_OP_breg12:
+ case DW_OP_breg13:
+ case DW_OP_breg14:
+ case DW_OP_breg15:
+ case DW_OP_breg16:
+ case DW_OP_breg17:
+ case DW_OP_breg18:
+ case DW_OP_breg19:
+ case DW_OP_breg20:
+ case DW_OP_breg21:
+ case DW_OP_breg22:
+ case DW_OP_breg23:
+ case DW_OP_breg24:
+ case DW_OP_breg25:
+ case DW_OP_breg26:
+ case DW_OP_breg27:
+ case DW_OP_breg28:
+ case DW_OP_breg29:
+ case DW_OP_breg30:
+ case DW_OP_breg31:
+ state->cfa_reg = op - DW_OP_breg0;
+ buf = decode_sleb128 (buf, &offset);
+ state->base_offset = offset;
+ break;
+ case DW_OP_bregx:
+ buf = decode_sleb128 (buf, &offset);
+ state->cfa_reg = offset;
+ buf = decode_sleb128 (buf, &offset);
+ state->base_offset = offset;
+ break;
+ case DW_OP_deref:
+ state->indirect = 1;
+ break;
+ case DW_OP_plus_uconst:
+ buf = decode_uleb128 (buf, &offset);
+ state->cfa_offset = offset;
+ break;
+ default:
+ abort ();
+ }
+ return buf;
+}
/* Decode one instruction's worth of DWARF 2 call frame information.
Used by __frame_state_for. Takes pointers P to the instruction to
decode, STATE to the current register unwind information, INFO to the
@@ -567,6 +669,20 @@ execute_cfa_insn (void *p, struct frame_state_internal *state,
p = decode_uleb128 (p, &offset);
state->s.cfa_offset = offset;
break;
+ case DW_CFA_def_cfa_expression:
+ {
+ void *end;
+ state->s.cfa_reg = 0;
+ state->s.cfa_offset = 0;
+ state->s.base_offset = 0;
+ state->s.indirect = 0;
+
+ p = decode_uleb128 (p, &offset);
+ end = p + offset;
+ while (p < end)
+ p = decode_stack_op (p, &(state->s));
+ break;
+ }
case DW_CFA_remember_state:
{