diff --git a/gdb/ChangeLog b/gdb/ChangeLog index d1fbeb6b7c..f96c664c79 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,13 @@ +2006-05-28 Alexandre Oliva + + * dwarf2-frame.h (enum dwarf2_frame_reg_rule): Add + DWARF2_FRAME_REG_SAVED_VAL_OFFSET and + DWARF2_FRAME_REG_SAVED_VAL_EXP. + * dwarf2-frame.c (execute_cfa_program): Handle val_offset, + val_offset_sf and val_expression. + (dwarf2_frame_prev_register): Handle the new reg rules. + (dwarf2_frame_this_id): Use pc instead of function entry point. + 2006-05-28 Alexandre Oliva * dwarf2-frame.c (struct dwarf2_cie): Add signal_frame field. diff --git a/gdb/dwarf2-frame.c b/gdb/dwarf2-frame.c index 6b81dff799..edd9a7536a 100644 --- a/gdb/dwarf2-frame.c +++ b/gdb/dwarf2-frame.c @@ -481,6 +481,34 @@ bad CFI data; mismatched DW_CFA_restore_state at 0x%s"), paddr (fs->pc)); fs->regs.reg[reg].loc.offset = offset; break; + case DW_CFA_val_offset: + insn_ptr = read_uleb128 (insn_ptr, insn_end, ®); + dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1); + insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp); + offset = utmp * fs->data_align; + fs->regs.reg[reg].how = DWARF2_FRAME_REG_SAVED_VAL_OFFSET; + fs->regs.reg[reg].loc.offset = offset; + break; + + case DW_CFA_val_offset_sf: + insn_ptr = read_uleb128 (insn_ptr, insn_end, ®); + dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1); + insn_ptr = read_sleb128 (insn_ptr, insn_end, &offset); + offset *= fs->data_align; + fs->regs.reg[reg].how = DWARF2_FRAME_REG_SAVED_VAL_OFFSET; + fs->regs.reg[reg].loc.offset = offset; + break; + + case DW_CFA_val_expression: + insn_ptr = read_uleb128 (insn_ptr, insn_end, ®); + dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1); + insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp); + fs->regs.reg[reg].loc.exp = insn_ptr; + fs->regs.reg[reg].exp_len = utmp; + fs->regs.reg[reg].how = DWARF2_FRAME_REG_SAVED_VAL_EXP; + insn_ptr += utmp; + break; + case DW_CFA_def_cfa_sf: insn_ptr = read_uleb128 (insn_ptr, insn_end, &fs->cfa_reg); if (eh_frame_p) @@ -965,6 +993,28 @@ dwarf2_frame_prev_register (struct frame_info *next_frame, void **this_cache, } break; + case DWARF2_FRAME_REG_SAVED_VAL_OFFSET: + *optimizedp = 0; + *lvalp = not_lval; + *addrp = 0; + *realnump = -1; + if (valuep) + store_unsigned_integer (valuep, register_size (gdbarch, regnum), + cache->cfa + cache->reg[regnum].loc.offset); + break; + + case DWARF2_FRAME_REG_SAVED_VAL_EXP: + *optimizedp = 0; + *lvalp = not_lval; + *addrp = 0; + *realnump = -1; + if (valuep) + store_unsigned_integer (valuep, register_size (gdbarch, regnum), + execute_stack_op (cache->reg[regnum].loc.exp, + cache->reg[regnum].exp_len, + next_frame, cache->cfa)); + break; + case DWARF2_FRAME_REG_UNSPECIFIED: /* GCC, in its infinite wisdom decided to not provide unwind information for registers that are "same value". Since diff --git a/gdb/dwarf2-frame.h b/gdb/dwarf2-frame.h index da9fe4788f..15f456d757 100644 --- a/gdb/dwarf2-frame.h +++ b/gdb/dwarf2-frame.h @@ -51,6 +51,10 @@ enum dwarf2_frame_reg_rule DWARF2_FRAME_REG_SAVED_EXP, DWARF2_FRAME_REG_SAME_VALUE, + /* These are defined in Dwarf3. */ + DWARF2_FRAME_REG_SAVED_VAL_OFFSET, + DWARF2_FRAME_REG_SAVED_VAL_EXP, + /* These aren't defined by the DWARF2 CFI specification, but are used internally by GDB. */ DWARF2_FRAME_REG_RA, /* Return Address. */