我想从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_internal
。
readelf -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传递对这里没有帮助(这里不是专家)。
不同的想法也将不胜感激。 如您所见,问题非常复杂。也许您有一些指导/想法如何解决这个问题?谢谢!
答案 0 :(得分:1)
已经有一种有效的打包机制来处理重定位。它称为dlsym()
。尽管它没有直接为您提供函数指针,但所有主要的C ++编译器都支持reinterpret_cast
的{{1}}结果转换为任何普通函数指针。 (成员函数完全是另一个问题,但这与这里无关)