动态执行的ARM ASM系统调用,并带有C ++中的重定位

时间:2019-07-05 14:25:08

标签: c++ assembly linker arm llvm

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

我有以下在共享库中调用的ASM系统调用(来自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修复了重定位后,共享库包含相对偏移量(用于类似的外部函数调用),因此文件应包含正确的偏移量(无需运行时重定位工作),因此应修复{{1 }}在链接期间应该有缓冲。

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

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

1 个答案:

答案 0 :(得分:1)

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