c - ARM GCC 生成的函数序言

标签 c gcc assembly stack arm

我提到过 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) 都需要保存,因为它们需要在返回给调用者时恢复。编译器将在堆栈上分配额外的局部变量,因此 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?

如您所料,它是编译器标志。

; Prologue - setup
mov     ip, sp                 ; get a copy of sp.
stm     sp!, {fp, ip, lr, pc}  ; Save the frame on the stack. <sup>See Addendum</sup>
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 函数 这里可能还有更多内容。这称为尾调用。此外,当在例程中间调用叶函数并发生异常时,它将看到 PC 范围的叶,但叶可能没有调用帧。通过保存 pccall frame 可以在 leaf 中发生异常时检查,以了解真正保存堆栈的人。 pc 与析构函数等的表可能会被存储以允许释放对象 或找出如何调用信号处理程序。额外的 pc 在跟踪堆栈时非常好,并且由于管道衬里,操作几乎是免费的。

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

关于c - ARM GCC 生成的函数序言,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32623597/

相关文章:

c - 从数组创建链表时 C 中的段错误

c - Pthread代码运行时中途崩溃

c - 模糊图像矩阵时出现分割错误。 [C]

c++ - 为什么 GCC 不优化 C++ 中空指针的删除?

c - ncurses 新手 - 从 GNU C 开始

c - 归档和 gtk 一起 - 可能吗?

linux - 编译后无法识别 gcc 7.1 参数

assembly - 错误:“push”的无效指令后缀

assembly - 在堆栈帧中推送返回值

c++ - VS 2008 生成的奇怪汇编器