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" 13274955Ssvnmir#include "llvm/ADT/StringExtras.h" 14274955Ssvnmir#include "llvm/ADT/Triple.h" 15280031Sdim#include "llvm/MC/MCAsmInfo.h" 16274955Ssvnmir#include "llvm/MC/MCContext.h" 17274955Ssvnmir#include "llvm/MC/MCInst.h" 18274955Ssvnmir#include "llvm/MC/MCInstBuilder.h" 19274955Ssvnmir#include "llvm/MC/MCInstrInfo.h" 20274955Ssvnmir#include "llvm/MC/MCParser/MCParsedAsmOperand.h" 21274955Ssvnmir#include "llvm/MC/MCStreamer.h" 22274955Ssvnmir#include "llvm/MC/MCSubtargetInfo.h" 23274955Ssvnmir#include "llvm/MC/MCTargetAsmParser.h" 24274955Ssvnmir#include "llvm/MC/MCTargetOptions.h" 25274955Ssvnmir#include "llvm/Support/CommandLine.h" 26280031Sdim#include <algorithm> 27280031Sdim#include <cassert> 28280031Sdim#include <vector> 29274955Ssvnmir 30280031Sdim// Following comment describes how assembly instrumentation works. 31280031Sdim// Currently we have only AddressSanitizer instrumentation, but we're 32280031Sdim// planning to implement MemorySanitizer for inline assembly too. If 33280031Sdim// you're not familiar with AddressSanitizer algorithm, please, read 34280031Sdim// https://code.google.com/p/address-sanitizer/wiki/AddressSanitizerAlgorithm. 35280031Sdim// 36280031Sdim// When inline assembly is parsed by an instance of X86AsmParser, all 37280031Sdim// instructions are emitted via EmitInstruction method. That's the 38280031Sdim// place where X86AsmInstrumentation analyzes an instruction and 39280031Sdim// decides, whether the instruction should be emitted as is or 40280031Sdim// instrumentation is required. The latter case happens when an 41280031Sdim// instruction reads from or writes to memory. Now instruction opcode 42280031Sdim// is explicitly checked, and if an instruction has a memory operand 43280031Sdim// (for instance, movq (%rsi, %rcx, 8), %rax) - it should be 44280031Sdim// instrumented. There're also exist instructions that modify 45280031Sdim// memory but don't have an explicit memory operands, for instance, 46280031Sdim// movs. 47280031Sdim// 48280031Sdim// Let's consider at first 8-byte memory accesses when an instruction 49280031Sdim// has an explicit memory operand. In this case we need two registers - 50280031Sdim// AddressReg to compute address of a memory cells which are accessed 51280031Sdim// and ShadowReg to compute corresponding shadow address. So, we need 52280031Sdim// to spill both registers before instrumentation code and restore them 53280031Sdim// after instrumentation. Thus, in general, instrumentation code will 54280031Sdim// look like this: 55280031Sdim// PUSHF # Store flags, otherwise they will be overwritten 56280031Sdim// PUSH AddressReg # spill AddressReg 57280031Sdim// PUSH ShadowReg # spill ShadowReg 58280031Sdim// LEA MemOp, AddressReg # compute address of the memory operand 59280031Sdim// MOV AddressReg, ShadowReg 60280031Sdim// SHR ShadowReg, 3 61280031Sdim// # ShadowOffset(AddressReg >> 3) contains address of a shadow 62280031Sdim// # corresponding to MemOp. 63280031Sdim// CMP ShadowOffset(ShadowReg), 0 # test shadow value 64280031Sdim// JZ .Done # when shadow equals to zero, everything is fine 65280031Sdim// MOV AddressReg, RDI 66280031Sdim// # Call __asan_report function with AddressReg as an argument 67280031Sdim// CALL __asan_report 68280031Sdim// .Done: 69280031Sdim// POP ShadowReg # Restore ShadowReg 70280031Sdim// POP AddressReg # Restore AddressReg 71280031Sdim// POPF # Restore flags 72280031Sdim// 73280031Sdim// Memory accesses with different size (1-, 2-, 4- and 16-byte) are 74280031Sdim// handled in a similar manner, but small memory accesses (less than 8 75280031Sdim// byte) require an additional ScratchReg, which is used for shadow value. 76280031Sdim// 77280031Sdim// If, suppose, we're instrumenting an instruction like movs, only 78280031Sdim// contents of RDI, RDI + AccessSize * RCX, RSI, RSI + AccessSize * 79280031Sdim// RCX are checked. In this case there're no need to spill and restore 80280031Sdim// AddressReg , ShadowReg or flags four times, they're saved on stack 81280031Sdim// just once, before instrumentation of these four addresses, and restored 82280031Sdim// at the end of the instrumentation. 83280031Sdim// 84280031Sdim// There exist several things which complicate this simple algorithm. 85280031Sdim// * Instrumented memory operand can have RSP as a base or an index 86280031Sdim// register. So we need to add a constant offset before computation 87280031Sdim// of memory address, since flags, AddressReg, ShadowReg, etc. were 88280031Sdim// already stored on stack and RSP was modified. 89280031Sdim// * Debug info (usually, DWARF) should be adjusted, because sometimes 90280031Sdim// RSP is used as a frame register. So, we need to select some 91280031Sdim// register as a frame register and temprorary override current CFA 92280031Sdim// register. 93280031Sdim 94274955Ssvnmirnamespace llvm { 95274955Ssvnmirnamespace { 96274955Ssvnmir 97274955Ssvnmirstatic cl::opt<bool> ClAsanInstrumentAssembly( 98274955Ssvnmir "asan-instrument-assembly", 99274955Ssvnmir cl::desc("instrument assembly with AddressSanitizer checks"), cl::Hidden, 100274955Ssvnmir cl::init(false)); 101274955Ssvnmir 102280031Sdimconst int64_t MinAllowedDisplacement = std::numeric_limits<int32_t>::min(); 103280031Sdimconst int64_t MaxAllowedDisplacement = std::numeric_limits<int32_t>::max(); 104280031Sdim 105280031Sdimint64_t ApplyDisplacementBounds(int64_t Displacement) { 106280031Sdim return std::max(std::min(MaxAllowedDisplacement, Displacement), 107280031Sdim MinAllowedDisplacement); 108274955Ssvnmir} 109274955Ssvnmir 110280031Sdimvoid CheckDisplacementBounds(int64_t Displacement) { 111280031Sdim assert(Displacement >= MinAllowedDisplacement && 112280031Sdim Displacement <= MaxAllowedDisplacement); 113280031Sdim} 114280031Sdim 115280031Sdimbool IsStackReg(unsigned Reg) { return Reg == X86::RSP || Reg == X86::ESP; } 116280031Sdim 117280031Sdimbool IsSmallMemAccess(unsigned AccessSize) { return AccessSize < 8; } 118280031Sdim 119274955Ssvnmirclass X86AddressSanitizer : public X86AsmInstrumentation { 120274955Ssvnmirpublic: 121280031Sdim struct RegisterContext { 122280031Sdim private: 123280031Sdim enum RegOffset { 124280031Sdim REG_OFFSET_ADDRESS = 0, 125280031Sdim REG_OFFSET_SHADOW, 126280031Sdim REG_OFFSET_SCRATCH 127280031Sdim }; 128280031Sdim 129280031Sdim public: 130280031Sdim RegisterContext(unsigned AddressReg, unsigned ShadowReg, 131280031Sdim unsigned ScratchReg) { 132296417Sdim BusyRegs.push_back(convReg(AddressReg, 64)); 133296417Sdim BusyRegs.push_back(convReg(ShadowReg, 64)); 134296417Sdim BusyRegs.push_back(convReg(ScratchReg, 64)); 135280031Sdim } 136280031Sdim 137296417Sdim unsigned AddressReg(unsigned Size) const { 138296417Sdim return convReg(BusyRegs[REG_OFFSET_ADDRESS], Size); 139280031Sdim } 140280031Sdim 141296417Sdim unsigned ShadowReg(unsigned Size) const { 142296417Sdim return convReg(BusyRegs[REG_OFFSET_SHADOW], Size); 143280031Sdim } 144280031Sdim 145296417Sdim unsigned ScratchReg(unsigned Size) const { 146296417Sdim return convReg(BusyRegs[REG_OFFSET_SCRATCH], Size); 147280031Sdim } 148280031Sdim 149280031Sdim void AddBusyReg(unsigned Reg) { 150280031Sdim if (Reg != X86::NoRegister) 151296417Sdim BusyRegs.push_back(convReg(Reg, 64)); 152280031Sdim } 153280031Sdim 154280031Sdim void AddBusyRegs(const X86Operand &Op) { 155280031Sdim AddBusyReg(Op.getMemBaseReg()); 156280031Sdim AddBusyReg(Op.getMemIndexReg()); 157280031Sdim } 158280031Sdim 159296417Sdim unsigned ChooseFrameReg(unsigned Size) const { 160280031Sdim static const MCPhysReg Candidates[] = { X86::RBP, X86::RAX, X86::RBX, 161280031Sdim X86::RCX, X86::RDX, X86::RDI, 162280031Sdim X86::RSI }; 163280031Sdim for (unsigned Reg : Candidates) { 164280031Sdim if (!std::count(BusyRegs.begin(), BusyRegs.end(), Reg)) 165296417Sdim return convReg(Reg, Size); 166280031Sdim } 167280031Sdim return X86::NoRegister; 168280031Sdim } 169280031Sdim 170280031Sdim private: 171296417Sdim unsigned convReg(unsigned Reg, unsigned Size) const { 172296417Sdim return Reg == X86::NoRegister ? Reg : getX86SubSuperRegister(Reg, Size); 173280031Sdim } 174280031Sdim 175280031Sdim std::vector<unsigned> BusyRegs; 176280031Sdim }; 177280031Sdim 178296417Sdim X86AddressSanitizer(const MCSubtargetInfo *&STI) 179280031Sdim : X86AsmInstrumentation(STI), RepPrefix(false), OrigSPOffset(0) {} 180280031Sdim 181296417Sdim ~X86AddressSanitizer() override {} 182274955Ssvnmir 183274955Ssvnmir // X86AsmInstrumentation implementation: 184296417Sdim void InstrumentAndEmitInstruction(const MCInst &Inst, 185296417Sdim OperandVector &Operands, 186296417Sdim MCContext &Ctx, 187296417Sdim const MCInstrInfo &MII, 188296417Sdim MCStreamer &Out) override { 189280031Sdim InstrumentMOVS(Inst, Operands, Ctx, MII, Out); 190280031Sdim if (RepPrefix) 191280031Sdim EmitInstruction(Out, MCInstBuilder(X86::REP_PREFIX)); 192280031Sdim 193274955Ssvnmir InstrumentMOV(Inst, Operands, Ctx, MII, Out); 194280031Sdim 195280031Sdim RepPrefix = (Inst.getOpcode() == X86::REP_PREFIX); 196280031Sdim if (!RepPrefix) 197280031Sdim EmitInstruction(Out, Inst); 198274955Ssvnmir } 199274955Ssvnmir 200280031Sdim // Adjusts up stack and saves all registers used in instrumentation. 201280031Sdim virtual void InstrumentMemOperandPrologue(const RegisterContext &RegCtx, 202280031Sdim MCContext &Ctx, 203280031Sdim MCStreamer &Out) = 0; 204274955Ssvnmir 205280031Sdim // Restores all registers used in instrumentation and adjusts stack. 206280031Sdim virtual void InstrumentMemOperandEpilogue(const RegisterContext &RegCtx, 207280031Sdim MCContext &Ctx, 208280031Sdim MCStreamer &Out) = 0; 209280031Sdim 210280031Sdim virtual void InstrumentMemOperandSmall(X86Operand &Op, unsigned AccessSize, 211280031Sdim bool IsWrite, 212280031Sdim const RegisterContext &RegCtx, 213280031Sdim MCContext &Ctx, MCStreamer &Out) = 0; 214280031Sdim virtual void InstrumentMemOperandLarge(X86Operand &Op, unsigned AccessSize, 215280031Sdim bool IsWrite, 216280031Sdim const RegisterContext &RegCtx, 217280031Sdim MCContext &Ctx, MCStreamer &Out) = 0; 218280031Sdim 219280031Sdim virtual void InstrumentMOVSImpl(unsigned AccessSize, MCContext &Ctx, 220280031Sdim MCStreamer &Out) = 0; 221280031Sdim 222280031Sdim void InstrumentMemOperand(X86Operand &Op, unsigned AccessSize, bool IsWrite, 223280031Sdim const RegisterContext &RegCtx, MCContext &Ctx, 224280031Sdim MCStreamer &Out); 225280031Sdim void InstrumentMOVSBase(unsigned DstReg, unsigned SrcReg, unsigned CntReg, 226280031Sdim unsigned AccessSize, MCContext &Ctx, MCStreamer &Out); 227280031Sdim 228280031Sdim void InstrumentMOVS(const MCInst &Inst, OperandVector &Operands, 229280031Sdim MCContext &Ctx, const MCInstrInfo &MII, MCStreamer &Out); 230274955Ssvnmir void InstrumentMOV(const MCInst &Inst, OperandVector &Operands, 231274955Ssvnmir MCContext &Ctx, const MCInstrInfo &MII, MCStreamer &Out); 232274955Ssvnmir 233280031Sdimprotected: 234274955Ssvnmir void EmitLabel(MCStreamer &Out, MCSymbol *Label) { Out.EmitLabel(Label); } 235274955Ssvnmir 236296417Sdim void EmitLEA(X86Operand &Op, unsigned Size, unsigned Reg, MCStreamer &Out) { 237296417Sdim assert(Size == 32 || Size == 64); 238280031Sdim MCInst Inst; 239296417Sdim Inst.setOpcode(Size == 32 ? X86::LEA32r : X86::LEA64r); 240296417Sdim Inst.addOperand(MCOperand::createReg(getX86SubSuperRegister(Reg, Size))); 241280031Sdim Op.addMemOperands(Inst, 5); 242280031Sdim EmitInstruction(Out, Inst); 243280031Sdim } 244280031Sdim 245296417Sdim void ComputeMemOperandAddress(X86Operand &Op, unsigned Size, 246280031Sdim unsigned Reg, MCContext &Ctx, MCStreamer &Out); 247280031Sdim 248280031Sdim // Creates new memory operand with Displacement added to an original 249280031Sdim // displacement. Residue will contain a residue which could happen when the 250280031Sdim // total displacement exceeds 32-bit limitation. 251280031Sdim std::unique_ptr<X86Operand> AddDisplacement(X86Operand &Op, 252280031Sdim int64_t Displacement, 253280031Sdim MCContext &Ctx, int64_t *Residue); 254280031Sdim 255280031Sdim bool is64BitMode() const { 256296417Sdim return STI->getFeatureBits()[X86::Mode64Bit]; 257280031Sdim } 258280031Sdim bool is32BitMode() const { 259296417Sdim return STI->getFeatureBits()[X86::Mode32Bit]; 260280031Sdim } 261280031Sdim bool is16BitMode() const { 262296417Sdim return STI->getFeatureBits()[X86::Mode16Bit]; 263280031Sdim } 264280031Sdim 265280031Sdim unsigned getPointerWidth() { 266280031Sdim if (is16BitMode()) return 16; 267280031Sdim if (is32BitMode()) return 32; 268280031Sdim if (is64BitMode()) return 64; 269280031Sdim llvm_unreachable("invalid mode"); 270280031Sdim } 271280031Sdim 272280031Sdim // True when previous instruction was actually REP prefix. 273280031Sdim bool RepPrefix; 274280031Sdim 275280031Sdim // Offset from the original SP register. 276280031Sdim int64_t OrigSPOffset; 277274955Ssvnmir}; 278274955Ssvnmir 279274955Ssvnmirvoid X86AddressSanitizer::InstrumentMemOperand( 280280031Sdim X86Operand &Op, unsigned AccessSize, bool IsWrite, 281280031Sdim const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) { 282274955Ssvnmir assert(Op.isMem() && "Op should be a memory operand."); 283274955Ssvnmir assert((AccessSize & (AccessSize - 1)) == 0 && AccessSize <= 16 && 284274955Ssvnmir "AccessSize should be a power of two, less or equal than 16."); 285280031Sdim // FIXME: take into account load/store alignment. 286280031Sdim if (IsSmallMemAccess(AccessSize)) 287280031Sdim InstrumentMemOperandSmall(Op, AccessSize, IsWrite, RegCtx, Ctx, Out); 288280031Sdim else 289280031Sdim InstrumentMemOperandLarge(Op, AccessSize, IsWrite, RegCtx, Ctx, Out); 290280031Sdim} 291274955Ssvnmir 292280031Sdimvoid X86AddressSanitizer::InstrumentMOVSBase(unsigned DstReg, unsigned SrcReg, 293280031Sdim unsigned CntReg, 294280031Sdim unsigned AccessSize, 295280031Sdim MCContext &Ctx, MCStreamer &Out) { 296280031Sdim // FIXME: check whole ranges [DstReg .. DstReg + AccessSize * (CntReg - 1)] 297280031Sdim // and [SrcReg .. SrcReg + AccessSize * (CntReg - 1)]. 298280031Sdim RegisterContext RegCtx(X86::RDX /* AddressReg */, X86::RAX /* ShadowReg */, 299280031Sdim IsSmallMemAccess(AccessSize) 300280031Sdim ? X86::RBX 301280031Sdim : X86::NoRegister /* ScratchReg */); 302280031Sdim RegCtx.AddBusyReg(DstReg); 303280031Sdim RegCtx.AddBusyReg(SrcReg); 304280031Sdim RegCtx.AddBusyReg(CntReg); 305280031Sdim 306280031Sdim InstrumentMemOperandPrologue(RegCtx, Ctx, Out); 307280031Sdim 308280031Sdim // Test (%SrcReg) 309280031Sdim { 310288943Sdim const MCExpr *Disp = MCConstantExpr::create(0, Ctx); 311280031Sdim std::unique_ptr<X86Operand> Op(X86Operand::CreateMem( 312280031Sdim getPointerWidth(), 0, Disp, SrcReg, 0, AccessSize, SMLoc(), SMLoc())); 313280031Sdim InstrumentMemOperand(*Op, AccessSize, false /* IsWrite */, RegCtx, Ctx, 314280031Sdim Out); 315280031Sdim } 316280031Sdim 317280031Sdim // Test -1(%SrcReg, %CntReg, AccessSize) 318280031Sdim { 319288943Sdim const MCExpr *Disp = MCConstantExpr::create(-1, Ctx); 320280031Sdim std::unique_ptr<X86Operand> Op(X86Operand::CreateMem( 321280031Sdim getPointerWidth(), 0, Disp, SrcReg, CntReg, AccessSize, SMLoc(), 322280031Sdim SMLoc())); 323280031Sdim InstrumentMemOperand(*Op, AccessSize, false /* IsWrite */, RegCtx, Ctx, 324280031Sdim Out); 325280031Sdim } 326280031Sdim 327280031Sdim // Test (%DstReg) 328280031Sdim { 329288943Sdim const MCExpr *Disp = MCConstantExpr::create(0, Ctx); 330280031Sdim std::unique_ptr<X86Operand> Op(X86Operand::CreateMem( 331280031Sdim getPointerWidth(), 0, Disp, DstReg, 0, AccessSize, SMLoc(), SMLoc())); 332280031Sdim InstrumentMemOperand(*Op, AccessSize, true /* IsWrite */, RegCtx, Ctx, Out); 333280031Sdim } 334280031Sdim 335280031Sdim // Test -1(%DstReg, %CntReg, AccessSize) 336280031Sdim { 337288943Sdim const MCExpr *Disp = MCConstantExpr::create(-1, Ctx); 338280031Sdim std::unique_ptr<X86Operand> Op(X86Operand::CreateMem( 339280031Sdim getPointerWidth(), 0, Disp, DstReg, CntReg, AccessSize, SMLoc(), 340280031Sdim SMLoc())); 341280031Sdim InstrumentMemOperand(*Op, AccessSize, true /* IsWrite */, RegCtx, Ctx, Out); 342280031Sdim } 343280031Sdim 344280031Sdim InstrumentMemOperandEpilogue(RegCtx, Ctx, Out); 345280031Sdim} 346280031Sdim 347280031Sdimvoid X86AddressSanitizer::InstrumentMOVS(const MCInst &Inst, 348280031Sdim OperandVector &Operands, 349280031Sdim MCContext &Ctx, const MCInstrInfo &MII, 350280031Sdim MCStreamer &Out) { 351280031Sdim // Access size in bytes. 352280031Sdim unsigned AccessSize = 0; 353280031Sdim 354280031Sdim switch (Inst.getOpcode()) { 355280031Sdim case X86::MOVSB: 356280031Sdim AccessSize = 1; 357280031Sdim break; 358280031Sdim case X86::MOVSW: 359280031Sdim AccessSize = 2; 360280031Sdim break; 361280031Sdim case X86::MOVSL: 362280031Sdim AccessSize = 4; 363280031Sdim break; 364280031Sdim case X86::MOVSQ: 365280031Sdim AccessSize = 8; 366280031Sdim break; 367280031Sdim default: 368274955Ssvnmir return; 369280031Sdim } 370274955Ssvnmir 371280031Sdim InstrumentMOVSImpl(AccessSize, Ctx, Out); 372274955Ssvnmir} 373274955Ssvnmir 374280031Sdimvoid X86AddressSanitizer::InstrumentMOV(const MCInst &Inst, 375280031Sdim OperandVector &Operands, MCContext &Ctx, 376280031Sdim const MCInstrInfo &MII, 377280031Sdim MCStreamer &Out) { 378274955Ssvnmir // Access size in bytes. 379274955Ssvnmir unsigned AccessSize = 0; 380274955Ssvnmir 381274955Ssvnmir switch (Inst.getOpcode()) { 382274955Ssvnmir case X86::MOV8mi: 383274955Ssvnmir case X86::MOV8mr: 384274955Ssvnmir case X86::MOV8rm: 385274955Ssvnmir AccessSize = 1; 386274955Ssvnmir break; 387274955Ssvnmir case X86::MOV16mi: 388274955Ssvnmir case X86::MOV16mr: 389274955Ssvnmir case X86::MOV16rm: 390274955Ssvnmir AccessSize = 2; 391274955Ssvnmir break; 392274955Ssvnmir case X86::MOV32mi: 393274955Ssvnmir case X86::MOV32mr: 394274955Ssvnmir case X86::MOV32rm: 395274955Ssvnmir AccessSize = 4; 396274955Ssvnmir break; 397274955Ssvnmir case X86::MOV64mi32: 398274955Ssvnmir case X86::MOV64mr: 399274955Ssvnmir case X86::MOV64rm: 400274955Ssvnmir AccessSize = 8; 401274955Ssvnmir break; 402274955Ssvnmir case X86::MOVAPDmr: 403274955Ssvnmir case X86::MOVAPSmr: 404274955Ssvnmir case X86::MOVAPDrm: 405274955Ssvnmir case X86::MOVAPSrm: 406274955Ssvnmir AccessSize = 16; 407274955Ssvnmir break; 408274955Ssvnmir default: 409274955Ssvnmir return; 410274955Ssvnmir } 411274955Ssvnmir 412274955Ssvnmir const bool IsWrite = MII.get(Inst.getOpcode()).mayStore(); 413280031Sdim 414274955Ssvnmir for (unsigned Ix = 0; Ix < Operands.size(); ++Ix) { 415274955Ssvnmir assert(Operands[Ix]); 416274955Ssvnmir MCParsedAsmOperand &Op = *Operands[Ix]; 417280031Sdim if (Op.isMem()) { 418280031Sdim X86Operand &MemOp = static_cast<X86Operand &>(Op); 419280031Sdim RegisterContext RegCtx( 420280031Sdim X86::RDI /* AddressReg */, X86::RAX /* ShadowReg */, 421280031Sdim IsSmallMemAccess(AccessSize) ? X86::RCX 422280031Sdim : X86::NoRegister /* ScratchReg */); 423280031Sdim RegCtx.AddBusyRegs(MemOp); 424280031Sdim InstrumentMemOperandPrologue(RegCtx, Ctx, Out); 425280031Sdim InstrumentMemOperand(MemOp, AccessSize, IsWrite, RegCtx, Ctx, Out); 426280031Sdim InstrumentMemOperandEpilogue(RegCtx, Ctx, Out); 427280031Sdim } 428274955Ssvnmir } 429274955Ssvnmir} 430274955Ssvnmir 431280031Sdimvoid X86AddressSanitizer::ComputeMemOperandAddress(X86Operand &Op, 432296417Sdim unsigned Size, 433280031Sdim unsigned Reg, MCContext &Ctx, 434280031Sdim MCStreamer &Out) { 435280031Sdim int64_t Displacement = 0; 436280031Sdim if (IsStackReg(Op.getMemBaseReg())) 437280031Sdim Displacement -= OrigSPOffset; 438280031Sdim if (IsStackReg(Op.getMemIndexReg())) 439280031Sdim Displacement -= OrigSPOffset * Op.getMemScale(); 440280031Sdim 441280031Sdim assert(Displacement >= 0); 442280031Sdim 443280031Sdim // Emit Op as is. 444280031Sdim if (Displacement == 0) { 445296417Sdim EmitLEA(Op, Size, Reg, Out); 446280031Sdim return; 447280031Sdim } 448280031Sdim 449280031Sdim int64_t Residue; 450280031Sdim std::unique_ptr<X86Operand> NewOp = 451280031Sdim AddDisplacement(Op, Displacement, Ctx, &Residue); 452296417Sdim EmitLEA(*NewOp, Size, Reg, Out); 453280031Sdim 454280031Sdim while (Residue != 0) { 455280031Sdim const MCConstantExpr *Disp = 456288943Sdim MCConstantExpr::create(ApplyDisplacementBounds(Residue), Ctx); 457280031Sdim std::unique_ptr<X86Operand> DispOp = 458280031Sdim X86Operand::CreateMem(getPointerWidth(), 0, Disp, Reg, 0, 1, SMLoc(), 459280031Sdim SMLoc()); 460296417Sdim EmitLEA(*DispOp, Size, Reg, Out); 461280031Sdim Residue -= Disp->getValue(); 462280031Sdim } 463280031Sdim} 464280031Sdim 465280031Sdimstd::unique_ptr<X86Operand> 466280031SdimX86AddressSanitizer::AddDisplacement(X86Operand &Op, int64_t Displacement, 467280031Sdim MCContext &Ctx, int64_t *Residue) { 468280031Sdim assert(Displacement >= 0); 469280031Sdim 470280031Sdim if (Displacement == 0 || 471280031Sdim (Op.getMemDisp() && Op.getMemDisp()->getKind() != MCExpr::Constant)) { 472280031Sdim *Residue = Displacement; 473280031Sdim return X86Operand::CreateMem(Op.getMemModeSize(), Op.getMemSegReg(), 474280031Sdim Op.getMemDisp(), Op.getMemBaseReg(), 475280031Sdim Op.getMemIndexReg(), Op.getMemScale(), 476280031Sdim SMLoc(), SMLoc()); 477280031Sdim } 478280031Sdim 479280031Sdim int64_t OrigDisplacement = 480280031Sdim static_cast<const MCConstantExpr *>(Op.getMemDisp())->getValue(); 481280031Sdim CheckDisplacementBounds(OrigDisplacement); 482280031Sdim Displacement += OrigDisplacement; 483280031Sdim 484280031Sdim int64_t NewDisplacement = ApplyDisplacementBounds(Displacement); 485280031Sdim CheckDisplacementBounds(NewDisplacement); 486280031Sdim 487280031Sdim *Residue = Displacement - NewDisplacement; 488288943Sdim const MCExpr *Disp = MCConstantExpr::create(NewDisplacement, Ctx); 489280031Sdim return X86Operand::CreateMem(Op.getMemModeSize(), Op.getMemSegReg(), Disp, 490280031Sdim Op.getMemBaseReg(), Op.getMemIndexReg(), 491280031Sdim Op.getMemScale(), SMLoc(), SMLoc()); 492280031Sdim} 493280031Sdim 494274955Ssvnmirclass X86AddressSanitizer32 : public X86AddressSanitizer { 495274955Ssvnmirpublic: 496274955Ssvnmir static const long kShadowOffset = 0x20000000; 497274955Ssvnmir 498296417Sdim X86AddressSanitizer32(const MCSubtargetInfo *&STI) 499274955Ssvnmir : X86AddressSanitizer(STI) {} 500280031Sdim 501296417Sdim ~X86AddressSanitizer32() override {} 502274955Ssvnmir 503280031Sdim unsigned GetFrameReg(const MCContext &Ctx, MCStreamer &Out) { 504280031Sdim unsigned FrameReg = GetFrameRegGeneric(Ctx, Out); 505280031Sdim if (FrameReg == X86::NoRegister) 506280031Sdim return FrameReg; 507296417Sdim return getX86SubSuperRegister(FrameReg, 32); 508280031Sdim } 509274955Ssvnmir 510280031Sdim void SpillReg(MCStreamer &Out, unsigned Reg) { 511280031Sdim EmitInstruction(Out, MCInstBuilder(X86::PUSH32r).addReg(Reg)); 512280031Sdim OrigSPOffset -= 4; 513280031Sdim } 514280031Sdim 515280031Sdim void RestoreReg(MCStreamer &Out, unsigned Reg) { 516280031Sdim EmitInstruction(Out, MCInstBuilder(X86::POP32r).addReg(Reg)); 517280031Sdim OrigSPOffset += 4; 518280031Sdim } 519280031Sdim 520280031Sdim void StoreFlags(MCStreamer &Out) { 521280031Sdim EmitInstruction(Out, MCInstBuilder(X86::PUSHF32)); 522280031Sdim OrigSPOffset -= 4; 523280031Sdim } 524280031Sdim 525280031Sdim void RestoreFlags(MCStreamer &Out) { 526280031Sdim EmitInstruction(Out, MCInstBuilder(X86::POPF32)); 527280031Sdim OrigSPOffset += 4; 528280031Sdim } 529280031Sdim 530296417Sdim void InstrumentMemOperandPrologue(const RegisterContext &RegCtx, 531296417Sdim MCContext &Ctx, 532296417Sdim MCStreamer &Out) override { 533296417Sdim unsigned LocalFrameReg = RegCtx.ChooseFrameReg(32); 534280031Sdim assert(LocalFrameReg != X86::NoRegister); 535280031Sdim 536280031Sdim const MCRegisterInfo *MRI = Ctx.getRegisterInfo(); 537280031Sdim unsigned FrameReg = GetFrameReg(Ctx, Out); 538280031Sdim if (MRI && FrameReg != X86::NoRegister) { 539280031Sdim SpillReg(Out, LocalFrameReg); 540280031Sdim if (FrameReg == X86::ESP) { 541280031Sdim Out.EmitCFIAdjustCfaOffset(4 /* byte size of the LocalFrameReg */); 542280031Sdim Out.EmitCFIRelOffset( 543280031Sdim MRI->getDwarfRegNum(LocalFrameReg, true /* IsEH */), 0); 544280031Sdim } 545280031Sdim EmitInstruction( 546280031Sdim Out, 547280031Sdim MCInstBuilder(X86::MOV32rr).addReg(LocalFrameReg).addReg(FrameReg)); 548280031Sdim Out.EmitCFIRememberState(); 549280031Sdim Out.EmitCFIDefCfaRegister( 550280031Sdim MRI->getDwarfRegNum(LocalFrameReg, true /* IsEH */)); 551280031Sdim } 552280031Sdim 553296417Sdim SpillReg(Out, RegCtx.AddressReg(32)); 554296417Sdim SpillReg(Out, RegCtx.ShadowReg(32)); 555296417Sdim if (RegCtx.ScratchReg(32) != X86::NoRegister) 556296417Sdim SpillReg(Out, RegCtx.ScratchReg(32)); 557280031Sdim StoreFlags(Out); 558280031Sdim } 559280031Sdim 560296417Sdim void InstrumentMemOperandEpilogue(const RegisterContext &RegCtx, 561296417Sdim MCContext &Ctx, 562296417Sdim MCStreamer &Out) override { 563296417Sdim unsigned LocalFrameReg = RegCtx.ChooseFrameReg(32); 564280031Sdim assert(LocalFrameReg != X86::NoRegister); 565280031Sdim 566280031Sdim RestoreFlags(Out); 567296417Sdim if (RegCtx.ScratchReg(32) != X86::NoRegister) 568296417Sdim RestoreReg(Out, RegCtx.ScratchReg(32)); 569296417Sdim RestoreReg(Out, RegCtx.ShadowReg(32)); 570296417Sdim RestoreReg(Out, RegCtx.AddressReg(32)); 571280031Sdim 572280031Sdim unsigned FrameReg = GetFrameReg(Ctx, Out); 573280031Sdim if (Ctx.getRegisterInfo() && FrameReg != X86::NoRegister) { 574280031Sdim RestoreReg(Out, LocalFrameReg); 575280031Sdim Out.EmitCFIRestoreState(); 576280031Sdim if (FrameReg == X86::ESP) 577280031Sdim Out.EmitCFIAdjustCfaOffset(-4 /* byte size of the LocalFrameReg */); 578280031Sdim } 579280031Sdim } 580280031Sdim 581296417Sdim void InstrumentMemOperandSmall(X86Operand &Op, unsigned AccessSize, 582296417Sdim bool IsWrite, 583296417Sdim const RegisterContext &RegCtx, 584296417Sdim MCContext &Ctx, 585296417Sdim MCStreamer &Out) override; 586296417Sdim void InstrumentMemOperandLarge(X86Operand &Op, unsigned AccessSize, 587296417Sdim bool IsWrite, 588296417Sdim const RegisterContext &RegCtx, 589296417Sdim MCContext &Ctx, 590296417Sdim MCStreamer &Out) override; 591296417Sdim void InstrumentMOVSImpl(unsigned AccessSize, MCContext &Ctx, 592296417Sdim MCStreamer &Out) override; 593280031Sdim 594280031Sdimprivate: 595280031Sdim void EmitCallAsanReport(unsigned AccessSize, bool IsWrite, MCContext &Ctx, 596280031Sdim MCStreamer &Out, const RegisterContext &RegCtx) { 597274955Ssvnmir EmitInstruction(Out, MCInstBuilder(X86::CLD)); 598274955Ssvnmir EmitInstruction(Out, MCInstBuilder(X86::MMX_EMMS)); 599274955Ssvnmir 600280031Sdim EmitInstruction(Out, MCInstBuilder(X86::AND64ri8) 601280031Sdim .addReg(X86::ESP) 602280031Sdim .addReg(X86::ESP) 603280031Sdim .addImm(-16)); 604280031Sdim EmitInstruction( 605296417Sdim Out, MCInstBuilder(X86::PUSH32r).addReg(RegCtx.AddressReg(32))); 606274955Ssvnmir 607296417Sdim MCSymbol *FnSym = Ctx.getOrCreateSymbol(llvm::Twine("__asan_report_") + 608296417Sdim (IsWrite ? "store" : "load") + 609296417Sdim llvm::Twine(AccessSize)); 610274955Ssvnmir const MCSymbolRefExpr *FnExpr = 611288943Sdim MCSymbolRefExpr::create(FnSym, MCSymbolRefExpr::VK_PLT, Ctx); 612274955Ssvnmir EmitInstruction(Out, MCInstBuilder(X86::CALLpcrel32).addExpr(FnExpr)); 613274955Ssvnmir } 614274955Ssvnmir}; 615274955Ssvnmir 616280031Sdimvoid X86AddressSanitizer32::InstrumentMemOperandSmall( 617280031Sdim X86Operand &Op, unsigned AccessSize, bool IsWrite, 618280031Sdim const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) { 619296417Sdim unsigned AddressRegI32 = RegCtx.AddressReg(32); 620296417Sdim unsigned ShadowRegI32 = RegCtx.ShadowReg(32); 621296417Sdim unsigned ShadowRegI8 = RegCtx.ShadowReg(8); 622274955Ssvnmir 623296417Sdim assert(RegCtx.ScratchReg(32) != X86::NoRegister); 624296417Sdim unsigned ScratchRegI32 = RegCtx.ScratchReg(32); 625274955Ssvnmir 626296417Sdim ComputeMemOperandAddress(Op, 32, AddressRegI32, Ctx, Out); 627274955Ssvnmir 628280031Sdim EmitInstruction(Out, MCInstBuilder(X86::MOV32rr).addReg(ShadowRegI32).addReg( 629280031Sdim AddressRegI32)); 630280031Sdim EmitInstruction(Out, MCInstBuilder(X86::SHR32ri) 631280031Sdim .addReg(ShadowRegI32) 632280031Sdim .addReg(ShadowRegI32) 633280031Sdim .addImm(3)); 634280031Sdim 635274955Ssvnmir { 636274955Ssvnmir MCInst Inst; 637274955Ssvnmir Inst.setOpcode(X86::MOV8rm); 638288943Sdim Inst.addOperand(MCOperand::createReg(ShadowRegI8)); 639288943Sdim const MCExpr *Disp = MCConstantExpr::create(kShadowOffset, Ctx); 640274955Ssvnmir std::unique_ptr<X86Operand> Op( 641280031Sdim X86Operand::CreateMem(getPointerWidth(), 0, Disp, ShadowRegI32, 0, 1, 642280031Sdim SMLoc(), SMLoc())); 643274955Ssvnmir Op->addMemOperands(Inst, 5); 644274955Ssvnmir EmitInstruction(Out, Inst); 645274955Ssvnmir } 646274955Ssvnmir 647280031Sdim EmitInstruction( 648280031Sdim Out, MCInstBuilder(X86::TEST8rr).addReg(ShadowRegI8).addReg(ShadowRegI8)); 649288943Sdim MCSymbol *DoneSym = Ctx.createTempSymbol(); 650288943Sdim const MCExpr *DoneExpr = MCSymbolRefExpr::create(DoneSym, Ctx); 651280031Sdim EmitInstruction(Out, MCInstBuilder(X86::JE_1).addExpr(DoneExpr)); 652274955Ssvnmir 653280031Sdim EmitInstruction(Out, MCInstBuilder(X86::MOV32rr).addReg(ScratchRegI32).addReg( 654280031Sdim AddressRegI32)); 655280031Sdim EmitInstruction(Out, MCInstBuilder(X86::AND32ri) 656280031Sdim .addReg(ScratchRegI32) 657280031Sdim .addReg(ScratchRegI32) 658280031Sdim .addImm(7)); 659274955Ssvnmir 660274955Ssvnmir switch (AccessSize) { 661280031Sdim default: llvm_unreachable("Incorrect access size"); 662274955Ssvnmir case 1: 663274955Ssvnmir break; 664274955Ssvnmir case 2: { 665288943Sdim const MCExpr *Disp = MCConstantExpr::create(1, Ctx); 666274955Ssvnmir std::unique_ptr<X86Operand> Op( 667280031Sdim X86Operand::CreateMem(getPointerWidth(), 0, Disp, ScratchRegI32, 0, 1, 668280031Sdim SMLoc(), SMLoc())); 669296417Sdim EmitLEA(*Op, 32, ScratchRegI32, Out); 670274955Ssvnmir break; 671274955Ssvnmir } 672274955Ssvnmir case 4: 673280031Sdim EmitInstruction(Out, MCInstBuilder(X86::ADD32ri8) 674280031Sdim .addReg(ScratchRegI32) 675280031Sdim .addReg(ScratchRegI32) 676280031Sdim .addImm(3)); 677274955Ssvnmir break; 678274955Ssvnmir } 679274955Ssvnmir 680274955Ssvnmir EmitInstruction( 681280031Sdim Out, 682280031Sdim MCInstBuilder(X86::MOVSX32rr8).addReg(ShadowRegI32).addReg(ShadowRegI8)); 683280031Sdim EmitInstruction(Out, MCInstBuilder(X86::CMP32rr).addReg(ScratchRegI32).addReg( 684280031Sdim ShadowRegI32)); 685280031Sdim EmitInstruction(Out, MCInstBuilder(X86::JL_1).addExpr(DoneExpr)); 686274955Ssvnmir 687280031Sdim EmitCallAsanReport(AccessSize, IsWrite, Ctx, Out, RegCtx); 688274955Ssvnmir EmitLabel(Out, DoneSym); 689274955Ssvnmir} 690274955Ssvnmir 691280031Sdimvoid X86AddressSanitizer32::InstrumentMemOperandLarge( 692280031Sdim X86Operand &Op, unsigned AccessSize, bool IsWrite, 693280031Sdim const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) { 694296417Sdim unsigned AddressRegI32 = RegCtx.AddressReg(32); 695296417Sdim unsigned ShadowRegI32 = RegCtx.ShadowReg(32); 696274955Ssvnmir 697296417Sdim ComputeMemOperandAddress(Op, 32, AddressRegI32, Ctx, Out); 698280031Sdim 699280031Sdim EmitInstruction(Out, MCInstBuilder(X86::MOV32rr).addReg(ShadowRegI32).addReg( 700280031Sdim AddressRegI32)); 701280031Sdim EmitInstruction(Out, MCInstBuilder(X86::SHR32ri) 702280031Sdim .addReg(ShadowRegI32) 703280031Sdim .addReg(ShadowRegI32) 704280031Sdim .addImm(3)); 705274955Ssvnmir { 706274955Ssvnmir MCInst Inst; 707274955Ssvnmir switch (AccessSize) { 708280031Sdim default: llvm_unreachable("Incorrect access size"); 709280031Sdim case 8: 710280031Sdim Inst.setOpcode(X86::CMP8mi); 711280031Sdim break; 712280031Sdim case 16: 713280031Sdim Inst.setOpcode(X86::CMP16mi); 714280031Sdim break; 715274955Ssvnmir } 716288943Sdim const MCExpr *Disp = MCConstantExpr::create(kShadowOffset, Ctx); 717274955Ssvnmir std::unique_ptr<X86Operand> Op( 718280031Sdim X86Operand::CreateMem(getPointerWidth(), 0, Disp, ShadowRegI32, 0, 1, 719280031Sdim SMLoc(), SMLoc())); 720274955Ssvnmir Op->addMemOperands(Inst, 5); 721288943Sdim Inst.addOperand(MCOperand::createImm(0)); 722274955Ssvnmir EmitInstruction(Out, Inst); 723274955Ssvnmir } 724288943Sdim MCSymbol *DoneSym = Ctx.createTempSymbol(); 725288943Sdim const MCExpr *DoneExpr = MCSymbolRefExpr::create(DoneSym, Ctx); 726280031Sdim EmitInstruction(Out, MCInstBuilder(X86::JE_1).addExpr(DoneExpr)); 727274955Ssvnmir 728280031Sdim EmitCallAsanReport(AccessSize, IsWrite, Ctx, Out, RegCtx); 729274955Ssvnmir EmitLabel(Out, DoneSym); 730280031Sdim} 731274955Ssvnmir 732280031Sdimvoid X86AddressSanitizer32::InstrumentMOVSImpl(unsigned AccessSize, 733280031Sdim MCContext &Ctx, 734280031Sdim MCStreamer &Out) { 735280031Sdim StoreFlags(Out); 736280031Sdim 737280031Sdim // No need to test when ECX is equals to zero. 738288943Sdim MCSymbol *DoneSym = Ctx.createTempSymbol(); 739288943Sdim const MCExpr *DoneExpr = MCSymbolRefExpr::create(DoneSym, Ctx); 740280031Sdim EmitInstruction( 741280031Sdim Out, MCInstBuilder(X86::TEST32rr).addReg(X86::ECX).addReg(X86::ECX)); 742280031Sdim EmitInstruction(Out, MCInstBuilder(X86::JE_1).addExpr(DoneExpr)); 743280031Sdim 744280031Sdim // Instrument first and last elements in src and dst range. 745280031Sdim InstrumentMOVSBase(X86::EDI /* DstReg */, X86::ESI /* SrcReg */, 746280031Sdim X86::ECX /* CntReg */, AccessSize, Ctx, Out); 747280031Sdim 748280031Sdim EmitLabel(Out, DoneSym); 749280031Sdim RestoreFlags(Out); 750274955Ssvnmir} 751274955Ssvnmir 752274955Ssvnmirclass X86AddressSanitizer64 : public X86AddressSanitizer { 753274955Ssvnmirpublic: 754274955Ssvnmir static const long kShadowOffset = 0x7fff8000; 755274955Ssvnmir 756296417Sdim X86AddressSanitizer64(const MCSubtargetInfo *&STI) 757274955Ssvnmir : X86AddressSanitizer(STI) {} 758280031Sdim 759296417Sdim ~X86AddressSanitizer64() override {} 760274955Ssvnmir 761280031Sdim unsigned GetFrameReg(const MCContext &Ctx, MCStreamer &Out) { 762280031Sdim unsigned FrameReg = GetFrameRegGeneric(Ctx, Out); 763280031Sdim if (FrameReg == X86::NoRegister) 764280031Sdim return FrameReg; 765296417Sdim return getX86SubSuperRegister(FrameReg, 64); 766280031Sdim } 767274955Ssvnmir 768280031Sdim void SpillReg(MCStreamer &Out, unsigned Reg) { 769280031Sdim EmitInstruction(Out, MCInstBuilder(X86::PUSH64r).addReg(Reg)); 770280031Sdim OrigSPOffset -= 8; 771280031Sdim } 772280031Sdim 773280031Sdim void RestoreReg(MCStreamer &Out, unsigned Reg) { 774280031Sdim EmitInstruction(Out, MCInstBuilder(X86::POP64r).addReg(Reg)); 775280031Sdim OrigSPOffset += 8; 776280031Sdim } 777280031Sdim 778280031Sdim void StoreFlags(MCStreamer &Out) { 779280031Sdim EmitInstruction(Out, MCInstBuilder(X86::PUSHF64)); 780280031Sdim OrigSPOffset -= 8; 781280031Sdim } 782280031Sdim 783280031Sdim void RestoreFlags(MCStreamer &Out) { 784280031Sdim EmitInstruction(Out, MCInstBuilder(X86::POPF64)); 785280031Sdim OrigSPOffset += 8; 786280031Sdim } 787280031Sdim 788296417Sdim void InstrumentMemOperandPrologue(const RegisterContext &RegCtx, 789296417Sdim MCContext &Ctx, 790296417Sdim MCStreamer &Out) override { 791296417Sdim unsigned LocalFrameReg = RegCtx.ChooseFrameReg(64); 792280031Sdim assert(LocalFrameReg != X86::NoRegister); 793280031Sdim 794280031Sdim const MCRegisterInfo *MRI = Ctx.getRegisterInfo(); 795280031Sdim unsigned FrameReg = GetFrameReg(Ctx, Out); 796280031Sdim if (MRI && FrameReg != X86::NoRegister) { 797280031Sdim SpillReg(Out, X86::RBP); 798280031Sdim if (FrameReg == X86::RSP) { 799280031Sdim Out.EmitCFIAdjustCfaOffset(8 /* byte size of the LocalFrameReg */); 800280031Sdim Out.EmitCFIRelOffset( 801280031Sdim MRI->getDwarfRegNum(LocalFrameReg, true /* IsEH */), 0); 802280031Sdim } 803280031Sdim EmitInstruction( 804280031Sdim Out, 805280031Sdim MCInstBuilder(X86::MOV64rr).addReg(LocalFrameReg).addReg(FrameReg)); 806280031Sdim Out.EmitCFIRememberState(); 807280031Sdim Out.EmitCFIDefCfaRegister( 808280031Sdim MRI->getDwarfRegNum(LocalFrameReg, true /* IsEH */)); 809280031Sdim } 810280031Sdim 811280031Sdim EmitAdjustRSP(Ctx, Out, -128); 812296417Sdim SpillReg(Out, RegCtx.ShadowReg(64)); 813296417Sdim SpillReg(Out, RegCtx.AddressReg(64)); 814296417Sdim if (RegCtx.ScratchReg(64) != X86::NoRegister) 815296417Sdim SpillReg(Out, RegCtx.ScratchReg(64)); 816280031Sdim StoreFlags(Out); 817280031Sdim } 818280031Sdim 819296417Sdim void InstrumentMemOperandEpilogue(const RegisterContext &RegCtx, 820296417Sdim MCContext &Ctx, 821296417Sdim MCStreamer &Out) override { 822296417Sdim unsigned LocalFrameReg = RegCtx.ChooseFrameReg(64); 823280031Sdim assert(LocalFrameReg != X86::NoRegister); 824280031Sdim 825280031Sdim RestoreFlags(Out); 826296417Sdim if (RegCtx.ScratchReg(64) != X86::NoRegister) 827296417Sdim RestoreReg(Out, RegCtx.ScratchReg(64)); 828296417Sdim RestoreReg(Out, RegCtx.AddressReg(64)); 829296417Sdim RestoreReg(Out, RegCtx.ShadowReg(64)); 830280031Sdim EmitAdjustRSP(Ctx, Out, 128); 831280031Sdim 832280031Sdim unsigned FrameReg = GetFrameReg(Ctx, Out); 833280031Sdim if (Ctx.getRegisterInfo() && FrameReg != X86::NoRegister) { 834280031Sdim RestoreReg(Out, LocalFrameReg); 835280031Sdim Out.EmitCFIRestoreState(); 836280031Sdim if (FrameReg == X86::RSP) 837280031Sdim Out.EmitCFIAdjustCfaOffset(-8 /* byte size of the LocalFrameReg */); 838280031Sdim } 839280031Sdim } 840280031Sdim 841296417Sdim void InstrumentMemOperandSmall(X86Operand &Op, unsigned AccessSize, 842296417Sdim bool IsWrite, 843296417Sdim const RegisterContext &RegCtx, 844296417Sdim MCContext &Ctx, 845296417Sdim MCStreamer &Out) override; 846296417Sdim void InstrumentMemOperandLarge(X86Operand &Op, unsigned AccessSize, 847296417Sdim bool IsWrite, 848296417Sdim const RegisterContext &RegCtx, 849296417Sdim MCContext &Ctx, 850296417Sdim MCStreamer &Out) override; 851296417Sdim void InstrumentMOVSImpl(unsigned AccessSize, MCContext &Ctx, 852296417Sdim MCStreamer &Out) override; 853280031Sdim 854274955Ssvnmirprivate: 855274955Ssvnmir void EmitAdjustRSP(MCContext &Ctx, MCStreamer &Out, long Offset) { 856288943Sdim const MCExpr *Disp = MCConstantExpr::create(Offset, Ctx); 857274955Ssvnmir std::unique_ptr<X86Operand> Op( 858280031Sdim X86Operand::CreateMem(getPointerWidth(), 0, Disp, X86::RSP, 0, 1, 859280031Sdim SMLoc(), SMLoc())); 860296417Sdim EmitLEA(*Op, 64, X86::RSP, Out); 861280031Sdim OrigSPOffset += Offset; 862274955Ssvnmir } 863274955Ssvnmir 864280031Sdim void EmitCallAsanReport(unsigned AccessSize, bool IsWrite, MCContext &Ctx, 865280031Sdim MCStreamer &Out, const RegisterContext &RegCtx) { 866274955Ssvnmir EmitInstruction(Out, MCInstBuilder(X86::CLD)); 867274955Ssvnmir EmitInstruction(Out, MCInstBuilder(X86::MMX_EMMS)); 868274955Ssvnmir 869280031Sdim EmitInstruction(Out, MCInstBuilder(X86::AND64ri8) 870280031Sdim .addReg(X86::RSP) 871280031Sdim .addReg(X86::RSP) 872280031Sdim .addImm(-16)); 873274955Ssvnmir 874296417Sdim if (RegCtx.AddressReg(64) != X86::RDI) { 875280031Sdim EmitInstruction(Out, MCInstBuilder(X86::MOV64rr).addReg(X86::RDI).addReg( 876296417Sdim RegCtx.AddressReg(64))); 877280031Sdim } 878296417Sdim MCSymbol *FnSym = Ctx.getOrCreateSymbol(llvm::Twine("__asan_report_") + 879296417Sdim (IsWrite ? "store" : "load") + 880296417Sdim llvm::Twine(AccessSize)); 881274955Ssvnmir const MCSymbolRefExpr *FnExpr = 882288943Sdim MCSymbolRefExpr::create(FnSym, MCSymbolRefExpr::VK_PLT, Ctx); 883274955Ssvnmir EmitInstruction(Out, MCInstBuilder(X86::CALL64pcrel32).addExpr(FnExpr)); 884274955Ssvnmir } 885274955Ssvnmir}; 886274955Ssvnmir 887280031Sdimvoid X86AddressSanitizer64::InstrumentMemOperandSmall( 888280031Sdim X86Operand &Op, unsigned AccessSize, bool IsWrite, 889280031Sdim const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) { 890296417Sdim unsigned AddressRegI64 = RegCtx.AddressReg(64); 891296417Sdim unsigned AddressRegI32 = RegCtx.AddressReg(32); 892296417Sdim unsigned ShadowRegI64 = RegCtx.ShadowReg(64); 893296417Sdim unsigned ShadowRegI32 = RegCtx.ShadowReg(32); 894296417Sdim unsigned ShadowRegI8 = RegCtx.ShadowReg(8); 895280031Sdim 896296417Sdim assert(RegCtx.ScratchReg(32) != X86::NoRegister); 897296417Sdim unsigned ScratchRegI32 = RegCtx.ScratchReg(32); 898280031Sdim 899296417Sdim ComputeMemOperandAddress(Op, 64, AddressRegI64, Ctx, Out); 900280031Sdim 901280031Sdim EmitInstruction(Out, MCInstBuilder(X86::MOV64rr).addReg(ShadowRegI64).addReg( 902280031Sdim AddressRegI64)); 903280031Sdim EmitInstruction(Out, MCInstBuilder(X86::SHR64ri) 904280031Sdim .addReg(ShadowRegI64) 905280031Sdim .addReg(ShadowRegI64) 906280031Sdim .addImm(3)); 907274955Ssvnmir { 908274955Ssvnmir MCInst Inst; 909274955Ssvnmir Inst.setOpcode(X86::MOV8rm); 910288943Sdim Inst.addOperand(MCOperand::createReg(ShadowRegI8)); 911288943Sdim const MCExpr *Disp = MCConstantExpr::create(kShadowOffset, Ctx); 912274955Ssvnmir std::unique_ptr<X86Operand> Op( 913280031Sdim X86Operand::CreateMem(getPointerWidth(), 0, Disp, ShadowRegI64, 0, 1, 914280031Sdim SMLoc(), SMLoc())); 915274955Ssvnmir Op->addMemOperands(Inst, 5); 916274955Ssvnmir EmitInstruction(Out, Inst); 917274955Ssvnmir } 918274955Ssvnmir 919280031Sdim EmitInstruction( 920280031Sdim Out, MCInstBuilder(X86::TEST8rr).addReg(ShadowRegI8).addReg(ShadowRegI8)); 921288943Sdim MCSymbol *DoneSym = Ctx.createTempSymbol(); 922288943Sdim const MCExpr *DoneExpr = MCSymbolRefExpr::create(DoneSym, Ctx); 923280031Sdim EmitInstruction(Out, MCInstBuilder(X86::JE_1).addExpr(DoneExpr)); 924274955Ssvnmir 925280031Sdim EmitInstruction(Out, MCInstBuilder(X86::MOV32rr).addReg(ScratchRegI32).addReg( 926280031Sdim AddressRegI32)); 927280031Sdim EmitInstruction(Out, MCInstBuilder(X86::AND32ri) 928280031Sdim .addReg(ScratchRegI32) 929280031Sdim .addReg(ScratchRegI32) 930280031Sdim .addImm(7)); 931274955Ssvnmir 932274955Ssvnmir switch (AccessSize) { 933280031Sdim default: llvm_unreachable("Incorrect access size"); 934274955Ssvnmir case 1: 935274955Ssvnmir break; 936274955Ssvnmir case 2: { 937288943Sdim const MCExpr *Disp = MCConstantExpr::create(1, Ctx); 938274955Ssvnmir std::unique_ptr<X86Operand> Op( 939280031Sdim X86Operand::CreateMem(getPointerWidth(), 0, Disp, ScratchRegI32, 0, 1, 940280031Sdim SMLoc(), SMLoc())); 941296417Sdim EmitLEA(*Op, 32, ScratchRegI32, Out); 942274955Ssvnmir break; 943274955Ssvnmir } 944274955Ssvnmir case 4: 945280031Sdim EmitInstruction(Out, MCInstBuilder(X86::ADD32ri8) 946280031Sdim .addReg(ScratchRegI32) 947280031Sdim .addReg(ScratchRegI32) 948280031Sdim .addImm(3)); 949274955Ssvnmir break; 950274955Ssvnmir } 951274955Ssvnmir 952274955Ssvnmir EmitInstruction( 953280031Sdim Out, 954280031Sdim MCInstBuilder(X86::MOVSX32rr8).addReg(ShadowRegI32).addReg(ShadowRegI8)); 955280031Sdim EmitInstruction(Out, MCInstBuilder(X86::CMP32rr).addReg(ScratchRegI32).addReg( 956280031Sdim ShadowRegI32)); 957280031Sdim EmitInstruction(Out, MCInstBuilder(X86::JL_1).addExpr(DoneExpr)); 958274955Ssvnmir 959280031Sdim EmitCallAsanReport(AccessSize, IsWrite, Ctx, Out, RegCtx); 960274955Ssvnmir EmitLabel(Out, DoneSym); 961274955Ssvnmir} 962274955Ssvnmir 963280031Sdimvoid X86AddressSanitizer64::InstrumentMemOperandLarge( 964280031Sdim X86Operand &Op, unsigned AccessSize, bool IsWrite, 965280031Sdim const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) { 966296417Sdim unsigned AddressRegI64 = RegCtx.AddressReg(64); 967296417Sdim unsigned ShadowRegI64 = RegCtx.ShadowReg(64); 968274955Ssvnmir 969296417Sdim ComputeMemOperandAddress(Op, 64, AddressRegI64, Ctx, Out); 970280031Sdim 971280031Sdim EmitInstruction(Out, MCInstBuilder(X86::MOV64rr).addReg(ShadowRegI64).addReg( 972280031Sdim AddressRegI64)); 973280031Sdim EmitInstruction(Out, MCInstBuilder(X86::SHR64ri) 974280031Sdim .addReg(ShadowRegI64) 975280031Sdim .addReg(ShadowRegI64) 976280031Sdim .addImm(3)); 977274955Ssvnmir { 978274955Ssvnmir MCInst Inst; 979274955Ssvnmir switch (AccessSize) { 980280031Sdim default: llvm_unreachable("Incorrect access size"); 981274955Ssvnmir case 8: 982274955Ssvnmir Inst.setOpcode(X86::CMP8mi); 983274955Ssvnmir break; 984274955Ssvnmir case 16: 985274955Ssvnmir Inst.setOpcode(X86::CMP16mi); 986274955Ssvnmir break; 987274955Ssvnmir } 988288943Sdim const MCExpr *Disp = MCConstantExpr::create(kShadowOffset, Ctx); 989274955Ssvnmir std::unique_ptr<X86Operand> Op( 990280031Sdim X86Operand::CreateMem(getPointerWidth(), 0, Disp, ShadowRegI64, 0, 1, 991280031Sdim SMLoc(), SMLoc())); 992274955Ssvnmir Op->addMemOperands(Inst, 5); 993288943Sdim Inst.addOperand(MCOperand::createImm(0)); 994274955Ssvnmir EmitInstruction(Out, Inst); 995274955Ssvnmir } 996274955Ssvnmir 997288943Sdim MCSymbol *DoneSym = Ctx.createTempSymbol(); 998288943Sdim const MCExpr *DoneExpr = MCSymbolRefExpr::create(DoneSym, Ctx); 999280031Sdim EmitInstruction(Out, MCInstBuilder(X86::JE_1).addExpr(DoneExpr)); 1000274955Ssvnmir 1001280031Sdim EmitCallAsanReport(AccessSize, IsWrite, Ctx, Out, RegCtx); 1002274955Ssvnmir EmitLabel(Out, DoneSym); 1003280031Sdim} 1004274955Ssvnmir 1005280031Sdimvoid X86AddressSanitizer64::InstrumentMOVSImpl(unsigned AccessSize, 1006280031Sdim MCContext &Ctx, 1007280031Sdim MCStreamer &Out) { 1008280031Sdim StoreFlags(Out); 1009280031Sdim 1010280031Sdim // No need to test when RCX is equals to zero. 1011288943Sdim MCSymbol *DoneSym = Ctx.createTempSymbol(); 1012288943Sdim const MCExpr *DoneExpr = MCSymbolRefExpr::create(DoneSym, Ctx); 1013280031Sdim EmitInstruction( 1014280031Sdim Out, MCInstBuilder(X86::TEST64rr).addReg(X86::RCX).addReg(X86::RCX)); 1015280031Sdim EmitInstruction(Out, MCInstBuilder(X86::JE_1).addExpr(DoneExpr)); 1016280031Sdim 1017280031Sdim // Instrument first and last elements in src and dst range. 1018280031Sdim InstrumentMOVSBase(X86::RDI /* DstReg */, X86::RSI /* SrcReg */, 1019280031Sdim X86::RCX /* CntReg */, AccessSize, Ctx, Out); 1020280031Sdim 1021280031Sdim EmitLabel(Out, DoneSym); 1022280031Sdim RestoreFlags(Out); 1023274955Ssvnmir} 1024274955Ssvnmir 1025274955Ssvnmir} // End anonymous namespace 1026274955Ssvnmir 1027296417SdimX86AsmInstrumentation::X86AsmInstrumentation(const MCSubtargetInfo *&STI) 1028280031Sdim : STI(STI), InitialFrameReg(0) {} 1029280031Sdim 1030274955SsvnmirX86AsmInstrumentation::~X86AsmInstrumentation() {} 1031274955Ssvnmir 1032280031Sdimvoid X86AsmInstrumentation::InstrumentAndEmitInstruction( 1033274955Ssvnmir const MCInst &Inst, OperandVector &Operands, MCContext &Ctx, 1034280031Sdim const MCInstrInfo &MII, MCStreamer &Out) { 1035280031Sdim EmitInstruction(Out, Inst); 1036280031Sdim} 1037274955Ssvnmir 1038280031Sdimvoid X86AsmInstrumentation::EmitInstruction(MCStreamer &Out, 1039280031Sdim const MCInst &Inst) { 1040296417Sdim Out.EmitInstruction(Inst, *STI); 1041280031Sdim} 1042280031Sdim 1043280031Sdimunsigned X86AsmInstrumentation::GetFrameRegGeneric(const MCContext &Ctx, 1044280031Sdim MCStreamer &Out) { 1045280031Sdim if (!Out.getNumFrameInfos()) // No active dwarf frame 1046280031Sdim return X86::NoRegister; 1047280031Sdim const MCDwarfFrameInfo &Frame = Out.getDwarfFrameInfos().back(); 1048280031Sdim if (Frame.End) // Active dwarf frame is closed 1049280031Sdim return X86::NoRegister; 1050280031Sdim const MCRegisterInfo *MRI = Ctx.getRegisterInfo(); 1051280031Sdim if (!MRI) // No register info 1052280031Sdim return X86::NoRegister; 1053280031Sdim 1054280031Sdim if (InitialFrameReg) { 1055280031Sdim // FrameReg is set explicitly, we're instrumenting a MachineFunction. 1056280031Sdim return InitialFrameReg; 1057280031Sdim } 1058280031Sdim 1059280031Sdim return MRI->getLLVMRegNum(Frame.CurrentCfaRegister, true /* IsEH */); 1060280031Sdim} 1061280031Sdim 1062274955SsvnmirX86AsmInstrumentation * 1063274955SsvnmirCreateX86AsmInstrumentation(const MCTargetOptions &MCOptions, 1064296417Sdim const MCContext &Ctx, const MCSubtargetInfo *&STI) { 1065296417Sdim Triple T(STI->getTargetTriple()); 1066274955Ssvnmir const bool hasCompilerRTSupport = T.isOSLinux(); 1067274955Ssvnmir if (ClAsanInstrumentAssembly && hasCompilerRTSupport && 1068274955Ssvnmir MCOptions.SanitizeAddress) { 1069296417Sdim if (STI->getFeatureBits()[X86::Mode32Bit] != 0) 1070274955Ssvnmir return new X86AddressSanitizer32(STI); 1071296417Sdim if (STI->getFeatureBits()[X86::Mode64Bit] != 0) 1072274955Ssvnmir return new X86AddressSanitizer64(STI); 1073274955Ssvnmir } 1074280031Sdim return new X86AsmInstrumentation(STI); 1075274955Ssvnmir} 1076274955Ssvnmir 1077296417Sdim} // end llvm namespace 1078