按地址从jitted代码中调用c函数。

问题描述 投票:1回答:0

我目前正在尝试通过python进行JIT。我发现 桃色 通过另一个SO问题。大多数情况下,这是很容易的,但我在使用外部c函数时失败了。我想调用putchar,所以用一个单一参数的函数。因为我是在windows下,用的是x86-64,所以我希望将单个参数放到到 rcx,然后运行 call 与函数指针地址。为此我写了这段代码。

from peachpy import *
from peachpy.x86_64 import *
import ctypes


putchar_address = ctypes.addressof(ctypes.cdll.msvcrt.putchar)
c = Argument(uint64_t)

with Function("p", (c,), int64_t) as asm_function:
    LOAD.ARGUMENT(rcx, c)
    MOV(r8, putchar_address)
    CALL(r8)
    RETURN(rax)


raw = asm_function.finalize(abi.detect()).encode()
python_function = raw.load()

print(python_function(48))

这与 OSError: exception: access violation writing 0x0000029E58C1A978 在最后的代码上。

我翻阅了很多其他SO的答案,但都没有真正帮助解决这个问题,其实代码就是这些结果。最有用的是这个。处理从JIT代码中调用(潜在的)远期的超前编译函数。

编辑:我又尝试了几件事。

PeachPy不会特别暴露 rsp 直接,声称它已经正确处理了它。但我还是可以直接影响它,导致这段代码。

from peachpy.x86_64.registers import rsp
#...
    LOAD.ARGUMENT(rcx, c)
    SUB(rsp, 40)
    MOV(r8, putchar_address)
    CALL(r8)
    ADD(rsp, 40)
    RETURN(rax)

这就把错误改成了带有退出代码的崩溃。0xC0000409意思是堆栈访问超过堆栈顶部。

下面是PeaachPy生成的拆解结果。

没有 rsp

0:  49 b8 a8 a8 1a 84 1f    movabs r8,0x21f841aa8a8
7:  02 00 00
a:  41 ff d0                call   r8
d:  c3                      ret 

随着 rsp

0:  48 83 ec 28             sub    rsp,0x28
4:  49 b8 a8 98 ad 9e ac    movabs r8,0x1ac9ead98a8
b:  01 00 00
e:  41 ff d0                call   r8
11: 48 83 c4 28             add    rsp,0x28
15: c3                      ret 

(自 https:/defuse.caonline-x86-assembler.htm。)

根据c编译器的输出(这里。https:/godbolt.orgzBKgk7Y),我创建了以下代码

    MOV([rsp + 16], rdx)
    MOV([rsp + 8], rcx)
    SUB(rsp, 40)
    MOV(rcx, [rsp + 56])
    CALL([rsp + 48])
    ADD(rsp, 40)
    RETURN(rax)

它创建了与c编译器相同的汇编器代码。

0:  48 89 54 24 10          mov    QWORD PTR [rsp+0x10],rdx
5:  48 89 4c 24 08          mov    QWORD PTR [rsp+0x8],rcx
a:  48 83 ec 28             sub    rsp,0x28
e:  48 8b 4c 24 38          mov    rcx,QWORD PTR [rsp+0x38]
13: ff 54 24 30             call   QWORD PTR [rsp+0x30]
17: 48 83 c4 28             add    rsp,0x28
1b: c3                      ret 

这个失败,意味着问题不在生成的代码中。(而且我没有使用putchar,我仍然得到同样的退出代码0xC0000409)

python x86-64 jit calling-convention peachpy
© www.soinside.com 2019 - 2024. All rights reserved.