假设函数调用过程 34%34$,另外每个函数中只有一个 *5 打印。这种情况下
函数的入栈和 0 段的信息就很规则和简单,这里就以简单的来讲解,便于理解。
此时每个函数第一条指令一般是 67(+8,这表示将 和 ( 寄存器入栈,此时系
统会将跟 67(+8指令相关的编码数据 99 存入 函数的 0 段中,
,-- 跟 偏移 有关 ,但 是实 际用 处不 大。 99 分 离成 9, 9
, 又有不同的意义,最重要的是 9,表示出栈指令 7((8,( 就
是 寄存器,与 67(+8入栈指令正好相反。 函数跳转到 % 函数后,会把 % 函数
的返回地址 (:9 存入 % 函数栈。% 函数按照同样的方法执行,当执行到 $ 函
数最后,几个函数的栈信息和 0 段信息就如图所示。假设在 $ 函数中崩溃了,会
首先根据崩溃的 值,找到崩溃 $ 函数的 0 段每个函数的指令地址和 0
段都是对应的,内核有标准的函数可以查找。如图所示,从地址 (: 的 $ 函
数 0 段中 取出数 据 99 ,分析 出其中的 9 ,就 知道对应的
7((8出栈指令,相应就知道函数入栈时执行的是 67(+8指令,其中有两个
重要信息,一个是函数入栈时只有 和 ( 寄存器入栈,并且函数栈大小是 ;(<9 个字
节,函数崩溃时栈指针 指向崩溃函数 $ 的栈顶,根据 就能找到 寄存器存储在 $
函数栈的数据 (9,就是崩溃函数的返回地址,上一级函数 % 的指令地址,
而 2;( 就是上一级 % 函数的栈顶。知道了 % 函数的指令地址和栈顶地址,就能根
据指令地址找到 % 函数的 0 段,分析出 % 函数的入栈指令,按照同样的方法,就
能找到 函数的返回地址和栈顶。这只是几个很简单 0 栈回溯过程的演示,省去
了很多细节,读者想研究清楚的话,可以阅读内核 架构 01 函数实现
流程,其中最核心的是在 011 函数,根据 9, 这些跟函数入
栈过程有关的编码数据,分析入栈过程的详细信息,计算出函数 寄存器保存在栈中的
地址和上一级函数的栈顶地址。
不同的入栈指令在函数的 0 段对应不同的编码,99 只是其中比
较简单的的编码,还有 9,9 等等很多。可以执行{ 3
/$&)/01= 查看内核 * 段函数的 0 段数据。比如:
这 就 表 示 *61=11 函 数 在 0 段 编 码 数 据 是
99,9 9 是该函数指令首地址。其中有用的是 9,表示
7(+(8出栈指令, 表示 0 段结束。
为了方便读者分析对应的栈回溯内核源码,这里把关键点列出,并添加必要注释。内
核版本 //(。
650/
评论0
最新资源