[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[libunwind] parse_dynamic under DWARF
From: |
Max Asbock |
Subject: |
[libunwind] parse_dynamic under DWARF |
Date: |
Tue, 22 Jun 2004 15:54:39 -0700 |
Part of the dwarf changes in the patch I sent out recently contain an attempt to
implement the parse_dynamic function in Gparser-dwarf.c. In the state this code
is
in it is probably not worthy of publication and I am sure it is at least
partially bogus.
I started on the assumption that whatever parse_dynamic does must cooperate with
the other dwarf functions, e.g apply_reg_state(). So I modeled it closely on
the
dwarf instructions that gcc generates.
For instance for a function prologue:
call (i.e. push %rip)
push %rbp
mov %rsp %rbp
we get the following DWARF instructions:
run_cfi_program: CFA_def_cfa r7+0x8
run_cfi_program: CFA_offset r16 at cfa-0x8
run_cfi_program: CFA_advance_loc to 0x400e13
run_cfi_program: CFA_def_cfa_offset 0x10
run_cfi_program: CFA_offset r6 at cfa-0x10
run_cfi_program: CFA_advance_loc to 0x400e16
run_cfi_program: CFA_def_cfa_register r6
Translated to dynamic info instructions this could look like:
region->insn_count = 4;
region->op_count = 6;
_U_dyn_op_add(®ion->op[0], _U_QP_TRUE, 0, UNW_TDEP_SP, 8);
/* we need to specify here that CFA is in r7 */
_U_dyn_op_spill_fp_rel(®ion->op[1], _U_QP_TRUE, 0, UNW_TDEP_IP, -8);
_U_dyn_op_add(®ion->op[2], _U_QP_TRUE, 1, UNW_TDEP_SP, 16);
_U_dyn_op_spill_fp_rel(®ion->op[3], _U_QP_TRUE, 4, UNW_TDEP_BP, -16);
_U_dyn_op_save_reg(®ion->op[4], _U_QP_TRUE, 4, UNW_TDEP_SP,
UNW_TDEP_BP);
_U_dyn_op_stop(®ion->op[5]);
region->next = NULL;
Of course from the point of view of the dynamic code producer this is not very
intuitive. Besides I am not really sure how to best specify that the CFA is in
r7 (RSP)
initially.
Here is the parse_dynamic function:
static int
parse_dynamic (struct dwarf_cursor *c, unw_word_t ip, dwarf_state_record_t *sr)
{
unw_dyn_info_t *di = c->pi.unwind_info;
unw_dyn_proc_info_t *proc = &di->u.pi;
unw_dyn_region_info_t *r;
unw_dyn_op_t *op;
unw_word_t when;
int ret;
for (r = proc->regions; r; r = r->next)
{
for (op = r->op; op < r->op + r->op_count; ++op)
{
if (op->tag == UNW_DYN_STOP)
break;
if (op->when >= 0)
when = di->start_ip + op->when;
else
when = di->end_ip + op->when;
if (when > ip)
continue;
switch (op->tag)
{
case UNW_DYN_SAVE_REG: /* save register to another register */
Debug(16, "UNW_DYN_SAVE_REG: saving reg %d in reg %d\n",
op->reg, op->val);
set_reg (sr, op->reg, DWARF_WHERE_REG, op->val);
if (op->reg == UNW_TDEP_SP)
set_reg (sr, DWARF_CFA_REG_COLUMN, DWARF_WHERE_REG, op->val);
break;
case UNW_DYN_SPILL_FP_REL: /* frame-pointer-relative reg spill */
Debug(16, "UNW_DYN_SPILL_FP_REL: save reg: %d at 0x%x\n",
op->reg, op->val);
set_reg (sr, op->reg, DWARF_WHERE_CFAREL, op->val);
break;
case UNW_DYN_SPILL_SP_REL: /* stack-pointer-relative reg spill */
Debug(16, "UNW_DYN_SPILL_SP_REL: not used on x86_64\n");
break;
case UNW_DYN_ADD: /* add constant value to a register */
Debug(16, "UNW_DYN_ADD: add 0x%x to CFA\n", op->val);
if (op->reg == UNW_TDEP_SP)
set_reg (sr, DWARF_CFA_OFF_COLUMN, 0, op->val);
break;
case UNW_DYN_POP_FRAMES: /* drop one or more stack frames */
Debug(16, "UNW_DYN_POP_FRAMES: not used on x86_64\n");
break;
case UNW_DYN_LABEL_STATE: /* name the current state */
break;
case UNW_DYN_COPY_STATE: /* set the region's entry-state */
break;
case UNW_DYN_ALIAS:
Debug(16, "UNW_DYN_ALIAS, new ip: 0x%016lx\n", op->val);
ret = fetch_proc_info (c, op->val, 1);
if (ret < 0)
return ret;
return create_state_record_for (c, sr, op->val);
}
}
}
c->ret_addr_column = UNW_TDEP_IP;
return 0;
}
Let me know what you think.
regards,
max
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [libunwind] parse_dynamic under DWARF,
Max Asbock <=