Android如何打印内核态堆栈,<深入浅出> mips 用户态堆栈回溯原理 以及内核态打印用户态堆栈回溯...

mips的回溯,核心思想就是一层一层的找调用函数的ra 叶子函数的ra就是当前寄存器,非叶子函数的ra保存在函数栈里

例如

func3()

{

}

func2()

{

func3();

}

func1()

{

func2();

}

main()

{

func3();

}

func3: //叶子函数,所以ra一直没有变化过,返回时可以jr ra来返回

addi sp,sp,-24 //于是可以通过寄存器里的ra值得到上一级pc

xxx

jr ra

func2:

addi sp,sp,-52 //非叶子函数,如果要找到ra,就需要根据sp里的值来确认

sw ra,48(sp) //根据当前sp的值,加上52是栈帧,接着减去(52-48),就得到ra保存的位置,实际上就是sp+48,取出ra得到func1里的某句地址

jal func3 //即上一层pc,jal会把pc的下一条指令放到ra里,再进行跳转,相对于jr直接跳转

nop

func1: //同上

addi sp,sp,-48

sw ra,44(sp)

jal func2

nop

打印用户态堆栈回溯

arch/mips/kernel/traps.c

#define USER_LEN 200

int sysctl_user_len = 200;

void show_user_raw_stack(void)

{

struct pt_regs *regs;

unsigned long tmp = 0;

unsigned long sp;

int i=0;

unsigned long val;

int line = 0;

regs = task_pt_regs(current);

sp = regs->regs[29];

if(!current->mm) /*内核态线程没有用户态堆栈*/

return;

printk("current process:[%d %s]-[0x%lx] \n",current->pid,current->comm,regs->cp0_epc);

printk("dump user stack:");

for(;i

if (access_ok(VERIFY_READ, (unsigned long*)sp+i, sizeof(unsigned long)))

{

if(!(line%4))

printk("\n%p:",(unsigned long*)sp+i);

line++;

copy_from_user(&val, (unsigned long*)sp+i, sizeof(unsigned long));

#ifndef CONFIG_64BIT

printk("%08lx ",val);

#else

printk("%016lx ",val);

#endif

}

}

printk("\ndump end\n");

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值