smeso - MIPS 堆栈跟踪:一次意外的旅程

主要观点:C 程序在 MIPS32 架构的嵌入式设备上随机崩溃,需获取栈回溯,glibc 的backtrace(3)等函数在 MIPS32 上不适用,需通过解析操作码确定栈帧起始的偏移量来获取栈回溯,还可通过dl_iterate_phdr(3)将地址转换为函数名等。
关键信息

  • 程序在 Linux 上运行,设备架构为 MIPS32,需异步接收详细报告(栈回溯)。
  • backtrace(3)等函数在 MIPS32 上不工作,原因是 MIPS32 上的帧指针($fp$)像另一个栈指针一样无用,backtrace(3)实现会返回随机值。
  • 可通过跳入函数实际代码解析操作码来确定与$sp$配合的正确偏移量以获取栈回溯。
  • 可用dl_iterate_phdr(3)查找包含地址的共享对象并在其.symtab中找到函数名,还可通过.debug_line节或addr2line获取源文件名和行号。
    重要细节
  • 在 MIPS32 上,当前函数的返回地址存于$ra$寄存器,进入新函数时“旧”返回地址压入栈且在新函数栈帧开始前。
  • 代码示例展示了如何实现获取栈回溯及符号化地址的功能,包括通过循环解析操作码确定栈帧信息,使用dl_iterate_phdr(3)查找共享对象等。
  • 最后强调不能完全相信博客文章,不同的编译器和 libc 组合可能有不同行为和问题。
阅读 18
0 条评论