【问题标题】:ARM64: How to protect the whole stack when branching to a function from assemblyARM64:从汇编分支到函数时如何保护整个堆栈
【发布时间】:2017-02-05 01:19:28
【问题描述】:

我有以下 ARM64 汇编代码:

.text
.arch armv8-a
.type testARM64, STT_FUNC
.global testARM64

testARM64:
arg1    .req x0
arg2    .req x1
arg3    .req x2
arg4    .req x3
arg5    .req x4
arg6    .req x5
tmp .req x9


    mov tmp, #0

    mov x0, #1
    bl debugAssembly

    mov tmp, #2

    ret

.unreq arg1
.unreq arg2
.unreq arg3
.unreq arg4
.unreq arg5
.unreq arg6
.unreq tmp

我叫它:

#include <stdlib.h>

void testARM64(int arg1, int arg2, int arg3, int arg4, int arg5, int arg6);

void debugAssembly(int a) {
    fprintf(stderr, "Debug 0x%d\n", a);
}

int main(int argc, char **argv) {
    testARM64(0, 0, 0, 0, 0, 0);
    return 0;
}

分支到 debugAssembly 时如何保护整个堆栈?我的意思是什么相当于 push/pop ARM 指令,无论参数的数量和我在我的程序集中使用任何临时寄存器做什么都可以工作? (我不需要保护/保存车道)。

【问题讨论】:

标签: arm arm64


【解决方案1】:

您需要保存 fp reg 和链接寄存器——通常使用 stp x29, x30, [sp, #0x10] 之类的东西来完成!假设您的平台使用 x29 作为 fp - 在您调用另一个函数并在退出函数之前恢复值之前。否则,当您使用其他函数时,链接寄存器(保存调用者的返回地址)将被覆盖。您的 ABI 可能需要堆栈指针的 16 字节对齐,因此即使您的平台不使用帧指针,您也需要将两个寄存器保存到堆栈中。

我建议反汇编您的编译器生成的一些简单函数,并将其指令用作您自己的手写例程的模型。

【讨论】:

  • 我使用 gcc -S 来了解 gcc 是如何做到的,但它总是特定于当前情况,也就是。我改变了多少寄存器。我希望能够在任何需要的地方复制粘贴相同的调试代码,而不必担心堆栈/寄存器的状态。因此,为什么我的问题说“整个堆栈”。
  • 我不明白你所说的“整个堆栈”是什么意思。您可以将所有非易失性(或“被调用者保存”)寄存器保存在函数序言(函数的开头)中,然后在函数结尾(函数的结尾)中恢复它们——这将是安全的适用于您所有的手写功能。假设您的 ABI 符合 AAPCS,InfinitelyManic 链接的 AAPCS 是需要保存的很好的参考。请注意,保存比您需要保存更多的寄存器是低效的......编写手写汇编的唯一原因是为了关键的效率功能......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-07-12
  • 2015-04-28
  • 2016-10-04
  • 2011-07-30
  • 2016-03-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多