1
+ import std.stdio ;
2
+ import test;
3
+
4
+ // From x86_64 System V EABI Spec...
5
+ // rdi - 1st arg
6
+ // rsi - 2nd arg
7
+ // rdx - 3rd arg or 2nd return reg
8
+ // rcx - 4th arg
9
+ // r8 - 5th arg
10
+ // r9 - 6th arg
11
+ // rax - 1st return reg
12
+
13
+ // ASM code appears to be generated correctly for small sized return values
14
+ // extern (C) void* test(void* p1, uint p2);
15
+ // 0000000000401f18 <_Dmain>:
16
+ // 401f18: 55 push rbp
17
+ // 401f19: 48 8b ec mov rbp,rsp //end of function prologue
18
+ // 401f1c: 48 b8 ef be ad de 00 movabs rax,0xdeadbeef //rax = 0xdeadbeef (=p1)
19
+ // 401f23: 00 00 00
20
+ // 401f26: b9 64 00 00 00 mov ecx,0x64 //ecx = 0x64 (=p2)
21
+ // 401f2b: 48 89 ce mov rsi,rcx //rsi = rcx = ecx = p2
22
+ // 401f2e: 48 89 c7 mov rdi,rax //rdi = rax = p1
23
+ // 401f31: e8 d2 fc ff ff call 401c08 <test@plt> //test(rdi = p1, rsi = p2 )
24
+
25
+ // This is the problem case...
26
+ // extern (C) TestStruct test(void* p1, uint p2);
27
+ // 0000000000401f18 <_Dmain>:
28
+ // 401f18: 55 push rbp
29
+ // 401f19: 48 8b ec mov rbp,rsp
30
+ // 401f1c: 48 83 ec 10 sub rsp,0x10 //rsp -= 0x10 //reserve space for the return value
31
+ // we can only allocate 8 byte chunks on the 64 bit stack
32
+ // hence we have to allocate 16 (0x10) bytes even though we
33
+ // just need 12 (=TestStruct.sizeof)
34
+ // 401f20: 48 b8 ef be ad de 00 movabs rax,0xdeadbeef //rax = 0xdeadbeef
35
+ // 401f27: 00 00 00
36
+ // 401f2a: b9 64 00 00 00 mov ecx,0x64 //ecx = p2
37
+ // 401f2f: 48 89 ca mov rdx,rcx //rdx = rcx = ecx = p2
38
+ // 401f32: 48 89 c6 mov rsi,rax //rsi = rax = p1
39
+ // 401f35: 48 8d 7d f0 lea rdi,[rbp-0x10] //rdi = rbp-0x10 = retptr //BUG?
40
+ // 401f39: e8 ca fc ff ff call 401c08 <test@plt> //test(rdi = retptr, rsi = p1, rdx = p2 )
41
+
42
+ // Dont know why the ASM code changed from above to the following (maybe optimisation failed?)!
43
+ // 0000000000401f18 <_Dmain>:
44
+ // 401f18: 55 push rbp
45
+ // 401f19: 48 8b ec mov rbp,rsp
46
+ // 401f1c: 48 83 ec 20 sub rsp,0x20 //rsp -= 0x20 (=32)//reserve space for the locals and return value from test()
47
+ // 32 = TestStruct.sizeof(=12) + (void*).sizeof(=8) + uint.sizeof (=4)
48
+ // It appears that the return value is directly stored in the TestStruct local var
49
+ // hence TestStruct is not allocated twice
50
+ // 401f20: 48 b8 ef be ad de 00 movabs rax,0xdeadbeef //rax = 0xdeadbeef
51
+ // 401f27: 00 00 00
52
+ // 401f2a: 48 89 45 e0 mov QWORD PTR [rbp-0x20],rax //p1 = *(rbp-0x20) ~ rax ~ 0xdeadbeef
53
+ // 401f2e: b9 64 00 00 00 mov ecx,0x64 //ecx = 0x64
54
+ // 401f33: 89 4d e8 mov DWORD PTR [rbp-0x18],ecx //p2 = *(rbp-0x18) ~ ecx ~ 0x64
55
+ // 401f36: 48 89 ca mov rdx,rcx //rdx = rcx ~ ecx ~ p2
56
+ // 401f39: 48 89 c6 mov rsi,rax //rsi = rax ~ p1
57
+ // 401f3c: 48 8d 7d f0 lea rdi,[rbp-0x10] //rdi = *(rbp-0x10) ~ retptr?
58
+ // 401f40: e8 c3 fc ff ff call 401c08 <test@plt> //test(rdi = retptr, rsi = p1, rdx = p2)
59
+ // 401f45: ff 35 7d 3f 02 00 push QWORD PTR [rip+0x23f7d] # 425ec8 <_TMP0+0x8> //format string?
60
+ // 401f4b: ff 35 6f 3f 02 00 push QWORD PTR [rip+0x23f6f] # 425ec0 <_TMP0>
61
+ // 401f51: 48 8b 75 f0 mov rsi,QWORD PTR [rbp-0x10] //rsi = *retptr ~ ts.data
62
+ // 401f55: 8b 7d f8 mov edi,DWORD PTR [rbp-0x8] //edi = *(retptr-0x8) ~ ts.flags
63
+ // 401f58: e8 0b 00 00 00 call 401f68 <_D3std5stdio22__T8writeflnTAyaTPvTkZ8writeflnFAyaPvkZv>
64
+ // 401f5d: 48 83 c4 10 add rsp,0x10
65
+ // 401f61: 31 c0 xor eax,eax
66
+ // 401f63: c9 leave
67
+ // 401f64: c3 ret
68
+ void main ()
69
+ {
70
+ void * p1 = cast (void * )0xDEADBEEF ;
71
+ uint p2 = 100 ;// 0x64
72
+
73
+ TestStruct ts = test.test(p1, p2);
74
+
75
+ writefln(" ts.data=%s\n ts.flags=%s" , ts.data, ts.flags);
76
+ }
0 commit comments