1*9880d681SAndroid Build Coastguard Worker //===-- X86AsmInstrumentation.cpp - Instrument X86 inline assembly C++ -*-===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker
10*9880d681SAndroid Build Coastguard Worker #include "X86AsmInstrumentation.h"
11*9880d681SAndroid Build Coastguard Worker #include "MCTargetDesc/X86BaseInfo.h"
12*9880d681SAndroid Build Coastguard Worker #include "X86Operand.h"
13*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/StringExtras.h"
14*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/Triple.h"
15*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCAsmInfo.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCContext.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCInst.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCInstBuilder.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCInstrInfo.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCParser/MCTargetAsmParser.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCStreamer.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCSubtargetInfo.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCTargetOptions.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/CommandLine.h"
26*9880d681SAndroid Build Coastguard Worker #include <algorithm>
27*9880d681SAndroid Build Coastguard Worker #include <cassert>
28*9880d681SAndroid Build Coastguard Worker #include <vector>
29*9880d681SAndroid Build Coastguard Worker
30*9880d681SAndroid Build Coastguard Worker // Following comment describes how assembly instrumentation works.
31*9880d681SAndroid Build Coastguard Worker // Currently we have only AddressSanitizer instrumentation, but we're
32*9880d681SAndroid Build Coastguard Worker // planning to implement MemorySanitizer for inline assembly too. If
33*9880d681SAndroid Build Coastguard Worker // you're not familiar with AddressSanitizer algorithm, please, read
34*9880d681SAndroid Build Coastguard Worker // https://code.google.com/p/address-sanitizer/wiki/AddressSanitizerAlgorithm.
35*9880d681SAndroid Build Coastguard Worker //
36*9880d681SAndroid Build Coastguard Worker // When inline assembly is parsed by an instance of X86AsmParser, all
37*9880d681SAndroid Build Coastguard Worker // instructions are emitted via EmitInstruction method. That's the
38*9880d681SAndroid Build Coastguard Worker // place where X86AsmInstrumentation analyzes an instruction and
39*9880d681SAndroid Build Coastguard Worker // decides, whether the instruction should be emitted as is or
40*9880d681SAndroid Build Coastguard Worker // instrumentation is required. The latter case happens when an
41*9880d681SAndroid Build Coastguard Worker // instruction reads from or writes to memory. Now instruction opcode
42*9880d681SAndroid Build Coastguard Worker // is explicitly checked, and if an instruction has a memory operand
43*9880d681SAndroid Build Coastguard Worker // (for instance, movq (%rsi, %rcx, 8), %rax) - it should be
44*9880d681SAndroid Build Coastguard Worker // instrumented. There're also exist instructions that modify
45*9880d681SAndroid Build Coastguard Worker // memory but don't have an explicit memory operands, for instance,
46*9880d681SAndroid Build Coastguard Worker // movs.
47*9880d681SAndroid Build Coastguard Worker //
48*9880d681SAndroid Build Coastguard Worker // Let's consider at first 8-byte memory accesses when an instruction
49*9880d681SAndroid Build Coastguard Worker // has an explicit memory operand. In this case we need two registers -
50*9880d681SAndroid Build Coastguard Worker // AddressReg to compute address of a memory cells which are accessed
51*9880d681SAndroid Build Coastguard Worker // and ShadowReg to compute corresponding shadow address. So, we need
52*9880d681SAndroid Build Coastguard Worker // to spill both registers before instrumentation code and restore them
53*9880d681SAndroid Build Coastguard Worker // after instrumentation. Thus, in general, instrumentation code will
54*9880d681SAndroid Build Coastguard Worker // look like this:
55*9880d681SAndroid Build Coastguard Worker // PUSHF # Store flags, otherwise they will be overwritten
56*9880d681SAndroid Build Coastguard Worker // PUSH AddressReg # spill AddressReg
57*9880d681SAndroid Build Coastguard Worker // PUSH ShadowReg # spill ShadowReg
58*9880d681SAndroid Build Coastguard Worker // LEA MemOp, AddressReg # compute address of the memory operand
59*9880d681SAndroid Build Coastguard Worker // MOV AddressReg, ShadowReg
60*9880d681SAndroid Build Coastguard Worker // SHR ShadowReg, 3
61*9880d681SAndroid Build Coastguard Worker // # ShadowOffset(AddressReg >> 3) contains address of a shadow
62*9880d681SAndroid Build Coastguard Worker // # corresponding to MemOp.
63*9880d681SAndroid Build Coastguard Worker // CMP ShadowOffset(ShadowReg), 0 # test shadow value
64*9880d681SAndroid Build Coastguard Worker // JZ .Done # when shadow equals to zero, everything is fine
65*9880d681SAndroid Build Coastguard Worker // MOV AddressReg, RDI
66*9880d681SAndroid Build Coastguard Worker // # Call __asan_report function with AddressReg as an argument
67*9880d681SAndroid Build Coastguard Worker // CALL __asan_report
68*9880d681SAndroid Build Coastguard Worker // .Done:
69*9880d681SAndroid Build Coastguard Worker // POP ShadowReg # Restore ShadowReg
70*9880d681SAndroid Build Coastguard Worker // POP AddressReg # Restore AddressReg
71*9880d681SAndroid Build Coastguard Worker // POPF # Restore flags
72*9880d681SAndroid Build Coastguard Worker //
73*9880d681SAndroid Build Coastguard Worker // Memory accesses with different size (1-, 2-, 4- and 16-byte) are
74*9880d681SAndroid Build Coastguard Worker // handled in a similar manner, but small memory accesses (less than 8
75*9880d681SAndroid Build Coastguard Worker // byte) require an additional ScratchReg, which is used for shadow value.
76*9880d681SAndroid Build Coastguard Worker //
77*9880d681SAndroid Build Coastguard Worker // If, suppose, we're instrumenting an instruction like movs, only
78*9880d681SAndroid Build Coastguard Worker // contents of RDI, RDI + AccessSize * RCX, RSI, RSI + AccessSize *
79*9880d681SAndroid Build Coastguard Worker // RCX are checked. In this case there're no need to spill and restore
80*9880d681SAndroid Build Coastguard Worker // AddressReg , ShadowReg or flags four times, they're saved on stack
81*9880d681SAndroid Build Coastguard Worker // just once, before instrumentation of these four addresses, and restored
82*9880d681SAndroid Build Coastguard Worker // at the end of the instrumentation.
83*9880d681SAndroid Build Coastguard Worker //
84*9880d681SAndroid Build Coastguard Worker // There exist several things which complicate this simple algorithm.
85*9880d681SAndroid Build Coastguard Worker // * Instrumented memory operand can have RSP as a base or an index
86*9880d681SAndroid Build Coastguard Worker // register. So we need to add a constant offset before computation
87*9880d681SAndroid Build Coastguard Worker // of memory address, since flags, AddressReg, ShadowReg, etc. were
88*9880d681SAndroid Build Coastguard Worker // already stored on stack and RSP was modified.
89*9880d681SAndroid Build Coastguard Worker // * Debug info (usually, DWARF) should be adjusted, because sometimes
90*9880d681SAndroid Build Coastguard Worker // RSP is used as a frame register. So, we need to select some
91*9880d681SAndroid Build Coastguard Worker // register as a frame register and temprorary override current CFA
92*9880d681SAndroid Build Coastguard Worker // register.
93*9880d681SAndroid Build Coastguard Worker
94*9880d681SAndroid Build Coastguard Worker namespace llvm {
95*9880d681SAndroid Build Coastguard Worker namespace {
96*9880d681SAndroid Build Coastguard Worker
97*9880d681SAndroid Build Coastguard Worker static cl::opt<bool> ClAsanInstrumentAssembly(
98*9880d681SAndroid Build Coastguard Worker "asan-instrument-assembly",
99*9880d681SAndroid Build Coastguard Worker cl::desc("instrument assembly with AddressSanitizer checks"), cl::Hidden,
100*9880d681SAndroid Build Coastguard Worker cl::init(false));
101*9880d681SAndroid Build Coastguard Worker
102*9880d681SAndroid Build Coastguard Worker const int64_t MinAllowedDisplacement = std::numeric_limits<int32_t>::min();
103*9880d681SAndroid Build Coastguard Worker const int64_t MaxAllowedDisplacement = std::numeric_limits<int32_t>::max();
104*9880d681SAndroid Build Coastguard Worker
ApplyDisplacementBounds(int64_t Displacement)105*9880d681SAndroid Build Coastguard Worker int64_t ApplyDisplacementBounds(int64_t Displacement) {
106*9880d681SAndroid Build Coastguard Worker return std::max(std::min(MaxAllowedDisplacement, Displacement),
107*9880d681SAndroid Build Coastguard Worker MinAllowedDisplacement);
108*9880d681SAndroid Build Coastguard Worker }
109*9880d681SAndroid Build Coastguard Worker
CheckDisplacementBounds(int64_t Displacement)110*9880d681SAndroid Build Coastguard Worker void CheckDisplacementBounds(int64_t Displacement) {
111*9880d681SAndroid Build Coastguard Worker assert(Displacement >= MinAllowedDisplacement &&
112*9880d681SAndroid Build Coastguard Worker Displacement <= MaxAllowedDisplacement);
113*9880d681SAndroid Build Coastguard Worker }
114*9880d681SAndroid Build Coastguard Worker
IsStackReg(unsigned Reg)115*9880d681SAndroid Build Coastguard Worker bool IsStackReg(unsigned Reg) { return Reg == X86::RSP || Reg == X86::ESP; }
116*9880d681SAndroid Build Coastguard Worker
IsSmallMemAccess(unsigned AccessSize)117*9880d681SAndroid Build Coastguard Worker bool IsSmallMemAccess(unsigned AccessSize) { return AccessSize < 8; }
118*9880d681SAndroid Build Coastguard Worker
119*9880d681SAndroid Build Coastguard Worker class X86AddressSanitizer : public X86AsmInstrumentation {
120*9880d681SAndroid Build Coastguard Worker public:
121*9880d681SAndroid Build Coastguard Worker struct RegisterContext {
122*9880d681SAndroid Build Coastguard Worker private:
123*9880d681SAndroid Build Coastguard Worker enum RegOffset {
124*9880d681SAndroid Build Coastguard Worker REG_OFFSET_ADDRESS = 0,
125*9880d681SAndroid Build Coastguard Worker REG_OFFSET_SHADOW,
126*9880d681SAndroid Build Coastguard Worker REG_OFFSET_SCRATCH
127*9880d681SAndroid Build Coastguard Worker };
128*9880d681SAndroid Build Coastguard Worker
129*9880d681SAndroid Build Coastguard Worker public:
RegisterContextllvm::__anon97297eab0111::X86AddressSanitizer::RegisterContext130*9880d681SAndroid Build Coastguard Worker RegisterContext(unsigned AddressReg, unsigned ShadowReg,
131*9880d681SAndroid Build Coastguard Worker unsigned ScratchReg) {
132*9880d681SAndroid Build Coastguard Worker BusyRegs.push_back(convReg(AddressReg, 64));
133*9880d681SAndroid Build Coastguard Worker BusyRegs.push_back(convReg(ShadowReg, 64));
134*9880d681SAndroid Build Coastguard Worker BusyRegs.push_back(convReg(ScratchReg, 64));
135*9880d681SAndroid Build Coastguard Worker }
136*9880d681SAndroid Build Coastguard Worker
AddressRegllvm::__anon97297eab0111::X86AddressSanitizer::RegisterContext137*9880d681SAndroid Build Coastguard Worker unsigned AddressReg(unsigned Size) const {
138*9880d681SAndroid Build Coastguard Worker return convReg(BusyRegs[REG_OFFSET_ADDRESS], Size);
139*9880d681SAndroid Build Coastguard Worker }
140*9880d681SAndroid Build Coastguard Worker
ShadowRegllvm::__anon97297eab0111::X86AddressSanitizer::RegisterContext141*9880d681SAndroid Build Coastguard Worker unsigned ShadowReg(unsigned Size) const {
142*9880d681SAndroid Build Coastguard Worker return convReg(BusyRegs[REG_OFFSET_SHADOW], Size);
143*9880d681SAndroid Build Coastguard Worker }
144*9880d681SAndroid Build Coastguard Worker
ScratchRegllvm::__anon97297eab0111::X86AddressSanitizer::RegisterContext145*9880d681SAndroid Build Coastguard Worker unsigned ScratchReg(unsigned Size) const {
146*9880d681SAndroid Build Coastguard Worker return convReg(BusyRegs[REG_OFFSET_SCRATCH], Size);
147*9880d681SAndroid Build Coastguard Worker }
148*9880d681SAndroid Build Coastguard Worker
AddBusyRegllvm::__anon97297eab0111::X86AddressSanitizer::RegisterContext149*9880d681SAndroid Build Coastguard Worker void AddBusyReg(unsigned Reg) {
150*9880d681SAndroid Build Coastguard Worker if (Reg != X86::NoRegister)
151*9880d681SAndroid Build Coastguard Worker BusyRegs.push_back(convReg(Reg, 64));
152*9880d681SAndroid Build Coastguard Worker }
153*9880d681SAndroid Build Coastguard Worker
AddBusyRegsllvm::__anon97297eab0111::X86AddressSanitizer::RegisterContext154*9880d681SAndroid Build Coastguard Worker void AddBusyRegs(const X86Operand &Op) {
155*9880d681SAndroid Build Coastguard Worker AddBusyReg(Op.getMemBaseReg());
156*9880d681SAndroid Build Coastguard Worker AddBusyReg(Op.getMemIndexReg());
157*9880d681SAndroid Build Coastguard Worker }
158*9880d681SAndroid Build Coastguard Worker
ChooseFrameRegllvm::__anon97297eab0111::X86AddressSanitizer::RegisterContext159*9880d681SAndroid Build Coastguard Worker unsigned ChooseFrameReg(unsigned Size) const {
160*9880d681SAndroid Build Coastguard Worker static const MCPhysReg Candidates[] = { X86::RBP, X86::RAX, X86::RBX,
161*9880d681SAndroid Build Coastguard Worker X86::RCX, X86::RDX, X86::RDI,
162*9880d681SAndroid Build Coastguard Worker X86::RSI };
163*9880d681SAndroid Build Coastguard Worker for (unsigned Reg : Candidates) {
164*9880d681SAndroid Build Coastguard Worker if (!std::count(BusyRegs.begin(), BusyRegs.end(), Reg))
165*9880d681SAndroid Build Coastguard Worker return convReg(Reg, Size);
166*9880d681SAndroid Build Coastguard Worker }
167*9880d681SAndroid Build Coastguard Worker return X86::NoRegister;
168*9880d681SAndroid Build Coastguard Worker }
169*9880d681SAndroid Build Coastguard Worker
170*9880d681SAndroid Build Coastguard Worker private:
convRegllvm::__anon97297eab0111::X86AddressSanitizer::RegisterContext171*9880d681SAndroid Build Coastguard Worker unsigned convReg(unsigned Reg, unsigned Size) const {
172*9880d681SAndroid Build Coastguard Worker return Reg == X86::NoRegister ? Reg : getX86SubSuperRegister(Reg, Size);
173*9880d681SAndroid Build Coastguard Worker }
174*9880d681SAndroid Build Coastguard Worker
175*9880d681SAndroid Build Coastguard Worker std::vector<unsigned> BusyRegs;
176*9880d681SAndroid Build Coastguard Worker };
177*9880d681SAndroid Build Coastguard Worker
X86AddressSanitizer(const MCSubtargetInfo * & STI)178*9880d681SAndroid Build Coastguard Worker X86AddressSanitizer(const MCSubtargetInfo *&STI)
179*9880d681SAndroid Build Coastguard Worker : X86AsmInstrumentation(STI), RepPrefix(false), OrigSPOffset(0) {}
180*9880d681SAndroid Build Coastguard Worker
~X86AddressSanitizer()181*9880d681SAndroid Build Coastguard Worker ~X86AddressSanitizer() override {}
182*9880d681SAndroid Build Coastguard Worker
183*9880d681SAndroid Build Coastguard Worker // X86AsmInstrumentation implementation:
InstrumentAndEmitInstruction(const MCInst & Inst,OperandVector & Operands,MCContext & Ctx,const MCInstrInfo & MII,MCStreamer & Out)184*9880d681SAndroid Build Coastguard Worker void InstrumentAndEmitInstruction(const MCInst &Inst,
185*9880d681SAndroid Build Coastguard Worker OperandVector &Operands,
186*9880d681SAndroid Build Coastguard Worker MCContext &Ctx,
187*9880d681SAndroid Build Coastguard Worker const MCInstrInfo &MII,
188*9880d681SAndroid Build Coastguard Worker MCStreamer &Out) override {
189*9880d681SAndroid Build Coastguard Worker InstrumentMOVS(Inst, Operands, Ctx, MII, Out);
190*9880d681SAndroid Build Coastguard Worker if (RepPrefix)
191*9880d681SAndroid Build Coastguard Worker EmitInstruction(Out, MCInstBuilder(X86::REP_PREFIX));
192*9880d681SAndroid Build Coastguard Worker
193*9880d681SAndroid Build Coastguard Worker InstrumentMOV(Inst, Operands, Ctx, MII, Out);
194*9880d681SAndroid Build Coastguard Worker
195*9880d681SAndroid Build Coastguard Worker RepPrefix = (Inst.getOpcode() == X86::REP_PREFIX);
196*9880d681SAndroid Build Coastguard Worker if (!RepPrefix)
197*9880d681SAndroid Build Coastguard Worker EmitInstruction(Out, Inst);
198*9880d681SAndroid Build Coastguard Worker }
199*9880d681SAndroid Build Coastguard Worker
200*9880d681SAndroid Build Coastguard Worker // Adjusts up stack and saves all registers used in instrumentation.
201*9880d681SAndroid Build Coastguard Worker virtual void InstrumentMemOperandPrologue(const RegisterContext &RegCtx,
202*9880d681SAndroid Build Coastguard Worker MCContext &Ctx,
203*9880d681SAndroid Build Coastguard Worker MCStreamer &Out) = 0;
204*9880d681SAndroid Build Coastguard Worker
205*9880d681SAndroid Build Coastguard Worker // Restores all registers used in instrumentation and adjusts stack.
206*9880d681SAndroid Build Coastguard Worker virtual void InstrumentMemOperandEpilogue(const RegisterContext &RegCtx,
207*9880d681SAndroid Build Coastguard Worker MCContext &Ctx,
208*9880d681SAndroid Build Coastguard Worker MCStreamer &Out) = 0;
209*9880d681SAndroid Build Coastguard Worker
210*9880d681SAndroid Build Coastguard Worker virtual void InstrumentMemOperandSmall(X86Operand &Op, unsigned AccessSize,
211*9880d681SAndroid Build Coastguard Worker bool IsWrite,
212*9880d681SAndroid Build Coastguard Worker const RegisterContext &RegCtx,
213*9880d681SAndroid Build Coastguard Worker MCContext &Ctx, MCStreamer &Out) = 0;
214*9880d681SAndroid Build Coastguard Worker virtual void InstrumentMemOperandLarge(X86Operand &Op, unsigned AccessSize,
215*9880d681SAndroid Build Coastguard Worker bool IsWrite,
216*9880d681SAndroid Build Coastguard Worker const RegisterContext &RegCtx,
217*9880d681SAndroid Build Coastguard Worker MCContext &Ctx, MCStreamer &Out) = 0;
218*9880d681SAndroid Build Coastguard Worker
219*9880d681SAndroid Build Coastguard Worker virtual void InstrumentMOVSImpl(unsigned AccessSize, MCContext &Ctx,
220*9880d681SAndroid Build Coastguard Worker MCStreamer &Out) = 0;
221*9880d681SAndroid Build Coastguard Worker
222*9880d681SAndroid Build Coastguard Worker void InstrumentMemOperand(X86Operand &Op, unsigned AccessSize, bool IsWrite,
223*9880d681SAndroid Build Coastguard Worker const RegisterContext &RegCtx, MCContext &Ctx,
224*9880d681SAndroid Build Coastguard Worker MCStreamer &Out);
225*9880d681SAndroid Build Coastguard Worker void InstrumentMOVSBase(unsigned DstReg, unsigned SrcReg, unsigned CntReg,
226*9880d681SAndroid Build Coastguard Worker unsigned AccessSize, MCContext &Ctx, MCStreamer &Out);
227*9880d681SAndroid Build Coastguard Worker
228*9880d681SAndroid Build Coastguard Worker void InstrumentMOVS(const MCInst &Inst, OperandVector &Operands,
229*9880d681SAndroid Build Coastguard Worker MCContext &Ctx, const MCInstrInfo &MII, MCStreamer &Out);
230*9880d681SAndroid Build Coastguard Worker void InstrumentMOV(const MCInst &Inst, OperandVector &Operands,
231*9880d681SAndroid Build Coastguard Worker MCContext &Ctx, const MCInstrInfo &MII, MCStreamer &Out);
232*9880d681SAndroid Build Coastguard Worker
233*9880d681SAndroid Build Coastguard Worker protected:
EmitLabel(MCStreamer & Out,MCSymbol * Label)234*9880d681SAndroid Build Coastguard Worker void EmitLabel(MCStreamer &Out, MCSymbol *Label) { Out.EmitLabel(Label); }
235*9880d681SAndroid Build Coastguard Worker
EmitLEA(X86Operand & Op,unsigned Size,unsigned Reg,MCStreamer & Out)236*9880d681SAndroid Build Coastguard Worker void EmitLEA(X86Operand &Op, unsigned Size, unsigned Reg, MCStreamer &Out) {
237*9880d681SAndroid Build Coastguard Worker assert(Size == 32 || Size == 64);
238*9880d681SAndroid Build Coastguard Worker MCInst Inst;
239*9880d681SAndroid Build Coastguard Worker Inst.setOpcode(Size == 32 ? X86::LEA32r : X86::LEA64r);
240*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(getX86SubSuperRegister(Reg, Size)));
241*9880d681SAndroid Build Coastguard Worker Op.addMemOperands(Inst, 5);
242*9880d681SAndroid Build Coastguard Worker EmitInstruction(Out, Inst);
243*9880d681SAndroid Build Coastguard Worker }
244*9880d681SAndroid Build Coastguard Worker
245*9880d681SAndroid Build Coastguard Worker void ComputeMemOperandAddress(X86Operand &Op, unsigned Size,
246*9880d681SAndroid Build Coastguard Worker unsigned Reg, MCContext &Ctx, MCStreamer &Out);
247*9880d681SAndroid Build Coastguard Worker
248*9880d681SAndroid Build Coastguard Worker // Creates new memory operand with Displacement added to an original
249*9880d681SAndroid Build Coastguard Worker // displacement. Residue will contain a residue which could happen when the
250*9880d681SAndroid Build Coastguard Worker // total displacement exceeds 32-bit limitation.
251*9880d681SAndroid Build Coastguard Worker std::unique_ptr<X86Operand> AddDisplacement(X86Operand &Op,
252*9880d681SAndroid Build Coastguard Worker int64_t Displacement,
253*9880d681SAndroid Build Coastguard Worker MCContext &Ctx, int64_t *Residue);
254*9880d681SAndroid Build Coastguard Worker
is64BitMode() const255*9880d681SAndroid Build Coastguard Worker bool is64BitMode() const {
256*9880d681SAndroid Build Coastguard Worker return STI->getFeatureBits()[X86::Mode64Bit];
257*9880d681SAndroid Build Coastguard Worker }
is32BitMode() const258*9880d681SAndroid Build Coastguard Worker bool is32BitMode() const {
259*9880d681SAndroid Build Coastguard Worker return STI->getFeatureBits()[X86::Mode32Bit];
260*9880d681SAndroid Build Coastguard Worker }
is16BitMode() const261*9880d681SAndroid Build Coastguard Worker bool is16BitMode() const {
262*9880d681SAndroid Build Coastguard Worker return STI->getFeatureBits()[X86::Mode16Bit];
263*9880d681SAndroid Build Coastguard Worker }
264*9880d681SAndroid Build Coastguard Worker
getPointerWidth()265*9880d681SAndroid Build Coastguard Worker unsigned getPointerWidth() {
266*9880d681SAndroid Build Coastguard Worker if (is16BitMode()) return 16;
267*9880d681SAndroid Build Coastguard Worker if (is32BitMode()) return 32;
268*9880d681SAndroid Build Coastguard Worker if (is64BitMode()) return 64;
269*9880d681SAndroid Build Coastguard Worker llvm_unreachable("invalid mode");
270*9880d681SAndroid Build Coastguard Worker }
271*9880d681SAndroid Build Coastguard Worker
272*9880d681SAndroid Build Coastguard Worker // True when previous instruction was actually REP prefix.
273*9880d681SAndroid Build Coastguard Worker bool RepPrefix;
274*9880d681SAndroid Build Coastguard Worker
275*9880d681SAndroid Build Coastguard Worker // Offset from the original SP register.
276*9880d681SAndroid Build Coastguard Worker int64_t OrigSPOffset;
277*9880d681SAndroid Build Coastguard Worker };
278*9880d681SAndroid Build Coastguard Worker
InstrumentMemOperand(X86Operand & Op,unsigned AccessSize,bool IsWrite,const RegisterContext & RegCtx,MCContext & Ctx,MCStreamer & Out)279*9880d681SAndroid Build Coastguard Worker void X86AddressSanitizer::InstrumentMemOperand(
280*9880d681SAndroid Build Coastguard Worker X86Operand &Op, unsigned AccessSize, bool IsWrite,
281*9880d681SAndroid Build Coastguard Worker const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) {
282*9880d681SAndroid Build Coastguard Worker assert(Op.isMem() && "Op should be a memory operand.");
283*9880d681SAndroid Build Coastguard Worker assert((AccessSize & (AccessSize - 1)) == 0 && AccessSize <= 16 &&
284*9880d681SAndroid Build Coastguard Worker "AccessSize should be a power of two, less or equal than 16.");
285*9880d681SAndroid Build Coastguard Worker // FIXME: take into account load/store alignment.
286*9880d681SAndroid Build Coastguard Worker if (IsSmallMemAccess(AccessSize))
287*9880d681SAndroid Build Coastguard Worker InstrumentMemOperandSmall(Op, AccessSize, IsWrite, RegCtx, Ctx, Out);
288*9880d681SAndroid Build Coastguard Worker else
289*9880d681SAndroid Build Coastguard Worker InstrumentMemOperandLarge(Op, AccessSize, IsWrite, RegCtx, Ctx, Out);
290*9880d681SAndroid Build Coastguard Worker }
291*9880d681SAndroid Build Coastguard Worker
InstrumentMOVSBase(unsigned DstReg,unsigned SrcReg,unsigned CntReg,unsigned AccessSize,MCContext & Ctx,MCStreamer & Out)292*9880d681SAndroid Build Coastguard Worker void X86AddressSanitizer::InstrumentMOVSBase(unsigned DstReg, unsigned SrcReg,
293*9880d681SAndroid Build Coastguard Worker unsigned CntReg,
294*9880d681SAndroid Build Coastguard Worker unsigned AccessSize,
295*9880d681SAndroid Build Coastguard Worker MCContext &Ctx, MCStreamer &Out) {
296*9880d681SAndroid Build Coastguard Worker // FIXME: check whole ranges [DstReg .. DstReg + AccessSize * (CntReg - 1)]
297*9880d681SAndroid Build Coastguard Worker // and [SrcReg .. SrcReg + AccessSize * (CntReg - 1)].
298*9880d681SAndroid Build Coastguard Worker RegisterContext RegCtx(X86::RDX /* AddressReg */, X86::RAX /* ShadowReg */,
299*9880d681SAndroid Build Coastguard Worker IsSmallMemAccess(AccessSize)
300*9880d681SAndroid Build Coastguard Worker ? X86::RBX
301*9880d681SAndroid Build Coastguard Worker : X86::NoRegister /* ScratchReg */);
302*9880d681SAndroid Build Coastguard Worker RegCtx.AddBusyReg(DstReg);
303*9880d681SAndroid Build Coastguard Worker RegCtx.AddBusyReg(SrcReg);
304*9880d681SAndroid Build Coastguard Worker RegCtx.AddBusyReg(CntReg);
305*9880d681SAndroid Build Coastguard Worker
306*9880d681SAndroid Build Coastguard Worker InstrumentMemOperandPrologue(RegCtx, Ctx, Out);
307*9880d681SAndroid Build Coastguard Worker
308*9880d681SAndroid Build Coastguard Worker // Test (%SrcReg)
309*9880d681SAndroid Build Coastguard Worker {
310*9880d681SAndroid Build Coastguard Worker const MCExpr *Disp = MCConstantExpr::create(0, Ctx);
311*9880d681SAndroid Build Coastguard Worker std::unique_ptr<X86Operand> Op(X86Operand::CreateMem(
312*9880d681SAndroid Build Coastguard Worker getPointerWidth(), 0, Disp, SrcReg, 0, AccessSize, SMLoc(), SMLoc()));
313*9880d681SAndroid Build Coastguard Worker InstrumentMemOperand(*Op, AccessSize, false /* IsWrite */, RegCtx, Ctx,
314*9880d681SAndroid Build Coastguard Worker Out);
315*9880d681SAndroid Build Coastguard Worker }
316*9880d681SAndroid Build Coastguard Worker
317*9880d681SAndroid Build Coastguard Worker // Test -1(%SrcReg, %CntReg, AccessSize)
318*9880d681SAndroid Build Coastguard Worker {
319*9880d681SAndroid Build Coastguard Worker const MCExpr *Disp = MCConstantExpr::create(-1, Ctx);
320*9880d681SAndroid Build Coastguard Worker std::unique_ptr<X86Operand> Op(X86Operand::CreateMem(
321*9880d681SAndroid Build Coastguard Worker getPointerWidth(), 0, Disp, SrcReg, CntReg, AccessSize, SMLoc(),
322*9880d681SAndroid Build Coastguard Worker SMLoc()));
323*9880d681SAndroid Build Coastguard Worker InstrumentMemOperand(*Op, AccessSize, false /* IsWrite */, RegCtx, Ctx,
324*9880d681SAndroid Build Coastguard Worker Out);
325*9880d681SAndroid Build Coastguard Worker }
326*9880d681SAndroid Build Coastguard Worker
327*9880d681SAndroid Build Coastguard Worker // Test (%DstReg)
328*9880d681SAndroid Build Coastguard Worker {
329*9880d681SAndroid Build Coastguard Worker const MCExpr *Disp = MCConstantExpr::create(0, Ctx);
330*9880d681SAndroid Build Coastguard Worker std::unique_ptr<X86Operand> Op(X86Operand::CreateMem(
331*9880d681SAndroid Build Coastguard Worker getPointerWidth(), 0, Disp, DstReg, 0, AccessSize, SMLoc(), SMLoc()));
332*9880d681SAndroid Build Coastguard Worker InstrumentMemOperand(*Op, AccessSize, true /* IsWrite */, RegCtx, Ctx, Out);
333*9880d681SAndroid Build Coastguard Worker }
334*9880d681SAndroid Build Coastguard Worker
335*9880d681SAndroid Build Coastguard Worker // Test -1(%DstReg, %CntReg, AccessSize)
336*9880d681SAndroid Build Coastguard Worker {
337*9880d681SAndroid Build Coastguard Worker const MCExpr *Disp = MCConstantExpr::create(-1, Ctx);
338*9880d681SAndroid Build Coastguard Worker std::unique_ptr<X86Operand> Op(X86Operand::CreateMem(
339*9880d681SAndroid Build Coastguard Worker getPointerWidth(), 0, Disp, DstReg, CntReg, AccessSize, SMLoc(),
340*9880d681SAndroid Build Coastguard Worker SMLoc()));
341*9880d681SAndroid Build Coastguard Worker InstrumentMemOperand(*Op, AccessSize, true /* IsWrite */, RegCtx, Ctx, Out);
342*9880d681SAndroid Build Coastguard Worker }
343*9880d681SAndroid Build Coastguard Worker
344*9880d681SAndroid Build Coastguard Worker InstrumentMemOperandEpilogue(RegCtx, Ctx, Out);
345*9880d681SAndroid Build Coastguard Worker }
346*9880d681SAndroid Build Coastguard Worker
InstrumentMOVS(const MCInst & Inst,OperandVector & Operands,MCContext & Ctx,const MCInstrInfo & MII,MCStreamer & Out)347*9880d681SAndroid Build Coastguard Worker void X86AddressSanitizer::InstrumentMOVS(const MCInst &Inst,
348*9880d681SAndroid Build Coastguard Worker OperandVector &Operands,
349*9880d681SAndroid Build Coastguard Worker MCContext &Ctx, const MCInstrInfo &MII,
350*9880d681SAndroid Build Coastguard Worker MCStreamer &Out) {
351*9880d681SAndroid Build Coastguard Worker // Access size in bytes.
352*9880d681SAndroid Build Coastguard Worker unsigned AccessSize = 0;
353*9880d681SAndroid Build Coastguard Worker
354*9880d681SAndroid Build Coastguard Worker switch (Inst.getOpcode()) {
355*9880d681SAndroid Build Coastguard Worker case X86::MOVSB:
356*9880d681SAndroid Build Coastguard Worker AccessSize = 1;
357*9880d681SAndroid Build Coastguard Worker break;
358*9880d681SAndroid Build Coastguard Worker case X86::MOVSW:
359*9880d681SAndroid Build Coastguard Worker AccessSize = 2;
360*9880d681SAndroid Build Coastguard Worker break;
361*9880d681SAndroid Build Coastguard Worker case X86::MOVSL:
362*9880d681SAndroid Build Coastguard Worker AccessSize = 4;
363*9880d681SAndroid Build Coastguard Worker break;
364*9880d681SAndroid Build Coastguard Worker case X86::MOVSQ:
365*9880d681SAndroid Build Coastguard Worker AccessSize = 8;
366*9880d681SAndroid Build Coastguard Worker break;
367*9880d681SAndroid Build Coastguard Worker default:
368*9880d681SAndroid Build Coastguard Worker return;
369*9880d681SAndroid Build Coastguard Worker }
370*9880d681SAndroid Build Coastguard Worker
371*9880d681SAndroid Build Coastguard Worker InstrumentMOVSImpl(AccessSize, Ctx, Out);
372*9880d681SAndroid Build Coastguard Worker }
373*9880d681SAndroid Build Coastguard Worker
InstrumentMOV(const MCInst & Inst,OperandVector & Operands,MCContext & Ctx,const MCInstrInfo & MII,MCStreamer & Out)374*9880d681SAndroid Build Coastguard Worker void X86AddressSanitizer::InstrumentMOV(const MCInst &Inst,
375*9880d681SAndroid Build Coastguard Worker OperandVector &Operands, MCContext &Ctx,
376*9880d681SAndroid Build Coastguard Worker const MCInstrInfo &MII,
377*9880d681SAndroid Build Coastguard Worker MCStreamer &Out) {
378*9880d681SAndroid Build Coastguard Worker // Access size in bytes.
379*9880d681SAndroid Build Coastguard Worker unsigned AccessSize = 0;
380*9880d681SAndroid Build Coastguard Worker
381*9880d681SAndroid Build Coastguard Worker switch (Inst.getOpcode()) {
382*9880d681SAndroid Build Coastguard Worker case X86::MOV8mi:
383*9880d681SAndroid Build Coastguard Worker case X86::MOV8mr:
384*9880d681SAndroid Build Coastguard Worker case X86::MOV8rm:
385*9880d681SAndroid Build Coastguard Worker AccessSize = 1;
386*9880d681SAndroid Build Coastguard Worker break;
387*9880d681SAndroid Build Coastguard Worker case X86::MOV16mi:
388*9880d681SAndroid Build Coastguard Worker case X86::MOV16mr:
389*9880d681SAndroid Build Coastguard Worker case X86::MOV16rm:
390*9880d681SAndroid Build Coastguard Worker AccessSize = 2;
391*9880d681SAndroid Build Coastguard Worker break;
392*9880d681SAndroid Build Coastguard Worker case X86::MOV32mi:
393*9880d681SAndroid Build Coastguard Worker case X86::MOV32mr:
394*9880d681SAndroid Build Coastguard Worker case X86::MOV32rm:
395*9880d681SAndroid Build Coastguard Worker AccessSize = 4;
396*9880d681SAndroid Build Coastguard Worker break;
397*9880d681SAndroid Build Coastguard Worker case X86::MOV64mi32:
398*9880d681SAndroid Build Coastguard Worker case X86::MOV64mr:
399*9880d681SAndroid Build Coastguard Worker case X86::MOV64rm:
400*9880d681SAndroid Build Coastguard Worker AccessSize = 8;
401*9880d681SAndroid Build Coastguard Worker break;
402*9880d681SAndroid Build Coastguard Worker case X86::MOVAPDmr:
403*9880d681SAndroid Build Coastguard Worker case X86::MOVAPSmr:
404*9880d681SAndroid Build Coastguard Worker case X86::MOVAPDrm:
405*9880d681SAndroid Build Coastguard Worker case X86::MOVAPSrm:
406*9880d681SAndroid Build Coastguard Worker AccessSize = 16;
407*9880d681SAndroid Build Coastguard Worker break;
408*9880d681SAndroid Build Coastguard Worker default:
409*9880d681SAndroid Build Coastguard Worker return;
410*9880d681SAndroid Build Coastguard Worker }
411*9880d681SAndroid Build Coastguard Worker
412*9880d681SAndroid Build Coastguard Worker const bool IsWrite = MII.get(Inst.getOpcode()).mayStore();
413*9880d681SAndroid Build Coastguard Worker
414*9880d681SAndroid Build Coastguard Worker for (unsigned Ix = 0; Ix < Operands.size(); ++Ix) {
415*9880d681SAndroid Build Coastguard Worker assert(Operands[Ix]);
416*9880d681SAndroid Build Coastguard Worker MCParsedAsmOperand &Op = *Operands[Ix];
417*9880d681SAndroid Build Coastguard Worker if (Op.isMem()) {
418*9880d681SAndroid Build Coastguard Worker X86Operand &MemOp = static_cast<X86Operand &>(Op);
419*9880d681SAndroid Build Coastguard Worker RegisterContext RegCtx(
420*9880d681SAndroid Build Coastguard Worker X86::RDI /* AddressReg */, X86::RAX /* ShadowReg */,
421*9880d681SAndroid Build Coastguard Worker IsSmallMemAccess(AccessSize) ? X86::RCX
422*9880d681SAndroid Build Coastguard Worker : X86::NoRegister /* ScratchReg */);
423*9880d681SAndroid Build Coastguard Worker RegCtx.AddBusyRegs(MemOp);
424*9880d681SAndroid Build Coastguard Worker InstrumentMemOperandPrologue(RegCtx, Ctx, Out);
425*9880d681SAndroid Build Coastguard Worker InstrumentMemOperand(MemOp, AccessSize, IsWrite, RegCtx, Ctx, Out);
426*9880d681SAndroid Build Coastguard Worker InstrumentMemOperandEpilogue(RegCtx, Ctx, Out);
427*9880d681SAndroid Build Coastguard Worker }
428*9880d681SAndroid Build Coastguard Worker }
429*9880d681SAndroid Build Coastguard Worker }
430*9880d681SAndroid Build Coastguard Worker
ComputeMemOperandAddress(X86Operand & Op,unsigned Size,unsigned Reg,MCContext & Ctx,MCStreamer & Out)431*9880d681SAndroid Build Coastguard Worker void X86AddressSanitizer::ComputeMemOperandAddress(X86Operand &Op,
432*9880d681SAndroid Build Coastguard Worker unsigned Size,
433*9880d681SAndroid Build Coastguard Worker unsigned Reg, MCContext &Ctx,
434*9880d681SAndroid Build Coastguard Worker MCStreamer &Out) {
435*9880d681SAndroid Build Coastguard Worker int64_t Displacement = 0;
436*9880d681SAndroid Build Coastguard Worker if (IsStackReg(Op.getMemBaseReg()))
437*9880d681SAndroid Build Coastguard Worker Displacement -= OrigSPOffset;
438*9880d681SAndroid Build Coastguard Worker if (IsStackReg(Op.getMemIndexReg()))
439*9880d681SAndroid Build Coastguard Worker Displacement -= OrigSPOffset * Op.getMemScale();
440*9880d681SAndroid Build Coastguard Worker
441*9880d681SAndroid Build Coastguard Worker assert(Displacement >= 0);
442*9880d681SAndroid Build Coastguard Worker
443*9880d681SAndroid Build Coastguard Worker // Emit Op as is.
444*9880d681SAndroid Build Coastguard Worker if (Displacement == 0) {
445*9880d681SAndroid Build Coastguard Worker EmitLEA(Op, Size, Reg, Out);
446*9880d681SAndroid Build Coastguard Worker return;
447*9880d681SAndroid Build Coastguard Worker }
448*9880d681SAndroid Build Coastguard Worker
449*9880d681SAndroid Build Coastguard Worker int64_t Residue;
450*9880d681SAndroid Build Coastguard Worker std::unique_ptr<X86Operand> NewOp =
451*9880d681SAndroid Build Coastguard Worker AddDisplacement(Op, Displacement, Ctx, &Residue);
452*9880d681SAndroid Build Coastguard Worker EmitLEA(*NewOp, Size, Reg, Out);
453*9880d681SAndroid Build Coastguard Worker
454*9880d681SAndroid Build Coastguard Worker while (Residue != 0) {
455*9880d681SAndroid Build Coastguard Worker const MCConstantExpr *Disp =
456*9880d681SAndroid Build Coastguard Worker MCConstantExpr::create(ApplyDisplacementBounds(Residue), Ctx);
457*9880d681SAndroid Build Coastguard Worker std::unique_ptr<X86Operand> DispOp =
458*9880d681SAndroid Build Coastguard Worker X86Operand::CreateMem(getPointerWidth(), 0, Disp, Reg, 0, 1, SMLoc(),
459*9880d681SAndroid Build Coastguard Worker SMLoc());
460*9880d681SAndroid Build Coastguard Worker EmitLEA(*DispOp, Size, Reg, Out);
461*9880d681SAndroid Build Coastguard Worker Residue -= Disp->getValue();
462*9880d681SAndroid Build Coastguard Worker }
463*9880d681SAndroid Build Coastguard Worker }
464*9880d681SAndroid Build Coastguard Worker
465*9880d681SAndroid Build Coastguard Worker std::unique_ptr<X86Operand>
AddDisplacement(X86Operand & Op,int64_t Displacement,MCContext & Ctx,int64_t * Residue)466*9880d681SAndroid Build Coastguard Worker X86AddressSanitizer::AddDisplacement(X86Operand &Op, int64_t Displacement,
467*9880d681SAndroid Build Coastguard Worker MCContext &Ctx, int64_t *Residue) {
468*9880d681SAndroid Build Coastguard Worker assert(Displacement >= 0);
469*9880d681SAndroid Build Coastguard Worker
470*9880d681SAndroid Build Coastguard Worker if (Displacement == 0 ||
471*9880d681SAndroid Build Coastguard Worker (Op.getMemDisp() && Op.getMemDisp()->getKind() != MCExpr::Constant)) {
472*9880d681SAndroid Build Coastguard Worker *Residue = Displacement;
473*9880d681SAndroid Build Coastguard Worker return X86Operand::CreateMem(Op.getMemModeSize(), Op.getMemSegReg(),
474*9880d681SAndroid Build Coastguard Worker Op.getMemDisp(), Op.getMemBaseReg(),
475*9880d681SAndroid Build Coastguard Worker Op.getMemIndexReg(), Op.getMemScale(),
476*9880d681SAndroid Build Coastguard Worker SMLoc(), SMLoc());
477*9880d681SAndroid Build Coastguard Worker }
478*9880d681SAndroid Build Coastguard Worker
479*9880d681SAndroid Build Coastguard Worker int64_t OrigDisplacement =
480*9880d681SAndroid Build Coastguard Worker static_cast<const MCConstantExpr *>(Op.getMemDisp())->getValue();
481*9880d681SAndroid Build Coastguard Worker CheckDisplacementBounds(OrigDisplacement);
482*9880d681SAndroid Build Coastguard Worker Displacement += OrigDisplacement;
483*9880d681SAndroid Build Coastguard Worker
484*9880d681SAndroid Build Coastguard Worker int64_t NewDisplacement = ApplyDisplacementBounds(Displacement);
485*9880d681SAndroid Build Coastguard Worker CheckDisplacementBounds(NewDisplacement);
486*9880d681SAndroid Build Coastguard Worker
487*9880d681SAndroid Build Coastguard Worker *Residue = Displacement - NewDisplacement;
488*9880d681SAndroid Build Coastguard Worker const MCExpr *Disp = MCConstantExpr::create(NewDisplacement, Ctx);
489*9880d681SAndroid Build Coastguard Worker return X86Operand::CreateMem(Op.getMemModeSize(), Op.getMemSegReg(), Disp,
490*9880d681SAndroid Build Coastguard Worker Op.getMemBaseReg(), Op.getMemIndexReg(),
491*9880d681SAndroid Build Coastguard Worker Op.getMemScale(), SMLoc(), SMLoc());
492*9880d681SAndroid Build Coastguard Worker }
493*9880d681SAndroid Build Coastguard Worker
494*9880d681SAndroid Build Coastguard Worker class X86AddressSanitizer32 : public X86AddressSanitizer {
495*9880d681SAndroid Build Coastguard Worker public:
496*9880d681SAndroid Build Coastguard Worker static const long kShadowOffset = 0x20000000;
497*9880d681SAndroid Build Coastguard Worker
X86AddressSanitizer32(const MCSubtargetInfo * & STI)498*9880d681SAndroid Build Coastguard Worker X86AddressSanitizer32(const MCSubtargetInfo *&STI)
499*9880d681SAndroid Build Coastguard Worker : X86AddressSanitizer(STI) {}
500*9880d681SAndroid Build Coastguard Worker
~X86AddressSanitizer32()501*9880d681SAndroid Build Coastguard Worker ~X86AddressSanitizer32() override {}
502*9880d681SAndroid Build Coastguard Worker
GetFrameReg(const MCContext & Ctx,MCStreamer & Out)503*9880d681SAndroid Build Coastguard Worker unsigned GetFrameReg(const MCContext &Ctx, MCStreamer &Out) {
504*9880d681SAndroid Build Coastguard Worker unsigned FrameReg = GetFrameRegGeneric(Ctx, Out);
505*9880d681SAndroid Build Coastguard Worker if (FrameReg == X86::NoRegister)
506*9880d681SAndroid Build Coastguard Worker return FrameReg;
507*9880d681SAndroid Build Coastguard Worker return getX86SubSuperRegister(FrameReg, 32);
508*9880d681SAndroid Build Coastguard Worker }
509*9880d681SAndroid Build Coastguard Worker
SpillReg(MCStreamer & Out,unsigned Reg)510*9880d681SAndroid Build Coastguard Worker void SpillReg(MCStreamer &Out, unsigned Reg) {
511*9880d681SAndroid Build Coastguard Worker EmitInstruction(Out, MCInstBuilder(X86::PUSH32r).addReg(Reg));
512*9880d681SAndroid Build Coastguard Worker OrigSPOffset -= 4;
513*9880d681SAndroid Build Coastguard Worker }
514*9880d681SAndroid Build Coastguard Worker
RestoreReg(MCStreamer & Out,unsigned Reg)515*9880d681SAndroid Build Coastguard Worker void RestoreReg(MCStreamer &Out, unsigned Reg) {
516*9880d681SAndroid Build Coastguard Worker EmitInstruction(Out, MCInstBuilder(X86::POP32r).addReg(Reg));
517*9880d681SAndroid Build Coastguard Worker OrigSPOffset += 4;
518*9880d681SAndroid Build Coastguard Worker }
519*9880d681SAndroid Build Coastguard Worker
StoreFlags(MCStreamer & Out)520*9880d681SAndroid Build Coastguard Worker void StoreFlags(MCStreamer &Out) {
521*9880d681SAndroid Build Coastguard Worker EmitInstruction(Out, MCInstBuilder(X86::PUSHF32));
522*9880d681SAndroid Build Coastguard Worker OrigSPOffset -= 4;
523*9880d681SAndroid Build Coastguard Worker }
524*9880d681SAndroid Build Coastguard Worker
RestoreFlags(MCStreamer & Out)525*9880d681SAndroid Build Coastguard Worker void RestoreFlags(MCStreamer &Out) {
526*9880d681SAndroid Build Coastguard Worker EmitInstruction(Out, MCInstBuilder(X86::POPF32));
527*9880d681SAndroid Build Coastguard Worker OrigSPOffset += 4;
528*9880d681SAndroid Build Coastguard Worker }
529*9880d681SAndroid Build Coastguard Worker
InstrumentMemOperandPrologue(const RegisterContext & RegCtx,MCContext & Ctx,MCStreamer & Out)530*9880d681SAndroid Build Coastguard Worker void InstrumentMemOperandPrologue(const RegisterContext &RegCtx,
531*9880d681SAndroid Build Coastguard Worker MCContext &Ctx,
532*9880d681SAndroid Build Coastguard Worker MCStreamer &Out) override {
533*9880d681SAndroid Build Coastguard Worker unsigned LocalFrameReg = RegCtx.ChooseFrameReg(32);
534*9880d681SAndroid Build Coastguard Worker assert(LocalFrameReg != X86::NoRegister);
535*9880d681SAndroid Build Coastguard Worker
536*9880d681SAndroid Build Coastguard Worker const MCRegisterInfo *MRI = Ctx.getRegisterInfo();
537*9880d681SAndroid Build Coastguard Worker unsigned FrameReg = GetFrameReg(Ctx, Out);
538*9880d681SAndroid Build Coastguard Worker if (MRI && FrameReg != X86::NoRegister) {
539*9880d681SAndroid Build Coastguard Worker SpillReg(Out, LocalFrameReg);
540*9880d681SAndroid Build Coastguard Worker if (FrameReg == X86::ESP) {
541*9880d681SAndroid Build Coastguard Worker Out.EmitCFIAdjustCfaOffset(4 /* byte size of the LocalFrameReg */);
542*9880d681SAndroid Build Coastguard Worker Out.EmitCFIRelOffset(
543*9880d681SAndroid Build Coastguard Worker MRI->getDwarfRegNum(LocalFrameReg, true /* IsEH */), 0);
544*9880d681SAndroid Build Coastguard Worker }
545*9880d681SAndroid Build Coastguard Worker EmitInstruction(
546*9880d681SAndroid Build Coastguard Worker Out,
547*9880d681SAndroid Build Coastguard Worker MCInstBuilder(X86::MOV32rr).addReg(LocalFrameReg).addReg(FrameReg));
548*9880d681SAndroid Build Coastguard Worker Out.EmitCFIRememberState();
549*9880d681SAndroid Build Coastguard Worker Out.EmitCFIDefCfaRegister(
550*9880d681SAndroid Build Coastguard Worker MRI->getDwarfRegNum(LocalFrameReg, true /* IsEH */));
551*9880d681SAndroid Build Coastguard Worker }
552*9880d681SAndroid Build Coastguard Worker
553*9880d681SAndroid Build Coastguard Worker SpillReg(Out, RegCtx.AddressReg(32));
554*9880d681SAndroid Build Coastguard Worker SpillReg(Out, RegCtx.ShadowReg(32));
555*9880d681SAndroid Build Coastguard Worker if (RegCtx.ScratchReg(32) != X86::NoRegister)
556*9880d681SAndroid Build Coastguard Worker SpillReg(Out, RegCtx.ScratchReg(32));
557*9880d681SAndroid Build Coastguard Worker StoreFlags(Out);
558*9880d681SAndroid Build Coastguard Worker }
559*9880d681SAndroid Build Coastguard Worker
InstrumentMemOperandEpilogue(const RegisterContext & RegCtx,MCContext & Ctx,MCStreamer & Out)560*9880d681SAndroid Build Coastguard Worker void InstrumentMemOperandEpilogue(const RegisterContext &RegCtx,
561*9880d681SAndroid Build Coastguard Worker MCContext &Ctx,
562*9880d681SAndroid Build Coastguard Worker MCStreamer &Out) override {
563*9880d681SAndroid Build Coastguard Worker unsigned LocalFrameReg = RegCtx.ChooseFrameReg(32);
564*9880d681SAndroid Build Coastguard Worker assert(LocalFrameReg != X86::NoRegister);
565*9880d681SAndroid Build Coastguard Worker
566*9880d681SAndroid Build Coastguard Worker RestoreFlags(Out);
567*9880d681SAndroid Build Coastguard Worker if (RegCtx.ScratchReg(32) != X86::NoRegister)
568*9880d681SAndroid Build Coastguard Worker RestoreReg(Out, RegCtx.ScratchReg(32));
569*9880d681SAndroid Build Coastguard Worker RestoreReg(Out, RegCtx.ShadowReg(32));
570*9880d681SAndroid Build Coastguard Worker RestoreReg(Out, RegCtx.AddressReg(32));
571*9880d681SAndroid Build Coastguard Worker
572*9880d681SAndroid Build Coastguard Worker unsigned FrameReg = GetFrameReg(Ctx, Out);
573*9880d681SAndroid Build Coastguard Worker if (Ctx.getRegisterInfo() && FrameReg != X86::NoRegister) {
574*9880d681SAndroid Build Coastguard Worker RestoreReg(Out, LocalFrameReg);
575*9880d681SAndroid Build Coastguard Worker Out.EmitCFIRestoreState();
576*9880d681SAndroid Build Coastguard Worker if (FrameReg == X86::ESP)
577*9880d681SAndroid Build Coastguard Worker Out.EmitCFIAdjustCfaOffset(-4 /* byte size of the LocalFrameReg */);
578*9880d681SAndroid Build Coastguard Worker }
579*9880d681SAndroid Build Coastguard Worker }
580*9880d681SAndroid Build Coastguard Worker
581*9880d681SAndroid Build Coastguard Worker void InstrumentMemOperandSmall(X86Operand &Op, unsigned AccessSize,
582*9880d681SAndroid Build Coastguard Worker bool IsWrite,
583*9880d681SAndroid Build Coastguard Worker const RegisterContext &RegCtx,
584*9880d681SAndroid Build Coastguard Worker MCContext &Ctx,
585*9880d681SAndroid Build Coastguard Worker MCStreamer &Out) override;
586*9880d681SAndroid Build Coastguard Worker void InstrumentMemOperandLarge(X86Operand &Op, unsigned AccessSize,
587*9880d681SAndroid Build Coastguard Worker bool IsWrite,
588*9880d681SAndroid Build Coastguard Worker const RegisterContext &RegCtx,
589*9880d681SAndroid Build Coastguard Worker MCContext &Ctx,
590*9880d681SAndroid Build Coastguard Worker MCStreamer &Out) override;
591*9880d681SAndroid Build Coastguard Worker void InstrumentMOVSImpl(unsigned AccessSize, MCContext &Ctx,
592*9880d681SAndroid Build Coastguard Worker MCStreamer &Out) override;
593*9880d681SAndroid Build Coastguard Worker
594*9880d681SAndroid Build Coastguard Worker private:
EmitCallAsanReport(unsigned AccessSize,bool IsWrite,MCContext & Ctx,MCStreamer & Out,const RegisterContext & RegCtx)595*9880d681SAndroid Build Coastguard Worker void EmitCallAsanReport(unsigned AccessSize, bool IsWrite, MCContext &Ctx,
596*9880d681SAndroid Build Coastguard Worker MCStreamer &Out, const RegisterContext &RegCtx) {
597*9880d681SAndroid Build Coastguard Worker EmitInstruction(Out, MCInstBuilder(X86::CLD));
598*9880d681SAndroid Build Coastguard Worker EmitInstruction(Out, MCInstBuilder(X86::MMX_EMMS));
599*9880d681SAndroid Build Coastguard Worker
600*9880d681SAndroid Build Coastguard Worker EmitInstruction(Out, MCInstBuilder(X86::AND64ri8)
601*9880d681SAndroid Build Coastguard Worker .addReg(X86::ESP)
602*9880d681SAndroid Build Coastguard Worker .addReg(X86::ESP)
603*9880d681SAndroid Build Coastguard Worker .addImm(-16));
604*9880d681SAndroid Build Coastguard Worker EmitInstruction(
605*9880d681SAndroid Build Coastguard Worker Out, MCInstBuilder(X86::PUSH32r).addReg(RegCtx.AddressReg(32)));
606*9880d681SAndroid Build Coastguard Worker
607*9880d681SAndroid Build Coastguard Worker MCSymbol *FnSym = Ctx.getOrCreateSymbol(llvm::Twine("__asan_report_") +
608*9880d681SAndroid Build Coastguard Worker (IsWrite ? "store" : "load") +
609*9880d681SAndroid Build Coastguard Worker llvm::Twine(AccessSize));
610*9880d681SAndroid Build Coastguard Worker const MCSymbolRefExpr *FnExpr =
611*9880d681SAndroid Build Coastguard Worker MCSymbolRefExpr::create(FnSym, MCSymbolRefExpr::VK_PLT, Ctx);
612*9880d681SAndroid Build Coastguard Worker EmitInstruction(Out, MCInstBuilder(X86::CALLpcrel32).addExpr(FnExpr));
613*9880d681SAndroid Build Coastguard Worker }
614*9880d681SAndroid Build Coastguard Worker };
615*9880d681SAndroid Build Coastguard Worker
InstrumentMemOperandSmall(X86Operand & Op,unsigned AccessSize,bool IsWrite,const RegisterContext & RegCtx,MCContext & Ctx,MCStreamer & Out)616*9880d681SAndroid Build Coastguard Worker void X86AddressSanitizer32::InstrumentMemOperandSmall(
617*9880d681SAndroid Build Coastguard Worker X86Operand &Op, unsigned AccessSize, bool IsWrite,
618*9880d681SAndroid Build Coastguard Worker const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) {
619*9880d681SAndroid Build Coastguard Worker unsigned AddressRegI32 = RegCtx.AddressReg(32);
620*9880d681SAndroid Build Coastguard Worker unsigned ShadowRegI32 = RegCtx.ShadowReg(32);
621*9880d681SAndroid Build Coastguard Worker unsigned ShadowRegI8 = RegCtx.ShadowReg(8);
622*9880d681SAndroid Build Coastguard Worker
623*9880d681SAndroid Build Coastguard Worker assert(RegCtx.ScratchReg(32) != X86::NoRegister);
624*9880d681SAndroid Build Coastguard Worker unsigned ScratchRegI32 = RegCtx.ScratchReg(32);
625*9880d681SAndroid Build Coastguard Worker
626*9880d681SAndroid Build Coastguard Worker ComputeMemOperandAddress(Op, 32, AddressRegI32, Ctx, Out);
627*9880d681SAndroid Build Coastguard Worker
628*9880d681SAndroid Build Coastguard Worker EmitInstruction(Out, MCInstBuilder(X86::MOV32rr).addReg(ShadowRegI32).addReg(
629*9880d681SAndroid Build Coastguard Worker AddressRegI32));
630*9880d681SAndroid Build Coastguard Worker EmitInstruction(Out, MCInstBuilder(X86::SHR32ri)
631*9880d681SAndroid Build Coastguard Worker .addReg(ShadowRegI32)
632*9880d681SAndroid Build Coastguard Worker .addReg(ShadowRegI32)
633*9880d681SAndroid Build Coastguard Worker .addImm(3));
634*9880d681SAndroid Build Coastguard Worker
635*9880d681SAndroid Build Coastguard Worker {
636*9880d681SAndroid Build Coastguard Worker MCInst Inst;
637*9880d681SAndroid Build Coastguard Worker Inst.setOpcode(X86::MOV8rm);
638*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(ShadowRegI8));
639*9880d681SAndroid Build Coastguard Worker const MCExpr *Disp = MCConstantExpr::create(kShadowOffset, Ctx);
640*9880d681SAndroid Build Coastguard Worker std::unique_ptr<X86Operand> Op(
641*9880d681SAndroid Build Coastguard Worker X86Operand::CreateMem(getPointerWidth(), 0, Disp, ShadowRegI32, 0, 1,
642*9880d681SAndroid Build Coastguard Worker SMLoc(), SMLoc()));
643*9880d681SAndroid Build Coastguard Worker Op->addMemOperands(Inst, 5);
644*9880d681SAndroid Build Coastguard Worker EmitInstruction(Out, Inst);
645*9880d681SAndroid Build Coastguard Worker }
646*9880d681SAndroid Build Coastguard Worker
647*9880d681SAndroid Build Coastguard Worker EmitInstruction(
648*9880d681SAndroid Build Coastguard Worker Out, MCInstBuilder(X86::TEST8rr).addReg(ShadowRegI8).addReg(ShadowRegI8));
649*9880d681SAndroid Build Coastguard Worker MCSymbol *DoneSym = Ctx.createTempSymbol();
650*9880d681SAndroid Build Coastguard Worker const MCExpr *DoneExpr = MCSymbolRefExpr::create(DoneSym, Ctx);
651*9880d681SAndroid Build Coastguard Worker EmitInstruction(Out, MCInstBuilder(X86::JE_1).addExpr(DoneExpr));
652*9880d681SAndroid Build Coastguard Worker
653*9880d681SAndroid Build Coastguard Worker EmitInstruction(Out, MCInstBuilder(X86::MOV32rr).addReg(ScratchRegI32).addReg(
654*9880d681SAndroid Build Coastguard Worker AddressRegI32));
655*9880d681SAndroid Build Coastguard Worker EmitInstruction(Out, MCInstBuilder(X86::AND32ri)
656*9880d681SAndroid Build Coastguard Worker .addReg(ScratchRegI32)
657*9880d681SAndroid Build Coastguard Worker .addReg(ScratchRegI32)
658*9880d681SAndroid Build Coastguard Worker .addImm(7));
659*9880d681SAndroid Build Coastguard Worker
660*9880d681SAndroid Build Coastguard Worker switch (AccessSize) {
661*9880d681SAndroid Build Coastguard Worker default: llvm_unreachable("Incorrect access size");
662*9880d681SAndroid Build Coastguard Worker case 1:
663*9880d681SAndroid Build Coastguard Worker break;
664*9880d681SAndroid Build Coastguard Worker case 2: {
665*9880d681SAndroid Build Coastguard Worker const MCExpr *Disp = MCConstantExpr::create(1, Ctx);
666*9880d681SAndroid Build Coastguard Worker std::unique_ptr<X86Operand> Op(
667*9880d681SAndroid Build Coastguard Worker X86Operand::CreateMem(getPointerWidth(), 0, Disp, ScratchRegI32, 0, 1,
668*9880d681SAndroid Build Coastguard Worker SMLoc(), SMLoc()));
669*9880d681SAndroid Build Coastguard Worker EmitLEA(*Op, 32, ScratchRegI32, Out);
670*9880d681SAndroid Build Coastguard Worker break;
671*9880d681SAndroid Build Coastguard Worker }
672*9880d681SAndroid Build Coastguard Worker case 4:
673*9880d681SAndroid Build Coastguard Worker EmitInstruction(Out, MCInstBuilder(X86::ADD32ri8)
674*9880d681SAndroid Build Coastguard Worker .addReg(ScratchRegI32)
675*9880d681SAndroid Build Coastguard Worker .addReg(ScratchRegI32)
676*9880d681SAndroid Build Coastguard Worker .addImm(3));
677*9880d681SAndroid Build Coastguard Worker break;
678*9880d681SAndroid Build Coastguard Worker }
679*9880d681SAndroid Build Coastguard Worker
680*9880d681SAndroid Build Coastguard Worker EmitInstruction(
681*9880d681SAndroid Build Coastguard Worker Out,
682*9880d681SAndroid Build Coastguard Worker MCInstBuilder(X86::MOVSX32rr8).addReg(ShadowRegI32).addReg(ShadowRegI8));
683*9880d681SAndroid Build Coastguard Worker EmitInstruction(Out, MCInstBuilder(X86::CMP32rr).addReg(ScratchRegI32).addReg(
684*9880d681SAndroid Build Coastguard Worker ShadowRegI32));
685*9880d681SAndroid Build Coastguard Worker EmitInstruction(Out, MCInstBuilder(X86::JL_1).addExpr(DoneExpr));
686*9880d681SAndroid Build Coastguard Worker
687*9880d681SAndroid Build Coastguard Worker EmitCallAsanReport(AccessSize, IsWrite, Ctx, Out, RegCtx);
688*9880d681SAndroid Build Coastguard Worker EmitLabel(Out, DoneSym);
689*9880d681SAndroid Build Coastguard Worker }
690*9880d681SAndroid Build Coastguard Worker
InstrumentMemOperandLarge(X86Operand & Op,unsigned AccessSize,bool IsWrite,const RegisterContext & RegCtx,MCContext & Ctx,MCStreamer & Out)691*9880d681SAndroid Build Coastguard Worker void X86AddressSanitizer32::InstrumentMemOperandLarge(
692*9880d681SAndroid Build Coastguard Worker X86Operand &Op, unsigned AccessSize, bool IsWrite,
693*9880d681SAndroid Build Coastguard Worker const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) {
694*9880d681SAndroid Build Coastguard Worker unsigned AddressRegI32 = RegCtx.AddressReg(32);
695*9880d681SAndroid Build Coastguard Worker unsigned ShadowRegI32 = RegCtx.ShadowReg(32);
696*9880d681SAndroid Build Coastguard Worker
697*9880d681SAndroid Build Coastguard Worker ComputeMemOperandAddress(Op, 32, AddressRegI32, Ctx, Out);
698*9880d681SAndroid Build Coastguard Worker
699*9880d681SAndroid Build Coastguard Worker EmitInstruction(Out, MCInstBuilder(X86::MOV32rr).addReg(ShadowRegI32).addReg(
700*9880d681SAndroid Build Coastguard Worker AddressRegI32));
701*9880d681SAndroid Build Coastguard Worker EmitInstruction(Out, MCInstBuilder(X86::SHR32ri)
702*9880d681SAndroid Build Coastguard Worker .addReg(ShadowRegI32)
703*9880d681SAndroid Build Coastguard Worker .addReg(ShadowRegI32)
704*9880d681SAndroid Build Coastguard Worker .addImm(3));
705*9880d681SAndroid Build Coastguard Worker {
706*9880d681SAndroid Build Coastguard Worker MCInst Inst;
707*9880d681SAndroid Build Coastguard Worker switch (AccessSize) {
708*9880d681SAndroid Build Coastguard Worker default: llvm_unreachable("Incorrect access size");
709*9880d681SAndroid Build Coastguard Worker case 8:
710*9880d681SAndroid Build Coastguard Worker Inst.setOpcode(X86::CMP8mi);
711*9880d681SAndroid Build Coastguard Worker break;
712*9880d681SAndroid Build Coastguard Worker case 16:
713*9880d681SAndroid Build Coastguard Worker Inst.setOpcode(X86::CMP16mi);
714*9880d681SAndroid Build Coastguard Worker break;
715*9880d681SAndroid Build Coastguard Worker }
716*9880d681SAndroid Build Coastguard Worker const MCExpr *Disp = MCConstantExpr::create(kShadowOffset, Ctx);
717*9880d681SAndroid Build Coastguard Worker std::unique_ptr<X86Operand> Op(
718*9880d681SAndroid Build Coastguard Worker X86Operand::CreateMem(getPointerWidth(), 0, Disp, ShadowRegI32, 0, 1,
719*9880d681SAndroid Build Coastguard Worker SMLoc(), SMLoc()));
720*9880d681SAndroid Build Coastguard Worker Op->addMemOperands(Inst, 5);
721*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(0));
722*9880d681SAndroid Build Coastguard Worker EmitInstruction(Out, Inst);
723*9880d681SAndroid Build Coastguard Worker }
724*9880d681SAndroid Build Coastguard Worker MCSymbol *DoneSym = Ctx.createTempSymbol();
725*9880d681SAndroid Build Coastguard Worker const MCExpr *DoneExpr = MCSymbolRefExpr::create(DoneSym, Ctx);
726*9880d681SAndroid Build Coastguard Worker EmitInstruction(Out, MCInstBuilder(X86::JE_1).addExpr(DoneExpr));
727*9880d681SAndroid Build Coastguard Worker
728*9880d681SAndroid Build Coastguard Worker EmitCallAsanReport(AccessSize, IsWrite, Ctx, Out, RegCtx);
729*9880d681SAndroid Build Coastguard Worker EmitLabel(Out, DoneSym);
730*9880d681SAndroid Build Coastguard Worker }
731*9880d681SAndroid Build Coastguard Worker
InstrumentMOVSImpl(unsigned AccessSize,MCContext & Ctx,MCStreamer & Out)732*9880d681SAndroid Build Coastguard Worker void X86AddressSanitizer32::InstrumentMOVSImpl(unsigned AccessSize,
733*9880d681SAndroid Build Coastguard Worker MCContext &Ctx,
734*9880d681SAndroid Build Coastguard Worker MCStreamer &Out) {
735*9880d681SAndroid Build Coastguard Worker StoreFlags(Out);
736*9880d681SAndroid Build Coastguard Worker
737*9880d681SAndroid Build Coastguard Worker // No need to test when ECX is equals to zero.
738*9880d681SAndroid Build Coastguard Worker MCSymbol *DoneSym = Ctx.createTempSymbol();
739*9880d681SAndroid Build Coastguard Worker const MCExpr *DoneExpr = MCSymbolRefExpr::create(DoneSym, Ctx);
740*9880d681SAndroid Build Coastguard Worker EmitInstruction(
741*9880d681SAndroid Build Coastguard Worker Out, MCInstBuilder(X86::TEST32rr).addReg(X86::ECX).addReg(X86::ECX));
742*9880d681SAndroid Build Coastguard Worker EmitInstruction(Out, MCInstBuilder(X86::JE_1).addExpr(DoneExpr));
743*9880d681SAndroid Build Coastguard Worker
744*9880d681SAndroid Build Coastguard Worker // Instrument first and last elements in src and dst range.
745*9880d681SAndroid Build Coastguard Worker InstrumentMOVSBase(X86::EDI /* DstReg */, X86::ESI /* SrcReg */,
746*9880d681SAndroid Build Coastguard Worker X86::ECX /* CntReg */, AccessSize, Ctx, Out);
747*9880d681SAndroid Build Coastguard Worker
748*9880d681SAndroid Build Coastguard Worker EmitLabel(Out, DoneSym);
749*9880d681SAndroid Build Coastguard Worker RestoreFlags(Out);
750*9880d681SAndroid Build Coastguard Worker }
751*9880d681SAndroid Build Coastguard Worker
752*9880d681SAndroid Build Coastguard Worker class X86AddressSanitizer64 : public X86AddressSanitizer {
753*9880d681SAndroid Build Coastguard Worker public:
754*9880d681SAndroid Build Coastguard Worker static const long kShadowOffset = 0x7fff8000;
755*9880d681SAndroid Build Coastguard Worker
X86AddressSanitizer64(const MCSubtargetInfo * & STI)756*9880d681SAndroid Build Coastguard Worker X86AddressSanitizer64(const MCSubtargetInfo *&STI)
757*9880d681SAndroid Build Coastguard Worker : X86AddressSanitizer(STI) {}
758*9880d681SAndroid Build Coastguard Worker
~X86AddressSanitizer64()759*9880d681SAndroid Build Coastguard Worker ~X86AddressSanitizer64() override {}
760*9880d681SAndroid Build Coastguard Worker
GetFrameReg(const MCContext & Ctx,MCStreamer & Out)761*9880d681SAndroid Build Coastguard Worker unsigned GetFrameReg(const MCContext &Ctx, MCStreamer &Out) {
762*9880d681SAndroid Build Coastguard Worker unsigned FrameReg = GetFrameRegGeneric(Ctx, Out);
763*9880d681SAndroid Build Coastguard Worker if (FrameReg == X86::NoRegister)
764*9880d681SAndroid Build Coastguard Worker return FrameReg;
765*9880d681SAndroid Build Coastguard Worker return getX86SubSuperRegister(FrameReg, 64);
766*9880d681SAndroid Build Coastguard Worker }
767*9880d681SAndroid Build Coastguard Worker
SpillReg(MCStreamer & Out,unsigned Reg)768*9880d681SAndroid Build Coastguard Worker void SpillReg(MCStreamer &Out, unsigned Reg) {
769*9880d681SAndroid Build Coastguard Worker EmitInstruction(Out, MCInstBuilder(X86::PUSH64r).addReg(Reg));
770*9880d681SAndroid Build Coastguard Worker OrigSPOffset -= 8;
771*9880d681SAndroid Build Coastguard Worker }
772*9880d681SAndroid Build Coastguard Worker
RestoreReg(MCStreamer & Out,unsigned Reg)773*9880d681SAndroid Build Coastguard Worker void RestoreReg(MCStreamer &Out, unsigned Reg) {
774*9880d681SAndroid Build Coastguard Worker EmitInstruction(Out, MCInstBuilder(X86::POP64r).addReg(Reg));
775*9880d681SAndroid Build Coastguard Worker OrigSPOffset += 8;
776*9880d681SAndroid Build Coastguard Worker }
777*9880d681SAndroid Build Coastguard Worker
StoreFlags(MCStreamer & Out)778*9880d681SAndroid Build Coastguard Worker void StoreFlags(MCStreamer &Out) {
779*9880d681SAndroid Build Coastguard Worker EmitInstruction(Out, MCInstBuilder(X86::PUSHF64));
780*9880d681SAndroid Build Coastguard Worker OrigSPOffset -= 8;
781*9880d681SAndroid Build Coastguard Worker }
782*9880d681SAndroid Build Coastguard Worker
RestoreFlags(MCStreamer & Out)783*9880d681SAndroid Build Coastguard Worker void RestoreFlags(MCStreamer &Out) {
784*9880d681SAndroid Build Coastguard Worker EmitInstruction(Out, MCInstBuilder(X86::POPF64));
785*9880d681SAndroid Build Coastguard Worker OrigSPOffset += 8;
786*9880d681SAndroid Build Coastguard Worker }
787*9880d681SAndroid Build Coastguard Worker
InstrumentMemOperandPrologue(const RegisterContext & RegCtx,MCContext & Ctx,MCStreamer & Out)788*9880d681SAndroid Build Coastguard Worker void InstrumentMemOperandPrologue(const RegisterContext &RegCtx,
789*9880d681SAndroid Build Coastguard Worker MCContext &Ctx,
790*9880d681SAndroid Build Coastguard Worker MCStreamer &Out) override {
791*9880d681SAndroid Build Coastguard Worker unsigned LocalFrameReg = RegCtx.ChooseFrameReg(64);
792*9880d681SAndroid Build Coastguard Worker assert(LocalFrameReg != X86::NoRegister);
793*9880d681SAndroid Build Coastguard Worker
794*9880d681SAndroid Build Coastguard Worker const MCRegisterInfo *MRI = Ctx.getRegisterInfo();
795*9880d681SAndroid Build Coastguard Worker unsigned FrameReg = GetFrameReg(Ctx, Out);
796*9880d681SAndroid Build Coastguard Worker if (MRI && FrameReg != X86::NoRegister) {
797*9880d681SAndroid Build Coastguard Worker SpillReg(Out, X86::RBP);
798*9880d681SAndroid Build Coastguard Worker if (FrameReg == X86::RSP) {
799*9880d681SAndroid Build Coastguard Worker Out.EmitCFIAdjustCfaOffset(8 /* byte size of the LocalFrameReg */);
800*9880d681SAndroid Build Coastguard Worker Out.EmitCFIRelOffset(
801*9880d681SAndroid Build Coastguard Worker MRI->getDwarfRegNum(LocalFrameReg, true /* IsEH */), 0);
802*9880d681SAndroid Build Coastguard Worker }
803*9880d681SAndroid Build Coastguard Worker EmitInstruction(
804*9880d681SAndroid Build Coastguard Worker Out,
805*9880d681SAndroid Build Coastguard Worker MCInstBuilder(X86::MOV64rr).addReg(LocalFrameReg).addReg(FrameReg));
806*9880d681SAndroid Build Coastguard Worker Out.EmitCFIRememberState();
807*9880d681SAndroid Build Coastguard Worker Out.EmitCFIDefCfaRegister(
808*9880d681SAndroid Build Coastguard Worker MRI->getDwarfRegNum(LocalFrameReg, true /* IsEH */));
809*9880d681SAndroid Build Coastguard Worker }
810*9880d681SAndroid Build Coastguard Worker
811*9880d681SAndroid Build Coastguard Worker EmitAdjustRSP(Ctx, Out, -128);
812*9880d681SAndroid Build Coastguard Worker SpillReg(Out, RegCtx.ShadowReg(64));
813*9880d681SAndroid Build Coastguard Worker SpillReg(Out, RegCtx.AddressReg(64));
814*9880d681SAndroid Build Coastguard Worker if (RegCtx.ScratchReg(64) != X86::NoRegister)
815*9880d681SAndroid Build Coastguard Worker SpillReg(Out, RegCtx.ScratchReg(64));
816*9880d681SAndroid Build Coastguard Worker StoreFlags(Out);
817*9880d681SAndroid Build Coastguard Worker }
818*9880d681SAndroid Build Coastguard Worker
InstrumentMemOperandEpilogue(const RegisterContext & RegCtx,MCContext & Ctx,MCStreamer & Out)819*9880d681SAndroid Build Coastguard Worker void InstrumentMemOperandEpilogue(const RegisterContext &RegCtx,
820*9880d681SAndroid Build Coastguard Worker MCContext &Ctx,
821*9880d681SAndroid Build Coastguard Worker MCStreamer &Out) override {
822*9880d681SAndroid Build Coastguard Worker unsigned LocalFrameReg = RegCtx.ChooseFrameReg(64);
823*9880d681SAndroid Build Coastguard Worker assert(LocalFrameReg != X86::NoRegister);
824*9880d681SAndroid Build Coastguard Worker
825*9880d681SAndroid Build Coastguard Worker RestoreFlags(Out);
826*9880d681SAndroid Build Coastguard Worker if (RegCtx.ScratchReg(64) != X86::NoRegister)
827*9880d681SAndroid Build Coastguard Worker RestoreReg(Out, RegCtx.ScratchReg(64));
828*9880d681SAndroid Build Coastguard Worker RestoreReg(Out, RegCtx.AddressReg(64));
829*9880d681SAndroid Build Coastguard Worker RestoreReg(Out, RegCtx.ShadowReg(64));
830*9880d681SAndroid Build Coastguard Worker EmitAdjustRSP(Ctx, Out, 128);
831*9880d681SAndroid Build Coastguard Worker
832*9880d681SAndroid Build Coastguard Worker unsigned FrameReg = GetFrameReg(Ctx, Out);
833*9880d681SAndroid Build Coastguard Worker if (Ctx.getRegisterInfo() && FrameReg != X86::NoRegister) {
834*9880d681SAndroid Build Coastguard Worker RestoreReg(Out, LocalFrameReg);
835*9880d681SAndroid Build Coastguard Worker Out.EmitCFIRestoreState();
836*9880d681SAndroid Build Coastguard Worker if (FrameReg == X86::RSP)
837*9880d681SAndroid Build Coastguard Worker Out.EmitCFIAdjustCfaOffset(-8 /* byte size of the LocalFrameReg */);
838*9880d681SAndroid Build Coastguard Worker }
839*9880d681SAndroid Build Coastguard Worker }
840*9880d681SAndroid Build Coastguard Worker
841*9880d681SAndroid Build Coastguard Worker void InstrumentMemOperandSmall(X86Operand &Op, unsigned AccessSize,
842*9880d681SAndroid Build Coastguard Worker bool IsWrite,
843*9880d681SAndroid Build Coastguard Worker const RegisterContext &RegCtx,
844*9880d681SAndroid Build Coastguard Worker MCContext &Ctx,
845*9880d681SAndroid Build Coastguard Worker MCStreamer &Out) override;
846*9880d681SAndroid Build Coastguard Worker void InstrumentMemOperandLarge(X86Operand &Op, unsigned AccessSize,
847*9880d681SAndroid Build Coastguard Worker bool IsWrite,
848*9880d681SAndroid Build Coastguard Worker const RegisterContext &RegCtx,
849*9880d681SAndroid Build Coastguard Worker MCContext &Ctx,
850*9880d681SAndroid Build Coastguard Worker MCStreamer &Out) override;
851*9880d681SAndroid Build Coastguard Worker void InstrumentMOVSImpl(unsigned AccessSize, MCContext &Ctx,
852*9880d681SAndroid Build Coastguard Worker MCStreamer &Out) override;
853*9880d681SAndroid Build Coastguard Worker
854*9880d681SAndroid Build Coastguard Worker private:
EmitAdjustRSP(MCContext & Ctx,MCStreamer & Out,long Offset)855*9880d681SAndroid Build Coastguard Worker void EmitAdjustRSP(MCContext &Ctx, MCStreamer &Out, long Offset) {
856*9880d681SAndroid Build Coastguard Worker const MCExpr *Disp = MCConstantExpr::create(Offset, Ctx);
857*9880d681SAndroid Build Coastguard Worker std::unique_ptr<X86Operand> Op(
858*9880d681SAndroid Build Coastguard Worker X86Operand::CreateMem(getPointerWidth(), 0, Disp, X86::RSP, 0, 1,
859*9880d681SAndroid Build Coastguard Worker SMLoc(), SMLoc()));
860*9880d681SAndroid Build Coastguard Worker EmitLEA(*Op, 64, X86::RSP, Out);
861*9880d681SAndroid Build Coastguard Worker OrigSPOffset += Offset;
862*9880d681SAndroid Build Coastguard Worker }
863*9880d681SAndroid Build Coastguard Worker
EmitCallAsanReport(unsigned AccessSize,bool IsWrite,MCContext & Ctx,MCStreamer & Out,const RegisterContext & RegCtx)864*9880d681SAndroid Build Coastguard Worker void EmitCallAsanReport(unsigned AccessSize, bool IsWrite, MCContext &Ctx,
865*9880d681SAndroid Build Coastguard Worker MCStreamer &Out, const RegisterContext &RegCtx) {
866*9880d681SAndroid Build Coastguard Worker EmitInstruction(Out, MCInstBuilder(X86::CLD));
867*9880d681SAndroid Build Coastguard Worker EmitInstruction(Out, MCInstBuilder(X86::MMX_EMMS));
868*9880d681SAndroid Build Coastguard Worker
869*9880d681SAndroid Build Coastguard Worker EmitInstruction(Out, MCInstBuilder(X86::AND64ri8)
870*9880d681SAndroid Build Coastguard Worker .addReg(X86::RSP)
871*9880d681SAndroid Build Coastguard Worker .addReg(X86::RSP)
872*9880d681SAndroid Build Coastguard Worker .addImm(-16));
873*9880d681SAndroid Build Coastguard Worker
874*9880d681SAndroid Build Coastguard Worker if (RegCtx.AddressReg(64) != X86::RDI) {
875*9880d681SAndroid Build Coastguard Worker EmitInstruction(Out, MCInstBuilder(X86::MOV64rr).addReg(X86::RDI).addReg(
876*9880d681SAndroid Build Coastguard Worker RegCtx.AddressReg(64)));
877*9880d681SAndroid Build Coastguard Worker }
878*9880d681SAndroid Build Coastguard Worker MCSymbol *FnSym = Ctx.getOrCreateSymbol(llvm::Twine("__asan_report_") +
879*9880d681SAndroid Build Coastguard Worker (IsWrite ? "store" : "load") +
880*9880d681SAndroid Build Coastguard Worker llvm::Twine(AccessSize));
881*9880d681SAndroid Build Coastguard Worker const MCSymbolRefExpr *FnExpr =
882*9880d681SAndroid Build Coastguard Worker MCSymbolRefExpr::create(FnSym, MCSymbolRefExpr::VK_PLT, Ctx);
883*9880d681SAndroid Build Coastguard Worker EmitInstruction(Out, MCInstBuilder(X86::CALL64pcrel32).addExpr(FnExpr));
884*9880d681SAndroid Build Coastguard Worker }
885*9880d681SAndroid Build Coastguard Worker };
886*9880d681SAndroid Build Coastguard Worker
InstrumentMemOperandSmall(X86Operand & Op,unsigned AccessSize,bool IsWrite,const RegisterContext & RegCtx,MCContext & Ctx,MCStreamer & Out)887*9880d681SAndroid Build Coastguard Worker void X86AddressSanitizer64::InstrumentMemOperandSmall(
888*9880d681SAndroid Build Coastguard Worker X86Operand &Op, unsigned AccessSize, bool IsWrite,
889*9880d681SAndroid Build Coastguard Worker const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) {
890*9880d681SAndroid Build Coastguard Worker unsigned AddressRegI64 = RegCtx.AddressReg(64);
891*9880d681SAndroid Build Coastguard Worker unsigned AddressRegI32 = RegCtx.AddressReg(32);
892*9880d681SAndroid Build Coastguard Worker unsigned ShadowRegI64 = RegCtx.ShadowReg(64);
893*9880d681SAndroid Build Coastguard Worker unsigned ShadowRegI32 = RegCtx.ShadowReg(32);
894*9880d681SAndroid Build Coastguard Worker unsigned ShadowRegI8 = RegCtx.ShadowReg(8);
895*9880d681SAndroid Build Coastguard Worker
896*9880d681SAndroid Build Coastguard Worker assert(RegCtx.ScratchReg(32) != X86::NoRegister);
897*9880d681SAndroid Build Coastguard Worker unsigned ScratchRegI32 = RegCtx.ScratchReg(32);
898*9880d681SAndroid Build Coastguard Worker
899*9880d681SAndroid Build Coastguard Worker ComputeMemOperandAddress(Op, 64, AddressRegI64, Ctx, Out);
900*9880d681SAndroid Build Coastguard Worker
901*9880d681SAndroid Build Coastguard Worker EmitInstruction(Out, MCInstBuilder(X86::MOV64rr).addReg(ShadowRegI64).addReg(
902*9880d681SAndroid Build Coastguard Worker AddressRegI64));
903*9880d681SAndroid Build Coastguard Worker EmitInstruction(Out, MCInstBuilder(X86::SHR64ri)
904*9880d681SAndroid Build Coastguard Worker .addReg(ShadowRegI64)
905*9880d681SAndroid Build Coastguard Worker .addReg(ShadowRegI64)
906*9880d681SAndroid Build Coastguard Worker .addImm(3));
907*9880d681SAndroid Build Coastguard Worker {
908*9880d681SAndroid Build Coastguard Worker MCInst Inst;
909*9880d681SAndroid Build Coastguard Worker Inst.setOpcode(X86::MOV8rm);
910*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createReg(ShadowRegI8));
911*9880d681SAndroid Build Coastguard Worker const MCExpr *Disp = MCConstantExpr::create(kShadowOffset, Ctx);
912*9880d681SAndroid Build Coastguard Worker std::unique_ptr<X86Operand> Op(
913*9880d681SAndroid Build Coastguard Worker X86Operand::CreateMem(getPointerWidth(), 0, Disp, ShadowRegI64, 0, 1,
914*9880d681SAndroid Build Coastguard Worker SMLoc(), SMLoc()));
915*9880d681SAndroid Build Coastguard Worker Op->addMemOperands(Inst, 5);
916*9880d681SAndroid Build Coastguard Worker EmitInstruction(Out, Inst);
917*9880d681SAndroid Build Coastguard Worker }
918*9880d681SAndroid Build Coastguard Worker
919*9880d681SAndroid Build Coastguard Worker EmitInstruction(
920*9880d681SAndroid Build Coastguard Worker Out, MCInstBuilder(X86::TEST8rr).addReg(ShadowRegI8).addReg(ShadowRegI8));
921*9880d681SAndroid Build Coastguard Worker MCSymbol *DoneSym = Ctx.createTempSymbol();
922*9880d681SAndroid Build Coastguard Worker const MCExpr *DoneExpr = MCSymbolRefExpr::create(DoneSym, Ctx);
923*9880d681SAndroid Build Coastguard Worker EmitInstruction(Out, MCInstBuilder(X86::JE_1).addExpr(DoneExpr));
924*9880d681SAndroid Build Coastguard Worker
925*9880d681SAndroid Build Coastguard Worker EmitInstruction(Out, MCInstBuilder(X86::MOV32rr).addReg(ScratchRegI32).addReg(
926*9880d681SAndroid Build Coastguard Worker AddressRegI32));
927*9880d681SAndroid Build Coastguard Worker EmitInstruction(Out, MCInstBuilder(X86::AND32ri)
928*9880d681SAndroid Build Coastguard Worker .addReg(ScratchRegI32)
929*9880d681SAndroid Build Coastguard Worker .addReg(ScratchRegI32)
930*9880d681SAndroid Build Coastguard Worker .addImm(7));
931*9880d681SAndroid Build Coastguard Worker
932*9880d681SAndroid Build Coastguard Worker switch (AccessSize) {
933*9880d681SAndroid Build Coastguard Worker default: llvm_unreachable("Incorrect access size");
934*9880d681SAndroid Build Coastguard Worker case 1:
935*9880d681SAndroid Build Coastguard Worker break;
936*9880d681SAndroid Build Coastguard Worker case 2: {
937*9880d681SAndroid Build Coastguard Worker const MCExpr *Disp = MCConstantExpr::create(1, Ctx);
938*9880d681SAndroid Build Coastguard Worker std::unique_ptr<X86Operand> Op(
939*9880d681SAndroid Build Coastguard Worker X86Operand::CreateMem(getPointerWidth(), 0, Disp, ScratchRegI32, 0, 1,
940*9880d681SAndroid Build Coastguard Worker SMLoc(), SMLoc()));
941*9880d681SAndroid Build Coastguard Worker EmitLEA(*Op, 32, ScratchRegI32, Out);
942*9880d681SAndroid Build Coastguard Worker break;
943*9880d681SAndroid Build Coastguard Worker }
944*9880d681SAndroid Build Coastguard Worker case 4:
945*9880d681SAndroid Build Coastguard Worker EmitInstruction(Out, MCInstBuilder(X86::ADD32ri8)
946*9880d681SAndroid Build Coastguard Worker .addReg(ScratchRegI32)
947*9880d681SAndroid Build Coastguard Worker .addReg(ScratchRegI32)
948*9880d681SAndroid Build Coastguard Worker .addImm(3));
949*9880d681SAndroid Build Coastguard Worker break;
950*9880d681SAndroid Build Coastguard Worker }
951*9880d681SAndroid Build Coastguard Worker
952*9880d681SAndroid Build Coastguard Worker EmitInstruction(
953*9880d681SAndroid Build Coastguard Worker Out,
954*9880d681SAndroid Build Coastguard Worker MCInstBuilder(X86::MOVSX32rr8).addReg(ShadowRegI32).addReg(ShadowRegI8));
955*9880d681SAndroid Build Coastguard Worker EmitInstruction(Out, MCInstBuilder(X86::CMP32rr).addReg(ScratchRegI32).addReg(
956*9880d681SAndroid Build Coastguard Worker ShadowRegI32));
957*9880d681SAndroid Build Coastguard Worker EmitInstruction(Out, MCInstBuilder(X86::JL_1).addExpr(DoneExpr));
958*9880d681SAndroid Build Coastguard Worker
959*9880d681SAndroid Build Coastguard Worker EmitCallAsanReport(AccessSize, IsWrite, Ctx, Out, RegCtx);
960*9880d681SAndroid Build Coastguard Worker EmitLabel(Out, DoneSym);
961*9880d681SAndroid Build Coastguard Worker }
962*9880d681SAndroid Build Coastguard Worker
InstrumentMemOperandLarge(X86Operand & Op,unsigned AccessSize,bool IsWrite,const RegisterContext & RegCtx,MCContext & Ctx,MCStreamer & Out)963*9880d681SAndroid Build Coastguard Worker void X86AddressSanitizer64::InstrumentMemOperandLarge(
964*9880d681SAndroid Build Coastguard Worker X86Operand &Op, unsigned AccessSize, bool IsWrite,
965*9880d681SAndroid Build Coastguard Worker const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) {
966*9880d681SAndroid Build Coastguard Worker unsigned AddressRegI64 = RegCtx.AddressReg(64);
967*9880d681SAndroid Build Coastguard Worker unsigned ShadowRegI64 = RegCtx.ShadowReg(64);
968*9880d681SAndroid Build Coastguard Worker
969*9880d681SAndroid Build Coastguard Worker ComputeMemOperandAddress(Op, 64, AddressRegI64, Ctx, Out);
970*9880d681SAndroid Build Coastguard Worker
971*9880d681SAndroid Build Coastguard Worker EmitInstruction(Out, MCInstBuilder(X86::MOV64rr).addReg(ShadowRegI64).addReg(
972*9880d681SAndroid Build Coastguard Worker AddressRegI64));
973*9880d681SAndroid Build Coastguard Worker EmitInstruction(Out, MCInstBuilder(X86::SHR64ri)
974*9880d681SAndroid Build Coastguard Worker .addReg(ShadowRegI64)
975*9880d681SAndroid Build Coastguard Worker .addReg(ShadowRegI64)
976*9880d681SAndroid Build Coastguard Worker .addImm(3));
977*9880d681SAndroid Build Coastguard Worker {
978*9880d681SAndroid Build Coastguard Worker MCInst Inst;
979*9880d681SAndroid Build Coastguard Worker switch (AccessSize) {
980*9880d681SAndroid Build Coastguard Worker default: llvm_unreachable("Incorrect access size");
981*9880d681SAndroid Build Coastguard Worker case 8:
982*9880d681SAndroid Build Coastguard Worker Inst.setOpcode(X86::CMP8mi);
983*9880d681SAndroid Build Coastguard Worker break;
984*9880d681SAndroid Build Coastguard Worker case 16:
985*9880d681SAndroid Build Coastguard Worker Inst.setOpcode(X86::CMP16mi);
986*9880d681SAndroid Build Coastguard Worker break;
987*9880d681SAndroid Build Coastguard Worker }
988*9880d681SAndroid Build Coastguard Worker const MCExpr *Disp = MCConstantExpr::create(kShadowOffset, Ctx);
989*9880d681SAndroid Build Coastguard Worker std::unique_ptr<X86Operand> Op(
990*9880d681SAndroid Build Coastguard Worker X86Operand::CreateMem(getPointerWidth(), 0, Disp, ShadowRegI64, 0, 1,
991*9880d681SAndroid Build Coastguard Worker SMLoc(), SMLoc()));
992*9880d681SAndroid Build Coastguard Worker Op->addMemOperands(Inst, 5);
993*9880d681SAndroid Build Coastguard Worker Inst.addOperand(MCOperand::createImm(0));
994*9880d681SAndroid Build Coastguard Worker EmitInstruction(Out, Inst);
995*9880d681SAndroid Build Coastguard Worker }
996*9880d681SAndroid Build Coastguard Worker
997*9880d681SAndroid Build Coastguard Worker MCSymbol *DoneSym = Ctx.createTempSymbol();
998*9880d681SAndroid Build Coastguard Worker const MCExpr *DoneExpr = MCSymbolRefExpr::create(DoneSym, Ctx);
999*9880d681SAndroid Build Coastguard Worker EmitInstruction(Out, MCInstBuilder(X86::JE_1).addExpr(DoneExpr));
1000*9880d681SAndroid Build Coastguard Worker
1001*9880d681SAndroid Build Coastguard Worker EmitCallAsanReport(AccessSize, IsWrite, Ctx, Out, RegCtx);
1002*9880d681SAndroid Build Coastguard Worker EmitLabel(Out, DoneSym);
1003*9880d681SAndroid Build Coastguard Worker }
1004*9880d681SAndroid Build Coastguard Worker
InstrumentMOVSImpl(unsigned AccessSize,MCContext & Ctx,MCStreamer & Out)1005*9880d681SAndroid Build Coastguard Worker void X86AddressSanitizer64::InstrumentMOVSImpl(unsigned AccessSize,
1006*9880d681SAndroid Build Coastguard Worker MCContext &Ctx,
1007*9880d681SAndroid Build Coastguard Worker MCStreamer &Out) {
1008*9880d681SAndroid Build Coastguard Worker StoreFlags(Out);
1009*9880d681SAndroid Build Coastguard Worker
1010*9880d681SAndroid Build Coastguard Worker // No need to test when RCX is equals to zero.
1011*9880d681SAndroid Build Coastguard Worker MCSymbol *DoneSym = Ctx.createTempSymbol();
1012*9880d681SAndroid Build Coastguard Worker const MCExpr *DoneExpr = MCSymbolRefExpr::create(DoneSym, Ctx);
1013*9880d681SAndroid Build Coastguard Worker EmitInstruction(
1014*9880d681SAndroid Build Coastguard Worker Out, MCInstBuilder(X86::TEST64rr).addReg(X86::RCX).addReg(X86::RCX));
1015*9880d681SAndroid Build Coastguard Worker EmitInstruction(Out, MCInstBuilder(X86::JE_1).addExpr(DoneExpr));
1016*9880d681SAndroid Build Coastguard Worker
1017*9880d681SAndroid Build Coastguard Worker // Instrument first and last elements in src and dst range.
1018*9880d681SAndroid Build Coastguard Worker InstrumentMOVSBase(X86::RDI /* DstReg */, X86::RSI /* SrcReg */,
1019*9880d681SAndroid Build Coastguard Worker X86::RCX /* CntReg */, AccessSize, Ctx, Out);
1020*9880d681SAndroid Build Coastguard Worker
1021*9880d681SAndroid Build Coastguard Worker EmitLabel(Out, DoneSym);
1022*9880d681SAndroid Build Coastguard Worker RestoreFlags(Out);
1023*9880d681SAndroid Build Coastguard Worker }
1024*9880d681SAndroid Build Coastguard Worker
1025*9880d681SAndroid Build Coastguard Worker } // End anonymous namespace
1026*9880d681SAndroid Build Coastguard Worker
X86AsmInstrumentation(const MCSubtargetInfo * & STI)1027*9880d681SAndroid Build Coastguard Worker X86AsmInstrumentation::X86AsmInstrumentation(const MCSubtargetInfo *&STI)
1028*9880d681SAndroid Build Coastguard Worker : STI(STI), InitialFrameReg(0) {}
1029*9880d681SAndroid Build Coastguard Worker
~X86AsmInstrumentation()1030*9880d681SAndroid Build Coastguard Worker X86AsmInstrumentation::~X86AsmInstrumentation() {}
1031*9880d681SAndroid Build Coastguard Worker
InstrumentAndEmitInstruction(const MCInst & Inst,OperandVector & Operands,MCContext & Ctx,const MCInstrInfo & MII,MCStreamer & Out)1032*9880d681SAndroid Build Coastguard Worker void X86AsmInstrumentation::InstrumentAndEmitInstruction(
1033*9880d681SAndroid Build Coastguard Worker const MCInst &Inst, OperandVector &Operands, MCContext &Ctx,
1034*9880d681SAndroid Build Coastguard Worker const MCInstrInfo &MII, MCStreamer &Out) {
1035*9880d681SAndroid Build Coastguard Worker EmitInstruction(Out, Inst);
1036*9880d681SAndroid Build Coastguard Worker }
1037*9880d681SAndroid Build Coastguard Worker
EmitInstruction(MCStreamer & Out,const MCInst & Inst)1038*9880d681SAndroid Build Coastguard Worker void X86AsmInstrumentation::EmitInstruction(MCStreamer &Out,
1039*9880d681SAndroid Build Coastguard Worker const MCInst &Inst) {
1040*9880d681SAndroid Build Coastguard Worker Out.EmitInstruction(Inst, *STI);
1041*9880d681SAndroid Build Coastguard Worker }
1042*9880d681SAndroid Build Coastguard Worker
GetFrameRegGeneric(const MCContext & Ctx,MCStreamer & Out)1043*9880d681SAndroid Build Coastguard Worker unsigned X86AsmInstrumentation::GetFrameRegGeneric(const MCContext &Ctx,
1044*9880d681SAndroid Build Coastguard Worker MCStreamer &Out) {
1045*9880d681SAndroid Build Coastguard Worker if (!Out.getNumFrameInfos()) // No active dwarf frame
1046*9880d681SAndroid Build Coastguard Worker return X86::NoRegister;
1047*9880d681SAndroid Build Coastguard Worker const MCDwarfFrameInfo &Frame = Out.getDwarfFrameInfos().back();
1048*9880d681SAndroid Build Coastguard Worker if (Frame.End) // Active dwarf frame is closed
1049*9880d681SAndroid Build Coastguard Worker return X86::NoRegister;
1050*9880d681SAndroid Build Coastguard Worker const MCRegisterInfo *MRI = Ctx.getRegisterInfo();
1051*9880d681SAndroid Build Coastguard Worker if (!MRI) // No register info
1052*9880d681SAndroid Build Coastguard Worker return X86::NoRegister;
1053*9880d681SAndroid Build Coastguard Worker
1054*9880d681SAndroid Build Coastguard Worker if (InitialFrameReg) {
1055*9880d681SAndroid Build Coastguard Worker // FrameReg is set explicitly, we're instrumenting a MachineFunction.
1056*9880d681SAndroid Build Coastguard Worker return InitialFrameReg;
1057*9880d681SAndroid Build Coastguard Worker }
1058*9880d681SAndroid Build Coastguard Worker
1059*9880d681SAndroid Build Coastguard Worker return MRI->getLLVMRegNum(Frame.CurrentCfaRegister, true /* IsEH */);
1060*9880d681SAndroid Build Coastguard Worker }
1061*9880d681SAndroid Build Coastguard Worker
1062*9880d681SAndroid Build Coastguard Worker X86AsmInstrumentation *
CreateX86AsmInstrumentation(const MCTargetOptions & MCOptions,const MCContext & Ctx,const MCSubtargetInfo * & STI)1063*9880d681SAndroid Build Coastguard Worker CreateX86AsmInstrumentation(const MCTargetOptions &MCOptions,
1064*9880d681SAndroid Build Coastguard Worker const MCContext &Ctx, const MCSubtargetInfo *&STI) {
1065*9880d681SAndroid Build Coastguard Worker Triple T(STI->getTargetTriple());
1066*9880d681SAndroid Build Coastguard Worker const bool hasCompilerRTSupport = T.isOSLinux();
1067*9880d681SAndroid Build Coastguard Worker if (ClAsanInstrumentAssembly && hasCompilerRTSupport &&
1068*9880d681SAndroid Build Coastguard Worker MCOptions.SanitizeAddress) {
1069*9880d681SAndroid Build Coastguard Worker if (STI->getFeatureBits()[X86::Mode32Bit] != 0)
1070*9880d681SAndroid Build Coastguard Worker return new X86AddressSanitizer32(STI);
1071*9880d681SAndroid Build Coastguard Worker if (STI->getFeatureBits()[X86::Mode64Bit] != 0)
1072*9880d681SAndroid Build Coastguard Worker return new X86AddressSanitizer64(STI);
1073*9880d681SAndroid Build Coastguard Worker }
1074*9880d681SAndroid Build Coastguard Worker return new X86AsmInstrumentation(STI);
1075*9880d681SAndroid Build Coastguard Worker }
1076*9880d681SAndroid Build Coastguard Worker
1077*9880d681SAndroid Build Coastguard Worker } // end llvm namespace
1078