C语言 如何让MASM汇编在Linux.so文件中工作

nfeuvbwi  于 2023-05-22  发布在  Linux
关注(0)|答案(1)|浏览(123)

我有个特殊的问题。我有一个用VC++和MASM写的.dll。(ml64 14.34.31942)
C部分只是一个 Package 器,因此一个函数可以由C#(.net6)应用程序调用。只有一个入口点,它传递一个指向大型状态对象的指针。该函数返回一个int 32作为结果代码。
我想让这个应用程序在Linux上工作。我认为C#应用程序可以工作,但我的问题是对非托管.dll的调用。
如果我接受ml64.exe创建的对象文件,我可以将其 Package 在C Package 器中,以将寄存器设置为调用约定:

  • core.c*
#include <stdint.h>

extern int32_t asm_func(void* state);

int wrapper(void *state)
{
  __asm__ volatile(
     "mov %rdi, %rsi \t\n"
     "call asm_func  \t\n");

  return 0;
}

int32_t fnEmulatorCode(void* state) {
  return wrapper(state);
}

(返回代码待定!)
并使用以下命令编译:gcc -shared -o EmulatorCore.so -fPIC core.c core.obj -Wall -g -m64(core.obj是MASM对象文件)
生成的.so文件与任何其他非托管dll一样被引用:

[DllImport(@"./EmulatorCore/EmulatorCore.so")]
    private static extern int fnEmulatorCode(ref CpuState state);

而且电话起作用了!有点。入口点找到了,C Package 器改变寄存器也没问题。
然而,在汇编代码中有函数指针表,在Linux上没有被重新定位,所以对表的调用是分段错误的。这在Windows上有效。
例如:

lea rax [opcode_00]
lea rax, qword ptr [rax + rbx * 8]  ; rbx is the instruction
jmp qword ptr [rax]                 ; was original jmp qword ptr [rax + rbx * 8]

...

opcode_00   qword   x00_brk         ; $00
opcode_01   qword   x01_ora_indx    ; $01
opcode_02   qword   noinstruction   ; $02
...

所有其他的跳转和引用似乎都很好。
以及如何进行的建议?MASM根据objdump生成的目标文件为pe-x86-64。但是objcopy似乎无法将其转换为elf64-x86-64
那么,为什么Linux不“重新定位”这些表呢?是通过一些gcc优化吗?或者dotnet没有正确加载库?或者只是pe-coff文件没有正确地公开它们?如果是这样,我该如何工作?
我不能改变MASM的原始代码,但是有没有什么东西可以把它转换成NASM或类似的代码,这样我就可以交叉编译了?(不是说谷歌搜索找到任何东西…)
我可能会将表更改为适当的“跳转表”,但这会影响性能,并且可能会出现其他问题,因此在第一个示例中,我宁愿尝试保持ASM源代码不变。
编辑:
using nm -gC EmulatorCore.so | grep opcode_00返回nothing,这意味着引用没有包含在.so文件中,所以不能正确重定位?(表中的procs确实会出现,这就是为什么应用程序的其余部分看起来可以工作的原因)
编辑2:
为了说明这个问题,比较这两个图像。一个来自Windows,它显示了库在内存中的范围内的表,在Linux中,值都很低,表明是从库入口点的偏移量。
Windows中内存中的表(RIP:0x00007FFE043C5817)

Linux中内存中的表(RIP:0x00007f24fc59a5a8)

显示从表中跳转后的RIP,显示它正确阅读值,只是值错误。

4c8rllxm

4c8rllxm1#

在Windows上,跳转表会正确地重新计算,但在Linux上则不会。
为了让它工作,需要将表转换为相对跳转,并像这样调用:

lea rax [start]
add rax, qword ptr [rax + rbx * 8]  ; rbx is the instruction
jmp qword ptr [rax]                 ; was original jmp qword ptr [rax + rbx * 8]

...

start:
opcode_00   qword   x00_brk         - start ; $00
opcode_01   qword   x01_ora_indx    - start ; $01
opcode_02   qword   noinstruction   - start ; $02
...

相关问题