Linux Call Trace原理分析

转载 2012年03月26日 22:27:59

本文介绍了在Linux环境下根据EABI标准进行call trace调试的一般性原理。

本文所说的call trace是指程序出问题时能把当前的函数调用栈打印出来。

本文只介绍了得到函数调用栈的一般性原理,没有涉及Linux的core dump机制。

下面简单介绍powerpc环境中如何实现call trace。

内核态call trace

内核态有三种出错情况,分别是bug, oops和panic。

bug属于轻微错误,比如在spin_lock期间调用了sleep,导致潜在的死锁问题,等等。

oops代表某一用户进程出现错误,需要杀死用户进程。这时如果用户进程占用了某些信号锁,所以这些信号锁将永远不会得到释放,这会导致系统潜在的不稳定性。

panic是严重错误,代表整个系统崩溃。

OOPS

先介绍下oops情况的处理。Linux oops时,会进入traps.c中的die函数。

int die(const char *str, struct pt_regs *regs, long err)

。。。

show_regs(regs);

void show_regs(struct pt_regs * regs)函数中,会调用show_stack函数,这个函数会打印系统的内核态堆栈。

具体原理为:

从寄存器里找到当前栈,在栈指针里会有上一级调用函数的栈指针,根据这个指针回溯到上一级的栈,依次类推。

在powerpc的EABI标准中,当前栈的栈底(注意是栈底,不是栈顶,即Frame Header的地址)指针保存在寄存器GPR1中。在GPR1指向的栈空间,第一个DWORD为上一级调用函数的Frame Header指针(Back Chain Word),第二个DWORD是当前函数在上一级函数中的返回地址(LR Save Word)。通过此种方式一级级向上回溯,完成整个call dump。除了这种方法,内建函数__builtin_frame_address函数理论上也应该能用,虽然在内核中没有见到。(2.6.29的ftrace模块用到了__builtin_return_address函数)。

show_regs函数在call trace的时候,只是用printk打印了一下栈中的信息。如果当前系统没有终端,那就需要修改内核,把这些栈信息根据需求保存到其它地方。

例如,可以在系统的flash中开出一块空间专门用于打印信息的保存。然后,写一个内核模块,再在die函数中加一个回调函数。这样,每当回调函数被调用,就通知自定义的内核模块,在模块中可以把调用栈还有其它感兴趣的信息保存到那块专用flash空间中去。这里有一点需要注意的是,oops时内核可能不稳定,所以为了确保信息能被正确写入flash,在写flash的函数中尽量不要用中断,而用轮循的方式。另外信号量、sleep等可能导致阻塞的函数也不要使用。

此外,由于oops时系统还在运行,所以可以发一个消息(信号,netlink等)到用户空间,通知用户空间做一些信息收集工作。

Panic

Panic时,Linux处于更最严重的错误状态,标志着整个系统不可用,即中断、进程调度等都已经停止,但栈还没被破坏。所以,oops中的栈回溯理论上还是能用。printk函数中因为没有阻塞,也还是能够使用。

用户态call trace

用户程序可以在以下情形call trace,以方便调试:

l 程序崩溃时,都会收到一个信号。Linux系统接收到某些信号时会自动打印call trace。

l 在用户程序中添加检查点,类似于assert机制,如果检查点的条件不满足,就执行call trace。

用户态的call trace与内核态相同,同样满足EABI标准,原理如下:

在GNU标准中,有一个内建函数__builtin_frame_address。这个函数可以返回当前执行上下文的栈底(Frame Header)指针(同时也是指向Back Chain Word的指针),通过这个指针得到当前调用栈。而这个调用栈中,会有上一级调用函数的栈底指针,通过这个指针再回溯到上一级的调用栈。以此类推完成整个call dump过程。

得到函数的地址后,可以通过符号表得到函数名字。如果是动态库中定义的函数,还可以通过扩展函数dladdr得到这个函数的动态库信息。

Linux Call Trace原理分析

本文介绍了在Linux环境下根据EABI标准进行call trace调试的一般性原理。 本文所说的call trace是指程序出问题时能把当前的函数调用栈打印出来。 本文只介绍了得到函数调用栈...
  • LinuxEngineer
  • LinuxEngineer
  • 2013年12月11日 11:32
  • 1202

linux kernel debug 之 CallTrace

这篇文章是基于上次UWB(WUSB) wireless debug 的一个问题,然后引申出来的一个话题,对kenel有一定理解的同学可能会有一定的帮助。 --其实这个问题,个人认为,这个个CallT...
  • csdn_zhang99
  • csdn_zhang99
  • 2016年07月15日 10:09
  • 2373

Linux调试 call trace dump_stuck

call trace能把当前的函数调用栈打印出来。 内核态call trace 内核态有三种出错情况,分别是bug, oops和panic。 bug属于轻微错误,比如在spin_lock期间调用了sl...
  • zifeng274059226
  • zifeng274059226
  • 2016年01月09日 18:23
  • 3649

linux call trace

Manish Sarori says:  November 25th, 2008 at 10:20 pm In the calltrace, does anyone know what the n...
  • ssmale
  • ssmale
  • 2014年04月18日 10:47
  • 475

Linux calltrace

本文介绍了在Linux环境下根据EABI标准进行call trace调试的一般性原理。 本文所说的call trace是指程序出问题时能把当前的函数调用栈打印出来。 本文只介绍...
  • CHALLEN537
  • CHALLEN537
  • 2012年05月18日 22:54
  • 593

CALL STACK TRACE GENERATION

转载自http://www.acsu.buffalo.edu/~charngda/backtrace.html(链接已失效)
  • littlefang
  • littlefang
  • 2014年11月19日 13:30
  • 3176

Linux系统调用的system_call处理过程分析

董涛  原创作品转载请注明出处 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000   基于实验楼网站提供的《L...
  • u011543541
  • u011543541
  • 2015年03月29日 10:54
  • 1260

calltrace 中寄存器 && vmalloc && virt_to_page

1预备知识:RIP(指令指针)RIP寻址代码段存储区内的下一条指令  RSP(堆栈指针)RSP寻址一个称为堆栈的存储区。通过这个指针存取堆栈存储器数据,具体操作将在本书后面讲解访问堆栈存储器数据的指令...
  • guogaofeng1219
  • guogaofeng1219
  • 2011年04月15日 11:02
  • 1144

Choregographer工作原理分析

结论写在前面:Choreographer就是一个消息处理器,根据vsync 信号 来计算frame,而计算frame的方式就是处理三种回调,包括事件回调、动画回调、绘制回调。这三种事件在消息输入、加入...
  • prike
  • prike
  • 2015年11月18日 13:33
  • 525

Linux程序运行跟踪trace

一、源程序 1.源码 #include #include int main() { int i; printf("TK------>>>sizeof i is %d\n",sizeo...
  • tankai19880619
  • tankai19880619
  • 2014年04月08日 10:53
  • 7331
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Linux Call Trace原理分析
举报原因:
原因补充:

(最多只允许输入30个字)