1 //===-- X86AsmInstrumentation.cpp - Instrument X86 inline assembly C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "MCTargetDesc/X86BaseInfo.h" 11 #include "X86AsmInstrumentation.h" 12 #include "X86Operand.h" 13 #include "llvm/ADT/StringExtras.h" 14 #include "llvm/ADT/Triple.h" 15 #include "llvm/IR/Function.h" 16 #include "llvm/MC/MCContext.h" 17 #include "llvm/MC/MCInst.h" 18 #include "llvm/MC/MCInstBuilder.h" 19 #include "llvm/MC/MCInstrInfo.h" 20 #include "llvm/MC/MCParser/MCParsedAsmOperand.h" 21 #include "llvm/MC/MCStreamer.h" 22 #include "llvm/MC/MCSubtargetInfo.h" 23 #include "llvm/MC/MCTargetAsmParser.h" 24 #include "llvm/MC/MCTargetOptions.h" 25 #include "llvm/Support/CommandLine.h" 26 27 namespace llvm { 28 namespace { 29 30 static cl::opt<bool> ClAsanInstrumentAssembly( 31 "asan-instrument-assembly", 32 cl::desc("instrument assembly with AddressSanitizer checks"), cl::Hidden, 33 cl::init(false)); 34 35 bool IsStackReg(unsigned Reg) { 36 return Reg == X86::RSP || Reg == X86::ESP || Reg == X86::SP; 37 } 38 39 std::string FuncName(unsigned AccessSize, bool IsWrite) { 40 return std::string("__asan_report_") + (IsWrite ? "store" : "load") + 41 utostr(AccessSize); 42 } 43 44 class X86AddressSanitizer : public X86AsmInstrumentation { 45 public: 46 X86AddressSanitizer(const MCSubtargetInfo &STI) : STI(STI) {} 47 virtual ~X86AddressSanitizer() {} 48 49 // X86AsmInstrumentation implementation: 50 virtual void InstrumentInstruction( 51 const MCInst &Inst, OperandVector &Operands, MCContext &Ctx, 52 const MCInstrInfo &MII, MCStreamer &Out) override { 53 InstrumentMOV(Inst, Operands, Ctx, MII, Out); 54 } 55 56 // Should be implemented differently in x86_32 and x86_64 subclasses. 57 virtual void InstrumentMemOperandSmallImpl( 58 X86Operand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx, 59 MCStreamer &Out) = 0; 60 virtual void InstrumentMemOperandLargeImpl( 61 X86Operand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx, 62 MCStreamer &Out) = 0; 63 64 void InstrumentMemOperand(MCParsedAsmOperand &Op, unsigned AccessSize, 65 bool IsWrite, MCContext &Ctx, MCStreamer &Out); 66 void InstrumentMOV(const MCInst &Inst, OperandVector &Operands, 67 MCContext &Ctx, const MCInstrInfo &MII, MCStreamer &Out); 68 void EmitInstruction(MCStreamer &Out, const MCInst &Inst) { 69 Out.EmitInstruction(Inst, STI); 70 } 71 72 void EmitLabel(MCStreamer &Out, MCSymbol *Label) { Out.EmitLabel(Label); } 73 74 protected: 75 const MCSubtargetInfo &STI; 76 }; 77 78 void X86AddressSanitizer::InstrumentMemOperand( 79 MCParsedAsmOperand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx, 80 MCStreamer &Out) { 81 assert(Op.isMem() && "Op should be a memory operand."); 82 assert((AccessSize & (AccessSize - 1)) == 0 && AccessSize <= 16 && 83 "AccessSize should be a power of two, less or equal than 16."); 84 85 X86Operand &MemOp = static_cast<X86Operand &>(Op); 86 // FIXME: get rid of this limitation. 87 if (IsStackReg(MemOp.getMemBaseReg()) || IsStackReg(MemOp.getMemIndexReg())) 88 return; 89 90 // FIXME: take into account load/store alignment. 91 if (AccessSize < 8) 92 InstrumentMemOperandSmallImpl(MemOp, AccessSize, IsWrite, Ctx, Out); 93 else 94 InstrumentMemOperandLargeImpl(MemOp, AccessSize, IsWrite, Ctx, Out); 95 } 96 97 void X86AddressSanitizer::InstrumentMOV( 98 const MCInst &Inst, OperandVector &Operands, MCContext &Ctx, 99 const MCInstrInfo &MII, MCStreamer &Out) { 100 // Access size in bytes. 101 unsigned AccessSize = 0; 102 103 switch (Inst.getOpcode()) { 104 case X86::MOV8mi: 105 case X86::MOV8mr: 106 case X86::MOV8rm: 107 AccessSize = 1; 108 break; 109 case X86::MOV16mi: 110 case X86::MOV16mr: 111 case X86::MOV16rm: 112 AccessSize = 2; 113 break; 114 case X86::MOV32mi: 115 case X86::MOV32mr: 116 case X86::MOV32rm: 117 AccessSize = 4; 118 break; 119 case X86::MOV64mi32: 120 case X86::MOV64mr: 121 case X86::MOV64rm: 122 AccessSize = 8; 123 break; 124 case X86::MOVAPDmr: 125 case X86::MOVAPSmr: 126 case X86::MOVAPDrm: 127 case X86::MOVAPSrm: 128 AccessSize = 16; 129 break; 130 default: 131 return; 132 } 133 134 const bool IsWrite = MII.get(Inst.getOpcode()).mayStore(); 135 for (unsigned Ix = 0; Ix < Operands.size(); ++Ix) { 136 assert(Operands[Ix]); 137 MCParsedAsmOperand &Op = *Operands[Ix]; 138 if (Op.isMem()) 139 InstrumentMemOperand(Op, AccessSize, IsWrite, Ctx, Out); 140 } 141 } 142 143 class X86AddressSanitizer32 : public X86AddressSanitizer { 144 public: 145 static const long kShadowOffset = 0x20000000; 146 147 X86AddressSanitizer32(const MCSubtargetInfo &STI) 148 : X86AddressSanitizer(STI) {} 149 virtual ~X86AddressSanitizer32() {} 150 151 virtual void InstrumentMemOperandSmallImpl( 152 X86Operand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx, 153 MCStreamer &Out) override; 154 virtual void InstrumentMemOperandLargeImpl( 155 X86Operand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx, 156 MCStreamer &Out) override; 157 158 private: 159 void EmitCallAsanReport(MCContext &Ctx, MCStreamer &Out, unsigned AccessSize, 160 bool IsWrite, unsigned AddressReg) { 161 EmitInstruction(Out, MCInstBuilder(X86::CLD)); 162 EmitInstruction(Out, MCInstBuilder(X86::MMX_EMMS)); 163 164 EmitInstruction(Out, MCInstBuilder(X86::AND64ri8).addReg(X86::ESP) 165 .addReg(X86::ESP).addImm(-16)); 166 EmitInstruction(Out, MCInstBuilder(X86::PUSH32r).addReg(AddressReg)); 167 168 169 const std::string& Fn = FuncName(AccessSize, IsWrite); 170 MCSymbol *FnSym = Ctx.GetOrCreateSymbol(StringRef(Fn)); 171 const MCSymbolRefExpr *FnExpr = 172 MCSymbolRefExpr::Create(FnSym, MCSymbolRefExpr::VK_PLT, Ctx); 173 EmitInstruction(Out, MCInstBuilder(X86::CALLpcrel32).addExpr(FnExpr)); 174 } 175 }; 176 177 void X86AddressSanitizer32::InstrumentMemOperandSmallImpl( 178 X86Operand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx, 179 MCStreamer &Out) { 180 EmitInstruction(Out, MCInstBuilder(X86::PUSH32r).addReg(X86::EAX)); 181 EmitInstruction(Out, MCInstBuilder(X86::PUSH32r).addReg(X86::ECX)); 182 EmitInstruction(Out, MCInstBuilder(X86::PUSH32r).addReg(X86::EDX)); 183 EmitInstruction(Out, MCInstBuilder(X86::PUSHF32)); 184 185 { 186 MCInst Inst; 187 Inst.setOpcode(X86::LEA32r); 188 Inst.addOperand(MCOperand::CreateReg(X86::EAX)); 189 Op.addMemOperands(Inst, 5); 190 EmitInstruction(Out, Inst); 191 } 192 193 EmitInstruction( 194 Out, MCInstBuilder(X86::MOV32rr).addReg(X86::ECX).addReg(X86::EAX)); 195 EmitInstruction(Out, MCInstBuilder(X86::SHR32ri).addReg(X86::ECX) 196 .addReg(X86::ECX).addImm(3)); 197 198 { 199 MCInst Inst; 200 Inst.setOpcode(X86::MOV8rm); 201 Inst.addOperand(MCOperand::CreateReg(X86::CL)); 202 const MCExpr *Disp = MCConstantExpr::Create(kShadowOffset, Ctx); 203 std::unique_ptr<X86Operand> Op( 204 X86Operand::CreateMem(0, Disp, X86::ECX, 0, 1, SMLoc(), SMLoc())); 205 Op->addMemOperands(Inst, 5); 206 EmitInstruction(Out, Inst); 207 } 208 209 EmitInstruction(Out, 210 MCInstBuilder(X86::TEST8rr).addReg(X86::CL).addReg(X86::CL)); 211 MCSymbol *DoneSym = Ctx.CreateTempSymbol(); 212 const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx); 213 EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr)); 214 215 EmitInstruction( 216 Out, MCInstBuilder(X86::MOV32rr).addReg(X86::EDX).addReg(X86::EAX)); 217 EmitInstruction(Out, MCInstBuilder(X86::AND32ri).addReg(X86::EDX) 218 .addReg(X86::EDX).addImm(7)); 219 220 switch (AccessSize) { 221 case 1: 222 break; 223 case 2: { 224 MCInst Inst; 225 Inst.setOpcode(X86::LEA32r); 226 Inst.addOperand(MCOperand::CreateReg(X86::EDX)); 227 228 const MCExpr *Disp = MCConstantExpr::Create(1, Ctx); 229 std::unique_ptr<X86Operand> Op( 230 X86Operand::CreateMem(0, Disp, X86::EDX, 0, 1, SMLoc(), SMLoc())); 231 Op->addMemOperands(Inst, 5); 232 EmitInstruction(Out, Inst); 233 break; 234 } 235 case 4: 236 EmitInstruction(Out, MCInstBuilder(X86::ADD32ri8).addReg(X86::EDX) 237 .addReg(X86::EDX).addImm(3)); 238 break; 239 default: 240 assert(false && "Incorrect access size"); 241 break; 242 } 243 244 EmitInstruction( 245 Out, MCInstBuilder(X86::MOVSX32rr8).addReg(X86::ECX).addReg(X86::CL)); 246 EmitInstruction( 247 Out, MCInstBuilder(X86::CMP32rr).addReg(X86::EDX).addReg(X86::ECX)); 248 EmitInstruction(Out, MCInstBuilder(X86::JL_4).addExpr(DoneExpr)); 249 250 EmitCallAsanReport(Ctx, Out, AccessSize, IsWrite, X86::EAX); 251 EmitLabel(Out, DoneSym); 252 253 EmitInstruction(Out, MCInstBuilder(X86::POPF32)); 254 EmitInstruction(Out, MCInstBuilder(X86::POP32r).addReg(X86::EDX)); 255 EmitInstruction(Out, MCInstBuilder(X86::POP32r).addReg(X86::ECX)); 256 EmitInstruction(Out, MCInstBuilder(X86::POP32r).addReg(X86::EAX)); 257 } 258 259 void X86AddressSanitizer32::InstrumentMemOperandLargeImpl( 260 X86Operand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx, 261 MCStreamer &Out) { 262 EmitInstruction(Out, MCInstBuilder(X86::PUSH32r).addReg(X86::EAX)); 263 EmitInstruction(Out, MCInstBuilder(X86::PUSH32r).addReg(X86::ECX)); 264 EmitInstruction(Out, MCInstBuilder(X86::PUSHF32)); 265 266 { 267 MCInst Inst; 268 Inst.setOpcode(X86::LEA32r); 269 Inst.addOperand(MCOperand::CreateReg(X86::EAX)); 270 Op.addMemOperands(Inst, 5); 271 EmitInstruction(Out, Inst); 272 } 273 EmitInstruction( 274 Out, MCInstBuilder(X86::MOV32rr).addReg(X86::ECX).addReg(X86::EAX)); 275 EmitInstruction(Out, MCInstBuilder(X86::SHR32ri).addReg(X86::ECX) 276 .addReg(X86::ECX).addImm(3)); 277 { 278 MCInst Inst; 279 switch (AccessSize) { 280 case 8: 281 Inst.setOpcode(X86::CMP8mi); 282 break; 283 case 16: 284 Inst.setOpcode(X86::CMP16mi); 285 break; 286 default: 287 assert(false && "Incorrect access size"); 288 break; 289 } 290 const MCExpr *Disp = MCConstantExpr::Create(kShadowOffset, Ctx); 291 std::unique_ptr<X86Operand> Op( 292 X86Operand::CreateMem(0, Disp, X86::ECX, 0, 1, SMLoc(), SMLoc())); 293 Op->addMemOperands(Inst, 5); 294 Inst.addOperand(MCOperand::CreateImm(0)); 295 EmitInstruction(Out, Inst); 296 } 297 MCSymbol *DoneSym = Ctx.CreateTempSymbol(); 298 const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx); 299 EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr)); 300 301 EmitCallAsanReport(Ctx, Out, AccessSize, IsWrite, X86::EAX); 302 EmitLabel(Out, DoneSym); 303 304 EmitInstruction(Out, MCInstBuilder(X86::POPF32)); 305 EmitInstruction(Out, MCInstBuilder(X86::POP32r).addReg(X86::ECX)); 306 EmitInstruction(Out, MCInstBuilder(X86::POP32r).addReg(X86::EAX)); 307 } 308 309 class X86AddressSanitizer64 : public X86AddressSanitizer { 310 public: 311 static const long kShadowOffset = 0x7fff8000; 312 313 X86AddressSanitizer64(const MCSubtargetInfo &STI) 314 : X86AddressSanitizer(STI) {} 315 virtual ~X86AddressSanitizer64() {} 316 317 virtual void InstrumentMemOperandSmallImpl( 318 X86Operand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx, 319 MCStreamer &Out) override; 320 virtual void InstrumentMemOperandLargeImpl( 321 X86Operand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx, 322 MCStreamer &Out) override; 323 324 private: 325 void EmitAdjustRSP(MCContext &Ctx, MCStreamer &Out, long Offset) { 326 MCInst Inst; 327 Inst.setOpcode(X86::LEA64r); 328 Inst.addOperand(MCOperand::CreateReg(X86::RSP)); 329 330 const MCExpr *Disp = MCConstantExpr::Create(Offset, Ctx); 331 std::unique_ptr<X86Operand> Op( 332 X86Operand::CreateMem(0, Disp, X86::RSP, 0, 1, SMLoc(), SMLoc())); 333 Op->addMemOperands(Inst, 5); 334 EmitInstruction(Out, Inst); 335 } 336 337 void EmitCallAsanReport(MCContext &Ctx, MCStreamer &Out, unsigned AccessSize, 338 bool IsWrite) { 339 EmitInstruction(Out, MCInstBuilder(X86::CLD)); 340 EmitInstruction(Out, MCInstBuilder(X86::MMX_EMMS)); 341 342 EmitInstruction(Out, MCInstBuilder(X86::AND64ri8).addReg(X86::RSP) 343 .addReg(X86::RSP).addImm(-16)); 344 345 const std::string& Fn = FuncName(AccessSize, IsWrite); 346 MCSymbol *FnSym = Ctx.GetOrCreateSymbol(StringRef(Fn)); 347 const MCSymbolRefExpr *FnExpr = 348 MCSymbolRefExpr::Create(FnSym, MCSymbolRefExpr::VK_PLT, Ctx); 349 EmitInstruction(Out, MCInstBuilder(X86::CALL64pcrel32).addExpr(FnExpr)); 350 } 351 }; 352 353 void X86AddressSanitizer64::InstrumentMemOperandSmallImpl( 354 X86Operand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx, 355 MCStreamer &Out) { 356 EmitAdjustRSP(Ctx, Out, -128); 357 EmitInstruction(Out, MCInstBuilder(X86::PUSH64r).addReg(X86::RAX)); 358 EmitInstruction(Out, MCInstBuilder(X86::PUSH64r).addReg(X86::RCX)); 359 EmitInstruction(Out, MCInstBuilder(X86::PUSH64r).addReg(X86::RDI)); 360 EmitInstruction(Out, MCInstBuilder(X86::PUSHF64)); 361 { 362 MCInst Inst; 363 Inst.setOpcode(X86::LEA64r); 364 Inst.addOperand(MCOperand::CreateReg(X86::RDI)); 365 Op.addMemOperands(Inst, 5); 366 EmitInstruction(Out, Inst); 367 } 368 EmitInstruction( 369 Out, MCInstBuilder(X86::MOV64rr).addReg(X86::RAX).addReg(X86::RDI)); 370 EmitInstruction(Out, MCInstBuilder(X86::SHR64ri).addReg(X86::RAX) 371 .addReg(X86::RAX).addImm(3)); 372 { 373 MCInst Inst; 374 Inst.setOpcode(X86::MOV8rm); 375 Inst.addOperand(MCOperand::CreateReg(X86::AL)); 376 const MCExpr *Disp = MCConstantExpr::Create(kShadowOffset, Ctx); 377 std::unique_ptr<X86Operand> Op( 378 X86Operand::CreateMem(0, Disp, X86::RAX, 0, 1, SMLoc(), SMLoc())); 379 Op->addMemOperands(Inst, 5); 380 EmitInstruction(Out, Inst); 381 } 382 383 EmitInstruction(Out, 384 MCInstBuilder(X86::TEST8rr).addReg(X86::AL).addReg(X86::AL)); 385 MCSymbol *DoneSym = Ctx.CreateTempSymbol(); 386 const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx); 387 EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr)); 388 389 EmitInstruction( 390 Out, MCInstBuilder(X86::MOV32rr).addReg(X86::ECX).addReg(X86::EDI)); 391 EmitInstruction(Out, MCInstBuilder(X86::AND32ri).addReg(X86::ECX) 392 .addReg(X86::ECX).addImm(7)); 393 394 switch (AccessSize) { 395 case 1: 396 break; 397 case 2: { 398 MCInst Inst; 399 Inst.setOpcode(X86::LEA32r); 400 Inst.addOperand(MCOperand::CreateReg(X86::ECX)); 401 402 const MCExpr *Disp = MCConstantExpr::Create(1, Ctx); 403 std::unique_ptr<X86Operand> Op( 404 X86Operand::CreateMem(0, Disp, X86::ECX, 0, 1, SMLoc(), SMLoc())); 405 Op->addMemOperands(Inst, 5); 406 EmitInstruction(Out, Inst); 407 break; 408 } 409 case 4: 410 EmitInstruction(Out, MCInstBuilder(X86::ADD32ri8).addReg(X86::ECX) 411 .addReg(X86::ECX).addImm(3)); 412 break; 413 default: 414 assert(false && "Incorrect access size"); 415 break; 416 } 417 418 EmitInstruction( 419 Out, MCInstBuilder(X86::MOVSX32rr8).addReg(X86::EAX).addReg(X86::AL)); 420 EmitInstruction( 421 Out, MCInstBuilder(X86::CMP32rr).addReg(X86::ECX).addReg(X86::EAX)); 422 EmitInstruction(Out, MCInstBuilder(X86::JL_4).addExpr(DoneExpr)); 423 424 EmitCallAsanReport(Ctx, Out, AccessSize, IsWrite); 425 EmitLabel(Out, DoneSym); 426 427 EmitInstruction(Out, MCInstBuilder(X86::POPF64)); 428 EmitInstruction(Out, MCInstBuilder(X86::POP64r).addReg(X86::RDI)); 429 EmitInstruction(Out, MCInstBuilder(X86::POP64r).addReg(X86::RCX)); 430 EmitInstruction(Out, MCInstBuilder(X86::POP64r).addReg(X86::RAX)); 431 EmitAdjustRSP(Ctx, Out, 128); 432 } 433 434 void X86AddressSanitizer64::InstrumentMemOperandLargeImpl( 435 X86Operand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx, 436 MCStreamer &Out) { 437 EmitAdjustRSP(Ctx, Out, -128); 438 EmitInstruction(Out, MCInstBuilder(X86::PUSH64r).addReg(X86::RAX)); 439 EmitInstruction(Out, MCInstBuilder(X86::PUSHF64)); 440 441 { 442 MCInst Inst; 443 Inst.setOpcode(X86::LEA64r); 444 Inst.addOperand(MCOperand::CreateReg(X86::RAX)); 445 Op.addMemOperands(Inst, 5); 446 EmitInstruction(Out, Inst); 447 } 448 EmitInstruction(Out, MCInstBuilder(X86::SHR64ri).addReg(X86::RAX) 449 .addReg(X86::RAX).addImm(3)); 450 { 451 MCInst Inst; 452 switch (AccessSize) { 453 case 8: 454 Inst.setOpcode(X86::CMP8mi); 455 break; 456 case 16: 457 Inst.setOpcode(X86::CMP16mi); 458 break; 459 default: 460 assert(false && "Incorrect access size"); 461 break; 462 } 463 const MCExpr *Disp = MCConstantExpr::Create(kShadowOffset, Ctx); 464 std::unique_ptr<X86Operand> Op( 465 X86Operand::CreateMem(0, Disp, X86::RAX, 0, 1, SMLoc(), SMLoc())); 466 Op->addMemOperands(Inst, 5); 467 Inst.addOperand(MCOperand::CreateImm(0)); 468 EmitInstruction(Out, Inst); 469 } 470 471 MCSymbol *DoneSym = Ctx.CreateTempSymbol(); 472 const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx); 473 EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr)); 474 475 EmitCallAsanReport(Ctx, Out, AccessSize, IsWrite); 476 EmitLabel(Out, DoneSym); 477 478 EmitInstruction(Out, MCInstBuilder(X86::POPF64)); 479 EmitInstruction(Out, MCInstBuilder(X86::POP64r).addReg(X86::RAX)); 480 EmitAdjustRSP(Ctx, Out, 128); 481 } 482 483 } // End anonymous namespace 484 485 X86AsmInstrumentation::X86AsmInstrumentation() {} 486 X86AsmInstrumentation::~X86AsmInstrumentation() {} 487 488 void X86AsmInstrumentation::InstrumentInstruction( 489 const MCInst &Inst, OperandVector &Operands, MCContext &Ctx, 490 const MCInstrInfo &MII, MCStreamer &Out) {} 491 492 X86AsmInstrumentation * 493 CreateX86AsmInstrumentation(const MCTargetOptions &MCOptions, 494 const MCContext &Ctx, const MCSubtargetInfo &STI) { 495 Triple T(STI.getTargetTriple()); 496 const bool hasCompilerRTSupport = T.isOSLinux(); 497 if (ClAsanInstrumentAssembly && hasCompilerRTSupport && 498 MCOptions.SanitizeAddress) { 499 if ((STI.getFeatureBits() & X86::Mode32Bit) != 0) 500 return new X86AddressSanitizer32(STI); 501 if ((STI.getFeatureBits() & X86::Mode64Bit) != 0) 502 return new X86AddressSanitizer64(STI); 503 } 504 return new X86AsmInstrumentation(); 505 } 506 507 } // End llvm namespace 508