ARM GCC 生成的函数序言
ARM GCC generated functions prolog
我提到过 ARM 工具链可以生成不同的函数序言。实际上,我看到了两个函数序言完全不同的 obj 文件(vmlinux):
第一个案例如下:
push {some registers maybe, fp, lr} (lr ommited in leaf function)
第二种情况如下:
push {some registers maybe, fp, sp, lr, pc} (i can confuse the order)
因此,正如我所见,第二个推额外的 pc 和 sp。此外,我在崩溃实用程序(kdump 项目)中看到了一些评论,其中指出,内核堆栈框架应该具有格式 {..., fp, sp, lr, pc} 更让我困惑的是,因为我发现在某些情况下它不是是的。
1.) 关于在函数 prolog 中额外推送 pc 和 sp 需要一些 gcc 额外标志,我说得对吗?如果是,它们是什么?
2.) 这是做什么用的?基本上,据我所知,我只能使用 FP 和 LR 展开堆栈,为什么我需要这些附加值?
3.) 如果这件事与编译标志无关——我如何强制生成这个扩展函数序言以及目的是什么?
谢谢。
1.) Am i right about that some gcc extra flags are needed for pushing additionally pc and sp in function prolog? If yes what are they?.
有许多 gcc 选项会影响堆栈帧(-march
、-mtune
等可能会影响所使用的指令)。在你的例子中,它是 -mapcs-frame
。此外,-fomit-frame-pointer
将从叶函数中删除帧。几个静态函数可以合并到一个生成的函数中,进一步减少帧数。 APCS 可能会导致代码稍慢,但堆栈跟踪需要它。
2.) What is this used for? Basically, as i understand i can unwind stack with FP and LR only, why do i need this additional values?
所有不是参数 (r0-r3) 的寄存器都需要保存,因为它们需要在 returning 给调用者时恢复。编译器将在堆栈上分配额外的局部变量,因此 sp
几乎总是在 fp
更改时更改。为什么要存储pc
,见下文。
3.) If this things dealth nothing with compilation flags - how can i force generation of this extended function prolog and again what is the purpose?
如您所料,这是编译器标志。
;序言 - 设置
移动 IP, SP ;获取 sp 的副本。
stm sp!, {fp, ip, lr, pc} ;将帧保存在堆栈上。 <sup>见附录</sup>
sub fp, ip, #4 ;设置新的帧指针。
...
;结语 - return
ldm sp, {fp, sp, lr} ;恢复堆栈、帧指针和旧 link。
...;也许更多的东西在这里。
bx lr ; return。
</pre>
典型的保存是 stm sp!, {fp, ip, lr, pc}
和恢复 ldm sp, {fp, sp, lr}
。如果您检查 ABI/APCS 文档,这是正确的。请注意,没有“!”尝试修复堆栈。它是从存储的 ip
值显式加载的。
此外,保存的pc
未在结语中使用。它只是堆栈中丢弃的数据。那为什么要这样做呢?异常处理程序(中断、信号或 C++ 异常)和其他堆栈跟踪机制想知道谁保存了帧。 ARM总是只有一个函数prologue(一个入口点)。但是,有多个出口。在某些情况下,像 return function();
这样的 return 实际上可能会在 中变成 b function
,这里可能还有更多内容 。这称为尾调用。此外,当在例程中间调用叶函数并发生异常时,它将看到 PC
范围的叶,但叶可能没有调用帧。通过保存pc
,call frame可以在leaf发生异常时进行检查,从而知道究竟是谁保存了堆栈。 pc
与析构函数等的表可能会被存储以允许 对象 被释放或弄清楚如何调用信号处理程序。额外的 pc
在跟踪堆栈时非常好,并且由于管道衬里,操作几乎是免费的。
另请参阅:ARM Link and frame register关于编译器如何使用这些寄存器的问题。
我提到过 ARM 工具链可以生成不同的函数序言。实际上,我看到了两个函数序言完全不同的 obj 文件(vmlinux):
第一个案例如下:
push {some registers maybe, fp, lr} (lr ommited in leaf function)
第二种情况如下:
push {some registers maybe, fp, sp, lr, pc} (i can confuse the order)
因此,正如我所见,第二个推额外的 pc 和 sp。此外,我在崩溃实用程序(kdump 项目)中看到了一些评论,其中指出,内核堆栈框架应该具有格式 {..., fp, sp, lr, pc} 更让我困惑的是,因为我发现在某些情况下它不是是的。
1.) 关于在函数 prolog 中额外推送 pc 和 sp 需要一些 gcc 额外标志,我说得对吗?如果是,它们是什么?
2.) 这是做什么用的?基本上,据我所知,我只能使用 FP 和 LR 展开堆栈,为什么我需要这些附加值?
3.) 如果这件事与编译标志无关——我如何强制生成这个扩展函数序言以及目的是什么?
谢谢。
1.) Am i right about that some gcc extra flags are needed for pushing additionally pc and sp in function prolog? If yes what are they?.
有许多 gcc 选项会影响堆栈帧(-march
、-mtune
等可能会影响所使用的指令)。在你的例子中,它是 -mapcs-frame
。此外,-fomit-frame-pointer
将从叶函数中删除帧。几个静态函数可以合并到一个生成的函数中,进一步减少帧数。 APCS 可能会导致代码稍慢,但堆栈跟踪需要它。
2.) What is this used for? Basically, as i understand i can unwind stack with FP and LR only, why do i need this additional values?
所有不是参数 (r0-r3) 的寄存器都需要保存,因为它们需要在 returning 给调用者时恢复。编译器将在堆栈上分配额外的局部变量,因此 sp
几乎总是在 fp
更改时更改。为什么要存储pc
,见下文。
3.) If this things dealth nothing with compilation flags - how can i force generation of this extended function prolog and again what is the purpose?
如您所料,这是编译器标志。
;序言 - 设置 移动 IP, SP ;获取 sp 的副本。 stm sp!, {fp, ip, lr, pc} ;将帧保存在堆栈上。 <sup>见附录</sup> sub fp, ip, #4 ;设置新的帧指针。 ... ;结语 - return ldm sp, {fp, sp, lr} ;恢复堆栈、帧指针和旧 link。 ...;也许更多的东西在这里。 bx lr ; return。 </pre>
典型的保存是
stm sp!, {fp, ip, lr, pc}
和恢复ldm sp, {fp, sp, lr}
。如果您检查 ABI/APCS 文档,这是正确的。请注意,没有“!”尝试修复堆栈。它是从存储的ip
值显式加载的。此外,保存的
pc
未在结语中使用。它只是堆栈中丢弃的数据。那为什么要这样做呢?异常处理程序(中断、信号或 C++ 异常)和其他堆栈跟踪机制想知道谁保存了帧。 ARM总是只有一个函数prologue(一个入口点)。但是,有多个出口。在某些情况下,像return function();
这样的 return 实际上可能会在 中变成b function
,这里可能还有更多内容 。这称为尾调用。此外,当在例程中间调用叶函数并发生异常时,它将看到PC
范围的叶,但叶可能没有调用帧。通过保存pc
,call frame可以在leaf发生异常时进行检查,从而知道究竟是谁保存了堆栈。pc
与析构函数等的表可能会被存储以允许 对象 被释放或弄清楚如何调用信号处理程序。额外的pc
在跟踪堆栈时非常好,并且由于管道衬里,操作几乎是免费的。另请参阅:ARM Link and frame register关于编译器如何使用这些寄存器的问题。