LLVM API Documentation

X86AsmInstrumentation.cpp
Go to the documentation of this file.
00001 //===-- X86AsmInstrumentation.cpp - Instrument X86 inline assembly C++ -*-===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 
00010 #include "MCTargetDesc/X86BaseInfo.h"
00011 #include "X86AsmInstrumentation.h"
00012 #include "X86Operand.h"
00013 #include "X86RegisterInfo.h"
00014 #include "llvm/ADT/StringExtras.h"
00015 #include "llvm/ADT/Triple.h"
00016 #include "llvm/CodeGen/MachineValueType.h"
00017 #include "llvm/IR/Function.h"
00018 #include "llvm/MC/MCContext.h"
00019 #include "llvm/MC/MCInst.h"
00020 #include "llvm/MC/MCInstBuilder.h"
00021 #include "llvm/MC/MCInstrInfo.h"
00022 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
00023 #include "llvm/MC/MCStreamer.h"
00024 #include "llvm/MC/MCSubtargetInfo.h"
00025 #include "llvm/MC/MCTargetAsmParser.h"
00026 #include "llvm/MC/MCTargetOptions.h"
00027 #include "llvm/Support/CommandLine.h"
00028 
00029 namespace llvm {
00030 namespace {
00031 
00032 static cl::opt<bool> ClAsanInstrumentAssembly(
00033     "asan-instrument-assembly",
00034     cl::desc("instrument assembly with AddressSanitizer checks"), cl::Hidden,
00035     cl::init(false));
00036 
00037 bool IsStackReg(unsigned Reg) {
00038   return Reg == X86::RSP || Reg == X86::ESP || Reg == X86::SP;
00039 }
00040 
00041 bool IsSmallMemAccess(unsigned AccessSize) { return AccessSize < 8; }
00042 
00043 std::string FuncName(unsigned AccessSize, bool IsWrite) {
00044   return std::string("__asan_report_") + (IsWrite ? "store" : "load") +
00045          utostr(AccessSize);
00046 }
00047 
00048 class X86AddressSanitizer : public X86AsmInstrumentation {
00049 public:
00050   struct RegisterContext {
00051     RegisterContext(unsigned AddressReg, unsigned ShadowReg,
00052                     unsigned ScratchReg)
00053         : AddressReg(AddressReg), ShadowReg(ShadowReg), ScratchReg(ScratchReg) {
00054     }
00055 
00056     unsigned addressReg(MVT::SimpleValueType VT) const {
00057       return getX86SubSuperRegister(AddressReg, VT);
00058     }
00059 
00060     unsigned shadowReg(MVT::SimpleValueType VT) const {
00061       return getX86SubSuperRegister(ShadowReg, VT);
00062     }
00063 
00064     unsigned scratchReg(MVT::SimpleValueType VT) const {
00065       return getX86SubSuperRegister(ScratchReg, VT);
00066     }
00067 
00068     const unsigned AddressReg;
00069     const unsigned ShadowReg;
00070     const unsigned ScratchReg;
00071   };
00072 
00073   X86AddressSanitizer(const MCSubtargetInfo &STI)
00074       : X86AsmInstrumentation(STI), RepPrefix(false) {}
00075   virtual ~X86AddressSanitizer() {}
00076 
00077   // X86AsmInstrumentation implementation:
00078   virtual void InstrumentAndEmitInstruction(const MCInst &Inst,
00079                                             OperandVector &Operands,
00080                                             MCContext &Ctx,
00081                                             const MCInstrInfo &MII,
00082                                             MCStreamer &Out) override {
00083     InstrumentMOVS(Inst, Operands, Ctx, MII, Out);
00084     if (RepPrefix)
00085       EmitInstruction(Out, MCInstBuilder(X86::REP_PREFIX));
00086 
00087     InstrumentMOV(Inst, Operands, Ctx, MII, Out);
00088 
00089     RepPrefix = (Inst.getOpcode() == X86::REP_PREFIX);
00090     if (!RepPrefix)
00091       EmitInstruction(Out, Inst);
00092   }
00093 
00094   // Should be implemented differently in x86_32 and x86_64 subclasses.
00095   virtual void StoreFlags(MCStreamer &Out) = 0;
00096 
00097   virtual void RestoreFlags(MCStreamer &Out) = 0;
00098 
00099   // Adjusts up stack and saves all registers used in instrumentation.
00100   virtual void InstrumentMemOperandPrologue(const RegisterContext &RegCtx,
00101                                             MCContext &Ctx,
00102                                             MCStreamer &Out) = 0;
00103 
00104   // Restores all registers used in instrumentation and adjusts stack.
00105   virtual void InstrumentMemOperandEpilogue(const RegisterContext &RegCtx,
00106                                             MCContext &Ctx,
00107                                             MCStreamer &Out) = 0;
00108 
00109   virtual void InstrumentMemOperandSmall(X86Operand &Op, unsigned AccessSize,
00110                                          bool IsWrite,
00111                                          const RegisterContext &RegCtx,
00112                                          MCContext &Ctx, MCStreamer &Out) = 0;
00113   virtual void InstrumentMemOperandLarge(X86Operand &Op, unsigned AccessSize,
00114                                          bool IsWrite,
00115                                          const RegisterContext &RegCtx,
00116                                          MCContext &Ctx, MCStreamer &Out) = 0;
00117 
00118   virtual void InstrumentMOVSImpl(unsigned AccessSize, MCContext &Ctx,
00119                                   MCStreamer &Out) = 0;
00120 
00121   void InstrumentMemOperand(X86Operand &Op, unsigned AccessSize, bool IsWrite,
00122                             const RegisterContext &RegCtx, MCContext &Ctx,
00123                             MCStreamer &Out);
00124   void InstrumentMOVSBase(unsigned DstReg, unsigned SrcReg, unsigned CntReg,
00125                           unsigned AccessSize, MCContext &Ctx, MCStreamer &Out);
00126 
00127   void InstrumentMOVS(const MCInst &Inst, OperandVector &Operands,
00128                       MCContext &Ctx, const MCInstrInfo &MII, MCStreamer &Out);
00129   void InstrumentMOV(const MCInst &Inst, OperandVector &Operands,
00130                      MCContext &Ctx, const MCInstrInfo &MII, MCStreamer &Out);
00131 
00132 protected:
00133   void EmitLabel(MCStreamer &Out, MCSymbol *Label) { Out.EmitLabel(Label); }
00134 
00135   // True when previous instruction was actually REP prefix.
00136   bool RepPrefix;
00137 };
00138 
00139 void X86AddressSanitizer::InstrumentMemOperand(
00140     X86Operand &Op, unsigned AccessSize, bool IsWrite,
00141     const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) {
00142   assert(Op.isMem() && "Op should be a memory operand.");
00143   assert((AccessSize & (AccessSize - 1)) == 0 && AccessSize <= 16 &&
00144          "AccessSize should be a power of two, less or equal than 16.");
00145   // FIXME: take into account load/store alignment.
00146   if (IsSmallMemAccess(AccessSize))
00147     InstrumentMemOperandSmall(Op, AccessSize, IsWrite, RegCtx, Ctx, Out);
00148   else
00149     InstrumentMemOperandLarge(Op, AccessSize, IsWrite, RegCtx, Ctx, Out);
00150 }
00151 
00152 void X86AddressSanitizer::InstrumentMOVSBase(unsigned DstReg, unsigned SrcReg,
00153                                              unsigned CntReg,
00154                                              unsigned AccessSize,
00155                                              MCContext &Ctx, MCStreamer &Out) {
00156   // FIXME: check whole ranges [DstReg .. DstReg + AccessSize * (CntReg - 1)]
00157   // and [SrcReg .. SrcReg + AccessSize * (CntReg - 1)].
00158   RegisterContext RegCtx(X86::RDX /* AddressReg */, X86::RAX /* ShadowReg */,
00159                          IsSmallMemAccess(AccessSize)
00160                              ? X86::RBX
00161                              : X86::NoRegister /* ScratchReg */);
00162 
00163   InstrumentMemOperandPrologue(RegCtx, Ctx, Out);
00164 
00165   // Test (%SrcReg)
00166   {
00167     const MCExpr *Disp = MCConstantExpr::Create(0, Ctx);
00168     std::unique_ptr<X86Operand> Op(X86Operand::CreateMem(
00169         0, Disp, SrcReg, 0, AccessSize, SMLoc(), SMLoc()));
00170     InstrumentMemOperand(*Op, AccessSize, false /* IsWrite */, RegCtx, Ctx,
00171                          Out);
00172   }
00173 
00174   // Test -1(%SrcReg, %CntReg, AccessSize)
00175   {
00176     const MCExpr *Disp = MCConstantExpr::Create(-1, Ctx);
00177     std::unique_ptr<X86Operand> Op(X86Operand::CreateMem(
00178         0, Disp, SrcReg, CntReg, AccessSize, SMLoc(), SMLoc()));
00179     InstrumentMemOperand(*Op, AccessSize, false /* IsWrite */, RegCtx, Ctx,
00180                          Out);
00181   }
00182 
00183   // Test (%DstReg)
00184   {
00185     const MCExpr *Disp = MCConstantExpr::Create(0, Ctx);
00186     std::unique_ptr<X86Operand> Op(X86Operand::CreateMem(
00187         0, Disp, DstReg, 0, AccessSize, SMLoc(), SMLoc()));
00188     InstrumentMemOperand(*Op, AccessSize, true /* IsWrite */, RegCtx, Ctx, Out);
00189   }
00190 
00191   // Test -1(%DstReg, %CntReg, AccessSize)
00192   {
00193     const MCExpr *Disp = MCConstantExpr::Create(-1, Ctx);
00194     std::unique_ptr<X86Operand> Op(X86Operand::CreateMem(
00195         0, Disp, DstReg, CntReg, AccessSize, SMLoc(), SMLoc()));
00196     InstrumentMemOperand(*Op, AccessSize, true /* IsWrite */, RegCtx, Ctx, Out);
00197   }
00198 
00199   InstrumentMemOperandEpilogue(RegCtx, Ctx, Out);
00200 }
00201 
00202 void X86AddressSanitizer::InstrumentMOVS(const MCInst &Inst,
00203                                          OperandVector &Operands,
00204                                          MCContext &Ctx, const MCInstrInfo &MII,
00205                                          MCStreamer &Out) {
00206   // Access size in bytes.
00207   unsigned AccessSize = 0;
00208 
00209   switch (Inst.getOpcode()) {
00210   case X86::MOVSB:
00211     AccessSize = 1;
00212     break;
00213   case X86::MOVSW:
00214     AccessSize = 2;
00215     break;
00216   case X86::MOVSL:
00217     AccessSize = 4;
00218     break;
00219   case X86::MOVSQ:
00220     AccessSize = 8;
00221     break;
00222   default:
00223     return;
00224   }
00225 
00226   InstrumentMOVSImpl(AccessSize, Ctx, Out);
00227 }
00228 
00229 void X86AddressSanitizer::InstrumentMOV(const MCInst &Inst,
00230                                         OperandVector &Operands, MCContext &Ctx,
00231                                         const MCInstrInfo &MII,
00232                                         MCStreamer &Out) {
00233   // Access size in bytes.
00234   unsigned AccessSize = 0;
00235 
00236   switch (Inst.getOpcode()) {
00237   case X86::MOV8mi:
00238   case X86::MOV8mr:
00239   case X86::MOV8rm:
00240     AccessSize = 1;
00241     break;
00242   case X86::MOV16mi:
00243   case X86::MOV16mr:
00244   case X86::MOV16rm:
00245     AccessSize = 2;
00246     break;
00247   case X86::MOV32mi:
00248   case X86::MOV32mr:
00249   case X86::MOV32rm:
00250     AccessSize = 4;
00251     break;
00252   case X86::MOV64mi32:
00253   case X86::MOV64mr:
00254   case X86::MOV64rm:
00255     AccessSize = 8;
00256     break;
00257   case X86::MOVAPDmr:
00258   case X86::MOVAPSmr:
00259   case X86::MOVAPDrm:
00260   case X86::MOVAPSrm:
00261     AccessSize = 16;
00262     break;
00263   default:
00264     return;
00265   }
00266 
00267   const bool IsWrite = MII.get(Inst.getOpcode()).mayStore();
00268   RegisterContext RegCtx(X86::RDI /* AddressReg */, X86::RAX /* ShadowReg */,
00269                          IsSmallMemAccess(AccessSize)
00270                              ? X86::RCX
00271                              : X86::NoRegister /* ScratchReg */);
00272 
00273   for (unsigned Ix = 0; Ix < Operands.size(); ++Ix) {
00274     assert(Operands[Ix]);
00275     MCParsedAsmOperand &Op = *Operands[Ix];
00276     if (Op.isMem()) {
00277       X86Operand &MemOp = static_cast<X86Operand &>(Op);
00278       // FIXME: get rid of this limitation.
00279       if (IsStackReg(MemOp.getMemBaseReg()) ||
00280           IsStackReg(MemOp.getMemIndexReg())) {
00281         continue;
00282       }
00283 
00284       InstrumentMemOperandPrologue(RegCtx, Ctx, Out);
00285       InstrumentMemOperand(MemOp, AccessSize, IsWrite, RegCtx, Ctx, Out);
00286       InstrumentMemOperandEpilogue(RegCtx, Ctx, Out);
00287     }
00288   }
00289 }
00290 
00291 class X86AddressSanitizer32 : public X86AddressSanitizer {
00292 public:
00293   static const long kShadowOffset = 0x20000000;
00294 
00295   X86AddressSanitizer32(const MCSubtargetInfo &STI)
00296       : X86AddressSanitizer(STI) {}
00297 
00298   virtual ~X86AddressSanitizer32() {}
00299 
00300   virtual void StoreFlags(MCStreamer &Out) override {
00301     EmitInstruction(Out, MCInstBuilder(X86::PUSHF32));
00302   }
00303 
00304   virtual void RestoreFlags(MCStreamer &Out) override {
00305     EmitInstruction(Out, MCInstBuilder(X86::POPF32));
00306   }
00307 
00308   virtual void InstrumentMemOperandPrologue(const RegisterContext &RegCtx,
00309                                             MCContext &Ctx,
00310                                             MCStreamer &Out) override {
00311     const MCRegisterInfo* MRI = Ctx.getRegisterInfo();
00312     if (MRI && FrameReg != X86::NoRegister) {
00313       EmitInstruction(
00314           Out, MCInstBuilder(X86::PUSH32r).addReg(X86::EBP));
00315       if (FrameReg == X86::ESP) {
00316         Out.EmitCFIAdjustCfaOffset(4 /* byte size of the FrameReg */);
00317         Out.EmitCFIRelOffset(
00318             MRI->getDwarfRegNum(X86::EBP, true /* IsEH */), 0);
00319       }
00320       EmitInstruction(
00321           Out, MCInstBuilder(X86::MOV32rr).addReg(X86::EBP).addReg(FrameReg));
00322       Out.EmitCFIRememberState();
00323       Out.EmitCFIDefCfaRegister(
00324           MRI->getDwarfRegNum(X86::EBP, true /* IsEH */));
00325     }
00326 
00327     EmitInstruction(
00328         Out, MCInstBuilder(X86::PUSH32r).addReg(RegCtx.addressReg(MVT::i32)));
00329     EmitInstruction(
00330         Out, MCInstBuilder(X86::PUSH32r).addReg(RegCtx.shadowReg(MVT::i32)));
00331     if (RegCtx.ScratchReg != X86::NoRegister) {
00332       EmitInstruction(
00333           Out, MCInstBuilder(X86::PUSH32r).addReg(RegCtx.scratchReg(MVT::i32)));
00334     }
00335     StoreFlags(Out);
00336   }
00337 
00338   virtual void InstrumentMemOperandEpilogue(const RegisterContext &RegCtx,
00339                                             MCContext &Ctx,
00340                                             MCStreamer &Out) override {
00341     RestoreFlags(Out);
00342     if (RegCtx.ScratchReg != X86::NoRegister) {
00343       EmitInstruction(
00344           Out, MCInstBuilder(X86::POP32r).addReg(RegCtx.scratchReg(MVT::i32)));
00345     }
00346     EmitInstruction(
00347         Out, MCInstBuilder(X86::POP32r).addReg(RegCtx.shadowReg(MVT::i32)));
00348     EmitInstruction(
00349         Out, MCInstBuilder(X86::POP32r).addReg(RegCtx.addressReg(MVT::i32)));
00350 
00351     if (Ctx.getRegisterInfo() && FrameReg != X86::NoRegister) {
00352       EmitInstruction(
00353           Out, MCInstBuilder(X86::POP32r).addReg(X86::EBP));
00354       Out.EmitCFIRestoreState();
00355       if (FrameReg == X86::ESP)
00356         Out.EmitCFIAdjustCfaOffset(-4 /* byte size of the FrameReg */);
00357     }
00358   }
00359 
00360   virtual void InstrumentMemOperandSmall(X86Operand &Op, unsigned AccessSize,
00361                                          bool IsWrite,
00362                                          const RegisterContext &RegCtx,
00363                                          MCContext &Ctx,
00364                                          MCStreamer &Out) override;
00365   virtual void InstrumentMemOperandLarge(X86Operand &Op, unsigned AccessSize,
00366                                          bool IsWrite,
00367                                          const RegisterContext &RegCtx,
00368                                          MCContext &Ctx,
00369                                          MCStreamer &Out) override;
00370   virtual void InstrumentMOVSImpl(unsigned AccessSize, MCContext &Ctx,
00371                                   MCStreamer &Out) override;
00372 
00373 private:
00374   void EmitCallAsanReport(unsigned AccessSize, bool IsWrite, MCContext &Ctx,
00375                           MCStreamer &Out, const RegisterContext &RegCtx) {
00376     EmitInstruction(Out, MCInstBuilder(X86::CLD));
00377     EmitInstruction(Out, MCInstBuilder(X86::MMX_EMMS));
00378 
00379     EmitInstruction(Out, MCInstBuilder(X86::AND64ri8)
00380                              .addReg(X86::ESP)
00381                              .addReg(X86::ESP)
00382                              .addImm(-16));
00383     EmitInstruction(
00384         Out, MCInstBuilder(X86::PUSH32r).addReg(RegCtx.addressReg(MVT::i32)));
00385 
00386     const std::string &Fn = FuncName(AccessSize, IsWrite);
00387     MCSymbol *FnSym = Ctx.GetOrCreateSymbol(StringRef(Fn));
00388     const MCSymbolRefExpr *FnExpr =
00389         MCSymbolRefExpr::Create(FnSym, MCSymbolRefExpr::VK_PLT, Ctx);
00390     EmitInstruction(Out, MCInstBuilder(X86::CALLpcrel32).addExpr(FnExpr));
00391   }
00392 };
00393 
00394 void X86AddressSanitizer32::InstrumentMemOperandSmall(
00395     X86Operand &Op, unsigned AccessSize, bool IsWrite,
00396     const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) {
00397   unsigned AddressRegI32 = RegCtx.addressReg(MVT::i32);
00398   unsigned ShadowRegI32 = RegCtx.shadowReg(MVT::i32);
00399   unsigned ShadowRegI8 = RegCtx.shadowReg(MVT::i8);
00400 
00401   assert(RegCtx.ScratchReg != X86::NoRegister);
00402   unsigned ScratchRegI32 = RegCtx.scratchReg(MVT::i32);
00403 
00404   {
00405     MCInst Inst;
00406     Inst.setOpcode(X86::LEA32r);
00407     Inst.addOperand(MCOperand::CreateReg(AddressRegI32));
00408     Op.addMemOperands(Inst, 5);
00409     EmitInstruction(Out, Inst);
00410   }
00411 
00412   EmitInstruction(Out, MCInstBuilder(X86::MOV32rr).addReg(ShadowRegI32).addReg(
00413                            AddressRegI32));
00414   EmitInstruction(Out, MCInstBuilder(X86::SHR32ri)
00415                            .addReg(ShadowRegI32)
00416                            .addReg(ShadowRegI32)
00417                            .addImm(3));
00418 
00419   {
00420     MCInst Inst;
00421     Inst.setOpcode(X86::MOV8rm);
00422     Inst.addOperand(MCOperand::CreateReg(ShadowRegI8));
00423     const MCExpr *Disp = MCConstantExpr::Create(kShadowOffset, Ctx);
00424     std::unique_ptr<X86Operand> Op(
00425         X86Operand::CreateMem(0, Disp, ShadowRegI32, 0, 1, SMLoc(), SMLoc()));
00426     Op->addMemOperands(Inst, 5);
00427     EmitInstruction(Out, Inst);
00428   }
00429 
00430   EmitInstruction(
00431       Out, MCInstBuilder(X86::TEST8rr).addReg(ShadowRegI8).addReg(ShadowRegI8));
00432   MCSymbol *DoneSym = Ctx.CreateTempSymbol();
00433   const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx);
00434   EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr));
00435 
00436   EmitInstruction(Out, MCInstBuilder(X86::MOV32rr).addReg(ScratchRegI32).addReg(
00437                            AddressRegI32));
00438   EmitInstruction(Out, MCInstBuilder(X86::AND32ri)
00439                            .addReg(ScratchRegI32)
00440                            .addReg(ScratchRegI32)
00441                            .addImm(7));
00442 
00443   switch (AccessSize) {
00444   case 1:
00445     break;
00446   case 2: {
00447     MCInst Inst;
00448     Inst.setOpcode(X86::LEA32r);
00449     Inst.addOperand(MCOperand::CreateReg(ScratchRegI32));
00450 
00451     const MCExpr *Disp = MCConstantExpr::Create(1, Ctx);
00452     std::unique_ptr<X86Operand> Op(
00453         X86Operand::CreateMem(0, Disp, ScratchRegI32, 0, 1, SMLoc(), SMLoc()));
00454     Op->addMemOperands(Inst, 5);
00455     EmitInstruction(Out, Inst);
00456     break;
00457   }
00458   case 4:
00459     EmitInstruction(Out, MCInstBuilder(X86::ADD32ri8)
00460                              .addReg(ScratchRegI32)
00461                              .addReg(ScratchRegI32)
00462                              .addImm(3));
00463     break;
00464   default:
00465     assert(false && "Incorrect access size");
00466     break;
00467   }
00468 
00469   EmitInstruction(
00470       Out,
00471       MCInstBuilder(X86::MOVSX32rr8).addReg(ShadowRegI32).addReg(ShadowRegI8));
00472   EmitInstruction(Out, MCInstBuilder(X86::CMP32rr).addReg(ScratchRegI32).addReg(
00473                            ShadowRegI32));
00474   EmitInstruction(Out, MCInstBuilder(X86::JL_4).addExpr(DoneExpr));
00475 
00476   EmitCallAsanReport(AccessSize, IsWrite, Ctx, Out, RegCtx);
00477   EmitLabel(Out, DoneSym);
00478 }
00479 
00480 void X86AddressSanitizer32::InstrumentMemOperandLarge(
00481     X86Operand &Op, unsigned AccessSize, bool IsWrite,
00482     const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) {
00483   unsigned AddressRegI32 = RegCtx.addressReg(MVT::i32);
00484   unsigned ShadowRegI32 = RegCtx.shadowReg(MVT::i32);
00485 
00486   {
00487     MCInst Inst;
00488     Inst.setOpcode(X86::LEA32r);
00489     Inst.addOperand(MCOperand::CreateReg(AddressRegI32));
00490     Op.addMemOperands(Inst, 5);
00491     EmitInstruction(Out, Inst);
00492   }
00493 
00494   EmitInstruction(Out, MCInstBuilder(X86::MOV32rr).addReg(ShadowRegI32).addReg(
00495                            AddressRegI32));
00496   EmitInstruction(Out, MCInstBuilder(X86::SHR32ri)
00497                            .addReg(ShadowRegI32)
00498                            .addReg(ShadowRegI32)
00499                            .addImm(3));
00500   {
00501     MCInst Inst;
00502     switch (AccessSize) {
00503     case 8:
00504       Inst.setOpcode(X86::CMP8mi);
00505       break;
00506     case 16:
00507       Inst.setOpcode(X86::CMP16mi);
00508       break;
00509     default:
00510       assert(false && "Incorrect access size");
00511       break;
00512     }
00513     const MCExpr *Disp = MCConstantExpr::Create(kShadowOffset, Ctx);
00514     std::unique_ptr<X86Operand> Op(
00515         X86Operand::CreateMem(0, Disp, ShadowRegI32, 0, 1, SMLoc(), SMLoc()));
00516     Op->addMemOperands(Inst, 5);
00517     Inst.addOperand(MCOperand::CreateImm(0));
00518     EmitInstruction(Out, Inst);
00519   }
00520   MCSymbol *DoneSym = Ctx.CreateTempSymbol();
00521   const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx);
00522   EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr));
00523 
00524   EmitCallAsanReport(AccessSize, IsWrite, Ctx, Out, RegCtx);
00525   EmitLabel(Out, DoneSym);
00526 }
00527 
00528 void X86AddressSanitizer32::InstrumentMOVSImpl(unsigned AccessSize,
00529                                                MCContext &Ctx,
00530                                                MCStreamer &Out) {
00531   StoreFlags(Out);
00532 
00533   // No need to test when ECX is equals to zero.
00534   MCSymbol *DoneSym = Ctx.CreateTempSymbol();
00535   const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx);
00536   EmitInstruction(
00537       Out, MCInstBuilder(X86::TEST32rr).addReg(X86::ECX).addReg(X86::ECX));
00538   EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr));
00539 
00540   // Instrument first and last elements in src and dst range.
00541   InstrumentMOVSBase(X86::EDI /* DstReg */, X86::ESI /* SrcReg */,
00542                      X86::ECX /* CntReg */, AccessSize, Ctx, Out);
00543 
00544   EmitLabel(Out, DoneSym);
00545   RestoreFlags(Out);
00546 }
00547 
00548 class X86AddressSanitizer64 : public X86AddressSanitizer {
00549 public:
00550   static const long kShadowOffset = 0x7fff8000;
00551 
00552   X86AddressSanitizer64(const MCSubtargetInfo &STI)
00553       : X86AddressSanitizer(STI) {}
00554 
00555   virtual ~X86AddressSanitizer64() {}
00556 
00557   virtual void StoreFlags(MCStreamer &Out) override {
00558     EmitInstruction(Out, MCInstBuilder(X86::PUSHF64));
00559   }
00560 
00561   virtual void RestoreFlags(MCStreamer &Out) override {
00562     EmitInstruction(Out, MCInstBuilder(X86::POPF64));
00563   }
00564 
00565   virtual void InstrumentMemOperandPrologue(const RegisterContext &RegCtx,
00566                                             MCContext &Ctx,
00567                                             MCStreamer &Out) override {
00568     const MCRegisterInfo *RegisterInfo = Ctx.getRegisterInfo();
00569     if (RegisterInfo && FrameReg != X86::NoRegister) {
00570       EmitInstruction(Out, MCInstBuilder(X86::PUSH64r).addReg(X86::RBP));
00571       if (FrameReg == X86::RSP) {
00572         Out.EmitCFIAdjustCfaOffset(8 /* byte size of the FrameReg */);
00573         Out.EmitCFIRelOffset(
00574             RegisterInfo->getDwarfRegNum(X86::RBP, true /* IsEH */), 0);
00575       }
00576       EmitInstruction(
00577           Out, MCInstBuilder(X86::MOV64rr).addReg(X86::RBP).addReg(FrameReg));
00578       Out.EmitCFIRememberState();
00579       Out.EmitCFIDefCfaRegister(
00580           RegisterInfo->getDwarfRegNum(X86::RBP, true /* IsEH */));
00581     }
00582 
00583     EmitAdjustRSP(Ctx, Out, -128);
00584     EmitInstruction(
00585         Out, MCInstBuilder(X86::PUSH64r).addReg(RegCtx.shadowReg(MVT::i64)));
00586     EmitInstruction(
00587         Out, MCInstBuilder(X86::PUSH64r).addReg(RegCtx.addressReg(MVT::i64)));
00588     if (RegCtx.ScratchReg != X86::NoRegister) {
00589       EmitInstruction(
00590           Out, MCInstBuilder(X86::PUSH64r).addReg(RegCtx.scratchReg(MVT::i64)));
00591     }
00592     StoreFlags(Out);
00593   }
00594 
00595   virtual void InstrumentMemOperandEpilogue(const RegisterContext &RegCtx,
00596                                             MCContext &Ctx,
00597                                             MCStreamer &Out) override {
00598     RestoreFlags(Out);
00599     if (RegCtx.ScratchReg != X86::NoRegister) {
00600       EmitInstruction(
00601           Out, MCInstBuilder(X86::POP64r).addReg(RegCtx.scratchReg(MVT::i64)));
00602     }
00603     EmitInstruction(
00604         Out, MCInstBuilder(X86::POP64r).addReg(RegCtx.addressReg(MVT::i64)));
00605     EmitInstruction(
00606         Out, MCInstBuilder(X86::POP64r).addReg(RegCtx.shadowReg(MVT::i64)));
00607     EmitAdjustRSP(Ctx, Out, 128);
00608 
00609     if (Ctx.getRegisterInfo() && FrameReg != X86::NoRegister) {
00610       EmitInstruction(
00611           Out, MCInstBuilder(X86::POP64r).addReg(X86::RBP));
00612       Out.EmitCFIRestoreState();
00613       if (FrameReg == X86::RSP)
00614         Out.EmitCFIAdjustCfaOffset(-8 /* byte size of the FrameReg */);
00615     }
00616   }
00617 
00618   virtual void InstrumentMemOperandSmall(X86Operand &Op, unsigned AccessSize,
00619                                          bool IsWrite,
00620                                          const RegisterContext &RegCtx,
00621                                          MCContext &Ctx,
00622                                          MCStreamer &Out) override;
00623   virtual void InstrumentMemOperandLarge(X86Operand &Op, unsigned AccessSize,
00624                                          bool IsWrite,
00625                                          const RegisterContext &RegCtx,
00626                                          MCContext &Ctx,
00627                                          MCStreamer &Out) override;
00628   virtual void InstrumentMOVSImpl(unsigned AccessSize, MCContext &Ctx,
00629                                   MCStreamer &Out) override;
00630 
00631 private:
00632   void EmitAdjustRSP(MCContext &Ctx, MCStreamer &Out, long Offset) {
00633     MCInst Inst;
00634     Inst.setOpcode(X86::LEA64r);
00635     Inst.addOperand(MCOperand::CreateReg(X86::RSP));
00636 
00637     const MCExpr *Disp = MCConstantExpr::Create(Offset, Ctx);
00638     std::unique_ptr<X86Operand> Op(
00639         X86Operand::CreateMem(0, Disp, X86::RSP, 0, 1, SMLoc(), SMLoc()));
00640     Op->addMemOperands(Inst, 5);
00641     EmitInstruction(Out, Inst);
00642   }
00643 
00644   void EmitCallAsanReport(unsigned AccessSize, bool IsWrite, MCContext &Ctx,
00645                           MCStreamer &Out, const RegisterContext &RegCtx) {
00646     EmitInstruction(Out, MCInstBuilder(X86::CLD));
00647     EmitInstruction(Out, MCInstBuilder(X86::MMX_EMMS));
00648 
00649     EmitInstruction(Out, MCInstBuilder(X86::AND64ri8)
00650                              .addReg(X86::RSP)
00651                              .addReg(X86::RSP)
00652                              .addImm(-16));
00653 
00654     if (RegCtx.AddressReg != X86::RDI) {
00655       EmitInstruction(Out, MCInstBuilder(X86::MOV64rr).addReg(X86::RDI).addReg(
00656                                RegCtx.addressReg(MVT::i64)));
00657     }
00658     const std::string &Fn = FuncName(AccessSize, IsWrite);
00659     MCSymbol *FnSym = Ctx.GetOrCreateSymbol(StringRef(Fn));
00660     const MCSymbolRefExpr *FnExpr =
00661         MCSymbolRefExpr::Create(FnSym, MCSymbolRefExpr::VK_PLT, Ctx);
00662     EmitInstruction(Out, MCInstBuilder(X86::CALL64pcrel32).addExpr(FnExpr));
00663   }
00664 };
00665 
00666 void X86AddressSanitizer64::InstrumentMemOperandSmall(
00667     X86Operand &Op, unsigned AccessSize, bool IsWrite,
00668     const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) {
00669   unsigned AddressRegI64 = RegCtx.addressReg(MVT::i64);
00670   unsigned AddressRegI32 = RegCtx.addressReg(MVT::i32);
00671   unsigned ShadowRegI64 = RegCtx.shadowReg(MVT::i64);
00672   unsigned ShadowRegI32 = RegCtx.shadowReg(MVT::i32);
00673   unsigned ShadowRegI8 = RegCtx.shadowReg(MVT::i8);
00674 
00675   assert(RegCtx.ScratchReg != X86::NoRegister);
00676   unsigned ScratchRegI32 = RegCtx.scratchReg(MVT::i32);
00677 
00678   {
00679     MCInst Inst;
00680     Inst.setOpcode(X86::LEA64r);
00681     Inst.addOperand(MCOperand::CreateReg(AddressRegI64));
00682     Op.addMemOperands(Inst, 5);
00683     EmitInstruction(Out, Inst);
00684   }
00685   EmitInstruction(Out, MCInstBuilder(X86::MOV64rr).addReg(ShadowRegI64).addReg(
00686                            AddressRegI64));
00687   EmitInstruction(Out, MCInstBuilder(X86::SHR64ri)
00688                            .addReg(ShadowRegI64)
00689                            .addReg(ShadowRegI64)
00690                            .addImm(3));
00691   {
00692     MCInst Inst;
00693     Inst.setOpcode(X86::MOV8rm);
00694     Inst.addOperand(MCOperand::CreateReg(ShadowRegI8));
00695     const MCExpr *Disp = MCConstantExpr::Create(kShadowOffset, Ctx);
00696     std::unique_ptr<X86Operand> Op(
00697         X86Operand::CreateMem(0, Disp, ShadowRegI64, 0, 1, SMLoc(), SMLoc()));
00698     Op->addMemOperands(Inst, 5);
00699     EmitInstruction(Out, Inst);
00700   }
00701 
00702   EmitInstruction(
00703       Out, MCInstBuilder(X86::TEST8rr).addReg(ShadowRegI8).addReg(ShadowRegI8));
00704   MCSymbol *DoneSym = Ctx.CreateTempSymbol();
00705   const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx);
00706   EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr));
00707 
00708   EmitInstruction(Out, MCInstBuilder(X86::MOV32rr).addReg(ScratchRegI32).addReg(
00709                            AddressRegI32));
00710   EmitInstruction(Out, MCInstBuilder(X86::AND32ri)
00711                            .addReg(ScratchRegI32)
00712                            .addReg(ScratchRegI32)
00713                            .addImm(7));
00714 
00715   switch (AccessSize) {
00716   case 1:
00717     break;
00718   case 2: {
00719     MCInst Inst;
00720     Inst.setOpcode(X86::LEA32r);
00721     Inst.addOperand(MCOperand::CreateReg(ScratchRegI32));
00722 
00723     const MCExpr *Disp = MCConstantExpr::Create(1, Ctx);
00724     std::unique_ptr<X86Operand> Op(
00725         X86Operand::CreateMem(0, Disp, ScratchRegI32, 0, 1, SMLoc(), SMLoc()));
00726     Op->addMemOperands(Inst, 5);
00727     EmitInstruction(Out, Inst);
00728     break;
00729   }
00730   case 4:
00731     EmitInstruction(Out, MCInstBuilder(X86::ADD32ri8)
00732                              .addReg(ScratchRegI32)
00733                              .addReg(ScratchRegI32)
00734                              .addImm(3));
00735     break;
00736   default:
00737     assert(false && "Incorrect access size");
00738     break;
00739   }
00740 
00741   EmitInstruction(
00742       Out,
00743       MCInstBuilder(X86::MOVSX32rr8).addReg(ShadowRegI32).addReg(ShadowRegI8));
00744   EmitInstruction(Out, MCInstBuilder(X86::CMP32rr).addReg(ScratchRegI32).addReg(
00745                            ShadowRegI32));
00746   EmitInstruction(Out, MCInstBuilder(X86::JL_4).addExpr(DoneExpr));
00747 
00748   EmitCallAsanReport(AccessSize, IsWrite, Ctx, Out, RegCtx);
00749   EmitLabel(Out, DoneSym);
00750 }
00751 
00752 void X86AddressSanitizer64::InstrumentMemOperandLarge(
00753     X86Operand &Op, unsigned AccessSize, bool IsWrite,
00754     const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) {
00755   unsigned AddressRegI64 = RegCtx.addressReg(MVT::i64);
00756   unsigned ShadowRegI64 = RegCtx.shadowReg(MVT::i64);
00757 
00758   {
00759     MCInst Inst;
00760     Inst.setOpcode(X86::LEA64r);
00761     Inst.addOperand(MCOperand::CreateReg(AddressRegI64));
00762     Op.addMemOperands(Inst, 5);
00763     EmitInstruction(Out, Inst);
00764   }
00765   EmitInstruction(Out, MCInstBuilder(X86::MOV64rr).addReg(ShadowRegI64).addReg(
00766                            AddressRegI64));
00767   EmitInstruction(Out, MCInstBuilder(X86::SHR64ri)
00768                            .addReg(ShadowRegI64)
00769                            .addReg(ShadowRegI64)
00770                            .addImm(3));
00771   {
00772     MCInst Inst;
00773     switch (AccessSize) {
00774     case 8:
00775       Inst.setOpcode(X86::CMP8mi);
00776       break;
00777     case 16:
00778       Inst.setOpcode(X86::CMP16mi);
00779       break;
00780     default:
00781       assert(false && "Incorrect access size");
00782       break;
00783     }
00784     const MCExpr *Disp = MCConstantExpr::Create(kShadowOffset, Ctx);
00785     std::unique_ptr<X86Operand> Op(
00786         X86Operand::CreateMem(0, Disp, ShadowRegI64, 0, 1, SMLoc(), SMLoc()));
00787     Op->addMemOperands(Inst, 5);
00788     Inst.addOperand(MCOperand::CreateImm(0));
00789     EmitInstruction(Out, Inst);
00790   }
00791 
00792   MCSymbol *DoneSym = Ctx.CreateTempSymbol();
00793   const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx);
00794   EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr));
00795 
00796   EmitCallAsanReport(AccessSize, IsWrite, Ctx, Out, RegCtx);
00797   EmitLabel(Out, DoneSym);
00798 }
00799 
00800 void X86AddressSanitizer64::InstrumentMOVSImpl(unsigned AccessSize,
00801                                                MCContext &Ctx,
00802                                                MCStreamer &Out) {
00803   StoreFlags(Out);
00804 
00805   // No need to test when RCX is equals to zero.
00806   MCSymbol *DoneSym = Ctx.CreateTempSymbol();
00807   const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx);
00808   EmitInstruction(
00809       Out, MCInstBuilder(X86::TEST64rr).addReg(X86::RCX).addReg(X86::RCX));
00810   EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr));
00811 
00812   // Instrument first and last elements in src and dst range.
00813   InstrumentMOVSBase(X86::RDI /* DstReg */, X86::RSI /* SrcReg */,
00814                      X86::RCX /* CntReg */, AccessSize, Ctx, Out);
00815 
00816   EmitLabel(Out, DoneSym);
00817   RestoreFlags(Out);
00818 }
00819 
00820 } // End anonymous namespace
00821 
00822 X86AsmInstrumentation::X86AsmInstrumentation(const MCSubtargetInfo &STI)
00823     : STI(STI), FrameReg(X86::NoRegister) {}
00824 
00825 X86AsmInstrumentation::~X86AsmInstrumentation() {}
00826 
00827 void X86AsmInstrumentation::InstrumentAndEmitInstruction(
00828     const MCInst &Inst, OperandVector &Operands, MCContext &Ctx,
00829     const MCInstrInfo &MII, MCStreamer &Out) {
00830   EmitInstruction(Out, Inst);
00831 }
00832 
00833 void X86AsmInstrumentation::EmitInstruction(MCStreamer &Out,
00834                                             const MCInst &Inst) {
00835   Out.EmitInstruction(Inst, STI);
00836 }
00837 
00838 X86AsmInstrumentation *
00839 CreateX86AsmInstrumentation(const MCTargetOptions &MCOptions,
00840                             const MCContext &Ctx, const MCSubtargetInfo &STI) {
00841   Triple T(STI.getTargetTriple());
00842   const bool hasCompilerRTSupport = T.isOSLinux();
00843   if (ClAsanInstrumentAssembly && hasCompilerRTSupport &&
00844       MCOptions.SanitizeAddress) {
00845     if ((STI.getFeatureBits() & X86::Mode32Bit) != 0)
00846       return new X86AddressSanitizer32(STI);
00847     if ((STI.getFeatureBits() & X86::Mode64Bit) != 0)
00848       return new X86AddressSanitizer64(STI);
00849   }
00850   return new X86AsmInstrumentation(STI);
00851 }
00852 
00853 } // End llvm namespace