X86AsmInstrumentation.cpp revision 280031
1274955Ssvnmir//===-- X86AsmInstrumentation.cpp - Instrument X86 inline assembly C++ -*-===// 2274955Ssvnmir// 3274955Ssvnmir// The LLVM Compiler Infrastructure 4274955Ssvnmir// 5274955Ssvnmir// This file is distributed under the University of Illinois Open Source 6274955Ssvnmir// License. See LICENSE.TXT for details. 7274955Ssvnmir// 8274955Ssvnmir//===----------------------------------------------------------------------===// 9274955Ssvnmir 10274955Ssvnmir#include "MCTargetDesc/X86BaseInfo.h" 11274955Ssvnmir#include "X86AsmInstrumentation.h" 12274955Ssvnmir#include "X86Operand.h" 13280031Sdim#include "X86RegisterInfo.h" 14274955Ssvnmir#include "llvm/ADT/StringExtras.h" 15274955Ssvnmir#include "llvm/ADT/Triple.h" 16280031Sdim#include "llvm/CodeGen/MachineValueType.h" 17274955Ssvnmir#include "llvm/IR/Function.h" 18280031Sdim#include "llvm/MC/MCAsmInfo.h" 19274955Ssvnmir#include "llvm/MC/MCContext.h" 20274955Ssvnmir#include "llvm/MC/MCInst.h" 21274955Ssvnmir#include "llvm/MC/MCInstBuilder.h" 22274955Ssvnmir#include "llvm/MC/MCInstrInfo.h" 23274955Ssvnmir#include "llvm/MC/MCParser/MCParsedAsmOperand.h" 24274955Ssvnmir#include "llvm/MC/MCStreamer.h" 25274955Ssvnmir#include "llvm/MC/MCSubtargetInfo.h" 26274955Ssvnmir#include "llvm/MC/MCTargetAsmParser.h" 27274955Ssvnmir#include "llvm/MC/MCTargetOptions.h" 28274955Ssvnmir#include "llvm/Support/CommandLine.h" 29280031Sdim#include <algorithm> 30280031Sdim#include <cassert> 31280031Sdim#include <vector> 32274955Ssvnmir 33280031Sdim// Following comment describes how assembly instrumentation works. 34280031Sdim// Currently we have only AddressSanitizer instrumentation, but we're 35280031Sdim// planning to implement MemorySanitizer for inline assembly too. If 36280031Sdim// you're not familiar with AddressSanitizer algorithm, please, read 37280031Sdim// https://code.google.com/p/address-sanitizer/wiki/AddressSanitizerAlgorithm. 38280031Sdim// 39280031Sdim// When inline assembly is parsed by an instance of X86AsmParser, all 40280031Sdim// instructions are emitted via EmitInstruction method. That's the 41280031Sdim// place where X86AsmInstrumentation analyzes an instruction and 42280031Sdim// decides, whether the instruction should be emitted as is or 43280031Sdim// instrumentation is required. The latter case happens when an 44280031Sdim// instruction reads from or writes to memory. Now instruction opcode 45280031Sdim// is explicitly checked, and if an instruction has a memory operand 46280031Sdim// (for instance, movq (%rsi, %rcx, 8), %rax) - it should be 47280031Sdim// instrumented. There're also exist instructions that modify 48280031Sdim// memory but don't have an explicit memory operands, for instance, 49280031Sdim// movs. 50280031Sdim// 51280031Sdim// Let's consider at first 8-byte memory accesses when an instruction 52280031Sdim// has an explicit memory operand. In this case we need two registers - 53280031Sdim// AddressReg to compute address of a memory cells which are accessed 54280031Sdim// and ShadowReg to compute corresponding shadow address. So, we need 55280031Sdim// to spill both registers before instrumentation code and restore them 56280031Sdim// after instrumentation. Thus, in general, instrumentation code will 57280031Sdim// look like this: 58280031Sdim// PUSHF # Store flags, otherwise they will be overwritten 59280031Sdim// PUSH AddressReg # spill AddressReg 60280031Sdim// PUSH ShadowReg # spill ShadowReg 61280031Sdim// LEA MemOp, AddressReg # compute address of the memory operand 62280031Sdim// MOV AddressReg, ShadowReg 63280031Sdim// SHR ShadowReg, 3 64280031Sdim// # ShadowOffset(AddressReg >> 3) contains address of a shadow 65280031Sdim// # corresponding to MemOp. 66280031Sdim// CMP ShadowOffset(ShadowReg), 0 # test shadow value 67280031Sdim// JZ .Done # when shadow equals to zero, everything is fine 68280031Sdim// MOV AddressReg, RDI 69280031Sdim// # Call __asan_report function with AddressReg as an argument 70280031Sdim// CALL __asan_report 71280031Sdim// .Done: 72280031Sdim// POP ShadowReg # Restore ShadowReg 73280031Sdim// POP AddressReg # Restore AddressReg 74280031Sdim// POPF # Restore flags 75280031Sdim// 76280031Sdim// Memory accesses with different size (1-, 2-, 4- and 16-byte) are 77280031Sdim// handled in a similar manner, but small memory accesses (less than 8 78280031Sdim// byte) require an additional ScratchReg, which is used for shadow value. 79280031Sdim// 80280031Sdim// If, suppose, we're instrumenting an instruction like movs, only 81280031Sdim// contents of RDI, RDI + AccessSize * RCX, RSI, RSI + AccessSize * 82280031Sdim// RCX are checked. In this case there're no need to spill and restore 83280031Sdim// AddressReg , ShadowReg or flags four times, they're saved on stack 84280031Sdim// just once, before instrumentation of these four addresses, and restored 85280031Sdim// at the end of the instrumentation. 86280031Sdim// 87280031Sdim// There exist several things which complicate this simple algorithm. 88280031Sdim// * Instrumented memory operand can have RSP as a base or an index 89280031Sdim// register. So we need to add a constant offset before computation 90280031Sdim// of memory address, since flags, AddressReg, ShadowReg, etc. were 91280031Sdim// already stored on stack and RSP was modified. 92280031Sdim// * Debug info (usually, DWARF) should be adjusted, because sometimes 93280031Sdim// RSP is used as a frame register. So, we need to select some 94280031Sdim// register as a frame register and temprorary override current CFA 95280031Sdim// register. 96280031Sdim 97274955Ssvnmirnamespace llvm { 98274955Ssvnmirnamespace { 99274955Ssvnmir 100274955Ssvnmirstatic cl::opt<bool> ClAsanInstrumentAssembly( 101274955Ssvnmir "asan-instrument-assembly", 102274955Ssvnmir cl::desc("instrument assembly with AddressSanitizer checks"), cl::Hidden, 103274955Ssvnmir cl::init(false)); 104274955Ssvnmir 105280031Sdimconst int64_t MinAllowedDisplacement = std::numeric_limits<int32_t>::min(); 106280031Sdimconst int64_t MaxAllowedDisplacement = std::numeric_limits<int32_t>::max(); 107280031Sdim 108280031Sdimint64_t ApplyDisplacementBounds(int64_t Displacement) { 109280031Sdim return std::max(std::min(MaxAllowedDisplacement, Displacement), 110280031Sdim MinAllowedDisplacement); 111274955Ssvnmir} 112274955Ssvnmir 113280031Sdimvoid CheckDisplacementBounds(int64_t Displacement) { 114280031Sdim assert(Displacement >= MinAllowedDisplacement && 115280031Sdim Displacement <= MaxAllowedDisplacement); 116280031Sdim} 117280031Sdim 118280031Sdimbool IsStackReg(unsigned Reg) { return Reg == X86::RSP || Reg == X86::ESP; } 119280031Sdim 120280031Sdimbool IsSmallMemAccess(unsigned AccessSize) { return AccessSize < 8; } 121280031Sdim 122274955Ssvnmirstd::string FuncName(unsigned AccessSize, bool IsWrite) { 123274955Ssvnmir return std::string("__asan_report_") + (IsWrite ? "store" : "load") + 124274955Ssvnmir utostr(AccessSize); 125274955Ssvnmir} 126274955Ssvnmir 127274955Ssvnmirclass X86AddressSanitizer : public X86AsmInstrumentation { 128274955Ssvnmirpublic: 129280031Sdim struct RegisterContext { 130280031Sdim private: 131280031Sdim enum RegOffset { 132280031Sdim REG_OFFSET_ADDRESS = 0, 133280031Sdim REG_OFFSET_SHADOW, 134280031Sdim REG_OFFSET_SCRATCH 135280031Sdim }; 136280031Sdim 137280031Sdim public: 138280031Sdim RegisterContext(unsigned AddressReg, unsigned ShadowReg, 139280031Sdim unsigned ScratchReg) { 140280031Sdim BusyRegs.push_back(convReg(AddressReg, MVT::i64)); 141280031Sdim BusyRegs.push_back(convReg(ShadowReg, MVT::i64)); 142280031Sdim BusyRegs.push_back(convReg(ScratchReg, MVT::i64)); 143280031Sdim } 144280031Sdim 145280031Sdim unsigned AddressReg(MVT::SimpleValueType VT) const { 146280031Sdim return convReg(BusyRegs[REG_OFFSET_ADDRESS], VT); 147280031Sdim } 148280031Sdim 149280031Sdim unsigned ShadowReg(MVT::SimpleValueType VT) const { 150280031Sdim return convReg(BusyRegs[REG_OFFSET_SHADOW], VT); 151280031Sdim } 152280031Sdim 153280031Sdim unsigned ScratchReg(MVT::SimpleValueType VT) const { 154280031Sdim return convReg(BusyRegs[REG_OFFSET_SCRATCH], VT); 155280031Sdim } 156280031Sdim 157280031Sdim void AddBusyReg(unsigned Reg) { 158280031Sdim if (Reg != X86::NoRegister) 159280031Sdim BusyRegs.push_back(convReg(Reg, MVT::i64)); 160280031Sdim } 161280031Sdim 162280031Sdim void AddBusyRegs(const X86Operand &Op) { 163280031Sdim AddBusyReg(Op.getMemBaseReg()); 164280031Sdim AddBusyReg(Op.getMemIndexReg()); 165280031Sdim } 166280031Sdim 167280031Sdim unsigned ChooseFrameReg(MVT::SimpleValueType VT) const { 168280031Sdim static const MCPhysReg Candidates[] = { X86::RBP, X86::RAX, X86::RBX, 169280031Sdim X86::RCX, X86::RDX, X86::RDI, 170280031Sdim X86::RSI }; 171280031Sdim for (unsigned Reg : Candidates) { 172280031Sdim if (!std::count(BusyRegs.begin(), BusyRegs.end(), Reg)) 173280031Sdim return convReg(Reg, VT); 174280031Sdim } 175280031Sdim return X86::NoRegister; 176280031Sdim } 177280031Sdim 178280031Sdim private: 179280031Sdim unsigned convReg(unsigned Reg, MVT::SimpleValueType VT) const { 180280031Sdim return Reg == X86::NoRegister ? Reg : getX86SubSuperRegister(Reg, VT); 181280031Sdim } 182280031Sdim 183280031Sdim std::vector<unsigned> BusyRegs; 184280031Sdim }; 185280031Sdim 186280031Sdim X86AddressSanitizer(const MCSubtargetInfo &STI) 187280031Sdim : X86AsmInstrumentation(STI), RepPrefix(false), OrigSPOffset(0) {} 188280031Sdim 189274955Ssvnmir virtual ~X86AddressSanitizer() {} 190274955Ssvnmir 191274955Ssvnmir // X86AsmInstrumentation implementation: 192280031Sdim virtual void InstrumentAndEmitInstruction(const MCInst &Inst, 193280031Sdim OperandVector &Operands, 194280031Sdim MCContext &Ctx, 195280031Sdim const MCInstrInfo &MII, 196280031Sdim MCStreamer &Out) override { 197280031Sdim InstrumentMOVS(Inst, Operands, Ctx, MII, Out); 198280031Sdim if (RepPrefix) 199280031Sdim EmitInstruction(Out, MCInstBuilder(X86::REP_PREFIX)); 200280031Sdim 201274955Ssvnmir InstrumentMOV(Inst, Operands, Ctx, MII, Out); 202280031Sdim 203280031Sdim RepPrefix = (Inst.getOpcode() == X86::REP_PREFIX); 204280031Sdim if (!RepPrefix) 205280031Sdim EmitInstruction(Out, Inst); 206274955Ssvnmir } 207274955Ssvnmir 208280031Sdim // Adjusts up stack and saves all registers used in instrumentation. 209280031Sdim virtual void InstrumentMemOperandPrologue(const RegisterContext &RegCtx, 210280031Sdim MCContext &Ctx, 211280031Sdim MCStreamer &Out) = 0; 212274955Ssvnmir 213280031Sdim // Restores all registers used in instrumentation and adjusts stack. 214280031Sdim virtual void InstrumentMemOperandEpilogue(const RegisterContext &RegCtx, 215280031Sdim MCContext &Ctx, 216280031Sdim MCStreamer &Out) = 0; 217280031Sdim 218280031Sdim virtual void InstrumentMemOperandSmall(X86Operand &Op, unsigned AccessSize, 219280031Sdim bool IsWrite, 220280031Sdim const RegisterContext &RegCtx, 221280031Sdim MCContext &Ctx, MCStreamer &Out) = 0; 222280031Sdim virtual void InstrumentMemOperandLarge(X86Operand &Op, unsigned AccessSize, 223280031Sdim bool IsWrite, 224280031Sdim const RegisterContext &RegCtx, 225280031Sdim MCContext &Ctx, MCStreamer &Out) = 0; 226280031Sdim 227280031Sdim virtual void InstrumentMOVSImpl(unsigned AccessSize, MCContext &Ctx, 228280031Sdim MCStreamer &Out) = 0; 229280031Sdim 230280031Sdim void InstrumentMemOperand(X86Operand &Op, unsigned AccessSize, bool IsWrite, 231280031Sdim const RegisterContext &RegCtx, MCContext &Ctx, 232280031Sdim MCStreamer &Out); 233280031Sdim void InstrumentMOVSBase(unsigned DstReg, unsigned SrcReg, unsigned CntReg, 234280031Sdim unsigned AccessSize, MCContext &Ctx, MCStreamer &Out); 235280031Sdim 236280031Sdim void InstrumentMOVS(const MCInst &Inst, OperandVector &Operands, 237280031Sdim MCContext &Ctx, const MCInstrInfo &MII, MCStreamer &Out); 238274955Ssvnmir void InstrumentMOV(const MCInst &Inst, OperandVector &Operands, 239274955Ssvnmir MCContext &Ctx, const MCInstrInfo &MII, MCStreamer &Out); 240274955Ssvnmir 241280031Sdimprotected: 242274955Ssvnmir void EmitLabel(MCStreamer &Out, MCSymbol *Label) { Out.EmitLabel(Label); } 243274955Ssvnmir 244280031Sdim void EmitLEA(X86Operand &Op, MVT::SimpleValueType VT, unsigned Reg, 245280031Sdim MCStreamer &Out) { 246280031Sdim assert(VT == MVT::i32 || VT == MVT::i64); 247280031Sdim MCInst Inst; 248280031Sdim Inst.setOpcode(VT == MVT::i32 ? X86::LEA32r : X86::LEA64r); 249280031Sdim Inst.addOperand(MCOperand::CreateReg(getX86SubSuperRegister(Reg, VT))); 250280031Sdim Op.addMemOperands(Inst, 5); 251280031Sdim EmitInstruction(Out, Inst); 252280031Sdim } 253280031Sdim 254280031Sdim void ComputeMemOperandAddress(X86Operand &Op, MVT::SimpleValueType VT, 255280031Sdim unsigned Reg, MCContext &Ctx, MCStreamer &Out); 256280031Sdim 257280031Sdim // Creates new memory operand with Displacement added to an original 258280031Sdim // displacement. Residue will contain a residue which could happen when the 259280031Sdim // total displacement exceeds 32-bit limitation. 260280031Sdim std::unique_ptr<X86Operand> AddDisplacement(X86Operand &Op, 261280031Sdim int64_t Displacement, 262280031Sdim MCContext &Ctx, int64_t *Residue); 263280031Sdim 264280031Sdim bool is64BitMode() const { 265280031Sdim return (STI.getFeatureBits() & X86::Mode64Bit) != 0; 266280031Sdim } 267280031Sdim bool is32BitMode() const { 268280031Sdim return (STI.getFeatureBits() & X86::Mode32Bit) != 0; 269280031Sdim } 270280031Sdim bool is16BitMode() const { 271280031Sdim return (STI.getFeatureBits() & X86::Mode16Bit) != 0; 272280031Sdim } 273280031Sdim 274280031Sdim unsigned getPointerWidth() { 275280031Sdim if (is16BitMode()) return 16; 276280031Sdim if (is32BitMode()) return 32; 277280031Sdim if (is64BitMode()) return 64; 278280031Sdim llvm_unreachable("invalid mode"); 279280031Sdim } 280280031Sdim 281280031Sdim // True when previous instruction was actually REP prefix. 282280031Sdim bool RepPrefix; 283280031Sdim 284280031Sdim // Offset from the original SP register. 285280031Sdim int64_t OrigSPOffset; 286274955Ssvnmir}; 287274955Ssvnmir 288274955Ssvnmirvoid X86AddressSanitizer::InstrumentMemOperand( 289280031Sdim X86Operand &Op, unsigned AccessSize, bool IsWrite, 290280031Sdim const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) { 291274955Ssvnmir assert(Op.isMem() && "Op should be a memory operand."); 292274955Ssvnmir assert((AccessSize & (AccessSize - 1)) == 0 && AccessSize <= 16 && 293274955Ssvnmir "AccessSize should be a power of two, less or equal than 16."); 294280031Sdim // FIXME: take into account load/store alignment. 295280031Sdim if (IsSmallMemAccess(AccessSize)) 296280031Sdim InstrumentMemOperandSmall(Op, AccessSize, IsWrite, RegCtx, Ctx, Out); 297280031Sdim else 298280031Sdim InstrumentMemOperandLarge(Op, AccessSize, IsWrite, RegCtx, Ctx, Out); 299280031Sdim} 300274955Ssvnmir 301280031Sdimvoid X86AddressSanitizer::InstrumentMOVSBase(unsigned DstReg, unsigned SrcReg, 302280031Sdim unsigned CntReg, 303280031Sdim unsigned AccessSize, 304280031Sdim MCContext &Ctx, MCStreamer &Out) { 305280031Sdim // FIXME: check whole ranges [DstReg .. DstReg + AccessSize * (CntReg - 1)] 306280031Sdim // and [SrcReg .. SrcReg + AccessSize * (CntReg - 1)]. 307280031Sdim RegisterContext RegCtx(X86::RDX /* AddressReg */, X86::RAX /* ShadowReg */, 308280031Sdim IsSmallMemAccess(AccessSize) 309280031Sdim ? X86::RBX 310280031Sdim : X86::NoRegister /* ScratchReg */); 311280031Sdim RegCtx.AddBusyReg(DstReg); 312280031Sdim RegCtx.AddBusyReg(SrcReg); 313280031Sdim RegCtx.AddBusyReg(CntReg); 314280031Sdim 315280031Sdim InstrumentMemOperandPrologue(RegCtx, Ctx, Out); 316280031Sdim 317280031Sdim // Test (%SrcReg) 318280031Sdim { 319280031Sdim const MCExpr *Disp = MCConstantExpr::Create(0, Ctx); 320280031Sdim std::unique_ptr<X86Operand> Op(X86Operand::CreateMem( 321280031Sdim getPointerWidth(), 0, Disp, SrcReg, 0, AccessSize, SMLoc(), SMLoc())); 322280031Sdim InstrumentMemOperand(*Op, AccessSize, false /* IsWrite */, RegCtx, Ctx, 323280031Sdim Out); 324280031Sdim } 325280031Sdim 326280031Sdim // Test -1(%SrcReg, %CntReg, AccessSize) 327280031Sdim { 328280031Sdim const MCExpr *Disp = MCConstantExpr::Create(-1, Ctx); 329280031Sdim std::unique_ptr<X86Operand> Op(X86Operand::CreateMem( 330280031Sdim getPointerWidth(), 0, Disp, SrcReg, CntReg, AccessSize, SMLoc(), 331280031Sdim SMLoc())); 332280031Sdim InstrumentMemOperand(*Op, AccessSize, false /* IsWrite */, RegCtx, Ctx, 333280031Sdim Out); 334280031Sdim } 335280031Sdim 336280031Sdim // Test (%DstReg) 337280031Sdim { 338280031Sdim const MCExpr *Disp = MCConstantExpr::Create(0, Ctx); 339280031Sdim std::unique_ptr<X86Operand> Op(X86Operand::CreateMem( 340280031Sdim getPointerWidth(), 0, Disp, DstReg, 0, AccessSize, SMLoc(), SMLoc())); 341280031Sdim InstrumentMemOperand(*Op, AccessSize, true /* IsWrite */, RegCtx, Ctx, Out); 342280031Sdim } 343280031Sdim 344280031Sdim // Test -1(%DstReg, %CntReg, AccessSize) 345280031Sdim { 346280031Sdim const MCExpr *Disp = MCConstantExpr::Create(-1, Ctx); 347280031Sdim std::unique_ptr<X86Operand> Op(X86Operand::CreateMem( 348280031Sdim getPointerWidth(), 0, Disp, DstReg, CntReg, AccessSize, SMLoc(), 349280031Sdim SMLoc())); 350280031Sdim InstrumentMemOperand(*Op, AccessSize, true /* IsWrite */, RegCtx, Ctx, Out); 351280031Sdim } 352280031Sdim 353280031Sdim InstrumentMemOperandEpilogue(RegCtx, Ctx, Out); 354280031Sdim} 355280031Sdim 356280031Sdimvoid X86AddressSanitizer::InstrumentMOVS(const MCInst &Inst, 357280031Sdim OperandVector &Operands, 358280031Sdim MCContext &Ctx, const MCInstrInfo &MII, 359280031Sdim MCStreamer &Out) { 360280031Sdim // Access size in bytes. 361280031Sdim unsigned AccessSize = 0; 362280031Sdim 363280031Sdim switch (Inst.getOpcode()) { 364280031Sdim case X86::MOVSB: 365280031Sdim AccessSize = 1; 366280031Sdim break; 367280031Sdim case X86::MOVSW: 368280031Sdim AccessSize = 2; 369280031Sdim break; 370280031Sdim case X86::MOVSL: 371280031Sdim AccessSize = 4; 372280031Sdim break; 373280031Sdim case X86::MOVSQ: 374280031Sdim AccessSize = 8; 375280031Sdim break; 376280031Sdim default: 377274955Ssvnmir return; 378280031Sdim } 379274955Ssvnmir 380280031Sdim InstrumentMOVSImpl(AccessSize, Ctx, Out); 381274955Ssvnmir} 382274955Ssvnmir 383280031Sdimvoid X86AddressSanitizer::InstrumentMOV(const MCInst &Inst, 384280031Sdim OperandVector &Operands, MCContext &Ctx, 385280031Sdim const MCInstrInfo &MII, 386280031Sdim MCStreamer &Out) { 387274955Ssvnmir // Access size in bytes. 388274955Ssvnmir unsigned AccessSize = 0; 389274955Ssvnmir 390274955Ssvnmir switch (Inst.getOpcode()) { 391274955Ssvnmir case X86::MOV8mi: 392274955Ssvnmir case X86::MOV8mr: 393274955Ssvnmir case X86::MOV8rm: 394274955Ssvnmir AccessSize = 1; 395274955Ssvnmir break; 396274955Ssvnmir case X86::MOV16mi: 397274955Ssvnmir case X86::MOV16mr: 398274955Ssvnmir case X86::MOV16rm: 399274955Ssvnmir AccessSize = 2; 400274955Ssvnmir break; 401274955Ssvnmir case X86::MOV32mi: 402274955Ssvnmir case X86::MOV32mr: 403274955Ssvnmir case X86::MOV32rm: 404274955Ssvnmir AccessSize = 4; 405274955Ssvnmir break; 406274955Ssvnmir case X86::MOV64mi32: 407274955Ssvnmir case X86::MOV64mr: 408274955Ssvnmir case X86::MOV64rm: 409274955Ssvnmir AccessSize = 8; 410274955Ssvnmir break; 411274955Ssvnmir case X86::MOVAPDmr: 412274955Ssvnmir case X86::MOVAPSmr: 413274955Ssvnmir case X86::MOVAPDrm: 414274955Ssvnmir case X86::MOVAPSrm: 415274955Ssvnmir AccessSize = 16; 416274955Ssvnmir break; 417274955Ssvnmir default: 418274955Ssvnmir return; 419274955Ssvnmir } 420274955Ssvnmir 421274955Ssvnmir const bool IsWrite = MII.get(Inst.getOpcode()).mayStore(); 422280031Sdim 423274955Ssvnmir for (unsigned Ix = 0; Ix < Operands.size(); ++Ix) { 424274955Ssvnmir assert(Operands[Ix]); 425274955Ssvnmir MCParsedAsmOperand &Op = *Operands[Ix]; 426280031Sdim if (Op.isMem()) { 427280031Sdim X86Operand &MemOp = static_cast<X86Operand &>(Op); 428280031Sdim RegisterContext RegCtx( 429280031Sdim X86::RDI /* AddressReg */, X86::RAX /* ShadowReg */, 430280031Sdim IsSmallMemAccess(AccessSize) ? X86::RCX 431280031Sdim : X86::NoRegister /* ScratchReg */); 432280031Sdim RegCtx.AddBusyRegs(MemOp); 433280031Sdim InstrumentMemOperandPrologue(RegCtx, Ctx, Out); 434280031Sdim InstrumentMemOperand(MemOp, AccessSize, IsWrite, RegCtx, Ctx, Out); 435280031Sdim InstrumentMemOperandEpilogue(RegCtx, Ctx, Out); 436280031Sdim } 437274955Ssvnmir } 438274955Ssvnmir} 439274955Ssvnmir 440280031Sdimvoid X86AddressSanitizer::ComputeMemOperandAddress(X86Operand &Op, 441280031Sdim MVT::SimpleValueType VT, 442280031Sdim unsigned Reg, MCContext &Ctx, 443280031Sdim MCStreamer &Out) { 444280031Sdim int64_t Displacement = 0; 445280031Sdim if (IsStackReg(Op.getMemBaseReg())) 446280031Sdim Displacement -= OrigSPOffset; 447280031Sdim if (IsStackReg(Op.getMemIndexReg())) 448280031Sdim Displacement -= OrigSPOffset * Op.getMemScale(); 449280031Sdim 450280031Sdim assert(Displacement >= 0); 451280031Sdim 452280031Sdim // Emit Op as is. 453280031Sdim if (Displacement == 0) { 454280031Sdim EmitLEA(Op, VT, Reg, Out); 455280031Sdim return; 456280031Sdim } 457280031Sdim 458280031Sdim int64_t Residue; 459280031Sdim std::unique_ptr<X86Operand> NewOp = 460280031Sdim AddDisplacement(Op, Displacement, Ctx, &Residue); 461280031Sdim EmitLEA(*NewOp, VT, Reg, Out); 462280031Sdim 463280031Sdim while (Residue != 0) { 464280031Sdim const MCConstantExpr *Disp = 465280031Sdim MCConstantExpr::Create(ApplyDisplacementBounds(Residue), Ctx); 466280031Sdim std::unique_ptr<X86Operand> DispOp = 467280031Sdim X86Operand::CreateMem(getPointerWidth(), 0, Disp, Reg, 0, 1, SMLoc(), 468280031Sdim SMLoc()); 469280031Sdim EmitLEA(*DispOp, VT, Reg, Out); 470280031Sdim Residue -= Disp->getValue(); 471280031Sdim } 472280031Sdim} 473280031Sdim 474280031Sdimstd::unique_ptr<X86Operand> 475280031SdimX86AddressSanitizer::AddDisplacement(X86Operand &Op, int64_t Displacement, 476280031Sdim MCContext &Ctx, int64_t *Residue) { 477280031Sdim assert(Displacement >= 0); 478280031Sdim 479280031Sdim if (Displacement == 0 || 480280031Sdim (Op.getMemDisp() && Op.getMemDisp()->getKind() != MCExpr::Constant)) { 481280031Sdim *Residue = Displacement; 482280031Sdim return X86Operand::CreateMem(Op.getMemModeSize(), Op.getMemSegReg(), 483280031Sdim Op.getMemDisp(), Op.getMemBaseReg(), 484280031Sdim Op.getMemIndexReg(), Op.getMemScale(), 485280031Sdim SMLoc(), SMLoc()); 486280031Sdim } 487280031Sdim 488280031Sdim int64_t OrigDisplacement = 489280031Sdim static_cast<const MCConstantExpr *>(Op.getMemDisp())->getValue(); 490280031Sdim CheckDisplacementBounds(OrigDisplacement); 491280031Sdim Displacement += OrigDisplacement; 492280031Sdim 493280031Sdim int64_t NewDisplacement = ApplyDisplacementBounds(Displacement); 494280031Sdim CheckDisplacementBounds(NewDisplacement); 495280031Sdim 496280031Sdim *Residue = Displacement - NewDisplacement; 497280031Sdim const MCExpr *Disp = MCConstantExpr::Create(NewDisplacement, Ctx); 498280031Sdim return X86Operand::CreateMem(Op.getMemModeSize(), Op.getMemSegReg(), Disp, 499280031Sdim Op.getMemBaseReg(), Op.getMemIndexReg(), 500280031Sdim Op.getMemScale(), SMLoc(), SMLoc()); 501280031Sdim} 502280031Sdim 503274955Ssvnmirclass X86AddressSanitizer32 : public X86AddressSanitizer { 504274955Ssvnmirpublic: 505274955Ssvnmir static const long kShadowOffset = 0x20000000; 506274955Ssvnmir 507274955Ssvnmir X86AddressSanitizer32(const MCSubtargetInfo &STI) 508274955Ssvnmir : X86AddressSanitizer(STI) {} 509280031Sdim 510274955Ssvnmir virtual ~X86AddressSanitizer32() {} 511274955Ssvnmir 512280031Sdim unsigned GetFrameReg(const MCContext &Ctx, MCStreamer &Out) { 513280031Sdim unsigned FrameReg = GetFrameRegGeneric(Ctx, Out); 514280031Sdim if (FrameReg == X86::NoRegister) 515280031Sdim return FrameReg; 516280031Sdim return getX86SubSuperRegister(FrameReg, MVT::i32); 517280031Sdim } 518274955Ssvnmir 519280031Sdim void SpillReg(MCStreamer &Out, unsigned Reg) { 520280031Sdim EmitInstruction(Out, MCInstBuilder(X86::PUSH32r).addReg(Reg)); 521280031Sdim OrigSPOffset -= 4; 522280031Sdim } 523280031Sdim 524280031Sdim void RestoreReg(MCStreamer &Out, unsigned Reg) { 525280031Sdim EmitInstruction(Out, MCInstBuilder(X86::POP32r).addReg(Reg)); 526280031Sdim OrigSPOffset += 4; 527280031Sdim } 528280031Sdim 529280031Sdim void StoreFlags(MCStreamer &Out) { 530280031Sdim EmitInstruction(Out, MCInstBuilder(X86::PUSHF32)); 531280031Sdim OrigSPOffset -= 4; 532280031Sdim } 533280031Sdim 534280031Sdim void RestoreFlags(MCStreamer &Out) { 535280031Sdim EmitInstruction(Out, MCInstBuilder(X86::POPF32)); 536280031Sdim OrigSPOffset += 4; 537280031Sdim } 538280031Sdim 539280031Sdim virtual void InstrumentMemOperandPrologue(const RegisterContext &RegCtx, 540280031Sdim MCContext &Ctx, 541280031Sdim MCStreamer &Out) override { 542280031Sdim unsigned LocalFrameReg = RegCtx.ChooseFrameReg(MVT::i32); 543280031Sdim assert(LocalFrameReg != X86::NoRegister); 544280031Sdim 545280031Sdim const MCRegisterInfo *MRI = Ctx.getRegisterInfo(); 546280031Sdim unsigned FrameReg = GetFrameReg(Ctx, Out); 547280031Sdim if (MRI && FrameReg != X86::NoRegister) { 548280031Sdim SpillReg(Out, LocalFrameReg); 549280031Sdim if (FrameReg == X86::ESP) { 550280031Sdim Out.EmitCFIAdjustCfaOffset(4 /* byte size of the LocalFrameReg */); 551280031Sdim Out.EmitCFIRelOffset( 552280031Sdim MRI->getDwarfRegNum(LocalFrameReg, true /* IsEH */), 0); 553280031Sdim } 554280031Sdim EmitInstruction( 555280031Sdim Out, 556280031Sdim MCInstBuilder(X86::MOV32rr).addReg(LocalFrameReg).addReg(FrameReg)); 557280031Sdim Out.EmitCFIRememberState(); 558280031Sdim Out.EmitCFIDefCfaRegister( 559280031Sdim MRI->getDwarfRegNum(LocalFrameReg, true /* IsEH */)); 560280031Sdim } 561280031Sdim 562280031Sdim SpillReg(Out, RegCtx.AddressReg(MVT::i32)); 563280031Sdim SpillReg(Out, RegCtx.ShadowReg(MVT::i32)); 564280031Sdim if (RegCtx.ScratchReg(MVT::i32) != X86::NoRegister) 565280031Sdim SpillReg(Out, RegCtx.ScratchReg(MVT::i32)); 566280031Sdim StoreFlags(Out); 567280031Sdim } 568280031Sdim 569280031Sdim virtual void InstrumentMemOperandEpilogue(const RegisterContext &RegCtx, 570280031Sdim MCContext &Ctx, 571280031Sdim MCStreamer &Out) override { 572280031Sdim unsigned LocalFrameReg = RegCtx.ChooseFrameReg(MVT::i32); 573280031Sdim assert(LocalFrameReg != X86::NoRegister); 574280031Sdim 575280031Sdim RestoreFlags(Out); 576280031Sdim if (RegCtx.ScratchReg(MVT::i32) != X86::NoRegister) 577280031Sdim RestoreReg(Out, RegCtx.ScratchReg(MVT::i32)); 578280031Sdim RestoreReg(Out, RegCtx.ShadowReg(MVT::i32)); 579280031Sdim RestoreReg(Out, RegCtx.AddressReg(MVT::i32)); 580280031Sdim 581280031Sdim unsigned FrameReg = GetFrameReg(Ctx, Out); 582280031Sdim if (Ctx.getRegisterInfo() && FrameReg != X86::NoRegister) { 583280031Sdim RestoreReg(Out, LocalFrameReg); 584280031Sdim Out.EmitCFIRestoreState(); 585280031Sdim if (FrameReg == X86::ESP) 586280031Sdim Out.EmitCFIAdjustCfaOffset(-4 /* byte size of the LocalFrameReg */); 587280031Sdim } 588280031Sdim } 589280031Sdim 590280031Sdim virtual void InstrumentMemOperandSmall(X86Operand &Op, unsigned AccessSize, 591280031Sdim bool IsWrite, 592280031Sdim const RegisterContext &RegCtx, 593280031Sdim MCContext &Ctx, 594280031Sdim MCStreamer &Out) override; 595280031Sdim virtual void InstrumentMemOperandLarge(X86Operand &Op, unsigned AccessSize, 596280031Sdim bool IsWrite, 597280031Sdim const RegisterContext &RegCtx, 598280031Sdim MCContext &Ctx, 599280031Sdim MCStreamer &Out) override; 600280031Sdim virtual void InstrumentMOVSImpl(unsigned AccessSize, MCContext &Ctx, 601280031Sdim MCStreamer &Out) override; 602280031Sdim 603280031Sdimprivate: 604280031Sdim void EmitCallAsanReport(unsigned AccessSize, bool IsWrite, MCContext &Ctx, 605280031Sdim MCStreamer &Out, const RegisterContext &RegCtx) { 606274955Ssvnmir EmitInstruction(Out, MCInstBuilder(X86::CLD)); 607274955Ssvnmir EmitInstruction(Out, MCInstBuilder(X86::MMX_EMMS)); 608274955Ssvnmir 609280031Sdim EmitInstruction(Out, MCInstBuilder(X86::AND64ri8) 610280031Sdim .addReg(X86::ESP) 611280031Sdim .addReg(X86::ESP) 612280031Sdim .addImm(-16)); 613280031Sdim EmitInstruction( 614280031Sdim Out, MCInstBuilder(X86::PUSH32r).addReg(RegCtx.AddressReg(MVT::i32))); 615274955Ssvnmir 616280031Sdim const std::string &Fn = FuncName(AccessSize, IsWrite); 617274955Ssvnmir MCSymbol *FnSym = Ctx.GetOrCreateSymbol(StringRef(Fn)); 618274955Ssvnmir const MCSymbolRefExpr *FnExpr = 619274955Ssvnmir MCSymbolRefExpr::Create(FnSym, MCSymbolRefExpr::VK_PLT, Ctx); 620274955Ssvnmir EmitInstruction(Out, MCInstBuilder(X86::CALLpcrel32).addExpr(FnExpr)); 621274955Ssvnmir } 622274955Ssvnmir}; 623274955Ssvnmir 624280031Sdimvoid X86AddressSanitizer32::InstrumentMemOperandSmall( 625280031Sdim X86Operand &Op, unsigned AccessSize, bool IsWrite, 626280031Sdim const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) { 627280031Sdim unsigned AddressRegI32 = RegCtx.AddressReg(MVT::i32); 628280031Sdim unsigned ShadowRegI32 = RegCtx.ShadowReg(MVT::i32); 629280031Sdim unsigned ShadowRegI8 = RegCtx.ShadowReg(MVT::i8); 630274955Ssvnmir 631280031Sdim assert(RegCtx.ScratchReg(MVT::i32) != X86::NoRegister); 632280031Sdim unsigned ScratchRegI32 = RegCtx.ScratchReg(MVT::i32); 633274955Ssvnmir 634280031Sdim ComputeMemOperandAddress(Op, MVT::i32, AddressRegI32, Ctx, Out); 635274955Ssvnmir 636280031Sdim EmitInstruction(Out, MCInstBuilder(X86::MOV32rr).addReg(ShadowRegI32).addReg( 637280031Sdim AddressRegI32)); 638280031Sdim EmitInstruction(Out, MCInstBuilder(X86::SHR32ri) 639280031Sdim .addReg(ShadowRegI32) 640280031Sdim .addReg(ShadowRegI32) 641280031Sdim .addImm(3)); 642280031Sdim 643274955Ssvnmir { 644274955Ssvnmir MCInst Inst; 645274955Ssvnmir Inst.setOpcode(X86::MOV8rm); 646280031Sdim Inst.addOperand(MCOperand::CreateReg(ShadowRegI8)); 647274955Ssvnmir const MCExpr *Disp = MCConstantExpr::Create(kShadowOffset, Ctx); 648274955Ssvnmir std::unique_ptr<X86Operand> Op( 649280031Sdim X86Operand::CreateMem(getPointerWidth(), 0, Disp, ShadowRegI32, 0, 1, 650280031Sdim SMLoc(), SMLoc())); 651274955Ssvnmir Op->addMemOperands(Inst, 5); 652274955Ssvnmir EmitInstruction(Out, Inst); 653274955Ssvnmir } 654274955Ssvnmir 655280031Sdim EmitInstruction( 656280031Sdim Out, MCInstBuilder(X86::TEST8rr).addReg(ShadowRegI8).addReg(ShadowRegI8)); 657274955Ssvnmir MCSymbol *DoneSym = Ctx.CreateTempSymbol(); 658274955Ssvnmir const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx); 659280031Sdim EmitInstruction(Out, MCInstBuilder(X86::JE_1).addExpr(DoneExpr)); 660274955Ssvnmir 661280031Sdim EmitInstruction(Out, MCInstBuilder(X86::MOV32rr).addReg(ScratchRegI32).addReg( 662280031Sdim AddressRegI32)); 663280031Sdim EmitInstruction(Out, MCInstBuilder(X86::AND32ri) 664280031Sdim .addReg(ScratchRegI32) 665280031Sdim .addReg(ScratchRegI32) 666280031Sdim .addImm(7)); 667274955Ssvnmir 668274955Ssvnmir switch (AccessSize) { 669280031Sdim default: llvm_unreachable("Incorrect access size"); 670274955Ssvnmir case 1: 671274955Ssvnmir break; 672274955Ssvnmir case 2: { 673274955Ssvnmir const MCExpr *Disp = MCConstantExpr::Create(1, Ctx); 674274955Ssvnmir std::unique_ptr<X86Operand> Op( 675280031Sdim X86Operand::CreateMem(getPointerWidth(), 0, Disp, ScratchRegI32, 0, 1, 676280031Sdim SMLoc(), SMLoc())); 677280031Sdim EmitLEA(*Op, MVT::i32, ScratchRegI32, Out); 678274955Ssvnmir break; 679274955Ssvnmir } 680274955Ssvnmir case 4: 681280031Sdim EmitInstruction(Out, MCInstBuilder(X86::ADD32ri8) 682280031Sdim .addReg(ScratchRegI32) 683280031Sdim .addReg(ScratchRegI32) 684280031Sdim .addImm(3)); 685274955Ssvnmir break; 686274955Ssvnmir } 687274955Ssvnmir 688274955Ssvnmir EmitInstruction( 689280031Sdim Out, 690280031Sdim MCInstBuilder(X86::MOVSX32rr8).addReg(ShadowRegI32).addReg(ShadowRegI8)); 691280031Sdim EmitInstruction(Out, MCInstBuilder(X86::CMP32rr).addReg(ScratchRegI32).addReg( 692280031Sdim ShadowRegI32)); 693280031Sdim EmitInstruction(Out, MCInstBuilder(X86::JL_1).addExpr(DoneExpr)); 694274955Ssvnmir 695280031Sdim EmitCallAsanReport(AccessSize, IsWrite, Ctx, Out, RegCtx); 696274955Ssvnmir EmitLabel(Out, DoneSym); 697274955Ssvnmir} 698274955Ssvnmir 699280031Sdimvoid X86AddressSanitizer32::InstrumentMemOperandLarge( 700280031Sdim X86Operand &Op, unsigned AccessSize, bool IsWrite, 701280031Sdim const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) { 702280031Sdim unsigned AddressRegI32 = RegCtx.AddressReg(MVT::i32); 703280031Sdim unsigned ShadowRegI32 = RegCtx.ShadowReg(MVT::i32); 704274955Ssvnmir 705280031Sdim ComputeMemOperandAddress(Op, MVT::i32, AddressRegI32, Ctx, Out); 706280031Sdim 707280031Sdim EmitInstruction(Out, MCInstBuilder(X86::MOV32rr).addReg(ShadowRegI32).addReg( 708280031Sdim AddressRegI32)); 709280031Sdim EmitInstruction(Out, MCInstBuilder(X86::SHR32ri) 710280031Sdim .addReg(ShadowRegI32) 711280031Sdim .addReg(ShadowRegI32) 712280031Sdim .addImm(3)); 713274955Ssvnmir { 714274955Ssvnmir MCInst Inst; 715274955Ssvnmir switch (AccessSize) { 716280031Sdim default: llvm_unreachable("Incorrect access size"); 717280031Sdim case 8: 718280031Sdim Inst.setOpcode(X86::CMP8mi); 719280031Sdim break; 720280031Sdim case 16: 721280031Sdim Inst.setOpcode(X86::CMP16mi); 722280031Sdim break; 723274955Ssvnmir } 724274955Ssvnmir const MCExpr *Disp = MCConstantExpr::Create(kShadowOffset, Ctx); 725274955Ssvnmir std::unique_ptr<X86Operand> Op( 726280031Sdim X86Operand::CreateMem(getPointerWidth(), 0, Disp, ShadowRegI32, 0, 1, 727280031Sdim SMLoc(), SMLoc())); 728274955Ssvnmir Op->addMemOperands(Inst, 5); 729274955Ssvnmir Inst.addOperand(MCOperand::CreateImm(0)); 730274955Ssvnmir EmitInstruction(Out, Inst); 731274955Ssvnmir } 732274955Ssvnmir MCSymbol *DoneSym = Ctx.CreateTempSymbol(); 733274955Ssvnmir const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx); 734280031Sdim EmitInstruction(Out, MCInstBuilder(X86::JE_1).addExpr(DoneExpr)); 735274955Ssvnmir 736280031Sdim EmitCallAsanReport(AccessSize, IsWrite, Ctx, Out, RegCtx); 737274955Ssvnmir EmitLabel(Out, DoneSym); 738280031Sdim} 739274955Ssvnmir 740280031Sdimvoid X86AddressSanitizer32::InstrumentMOVSImpl(unsigned AccessSize, 741280031Sdim MCContext &Ctx, 742280031Sdim MCStreamer &Out) { 743280031Sdim StoreFlags(Out); 744280031Sdim 745280031Sdim // No need to test when ECX is equals to zero. 746280031Sdim MCSymbol *DoneSym = Ctx.CreateTempSymbol(); 747280031Sdim const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx); 748280031Sdim EmitInstruction( 749280031Sdim Out, MCInstBuilder(X86::TEST32rr).addReg(X86::ECX).addReg(X86::ECX)); 750280031Sdim EmitInstruction(Out, MCInstBuilder(X86::JE_1).addExpr(DoneExpr)); 751280031Sdim 752280031Sdim // Instrument first and last elements in src and dst range. 753280031Sdim InstrumentMOVSBase(X86::EDI /* DstReg */, X86::ESI /* SrcReg */, 754280031Sdim X86::ECX /* CntReg */, AccessSize, Ctx, Out); 755280031Sdim 756280031Sdim EmitLabel(Out, DoneSym); 757280031Sdim RestoreFlags(Out); 758274955Ssvnmir} 759274955Ssvnmir 760274955Ssvnmirclass X86AddressSanitizer64 : public X86AddressSanitizer { 761274955Ssvnmirpublic: 762274955Ssvnmir static const long kShadowOffset = 0x7fff8000; 763274955Ssvnmir 764274955Ssvnmir X86AddressSanitizer64(const MCSubtargetInfo &STI) 765274955Ssvnmir : X86AddressSanitizer(STI) {} 766280031Sdim 767274955Ssvnmir virtual ~X86AddressSanitizer64() {} 768274955Ssvnmir 769280031Sdim unsigned GetFrameReg(const MCContext &Ctx, MCStreamer &Out) { 770280031Sdim unsigned FrameReg = GetFrameRegGeneric(Ctx, Out); 771280031Sdim if (FrameReg == X86::NoRegister) 772280031Sdim return FrameReg; 773280031Sdim return getX86SubSuperRegister(FrameReg, MVT::i64); 774280031Sdim } 775274955Ssvnmir 776280031Sdim void SpillReg(MCStreamer &Out, unsigned Reg) { 777280031Sdim EmitInstruction(Out, MCInstBuilder(X86::PUSH64r).addReg(Reg)); 778280031Sdim OrigSPOffset -= 8; 779280031Sdim } 780280031Sdim 781280031Sdim void RestoreReg(MCStreamer &Out, unsigned Reg) { 782280031Sdim EmitInstruction(Out, MCInstBuilder(X86::POP64r).addReg(Reg)); 783280031Sdim OrigSPOffset += 8; 784280031Sdim } 785280031Sdim 786280031Sdim void StoreFlags(MCStreamer &Out) { 787280031Sdim EmitInstruction(Out, MCInstBuilder(X86::PUSHF64)); 788280031Sdim OrigSPOffset -= 8; 789280031Sdim } 790280031Sdim 791280031Sdim void RestoreFlags(MCStreamer &Out) { 792280031Sdim EmitInstruction(Out, MCInstBuilder(X86::POPF64)); 793280031Sdim OrigSPOffset += 8; 794280031Sdim } 795280031Sdim 796280031Sdim virtual void InstrumentMemOperandPrologue(const RegisterContext &RegCtx, 797280031Sdim MCContext &Ctx, 798280031Sdim MCStreamer &Out) override { 799280031Sdim unsigned LocalFrameReg = RegCtx.ChooseFrameReg(MVT::i64); 800280031Sdim assert(LocalFrameReg != X86::NoRegister); 801280031Sdim 802280031Sdim const MCRegisterInfo *MRI = Ctx.getRegisterInfo(); 803280031Sdim unsigned FrameReg = GetFrameReg(Ctx, Out); 804280031Sdim if (MRI && FrameReg != X86::NoRegister) { 805280031Sdim SpillReg(Out, X86::RBP); 806280031Sdim if (FrameReg == X86::RSP) { 807280031Sdim Out.EmitCFIAdjustCfaOffset(8 /* byte size of the LocalFrameReg */); 808280031Sdim Out.EmitCFIRelOffset( 809280031Sdim MRI->getDwarfRegNum(LocalFrameReg, true /* IsEH */), 0); 810280031Sdim } 811280031Sdim EmitInstruction( 812280031Sdim Out, 813280031Sdim MCInstBuilder(X86::MOV64rr).addReg(LocalFrameReg).addReg(FrameReg)); 814280031Sdim Out.EmitCFIRememberState(); 815280031Sdim Out.EmitCFIDefCfaRegister( 816280031Sdim MRI->getDwarfRegNum(LocalFrameReg, true /* IsEH */)); 817280031Sdim } 818280031Sdim 819280031Sdim EmitAdjustRSP(Ctx, Out, -128); 820280031Sdim SpillReg(Out, RegCtx.ShadowReg(MVT::i64)); 821280031Sdim SpillReg(Out, RegCtx.AddressReg(MVT::i64)); 822280031Sdim if (RegCtx.ScratchReg(MVT::i64) != X86::NoRegister) 823280031Sdim SpillReg(Out, RegCtx.ScratchReg(MVT::i64)); 824280031Sdim StoreFlags(Out); 825280031Sdim } 826280031Sdim 827280031Sdim virtual void InstrumentMemOperandEpilogue(const RegisterContext &RegCtx, 828280031Sdim MCContext &Ctx, 829280031Sdim MCStreamer &Out) override { 830280031Sdim unsigned LocalFrameReg = RegCtx.ChooseFrameReg(MVT::i64); 831280031Sdim assert(LocalFrameReg != X86::NoRegister); 832280031Sdim 833280031Sdim RestoreFlags(Out); 834280031Sdim if (RegCtx.ScratchReg(MVT::i64) != X86::NoRegister) 835280031Sdim RestoreReg(Out, RegCtx.ScratchReg(MVT::i64)); 836280031Sdim RestoreReg(Out, RegCtx.AddressReg(MVT::i64)); 837280031Sdim RestoreReg(Out, RegCtx.ShadowReg(MVT::i64)); 838280031Sdim EmitAdjustRSP(Ctx, Out, 128); 839280031Sdim 840280031Sdim unsigned FrameReg = GetFrameReg(Ctx, Out); 841280031Sdim if (Ctx.getRegisterInfo() && FrameReg != X86::NoRegister) { 842280031Sdim RestoreReg(Out, LocalFrameReg); 843280031Sdim Out.EmitCFIRestoreState(); 844280031Sdim if (FrameReg == X86::RSP) 845280031Sdim Out.EmitCFIAdjustCfaOffset(-8 /* byte size of the LocalFrameReg */); 846280031Sdim } 847280031Sdim } 848280031Sdim 849280031Sdim virtual void InstrumentMemOperandSmall(X86Operand &Op, unsigned AccessSize, 850280031Sdim bool IsWrite, 851280031Sdim const RegisterContext &RegCtx, 852280031Sdim MCContext &Ctx, 853280031Sdim MCStreamer &Out) override; 854280031Sdim virtual void InstrumentMemOperandLarge(X86Operand &Op, unsigned AccessSize, 855280031Sdim bool IsWrite, 856280031Sdim const RegisterContext &RegCtx, 857280031Sdim MCContext &Ctx, 858280031Sdim MCStreamer &Out) override; 859280031Sdim virtual void InstrumentMOVSImpl(unsigned AccessSize, MCContext &Ctx, 860280031Sdim MCStreamer &Out) override; 861280031Sdim 862274955Ssvnmirprivate: 863274955Ssvnmir void EmitAdjustRSP(MCContext &Ctx, MCStreamer &Out, long Offset) { 864274955Ssvnmir const MCExpr *Disp = MCConstantExpr::Create(Offset, Ctx); 865274955Ssvnmir std::unique_ptr<X86Operand> Op( 866280031Sdim X86Operand::CreateMem(getPointerWidth(), 0, Disp, X86::RSP, 0, 1, 867280031Sdim SMLoc(), SMLoc())); 868280031Sdim EmitLEA(*Op, MVT::i64, X86::RSP, Out); 869280031Sdim OrigSPOffset += Offset; 870274955Ssvnmir } 871274955Ssvnmir 872280031Sdim void EmitCallAsanReport(unsigned AccessSize, bool IsWrite, MCContext &Ctx, 873280031Sdim MCStreamer &Out, const RegisterContext &RegCtx) { 874274955Ssvnmir EmitInstruction(Out, MCInstBuilder(X86::CLD)); 875274955Ssvnmir EmitInstruction(Out, MCInstBuilder(X86::MMX_EMMS)); 876274955Ssvnmir 877280031Sdim EmitInstruction(Out, MCInstBuilder(X86::AND64ri8) 878280031Sdim .addReg(X86::RSP) 879280031Sdim .addReg(X86::RSP) 880280031Sdim .addImm(-16)); 881274955Ssvnmir 882280031Sdim if (RegCtx.AddressReg(MVT::i64) != X86::RDI) { 883280031Sdim EmitInstruction(Out, MCInstBuilder(X86::MOV64rr).addReg(X86::RDI).addReg( 884280031Sdim RegCtx.AddressReg(MVT::i64))); 885280031Sdim } 886280031Sdim const std::string &Fn = FuncName(AccessSize, IsWrite); 887274955Ssvnmir MCSymbol *FnSym = Ctx.GetOrCreateSymbol(StringRef(Fn)); 888274955Ssvnmir const MCSymbolRefExpr *FnExpr = 889274955Ssvnmir MCSymbolRefExpr::Create(FnSym, MCSymbolRefExpr::VK_PLT, Ctx); 890274955Ssvnmir EmitInstruction(Out, MCInstBuilder(X86::CALL64pcrel32).addExpr(FnExpr)); 891274955Ssvnmir } 892274955Ssvnmir}; 893274955Ssvnmir 894280031Sdimvoid X86AddressSanitizer64::InstrumentMemOperandSmall( 895280031Sdim X86Operand &Op, unsigned AccessSize, bool IsWrite, 896280031Sdim const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) { 897280031Sdim unsigned AddressRegI64 = RegCtx.AddressReg(MVT::i64); 898280031Sdim unsigned AddressRegI32 = RegCtx.AddressReg(MVT::i32); 899280031Sdim unsigned ShadowRegI64 = RegCtx.ShadowReg(MVT::i64); 900280031Sdim unsigned ShadowRegI32 = RegCtx.ShadowReg(MVT::i32); 901280031Sdim unsigned ShadowRegI8 = RegCtx.ShadowReg(MVT::i8); 902280031Sdim 903280031Sdim assert(RegCtx.ScratchReg(MVT::i32) != X86::NoRegister); 904280031Sdim unsigned ScratchRegI32 = RegCtx.ScratchReg(MVT::i32); 905280031Sdim 906280031Sdim ComputeMemOperandAddress(Op, MVT::i64, AddressRegI64, Ctx, Out); 907280031Sdim 908280031Sdim EmitInstruction(Out, MCInstBuilder(X86::MOV64rr).addReg(ShadowRegI64).addReg( 909280031Sdim AddressRegI64)); 910280031Sdim EmitInstruction(Out, MCInstBuilder(X86::SHR64ri) 911280031Sdim .addReg(ShadowRegI64) 912280031Sdim .addReg(ShadowRegI64) 913280031Sdim .addImm(3)); 914274955Ssvnmir { 915274955Ssvnmir MCInst Inst; 916274955Ssvnmir Inst.setOpcode(X86::MOV8rm); 917280031Sdim Inst.addOperand(MCOperand::CreateReg(ShadowRegI8)); 918274955Ssvnmir const MCExpr *Disp = MCConstantExpr::Create(kShadowOffset, Ctx); 919274955Ssvnmir std::unique_ptr<X86Operand> Op( 920280031Sdim X86Operand::CreateMem(getPointerWidth(), 0, Disp, ShadowRegI64, 0, 1, 921280031Sdim SMLoc(), SMLoc())); 922274955Ssvnmir Op->addMemOperands(Inst, 5); 923274955Ssvnmir EmitInstruction(Out, Inst); 924274955Ssvnmir } 925274955Ssvnmir 926280031Sdim EmitInstruction( 927280031Sdim Out, MCInstBuilder(X86::TEST8rr).addReg(ShadowRegI8).addReg(ShadowRegI8)); 928274955Ssvnmir MCSymbol *DoneSym = Ctx.CreateTempSymbol(); 929274955Ssvnmir const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx); 930280031Sdim EmitInstruction(Out, MCInstBuilder(X86::JE_1).addExpr(DoneExpr)); 931274955Ssvnmir 932280031Sdim EmitInstruction(Out, MCInstBuilder(X86::MOV32rr).addReg(ScratchRegI32).addReg( 933280031Sdim AddressRegI32)); 934280031Sdim EmitInstruction(Out, MCInstBuilder(X86::AND32ri) 935280031Sdim .addReg(ScratchRegI32) 936280031Sdim .addReg(ScratchRegI32) 937280031Sdim .addImm(7)); 938274955Ssvnmir 939274955Ssvnmir switch (AccessSize) { 940280031Sdim default: llvm_unreachable("Incorrect access size"); 941274955Ssvnmir case 1: 942274955Ssvnmir break; 943274955Ssvnmir case 2: { 944274955Ssvnmir const MCExpr *Disp = MCConstantExpr::Create(1, Ctx); 945274955Ssvnmir std::unique_ptr<X86Operand> Op( 946280031Sdim X86Operand::CreateMem(getPointerWidth(), 0, Disp, ScratchRegI32, 0, 1, 947280031Sdim SMLoc(), SMLoc())); 948280031Sdim EmitLEA(*Op, MVT::i32, ScratchRegI32, Out); 949274955Ssvnmir break; 950274955Ssvnmir } 951274955Ssvnmir case 4: 952280031Sdim EmitInstruction(Out, MCInstBuilder(X86::ADD32ri8) 953280031Sdim .addReg(ScratchRegI32) 954280031Sdim .addReg(ScratchRegI32) 955280031Sdim .addImm(3)); 956274955Ssvnmir break; 957274955Ssvnmir } 958274955Ssvnmir 959274955Ssvnmir EmitInstruction( 960280031Sdim Out, 961280031Sdim MCInstBuilder(X86::MOVSX32rr8).addReg(ShadowRegI32).addReg(ShadowRegI8)); 962280031Sdim EmitInstruction(Out, MCInstBuilder(X86::CMP32rr).addReg(ScratchRegI32).addReg( 963280031Sdim ShadowRegI32)); 964280031Sdim EmitInstruction(Out, MCInstBuilder(X86::JL_1).addExpr(DoneExpr)); 965274955Ssvnmir 966280031Sdim EmitCallAsanReport(AccessSize, IsWrite, Ctx, Out, RegCtx); 967274955Ssvnmir EmitLabel(Out, DoneSym); 968274955Ssvnmir} 969274955Ssvnmir 970280031Sdimvoid X86AddressSanitizer64::InstrumentMemOperandLarge( 971280031Sdim X86Operand &Op, unsigned AccessSize, bool IsWrite, 972280031Sdim const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) { 973280031Sdim unsigned AddressRegI64 = RegCtx.AddressReg(MVT::i64); 974280031Sdim unsigned ShadowRegI64 = RegCtx.ShadowReg(MVT::i64); 975274955Ssvnmir 976280031Sdim ComputeMemOperandAddress(Op, MVT::i64, AddressRegI64, Ctx, Out); 977280031Sdim 978280031Sdim EmitInstruction(Out, MCInstBuilder(X86::MOV64rr).addReg(ShadowRegI64).addReg( 979280031Sdim AddressRegI64)); 980280031Sdim EmitInstruction(Out, MCInstBuilder(X86::SHR64ri) 981280031Sdim .addReg(ShadowRegI64) 982280031Sdim .addReg(ShadowRegI64) 983280031Sdim .addImm(3)); 984274955Ssvnmir { 985274955Ssvnmir MCInst Inst; 986274955Ssvnmir switch (AccessSize) { 987280031Sdim default: llvm_unreachable("Incorrect access size"); 988274955Ssvnmir case 8: 989274955Ssvnmir Inst.setOpcode(X86::CMP8mi); 990274955Ssvnmir break; 991274955Ssvnmir case 16: 992274955Ssvnmir Inst.setOpcode(X86::CMP16mi); 993274955Ssvnmir break; 994274955Ssvnmir } 995274955Ssvnmir const MCExpr *Disp = MCConstantExpr::Create(kShadowOffset, Ctx); 996274955Ssvnmir std::unique_ptr<X86Operand> Op( 997280031Sdim X86Operand::CreateMem(getPointerWidth(), 0, Disp, ShadowRegI64, 0, 1, 998280031Sdim SMLoc(), SMLoc())); 999274955Ssvnmir Op->addMemOperands(Inst, 5); 1000274955Ssvnmir Inst.addOperand(MCOperand::CreateImm(0)); 1001274955Ssvnmir EmitInstruction(Out, Inst); 1002274955Ssvnmir } 1003274955Ssvnmir 1004274955Ssvnmir MCSymbol *DoneSym = Ctx.CreateTempSymbol(); 1005274955Ssvnmir const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx); 1006280031Sdim EmitInstruction(Out, MCInstBuilder(X86::JE_1).addExpr(DoneExpr)); 1007274955Ssvnmir 1008280031Sdim EmitCallAsanReport(AccessSize, IsWrite, Ctx, Out, RegCtx); 1009274955Ssvnmir EmitLabel(Out, DoneSym); 1010280031Sdim} 1011274955Ssvnmir 1012280031Sdimvoid X86AddressSanitizer64::InstrumentMOVSImpl(unsigned AccessSize, 1013280031Sdim MCContext &Ctx, 1014280031Sdim MCStreamer &Out) { 1015280031Sdim StoreFlags(Out); 1016280031Sdim 1017280031Sdim // No need to test when RCX is equals to zero. 1018280031Sdim MCSymbol *DoneSym = Ctx.CreateTempSymbol(); 1019280031Sdim const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx); 1020280031Sdim EmitInstruction( 1021280031Sdim Out, MCInstBuilder(X86::TEST64rr).addReg(X86::RCX).addReg(X86::RCX)); 1022280031Sdim EmitInstruction(Out, MCInstBuilder(X86::JE_1).addExpr(DoneExpr)); 1023280031Sdim 1024280031Sdim // Instrument first and last elements in src and dst range. 1025280031Sdim InstrumentMOVSBase(X86::RDI /* DstReg */, X86::RSI /* SrcReg */, 1026280031Sdim X86::RCX /* CntReg */, AccessSize, Ctx, Out); 1027280031Sdim 1028280031Sdim EmitLabel(Out, DoneSym); 1029280031Sdim RestoreFlags(Out); 1030274955Ssvnmir} 1031274955Ssvnmir 1032274955Ssvnmir} // End anonymous namespace 1033274955Ssvnmir 1034280031SdimX86AsmInstrumentation::X86AsmInstrumentation(const MCSubtargetInfo &STI) 1035280031Sdim : STI(STI), InitialFrameReg(0) {} 1036280031Sdim 1037274955SsvnmirX86AsmInstrumentation::~X86AsmInstrumentation() {} 1038274955Ssvnmir 1039280031Sdimvoid X86AsmInstrumentation::InstrumentAndEmitInstruction( 1040274955Ssvnmir const MCInst &Inst, OperandVector &Operands, MCContext &Ctx, 1041280031Sdim const MCInstrInfo &MII, MCStreamer &Out) { 1042280031Sdim EmitInstruction(Out, Inst); 1043280031Sdim} 1044274955Ssvnmir 1045280031Sdimvoid X86AsmInstrumentation::EmitInstruction(MCStreamer &Out, 1046280031Sdim const MCInst &Inst) { 1047280031Sdim Out.EmitInstruction(Inst, STI); 1048280031Sdim} 1049280031Sdim 1050280031Sdimunsigned X86AsmInstrumentation::GetFrameRegGeneric(const MCContext &Ctx, 1051280031Sdim MCStreamer &Out) { 1052280031Sdim if (!Out.getNumFrameInfos()) // No active dwarf frame 1053280031Sdim return X86::NoRegister; 1054280031Sdim const MCDwarfFrameInfo &Frame = Out.getDwarfFrameInfos().back(); 1055280031Sdim if (Frame.End) // Active dwarf frame is closed 1056280031Sdim return X86::NoRegister; 1057280031Sdim const MCRegisterInfo *MRI = Ctx.getRegisterInfo(); 1058280031Sdim if (!MRI) // No register info 1059280031Sdim return X86::NoRegister; 1060280031Sdim 1061280031Sdim if (InitialFrameReg) { 1062280031Sdim // FrameReg is set explicitly, we're instrumenting a MachineFunction. 1063280031Sdim return InitialFrameReg; 1064280031Sdim } 1065280031Sdim 1066280031Sdim return MRI->getLLVMRegNum(Frame.CurrentCfaRegister, true /* IsEH */); 1067280031Sdim} 1068280031Sdim 1069274955SsvnmirX86AsmInstrumentation * 1070274955SsvnmirCreateX86AsmInstrumentation(const MCTargetOptions &MCOptions, 1071274955Ssvnmir const MCContext &Ctx, const MCSubtargetInfo &STI) { 1072274955Ssvnmir Triple T(STI.getTargetTriple()); 1073274955Ssvnmir const bool hasCompilerRTSupport = T.isOSLinux(); 1074274955Ssvnmir if (ClAsanInstrumentAssembly && hasCompilerRTSupport && 1075274955Ssvnmir MCOptions.SanitizeAddress) { 1076274955Ssvnmir if ((STI.getFeatureBits() & X86::Mode32Bit) != 0) 1077274955Ssvnmir return new X86AddressSanitizer32(STI); 1078274955Ssvnmir if ((STI.getFeatureBits() & X86::Mode64Bit) != 0) 1079274955Ssvnmir return new X86AddressSanitizer64(STI); 1080274955Ssvnmir } 1081280031Sdim return new X86AsmInstrumentation(STI); 1082274955Ssvnmir} 1083274955Ssvnmir 1084274955Ssvnmir} // End llvm namespace 1085