【问题标题】:ARM GCC generated functions prologARM GCC 生成函数序言
【发布时间】:2015-12-13 22:12:33
【问题描述】:

我提到 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 项目)中看到了一些 cmets,其中指出,内核堆栈帧应该具有格式 {..., fp, sp, lr, pc} 这让我更加困惑,因为我看到在某些情况下它不是真的。

1.) 我对在函数 prolog 中额外推送 pc 和 sp 需要一些 gcc 额外标志是否正确?如果是,它们是什么?。

2.) 这是做什么用的?基本上,据我所知,我只能使用 FP 和 LR 展开堆栈,为什么我需要这些附加值?

3.) 如果这与编译标志无关 - 我如何强制生成此扩展函数序言,目的是什么?

谢谢。

【问题讨论】:

    标签: c gcc assembly stack arm


    【解决方案1】:

    1.) 我对在函数 prolog 中额外推送 pc 和 sp 需要一些 gcc 额外标志是正确的吗?如果是,它们是什么?。

    有许多 gcc 选项会影响堆栈帧(-march-mtune 等可能会影响所使用的指令)。在您的情况下,它是-mapcs-frame。此外,-fomit-frame-pointer 将从叶函数中删除帧。几个静态函数可以合并到一个生成的函数中,进一步减少帧数。 APCS 可能会导致代码稍慢,但堆栈跟踪需要它。

    2.) 这是做什么用的?基本上,据我所知,我只能使用 FP 和 LR 展开堆栈,为什么我需要这些附加值?

    所有不是参数的寄存器(r0-r3)都需要保存,因为它们需要在返回给调用者时恢复。编译器将在堆栈上分配额外的局部变量,因此sp 几乎总是会在fp 更改时更改。为什么要存储pc,请参见下文。

    3.) 如果这与编译标志无关 - 我如何强制生成此扩展函数序言,目的是什么?

    如你所料,这是编译器标志。

    ; 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++ 异常)和其他堆栈跟踪机制想知道谁保存了帧。 ARM 总是只有一个函数prologue(一个入口点)。但是,有多个出口。在某些情况下,像return function(); 这样的返回实际上可能会在这里可能会有更多内容中变成b function。这被称为尾调用。此外,当在例程中间调用叶函数并发生异常时,它将看到叶的PC 范围,但叶可能没有调用帧。通过保存pc调用帧可以在叶子中发生异常时检查,以了解谁真正保存了堆栈。 pc 与析构函数等的表可能被存储以允许释放 对象 或弄清楚如何调用信号处理程序。额外的pc 在跟踪堆栈时非常好,并且由于管道衬里,操作几乎是免费的。

    另请参阅:ARM Link and frame register 编译器如何使用这些寄存器的问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-07-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-24
      • 1970-01-01
      相关资源
      最近更新 更多