Как получить доступ к параметру, передаваемому в стеке при входе в DLL? - PullRequest
0 голосов
/ 19 мая 2018

Я звоню в 64-битную DLL NASM из ctypes.DLL принимает пять входных параметров.В соглашении о вызовах Windows первые четыре передаются в rcx, rdx, r8 и r9, а пятый передается в стеке.

Обзор соглашений о вызовах x64 doc (https://docs.microsoft.com/en-us/cpp/build/overview-of-x64-calling-conventions) говорит: «Любые параметры, кроме первых четырех, должны храниться в стеке, над хранилищем теней для первых четырех, до вызова».Таким образом, поэтому к значению нельзя получить доступ с помощью pop, и я думаю, что к нему следует обращаться с помощью RSP. Если пятые (и более поздние) параметры находятся выше хранилища теней, то я предположил, что это будет RSP минус 40 (mov rax,[rsp-40]), но это не так.

Я попытался «пройтись по стеку», что означает, что я пробовал в rsp-0, rsp-8, rsp-16 и т. д. вплоть до rsp-56, но он не вернул значение, которое я передал в качестве пятого параметра (одиночный 64-битный двойной).

Согласно https://docs.microsoft.com/en-us/cpp/build/stack-allocation, макет стека на входе - это адрес возврата, rcx,rdx, r8, r9 и область параметров стека, так что я ожидаю найти свое значение в rsp-48, но его нет и нет в rsp-56.

Итак, мой вопрос: какполучить доступ к параметру, передаваемому в стеке при входе в dll в Windows, вызывая convention?

РЕДАКТИРОВАТЬ: Вот соответствующий код ctypes:

hDLL = ctypes.WinDLL("C:/Test_Projects/MultiCompare/py_descent.dll")
    CallName = hDLL.Main_Entry_fn
    CallName.argtypes = [ctypes.POINTER(ctypes.c_double),ctypes.POINTER        (ctypes.c_double),ctypes.c_double,ctypes.POINTER(ctypes.c_double),ctypes.c_double]
    CallName.restype = ctypes.c_double

ret_ptr = CallName(CA_x,CA_d,CA_mu,length_array_out,CA_N_epochs)

Data types:
CA_x:  pointer to double(float) array
CA_d:  pointer to double(float) array
CA_mu:  double
length_array_out:  pointer to double(float) array
CA_N_epochs:  double

Вот точка входа в DLL, где получены переменные.Я всегда нажимаю rdi и rbp при входе, поэтому сначала беру параметры, переданные в стек, прежде чем сделать это, чтобы предотвратить смещение стека:

Main_Entry_fn:
; First the stack parameters
movsd xmm0,[rsp+40]
movsd [N_epochs],xmm0
; End stack section
push rdi
push rbp
mov [x_ptr],rcx
mov [d_ptr],rdx
movsd [mu],xmm2
mov [data_master_ptr],r9
; Now assign lengths
; (this part intentionally omitted for brevity)
call py_descent_fn
exit_label_for_Main_Entry_fn:
pop rbp
pop rdi
ret

1 Ответ

0 голосов
/ 19 мая 2018

Предоставленные ссылки были относительно ясными, но если что-то неоднозначно, я прибегаю к компиляции примера C и рассмотрению сборки.Результат в конце этого поста.Назначения были:

[RSP]           Return address
[RSP+8]  ECX    int a     (XMM0 unused)
[RSP+16] EDX    int b     (XMM1 unused)
[RSP+24] XMM2   double c  (R8 unused)
[RSP+32] R9     int d     (XMM3 unused)
[RSP+40]        double e    
[RSP+48]        int f

Первые четыре параметра находятся в регистрах.Первый параметр - R8 / XMM0 в зависимости от типа.Второй - R9 / XMM1 и т. Д. Пятый и более поздние параметры (в данном случае [RSP + 40] и [RSP + 48]) всегда находятся в стеке.Четыре четверных слова от [RSP + 8] до [RSP + 32] являются теневым пространством для регистров.Я скомпилировал без оптимизации ниже, поэтому функция немедленно вылила регистры в теневое пространство.

Надеюсь, это очистит его.

C пример

int func(int a, int b, double c, int d, double e, int f)
{
    return (int)(a+b+c+d+e+f);
}

int main()
{
    func(1,2,1.1,4,5.5,6);
    return 0;
}

Генерируемая сборка:

; Listing generated by Microsoft (R) Optimizing Compiler Version 19.00.24215.1 

include listing.inc

INCLUDELIB LIBCMT
INCLUDELIB OLDNAMES

PUBLIC  func
PUBLIC  main
PUBLIC  __real@3ff199999999999a
PUBLIC  __real@4016000000000000
EXTRN   _fltused:DWORD
pdata   SEGMENT
$pdata$main DD  imagerel $LN3
        DD      imagerel $LN3+62
        DD      imagerel $unwind$main
pdata   ENDS
;       COMDAT __real@4016000000000000
CONST   SEGMENT
__real@4016000000000000 DQ 04016000000000000r   ; 5.5
CONST   ENDS
;       COMDAT __real@3ff199999999999a
CONST   SEGMENT
__real@3ff199999999999a DQ 03ff199999999999ar   ; 1.1
CONST   ENDS
xdata   SEGMENT
$unwind$main DD 010401H
        DD      06204H
xdata   ENDS
; Function compile flags: /Odtp
; File c:\users\metolone\x.c
_TEXT   SEGMENT
main    PROC

; 7    : {

$LN3:
  00000 48 83 ec 38      sub     rsp, 56                        ; 00000038H

; 8    :     func(1,2,1.1,4,5.5,6);

  00004 c7 44 24 28 06
        00 00 00         mov     DWORD PTR [rsp+40], 6
  0000c f2 0f 10 05 00
        00 00 00         movsd   xmm0, QWORD PTR __real@4016000000000000
  00014 f2 0f 11 44 24
        20               movsd   QWORD PTR [rsp+32], xmm0
  0001a 41 b9 04 00 00
        00               mov     r9d, 4
  00020 f2 0f 10 15 00
        00 00 00         movsd   xmm2, QWORD PTR __real@3ff199999999999a
  00028 ba 02 00 00 00   mov     edx, 2
  0002d b9 01 00 00 00   mov     ecx, 1
  00032 e8 00 00 00 00   call    func

; 9    :     return 0;

  00037 33 c0            xor     eax, eax

; 10   : }

  00039 48 83 c4 38      add     rsp, 56                        ; 00000038H
  0003d c3               ret     0
main    ENDP
_TEXT   ENDS
; Function compile flags: /Odtp
; File c:\users\metolone\x.c
_TEXT   SEGMENT
a$ = 8
b$ = 16
c$ = 24
d$ = 32
e$ = 40
f$ = 48
func    PROC

; 2    : {

  00000 44 89 4c 24 20   mov     DWORD PTR [rsp+32], r9d
  00005 f2 0f 11 54 24
        18               movsd   QWORD PTR [rsp+24], xmm2
  0000b 89 54 24 10      mov     DWORD PTR [rsp+16], edx
  0000f 89 4c 24 08      mov     DWORD PTR [rsp+8], ecx

; 3    :     return (int)(a+b+c+d+e+f);

  00013 8b 44 24 10      mov     eax, DWORD PTR b$[rsp]
  00017 8b 4c 24 08      mov     ecx, DWORD PTR a$[rsp]
  0001b 03 c8            add     ecx, eax
  0001d 8b c1            mov     eax, ecx
  0001f f2 0f 2a c0      cvtsi2sd xmm0, eax
  00023 f2 0f 58 44 24
        18               addsd   xmm0, QWORD PTR c$[rsp]
  00029 f2 0f 2a 4c 24
        20               cvtsi2sd xmm1, DWORD PTR d$[rsp]
  0002f f2 0f 58 c1      addsd   xmm0, xmm1
  00033 f2 0f 58 44 24
        28               addsd   xmm0, QWORD PTR e$[rsp]
  00039 f2 0f 2a 4c 24
        30               cvtsi2sd xmm1, DWORD PTR f$[rsp]
  0003f f2 0f 58 c1      addsd   xmm0, xmm1
  00043 f2 0f 2c c0      cvttsd2si eax, xmm0

; 4    : }

  00047 c3               ret     0
func    ENDP
_TEXT   ENDS
END
...