97 static cl::opt<bool> ClAsanInstrumentAssembly(
98 "asan-instrument-assembly",
99 cl::desc(
"instrument assembly with AddressSanitizer checks"),
cl::Hidden,
103 const int64_t MaxAllowedDisplacement = std::numeric_limits<int32_t>::max();
105 int64_t ApplyDisplacementBounds(int64_t Displacement) {
106 return std::max(
std::min(MaxAllowedDisplacement, Displacement),
107 MinAllowedDisplacement);
110 void CheckDisplacementBounds(int64_t Displacement) {
111 assert(Displacement >= MinAllowedDisplacement &&
112 Displacement <= MaxAllowedDisplacement);
115 bool IsStackReg(
unsigned Reg) {
return Reg == X86::RSP || Reg == X86::ESP; }
117 bool IsSmallMemAccess(
unsigned AccessSize) {
return AccessSize < 8; }
119 class X86AddressSanitizer :
public X86AsmInstrumentation {
121 struct RegisterContext {
124 REG_OFFSET_ADDRESS = 0,
130 RegisterContext(
unsigned AddressReg,
unsigned ShadowReg,
131 unsigned ScratchReg) {
132 BusyRegs.push_back(convReg(AddressReg, 64));
133 BusyRegs.push_back(convReg(ShadowReg, 64));
134 BusyRegs.push_back(convReg(ScratchReg, 64));
137 unsigned AddressReg(
unsigned Size)
const {
138 return convReg(BusyRegs[REG_OFFSET_ADDRESS], Size);
141 unsigned ShadowReg(
unsigned Size)
const {
142 return convReg(BusyRegs[REG_OFFSET_SHADOW], Size);
145 unsigned ScratchReg(
unsigned Size)
const {
146 return convReg(BusyRegs[REG_OFFSET_SCRATCH], Size);
149 void AddBusyReg(
unsigned Reg) {
150 if (Reg != X86::NoRegister)
151 BusyRegs.push_back(convReg(Reg, 64));
154 void AddBusyRegs(
const X86Operand &
Op) {
155 AddBusyReg(Op.getMemBaseReg());
156 AddBusyReg(Op.getMemIndexReg());
159 unsigned ChooseFrameReg(
unsigned Size)
const {
160 static const MCPhysReg Candidates[] = { X86::RBP, X86::RAX, X86::RBX,
161 X86::RCX, X86::RDX, X86::RDI,
163 for (
unsigned Reg : Candidates) {
165 return convReg(Reg, Size);
167 return X86::NoRegister;
171 unsigned convReg(
unsigned Reg,
unsigned Size)
const {
175 std::vector<unsigned> BusyRegs;
178 X86AddressSanitizer(
const MCSubtargetInfo *&STI)
179 : X86AsmInstrumentation(STI), RepPrefix(
false), OrigSPOffset(0) {}
181 ~X86AddressSanitizer()
override {}
184 void InstrumentAndEmitInstruction(
const MCInst &Inst,
187 const MCInstrInfo &MII,
188 MCStreamer &Out)
override {
189 InstrumentMOVS(Inst, Operands, Ctx, MII, Out);
191 EmitInstruction(Out, MCInstBuilder(X86::REP_PREFIX));
193 InstrumentMOV(Inst, Operands, Ctx, MII, Out);
195 RepPrefix = (Inst.getOpcode() == X86::REP_PREFIX);
197 EmitInstruction(Out, Inst);
201 virtual void InstrumentMemOperandPrologue(
const RegisterContext &RegCtx,
203 MCStreamer &Out) = 0;
206 virtual void InstrumentMemOperandEpilogue(
const RegisterContext &RegCtx,
208 MCStreamer &Out) = 0;
210 virtual void InstrumentMemOperandSmall(X86Operand &Op,
unsigned AccessSize,
212 const RegisterContext &RegCtx,
213 MCContext &Ctx, MCStreamer &Out) = 0;
214 virtual void InstrumentMemOperandLarge(X86Operand &Op,
unsigned AccessSize,
216 const RegisterContext &RegCtx,
217 MCContext &Ctx, MCStreamer &Out) = 0;
219 virtual void InstrumentMOVSImpl(
unsigned AccessSize, MCContext &Ctx,
220 MCStreamer &Out) = 0;
222 void InstrumentMemOperand(X86Operand &Op,
unsigned AccessSize,
bool IsWrite,
223 const RegisterContext &RegCtx, MCContext &Ctx,
225 void InstrumentMOVSBase(
unsigned DstReg,
unsigned SrcReg,
unsigned CntReg,
226 unsigned AccessSize, MCContext &Ctx, MCStreamer &Out);
228 void InstrumentMOVS(
const MCInst &Inst,
OperandVector &Operands,
229 MCContext &Ctx,
const MCInstrInfo &MII, MCStreamer &Out);
230 void InstrumentMOV(
const MCInst &Inst,
OperandVector &Operands,
231 MCContext &Ctx,
const MCInstrInfo &MII, MCStreamer &Out);
234 void EmitLabel(MCStreamer &Out,
MCSymbol *Label) { Out.EmitLabel(Label); }
236 void EmitLEA(X86Operand &Op,
unsigned Size,
unsigned Reg, MCStreamer &Out) {
237 assert(Size == 32 || Size == 64);
239 Inst.setOpcode(Size == 32 ? X86::LEA32r : X86::LEA64r);
241 Op.addMemOperands(Inst, 5);
242 EmitInstruction(Out, Inst);
245 void ComputeMemOperandAddress(X86Operand &Op,
unsigned Size,
246 unsigned Reg, MCContext &Ctx, MCStreamer &Out);
251 std::unique_ptr<X86Operand> AddDisplacement(X86Operand &Op,
252 int64_t Displacement,
253 MCContext &Ctx, int64_t *Residue);
255 bool is64BitMode()
const {
256 return STI->getFeatureBits()[X86::Mode64Bit];
258 bool is32BitMode()
const {
259 return STI->getFeatureBits()[X86::Mode32Bit];
261 bool is16BitMode()
const {
262 return STI->getFeatureBits()[X86::Mode16Bit];
265 unsigned getPointerWidth() {
266 if (is16BitMode())
return 16;
267 if (is32BitMode())
return 32;
268 if (is64BitMode())
return 64;
276 int64_t OrigSPOffset;
279 void X86AddressSanitizer::InstrumentMemOperand(
280 X86Operand &Op,
unsigned AccessSize,
bool IsWrite,
281 const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) {
282 assert(Op.isMem() &&
"Op should be a memory operand.");
283 assert((AccessSize & (AccessSize - 1)) == 0 && AccessSize <= 16 &&
284 "AccessSize should be a power of two, less or equal than 16.");
286 if (IsSmallMemAccess(AccessSize))
287 InstrumentMemOperandSmall(Op, AccessSize, IsWrite, RegCtx, Ctx, Out);
289 InstrumentMemOperandLarge(Op, AccessSize, IsWrite, RegCtx, Ctx, Out);
292 void X86AddressSanitizer::InstrumentMOVSBase(
unsigned DstReg,
unsigned SrcReg,
295 MCContext &Ctx, MCStreamer &Out) {
298 RegisterContext RegCtx(X86::RDX , X86::RAX ,
299 IsSmallMemAccess(AccessSize)
302 RegCtx.AddBusyReg(DstReg);
303 RegCtx.AddBusyReg(SrcReg);
304 RegCtx.AddBusyReg(CntReg);
306 InstrumentMemOperandPrologue(RegCtx, Ctx, Out);
312 getPointerWidth(), 0, Disp, SrcReg, 0, AccessSize, SMLoc(), SMLoc()));
313 InstrumentMemOperand(*Op, AccessSize,
false , RegCtx, Ctx,
321 getPointerWidth(), 0, Disp, SrcReg, CntReg, AccessSize, SMLoc(),
323 InstrumentMemOperand(*Op, AccessSize,
false , RegCtx, Ctx,
331 getPointerWidth(), 0, Disp, DstReg, 0, AccessSize, SMLoc(), SMLoc()));
332 InstrumentMemOperand(*Op, AccessSize,
true , RegCtx, Ctx, Out);
339 getPointerWidth(), 0, Disp, DstReg, CntReg, AccessSize, SMLoc(),
341 InstrumentMemOperand(*Op, AccessSize,
true , RegCtx, Ctx, Out);
344 InstrumentMemOperandEpilogue(RegCtx, Ctx, Out);
347 void X86AddressSanitizer::InstrumentMOVS(
const MCInst &Inst,
349 MCContext &Ctx,
const MCInstrInfo &MII,
352 unsigned AccessSize = 0;
354 switch (Inst.getOpcode()) {
371 InstrumentMOVSImpl(AccessSize, Ctx, Out);
374 void X86AddressSanitizer::InstrumentMOV(
const MCInst &Inst,
376 const MCInstrInfo &MII,
379 unsigned AccessSize = 0;
381 switch (Inst.getOpcode()) {
412 const bool IsWrite = MII.get(Inst.getOpcode()).mayStore();
414 for (
unsigned Ix = 0; Ix < Operands.size(); ++Ix) {
416 MCParsedAsmOperand &Op = *Operands[Ix];
418 X86Operand &MemOp =
static_cast<X86Operand &
>(
Op);
419 RegisterContext RegCtx(
420 X86::RDI , X86::RAX ,
421 IsSmallMemAccess(AccessSize) ? X86::RCX
423 RegCtx.AddBusyRegs(MemOp);
424 InstrumentMemOperandPrologue(RegCtx, Ctx, Out);
425 InstrumentMemOperand(MemOp, AccessSize, IsWrite, RegCtx, Ctx, Out);
426 InstrumentMemOperandEpilogue(RegCtx, Ctx, Out);
431 void X86AddressSanitizer::ComputeMemOperandAddress(X86Operand &Op,
433 unsigned Reg, MCContext &Ctx,
435 int64_t Displacement = 0;
436 if (IsStackReg(Op.getMemBaseReg()))
437 Displacement -= OrigSPOffset;
438 if (IsStackReg(Op.getMemIndexReg()))
439 Displacement -= OrigSPOffset * Op.getMemScale();
441 assert(Displacement >= 0);
444 if (Displacement == 0) {
445 EmitLEA(Op, Size, Reg, Out);
450 std::unique_ptr<X86Operand> NewOp =
451 AddDisplacement(Op, Displacement, Ctx, &Residue);
452 EmitLEA(*NewOp, Size, Reg, Out);
454 while (Residue != 0) {
455 const MCConstantExpr *Disp =
457 std::unique_ptr<X86Operand> DispOp =
460 EmitLEA(*DispOp, Size, Reg, Out);
461 Residue -= Disp->getValue();
465 std::unique_ptr<X86Operand>
466 X86AddressSanitizer::AddDisplacement(X86Operand &Op, int64_t Displacement,
467 MCContext &Ctx, int64_t *Residue) {
468 assert(Displacement >= 0);
470 if (Displacement == 0 ||
472 *Residue = Displacement;
474 Op.getMemDisp(), Op.getMemBaseReg(),
475 Op.getMemIndexReg(), Op.getMemScale(),
479 int64_t OrigDisplacement =
480 static_cast<const MCConstantExpr *
>(Op.getMemDisp())->getValue();
481 CheckDisplacementBounds(OrigDisplacement);
482 Displacement += OrigDisplacement;
484 int64_t NewDisplacement = ApplyDisplacementBounds(Displacement);
485 CheckDisplacementBounds(NewDisplacement);
487 *Residue = Displacement - NewDisplacement;
490 Op.getMemBaseReg(), Op.getMemIndexReg(),
491 Op.getMemScale(), SMLoc(), SMLoc());
494 class X86AddressSanitizer32 :
public X86AddressSanitizer {
496 static const long kShadowOffset = 0x20000000;
498 X86AddressSanitizer32(
const MCSubtargetInfo *&STI)
499 : X86AddressSanitizer(STI) {}
501 ~X86AddressSanitizer32()
override {}
503 unsigned GetFrameReg(
const MCContext &Ctx, MCStreamer &Out) {
504 unsigned FrameReg = GetFrameRegGeneric(Ctx, Out);
505 if (FrameReg == X86::NoRegister)
510 void SpillReg(MCStreamer &Out,
unsigned Reg) {
511 EmitInstruction(Out, MCInstBuilder(X86::PUSH32r).addReg(Reg));
515 void RestoreReg(MCStreamer &Out,
unsigned Reg) {
516 EmitInstruction(Out, MCInstBuilder(X86::POP32r).addReg(Reg));
520 void StoreFlags(MCStreamer &Out) {
521 EmitInstruction(Out, MCInstBuilder(X86::PUSHF32));
525 void RestoreFlags(MCStreamer &Out) {
526 EmitInstruction(Out, MCInstBuilder(X86::POPF32));
530 void InstrumentMemOperandPrologue(
const RegisterContext &RegCtx,
532 MCStreamer &Out)
override {
533 unsigned LocalFrameReg = RegCtx.ChooseFrameReg(32);
534 assert(LocalFrameReg != X86::NoRegister);
536 const MCRegisterInfo *
MRI = Ctx.getRegisterInfo();
537 unsigned FrameReg = GetFrameReg(Ctx, Out);
538 if (MRI && FrameReg != X86::NoRegister) {
539 SpillReg(Out, LocalFrameReg);
540 if (FrameReg == X86::ESP) {
541 Out.EmitCFIAdjustCfaOffset(4 );
542 Out.EmitCFIRelOffset(
543 MRI->getDwarfRegNum(LocalFrameReg,
true ), 0);
547 MCInstBuilder(X86::MOV32rr).addReg(LocalFrameReg).addReg(FrameReg));
548 Out.EmitCFIRememberState();
549 Out.EmitCFIDefCfaRegister(
550 MRI->getDwarfRegNum(LocalFrameReg,
true ));
553 SpillReg(Out, RegCtx.AddressReg(32));
554 SpillReg(Out, RegCtx.ShadowReg(32));
555 if (RegCtx.ScratchReg(32) != X86::NoRegister)
556 SpillReg(Out, RegCtx.ScratchReg(32));
560 void InstrumentMemOperandEpilogue(
const RegisterContext &RegCtx,
562 MCStreamer &Out)
override {
563 unsigned LocalFrameReg = RegCtx.ChooseFrameReg(32);
564 assert(LocalFrameReg != X86::NoRegister);
567 if (RegCtx.ScratchReg(32) != X86::NoRegister)
568 RestoreReg(Out, RegCtx.ScratchReg(32));
569 RestoreReg(Out, RegCtx.ShadowReg(32));
570 RestoreReg(Out, RegCtx.AddressReg(32));
572 unsigned FrameReg = GetFrameReg(Ctx, Out);
573 if (Ctx.getRegisterInfo() && FrameReg != X86::NoRegister) {
574 RestoreReg(Out, LocalFrameReg);
575 Out.EmitCFIRestoreState();
576 if (FrameReg == X86::ESP)
577 Out.EmitCFIAdjustCfaOffset(-4 );
581 void InstrumentMemOperandSmall(X86Operand &Op,
unsigned AccessSize,
583 const RegisterContext &RegCtx,
585 MCStreamer &Out)
override;
586 void InstrumentMemOperandLarge(X86Operand &Op,
unsigned AccessSize,
588 const RegisterContext &RegCtx,
590 MCStreamer &Out)
override;
591 void InstrumentMOVSImpl(
unsigned AccessSize, MCContext &Ctx,
592 MCStreamer &Out)
override;
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 Out, MCInstBuilder(X86::PUSH32r).addReg(RegCtx.AddressReg(32)));
608 (IsWrite ?
"store" :
"load") +
610 const MCSymbolRefExpr *FnExpr =
612 EmitInstruction(Out, MCInstBuilder(X86::CALLpcrel32).addExpr(FnExpr));
616 void X86AddressSanitizer32::InstrumentMemOperandSmall(
617 X86Operand &Op,
unsigned AccessSize,
bool IsWrite,
618 const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) {
619 unsigned AddressRegI32 = RegCtx.AddressReg(32);
620 unsigned ShadowRegI32 = RegCtx.ShadowReg(32);
621 unsigned ShadowRegI8 = RegCtx.ShadowReg(8);
623 assert(RegCtx.ScratchReg(32) != X86::NoRegister);
624 unsigned ScratchRegI32 = RegCtx.ScratchReg(32);
626 ComputeMemOperandAddress(Op, 32, AddressRegI32, Ctx, Out);
628 EmitInstruction(Out, MCInstBuilder(X86::MOV32rr).addReg(ShadowRegI32).addReg(
630 EmitInstruction(Out, MCInstBuilder(X86::SHR32ri)
631 .addReg(ShadowRegI32)
632 .addReg(ShadowRegI32)
637 Inst.setOpcode(X86::MOV8rm);
640 std::unique_ptr<X86Operand>
Op(
643 Op->addMemOperands(Inst, 5);
644 EmitInstruction(Out, Inst);
648 Out, MCInstBuilder(X86::TEST8rr).addReg(ShadowRegI8).addReg(ShadowRegI8));
649 MCSymbol *DoneSym = Ctx.createTempSymbol();
651 EmitInstruction(Out, MCInstBuilder(X86::JE_1).addExpr(DoneExpr));
653 EmitInstruction(Out, MCInstBuilder(X86::MOV32rr).addReg(ScratchRegI32).addReg(
655 EmitInstruction(Out, MCInstBuilder(X86::AND32ri)
656 .addReg(ScratchRegI32)
657 .addReg(ScratchRegI32)
660 switch (AccessSize) {
666 std::unique_ptr<X86Operand>
Op(
669 EmitLEA(*Op, 32, ScratchRegI32, Out);
673 EmitInstruction(Out, MCInstBuilder(X86::ADD32ri8)
674 .addReg(ScratchRegI32)
675 .addReg(ScratchRegI32)
682 MCInstBuilder(X86::MOVSX32rr8).addReg(ShadowRegI32).addReg(ShadowRegI8));
683 EmitInstruction(Out, MCInstBuilder(X86::CMP32rr).addReg(ScratchRegI32).addReg(
685 EmitInstruction(Out, MCInstBuilder(X86::JL_1).addExpr(DoneExpr));
687 EmitCallAsanReport(AccessSize, IsWrite, Ctx, Out, RegCtx);
688 EmitLabel(Out, DoneSym);
691 void X86AddressSanitizer32::InstrumentMemOperandLarge(
692 X86Operand &Op,
unsigned AccessSize,
bool IsWrite,
693 const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) {
694 unsigned AddressRegI32 = RegCtx.AddressReg(32);
695 unsigned ShadowRegI32 = RegCtx.ShadowReg(32);
697 ComputeMemOperandAddress(Op, 32, AddressRegI32, Ctx, Out);
699 EmitInstruction(Out, MCInstBuilder(X86::MOV32rr).addReg(ShadowRegI32).addReg(
701 EmitInstruction(Out, MCInstBuilder(X86::SHR32ri)
702 .addReg(ShadowRegI32)
703 .addReg(ShadowRegI32)
707 switch (AccessSize) {
710 Inst.setOpcode(X86::CMP8mi);
713 Inst.setOpcode(X86::CMP16mi);
717 std::unique_ptr<X86Operand>
Op(
720 Op->addMemOperands(Inst, 5);
722 EmitInstruction(Out, Inst);
724 MCSymbol *DoneSym = Ctx.createTempSymbol();
726 EmitInstruction(Out, MCInstBuilder(X86::JE_1).addExpr(DoneExpr));
728 EmitCallAsanReport(AccessSize, IsWrite, Ctx, Out, RegCtx);
729 EmitLabel(Out, DoneSym);
732 void X86AddressSanitizer32::InstrumentMOVSImpl(
unsigned AccessSize,
738 MCSymbol *DoneSym = Ctx.createTempSymbol();
741 Out, MCInstBuilder(X86::TEST32rr).addReg(X86::ECX).addReg(X86::ECX));
742 EmitInstruction(Out, MCInstBuilder(X86::JE_1).addExpr(DoneExpr));
745 InstrumentMOVSBase(X86::EDI , X86::ESI ,
746 X86::ECX , AccessSize, Ctx, Out);
748 EmitLabel(Out, DoneSym);
752 class X86AddressSanitizer64 :
public X86AddressSanitizer {
754 static const long kShadowOffset = 0x7fff8000;
756 X86AddressSanitizer64(
const MCSubtargetInfo *&STI)
757 : X86AddressSanitizer(STI) {}
759 ~X86AddressSanitizer64()
override {}
761 unsigned GetFrameReg(
const MCContext &Ctx, MCStreamer &Out) {
762 unsigned FrameReg = GetFrameRegGeneric(Ctx, Out);
763 if (FrameReg == X86::NoRegister)
768 void SpillReg(MCStreamer &Out,
unsigned Reg) {
769 EmitInstruction(Out, MCInstBuilder(X86::PUSH64r).addReg(Reg));
773 void RestoreReg(MCStreamer &Out,
unsigned Reg) {
774 EmitInstruction(Out, MCInstBuilder(X86::POP64r).addReg(Reg));
778 void StoreFlags(MCStreamer &Out) {
779 EmitInstruction(Out, MCInstBuilder(X86::PUSHF64));
783 void RestoreFlags(MCStreamer &Out) {
784 EmitInstruction(Out, MCInstBuilder(X86::POPF64));
788 void InstrumentMemOperandPrologue(
const RegisterContext &RegCtx,
790 MCStreamer &Out)
override {
791 unsigned LocalFrameReg = RegCtx.ChooseFrameReg(64);
792 assert(LocalFrameReg != X86::NoRegister);
794 const MCRegisterInfo *MRI = Ctx.getRegisterInfo();
795 unsigned FrameReg = GetFrameReg(Ctx, Out);
796 if (MRI && FrameReg != X86::NoRegister) {
797 SpillReg(Out, X86::RBP);
798 if (FrameReg == X86::RSP) {
799 Out.EmitCFIAdjustCfaOffset(8 );
800 Out.EmitCFIRelOffset(
801 MRI->getDwarfRegNum(LocalFrameReg,
true ), 0);
805 MCInstBuilder(X86::MOV64rr).addReg(LocalFrameReg).addReg(FrameReg));
806 Out.EmitCFIRememberState();
807 Out.EmitCFIDefCfaRegister(
808 MRI->getDwarfRegNum(LocalFrameReg,
true ));
811 EmitAdjustRSP(Ctx, Out, -128);
812 SpillReg(Out, RegCtx.ShadowReg(64));
813 SpillReg(Out, RegCtx.AddressReg(64));
814 if (RegCtx.ScratchReg(64) != X86::NoRegister)
815 SpillReg(Out, RegCtx.ScratchReg(64));
819 void InstrumentMemOperandEpilogue(
const RegisterContext &RegCtx,
821 MCStreamer &Out)
override {
822 unsigned LocalFrameReg = RegCtx.ChooseFrameReg(64);
823 assert(LocalFrameReg != X86::NoRegister);
826 if (RegCtx.ScratchReg(64) != X86::NoRegister)
827 RestoreReg(Out, RegCtx.ScratchReg(64));
828 RestoreReg(Out, RegCtx.AddressReg(64));
829 RestoreReg(Out, RegCtx.ShadowReg(64));
830 EmitAdjustRSP(Ctx, Out, 128);
832 unsigned FrameReg = GetFrameReg(Ctx, Out);
833 if (Ctx.getRegisterInfo() && FrameReg != X86::NoRegister) {
834 RestoreReg(Out, LocalFrameReg);
835 Out.EmitCFIRestoreState();
836 if (FrameReg == X86::RSP)
837 Out.EmitCFIAdjustCfaOffset(-8 );
841 void InstrumentMemOperandSmall(X86Operand &Op,
unsigned AccessSize,
843 const RegisterContext &RegCtx,
845 MCStreamer &Out)
override;
846 void InstrumentMemOperandLarge(X86Operand &Op,
unsigned AccessSize,
848 const RegisterContext &RegCtx,
850 MCStreamer &Out)
override;
851 void InstrumentMOVSImpl(
unsigned AccessSize, MCContext &Ctx,
852 MCStreamer &Out)
override;
855 void EmitAdjustRSP(MCContext &Ctx, MCStreamer &Out,
long Offset) {
857 std::unique_ptr<X86Operand>
Op(
860 EmitLEA(*Op, 64, X86::RSP, Out);
864 void EmitCallAsanReport(
unsigned AccessSize,
bool IsWrite, MCContext &Ctx,
865 MCStreamer &Out,
const RegisterContext &RegCtx) {
866 EmitInstruction(Out, MCInstBuilder(X86::CLD));
867 EmitInstruction(Out, MCInstBuilder(X86::MMX_EMMS));
869 EmitInstruction(Out, MCInstBuilder(X86::AND64ri8)
874 if (RegCtx.AddressReg(64) != X86::RDI) {
875 EmitInstruction(Out, MCInstBuilder(X86::MOV64rr).addReg(X86::RDI).addReg(
876 RegCtx.AddressReg(64)));
879 (IsWrite ?
"store" :
"load") +
881 const MCSymbolRefExpr *FnExpr =
883 EmitInstruction(Out, MCInstBuilder(X86::CALL64pcrel32).addExpr(FnExpr));
887 void X86AddressSanitizer64::InstrumentMemOperandSmall(
888 X86Operand &Op,
unsigned AccessSize,
bool IsWrite,
889 const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) {
890 unsigned AddressRegI64 = RegCtx.AddressReg(64);
891 unsigned AddressRegI32 = RegCtx.AddressReg(32);
892 unsigned ShadowRegI64 = RegCtx.ShadowReg(64);
893 unsigned ShadowRegI32 = RegCtx.ShadowReg(32);
894 unsigned ShadowRegI8 = RegCtx.ShadowReg(8);
896 assert(RegCtx.ScratchReg(32) != X86::NoRegister);
897 unsigned ScratchRegI32 = RegCtx.ScratchReg(32);
899 ComputeMemOperandAddress(Op, 64, AddressRegI64, Ctx, Out);
901 EmitInstruction(Out, MCInstBuilder(X86::MOV64rr).addReg(ShadowRegI64).addReg(
903 EmitInstruction(Out, MCInstBuilder(X86::SHR64ri)
904 .addReg(ShadowRegI64)
905 .addReg(ShadowRegI64)
909 Inst.setOpcode(X86::MOV8rm);
912 std::unique_ptr<X86Operand>
Op(
915 Op->addMemOperands(Inst, 5);
916 EmitInstruction(Out, Inst);
920 Out, MCInstBuilder(X86::TEST8rr).addReg(ShadowRegI8).addReg(ShadowRegI8));
921 MCSymbol *DoneSym = Ctx.createTempSymbol();
923 EmitInstruction(Out, MCInstBuilder(X86::JE_1).addExpr(DoneExpr));
925 EmitInstruction(Out, MCInstBuilder(X86::MOV32rr).addReg(ScratchRegI32).addReg(
927 EmitInstruction(Out, MCInstBuilder(X86::AND32ri)
928 .addReg(ScratchRegI32)
929 .addReg(ScratchRegI32)
932 switch (AccessSize) {
938 std::unique_ptr<X86Operand>
Op(
941 EmitLEA(*Op, 32, ScratchRegI32, Out);
945 EmitInstruction(Out, MCInstBuilder(X86::ADD32ri8)
946 .addReg(ScratchRegI32)
947 .addReg(ScratchRegI32)
954 MCInstBuilder(X86::MOVSX32rr8).addReg(ShadowRegI32).addReg(ShadowRegI8));
955 EmitInstruction(Out, MCInstBuilder(X86::CMP32rr).addReg(ScratchRegI32).addReg(
957 EmitInstruction(Out, MCInstBuilder(X86::JL_1).addExpr(DoneExpr));
959 EmitCallAsanReport(AccessSize, IsWrite, Ctx, Out, RegCtx);
960 EmitLabel(Out, DoneSym);
963 void X86AddressSanitizer64::InstrumentMemOperandLarge(
964 X86Operand &Op,
unsigned AccessSize,
bool IsWrite,
965 const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) {
966 unsigned AddressRegI64 = RegCtx.AddressReg(64);
967 unsigned ShadowRegI64 = RegCtx.ShadowReg(64);
969 ComputeMemOperandAddress(Op, 64, AddressRegI64, Ctx, Out);
971 EmitInstruction(Out, MCInstBuilder(X86::MOV64rr).addReg(ShadowRegI64).addReg(
973 EmitInstruction(Out, MCInstBuilder(X86::SHR64ri)
974 .addReg(ShadowRegI64)
975 .addReg(ShadowRegI64)
979 switch (AccessSize) {
982 Inst.setOpcode(X86::CMP8mi);
985 Inst.setOpcode(X86::CMP16mi);
989 std::unique_ptr<X86Operand>
Op(
992 Op->addMemOperands(Inst, 5);
994 EmitInstruction(Out, Inst);
997 MCSymbol *DoneSym = Ctx.createTempSymbol();
999 EmitInstruction(Out, MCInstBuilder(X86::JE_1).addExpr(DoneExpr));
1001 EmitCallAsanReport(AccessSize, IsWrite, Ctx, Out, RegCtx);
1002 EmitLabel(Out, DoneSym);
1005 void X86AddressSanitizer64::InstrumentMOVSImpl(
unsigned AccessSize,
1011 MCSymbol *DoneSym = Ctx.createTempSymbol();
1014 Out, MCInstBuilder(X86::TEST64rr).addReg(X86::RCX).addReg(X86::RCX));
1015 EmitInstruction(Out, MCInstBuilder(X86::JE_1).addExpr(DoneExpr));
1018 InstrumentMOVSBase(X86::RDI , X86::RSI ,
1019 X86::RCX , AccessSize, Ctx, Out);
1021 EmitLabel(Out, DoneSym);
1028 : STI(STI), InitialFrameReg(0) {}
1046 return X86::NoRegister;
1049 return X86::NoRegister;
1052 return X86::NoRegister;
1066 const bool hasCompilerRTSupport =
T.isOSLinux();
1067 if (ClAsanInstrumentAssembly && hasCompilerRTSupport &&
1070 return new X86AddressSanitizer32(STI);
1072 return new X86AddressSanitizer64(STI);
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
bool SanitizeAddress
Enables AddressSanitizer instrumentation at machine level.
static std::unique_ptr< X86Operand > CreateMem(unsigned ModeSize, const MCExpr *Disp, SMLoc StartLoc, SMLoc EndLoc, unsigned Size=0, StringRef SymName=StringRef(), void *OpDecl=nullptr)
Create an absolute memory operand.
unsigned CurrentCfaRegister
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
ArrayRef< MCDwarfFrameInfo > getDwarfFrameInfos() const
virtual void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI)
Emit the given Instruction into the current section.
unsigned GetFrameRegGeneric(const MCContext &Ctx, MCStreamer &Out)
static MCOperand createReg(unsigned Reg)
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Reg
All possible values of the reg field in the ModR/M byte.
Context object for machine code objects.
Function Alias Analysis false
auto count(R &&Range, const E &Element) -> typename std::iterator_traits< decltype(std::begin(Range))>::difference_type
Wrapper function around std::count to count the number of times an element Element occurs in the give...
Instances of this class represent a single low-level machine instruction.
Maximum length of the test input libFuzzer tries to guess a good value based on the corpus and reports it always prefer smaller inputs during the corpus shuffle When libFuzzer itself reports a bug this exit code will be used If indicates the maximal total time in seconds to run the fuzzer minimizes the provided crash input Use with etc Experimental Use value profile to guide fuzzing Number of simultaneous worker processes to run the jobs If min(jobs, NumberOfCpuCores()/2)\" is used.") FUZZER_FLAG_INT(reload
virtual void InstrumentAndEmitInstruction(const MCInst &Inst, SmallVectorImpl< std::unique_ptr< MCParsedAsmOperand > > &Operands, MCContext &Ctx, const MCInstrInfo &MII, MCStreamer &Out)
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
void EmitInstruction(MCStreamer &Out, const MCInst &Inst)
initializer< Ty > init(const Ty &Val)
Streaming machine code generation interface.
unsigned const MachineRegisterInfo * MRI
X86AsmInstrumentation(const MCSubtargetInfo *&STI)
Interface to description of machine instruction set.
int getLLVMRegNum(unsigned RegNum, bool isEH) const
Map a dwarf register back to a target register.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Triple - Helper class for working with autoconf configuration names.
X86AsmInstrumentation * CreateX86AsmInstrumentation(const MCTargetOptions &MCOptions, const MCContext &Ctx, const MCSubtargetInfo *&STI)
const FeatureBitset & getFeatureBits() const
getFeatureBits - Return the feature bits.
unsigned getX86SubSuperRegister(unsigned, unsigned, bool High=false)
Returns the sub or super register of a specific X86 register.
const MCRegisterInfo * getRegisterInfo() const
unsigned getNumFrameInfos()
MCSubtargetInfo - Generic base class for all target subtargets.
const Triple & getTargetTriple() const
getTargetTriple - Return the target triple string.
virtual ~X86AsmInstrumentation()
const MCSubtargetInfo *& STI
SmallVectorImpl< std::unique_ptr< MCParsedAsmOperand > > OperandVector
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static MCOperand createImm(int64_t Val)
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx)