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/MCAsmInfo.h"
19 #include "llvm/MC/MCContext.h"
20 #include "llvm/MC/MCInst.h"
21 #include "llvm/MC/MCInstBuilder.h"
22 #include "llvm/MC/MCInstrInfo.h"
23 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
24 #include "llvm/MC/MCStreamer.h"
25 #include "llvm/MC/MCSubtargetInfo.h"
26 #include "llvm/MC/MCTargetAsmParser.h"
27 #include "llvm/MC/MCTargetOptions.h"
28 #include "llvm/Support/CommandLine.h"
33 static cl::opt<bool> ClAsanInstrumentAssembly(
34 "asan-instrument-assembly",
35 cl::desc("instrument assembly with AddressSanitizer checks"), cl::Hidden,
38 bool IsStackReg(unsigned Reg) {
39 return Reg == X86::RSP || Reg == X86::ESP || Reg == X86::SP;
42 bool IsSmallMemAccess(unsigned AccessSize) { return AccessSize < 8; }
44 std::string FuncName(unsigned AccessSize, bool IsWrite) {
45 return std::string("__asan_report_") + (IsWrite ? "store" : "load") +
49 class X86AddressSanitizer : public X86AsmInstrumentation {
51 struct RegisterContext {
52 RegisterContext(unsigned AddressReg, unsigned ShadowReg,
54 : AddressReg(AddressReg), ShadowReg(ShadowReg), ScratchReg(ScratchReg) {
57 unsigned addressReg(MVT::SimpleValueType VT) const {
58 return getX86SubSuperRegister(AddressReg, VT);
61 unsigned shadowReg(MVT::SimpleValueType VT) const {
62 return getX86SubSuperRegister(ShadowReg, VT);
65 unsigned scratchReg(MVT::SimpleValueType VT) const {
66 return getX86SubSuperRegister(ScratchReg, VT);
69 const unsigned AddressReg;
70 const unsigned ShadowReg;
71 const unsigned ScratchReg;
74 X86AddressSanitizer(const MCSubtargetInfo &STI)
75 : X86AsmInstrumentation(STI), RepPrefix(false) {}
76 virtual ~X86AddressSanitizer() {}
78 // X86AsmInstrumentation implementation:
79 virtual void InstrumentAndEmitInstruction(const MCInst &Inst,
80 OperandVector &Operands,
82 const MCInstrInfo &MII,
83 MCStreamer &Out) override {
84 InstrumentMOVS(Inst, Operands, Ctx, MII, Out);
86 EmitInstruction(Out, MCInstBuilder(X86::REP_PREFIX));
88 InstrumentMOV(Inst, Operands, Ctx, MII, Out);
90 RepPrefix = (Inst.getOpcode() == X86::REP_PREFIX);
92 EmitInstruction(Out, Inst);
95 // Should be implemented differently in x86_32 and x86_64 subclasses.
96 virtual void StoreFlags(MCStreamer &Out) = 0;
98 virtual void RestoreFlags(MCStreamer &Out) = 0;
100 // Adjusts up stack and saves all registers used in instrumentation.
101 virtual void InstrumentMemOperandPrologue(const RegisterContext &RegCtx,
103 MCStreamer &Out) = 0;
105 // Restores all registers used in instrumentation and adjusts stack.
106 virtual void InstrumentMemOperandEpilogue(const RegisterContext &RegCtx,
108 MCStreamer &Out) = 0;
110 virtual void InstrumentMemOperandSmall(X86Operand &Op, unsigned AccessSize,
112 const RegisterContext &RegCtx,
113 MCContext &Ctx, MCStreamer &Out) = 0;
114 virtual void InstrumentMemOperandLarge(X86Operand &Op, unsigned AccessSize,
116 const RegisterContext &RegCtx,
117 MCContext &Ctx, MCStreamer &Out) = 0;
119 virtual void InstrumentMOVSImpl(unsigned AccessSize, MCContext &Ctx,
120 MCStreamer &Out) = 0;
122 void InstrumentMemOperand(X86Operand &Op, unsigned AccessSize, bool IsWrite,
123 const RegisterContext &RegCtx, MCContext &Ctx,
125 void InstrumentMOVSBase(unsigned DstReg, unsigned SrcReg, unsigned CntReg,
126 unsigned AccessSize, MCContext &Ctx, MCStreamer &Out);
128 void InstrumentMOVS(const MCInst &Inst, OperandVector &Operands,
129 MCContext &Ctx, const MCInstrInfo &MII, MCStreamer &Out);
130 void InstrumentMOV(const MCInst &Inst, OperandVector &Operands,
131 MCContext &Ctx, const MCInstrInfo &MII, MCStreamer &Out);
134 void EmitLabel(MCStreamer &Out, MCSymbol *Label) { Out.EmitLabel(Label); }
136 // True when previous instruction was actually REP prefix.
140 void X86AddressSanitizer::InstrumentMemOperand(
141 X86Operand &Op, unsigned AccessSize, bool IsWrite,
142 const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) {
143 assert(Op.isMem() && "Op should be a memory operand.");
144 assert((AccessSize & (AccessSize - 1)) == 0 && AccessSize <= 16 &&
145 "AccessSize should be a power of two, less or equal than 16.");
146 // FIXME: take into account load/store alignment.
147 if (IsSmallMemAccess(AccessSize))
148 InstrumentMemOperandSmall(Op, AccessSize, IsWrite, RegCtx, Ctx, Out);
150 InstrumentMemOperandLarge(Op, AccessSize, IsWrite, RegCtx, Ctx, Out);
153 void X86AddressSanitizer::InstrumentMOVSBase(unsigned DstReg, unsigned SrcReg,
156 MCContext &Ctx, MCStreamer &Out) {
157 // FIXME: check whole ranges [DstReg .. DstReg + AccessSize * (CntReg - 1)]
158 // and [SrcReg .. SrcReg + AccessSize * (CntReg - 1)].
159 RegisterContext RegCtx(X86::RDX /* AddressReg */, X86::RAX /* ShadowReg */,
160 IsSmallMemAccess(AccessSize)
162 : X86::NoRegister /* ScratchReg */);
164 InstrumentMemOperandPrologue(RegCtx, Ctx, Out);
168 const MCExpr *Disp = MCConstantExpr::Create(0, Ctx);
169 std::unique_ptr<X86Operand> Op(X86Operand::CreateMem(
170 0, Disp, SrcReg, 0, AccessSize, SMLoc(), SMLoc()));
171 InstrumentMemOperand(*Op, AccessSize, false /* IsWrite */, RegCtx, Ctx,
175 // Test -1(%SrcReg, %CntReg, AccessSize)
177 const MCExpr *Disp = MCConstantExpr::Create(-1, Ctx);
178 std::unique_ptr<X86Operand> Op(X86Operand::CreateMem(
179 0, Disp, SrcReg, CntReg, AccessSize, SMLoc(), SMLoc()));
180 InstrumentMemOperand(*Op, AccessSize, false /* IsWrite */, RegCtx, Ctx,
186 const MCExpr *Disp = MCConstantExpr::Create(0, Ctx);
187 std::unique_ptr<X86Operand> Op(X86Operand::CreateMem(
188 0, Disp, DstReg, 0, AccessSize, SMLoc(), SMLoc()));
189 InstrumentMemOperand(*Op, AccessSize, true /* IsWrite */, RegCtx, Ctx, Out);
192 // Test -1(%DstReg, %CntReg, AccessSize)
194 const MCExpr *Disp = MCConstantExpr::Create(-1, Ctx);
195 std::unique_ptr<X86Operand> Op(X86Operand::CreateMem(
196 0, Disp, DstReg, CntReg, AccessSize, SMLoc(), SMLoc()));
197 InstrumentMemOperand(*Op, AccessSize, true /* IsWrite */, RegCtx, Ctx, Out);
200 InstrumentMemOperandEpilogue(RegCtx, Ctx, Out);
203 void X86AddressSanitizer::InstrumentMOVS(const MCInst &Inst,
204 OperandVector &Operands,
205 MCContext &Ctx, const MCInstrInfo &MII,
207 // Access size in bytes.
208 unsigned AccessSize = 0;
210 switch (Inst.getOpcode()) {
227 InstrumentMOVSImpl(AccessSize, Ctx, Out);
230 void X86AddressSanitizer::InstrumentMOV(const MCInst &Inst,
231 OperandVector &Operands, MCContext &Ctx,
232 const MCInstrInfo &MII,
234 // Access size in bytes.
235 unsigned AccessSize = 0;
237 switch (Inst.getOpcode()) {
268 const bool IsWrite = MII.get(Inst.getOpcode()).mayStore();
269 RegisterContext RegCtx(X86::RDI /* AddressReg */, X86::RAX /* ShadowReg */,
270 IsSmallMemAccess(AccessSize)
272 : X86::NoRegister /* ScratchReg */);
274 for (unsigned Ix = 0; Ix < Operands.size(); ++Ix) {
275 assert(Operands[Ix]);
276 MCParsedAsmOperand &Op = *Operands[Ix];
278 X86Operand &MemOp = static_cast<X86Operand &>(Op);
279 // FIXME: get rid of this limitation.
280 if (IsStackReg(MemOp.getMemBaseReg()) ||
281 IsStackReg(MemOp.getMemIndexReg())) {
285 InstrumentMemOperandPrologue(RegCtx, Ctx, Out);
286 InstrumentMemOperand(MemOp, AccessSize, IsWrite, RegCtx, Ctx, Out);
287 InstrumentMemOperandEpilogue(RegCtx, Ctx, Out);
292 class X86AddressSanitizer32 : public X86AddressSanitizer {
294 static const long kShadowOffset = 0x20000000;
296 X86AddressSanitizer32(const MCSubtargetInfo &STI)
297 : X86AddressSanitizer(STI) {}
299 virtual ~X86AddressSanitizer32() {}
301 unsigned GetFrameReg(const MCContext &Ctx, MCStreamer &Out) {
302 unsigned FrameReg = GetFrameRegGeneric(Ctx, Out);
303 if (FrameReg == X86::NoRegister)
305 return getX86SubSuperRegister(FrameReg, MVT::i32);
308 virtual void StoreFlags(MCStreamer &Out) override {
309 EmitInstruction(Out, MCInstBuilder(X86::PUSHF32));
312 virtual void RestoreFlags(MCStreamer &Out) override {
313 EmitInstruction(Out, MCInstBuilder(X86::POPF32));
316 virtual void InstrumentMemOperandPrologue(const RegisterContext &RegCtx,
318 MCStreamer &Out) override {
319 const MCRegisterInfo *MRI = Ctx.getRegisterInfo();
320 unsigned FrameReg = GetFrameReg(Ctx, Out);
321 if (MRI && FrameReg != X86::NoRegister) {
323 Out, MCInstBuilder(X86::PUSH32r).addReg(X86::EBP));
324 if (FrameReg == X86::ESP) {
325 Out.EmitCFIAdjustCfaOffset(4 /* byte size of the FrameReg */);
326 Out.EmitCFIRelOffset(
327 MRI->getDwarfRegNum(X86::EBP, true /* IsEH */), 0);
330 Out, MCInstBuilder(X86::MOV32rr).addReg(X86::EBP).addReg(FrameReg));
331 Out.EmitCFIRememberState();
332 Out.EmitCFIDefCfaRegister(
333 MRI->getDwarfRegNum(X86::EBP, true /* IsEH */));
337 Out, MCInstBuilder(X86::PUSH32r).addReg(RegCtx.addressReg(MVT::i32)));
339 Out, MCInstBuilder(X86::PUSH32r).addReg(RegCtx.shadowReg(MVT::i32)));
340 if (RegCtx.ScratchReg != X86::NoRegister) {
342 Out, MCInstBuilder(X86::PUSH32r).addReg(RegCtx.scratchReg(MVT::i32)));
347 virtual void InstrumentMemOperandEpilogue(const RegisterContext &RegCtx,
349 MCStreamer &Out) override {
351 if (RegCtx.ScratchReg != X86::NoRegister) {
353 Out, MCInstBuilder(X86::POP32r).addReg(RegCtx.scratchReg(MVT::i32)));
356 Out, MCInstBuilder(X86::POP32r).addReg(RegCtx.shadowReg(MVT::i32)));
358 Out, MCInstBuilder(X86::POP32r).addReg(RegCtx.addressReg(MVT::i32)));
360 unsigned FrameReg = GetFrameReg(Ctx, Out);
361 if (Ctx.getRegisterInfo() && FrameReg != X86::NoRegister) {
363 Out, MCInstBuilder(X86::POP32r).addReg(X86::EBP));
364 Out.EmitCFIRestoreState();
365 if (FrameReg == X86::ESP)
366 Out.EmitCFIAdjustCfaOffset(-4 /* byte size of the FrameReg */);
370 virtual void InstrumentMemOperandSmall(X86Operand &Op, unsigned AccessSize,
372 const RegisterContext &RegCtx,
374 MCStreamer &Out) override;
375 virtual void InstrumentMemOperandLarge(X86Operand &Op, unsigned AccessSize,
377 const RegisterContext &RegCtx,
379 MCStreamer &Out) override;
380 virtual void InstrumentMOVSImpl(unsigned AccessSize, MCContext &Ctx,
381 MCStreamer &Out) override;
384 void EmitCallAsanReport(unsigned AccessSize, bool IsWrite, MCContext &Ctx,
385 MCStreamer &Out, const RegisterContext &RegCtx) {
386 EmitInstruction(Out, MCInstBuilder(X86::CLD));
387 EmitInstruction(Out, MCInstBuilder(X86::MMX_EMMS));
389 EmitInstruction(Out, MCInstBuilder(X86::AND64ri8)
394 Out, MCInstBuilder(X86::PUSH32r).addReg(RegCtx.addressReg(MVT::i32)));
396 const std::string &Fn = FuncName(AccessSize, IsWrite);
397 MCSymbol *FnSym = Ctx.GetOrCreateSymbol(StringRef(Fn));
398 const MCSymbolRefExpr *FnExpr =
399 MCSymbolRefExpr::Create(FnSym, MCSymbolRefExpr::VK_PLT, Ctx);
400 EmitInstruction(Out, MCInstBuilder(X86::CALLpcrel32).addExpr(FnExpr));
404 void X86AddressSanitizer32::InstrumentMemOperandSmall(
405 X86Operand &Op, unsigned AccessSize, bool IsWrite,
406 const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) {
407 unsigned AddressRegI32 = RegCtx.addressReg(MVT::i32);
408 unsigned ShadowRegI32 = RegCtx.shadowReg(MVT::i32);
409 unsigned ShadowRegI8 = RegCtx.shadowReg(MVT::i8);
411 assert(RegCtx.ScratchReg != X86::NoRegister);
412 unsigned ScratchRegI32 = RegCtx.scratchReg(MVT::i32);
416 Inst.setOpcode(X86::LEA32r);
417 Inst.addOperand(MCOperand::CreateReg(AddressRegI32));
418 Op.addMemOperands(Inst, 5);
419 EmitInstruction(Out, Inst);
422 EmitInstruction(Out, MCInstBuilder(X86::MOV32rr).addReg(ShadowRegI32).addReg(
424 EmitInstruction(Out, MCInstBuilder(X86::SHR32ri)
425 .addReg(ShadowRegI32)
426 .addReg(ShadowRegI32)
431 Inst.setOpcode(X86::MOV8rm);
432 Inst.addOperand(MCOperand::CreateReg(ShadowRegI8));
433 const MCExpr *Disp = MCConstantExpr::Create(kShadowOffset, Ctx);
434 std::unique_ptr<X86Operand> Op(
435 X86Operand::CreateMem(0, Disp, ShadowRegI32, 0, 1, SMLoc(), SMLoc()));
436 Op->addMemOperands(Inst, 5);
437 EmitInstruction(Out, Inst);
441 Out, MCInstBuilder(X86::TEST8rr).addReg(ShadowRegI8).addReg(ShadowRegI8));
442 MCSymbol *DoneSym = Ctx.CreateTempSymbol();
443 const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx);
444 EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr));
446 EmitInstruction(Out, MCInstBuilder(X86::MOV32rr).addReg(ScratchRegI32).addReg(
448 EmitInstruction(Out, MCInstBuilder(X86::AND32ri)
449 .addReg(ScratchRegI32)
450 .addReg(ScratchRegI32)
453 switch (AccessSize) {
458 Inst.setOpcode(X86::LEA32r);
459 Inst.addOperand(MCOperand::CreateReg(ScratchRegI32));
461 const MCExpr *Disp = MCConstantExpr::Create(1, Ctx);
462 std::unique_ptr<X86Operand> Op(
463 X86Operand::CreateMem(0, Disp, ScratchRegI32, 0, 1, SMLoc(), SMLoc()));
464 Op->addMemOperands(Inst, 5);
465 EmitInstruction(Out, Inst);
469 EmitInstruction(Out, MCInstBuilder(X86::ADD32ri8)
470 .addReg(ScratchRegI32)
471 .addReg(ScratchRegI32)
475 assert(false && "Incorrect access size");
481 MCInstBuilder(X86::MOVSX32rr8).addReg(ShadowRegI32).addReg(ShadowRegI8));
482 EmitInstruction(Out, MCInstBuilder(X86::CMP32rr).addReg(ScratchRegI32).addReg(
484 EmitInstruction(Out, MCInstBuilder(X86::JL_4).addExpr(DoneExpr));
486 EmitCallAsanReport(AccessSize, IsWrite, Ctx, Out, RegCtx);
487 EmitLabel(Out, DoneSym);
490 void X86AddressSanitizer32::InstrumentMemOperandLarge(
491 X86Operand &Op, unsigned AccessSize, bool IsWrite,
492 const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) {
493 unsigned AddressRegI32 = RegCtx.addressReg(MVT::i32);
494 unsigned ShadowRegI32 = RegCtx.shadowReg(MVT::i32);
498 Inst.setOpcode(X86::LEA32r);
499 Inst.addOperand(MCOperand::CreateReg(AddressRegI32));
500 Op.addMemOperands(Inst, 5);
501 EmitInstruction(Out, Inst);
504 EmitInstruction(Out, MCInstBuilder(X86::MOV32rr).addReg(ShadowRegI32).addReg(
506 EmitInstruction(Out, MCInstBuilder(X86::SHR32ri)
507 .addReg(ShadowRegI32)
508 .addReg(ShadowRegI32)
512 switch (AccessSize) {
514 Inst.setOpcode(X86::CMP8mi);
517 Inst.setOpcode(X86::CMP16mi);
520 assert(false && "Incorrect access size");
523 const MCExpr *Disp = MCConstantExpr::Create(kShadowOffset, Ctx);
524 std::unique_ptr<X86Operand> Op(
525 X86Operand::CreateMem(0, Disp, ShadowRegI32, 0, 1, SMLoc(), SMLoc()));
526 Op->addMemOperands(Inst, 5);
527 Inst.addOperand(MCOperand::CreateImm(0));
528 EmitInstruction(Out, Inst);
530 MCSymbol *DoneSym = Ctx.CreateTempSymbol();
531 const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx);
532 EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr));
534 EmitCallAsanReport(AccessSize, IsWrite, Ctx, Out, RegCtx);
535 EmitLabel(Out, DoneSym);
538 void X86AddressSanitizer32::InstrumentMOVSImpl(unsigned AccessSize,
543 // No need to test when ECX is equals to zero.
544 MCSymbol *DoneSym = Ctx.CreateTempSymbol();
545 const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx);
547 Out, MCInstBuilder(X86::TEST32rr).addReg(X86::ECX).addReg(X86::ECX));
548 EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr));
550 // Instrument first and last elements in src and dst range.
551 InstrumentMOVSBase(X86::EDI /* DstReg */, X86::ESI /* SrcReg */,
552 X86::ECX /* CntReg */, AccessSize, Ctx, Out);
554 EmitLabel(Out, DoneSym);
558 class X86AddressSanitizer64 : public X86AddressSanitizer {
560 static const long kShadowOffset = 0x7fff8000;
562 X86AddressSanitizer64(const MCSubtargetInfo &STI)
563 : X86AddressSanitizer(STI) {}
565 virtual ~X86AddressSanitizer64() {}
567 unsigned GetFrameReg(const MCContext &Ctx, MCStreamer &Out) {
568 unsigned FrameReg = GetFrameRegGeneric(Ctx, Out);
569 if (FrameReg == X86::NoRegister)
571 return getX86SubSuperRegister(FrameReg, MVT::i64);
574 virtual void StoreFlags(MCStreamer &Out) override {
575 EmitInstruction(Out, MCInstBuilder(X86::PUSHF64));
578 virtual void RestoreFlags(MCStreamer &Out) override {
579 EmitInstruction(Out, MCInstBuilder(X86::POPF64));
582 virtual void InstrumentMemOperandPrologue(const RegisterContext &RegCtx,
584 MCStreamer &Out) override {
585 const MCRegisterInfo *MRI = Ctx.getRegisterInfo();
586 unsigned FrameReg = GetFrameReg(Ctx, Out);
587 if (MRI && FrameReg != X86::NoRegister) {
588 EmitInstruction(Out, MCInstBuilder(X86::PUSH64r).addReg(X86::RBP));
589 if (FrameReg == X86::RSP) {
590 Out.EmitCFIAdjustCfaOffset(8 /* byte size of the FrameReg */);
591 Out.EmitCFIRelOffset(
592 MRI->getDwarfRegNum(X86::RBP, true /* IsEH */), 0);
595 Out, MCInstBuilder(X86::MOV64rr).addReg(X86::RBP).addReg(FrameReg));
596 Out.EmitCFIRememberState();
597 Out.EmitCFIDefCfaRegister(
598 MRI->getDwarfRegNum(X86::RBP, true /* IsEH */));
601 EmitAdjustRSP(Ctx, Out, -128);
603 Out, MCInstBuilder(X86::PUSH64r).addReg(RegCtx.shadowReg(MVT::i64)));
605 Out, MCInstBuilder(X86::PUSH64r).addReg(RegCtx.addressReg(MVT::i64)));
606 if (RegCtx.ScratchReg != X86::NoRegister) {
608 Out, MCInstBuilder(X86::PUSH64r).addReg(RegCtx.scratchReg(MVT::i64)));
613 virtual void InstrumentMemOperandEpilogue(const RegisterContext &RegCtx,
615 MCStreamer &Out) override {
617 if (RegCtx.ScratchReg != X86::NoRegister) {
619 Out, MCInstBuilder(X86::POP64r).addReg(RegCtx.scratchReg(MVT::i64)));
622 Out, MCInstBuilder(X86::POP64r).addReg(RegCtx.addressReg(MVT::i64)));
624 Out, MCInstBuilder(X86::POP64r).addReg(RegCtx.shadowReg(MVT::i64)));
625 EmitAdjustRSP(Ctx, Out, 128);
627 unsigned FrameReg = GetFrameReg(Ctx, Out);
628 if (Ctx.getRegisterInfo() && FrameReg != X86::NoRegister) {
630 Out, MCInstBuilder(X86::POP64r).addReg(X86::RBP));
631 Out.EmitCFIRestoreState();
632 if (FrameReg == X86::RSP)
633 Out.EmitCFIAdjustCfaOffset(-8 /* byte size of the FrameReg */);
637 virtual void InstrumentMemOperandSmall(X86Operand &Op, unsigned AccessSize,
639 const RegisterContext &RegCtx,
641 MCStreamer &Out) override;
642 virtual void InstrumentMemOperandLarge(X86Operand &Op, unsigned AccessSize,
644 const RegisterContext &RegCtx,
646 MCStreamer &Out) override;
647 virtual void InstrumentMOVSImpl(unsigned AccessSize, MCContext &Ctx,
648 MCStreamer &Out) override;
651 void EmitAdjustRSP(MCContext &Ctx, MCStreamer &Out, long Offset) {
653 Inst.setOpcode(X86::LEA64r);
654 Inst.addOperand(MCOperand::CreateReg(X86::RSP));
656 const MCExpr *Disp = MCConstantExpr::Create(Offset, Ctx);
657 std::unique_ptr<X86Operand> Op(
658 X86Operand::CreateMem(0, Disp, X86::RSP, 0, 1, SMLoc(), SMLoc()));
659 Op->addMemOperands(Inst, 5);
660 EmitInstruction(Out, Inst);
663 void EmitCallAsanReport(unsigned AccessSize, bool IsWrite, MCContext &Ctx,
664 MCStreamer &Out, const RegisterContext &RegCtx) {
665 EmitInstruction(Out, MCInstBuilder(X86::CLD));
666 EmitInstruction(Out, MCInstBuilder(X86::MMX_EMMS));
668 EmitInstruction(Out, MCInstBuilder(X86::AND64ri8)
673 if (RegCtx.AddressReg != X86::RDI) {
674 EmitInstruction(Out, MCInstBuilder(X86::MOV64rr).addReg(X86::RDI).addReg(
675 RegCtx.addressReg(MVT::i64)));
677 const std::string &Fn = FuncName(AccessSize, IsWrite);
678 MCSymbol *FnSym = Ctx.GetOrCreateSymbol(StringRef(Fn));
679 const MCSymbolRefExpr *FnExpr =
680 MCSymbolRefExpr::Create(FnSym, MCSymbolRefExpr::VK_PLT, Ctx);
681 EmitInstruction(Out, MCInstBuilder(X86::CALL64pcrel32).addExpr(FnExpr));
685 void X86AddressSanitizer64::InstrumentMemOperandSmall(
686 X86Operand &Op, unsigned AccessSize, bool IsWrite,
687 const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) {
688 unsigned AddressRegI64 = RegCtx.addressReg(MVT::i64);
689 unsigned AddressRegI32 = RegCtx.addressReg(MVT::i32);
690 unsigned ShadowRegI64 = RegCtx.shadowReg(MVT::i64);
691 unsigned ShadowRegI32 = RegCtx.shadowReg(MVT::i32);
692 unsigned ShadowRegI8 = RegCtx.shadowReg(MVT::i8);
694 assert(RegCtx.ScratchReg != X86::NoRegister);
695 unsigned ScratchRegI32 = RegCtx.scratchReg(MVT::i32);
699 Inst.setOpcode(X86::LEA64r);
700 Inst.addOperand(MCOperand::CreateReg(AddressRegI64));
701 Op.addMemOperands(Inst, 5);
702 EmitInstruction(Out, Inst);
704 EmitInstruction(Out, MCInstBuilder(X86::MOV64rr).addReg(ShadowRegI64).addReg(
706 EmitInstruction(Out, MCInstBuilder(X86::SHR64ri)
707 .addReg(ShadowRegI64)
708 .addReg(ShadowRegI64)
712 Inst.setOpcode(X86::MOV8rm);
713 Inst.addOperand(MCOperand::CreateReg(ShadowRegI8));
714 const MCExpr *Disp = MCConstantExpr::Create(kShadowOffset, Ctx);
715 std::unique_ptr<X86Operand> Op(
716 X86Operand::CreateMem(0, Disp, ShadowRegI64, 0, 1, SMLoc(), SMLoc()));
717 Op->addMemOperands(Inst, 5);
718 EmitInstruction(Out, Inst);
722 Out, MCInstBuilder(X86::TEST8rr).addReg(ShadowRegI8).addReg(ShadowRegI8));
723 MCSymbol *DoneSym = Ctx.CreateTempSymbol();
724 const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx);
725 EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr));
727 EmitInstruction(Out, MCInstBuilder(X86::MOV32rr).addReg(ScratchRegI32).addReg(
729 EmitInstruction(Out, MCInstBuilder(X86::AND32ri)
730 .addReg(ScratchRegI32)
731 .addReg(ScratchRegI32)
734 switch (AccessSize) {
739 Inst.setOpcode(X86::LEA32r);
740 Inst.addOperand(MCOperand::CreateReg(ScratchRegI32));
742 const MCExpr *Disp = MCConstantExpr::Create(1, Ctx);
743 std::unique_ptr<X86Operand> Op(
744 X86Operand::CreateMem(0, Disp, ScratchRegI32, 0, 1, SMLoc(), SMLoc()));
745 Op->addMemOperands(Inst, 5);
746 EmitInstruction(Out, Inst);
750 EmitInstruction(Out, MCInstBuilder(X86::ADD32ri8)
751 .addReg(ScratchRegI32)
752 .addReg(ScratchRegI32)
756 assert(false && "Incorrect access size");
762 MCInstBuilder(X86::MOVSX32rr8).addReg(ShadowRegI32).addReg(ShadowRegI8));
763 EmitInstruction(Out, MCInstBuilder(X86::CMP32rr).addReg(ScratchRegI32).addReg(
765 EmitInstruction(Out, MCInstBuilder(X86::JL_4).addExpr(DoneExpr));
767 EmitCallAsanReport(AccessSize, IsWrite, Ctx, Out, RegCtx);
768 EmitLabel(Out, DoneSym);
771 void X86AddressSanitizer64::InstrumentMemOperandLarge(
772 X86Operand &Op, unsigned AccessSize, bool IsWrite,
773 const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) {
774 unsigned AddressRegI64 = RegCtx.addressReg(MVT::i64);
775 unsigned ShadowRegI64 = RegCtx.shadowReg(MVT::i64);
779 Inst.setOpcode(X86::LEA64r);
780 Inst.addOperand(MCOperand::CreateReg(AddressRegI64));
781 Op.addMemOperands(Inst, 5);
782 EmitInstruction(Out, Inst);
784 EmitInstruction(Out, MCInstBuilder(X86::MOV64rr).addReg(ShadowRegI64).addReg(
786 EmitInstruction(Out, MCInstBuilder(X86::SHR64ri)
787 .addReg(ShadowRegI64)
788 .addReg(ShadowRegI64)
792 switch (AccessSize) {
794 Inst.setOpcode(X86::CMP8mi);
797 Inst.setOpcode(X86::CMP16mi);
800 assert(false && "Incorrect access size");
803 const MCExpr *Disp = MCConstantExpr::Create(kShadowOffset, Ctx);
804 std::unique_ptr<X86Operand> Op(
805 X86Operand::CreateMem(0, Disp, ShadowRegI64, 0, 1, SMLoc(), SMLoc()));
806 Op->addMemOperands(Inst, 5);
807 Inst.addOperand(MCOperand::CreateImm(0));
808 EmitInstruction(Out, Inst);
811 MCSymbol *DoneSym = Ctx.CreateTempSymbol();
812 const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx);
813 EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr));
815 EmitCallAsanReport(AccessSize, IsWrite, Ctx, Out, RegCtx);
816 EmitLabel(Out, DoneSym);
819 void X86AddressSanitizer64::InstrumentMOVSImpl(unsigned AccessSize,
824 // No need to test when RCX is equals to zero.
825 MCSymbol *DoneSym = Ctx.CreateTempSymbol();
826 const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx);
828 Out, MCInstBuilder(X86::TEST64rr).addReg(X86::RCX).addReg(X86::RCX));
829 EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr));
831 // Instrument first and last elements in src and dst range.
832 InstrumentMOVSBase(X86::RDI /* DstReg */, X86::RSI /* SrcReg */,
833 X86::RCX /* CntReg */, AccessSize, Ctx, Out);
835 EmitLabel(Out, DoneSym);
839 } // End anonymous namespace
841 X86AsmInstrumentation::X86AsmInstrumentation(const MCSubtargetInfo &STI)
842 : STI(STI), InitialFrameReg(0) {}
844 X86AsmInstrumentation::~X86AsmInstrumentation() {}
846 void X86AsmInstrumentation::InstrumentAndEmitInstruction(
847 const MCInst &Inst, OperandVector &Operands, MCContext &Ctx,
848 const MCInstrInfo &MII, MCStreamer &Out) {
849 EmitInstruction(Out, Inst);
852 void X86AsmInstrumentation::EmitInstruction(MCStreamer &Out,
853 const MCInst &Inst) {
854 Out.EmitInstruction(Inst, STI);
857 unsigned X86AsmInstrumentation::GetFrameRegGeneric(const MCContext &Ctx,
859 if (!Out.getNumFrameInfos()) // No active dwarf frame
860 return X86::NoRegister;
861 const MCDwarfFrameInfo &Frame = Out.getDwarfFrameInfos().back();
862 if (Frame.End) // Active dwarf frame is closed
863 return X86::NoRegister;
864 const MCRegisterInfo *MRI = Ctx.getRegisterInfo();
865 if (!MRI) // No register info
866 return X86::NoRegister;
868 if (InitialFrameReg) {
869 // FrameReg is set explicitly, we're instrumenting a MachineFunction.
870 return InitialFrameReg;
873 return MRI->getLLVMRegNum(Frame.CurrentCfaRegister, true /* IsEH */);
876 X86AsmInstrumentation *
877 CreateX86AsmInstrumentation(const MCTargetOptions &MCOptions,
878 const MCContext &Ctx, const MCSubtargetInfo &STI) {
879 Triple T(STI.getTargetTriple());
880 const bool hasCompilerRTSupport = T.isOSLinux();
881 if (ClAsanInstrumentAssembly && hasCompilerRTSupport &&
882 MCOptions.SanitizeAddress) {
883 if ((STI.getFeatureBits() & X86::Mode32Bit) != 0)
884 return new X86AddressSanitizer32(STI);
885 if ((STI.getFeatureBits() & X86::Mode64Bit) != 0)
886 return new X86AddressSanitizer64(STI);
888 return new X86AsmInstrumentation(STI);
891 } // End llvm namespace