this repo has no description
at trunk 319 lines 11 kB view raw
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