暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

MIPS下用户态dump stack实现

han码录 2019-07-29
1465

dump stack

    在进行内核模块编写的时候,有非常方便的dump_stack进行函数调用的追溯,在代码调试过程中非常的方便。

Stack : 8795f3c8 8009990c 803312e0 00000000 803a0000 8009ba0c 803330b8 80330000
00000000 7fffffff 00000000 33b6236f 00000000 33d472cf 80331260 33d472cf
000341b4 00000000 841dfa48 848c3ebc 80332ddc 2e2a19d5 00000000 00000001
00000000 8017ec74 84be1ae0 841dfa48 80332ddc 841dfa48 00000001 841dfa48
80332dd0 000342e1 2e2a19d5 80092f84 84be1ae0 80332dd0 841dfa48 80092644
...
Call Trace:
[<802a59ec>] __schedule+0x268/0x4e4
[<802a5110>] schedule_hrtimeout_range_clock+0x130/0x1a0
[<800fa394>] poll_schedule_timeout+0x38/0x54
[<800fac48>] do_select+0x494/0x4ec
[<800faea8>] core_sys_select+0x208/0x2cc
[<800fb024>] sys_select+0xb8/0xfc
[<8006c584>] stack_done+0x20/0x40

通过dump_stack在出现问题时能方便的进行debug。

标准库

    UClibc库中有实现libubacktrace,提供_Unwind_Backtrace功能进行栈回溯。实际应用中为了更加了解MIPS体系结构,还是自己实现了一个轻量级的backtrace。

基本需求

    获取当前挂掉函数的纵向调用信息,进行堆栈的回溯和寄存器信息的回溯。通过当前函数的栈地址和当前运行位置PC指针,计算得到当前函数的返回地址和上层函数的栈地址,进行解析和反向跟踪。

MIPS栈帧

    栈帧的重要性主要体现在两方面

(1)调用者和被调用者约定函数调用时参数传递、返回值返回、寄存器共享的方式

(2)调用者如何使用自己的栈帧来完成局部变量的存储和使用

  • SP为当前函数栈针,指向栈底

  • current frame即为当前函数栈帧

  • caller frame在上,为调用者栈帧

  • MIPS O32向下增长的栈

实现分析

    (1)找到当前栈帧大小

    (2)找到函数返回地址

    (3)从调用函数循环往复

    (4)进行栈帧边界防护

特殊分析

  • 叶子函数


    如果一个函数不包括对其他函数的调用,即为叶子函数。叶子函数不必担心参数结构,可以安全的在非保留的t0~t7、a0~a3以及v0 v1中维护数据

  • 非叶子函数

    包含了对别的函数的调用,一般函数一开始进行SP设置,也要为ra和自动变量(栈的局部变量)自己的调用过程中需要保存的其它寄存器的值预留栈空间,栈中保留的所有位置都可以从sp开始的固定偏移量引用。

函数堆栈处理

    非内联函数执行分3步

(1)调整SP,调整前指向caller栈顶,调整后执行当前栈顶

SIZE为当前函数栈帧大小,编译时确定

(2)进行实际的逻辑计算,包括子函数调用

(3)将本栈中保存的返回值重新赋给ra寄存器   

进程获取寄存器

    sys/ucontext.h中定义了可用于信号处理的ucontext_t结构,在该结构中有内核在异常信号处理时提供的寄存器信息。

/* Userlevel context.  */
typedef struct ucontext
{
unsigned long int uc_flags;
struct ucontext *uc_link;
stack_t uc_stack;
mcontext_t uc_mcontext;
__sigset_t uc_sigmask;
} ucontext_t;


实现过程

有了以上的基本信息,实现就比较简单了

(1)获取当前pc、ra【寄存器31】、sp【寄存器29】

(2)进行指令查找addiu,找到栈帧大小

(3)进行sw ra指令查找,找到ra偏移

(4)进行栈帧防护,防越界处理

实现结果

(1)单层

对应反汇编

(2)双层

对应汇编

00405968 <log_msg>:    ===>对应函数起始
405968: 27bdffd8 addiu sp,sp,-40
40596c: 24020002 li v0,2
405970: afbf0024 sw ra,36(sp)
405974: afa60030 sw a2,48(sp)
405978: afa70034 sw a3,52(sp)
40597c: a0020001 sb v0,1(zero) ===>出错位置


405fec: 0c10165a jal 405968 <log_msg> ===>延迟槽
405ff0: afb30014 sw s3,20(sp)
  405ff4:  00001821   move  v1,zero



文章转载自han码录,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论