ARM GCC 生成函数序言 [英] ARM GCC generated functions prolog

查看:29
本文介绍了ARM GCC 生成函数序言的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我提到 ARM 工具链可以生成不同的函数序言.实际上,我看到两个 obj 文件(vmlinux)具有完全不同的功能序言:

I mentioned that ARM toolchains could generate different function prologs. Actually, i saw two obj files (vmlinux) with completely different function prologs:

第一种情况如下:

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} 这让我更加困惑,因为我看到在某些情况下它不是真的.

So as i see the second one pushes additionally pc and sp. Also i saw some comments in crash utility (kdump project) where was stated, that kernel stackframe should have format {..., fp, sp, lr, pc} what confuse me more, because i see that in some cases it is not true.

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

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?.

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

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?

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

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?

谢谢.

推荐答案

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

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 可能会导致代码稍慢,但堆栈跟踪需要它.

There are many gcc options that will affect stack frames (-march, -mtune, etc may affect the instructions used for instance). In your case, it was -mapcs-frame. Also, -fomit-frame-pointer will remove frames from leaf functions. Several static functions maybe merged together into a single generated function further reducing the number of frames. The APCS can cause slightly slower code but is needed for stack traces.

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

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 的存储原因见下文.

All registers that are not parameters (r0-r3) need to be saved as they need to be restored when returning to the caller. The compiler will allocate additional locals on the stack so sp will almost always change when fp changes. For why the pc is stored, see below.

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

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?

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

It is compiler flags as you had guessed.

; 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 值显式加载的.

A typical save is stm sp!, {fp, ip, lr, pc} and a restore of ldm sp, {fp, sp, lr}. This is correct if you examine the ABI/APCS documents. Note, there is no '!' to try and fix the stack. It is loaded explicitly from the stored ip value.

另外,已保存的 pc 不会在结尾使用.它只是堆栈上丢弃的数据.那么为什么要这样做呢?异常处理程序(中断、信号或 C++ 异常)和其他堆栈跟踪机制想知道谁保存了帧.ARM 总是只有一个函数prologue(一个入口点).但是,有多个出口.在某些情况下,像 return function(); 这样的返回实际上可能会在 这里可能更多内容中变成 b 函数.这被称为尾调用.此外,当在例程中间调用叶函数并发生异常时,它会看到 PC 范围的叶,但叶可能没有调用帧.通过保存pc,可以在叶子发生异常时检查调用帧,从而知道谁真正保存了堆栈.pc 与析构函数等的表可能被存储以允许 objects 被释放或弄清楚如何调用信号处理程序.在跟踪堆栈时,额外的 pc 非常好,并且由于管道衬里,操作几乎是免费的.

Also, the saved pc is not used in the epilogue. It is just discarded data on the stack. So why do this? Exception handlers (interrupts, signals or C++ exceptions) and other stack trace mechanisms want to know who saved a frame. The ARM always only have one function prologue (one point of entry). However, there are multiple exits. In some cases, a return like return function(); may actually turn into a b function in the maybe more stuff here. This is known as a tail call. Also when a leaf function is called in the middle of a routine and an exception occurs, it will see a PC range of leaf, but the leaf may have no call frame. By saving the pc, the call frame can be examined when an exception occurs in leaf to know who really saved the stack. Tables of pc versus destructor, etc. maybe stored to allow objects to be freed or to figure out how to call a signal handler. The extra pc is just plain nice when tracing a stack and the operation is almost free due to pipe lining.

另请参阅:ARM 链接和帧寄存器问题,了解如何编译使用这些寄存器.

See also: ARM Link and frame register question for how the compiler uses these registers.

这篇关于ARM GCC 生成函数序言的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆