this repo has no description
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com)
2#include "assembler-x64.h"
3
4#include "gtest/gtest.h"
5
6#include "memory-region.h"
7
8namespace py {
9namespace x64 {
10namespace testing {
11
12template <size_t N>
13::testing::AssertionResult assemblerContainsBytes(Assembler* a,
14 const byte (&expected)[N]) {
15 if (a->codeSize() != N) {
16 return ::testing::AssertionFailure() << "Code size of " << a->codeSize()
17 << " doesn't match expected " << N;
18 }
19
20 byte buf[N];
21 a->finalizeInstructions(MemoryRegion(buf, N));
22 for (size_t i = 0; i < sizeof(expected); ++i) {
23 if (buf[i] != expected[i]) {
24 // AssertionFailure()'s streaming doesn't support std::hex.
25 std::ostringstream msg;
26 msg << "Mismatch at index " << i << ": expected 0x" << std::hex
27 << int{expected[i]} << ", got 0x" << int{buf[i]} << std::dec;
28 return ::testing::AssertionFailure() << msg.str();
29 }
30 }
31
32 return ::testing::AssertionSuccess();
33}
34
35TEST(AssemblerTest, Empty) {
36 byte buf[] = {0x12, 0x34, 0x56, 0x78};
37 Assembler as;
38 EXPECT_EQ(as.codeSize(), 0);
39 as.finalizeInstructions(MemoryRegion(buf, sizeof(buf)));
40
41 // Make sure the buffer wasn't changed.
42 EXPECT_EQ(buf[0], 0x12);
43 EXPECT_EQ(buf[1], 0x34);
44 EXPECT_EQ(buf[2], 0x56);
45 EXPECT_EQ(buf[3], 0x78);
46}
47
48TEST(AssemblerTest, emit) {
49 const byte expected[] = {0x90};
50 Assembler as;
51 as.nop();
52 EXPECT_TRUE(assemblerContainsBytes(&as, expected));
53}
54
55TEST(AssemblerTest, Labels) {
56 const byte expected[] = {0x90, 0xeb, 0xfd};
57 Assembler as;
58 Label loop;
59 as.bind(&loop);
60 as.nop();
61 as.jmp(&loop, Assembler::kNearJump);
62 EXPECT_TRUE(assemblerContainsBytes(&as, expected));
63}
64
65TEST(AssemblerTest, Align) {
66 const byte expected[] = {0xcc, 0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00};
67 Assembler as;
68 as.int3();
69 as.align(8);
70 EXPECT_TRUE(assemblerContainsBytes(&as, expected));
71}
72
73TEST(AssemblerTest, Cmpb) {
74 // 3c 12 cmpb $18, %al
75 // 80 fb 34 cmpb $52, %bl
76 // 40 80 ff 56 cmpb $86, %dil
77 // 41 80 fa 78 cmpb $120, %r10b
78 const byte expected[] = {0x3c, 0x12, 0x80, 0xfb, 0x34, 0x40, 0x80,
79 0xff, 0x56, 0x41, 0x80, 0xfa, 0x78};
80 Assembler as;
81 as.cmpb(RAX, Immediate(0x12));
82 as.cmpb(RBX, Immediate(0x34));
83 as.cmpb(RDI, Immediate(0x56));
84 as.cmpb(R10, Immediate(0x78));
85 EXPECT_TRUE(assemblerContainsBytes(&as, expected));
86}
87
88TEST(AssemblerTest, MovbRexPrefix) {
89 // 40 8a 7a 12 movb 18(%rdx), %dil
90 // 41 8a 74 24 34 movb 52(%r12), %sil
91 // 40 88 6f 56 movb %bpl, 86(%rdi)
92 // 44 88 7e 78 movb %r15b, 120(%rsi)
93 const byte expected[] = {0x40, 0x8a, 0x7a, 0x12, 0x41, 0x8a, 0x74, 0x24, 0x34,
94 0x40, 0x88, 0x6f, 0x56, 0x44, 0x88, 0x7e, 0x78};
95 Assembler as;
96 as.movb(RDI, Address(RDX, 0x12));
97 as.movb(RSI, Address(R12, 0x34));
98 as.movb(Address(RDI, 0x56), RBP);
99 as.movb(Address(RSI, 0x78), R15);
100 EXPECT_TRUE(assemblerContainsBytes(&as, expected));
101}
102
103TEST(AssemblerTest, MovqAddressImmediate) {
104 const byte expected[] = {
105 0x48, 0xc7, 0x04, 0x24, 0x00, 0x00, 0x00, 0x00, // movq $0x0, (%rsp)
106 0x48, 0xc7, 0x45, 0x00, 0xff, 0xff, 0xff, 0xff, // movq $-1, (%rbp)
107 0x48, 0xc7, 0x01, 0x00, 0x00, 0x00, 0x80, // movq $-2147483648, (%rcx)
108 0x48, 0xc7, 0x44, 0xb2, 0x0d, 0x07, 0x00, 0x00,
109 0x00, // movq $0x7, 13(%rdx,%rsi,4)
110 0x48, 0xc7, 0x44, 0xf2, 0x9d, 0xff, 0xff, 0xff,
111 0x7f, // movq $0x7fffffff, -99(%rdx,%rsi,8)
112 };
113
114 Assembler as;
115 as.movq(Address(RSP, 0), Immediate(0));
116 as.movq(Address(RBP, 0), Immediate(-1));
117 as.movq(Address(RCX, 0), Immediate(kMinInt32));
118 as.movq(Address(RDX, RSI, TIMES_4, 13), Immediate(7));
119 as.movq(Address(RDX, RSI, TIMES_8, -99), Immediate(0x7fffffff));
120 EXPECT_TRUE(assemblerContainsBytes(&as, expected));
121}
122
123TEST(AssemblerTest, MovlAddressImmediate) {
124 const byte expected[] = {
125 0xc7, 0x04, 0x24, 0x00, 0x00, 0x00, 0x00, // movl $0, (%rsp)
126 0xc7, 0x45, 0x00, 0xff, 0xff, 0xff, 0xff, // movl $4294967295, (%rbp)
127 0xc7, 0x01, 0x00, 0x00, 0x00, 0x80, // movl $2147483648, (%rcx)
128 0xc7, 0x44, 0xb2, 0x0d, 0x07, 0x00, 0x00,
129 0x00, // movl $7, 13(%rdx,%rsi,4)
130 0xc7, 0x44, 0xf2, 0x9d, 0xff, 0xff, 0xff,
131 0x7f, // movl $2147483647, -99(%rdx,%rsi,8)
132 };
133
134 Assembler as;
135 as.movl(Address(RSP, 0), Immediate(0));
136 as.movl(Address(RBP, 0), Immediate(-1));
137 as.movl(Address(RCX, 0), Immediate(kMinInt32));
138 as.movl(Address(RDX, RSI, TIMES_4, 13), Immediate(7));
139 as.movl(Address(RDX, RSI, TIMES_8, -99), Immediate(0x7fffffff));
140 EXPECT_TRUE(assemblerContainsBytes(&as, expected));
141}
142
143TEST(AssemblerTest, MovsX) {
144 const byte expected[] = {
145 0xa4, // movsb
146 0x66, 0xa5, // movsw
147 0xa5, // movsl
148 0x48, 0xa5, // movsq
149 0xf3, 0xa4, // rep movsb
150 0xf3, 0x66, 0xa5, // rep movsw
151 0xf3, 0xa5, // rep movsl
152 0xf3, 0x48, 0xa5, // rep movsq
153 0xf2, 0xa4, // repnz movsb
154 0xf2, 0x66, 0xa5, // repnz movsw
155 0xf2, 0xa5, // repnz movsl
156 0xf2, 0x48, 0xa5, // repnz movsq
157 };
158
159 Assembler as;
160 as.movsb();
161 as.movsw();
162 as.movsl();
163 as.movsq();
164 as.repMovsb();
165 as.repMovsw();
166 as.repMovsl();
167 as.repMovsq();
168 as.repnzMovsb();
169 as.repnzMovsw();
170 as.repnzMovsl();
171 as.repnzMovsq();
172 EXPECT_TRUE(assemblerContainsBytes(&as, expected));
173}
174
175TEST(AssemblerTest, TestbWithRexPrefix) {
176 // 40 84 3e testb %dil, (%rsi)
177 // 41 84 2c 1a testb %bpl, (%r10,%rbx)
178 const byte expected[] = {0x40, 0x84, 0x3e, 0x41, 0x84, 0x2c, 0x1a};
179
180 Assembler as;
181 as.testb(Address(RSI, 0), RDI);
182 as.testb(Address(R10, RBX, TIMES_1, 0), RBP);
183 EXPECT_TRUE(assemblerContainsBytes(&as, expected));
184}
185
186TEST(AssemblerTest, TestbRegReg) {
187 const byte expected[] = {
188 0x84, 0xc0, // testb %al, %al
189 0x84, 0xca, // testb %cl, %dl
190 0x40, 0x84, 0xe5, // testb %spl, %bpl
191 0x40, 0x84, 0xf7, // testb %sil, %dil
192 0x45, 0x84, 0xff, // testb %r15b, %r15b
193 0x44, 0x84, 0xf8, // testb %r15b, %al
194 0x41, 0x84, 0xcb, // testb %cl, %r11b
195 };
196
197 Assembler as;
198 as.testb(RAX, RAX);
199 as.testb(RCX, RDX);
200 as.testb(RSP, RBP);
201 as.testb(RSI, RDI);
202 as.testb(R15, R15);
203 as.testb(R15, RAX);
204 as.testb(RCX, R11);
205 EXPECT_TRUE(assemblerContainsBytes(&as, expected));
206}
207
208TEST(AssemblerTest, TestqWithByteImm) {
209 // a8 12 test $0x12,%al
210 // f6 c3 34 test $0x34,%bl
211 // 40 f6 c6 56 test $0x56,%sil
212 // 41 f6 c2 78 test $0x78,%r10b
213 // f6 00 90 testb $0x90,(%rax)
214 // 41 f6 02 12 testb $0x12,(%r10)
215 const byte expected[] = {0xa8, 0x12, 0xf6, 0xc3, 0x34, 0x40, 0xf6,
216 0xc6, 0x56, 0x41, 0xf6, 0xc2, 0x78, 0xf6,
217 0x00, 0x90, 0x41, 0xf6, 0x02, 0x12};
218
219 Assembler as;
220 as.testq(RAX, Immediate(0x12));
221 as.testq(RBX, Immediate(0x34));
222 as.testq(RSI, Immediate(0x56));
223 as.testq(R10, Immediate(0x78));
224 as.testq(Address(RAX, 0), Immediate(0x90));
225 as.testq(Address(R10, 0), Immediate(0x12));
226 EXPECT_TRUE(assemblerContainsBytes(&as, expected));
227}
228
229TEST(AssemblerTest, TestqWithUnsignedLongImm) {
230 // a9 34 12 00 00 test $0x1234,%eax
231 // f7 c3 78 56 00 00 test $0x5678,%ebx
232 // 41 f7 c0 12 90 00 00 test $0x9012,%r10d
233 // f7 00 56 34 00 00 testl $0x3456,(%rax)
234 // 41 f7 00 00 00 00 40 testl $0x40000000,(%r10)
235 const byte expected[] = {0xa9, 0x34, 0x12, 0x00, 0x00, 0xf7, 0xc3, 0x78,
236 0x56, 0x00, 0x00, 0x41, 0xf7, 0xc2, 0x12, 0x90,
237 0x00, 0x00, 0xf7, 0x00, 0x56, 0x34, 0x00, 0x00,
238 0x41, 0xf7, 0x02, 0x00, 0x00, 0x00, 0x40};
239
240 Assembler as;
241 as.testq(RAX, Immediate(0x1234));
242 as.testq(RBX, Immediate(0x5678));
243 as.testq(R10, Immediate(0x9012));
244 as.testq(Address(RAX, 0), Immediate(0x3456));
245 as.testq(Address(R10, 0), Immediate(0x40000000));
246 EXPECT_TRUE(assemblerContainsBytes(&as, expected));
247}
248
249TEST(AssemblerTest, TestqWithSignedLongImm) {
250 // 48 a9 ff ff ff ff test $0xffffffffffffffff,%rax
251 // 48 f7 c3 fe ff ff ff test $0xfffffffffffffffe,%rbx
252 // 49 f7 c2 fd ff ff ff test $0xfffffffffffffffd,%r10
253 // 48 f7 00 fc ff ff ff testq $0xfffffffffffffffc,(%rax)
254 // 49 f7 02 fb ff ff ff testq $0xfffffffffffffffb,(%r10)
255 const byte expected[] = {0x48, 0xa9, 0xff, 0xff, 0xff, 0xff, 0x48, 0xf7, 0xc3,
256 0xfe, 0xff, 0xff, 0xff, 0x49, 0xf7, 0xc2, 0xfd, 0xff,
257 0xff, 0xff, 0x48, 0xf7, 0x00, 0xfc, 0xff, 0xff, 0xff,
258 0x49, 0xf7, 0x02, 0xfb, 0xff, 0xff, 0xff};
259
260 Assembler as;
261 as.testq(RAX, Immediate(-1));
262 as.testq(RBX, Immediate(-2));
263 as.testq(R10, Immediate(-3));
264 as.testq(Address(RAX, 0), Immediate(-4));
265 as.testq(Address(R10, 0), Immediate(-5));
266 EXPECT_TRUE(assemblerContainsBytes(&as, expected));
267}
268
269TEST(AssemblerTest, RIPRelativeLea) {
270 // 48 8d 05 03 00 00 00 leaq $0x3(%rip),%rax
271 // 48 33 d2 xorq %rdx, %rdx
272 // 48 33 d2 xorq %rdx, %rdx
273 const byte expected[] = {0x48, 0x8d, 0x05, 0x03, 0x00, 0x00, 0x00,
274 0x48, 0x33, 0xd2, 0x48, 0x33, 0xd2};
275
276 Assembler as;
277 Label label;
278 as.leaq(RAX, &label);
279 as.xorq(RDX, RDX);
280 as.bind(&label);
281 as.xorq(RDX, RDX);
282 EXPECT_TRUE(assemblerContainsBytes(&as, expected));
283}
284
285TEST(AssemblerTest, RIPRelativeLeaWithNonRax) {
286 // 48 8d 0d 03 00 00 00 leaq $0x3(%rip),%rcx
287 // 48 33 d2 xorq %rdx, %rdx
288 // 48 33 d2 xorq %rdx, %rdx
289 const byte expected[] = {0x48, 0x8d, 0x0d, 0x03, 0x00, 0x00, 0x00,
290 0x48, 0x33, 0xd2, 0x48, 0x33, 0xd2};
291
292 Assembler as;
293 Label label;
294 as.leaq(RCX, &label);
295 as.xorq(RDX, RDX);
296 as.bind(&label);
297 as.xorq(RDX, RDX);
298 EXPECT_TRUE(assemblerContainsBytes(&as, expected));
299}
300
301TEST(AssemblerTest, RIPRelativeLeaWithSixtyFourBitRegister) {
302 // 4c 8d 35 03 00 00 00 leaq $0x3(%rip),%r14
303 // 48 33 d2 xorq %rdx, %rdx
304 // 48 33 d2 xorq %rdx, %rdx
305 const byte expected[] = {0x4c, 0x8d, 0x35, 0x03, 0x00, 0x00, 0x00,
306 0x48, 0x33, 0xd2, 0x48, 0x33, 0xd2};
307
308 Assembler as;
309 Label label;
310 as.leaq(R14, &label);
311 as.xorq(RDX, RDX);
312 as.bind(&label);
313 as.xorq(RDX, RDX);
314 EXPECT_TRUE(assemblerContainsBytes(&as, expected));
315}
316
317} // namespace testing
318} // namespace x64
319} // namespace py