libunwind-devel
[Top][All Lists]
Advanced

[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(&region->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(&region->op[1], _U_QP_TRUE, 0, UNW_TDEP_IP, -8);
        _U_dyn_op_add(&region->op[2], _U_QP_TRUE, 1, UNW_TDEP_SP, 16);
        _U_dyn_op_spill_fp_rel(&region->op[3], _U_QP_TRUE, 4, UNW_TDEP_BP, -16);
        _U_dyn_op_save_reg(&region->op[4], _U_QP_TRUE, 4, UNW_TDEP_SP, 
UNW_TDEP_BP);
        _U_dyn_op_stop(&region->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 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]