1 //===-- X86AsmInstrumentation.cpp - Instrument X86 inline assembly C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "MCTargetDesc/X86BaseInfo.h"
11 #include "X86AsmInstrumentation.h"
12 #include "X86Operand.h"
13 #include "X86RegisterInfo.h"
14 #include "llvm/ADT/StringExtras.h"
15 #include "llvm/ADT/Triple.h"
16 #include "llvm/CodeGen/MachineValueType.h"
17 #include "llvm/IR/Function.h"
18 #include "llvm/MC/MCContext.h"
19 #include "llvm/MC/MCInst.h"
20 #include "llvm/MC/MCInstBuilder.h"
21 #include "llvm/MC/MCInstrInfo.h"
22 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
23 #include "llvm/MC/MCStreamer.h"
24 #include "llvm/MC/MCSubtargetInfo.h"
25 #include "llvm/MC/MCTargetAsmParser.h"
26 #include "llvm/MC/MCTargetOptions.h"
27 #include "llvm/Support/CommandLine.h"
32 static cl::opt<bool> ClAsanInstrumentAssembly(
33 "asan-instrument-assembly",
34 cl::desc("instrument assembly with AddressSanitizer checks"), cl::Hidden,
37 bool IsStackReg(unsigned Reg) {
38 return Reg == X86::RSP || Reg == X86::ESP || Reg == X86::SP;
41 bool IsSmallMemAccess(unsigned AccessSize) { return AccessSize < 8; }
43 std::string FuncName(unsigned AccessSize, bool IsWrite) {
44 return std::string("__asan_report_") + (IsWrite ? "store" : "load") +
48 class X86AddressSanitizer : public X86AsmInstrumentation {
50 struct RegisterContext {
51 RegisterContext(unsigned AddressReg, unsigned ShadowReg,
53 : AddressReg(AddressReg), ShadowReg(ShadowReg), ScratchReg(ScratchReg) {
56 unsigned addressReg(MVT::SimpleValueType VT) const {
57 return getX86SubSuperRegister(AddressReg, VT);
60 unsigned shadowReg(MVT::SimpleValueType VT) const {
61 return getX86SubSuperRegister(ShadowReg, VT);
64 unsigned scratchReg(MVT::SimpleValueType VT) const {
65 return getX86SubSuperRegister(ScratchReg, VT);
68 const unsigned AddressReg;
69 const unsigned ShadowReg;
70 const unsigned ScratchReg;
73 X86AddressSanitizer(const MCSubtargetInfo &STI)
74 : X86AsmInstrumentation(STI), RepPrefix(false) {}
75 virtual ~X86AddressSanitizer() {}
77 // X86AsmInstrumentation implementation:
78 virtual void InstrumentAndEmitInstruction(const MCInst &Inst,
79 OperandVector &Operands,
81 const MCInstrInfo &MII,
82 MCStreamer &Out) override {
83 InstrumentMOVS(Inst, Operands, Ctx, MII, Out);
85 EmitInstruction(Out, MCInstBuilder(X86::REP_PREFIX));
87 InstrumentMOV(Inst, Operands, Ctx, MII, Out);
89 RepPrefix = (Inst.getOpcode() == X86::REP_PREFIX);
91 EmitInstruction(Out, Inst);
94 // Should be implemented differently in x86_32 and x86_64 subclasses.
95 virtual void StoreFlags(MCStreamer &Out) = 0;
97 virtual void RestoreFlags(MCStreamer &Out) = 0;
99 // Adjusts up stack and saves all registers used in instrumentation.
100 virtual void InstrumentMemOperandPrologue(const RegisterContext &RegCtx,
102 MCStreamer &Out) = 0;
104 // Restores all registers used in instrumentation and adjusts stack.
105 virtual void InstrumentMemOperandEpilogue(const RegisterContext &RegCtx,
107 MCStreamer &Out) = 0;
109 virtual void InstrumentMemOperandSmall(X86Operand &Op, unsigned AccessSize,
111 const RegisterContext &RegCtx,
112 MCContext &Ctx, MCStreamer &Out) = 0;
113 virtual void InstrumentMemOperandLarge(X86Operand &Op, unsigned AccessSize,
115 const RegisterContext &RegCtx,
116 MCContext &Ctx, MCStreamer &Out) = 0;
118 virtual void InstrumentMOVSImpl(unsigned AccessSize, MCContext &Ctx,
119 MCStreamer &Out) = 0;
121 void InstrumentMemOperand(X86Operand &Op, unsigned AccessSize, bool IsWrite,
122 const RegisterContext &RegCtx, MCContext &Ctx,
124 void InstrumentMOVSBase(unsigned DstReg, unsigned SrcReg, unsigned CntReg,
125 unsigned AccessSize, MCContext &Ctx, MCStreamer &Out);
127 void InstrumentMOVS(const MCInst &Inst, OperandVector &Operands,
128 MCContext &Ctx, const MCInstrInfo &MII, MCStreamer &Out);
129 void InstrumentMOV(const MCInst &Inst, OperandVector &Operands,
130 MCContext &Ctx, const MCInstrInfo &MII, MCStreamer &Out);
133 void EmitLabel(MCStreamer &Out, MCSymbol *Label) { Out.EmitLabel(Label); }
135 // True when previous instruction was actually REP prefix.
139 void X86AddressSanitizer::InstrumentMemOperand(
140 X86Operand &Op, unsigned AccessSize, bool IsWrite,
141 const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) {
142 assert(Op.isMem() && "Op should be a memory operand.");
143 assert((AccessSize & (AccessSize - 1)) == 0 && AccessSize <= 16 &&
144 "AccessSize should be a power of two, less or equal than 16.");
145 // FIXME: take into account load/store alignment.
146 if (IsSmallMemAccess(AccessSize))
147 InstrumentMemOperandSmall(Op, AccessSize, IsWrite, RegCtx, Ctx, Out);
149 InstrumentMemOperandLarge(Op, AccessSize, IsWrite, RegCtx, Ctx, Out);
152 void X86AddressSanitizer::InstrumentMOVSBase(unsigned DstReg, unsigned SrcReg,
155 MCContext &Ctx, MCStreamer &Out) {
156 // FIXME: check whole ranges [DstReg .. DstReg + AccessSize * (CntReg - 1)]
157 // and [SrcReg .. SrcReg + AccessSize * (CntReg - 1)].
158 RegisterContext RegCtx(X86::RDX /* AddressReg */, X86::RAX /* ShadowReg */,
159 IsSmallMemAccess(AccessSize)
161 : X86::NoRegister /* ScratchReg */);
163 InstrumentMemOperandPrologue(RegCtx, Ctx, Out);
167 const MCExpr *Disp = MCConstantExpr::Create(0, Ctx);
168 std::unique_ptr<X86Operand> Op(X86Operand::CreateMem(
169 0, Disp, SrcReg, 0, AccessSize, SMLoc(), SMLoc()));
170 InstrumentMemOperand(*Op, AccessSize, false /* IsWrite */, RegCtx, Ctx,
174 // Test -1(%SrcReg, %CntReg, AccessSize)
176 const MCExpr *Disp = MCConstantExpr::Create(-1, Ctx);
177 std::unique_ptr<X86Operand> Op(X86Operand::CreateMem(
178 0, Disp, SrcReg, CntReg, AccessSize, SMLoc(), SMLoc()));
179 InstrumentMemOperand(*Op, AccessSize, false /* IsWrite */, RegCtx, Ctx,
185 const MCExpr *Disp = MCConstantExpr::Create(0, Ctx);
186 std::unique_ptr<X86Operand> Op(X86Operand::CreateMem(
187 0, Disp, DstReg, 0, AccessSize, SMLoc(), SMLoc()));
188 InstrumentMemOperand(*Op, AccessSize, true /* IsWrite */, RegCtx, Ctx, Out);
191 // Test -1(%DstReg, %CntReg, AccessSize)
193 const MCExpr *Disp = MCConstantExpr::Create(-1, Ctx);
194 std::unique_ptr<X86Operand> Op(X86Operand::CreateMem(
195 0, Disp, DstReg, CntReg, AccessSize, SMLoc(), SMLoc()));
196 InstrumentMemOperand(*Op, AccessSize, true /* IsWrite */, RegCtx, Ctx, Out);
199 InstrumentMemOperandEpilogue(RegCtx, Ctx, Out);
202 void X86AddressSanitizer::InstrumentMOVS(const MCInst &Inst,
203 OperandVector &Operands,
204 MCContext &Ctx, const MCInstrInfo &MII,
206 // Access size in bytes.
207 unsigned AccessSize = 0;
209 switch (Inst.getOpcode()) {
226 InstrumentMOVSImpl(AccessSize, Ctx, Out);
229 void X86AddressSanitizer::InstrumentMOV(const MCInst &Inst,
230 OperandVector &Operands, MCContext &Ctx,
231 const MCInstrInfo &MII,
233 // Access size in bytes.
234 unsigned AccessSize = 0;
236 switch (Inst.getOpcode()) {
267 const bool IsWrite = MII.get(Inst.getOpcode()).mayStore();
268 RegisterContext RegCtx(X86::RDI /* AddressReg */, X86::RAX /* ShadowReg */,
269 IsSmallMemAccess(AccessSize)
271 : X86::NoRegister /* ScratchReg */);
273 for (unsigned Ix = 0; Ix < Operands.size(); ++Ix) {
274 assert(Operands[Ix]);
275 MCParsedAsmOperand &Op = *Operands[Ix];
277 X86Operand &MemOp = static_cast<X86Operand &>(Op);
278 // FIXME: get rid of this limitation.
279 if (IsStackReg(MemOp.getMemBaseReg()) ||
280 IsStackReg(MemOp.getMemIndexReg())) {
284 InstrumentMemOperandPrologue(RegCtx, Ctx, Out);
285 InstrumentMemOperand(MemOp, AccessSize, IsWrite, RegCtx, Ctx, Out);
286 InstrumentMemOperandEpilogue(RegCtx, Ctx, Out);
291 class X86AddressSanitizer32 : public X86AddressSanitizer {
293 static const long kShadowOffset = 0x20000000;
295 X86AddressSanitizer32(const MCSubtargetInfo &STI)
296 : X86AddressSanitizer(STI) {}
297 virtual ~X86AddressSanitizer32() {}
299 virtual void StoreFlags(MCStreamer &Out) override {
300 EmitInstruction(Out, MCInstBuilder(X86::PUSHF32));
303 virtual void RestoreFlags(MCStreamer &Out) override {
304 EmitInstruction(Out, MCInstBuilder(X86::POPF32));
307 virtual void InstrumentMemOperandPrologue(const RegisterContext &RegCtx,
309 MCStreamer &Out) override {
311 Out, MCInstBuilder(X86::PUSH32r).addReg(RegCtx.addressReg(MVT::i32)));
313 Out, MCInstBuilder(X86::PUSH32r).addReg(RegCtx.shadowReg(MVT::i32)));
314 if (RegCtx.ScratchReg != X86::NoRegister) {
316 Out, MCInstBuilder(X86::PUSH32r).addReg(RegCtx.scratchReg(MVT::i32)));
321 virtual void InstrumentMemOperandEpilogue(const RegisterContext &RegCtx,
323 MCStreamer &Out) override {
325 if (RegCtx.ScratchReg != X86::NoRegister) {
327 Out, MCInstBuilder(X86::POP32r).addReg(RegCtx.scratchReg(MVT::i32)));
330 Out, MCInstBuilder(X86::POP32r).addReg(RegCtx.shadowReg(MVT::i32)));
332 Out, MCInstBuilder(X86::POP32r).addReg(RegCtx.addressReg(MVT::i32)));
335 virtual void InstrumentMemOperandSmall(X86Operand &Op, unsigned AccessSize,
337 const RegisterContext &RegCtx,
339 MCStreamer &Out) override;
340 virtual void InstrumentMemOperandLarge(X86Operand &Op, unsigned AccessSize,
342 const RegisterContext &RegCtx,
344 MCStreamer &Out) override;
345 virtual void InstrumentMOVSImpl(unsigned AccessSize, MCContext &Ctx,
346 MCStreamer &Out) override;
349 void EmitCallAsanReport(unsigned AccessSize, bool IsWrite, MCContext &Ctx,
350 MCStreamer &Out, const RegisterContext &RegCtx) {
351 EmitInstruction(Out, MCInstBuilder(X86::CLD));
352 EmitInstruction(Out, MCInstBuilder(X86::MMX_EMMS));
354 EmitInstruction(Out, MCInstBuilder(X86::AND64ri8)
359 Out, MCInstBuilder(X86::PUSH32r).addReg(RegCtx.addressReg(MVT::i32)));
361 const std::string &Fn = FuncName(AccessSize, IsWrite);
362 MCSymbol *FnSym = Ctx.GetOrCreateSymbol(StringRef(Fn));
363 const MCSymbolRefExpr *FnExpr =
364 MCSymbolRefExpr::Create(FnSym, MCSymbolRefExpr::VK_PLT, Ctx);
365 EmitInstruction(Out, MCInstBuilder(X86::CALLpcrel32).addExpr(FnExpr));
369 void X86AddressSanitizer32::InstrumentMemOperandSmall(
370 X86Operand &Op, unsigned AccessSize, bool IsWrite,
371 const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) {
372 unsigned AddressRegI32 = RegCtx.addressReg(MVT::i32);
373 unsigned ShadowRegI32 = RegCtx.shadowReg(MVT::i32);
374 unsigned ShadowRegI8 = RegCtx.shadowReg(MVT::i8);
376 assert(RegCtx.ScratchReg != X86::NoRegister);
377 unsigned ScratchRegI32 = RegCtx.scratchReg(MVT::i32);
381 Inst.setOpcode(X86::LEA32r);
382 Inst.addOperand(MCOperand::CreateReg(AddressRegI32));
383 Op.addMemOperands(Inst, 5);
384 EmitInstruction(Out, Inst);
387 EmitInstruction(Out, MCInstBuilder(X86::MOV32rr).addReg(ShadowRegI32).addReg(
389 EmitInstruction(Out, MCInstBuilder(X86::SHR32ri)
390 .addReg(ShadowRegI32)
391 .addReg(ShadowRegI32)
396 Inst.setOpcode(X86::MOV8rm);
397 Inst.addOperand(MCOperand::CreateReg(ShadowRegI8));
398 const MCExpr *Disp = MCConstantExpr::Create(kShadowOffset, Ctx);
399 std::unique_ptr<X86Operand> Op(
400 X86Operand::CreateMem(0, Disp, ShadowRegI32, 0, 1, SMLoc(), SMLoc()));
401 Op->addMemOperands(Inst, 5);
402 EmitInstruction(Out, Inst);
406 Out, MCInstBuilder(X86::TEST8rr).addReg(ShadowRegI8).addReg(ShadowRegI8));
407 MCSymbol *DoneSym = Ctx.CreateTempSymbol();
408 const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx);
409 EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr));
411 EmitInstruction(Out, MCInstBuilder(X86::MOV32rr).addReg(ScratchRegI32).addReg(
413 EmitInstruction(Out, MCInstBuilder(X86::AND32ri)
414 .addReg(ScratchRegI32)
415 .addReg(ScratchRegI32)
418 switch (AccessSize) {
423 Inst.setOpcode(X86::LEA32r);
424 Inst.addOperand(MCOperand::CreateReg(ScratchRegI32));
426 const MCExpr *Disp = MCConstantExpr::Create(1, Ctx);
427 std::unique_ptr<X86Operand> Op(
428 X86Operand::CreateMem(0, Disp, ScratchRegI32, 0, 1, SMLoc(), SMLoc()));
429 Op->addMemOperands(Inst, 5);
430 EmitInstruction(Out, Inst);
434 EmitInstruction(Out, MCInstBuilder(X86::ADD32ri8)
435 .addReg(ScratchRegI32)
436 .addReg(ScratchRegI32)
440 assert(false && "Incorrect access size");
446 MCInstBuilder(X86::MOVSX32rr8).addReg(ShadowRegI32).addReg(ShadowRegI8));
447 EmitInstruction(Out, MCInstBuilder(X86::CMP32rr).addReg(ScratchRegI32).addReg(
449 EmitInstruction(Out, MCInstBuilder(X86::JL_4).addExpr(DoneExpr));
451 EmitCallAsanReport(AccessSize, IsWrite, Ctx, Out, RegCtx);
452 EmitLabel(Out, DoneSym);
455 void X86AddressSanitizer32::InstrumentMemOperandLarge(
456 X86Operand &Op, unsigned AccessSize, bool IsWrite,
457 const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) {
458 unsigned AddressRegI32 = RegCtx.addressReg(MVT::i32);
459 unsigned ShadowRegI32 = RegCtx.shadowReg(MVT::i32);
463 Inst.setOpcode(X86::LEA32r);
464 Inst.addOperand(MCOperand::CreateReg(AddressRegI32));
465 Op.addMemOperands(Inst, 5);
466 EmitInstruction(Out, Inst);
469 EmitInstruction(Out, MCInstBuilder(X86::MOV32rr).addReg(ShadowRegI32).addReg(
471 EmitInstruction(Out, MCInstBuilder(X86::SHR32ri)
472 .addReg(ShadowRegI32)
473 .addReg(ShadowRegI32)
477 switch (AccessSize) {
479 Inst.setOpcode(X86::CMP8mi);
482 Inst.setOpcode(X86::CMP16mi);
485 assert(false && "Incorrect access size");
488 const MCExpr *Disp = MCConstantExpr::Create(kShadowOffset, Ctx);
489 std::unique_ptr<X86Operand> Op(
490 X86Operand::CreateMem(0, Disp, ShadowRegI32, 0, 1, SMLoc(), SMLoc()));
491 Op->addMemOperands(Inst, 5);
492 Inst.addOperand(MCOperand::CreateImm(0));
493 EmitInstruction(Out, Inst);
495 MCSymbol *DoneSym = Ctx.CreateTempSymbol();
496 const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx);
497 EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr));
499 EmitCallAsanReport(AccessSize, IsWrite, Ctx, Out, RegCtx);
500 EmitLabel(Out, DoneSym);
503 void X86AddressSanitizer32::InstrumentMOVSImpl(unsigned AccessSize,
508 // No need to test when ECX is equals to zero.
509 MCSymbol *DoneSym = Ctx.CreateTempSymbol();
510 const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx);
512 Out, MCInstBuilder(X86::TEST32rr).addReg(X86::ECX).addReg(X86::ECX));
513 EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr));
515 // Instrument first and last elements in src and dst range.
516 InstrumentMOVSBase(X86::EDI /* DstReg */, X86::ESI /* SrcReg */,
517 X86::ECX /* CntReg */, AccessSize, Ctx, Out);
519 EmitLabel(Out, DoneSym);
523 class X86AddressSanitizer64 : public X86AddressSanitizer {
525 static const long kShadowOffset = 0x7fff8000;
527 X86AddressSanitizer64(const MCSubtargetInfo &STI)
528 : X86AddressSanitizer(STI) {}
529 virtual ~X86AddressSanitizer64() {}
531 virtual void StoreFlags(MCStreamer &Out) override {
532 EmitInstruction(Out, MCInstBuilder(X86::PUSHF64));
535 virtual void RestoreFlags(MCStreamer &Out) override {
536 EmitInstruction(Out, MCInstBuilder(X86::POPF64));
539 virtual void InstrumentMemOperandPrologue(const RegisterContext &RegCtx,
541 MCStreamer &Out) override {
542 EmitAdjustRSP(Ctx, Out, -128);
544 Out, MCInstBuilder(X86::PUSH64r).addReg(RegCtx.shadowReg(MVT::i64)));
546 Out, MCInstBuilder(X86::PUSH64r).addReg(RegCtx.addressReg(MVT::i64)));
547 if (RegCtx.ScratchReg != X86::NoRegister) {
549 Out, MCInstBuilder(X86::PUSH64r).addReg(RegCtx.scratchReg(MVT::i64)));
554 virtual void InstrumentMemOperandEpilogue(const RegisterContext &RegCtx,
556 MCStreamer &Out) override {
558 if (RegCtx.ScratchReg != X86::NoRegister) {
560 Out, MCInstBuilder(X86::POP64r).addReg(RegCtx.scratchReg(MVT::i64)));
563 Out, MCInstBuilder(X86::POP64r).addReg(RegCtx.addressReg(MVT::i64)));
565 Out, MCInstBuilder(X86::POP64r).addReg(RegCtx.shadowReg(MVT::i64)));
566 EmitAdjustRSP(Ctx, Out, 128);
569 virtual void InstrumentMemOperandSmall(X86Operand &Op, unsigned AccessSize,
571 const RegisterContext &RegCtx,
573 MCStreamer &Out) override;
574 virtual void InstrumentMemOperandLarge(X86Operand &Op, unsigned AccessSize,
576 const RegisterContext &RegCtx,
578 MCStreamer &Out) override;
579 virtual void InstrumentMOVSImpl(unsigned AccessSize, MCContext &Ctx,
580 MCStreamer &Out) override;
583 void EmitAdjustRSP(MCContext &Ctx, MCStreamer &Out, long Offset) {
585 Inst.setOpcode(X86::LEA64r);
586 Inst.addOperand(MCOperand::CreateReg(X86::RSP));
588 const MCExpr *Disp = MCConstantExpr::Create(Offset, Ctx);
589 std::unique_ptr<X86Operand> Op(
590 X86Operand::CreateMem(0, Disp, X86::RSP, 0, 1, SMLoc(), SMLoc()));
591 Op->addMemOperands(Inst, 5);
592 EmitInstruction(Out, Inst);
595 void EmitCallAsanReport(unsigned AccessSize, bool IsWrite, MCContext &Ctx,
596 MCStreamer &Out, const RegisterContext &RegCtx) {
597 EmitInstruction(Out, MCInstBuilder(X86::CLD));
598 EmitInstruction(Out, MCInstBuilder(X86::MMX_EMMS));
600 EmitInstruction(Out, MCInstBuilder(X86::AND64ri8)
605 if (RegCtx.AddressReg != X86::RDI) {
606 EmitInstruction(Out, MCInstBuilder(X86::MOV64rr).addReg(X86::RDI).addReg(
607 RegCtx.addressReg(MVT::i64)));
609 const std::string &Fn = FuncName(AccessSize, IsWrite);
610 MCSymbol *FnSym = Ctx.GetOrCreateSymbol(StringRef(Fn));
611 const MCSymbolRefExpr *FnExpr =
612 MCSymbolRefExpr::Create(FnSym, MCSymbolRefExpr::VK_PLT, Ctx);
613 EmitInstruction(Out, MCInstBuilder(X86::CALL64pcrel32).addExpr(FnExpr));
617 void X86AddressSanitizer64::InstrumentMemOperandSmall(
618 X86Operand &Op, unsigned AccessSize, bool IsWrite,
619 const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) {
620 unsigned AddressRegI64 = RegCtx.addressReg(MVT::i64);
621 unsigned AddressRegI32 = RegCtx.addressReg(MVT::i32);
622 unsigned ShadowRegI64 = RegCtx.shadowReg(MVT::i64);
623 unsigned ShadowRegI32 = RegCtx.shadowReg(MVT::i32);
624 unsigned ShadowRegI8 = RegCtx.shadowReg(MVT::i8);
626 assert(RegCtx.ScratchReg != X86::NoRegister);
627 unsigned ScratchRegI32 = RegCtx.scratchReg(MVT::i32);
631 Inst.setOpcode(X86::LEA64r);
632 Inst.addOperand(MCOperand::CreateReg(AddressRegI64));
633 Op.addMemOperands(Inst, 5);
634 EmitInstruction(Out, Inst);
636 EmitInstruction(Out, MCInstBuilder(X86::MOV64rr).addReg(ShadowRegI64).addReg(
638 EmitInstruction(Out, MCInstBuilder(X86::SHR64ri)
639 .addReg(ShadowRegI64)
640 .addReg(ShadowRegI64)
644 Inst.setOpcode(X86::MOV8rm);
645 Inst.addOperand(MCOperand::CreateReg(ShadowRegI8));
646 const MCExpr *Disp = MCConstantExpr::Create(kShadowOffset, Ctx);
647 std::unique_ptr<X86Operand> Op(
648 X86Operand::CreateMem(0, Disp, ShadowRegI64, 0, 1, SMLoc(), SMLoc()));
649 Op->addMemOperands(Inst, 5);
650 EmitInstruction(Out, Inst);
654 Out, MCInstBuilder(X86::TEST8rr).addReg(ShadowRegI8).addReg(ShadowRegI8));
655 MCSymbol *DoneSym = Ctx.CreateTempSymbol();
656 const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx);
657 EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr));
659 EmitInstruction(Out, MCInstBuilder(X86::MOV32rr).addReg(ScratchRegI32).addReg(
661 EmitInstruction(Out, MCInstBuilder(X86::AND32ri)
662 .addReg(ScratchRegI32)
663 .addReg(ScratchRegI32)
666 switch (AccessSize) {
671 Inst.setOpcode(X86::LEA32r);
672 Inst.addOperand(MCOperand::CreateReg(ScratchRegI32));
674 const MCExpr *Disp = MCConstantExpr::Create(1, Ctx);
675 std::unique_ptr<X86Operand> Op(
676 X86Operand::CreateMem(0, Disp, ScratchRegI32, 0, 1, SMLoc(), SMLoc()));
677 Op->addMemOperands(Inst, 5);
678 EmitInstruction(Out, Inst);
682 EmitInstruction(Out, MCInstBuilder(X86::ADD32ri8)
683 .addReg(ScratchRegI32)
684 .addReg(ScratchRegI32)
688 assert(false && "Incorrect access size");
694 MCInstBuilder(X86::MOVSX32rr8).addReg(ShadowRegI32).addReg(ShadowRegI8));
695 EmitInstruction(Out, MCInstBuilder(X86::CMP32rr).addReg(ScratchRegI32).addReg(
697 EmitInstruction(Out, MCInstBuilder(X86::JL_4).addExpr(DoneExpr));
699 EmitCallAsanReport(AccessSize, IsWrite, Ctx, Out, RegCtx);
700 EmitLabel(Out, DoneSym);
703 void X86AddressSanitizer64::InstrumentMemOperandLarge(
704 X86Operand &Op, unsigned AccessSize, bool IsWrite,
705 const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) {
706 unsigned AddressRegI64 = RegCtx.addressReg(MVT::i64);
707 unsigned ShadowRegI64 = RegCtx.shadowReg(MVT::i64);
711 Inst.setOpcode(X86::LEA64r);
712 Inst.addOperand(MCOperand::CreateReg(AddressRegI64));
713 Op.addMemOperands(Inst, 5);
714 EmitInstruction(Out, Inst);
716 EmitInstruction(Out, MCInstBuilder(X86::MOV64rr).addReg(ShadowRegI64).addReg(
718 EmitInstruction(Out, MCInstBuilder(X86::SHR64ri)
719 .addReg(ShadowRegI64)
720 .addReg(ShadowRegI64)
724 switch (AccessSize) {
726 Inst.setOpcode(X86::CMP8mi);
729 Inst.setOpcode(X86::CMP16mi);
732 assert(false && "Incorrect access size");
735 const MCExpr *Disp = MCConstantExpr::Create(kShadowOffset, Ctx);
736 std::unique_ptr<X86Operand> Op(
737 X86Operand::CreateMem(0, Disp, ShadowRegI64, 0, 1, SMLoc(), SMLoc()));
738 Op->addMemOperands(Inst, 5);
739 Inst.addOperand(MCOperand::CreateImm(0));
740 EmitInstruction(Out, Inst);
743 MCSymbol *DoneSym = Ctx.CreateTempSymbol();
744 const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx);
745 EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr));
747 EmitCallAsanReport(AccessSize, IsWrite, Ctx, Out, RegCtx);
748 EmitLabel(Out, DoneSym);
751 void X86AddressSanitizer64::InstrumentMOVSImpl(unsigned AccessSize,
756 // No need to test when RCX is equals to zero.
757 MCSymbol *DoneSym = Ctx.CreateTempSymbol();
758 const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx);
760 Out, MCInstBuilder(X86::TEST64rr).addReg(X86::RCX).addReg(X86::RCX));
761 EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr));
763 // Instrument first and last elements in src and dst range.
764 InstrumentMOVSBase(X86::RDI /* DstReg */, X86::RSI /* SrcReg */,
765 X86::RCX /* CntReg */, AccessSize, Ctx, Out);
767 EmitLabel(Out, DoneSym);
771 } // End anonymous namespace
773 X86AsmInstrumentation::X86AsmInstrumentation(const MCSubtargetInfo &STI)
776 X86AsmInstrumentation::~X86AsmInstrumentation() {}
778 void X86AsmInstrumentation::InstrumentAndEmitInstruction(
779 const MCInst &Inst, OperandVector &Operands, MCContext &Ctx,
780 const MCInstrInfo &MII, MCStreamer &Out) {
781 EmitInstruction(Out, Inst);
784 void X86AsmInstrumentation::EmitInstruction(MCStreamer &Out,
785 const MCInst &Inst) {
786 Out.EmitInstruction(Inst, STI);
789 X86AsmInstrumentation *
790 CreateX86AsmInstrumentation(const MCTargetOptions &MCOptions,
791 const MCContext &Ctx, const MCSubtargetInfo &STI) {
792 Triple T(STI.getTargetTriple());
793 const bool hasCompilerRTSupport = T.isOSLinux();
794 if (ClAsanInstrumentAssembly && hasCompilerRTSupport &&
795 MCOptions.SanitizeAddress) {
796 if ((STI.getFeatureBits() & X86::Mode32Bit) != 0)
797 return new X86AddressSanitizer32(STI);
798 if ((STI.getFeatureBits() & X86::Mode64Bit) != 0)
799 return new X86AddressSanitizer64(STI);
801 return new X86AsmInstrumentation(STI);
804 } // End llvm namespace