assembly ARM GCC生成的函数prolog

i34xakig  于 11个月前  发布在  其他
关注(0)|答案(1)|浏览(147)

我提到过ARM工具链可以生成不同的函数prolog,实际上,我看到了两个obj文件(vmlinux),它们具有完全不同的函数prolog:
第一种情况如下所示:

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.)我说的对吗,一些gcc额外的标志需要在函数prolog中额外推送pc和sp?如果是,它们是什么?
2.)这是做什么用的?基本上,就我所知,我可以只用FP和LR来展开堆栈,为什么我需要这些额外的值?
3.)如果这个东西没有编译标志,我怎么能强制生成这个扩展函数的prolog,目的是什么?
谢谢

gudnpqoy

gudnpqoy1#

1.)我说的对吗,一些gcc额外的标志需要在函数prolog中额外推送pc和sp?如果是,它们是什么?
有许多gcc选项会影响堆栈帧(-march-mtune等可能会影响例如使用的指令)。在您的情况下,它是-mapcs-frame。此外,-fomit-frame-pointer将从叶函数中删除帧。几个静态函数可以合并到一个生成的函数中,以进一步减少帧的数量。APCS可能会导致代码稍微变慢但是对于简单的堆栈跟踪是需要的。
2.)这是做什么用的?基本上,就我所知,我可以只用FP和LR来展开堆栈,为什么我需要这些额外的值?
所有不是参数的寄存器(r 0-r3)都需要保存,因为它们需要在返回给调用者时恢复。编译器将在堆栈上分配额外的局部变量,因此当fp更改时,sp几乎总是会更改。关于存储pc的原因,请参阅下文。
3.)如果这个东西没有编译标志,我怎么能强制生成这个扩展函数的prolog,目的是什么?
正如您所猜测的那样,它是编译器标志。

; Prologue - setup
mov     ip, sp                 ; get a copy of sp.
stm     sp!, {fp, ip, lr, pc}  ; Save the frame on the stack. See Addendum
sub     fp, ip, #4             ; Set the new frame pointer.
    ...
; Epilogue - return
ldm     sp, {fp, sp, lr}       ; restore stack, frame pointer and old link.
    ...                        ; maybe more stuff here.
bx      lr                     ; return.

字符串
典型的保存是stm sp!, {fp, ip, lr, pc},恢复是ldm sp, {fp, sp, lr}。如果您检查ABI/APCS文档,这是正确的。注意,没有“!”来尝试和修复堆栈。它是从存储的ip值显式加载的。
另外,保存的pc并没有在尾声中使用。它只是堆栈上丢弃的数据。那么为什么要这样做呢?异常处理程序(中断、信号或C++异常)和其他堆栈跟踪机制都想知道谁保存了一个帧。(一个入口)。然而,有多个出口。在某些情况下,像return function();这样的返回实际上可能会变成b function,在 * 这里可能有更多的东西 *。这被称为尾调用。同样,当在例程中间调用叶函数并发生异常时,它将看到叶的PC范围,但叶可能没有调用帧。通过保存pc,当在leaf中发生异常时,可以检查 call frame,以知道是谁真正保存了堆栈。pc与析构函数的表,等,可以存储以允许 * 对象 * 释放或弄清楚如何调用信号处理程序。额外的pc在跟踪堆栈时非常好,由于管道衬里,操作几乎是免费的。
参见:ARM Link and frame register问题,了解编译器如何使用这些寄存器。

相关问题