static int die_mem_offset(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name, Dwarf_Unsigned *valp, int req) { Dwarf_Attribute attr; Dwarf_Locdesc *loc; Dwarf_Signed locnum; if ((attr = die_attr(dw, die, name, req)) == NULL) return (0); /* die_attr will terminate for us if necessary */ if (dwarf_loclist(attr, &loc, &locnum, &dw->dw_err) != DW_DLV_OK) { terminate("die %llu: failed to get mem offset location list\n", die_off(dw, die)); } dwarf_dealloc(dw->dw_dw, attr, DW_DLA_ATTR); if (locnum != 1 || loc->ld_s->lr_atom != DW_OP_plus_uconst) { terminate("die %llu: cannot parse member offset\n", die_off(dw, die)); } *valp = loc->ld_s->lr_number; dwarf_dealloc(dw->dw_dw, loc->ld_s, DW_DLA_LOC_BLOCK); dwarf_dealloc(dw->dw_dw, loc, DW_DLA_LOCDESC); return (1); }
static void DC_get_location_attr_value(Dwarf_Attribute at, DC_location *dcl){ /* * It is assumed that at has a block form, and is a location list * so this won't fail. Caller is responsible for checking. */ Dwarf_Locdesc *locationList; Dwarf_Signed listLength; Dwarf_Error error; int frameRel = 0; long offset = 0; int i; int ret = dwarf_loclist( at, &locationList, &listLength, &error ); if( ret != DW_DLV_OK ){ return; } /*Get the location info*/ decode_location(locationList,listLength,&(dcl->offset),NULL,&(dcl->isFrameOffset)); /*Clean up*/ for( i = 0; i < listLength; ++i){ dwarf_dealloc(d,locationList[i].ld_s,DW_DLA_LOC_BLOCK); } dwarf_dealloc(d,locationList,DW_DLA_LOCDESC); }
/* Return DW_DLV_OK if handling this went ok. */ static int handle_attr_locdesc(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Half attrnum, Dwarf_Error * perr) { int retval = DW_DLV_OK; Dwarf_Attribute attr; Dwarf_Locdesc *llbuf; Dwarf_Signed i; Dwarf_Off offset; Dwarf_Loc *locp; unsigned int entindx; int res; int ares; ares = dwarf_attr(die, attrnum, &attr, perr); if (ares == DW_DLV_OK) { Dwarf_Half form; int fres = dwarf_whatform(attr, &form, perr); if (fres == DW_DLV_OK) { switch (form) { case DW_FORM_block1: case DW_FORM_block2: case DW_FORM_block4: /* must be location description */ res = dwarf_attr_offset(die, attr, &offset, perr); llbuf = 0; if (res == DW_DLV_OK) { Dwarf_Signed count; int lres = dwarf_loclist(attr, &llbuf, &count, perr); if (lres != DW_DLV_OK) { return lres; } if (count != 1) { /* this cannot happen! */ /* perr? */ _dwarf_error(dbg, perr, DW_DLE_LOCDESC_COUNT_WRONG); retval = DW_DLV_ERROR; return retval; } for (i = 0; i < count; ++i) { unsigned int ents = llbuf[i].ld_cents; locp = llbuf[i].ld_s; for (entindx = 0; entindx < ents; entindx++) { Dwarf_Loc *llocp; llocp = locp + entindx; if (llocp->lr_atom == DW_OP_addr) { send_addr_note(DW_SECTION_INFO, offset + llocp->lr_offset + 1 /* The offset is the offset of the atom, ** and we know the addr is 1 past it. */ , llocp->lr_number); } } } if (count > 0) { for (i = 0; i < count; ++i) { dwarf_dealloc(dbg, llbuf[i].ld_s, DW_DLA_LOC_BLOCK); } dwarf_dealloc(dbg, llbuf, DW_DLA_LOCDESC); } } else { retval = res; } break; default: /* must be a const offset in debug_loc */ ; /* do nothing */ } dwarf_dealloc(dbg, attr, DW_DLA_ATTR); } /* else error or no entry */ retval = fres; } else { retval = ares; } return retval; }
error_t print_local_var(mygdb_info_t* gdb_info, Dwarf_Die var_die, char* var_name){ Dwarf_Half tag; Dwarf_Error err; unsigned long var_addr; Dwarf_Attribute* attrs; Dwarf_Locdesc* locs_var; Dwarf_Signed attrcount, i, cnt_var; if (dwarf_tag(var_die, &tag, &err) != DW_DLV_OK) return E_FATAL; /* Make sure to only have a var die */ if (tag != DW_TAG_variable) return E_FATAL; /* Grab the DIEs attributes */ if (dwarf_attrlist(var_die, &attrs, &attrcount, &err) != DW_DLV_OK) return E_FATAL; for (i = 0; i < attrcount; ++i) { Dwarf_Half attrcode; if (dwarf_whatattr(attrs[i], &attrcode, &err) != DW_DLV_OK) return E_FATAL; if (attrcode == DW_AT_location) break; } if( attrs[i] == NULL ){ printf("Failed to find the DW_AT_location attribute\n"); return E_NON_FATAL; } if( dwarf_loclist(attrs[i], &locs_var, &cnt_var, &err) != DW_DLV_OK){ printf("dwarf_loclist failed\n"); return E_FATAL; } if((cnt_var != 1) || (locs_var[0].ld_cents != 1) || (locs_var[0].ld_s[0].lr_atom != DW_OP_fbreg)){ fprintf(stderr, "Unexpected location information\n"); return E_NON_FATAL; } struct user_regs_struct regs; if( ptrace(PTRACE_GETREGS, gdb_info->child_pid, NULL, ®s ) < 0 ) return E_FATAL; var_addr = (unsigned long)(regs.rbp + (long)locs_var[0].ld_s[0].lr_number + 16); errno = 0; unsigned long data; data = ptrace(PTRACE_PEEKTEXT, gdb_info->child_pid, (void*)var_addr); if(errno){ printf("peektext failed\n"); return E_FATAL; } printf("%s = %lu\n", var_name, data); return E_NONE; }