我想从C++调用ARM / ARM64 ASM代码。 ASM代码包含syscall和重定位到外部函数。
这里的ARM体系结构不是那么重要,我只想了解如何从概念上解决问题。

我有以下在共享库中调用的ASM syscall(从objdump -d输出):

 198:   d28009e8    mov x8, #0x4f                   // #79
 19c:   d4000001    svc #0x0
 1a0:   b140041f    cmn x0, #0x1, lsl #12
 1a4:   da809400    cneg    x0, x0, hi
 1a8:   54000008    b.hi    0 <__set_errno_internal>
 1ac:   d65f03c0    ret

这段代码调用fstatat64 syscall,并通过外部errno函数设置__set_errno_internalreadelf -r显示了__set_errno_internal函数的以下重定位:
00000000000001a8 R_AARCH64_CONDBR19  __set_errno_internal

我想从C++调用这段代码,所以我将其转换为缓冲区:
  unsigned char machine_code[] __attribute__((section(".text"))) =
        "\xe8\x09\x80\xd2"
        "\x01\x00\x00\xd4"
        "\x1f\x04\x40\xb1"
        "\x00\x94\x80\xda"
        "\x08\x00\x00\x54"   // Here we have mentioned relocation
        "\xc0\x03\x5f\xd6";

编辑:重要细节-我选择使用缓冲区(而不是内联汇编等),因为我想对该缓冲区进行额外的处理(例如,字符串字面量的解密函数作为一种软件保护机制,但这在这里并不重要),然后才被评估为机器代码。

之后,可以将缓冲区转换为函数并直接调用以执行机器代码。显然,重定位存在问题,它不是自动修复的,我必须手动修复。但是在运行时我无法做到这一点,因为.text部分是只读的且可执行的。

尽管我几乎可以完全控制源代码,但是我一定不能关闭堆栈保护和其他功能以使该部分可写(不要问为什么)。因此,似乎应该以某种方式在链接阶段执行重定位修复。据我所知,在链接器和二进制文件* .so修复了重定位后,共享库包含相对偏移量(用于类似的外部函数调用),因此文件应包含正确的偏移量(无需运行时重定位工作),因此请在运行时修复machine_code缓冲区链接应该是可能的。

我正在使用手动构建的Clang 7编译器,并且可以完全控制LLVM传递,因此我认为也许可以编写某种在链接时间内执行的LLVM传递。尽管看起来ld最终被调用了,所以LLVM传递可能对这里没有帮助(这里不是专家)。

也将理解不同的想法。
如您所见,问题非常复杂。也许您有一些指导/想法如何解决这个问题?谢谢!

最佳答案

已经有一种有效的打包机制来处理重定位。它称为dlsym()。尽管它没有直接为您提供函数指针,但是所有主要的C++编译器都支持reinterpret_cast,将dlsym的结果存储到任何普通函数指针中。 (成员函数完全是另一个问题,但这与这里无关)

10-07 16:29