您的位置:首页 > 其它

ARCH64:怎样恢复函数的栈

2015-06-23 23:45 183 查看
static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk)

{

struct stackframe frame;

pr_debug("%s(regs = %p tsk = %p)\n", __func__, regs, tsk);

if (!tsk)

tsk = current;

if (regs) {

frame.fp = regs->regs[29];

frame.sp = regs->sp;

frame.pc = regs->pc;

} else if (tsk == current) {

frame.fp = (unsigned long)__builtin_frame_address(0);

frame.sp = current_stack_pointer;

frame.pc = (unsigned long)dump_backtrace;

} else {

/*

* task blocked in __switch_to

*/

frame.fp = thread_saved_fp(tsk);

frame.sp = thread_saved_sp(tsk);

frame.pc = thread_saved_pc(tsk);

}

pr_emerg("Call trace:\n");

while (1) {

unsigned long where = frame.pc;

int ret;

ret = unwind_frame(&frame);

if (ret < 0)

break;

dump_backtrace_entry(where, frame.sp);

}

}

/*

* This struct defines the way the registers are stored on the stack during an

* exception. Note that sizeof(struct pt_regs) has to be a multiple of 16 (for

* stack alignment). struct user_pt_regs must form a prefix of struct pt_regs.

*/

struct pt_regs {

union {

struct user_pt_regs user_regs;

struct {

u64 regs[31];

u64 sp;

u64 pc;

u64 pstate;

};

};

u64 orig_x0;

u64 syscallno;

};

struct stackframe {

unsigned long fp;

unsigned long sp;

unsigned long pc;

};

/*

* AArch64 PCS assigns the frame pointer to x29.

*

* A simple function prologue looks like this:

* sub
sp, sp, #0x10

* stp
x29, x30, [sp]

* mov
x29, sp

*

* A simple function epilogue looks like this:

* mov
sp, x29

* ldp
x29, x30, [sp]

* add
sp, sp, #0x10

*/

int notrace unwind_frame(struct stackframe *frame)

{

unsigned long high, low;

unsigned long fp = frame->fp;

low = frame->sp;

high = ALIGN(low, THREAD_SIZE);/*fp的内容是stack: 所以下面的位置比较*/

if (fp < low || fp > high - 0x18 || fp & 0xf)

return -EINVAL;

/*已知当前帧的fp:+0x10 得到caller的sp*/

/*已知当前帧的fp: 得到caller的fp*/

/*已知当前帧的fp: +0x8得到caller的pc*/

frame->sp = fp + 0x10;

frame->fp = *(unsigned long *)(fp);

/*

* -4 here because we care about the PC at time of bl,

* not where the return will go.

*/

frame->pc = *(unsigned long *)(fp + 8) - 4;

return 0;

}

static void dump_backtrace_entry(unsigned long where, unsigned long stack)

{

print_ip_sym(where);

if (in_exception_text(where))

dump_mem("", "Exception stack", stack,

stack + sizeof(struct pt_regs));

}

static inline void print_ip_sym(unsigned long ip)

{

printk("[<%p>] %pS\n", (void *) ip, (void *) ip);

}

进程的堆栈中保存的内容:肯定包括LR:

frame->pc = *(unsigned long *)(fp + 8) - 4;

如果从打印的看:应该是%p+4:在堆栈中.请验证下:找到了fp: 就找到了函数的栈.A4
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: