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
{
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
相关文章推荐
- ThinkPhp学习06
- 我的博客,我的梦想
- 路由器做DHCP的两个实验
- 大数据架构和模式(五):利用大数据识别保险行业中的欺诈业务案例
- CF 9C Hexadecimal's Numbers
- Hibernate性能调优--关联实体的延迟加载
- ThinkPhp学习05
- Appium 三种wait方法(appium 学习之改造轮子)
- Visual Assist X 10.8.2048.0破解教程
- scala之尾递归实际用处2
- HDU 2034 人见人爱A-B
- Thinkphp学习04
- HDU 2034 人见人爱A-B 分类: ACM 2015-06-23 23:42 9人阅读 评论(0) 收藏
- python第三方模块
- Linux-Nginx-关闭进程
- python中的argparse模块(参数解析)
- ThinkPhp学习03
- 初始配置CentOS 7服务器
- XML的基本操作--
- poj1703解题报告