107 lines
2.8 KiB
C
107 lines
2.8 KiB
C
|
|
static RList *backtrace_x86_64(RDebug *dbg, ut64 at) {
|
|
int i;
|
|
ut8 buf[8];
|
|
RDebugFrame *frame;
|
|
ut64 ptr, ebp2;
|
|
ut64 _rip, _rsp, _rbp = 0;
|
|
RList *list;
|
|
RReg *reg = dbg->reg;
|
|
RIOBind *bio = &dbg->iob;
|
|
|
|
_rip = r_reg_get_value (reg, r_reg_get (reg, "rip", R_REG_TYPE_GPR));
|
|
if (at == UT64_MAX) {
|
|
_rsp = r_reg_get_value (reg, r_reg_get (reg, "rsp", R_REG_TYPE_GPR));
|
|
_rbp = r_reg_get_value (reg, r_reg_get (reg, "rbp", R_REG_TYPE_GPR));
|
|
} else {
|
|
_rsp = _rbp = at;
|
|
}
|
|
|
|
list = r_list_new ();
|
|
list->free = free;
|
|
bio->read_at (bio->io, _rip, (ut8*)&buf, 8);
|
|
/* %rbp=old rbp, %rbp+4 points to ret */
|
|
/* Plugin before function prelude: push %rbp ; mov %rsp, %rbp */
|
|
if (!memcmp (buf, "\x55\x89\xe5", 3) || !memcmp (buf, "\x89\xe5\x57", 3)) {
|
|
if (bio->read_at (bio->io, _rsp, (ut8*)&ptr, 8) != 8) {
|
|
eprintf ("read error at 0x%08"PFMT64x"\n", _rsp);
|
|
r_list_purge (list);
|
|
free (list);
|
|
return R_FALSE;
|
|
}
|
|
frame = R_NEW0 (RDebugFrame);
|
|
frame->addr = ptr;
|
|
frame->size = 0; // TODO ?
|
|
r_list_append (list, frame);
|
|
_rbp = ptr;
|
|
}
|
|
|
|
for (i=1; i<MAXBT; i++) {
|
|
// TODO: make those two reads in a shot
|
|
bio->read_at (bio->io, _rbp, (ut8*)&ebp2, 8);
|
|
if (ebp2 == UT64_MAX)
|
|
break;
|
|
bio->read_at (bio->io, _rbp+8, (ut8*)&ptr, 8);
|
|
if (!ptr || !_rbp)
|
|
break;
|
|
frame = R_NEW0 (RDebugFrame);
|
|
frame->addr = ptr;
|
|
frame->size = 0; // TODO ?
|
|
r_list_append (list, frame);
|
|
_rbp = ebp2;
|
|
}
|
|
return list;
|
|
}
|
|
// XXX: Do this work correctly?
|
|
static RList *backtrace_x86_64_anal(RDebug *dbg, ut64 at) {
|
|
int i;
|
|
ut8 buf[8];
|
|
RDebugFrame *frame;
|
|
ut64 ptr, ebp2;
|
|
ut64 _rip, _rbp;
|
|
RList *list;
|
|
RReg *reg = dbg->reg;
|
|
RIOBind *bio = &dbg->iob;
|
|
RAnalFunction *fcn;
|
|
|
|
_rip = r_reg_get_value (reg, r_reg_get (reg, "rip", R_REG_TYPE_GPR));
|
|
if (at == UT64_MAX) {
|
|
//_rsp = r_reg_get_value (reg, r_reg_get (reg, "rsp", R_REG_TYPE_GPR));
|
|
_rbp = r_reg_get_value (reg, r_reg_get (reg, "rbp", R_REG_TYPE_GPR));
|
|
//} else {
|
|
// _rsp = _rbp = at;
|
|
}
|
|
|
|
list = r_list_new ();
|
|
list->free = free;
|
|
bio->read_at (bio->io, _rip, (ut8*)&buf, 8);
|
|
|
|
// TODO : frame->size by using esil to emulate first instructions
|
|
fcn = r_anal_get_fcn_in (dbg->anal, _rip, R_ANAL_FCN_TYPE_NULL);
|
|
if (fcn) {
|
|
frame = R_NEW0 (RDebugFrame);
|
|
frame->addr = _rip;
|
|
frame->size = 0;
|
|
r_list_append (list, frame);
|
|
}
|
|
|
|
for (i=1; i<MAXBT; i++) {
|
|
// TODO: make those two reads in a shot
|
|
bio->read_at (bio->io, _rbp, (ut8*)&ebp2, 8);
|
|
if (ebp2 == UT64_MAX)
|
|
break;
|
|
bio->read_at (bio->io, _rbp+8, (ut8*)&ptr, 8);
|
|
if (!ptr || !_rbp)
|
|
break;
|
|
//fcn = r_anal_get_fcn_in (dbg->anal, ptr, R_ANAL_FCN_TYPE_NULL);
|
|
frame = R_NEW0 (RDebugFrame);
|
|
frame->addr = ptr;
|
|
frame->size = 0;
|
|
//frame->name = (fcn && fcn->name) ? strdup (fcn->name) : NULL;
|
|
r_list_append (list, frame);
|
|
_rbp = ebp2;
|
|
}
|
|
|
|
return list;
|
|
}
|
|
|