blob: c38a7d1dd44df1d23f92f029c457de567d11cae2 [file] [log] [blame]
Evgeniy Stepanov49e26252014-03-14 08:58:04 +00001//===-- X86AsmInstrumentation.cpp - Instrument X86 inline assembly C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Evgeniy Stepanov49e26252014-03-14 08:58:04 +000010#include "X86AsmInstrumentation.h"
Benjamin Kramerb3e8a6d2016-01-27 10:01:28 +000011#include "MCTargetDesc/X86BaseInfo.h"
Evgeniy Stepanov49e26252014-03-14 08:58:04 +000012#include "X86Operand.h"
13#include "llvm/ADT/StringExtras.h"
Evgeniy Stepanov29865f72014-04-30 14:04:31 +000014#include "llvm/ADT/Triple.h"
Yuri Gorshenine8c81fd2014-10-07 11:03:09 +000015#include "llvm/MC/MCAsmInfo.h"
Evgeniy Stepanov49e26252014-03-14 08:58:04 +000016#include "llvm/MC/MCContext.h"
17#include "llvm/MC/MCInst.h"
18#include "llvm/MC/MCInstBuilder.h"
Evgeniy Stepanovf4a36992014-04-24 13:29:34 +000019#include "llvm/MC/MCInstrInfo.h"
Evgeniy Stepanov0a951b72014-04-23 11:16:03 +000020#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Benjamin Kramerb3e8a6d2016-01-27 10:01:28 +000021#include "llvm/MC/MCParser/MCTargetAsmParser.h"
Evgeniy Stepanov49e26252014-03-14 08:58:04 +000022#include "llvm/MC/MCStreamer.h"
23#include "llvm/MC/MCSubtargetInfo.h"
Evgeniy Stepanov0a951b72014-04-23 11:16:03 +000024#include "llvm/MC/MCTargetOptions.h"
Evgeniy Stepanov3819f022014-05-07 07:54:11 +000025#include "llvm/Support/CommandLine.h"
Yuri Gorshenin46853b52014-10-13 09:37:47 +000026#include <algorithm>
Yuri Gorshenin171eb8d2014-10-21 10:22:27 +000027#include <cassert>
28#include <vector>
Evgeniy Stepanov49e26252014-03-14 08:58:04 +000029
Yuri Gorshenin3e22bb82014-10-27 08:38:54 +000030// Following comment describes how assembly instrumentation works.
31// Currently we have only AddressSanitizer instrumentation, but we're
32// planning to implement MemorySanitizer for inline assembly too. If
33// you're not familiar with AddressSanitizer algorithm, please, read
34// https://code.google.com/p/address-sanitizer/wiki/AddressSanitizerAlgorithm.
35//
36// When inline assembly is parsed by an instance of X86AsmParser, all
37// instructions are emitted via EmitInstruction method. That's the
38// place where X86AsmInstrumentation analyzes an instruction and
39// decides, whether the instruction should be emitted as is or
40// instrumentation is required. The latter case happens when an
41// instruction reads from or writes to memory. Now instruction opcode
42// is explicitly checked, and if an instruction has a memory operand
43// (for instance, movq (%rsi, %rcx, 8), %rax) - it should be
44// instrumented. There're also exist instructions that modify
45// memory but don't have an explicit memory operands, for instance,
46// movs.
47//
48// Let's consider at first 8-byte memory accesses when an instruction
49// has an explicit memory operand. In this case we need two registers -
50// AddressReg to compute address of a memory cells which are accessed
51// and ShadowReg to compute corresponding shadow address. So, we need
52// to spill both registers before instrumentation code and restore them
53// after instrumentation. Thus, in general, instrumentation code will
54// look like this:
55// PUSHF # Store flags, otherwise they will be overwritten
56// PUSH AddressReg # spill AddressReg
57// PUSH ShadowReg # spill ShadowReg
58// LEA MemOp, AddressReg # compute address of the memory operand
59// MOV AddressReg, ShadowReg
60// SHR ShadowReg, 3
61// # ShadowOffset(AddressReg >> 3) contains address of a shadow
62// # corresponding to MemOp.
63// CMP ShadowOffset(ShadowReg), 0 # test shadow value
64// JZ .Done # when shadow equals to zero, everything is fine
65// MOV AddressReg, RDI
66// # Call __asan_report function with AddressReg as an argument
67// CALL __asan_report
68// .Done:
69// POP ShadowReg # Restore ShadowReg
70// POP AddressReg # Restore AddressReg
71// POPF # Restore flags
72//
73// Memory accesses with different size (1-, 2-, 4- and 16-byte) are
74// handled in a similar manner, but small memory accesses (less than 8
75// byte) require an additional ScratchReg, which is used for shadow value.
76//
77// If, suppose, we're instrumenting an instruction like movs, only
78// contents of RDI, RDI + AccessSize * RCX, RSI, RSI + AccessSize *
79// RCX are checked. In this case there're no need to spill and restore
80// AddressReg , ShadowReg or flags four times, they're saved on stack
81// just once, before instrumentation of these four addresses, and restored
82// at the end of the instrumentation.
83//
84// There exist several things which complicate this simple algorithm.
85// * Instrumented memory operand can have RSP as a base or an index
86// register. So we need to add a constant offset before computation
87// of memory address, since flags, AddressReg, ShadowReg, etc. were
88// already stored on stack and RSP was modified.
89// * Debug info (usually, DWARF) should be adjusted, because sometimes
90// RSP is used as a frame register. So, we need to select some
91// register as a frame register and temprorary override current CFA
92// register.
93
Evgeniy Stepanov49e26252014-03-14 08:58:04 +000094namespace llvm {
95namespace {
96
Evgeniy Stepanov3819f022014-05-07 07:54:11 +000097static cl::opt<bool> ClAsanInstrumentAssembly(
98 "asan-instrument-assembly",
99 cl::desc("instrument assembly with AddressSanitizer checks"), cl::Hidden,
100 cl::init(false));
101
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000102const int64_t MinAllowedDisplacement = std::numeric_limits<int32_t>::min();
103const int64_t MaxAllowedDisplacement = std::numeric_limits<int32_t>::max();
104
Yuri Gorsheninab1b88a2014-10-13 11:44:06 +0000105int64_t ApplyDisplacementBounds(int64_t Displacement) {
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000106 return std::max(std::min(MaxAllowedDisplacement, Displacement),
107 MinAllowedDisplacement);
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000108}
109
Yuri Gorsheninab1b88a2014-10-13 11:44:06 +0000110void CheckDisplacementBounds(int64_t Displacement) {
111 assert(Displacement >= MinAllowedDisplacement &&
112 Displacement <= MaxAllowedDisplacement);
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000113}
114
115bool IsStackReg(unsigned Reg) { return Reg == X86::RSP || Reg == X86::ESP; }
116
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000117bool IsSmallMemAccess(unsigned AccessSize) { return AccessSize < 8; }
118
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000119class X86AddressSanitizer : public X86AsmInstrumentation {
Evgeniy Stepanov50505532014-08-27 13:11:55 +0000120public:
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000121 struct RegisterContext {
Yuri Gorshenin171eb8d2014-10-21 10:22:27 +0000122 private:
123 enum RegOffset {
124 REG_OFFSET_ADDRESS = 0,
125 REG_OFFSET_SHADOW,
126 REG_OFFSET_SCRATCH
127 };
128
129 public:
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000130 RegisterContext(unsigned AddressReg, unsigned ShadowReg,
Yuri Gorshenin171eb8d2014-10-21 10:22:27 +0000131 unsigned ScratchReg) {
Craig Topper91dab7b2015-12-25 22:09:45 +0000132 BusyRegs.push_back(convReg(AddressReg, 64));
133 BusyRegs.push_back(convReg(ShadowReg, 64));
134 BusyRegs.push_back(convReg(ScratchReg, 64));
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000135 }
136
Craig Topper91dab7b2015-12-25 22:09:45 +0000137 unsigned AddressReg(unsigned Size) const {
138 return convReg(BusyRegs[REG_OFFSET_ADDRESS], Size);
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000139 }
140
Craig Topper91dab7b2015-12-25 22:09:45 +0000141 unsigned ShadowReg(unsigned Size) const {
142 return convReg(BusyRegs[REG_OFFSET_SHADOW], Size);
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000143 }
144
Craig Topper91dab7b2015-12-25 22:09:45 +0000145 unsigned ScratchReg(unsigned Size) const {
146 return convReg(BusyRegs[REG_OFFSET_SCRATCH], Size);
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000147 }
148
Yuri Gorshenin171eb8d2014-10-21 10:22:27 +0000149 void AddBusyReg(unsigned Reg) {
150 if (Reg != X86::NoRegister)
Craig Topper91dab7b2015-12-25 22:09:45 +0000151 BusyRegs.push_back(convReg(Reg, 64));
Yuri Gorshenin171eb8d2014-10-21 10:22:27 +0000152 }
153
154 void AddBusyRegs(const X86Operand &Op) {
155 AddBusyReg(Op.getMemBaseReg());
156 AddBusyReg(Op.getMemIndexReg());
157 }
158
Craig Topper91dab7b2015-12-25 22:09:45 +0000159 unsigned ChooseFrameReg(unsigned Size) const {
Craig Topper2e444922014-12-26 06:36:23 +0000160 static const MCPhysReg Candidates[] = { X86::RBP, X86::RAX, X86::RBX,
161 X86::RCX, X86::RDX, X86::RDI,
162 X86::RSI };
Yuri Gorshenin171eb8d2014-10-21 10:22:27 +0000163 for (unsigned Reg : Candidates) {
164 if (!std::count(BusyRegs.begin(), BusyRegs.end(), Reg))
Craig Topper91dab7b2015-12-25 22:09:45 +0000165 return convReg(Reg, Size);
Yuri Gorshenin171eb8d2014-10-21 10:22:27 +0000166 }
167 return X86::NoRegister;
168 }
169
170 private:
Craig Topper91dab7b2015-12-25 22:09:45 +0000171 unsigned convReg(unsigned Reg, unsigned Size) const {
172 return Reg == X86::NoRegister ? Reg : getX86SubSuperRegister(Reg, Size);
Yuri Gorshenin171eb8d2014-10-21 10:22:27 +0000173 }
174
175 std::vector<unsigned> BusyRegs;
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000176 };
177
Akira Hatanakab11ef082015-11-14 06:35:56 +0000178 X86AddressSanitizer(const MCSubtargetInfo *&STI)
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000179 : X86AsmInstrumentation(STI), RepPrefix(false), OrigSPOffset(0) {}
180
Hans Wennborgaa15bff2015-09-10 16:49:58 +0000181 ~X86AddressSanitizer() override {}
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000182
183 // X86AsmInstrumentation implementation:
Hans Wennborgaa15bff2015-09-10 16:49:58 +0000184 void InstrumentAndEmitInstruction(const MCInst &Inst,
185 OperandVector &Operands,
186 MCContext &Ctx,
187 const MCInstrInfo &MII,
188 MCStreamer &Out) override {
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000189 InstrumentMOVS(Inst, Operands, Ctx, MII, Out);
Evgeniy Stepanov50505532014-08-27 13:11:55 +0000190 if (RepPrefix)
191 EmitInstruction(Out, MCInstBuilder(X86::REP_PREFIX));
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000192
Evgeniy Stepanovf4a36992014-04-24 13:29:34 +0000193 InstrumentMOV(Inst, Operands, Ctx, MII, Out);
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000194
195 RepPrefix = (Inst.getOpcode() == X86::REP_PREFIX);
Evgeniy Stepanov50505532014-08-27 13:11:55 +0000196 if (!RepPrefix)
197 EmitInstruction(Out, Inst);
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000198 }
199
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000200 // Adjusts up stack and saves all registers used in instrumentation.
201 virtual void InstrumentMemOperandPrologue(const RegisterContext &RegCtx,
202 MCContext &Ctx,
203 MCStreamer &Out) = 0;
204
205 // Restores all registers used in instrumentation and adjusts stack.
206 virtual void InstrumentMemOperandEpilogue(const RegisterContext &RegCtx,
207 MCContext &Ctx,
208 MCStreamer &Out) = 0;
209
210 virtual void InstrumentMemOperandSmall(X86Operand &Op, unsigned AccessSize,
211 bool IsWrite,
212 const RegisterContext &RegCtx,
213 MCContext &Ctx, MCStreamer &Out) = 0;
214 virtual void InstrumentMemOperandLarge(X86Operand &Op, unsigned AccessSize,
215 bool IsWrite,
216 const RegisterContext &RegCtx,
217 MCContext &Ctx, MCStreamer &Out) = 0;
218
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000219 virtual void InstrumentMOVSImpl(unsigned AccessSize, MCContext &Ctx,
220 MCStreamer &Out) = 0;
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000221
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000222 void InstrumentMemOperand(X86Operand &Op, unsigned AccessSize, bool IsWrite,
223 const RegisterContext &RegCtx, MCContext &Ctx,
224 MCStreamer &Out);
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000225 void InstrumentMOVSBase(unsigned DstReg, unsigned SrcReg, unsigned CntReg,
226 unsigned AccessSize, MCContext &Ctx, MCStreamer &Out);
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000227
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000228 void InstrumentMOVS(const MCInst &Inst, OperandVector &Operands,
229 MCContext &Ctx, const MCInstrInfo &MII, MCStreamer &Out);
David Blaikie960ea3f2014-06-08 16:18:35 +0000230 void InstrumentMOV(const MCInst &Inst, OperandVector &Operands,
Evgeniy Stepanovf4a36992014-04-24 13:29:34 +0000231 MCContext &Ctx, const MCInstrInfo &MII, MCStreamer &Out);
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000232
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000233protected:
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000234 void EmitLabel(MCStreamer &Out, MCSymbol *Label) { Out.EmitLabel(Label); }
235
Craig Topper91dab7b2015-12-25 22:09:45 +0000236 void EmitLEA(X86Operand &Op, unsigned Size, unsigned Reg, MCStreamer &Out) {
237 assert(Size == 32 || Size == 64);
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000238 MCInst Inst;
Craig Topper91dab7b2015-12-25 22:09:45 +0000239 Inst.setOpcode(Size == 32 ? X86::LEA32r : X86::LEA64r);
240 Inst.addOperand(MCOperand::createReg(getX86SubSuperRegister(Reg, Size)));
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000241 Op.addMemOperands(Inst, 5);
242 EmitInstruction(Out, Inst);
243 }
244
Craig Topper91dab7b2015-12-25 22:09:45 +0000245 void ComputeMemOperandAddress(X86Operand &Op, unsigned Size,
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000246 unsigned Reg, MCContext &Ctx, MCStreamer &Out);
247
248 // Creates new memory operand with Displacement added to an original
249 // displacement. Residue will contain a residue which could happen when the
250 // total displacement exceeds 32-bit limitation.
251 std::unique_ptr<X86Operand> AddDisplacement(X86Operand &Op,
252 int64_t Displacement,
253 MCContext &Ctx, int64_t *Residue);
254
Craig Topper055845f2015-01-02 07:02:25 +0000255 bool is64BitMode() const {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000256 return STI->getFeatureBits()[X86::Mode64Bit];
Craig Topper055845f2015-01-02 07:02:25 +0000257 }
258 bool is32BitMode() const {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000259 return STI->getFeatureBits()[X86::Mode32Bit];
Craig Topper055845f2015-01-02 07:02:25 +0000260 }
261 bool is16BitMode() const {
Akira Hatanakab11ef082015-11-14 06:35:56 +0000262 return STI->getFeatureBits()[X86::Mode16Bit];
Craig Topper055845f2015-01-02 07:02:25 +0000263 }
264
265 unsigned getPointerWidth() {
266 if (is16BitMode()) return 16;
267 if (is32BitMode()) return 32;
268 if (is64BitMode()) return 64;
269 llvm_unreachable("invalid mode");
270 }
271
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000272 // True when previous instruction was actually REP prefix.
273 bool RepPrefix;
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000274
275 // Offset from the original SP register.
276 int64_t OrigSPOffset;
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000277};
278
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000279void X86AddressSanitizer::InstrumentMemOperand(
280 X86Operand &Op, unsigned AccessSize, bool IsWrite,
281 const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) {
David Blaikie960ea3f2014-06-08 16:18:35 +0000282 assert(Op.isMem() && "Op should be a memory operand.");
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000283 assert((AccessSize & (AccessSize - 1)) == 0 && AccessSize <= 16 &&
284 "AccessSize should be a power of two, less or equal than 16.");
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000285 // FIXME: take into account load/store alignment.
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000286 if (IsSmallMemAccess(AccessSize))
287 InstrumentMemOperandSmall(Op, AccessSize, IsWrite, RegCtx, Ctx, Out);
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000288 else
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000289 InstrumentMemOperandLarge(Op, AccessSize, IsWrite, RegCtx, Ctx, Out);
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000290}
291
Evgeniy Stepanov4d04f662014-08-27 11:10:54 +0000292void X86AddressSanitizer::InstrumentMOVSBase(unsigned DstReg, unsigned SrcReg,
293 unsigned CntReg,
294 unsigned AccessSize,
295 MCContext &Ctx, MCStreamer &Out) {
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000296 // FIXME: check whole ranges [DstReg .. DstReg + AccessSize * (CntReg - 1)]
297 // and [SrcReg .. SrcReg + AccessSize * (CntReg - 1)].
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000298 RegisterContext RegCtx(X86::RDX /* AddressReg */, X86::RAX /* ShadowReg */,
299 IsSmallMemAccess(AccessSize)
300 ? X86::RBX
301 : X86::NoRegister /* ScratchReg */);
Yuri Gorshenin171eb8d2014-10-21 10:22:27 +0000302 RegCtx.AddBusyReg(DstReg);
303 RegCtx.AddBusyReg(SrcReg);
304 RegCtx.AddBusyReg(CntReg);
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000305
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000306 InstrumentMemOperandPrologue(RegCtx, Ctx, Out);
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000307
308 // Test (%SrcReg)
309 {
Jim Grosbach13760bd2015-05-30 01:25:56 +0000310 const MCExpr *Disp = MCConstantExpr::create(0, Ctx);
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000311 std::unique_ptr<X86Operand> Op(X86Operand::CreateMem(
Craig Topper055845f2015-01-02 07:02:25 +0000312 getPointerWidth(), 0, Disp, SrcReg, 0, AccessSize, SMLoc(), SMLoc()));
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000313 InstrumentMemOperand(*Op, AccessSize, false /* IsWrite */, RegCtx, Ctx,
314 Out);
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000315 }
316
317 // Test -1(%SrcReg, %CntReg, AccessSize)
318 {
Jim Grosbach13760bd2015-05-30 01:25:56 +0000319 const MCExpr *Disp = MCConstantExpr::create(-1, Ctx);
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000320 std::unique_ptr<X86Operand> Op(X86Operand::CreateMem(
Craig Topper055845f2015-01-02 07:02:25 +0000321 getPointerWidth(), 0, Disp, SrcReg, CntReg, AccessSize, SMLoc(),
322 SMLoc()));
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000323 InstrumentMemOperand(*Op, AccessSize, false /* IsWrite */, RegCtx, Ctx,
324 Out);
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000325 }
326
327 // Test (%DstReg)
328 {
Jim Grosbach13760bd2015-05-30 01:25:56 +0000329 const MCExpr *Disp = MCConstantExpr::create(0, Ctx);
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000330 std::unique_ptr<X86Operand> Op(X86Operand::CreateMem(
Craig Topper055845f2015-01-02 07:02:25 +0000331 getPointerWidth(), 0, Disp, DstReg, 0, AccessSize, SMLoc(), SMLoc()));
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000332 InstrumentMemOperand(*Op, AccessSize, true /* IsWrite */, RegCtx, Ctx, Out);
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000333 }
334
335 // Test -1(%DstReg, %CntReg, AccessSize)
336 {
Jim Grosbach13760bd2015-05-30 01:25:56 +0000337 const MCExpr *Disp = MCConstantExpr::create(-1, Ctx);
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000338 std::unique_ptr<X86Operand> Op(X86Operand::CreateMem(
Craig Topper055845f2015-01-02 07:02:25 +0000339 getPointerWidth(), 0, Disp, DstReg, CntReg, AccessSize, SMLoc(),
340 SMLoc()));
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000341 InstrumentMemOperand(*Op, AccessSize, true /* IsWrite */, RegCtx, Ctx, Out);
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000342 }
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000343
344 InstrumentMemOperandEpilogue(RegCtx, Ctx, Out);
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000345}
346
Evgeniy Stepanov4d04f662014-08-27 11:10:54 +0000347void X86AddressSanitizer::InstrumentMOVS(const MCInst &Inst,
348 OperandVector &Operands,
349 MCContext &Ctx, const MCInstrInfo &MII,
350 MCStreamer &Out) {
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000351 // Access size in bytes.
352 unsigned AccessSize = 0;
353
354 switch (Inst.getOpcode()) {
Evgeniy Stepanov50505532014-08-27 13:11:55 +0000355 case X86::MOVSB:
356 AccessSize = 1;
357 break;
358 case X86::MOVSW:
359 AccessSize = 2;
360 break;
361 case X86::MOVSL:
362 AccessSize = 4;
363 break;
364 case X86::MOVSQ:
365 AccessSize = 8;
366 break;
367 default:
368 return;
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000369 }
370
371 InstrumentMOVSImpl(AccessSize, Ctx, Out);
372}
373
Evgeniy Stepanov4d04f662014-08-27 11:10:54 +0000374void X86AddressSanitizer::InstrumentMOV(const MCInst &Inst,
375 OperandVector &Operands, MCContext &Ctx,
376 const MCInstrInfo &MII,
377 MCStreamer &Out) {
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000378 // Access size in bytes.
379 unsigned AccessSize = 0;
Evgeniy Stepanovb6c47a52014-04-24 09:56:15 +0000380
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000381 switch (Inst.getOpcode()) {
Evgeniy Stepanov50505532014-08-27 13:11:55 +0000382 case X86::MOV8mi:
383 case X86::MOV8mr:
384 case X86::MOV8rm:
385 AccessSize = 1;
386 break;
387 case X86::MOV16mi:
388 case X86::MOV16mr:
389 case X86::MOV16rm:
390 AccessSize = 2;
391 break;
392 case X86::MOV32mi:
393 case X86::MOV32mr:
394 case X86::MOV32rm:
395 AccessSize = 4;
396 break;
397 case X86::MOV64mi32:
398 case X86::MOV64mr:
399 case X86::MOV64rm:
400 AccessSize = 8;
401 break;
402 case X86::MOVAPDmr:
403 case X86::MOVAPSmr:
404 case X86::MOVAPDrm:
405 case X86::MOVAPSrm:
406 AccessSize = 16;
407 break;
408 default:
409 return;
Evgeniy Stepanovb6c47a52014-04-24 09:56:15 +0000410 }
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000411
Evgeniy Stepanovf4a36992014-04-24 13:29:34 +0000412 const bool IsWrite = MII.get(Inst.getOpcode()).mayStore();
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000413
Evgeniy Stepanovb6c47a52014-04-24 09:56:15 +0000414 for (unsigned Ix = 0; Ix < Operands.size(); ++Ix) {
David Blaikie960ea3f2014-06-08 16:18:35 +0000415 assert(Operands[Ix]);
416 MCParsedAsmOperand &Op = *Operands[Ix];
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000417 if (Op.isMem()) {
418 X86Operand &MemOp = static_cast<X86Operand &>(Op);
Yuri Gorshenin171eb8d2014-10-21 10:22:27 +0000419 RegisterContext RegCtx(
420 X86::RDI /* AddressReg */, X86::RAX /* ShadowReg */,
421 IsSmallMemAccess(AccessSize) ? X86::RCX
422 : X86::NoRegister /* ScratchReg */);
423 RegCtx.AddBusyRegs(MemOp);
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000424 InstrumentMemOperandPrologue(RegCtx, Ctx, Out);
425 InstrumentMemOperand(MemOp, AccessSize, IsWrite, RegCtx, Ctx, Out);
426 InstrumentMemOperandEpilogue(RegCtx, Ctx, Out);
427 }
Evgeniy Stepanovb6c47a52014-04-24 09:56:15 +0000428 }
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000429}
430
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000431void X86AddressSanitizer::ComputeMemOperandAddress(X86Operand &Op,
Craig Topper91dab7b2015-12-25 22:09:45 +0000432 unsigned Size,
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000433 unsigned Reg, MCContext &Ctx,
434 MCStreamer &Out) {
435 int64_t Displacement = 0;
436 if (IsStackReg(Op.getMemBaseReg()))
437 Displacement -= OrigSPOffset;
438 if (IsStackReg(Op.getMemIndexReg()))
439 Displacement -= OrigSPOffset * Op.getMemScale();
440
441 assert(Displacement >= 0);
442
443 // Emit Op as is.
444 if (Displacement == 0) {
Craig Topper91dab7b2015-12-25 22:09:45 +0000445 EmitLEA(Op, Size, Reg, Out);
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000446 return;
447 }
448
449 int64_t Residue;
450 std::unique_ptr<X86Operand> NewOp =
451 AddDisplacement(Op, Displacement, Ctx, &Residue);
Craig Topper91dab7b2015-12-25 22:09:45 +0000452 EmitLEA(*NewOp, Size, Reg, Out);
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000453
454 while (Residue != 0) {
455 const MCConstantExpr *Disp =
Jim Grosbach13760bd2015-05-30 01:25:56 +0000456 MCConstantExpr::create(ApplyDisplacementBounds(Residue), Ctx);
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000457 std::unique_ptr<X86Operand> DispOp =
Craig Topper055845f2015-01-02 07:02:25 +0000458 X86Operand::CreateMem(getPointerWidth(), 0, Disp, Reg, 0, 1, SMLoc(),
459 SMLoc());
Craig Topper91dab7b2015-12-25 22:09:45 +0000460 EmitLEA(*DispOp, Size, Reg, Out);
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000461 Residue -= Disp->getValue();
462 }
463}
464
465std::unique_ptr<X86Operand>
466X86AddressSanitizer::AddDisplacement(X86Operand &Op, int64_t Displacement,
467 MCContext &Ctx, int64_t *Residue) {
468 assert(Displacement >= 0);
469
470 if (Displacement == 0 ||
471 (Op.getMemDisp() && Op.getMemDisp()->getKind() != MCExpr::Constant)) {
472 *Residue = Displacement;
Craig Topper055845f2015-01-02 07:02:25 +0000473 return X86Operand::CreateMem(Op.getMemModeSize(), Op.getMemSegReg(),
474 Op.getMemDisp(), Op.getMemBaseReg(),
475 Op.getMemIndexReg(), Op.getMemScale(),
476 SMLoc(), SMLoc());
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000477 }
478
479 int64_t OrigDisplacement =
480 static_cast<const MCConstantExpr *>(Op.getMemDisp())->getValue();
Yuri Gorsheninab1b88a2014-10-13 11:44:06 +0000481 CheckDisplacementBounds(OrigDisplacement);
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000482 Displacement += OrigDisplacement;
483
Yuri Gorsheninab1b88a2014-10-13 11:44:06 +0000484 int64_t NewDisplacement = ApplyDisplacementBounds(Displacement);
485 CheckDisplacementBounds(NewDisplacement);
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000486
487 *Residue = Displacement - NewDisplacement;
Jim Grosbach13760bd2015-05-30 01:25:56 +0000488 const MCExpr *Disp = MCConstantExpr::create(NewDisplacement, Ctx);
Craig Topper055845f2015-01-02 07:02:25 +0000489 return X86Operand::CreateMem(Op.getMemModeSize(), Op.getMemSegReg(), Disp,
490 Op.getMemBaseReg(), Op.getMemIndexReg(),
491 Op.getMemScale(), SMLoc(), SMLoc());
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000492}
493
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000494class X86AddressSanitizer32 : public X86AddressSanitizer {
Evgeniy Stepanov50505532014-08-27 13:11:55 +0000495public:
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000496 static const long kShadowOffset = 0x20000000;
497
Akira Hatanakab11ef082015-11-14 06:35:56 +0000498 X86AddressSanitizer32(const MCSubtargetInfo *&STI)
Evgeniy Stepanov0a951b72014-04-23 11:16:03 +0000499 : X86AddressSanitizer(STI) {}
Yuri Gorshenin3939dec2014-09-10 09:45:49 +0000500
Hans Wennborgaa15bff2015-09-10 16:49:58 +0000501 ~X86AddressSanitizer32() override {}
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000502
Yuri Gorshenine8c81fd2014-10-07 11:03:09 +0000503 unsigned GetFrameReg(const MCContext &Ctx, MCStreamer &Out) {
504 unsigned FrameReg = GetFrameRegGeneric(Ctx, Out);
505 if (FrameReg == X86::NoRegister)
506 return FrameReg;
Craig Topper91dab7b2015-12-25 22:09:45 +0000507 return getX86SubSuperRegister(FrameReg, 32);
Yuri Gorshenine8c81fd2014-10-07 11:03:09 +0000508 }
509
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000510 void SpillReg(MCStreamer &Out, unsigned Reg) {
511 EmitInstruction(Out, MCInstBuilder(X86::PUSH32r).addReg(Reg));
512 OrigSPOffset -= 4;
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000513 }
514
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000515 void RestoreReg(MCStreamer &Out, unsigned Reg) {
516 EmitInstruction(Out, MCInstBuilder(X86::POP32r).addReg(Reg));
517 OrigSPOffset += 4;
518 }
519
520 void StoreFlags(MCStreamer &Out) {
521 EmitInstruction(Out, MCInstBuilder(X86::PUSHF32));
522 OrigSPOffset -= 4;
523 }
524
525 void RestoreFlags(MCStreamer &Out) {
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000526 EmitInstruction(Out, MCInstBuilder(X86::POPF32));
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000527 OrigSPOffset += 4;
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000528 }
529
Hans Wennborgaa15bff2015-09-10 16:49:58 +0000530 void InstrumentMemOperandPrologue(const RegisterContext &RegCtx,
531 MCContext &Ctx,
532 MCStreamer &Out) override {
Craig Topper91dab7b2015-12-25 22:09:45 +0000533 unsigned LocalFrameReg = RegCtx.ChooseFrameReg(32);
Yuri Gorshenin171eb8d2014-10-21 10:22:27 +0000534 assert(LocalFrameReg != X86::NoRegister);
535
Yuri Gorshenine8c81fd2014-10-07 11:03:09 +0000536 const MCRegisterInfo *MRI = Ctx.getRegisterInfo();
537 unsigned FrameReg = GetFrameReg(Ctx, Out);
Yuri Gorshenin3939dec2014-09-10 09:45:49 +0000538 if (MRI && FrameReg != X86::NoRegister) {
Yuri Gorshenin171eb8d2014-10-21 10:22:27 +0000539 SpillReg(Out, LocalFrameReg);
Yuri Gorshenin3939dec2014-09-10 09:45:49 +0000540 if (FrameReg == X86::ESP) {
Yuri Gorshenin171eb8d2014-10-21 10:22:27 +0000541 Out.EmitCFIAdjustCfaOffset(4 /* byte size of the LocalFrameReg */);
542 Out.EmitCFIRelOffset(
543 MRI->getDwarfRegNum(LocalFrameReg, true /* IsEH */), 0);
Yuri Gorshenin3939dec2014-09-10 09:45:49 +0000544 }
545 EmitInstruction(
Yuri Gorshenin171eb8d2014-10-21 10:22:27 +0000546 Out,
547 MCInstBuilder(X86::MOV32rr).addReg(LocalFrameReg).addReg(FrameReg));
Yuri Gorshenin3939dec2014-09-10 09:45:49 +0000548 Out.EmitCFIRememberState();
Yuri Gorshenin171eb8d2014-10-21 10:22:27 +0000549 Out.EmitCFIDefCfaRegister(
550 MRI->getDwarfRegNum(LocalFrameReg, true /* IsEH */));
Yuri Gorshenin3939dec2014-09-10 09:45:49 +0000551 }
552
Craig Topper91dab7b2015-12-25 22:09:45 +0000553 SpillReg(Out, RegCtx.AddressReg(32));
554 SpillReg(Out, RegCtx.ShadowReg(32));
555 if (RegCtx.ScratchReg(32) != X86::NoRegister)
556 SpillReg(Out, RegCtx.ScratchReg(32));
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000557 StoreFlags(Out);
558 }
559
Hans Wennborgaa15bff2015-09-10 16:49:58 +0000560 void InstrumentMemOperandEpilogue(const RegisterContext &RegCtx,
561 MCContext &Ctx,
562 MCStreamer &Out) override {
Craig Topper91dab7b2015-12-25 22:09:45 +0000563 unsigned LocalFrameReg = RegCtx.ChooseFrameReg(32);
Yuri Gorshenin171eb8d2014-10-21 10:22:27 +0000564 assert(LocalFrameReg != X86::NoRegister);
565
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000566 RestoreFlags(Out);
Craig Topper91dab7b2015-12-25 22:09:45 +0000567 if (RegCtx.ScratchReg(32) != X86::NoRegister)
568 RestoreReg(Out, RegCtx.ScratchReg(32));
569 RestoreReg(Out, RegCtx.ShadowReg(32));
570 RestoreReg(Out, RegCtx.AddressReg(32));
Yuri Gorshenin3939dec2014-09-10 09:45:49 +0000571
Yuri Gorshenine8c81fd2014-10-07 11:03:09 +0000572 unsigned FrameReg = GetFrameReg(Ctx, Out);
Yuri Gorshenin3939dec2014-09-10 09:45:49 +0000573 if (Ctx.getRegisterInfo() && FrameReg != X86::NoRegister) {
Yuri Gorshenin171eb8d2014-10-21 10:22:27 +0000574 RestoreReg(Out, LocalFrameReg);
Yuri Gorshenin3939dec2014-09-10 09:45:49 +0000575 Out.EmitCFIRestoreState();
576 if (FrameReg == X86::ESP)
Yuri Gorshenin171eb8d2014-10-21 10:22:27 +0000577 Out.EmitCFIAdjustCfaOffset(-4 /* byte size of the LocalFrameReg */);
Yuri Gorshenin3939dec2014-09-10 09:45:49 +0000578 }
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000579 }
580
Hans Wennborgaa15bff2015-09-10 16:49:58 +0000581 void InstrumentMemOperandSmall(X86Operand &Op, unsigned AccessSize,
582 bool IsWrite,
583 const RegisterContext &RegCtx,
584 MCContext &Ctx,
585 MCStreamer &Out) override;
586 void InstrumentMemOperandLarge(X86Operand &Op, unsigned AccessSize,
587 bool IsWrite,
588 const RegisterContext &RegCtx,
589 MCContext &Ctx,
590 MCStreamer &Out) override;
591 void InstrumentMOVSImpl(unsigned AccessSize, MCContext &Ctx,
592 MCStreamer &Out) override;
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000593
Evgeniy Stepanov50505532014-08-27 13:11:55 +0000594private:
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000595 void EmitCallAsanReport(unsigned AccessSize, bool IsWrite, MCContext &Ctx,
596 MCStreamer &Out, const RegisterContext &RegCtx) {
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000597 EmitInstruction(Out, MCInstBuilder(X86::CLD));
598 EmitInstruction(Out, MCInstBuilder(X86::MMX_EMMS));
599
Evgeniy Stepanov4d04f662014-08-27 11:10:54 +0000600 EmitInstruction(Out, MCInstBuilder(X86::AND64ri8)
601 .addReg(X86::ESP)
602 .addReg(X86::ESP)
603 .addImm(-16));
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000604 EmitInstruction(
Craig Topper91dab7b2015-12-25 22:09:45 +0000605 Out, MCInstBuilder(X86::PUSH32r).addReg(RegCtx.AddressReg(32)));
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000606
Yaron Keren45ea8fa2015-12-14 19:28:40 +0000607 MCSymbol *FnSym = Ctx.getOrCreateSymbol(llvm::Twine("__asan_report_") +
608 (IsWrite ? "store" : "load") +
609 llvm::Twine(AccessSize));
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000610 const MCSymbolRefExpr *FnExpr =
Jim Grosbach13760bd2015-05-30 01:25:56 +0000611 MCSymbolRefExpr::create(FnSym, MCSymbolRefExpr::VK_PLT, Ctx);
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000612 EmitInstruction(Out, MCInstBuilder(X86::CALLpcrel32).addExpr(FnExpr));
613 }
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000614};
615
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000616void X86AddressSanitizer32::InstrumentMemOperandSmall(
617 X86Operand &Op, unsigned AccessSize, bool IsWrite,
618 const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) {
Craig Topper91dab7b2015-12-25 22:09:45 +0000619 unsigned AddressRegI32 = RegCtx.AddressReg(32);
620 unsigned ShadowRegI32 = RegCtx.ShadowReg(32);
621 unsigned ShadowRegI8 = RegCtx.ShadowReg(8);
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000622
Craig Topper91dab7b2015-12-25 22:09:45 +0000623 assert(RegCtx.ScratchReg(32) != X86::NoRegister);
624 unsigned ScratchRegI32 = RegCtx.ScratchReg(32);
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000625
Craig Topper91dab7b2015-12-25 22:09:45 +0000626 ComputeMemOperandAddress(Op, 32, AddressRegI32, Ctx, Out);
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000627
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000628 EmitInstruction(Out, MCInstBuilder(X86::MOV32rr).addReg(ShadowRegI32).addReg(
629 AddressRegI32));
630 EmitInstruction(Out, MCInstBuilder(X86::SHR32ri)
631 .addReg(ShadowRegI32)
632 .addReg(ShadowRegI32)
633 .addImm(3));
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000634
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000635 {
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000636 MCInst Inst;
637 Inst.setOpcode(X86::MOV8rm);
Jim Grosbache9119e42015-05-13 18:37:00 +0000638 Inst.addOperand(MCOperand::createReg(ShadowRegI8));
Jim Grosbach13760bd2015-05-30 01:25:56 +0000639 const MCExpr *Disp = MCConstantExpr::create(kShadowOffset, Ctx);
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000640 std::unique_ptr<X86Operand> Op(
Craig Topper055845f2015-01-02 07:02:25 +0000641 X86Operand::CreateMem(getPointerWidth(), 0, Disp, ShadowRegI32, 0, 1,
642 SMLoc(), SMLoc()));
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000643 Op->addMemOperands(Inst, 5);
644 EmitInstruction(Out, Inst);
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000645 }
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000646
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000647 EmitInstruction(
648 Out, MCInstBuilder(X86::TEST8rr).addReg(ShadowRegI8).addReg(ShadowRegI8));
Jim Grosbach6f482002015-05-18 18:43:14 +0000649 MCSymbol *DoneSym = Ctx.createTempSymbol();
Jim Grosbach13760bd2015-05-30 01:25:56 +0000650 const MCExpr *DoneExpr = MCSymbolRefExpr::create(DoneSym, Ctx);
Craig Topper49758aa2015-01-06 04:23:53 +0000651 EmitInstruction(Out, MCInstBuilder(X86::JE_1).addExpr(DoneExpr));
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000652
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000653 EmitInstruction(Out, MCInstBuilder(X86::MOV32rr).addReg(ScratchRegI32).addReg(
654 AddressRegI32));
655 EmitInstruction(Out, MCInstBuilder(X86::AND32ri)
656 .addReg(ScratchRegI32)
657 .addReg(ScratchRegI32)
658 .addImm(7));
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000659
660 switch (AccessSize) {
Craig Topperd3c02f12015-01-05 10:15:49 +0000661 default: llvm_unreachable("Incorrect access size");
Evgeniy Stepanov50505532014-08-27 13:11:55 +0000662 case 1:
663 break;
664 case 2: {
Jim Grosbach13760bd2015-05-30 01:25:56 +0000665 const MCExpr *Disp = MCConstantExpr::create(1, Ctx);
Evgeniy Stepanov50505532014-08-27 13:11:55 +0000666 std::unique_ptr<X86Operand> Op(
Craig Topper055845f2015-01-02 07:02:25 +0000667 X86Operand::CreateMem(getPointerWidth(), 0, Disp, ScratchRegI32, 0, 1,
668 SMLoc(), SMLoc()));
Craig Topper91dab7b2015-12-25 22:09:45 +0000669 EmitLEA(*Op, 32, ScratchRegI32, Out);
Evgeniy Stepanov50505532014-08-27 13:11:55 +0000670 break;
671 }
672 case 4:
673 EmitInstruction(Out, MCInstBuilder(X86::ADD32ri8)
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000674 .addReg(ScratchRegI32)
675 .addReg(ScratchRegI32)
Evgeniy Stepanov50505532014-08-27 13:11:55 +0000676 .addImm(3));
677 break;
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000678 }
679
680 EmitInstruction(
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000681 Out,
682 MCInstBuilder(X86::MOVSX32rr8).addReg(ShadowRegI32).addReg(ShadowRegI8));
683 EmitInstruction(Out, MCInstBuilder(X86::CMP32rr).addReg(ScratchRegI32).addReg(
684 ShadowRegI32));
Craig Topper49758aa2015-01-06 04:23:53 +0000685 EmitInstruction(Out, MCInstBuilder(X86::JL_1).addExpr(DoneExpr));
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000686
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000687 EmitCallAsanReport(AccessSize, IsWrite, Ctx, Out, RegCtx);
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000688 EmitLabel(Out, DoneSym);
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000689}
690
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000691void X86AddressSanitizer32::InstrumentMemOperandLarge(
692 X86Operand &Op, unsigned AccessSize, bool IsWrite,
693 const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) {
Craig Topper91dab7b2015-12-25 22:09:45 +0000694 unsigned AddressRegI32 = RegCtx.AddressReg(32);
695 unsigned ShadowRegI32 = RegCtx.ShadowReg(32);
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000696
Craig Topper91dab7b2015-12-25 22:09:45 +0000697 ComputeMemOperandAddress(Op, 32, AddressRegI32, Ctx, Out);
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000698
699 EmitInstruction(Out, MCInstBuilder(X86::MOV32rr).addReg(ShadowRegI32).addReg(
700 AddressRegI32));
701 EmitInstruction(Out, MCInstBuilder(X86::SHR32ri)
702 .addReg(ShadowRegI32)
703 .addReg(ShadowRegI32)
704 .addImm(3));
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000705 {
706 MCInst Inst;
707 switch (AccessSize) {
Craig Topperd3c02f12015-01-05 10:15:49 +0000708 default: llvm_unreachable("Incorrect access size");
Evgeniy Stepanov50505532014-08-27 13:11:55 +0000709 case 8:
710 Inst.setOpcode(X86::CMP8mi);
711 break;
712 case 16:
713 Inst.setOpcode(X86::CMP16mi);
714 break;
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000715 }
Jim Grosbach13760bd2015-05-30 01:25:56 +0000716 const MCExpr *Disp = MCConstantExpr::create(kShadowOffset, Ctx);
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000717 std::unique_ptr<X86Operand> Op(
Craig Topper055845f2015-01-02 07:02:25 +0000718 X86Operand::CreateMem(getPointerWidth(), 0, Disp, ShadowRegI32, 0, 1,
719 SMLoc(), SMLoc()));
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000720 Op->addMemOperands(Inst, 5);
Jim Grosbache9119e42015-05-13 18:37:00 +0000721 Inst.addOperand(MCOperand::createImm(0));
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000722 EmitInstruction(Out, Inst);
723 }
Jim Grosbach6f482002015-05-18 18:43:14 +0000724 MCSymbol *DoneSym = Ctx.createTempSymbol();
Jim Grosbach13760bd2015-05-30 01:25:56 +0000725 const MCExpr *DoneExpr = MCSymbolRefExpr::create(DoneSym, Ctx);
Craig Topper49758aa2015-01-06 04:23:53 +0000726 EmitInstruction(Out, MCInstBuilder(X86::JE_1).addExpr(DoneExpr));
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000727
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000728 EmitCallAsanReport(AccessSize, IsWrite, Ctx, Out, RegCtx);
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000729 EmitLabel(Out, DoneSym);
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000730}
731
Evgeniy Stepanov4d04f662014-08-27 11:10:54 +0000732void X86AddressSanitizer32::InstrumentMOVSImpl(unsigned AccessSize,
733 MCContext &Ctx,
734 MCStreamer &Out) {
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000735 StoreFlags(Out);
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000736
737 // No need to test when ECX is equals to zero.
Jim Grosbach6f482002015-05-18 18:43:14 +0000738 MCSymbol *DoneSym = Ctx.createTempSymbol();
Jim Grosbach13760bd2015-05-30 01:25:56 +0000739 const MCExpr *DoneExpr = MCSymbolRefExpr::create(DoneSym, Ctx);
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000740 EmitInstruction(
741 Out, MCInstBuilder(X86::TEST32rr).addReg(X86::ECX).addReg(X86::ECX));
Craig Topper49758aa2015-01-06 04:23:53 +0000742 EmitInstruction(Out, MCInstBuilder(X86::JE_1).addExpr(DoneExpr));
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000743
744 // Instrument first and last elements in src and dst range.
745 InstrumentMOVSBase(X86::EDI /* DstReg */, X86::ESI /* SrcReg */,
746 X86::ECX /* CntReg */, AccessSize, Ctx, Out);
747
748 EmitLabel(Out, DoneSym);
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000749 RestoreFlags(Out);
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000750}
751
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000752class X86AddressSanitizer64 : public X86AddressSanitizer {
Evgeniy Stepanov50505532014-08-27 13:11:55 +0000753public:
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000754 static const long kShadowOffset = 0x7fff8000;
755
Akira Hatanakab11ef082015-11-14 06:35:56 +0000756 X86AddressSanitizer64(const MCSubtargetInfo *&STI)
Evgeniy Stepanov0a951b72014-04-23 11:16:03 +0000757 : X86AddressSanitizer(STI) {}
Yuri Gorshenin3939dec2014-09-10 09:45:49 +0000758
Hans Wennborgaa15bff2015-09-10 16:49:58 +0000759 ~X86AddressSanitizer64() override {}
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000760
Yuri Gorshenine8c81fd2014-10-07 11:03:09 +0000761 unsigned GetFrameReg(const MCContext &Ctx, MCStreamer &Out) {
762 unsigned FrameReg = GetFrameRegGeneric(Ctx, Out);
763 if (FrameReg == X86::NoRegister)
764 return FrameReg;
Craig Topper91dab7b2015-12-25 22:09:45 +0000765 return getX86SubSuperRegister(FrameReg, 64);
Yuri Gorshenine8c81fd2014-10-07 11:03:09 +0000766 }
767
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000768 void SpillReg(MCStreamer &Out, unsigned Reg) {
769 EmitInstruction(Out, MCInstBuilder(X86::PUSH64r).addReg(Reg));
770 OrigSPOffset -= 8;
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000771 }
772
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000773 void RestoreReg(MCStreamer &Out, unsigned Reg) {
774 EmitInstruction(Out, MCInstBuilder(X86::POP64r).addReg(Reg));
775 OrigSPOffset += 8;
776 }
777
778 void StoreFlags(MCStreamer &Out) {
779 EmitInstruction(Out, MCInstBuilder(X86::PUSHF64));
780 OrigSPOffset -= 8;
781 }
782
783 void RestoreFlags(MCStreamer &Out) {
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000784 EmitInstruction(Out, MCInstBuilder(X86::POPF64));
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000785 OrigSPOffset += 8;
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000786 }
787
Hans Wennborgaa15bff2015-09-10 16:49:58 +0000788 void InstrumentMemOperandPrologue(const RegisterContext &RegCtx,
789 MCContext &Ctx,
790 MCStreamer &Out) override {
Craig Topper91dab7b2015-12-25 22:09:45 +0000791 unsigned LocalFrameReg = RegCtx.ChooseFrameReg(64);
Yuri Gorshenin171eb8d2014-10-21 10:22:27 +0000792 assert(LocalFrameReg != X86::NoRegister);
793
Yuri Gorshenine8c81fd2014-10-07 11:03:09 +0000794 const MCRegisterInfo *MRI = Ctx.getRegisterInfo();
795 unsigned FrameReg = GetFrameReg(Ctx, Out);
796 if (MRI && FrameReg != X86::NoRegister) {
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000797 SpillReg(Out, X86::RBP);
Yuri Gorshenin3939dec2014-09-10 09:45:49 +0000798 if (FrameReg == X86::RSP) {
Yuri Gorshenin171eb8d2014-10-21 10:22:27 +0000799 Out.EmitCFIAdjustCfaOffset(8 /* byte size of the LocalFrameReg */);
800 Out.EmitCFIRelOffset(
801 MRI->getDwarfRegNum(LocalFrameReg, true /* IsEH */), 0);
Yuri Gorshenin3939dec2014-09-10 09:45:49 +0000802 }
803 EmitInstruction(
Yuri Gorshenin171eb8d2014-10-21 10:22:27 +0000804 Out,
805 MCInstBuilder(X86::MOV64rr).addReg(LocalFrameReg).addReg(FrameReg));
Yuri Gorshenin3939dec2014-09-10 09:45:49 +0000806 Out.EmitCFIRememberState();
Yuri Gorshenin171eb8d2014-10-21 10:22:27 +0000807 Out.EmitCFIDefCfaRegister(
808 MRI->getDwarfRegNum(LocalFrameReg, true /* IsEH */));
Yuri Gorshenin3939dec2014-09-10 09:45:49 +0000809 }
810
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000811 EmitAdjustRSP(Ctx, Out, -128);
Craig Topper91dab7b2015-12-25 22:09:45 +0000812 SpillReg(Out, RegCtx.ShadowReg(64));
813 SpillReg(Out, RegCtx.AddressReg(64));
814 if (RegCtx.ScratchReg(64) != X86::NoRegister)
815 SpillReg(Out, RegCtx.ScratchReg(64));
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000816 StoreFlags(Out);
817 }
818
Hans Wennborgaa15bff2015-09-10 16:49:58 +0000819 void InstrumentMemOperandEpilogue(const RegisterContext &RegCtx,
820 MCContext &Ctx,
821 MCStreamer &Out) override {
Craig Topper91dab7b2015-12-25 22:09:45 +0000822 unsigned LocalFrameReg = RegCtx.ChooseFrameReg(64);
Yuri Gorshenin171eb8d2014-10-21 10:22:27 +0000823 assert(LocalFrameReg != X86::NoRegister);
824
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000825 RestoreFlags(Out);
Craig Topper91dab7b2015-12-25 22:09:45 +0000826 if (RegCtx.ScratchReg(64) != X86::NoRegister)
827 RestoreReg(Out, RegCtx.ScratchReg(64));
828 RestoreReg(Out, RegCtx.AddressReg(64));
829 RestoreReg(Out, RegCtx.ShadowReg(64));
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000830 EmitAdjustRSP(Ctx, Out, 128);
Yuri Gorshenin3939dec2014-09-10 09:45:49 +0000831
Yuri Gorshenine8c81fd2014-10-07 11:03:09 +0000832 unsigned FrameReg = GetFrameReg(Ctx, Out);
Yuri Gorshenin3939dec2014-09-10 09:45:49 +0000833 if (Ctx.getRegisterInfo() && FrameReg != X86::NoRegister) {
Yuri Gorshenin171eb8d2014-10-21 10:22:27 +0000834 RestoreReg(Out, LocalFrameReg);
Yuri Gorshenin3939dec2014-09-10 09:45:49 +0000835 Out.EmitCFIRestoreState();
836 if (FrameReg == X86::RSP)
Yuri Gorshenin171eb8d2014-10-21 10:22:27 +0000837 Out.EmitCFIAdjustCfaOffset(-8 /* byte size of the LocalFrameReg */);
Yuri Gorshenin3939dec2014-09-10 09:45:49 +0000838 }
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000839 }
840
Hans Wennborgaa15bff2015-09-10 16:49:58 +0000841 void InstrumentMemOperandSmall(X86Operand &Op, unsigned AccessSize,
842 bool IsWrite,
843 const RegisterContext &RegCtx,
844 MCContext &Ctx,
845 MCStreamer &Out) override;
846 void InstrumentMemOperandLarge(X86Operand &Op, unsigned AccessSize,
847 bool IsWrite,
848 const RegisterContext &RegCtx,
849 MCContext &Ctx,
850 MCStreamer &Out) override;
851 void InstrumentMOVSImpl(unsigned AccessSize, MCContext &Ctx,
NAKAMURA Takumi0a7d0ad2015-09-22 11:15:07 +0000852 MCStreamer &Out) override;
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000853
Evgeniy Stepanov50505532014-08-27 13:11:55 +0000854private:
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000855 void EmitAdjustRSP(MCContext &Ctx, MCStreamer &Out, long Offset) {
Jim Grosbach13760bd2015-05-30 01:25:56 +0000856 const MCExpr *Disp = MCConstantExpr::create(Offset, Ctx);
Benjamin Kramer8bbadc02014-05-09 09:48:03 +0000857 std::unique_ptr<X86Operand> Op(
Craig Topper055845f2015-01-02 07:02:25 +0000858 X86Operand::CreateMem(getPointerWidth(), 0, Disp, X86::RSP, 0, 1,
859 SMLoc(), SMLoc()));
Craig Topper91dab7b2015-12-25 22:09:45 +0000860 EmitLEA(*Op, 64, X86::RSP, Out);
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000861 OrigSPOffset += Offset;
Evgeniy Stepanov9661ec02014-05-08 09:55:24 +0000862 }
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000863
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000864 void EmitCallAsanReport(unsigned AccessSize, bool IsWrite, MCContext &Ctx,
865 MCStreamer &Out, const RegisterContext &RegCtx) {
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000866 EmitInstruction(Out, MCInstBuilder(X86::CLD));
867 EmitInstruction(Out, MCInstBuilder(X86::MMX_EMMS));
868
Evgeniy Stepanov4d04f662014-08-27 11:10:54 +0000869 EmitInstruction(Out, MCInstBuilder(X86::AND64ri8)
870 .addReg(X86::RSP)
871 .addReg(X86::RSP)
872 .addImm(-16));
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000873
Craig Topper91dab7b2015-12-25 22:09:45 +0000874 if (RegCtx.AddressReg(64) != X86::RDI) {
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000875 EmitInstruction(Out, MCInstBuilder(X86::MOV64rr).addReg(X86::RDI).addReg(
Craig Topper91dab7b2015-12-25 22:09:45 +0000876 RegCtx.AddressReg(64)));
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000877 }
Yaron Keren45ea8fa2015-12-14 19:28:40 +0000878 MCSymbol *FnSym = Ctx.getOrCreateSymbol(llvm::Twine("__asan_report_") +
879 (IsWrite ? "store" : "load") +
880 llvm::Twine(AccessSize));
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000881 const MCSymbolRefExpr *FnExpr =
Jim Grosbach13760bd2015-05-30 01:25:56 +0000882 MCSymbolRefExpr::create(FnSym, MCSymbolRefExpr::VK_PLT, Ctx);
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000883 EmitInstruction(Out, MCInstBuilder(X86::CALL64pcrel32).addExpr(FnExpr));
884 }
885};
886
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000887void X86AddressSanitizer64::InstrumentMemOperandSmall(
888 X86Operand &Op, unsigned AccessSize, bool IsWrite,
889 const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) {
Craig Topper91dab7b2015-12-25 22:09:45 +0000890 unsigned AddressRegI64 = RegCtx.AddressReg(64);
891 unsigned AddressRegI32 = RegCtx.AddressReg(32);
892 unsigned ShadowRegI64 = RegCtx.ShadowReg(64);
893 unsigned ShadowRegI32 = RegCtx.ShadowReg(32);
894 unsigned ShadowRegI8 = RegCtx.ShadowReg(8);
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000895
Craig Topper91dab7b2015-12-25 22:09:45 +0000896 assert(RegCtx.ScratchReg(32) != X86::NoRegister);
897 unsigned ScratchRegI32 = RegCtx.ScratchReg(32);
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000898
Craig Topper91dab7b2015-12-25 22:09:45 +0000899 ComputeMemOperandAddress(Op, 64, AddressRegI64, Ctx, Out);
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000900
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000901 EmitInstruction(Out, MCInstBuilder(X86::MOV64rr).addReg(ShadowRegI64).addReg(
902 AddressRegI64));
903 EmitInstruction(Out, MCInstBuilder(X86::SHR64ri)
904 .addReg(ShadowRegI64)
905 .addReg(ShadowRegI64)
906 .addImm(3));
Evgeniy Stepanov9661ec02014-05-08 09:55:24 +0000907 {
908 MCInst Inst;
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000909 Inst.setOpcode(X86::MOV8rm);
Jim Grosbache9119e42015-05-13 18:37:00 +0000910 Inst.addOperand(MCOperand::createReg(ShadowRegI8));
Jim Grosbach13760bd2015-05-30 01:25:56 +0000911 const MCExpr *Disp = MCConstantExpr::create(kShadowOffset, Ctx);
Benjamin Kramer8bbadc02014-05-09 09:48:03 +0000912 std::unique_ptr<X86Operand> Op(
Craig Topper055845f2015-01-02 07:02:25 +0000913 X86Operand::CreateMem(getPointerWidth(), 0, Disp, ShadowRegI64, 0, 1,
914 SMLoc(), SMLoc()));
Evgeniy Stepanov9661ec02014-05-08 09:55:24 +0000915 Op->addMemOperands(Inst, 5);
916 EmitInstruction(Out, Inst);
917 }
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000918
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000919 EmitInstruction(
920 Out, MCInstBuilder(X86::TEST8rr).addReg(ShadowRegI8).addReg(ShadowRegI8));
Jim Grosbach6f482002015-05-18 18:43:14 +0000921 MCSymbol *DoneSym = Ctx.createTempSymbol();
Jim Grosbach13760bd2015-05-30 01:25:56 +0000922 const MCExpr *DoneExpr = MCSymbolRefExpr::create(DoneSym, Ctx);
Craig Topper49758aa2015-01-06 04:23:53 +0000923 EmitInstruction(Out, MCInstBuilder(X86::JE_1).addExpr(DoneExpr));
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000924
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000925 EmitInstruction(Out, MCInstBuilder(X86::MOV32rr).addReg(ScratchRegI32).addReg(
926 AddressRegI32));
927 EmitInstruction(Out, MCInstBuilder(X86::AND32ri)
928 .addReg(ScratchRegI32)
929 .addReg(ScratchRegI32)
930 .addImm(7));
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000931
932 switch (AccessSize) {
Craig Topperd3c02f12015-01-05 10:15:49 +0000933 default: llvm_unreachable("Incorrect access size");
Evgeniy Stepanov50505532014-08-27 13:11:55 +0000934 case 1:
935 break;
936 case 2: {
Jim Grosbach13760bd2015-05-30 01:25:56 +0000937 const MCExpr *Disp = MCConstantExpr::create(1, Ctx);
Evgeniy Stepanov50505532014-08-27 13:11:55 +0000938 std::unique_ptr<X86Operand> Op(
Craig Topper055845f2015-01-02 07:02:25 +0000939 X86Operand::CreateMem(getPointerWidth(), 0, Disp, ScratchRegI32, 0, 1,
940 SMLoc(), SMLoc()));
Craig Topper91dab7b2015-12-25 22:09:45 +0000941 EmitLEA(*Op, 32, ScratchRegI32, Out);
Evgeniy Stepanov50505532014-08-27 13:11:55 +0000942 break;
943 }
944 case 4:
945 EmitInstruction(Out, MCInstBuilder(X86::ADD32ri8)
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000946 .addReg(ScratchRegI32)
947 .addReg(ScratchRegI32)
Evgeniy Stepanov50505532014-08-27 13:11:55 +0000948 .addImm(3));
949 break;
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000950 }
951
952 EmitInstruction(
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000953 Out,
954 MCInstBuilder(X86::MOVSX32rr8).addReg(ShadowRegI32).addReg(ShadowRegI8));
955 EmitInstruction(Out, MCInstBuilder(X86::CMP32rr).addReg(ScratchRegI32).addReg(
956 ShadowRegI32));
Craig Topper49758aa2015-01-06 04:23:53 +0000957 EmitInstruction(Out, MCInstBuilder(X86::JL_1).addExpr(DoneExpr));
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000958
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000959 EmitCallAsanReport(AccessSize, IsWrite, Ctx, Out, RegCtx);
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000960 EmitLabel(Out, DoneSym);
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000961}
962
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000963void X86AddressSanitizer64::InstrumentMemOperandLarge(
964 X86Operand &Op, unsigned AccessSize, bool IsWrite,
965 const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) {
Craig Topper91dab7b2015-12-25 22:09:45 +0000966 unsigned AddressRegI64 = RegCtx.AddressReg(64);
967 unsigned ShadowRegI64 = RegCtx.ShadowReg(64);
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000968
Craig Topper91dab7b2015-12-25 22:09:45 +0000969 ComputeMemOperandAddress(Op, 64, AddressRegI64, Ctx, Out);
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000970
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000971 EmitInstruction(Out, MCInstBuilder(X86::MOV64rr).addReg(ShadowRegI64).addReg(
972 AddressRegI64));
973 EmitInstruction(Out, MCInstBuilder(X86::SHR64ri)
974 .addReg(ShadowRegI64)
975 .addReg(ShadowRegI64)
976 .addImm(3));
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000977 {
978 MCInst Inst;
979 switch (AccessSize) {
Craig Topperd3c02f12015-01-05 10:15:49 +0000980 default: llvm_unreachable("Incorrect access size");
Evgeniy Stepanov50505532014-08-27 13:11:55 +0000981 case 8:
982 Inst.setOpcode(X86::CMP8mi);
983 break;
984 case 16:
985 Inst.setOpcode(X86::CMP16mi);
986 break;
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000987 }
Jim Grosbach13760bd2015-05-30 01:25:56 +0000988 const MCExpr *Disp = MCConstantExpr::create(kShadowOffset, Ctx);
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000989 std::unique_ptr<X86Operand> Op(
Craig Topper055845f2015-01-02 07:02:25 +0000990 X86Operand::CreateMem(getPointerWidth(), 0, Disp, ShadowRegI64, 0, 1,
991 SMLoc(), SMLoc()));
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000992 Op->addMemOperands(Inst, 5);
Jim Grosbache9119e42015-05-13 18:37:00 +0000993 Inst.addOperand(MCOperand::createImm(0));
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000994 EmitInstruction(Out, Inst);
995 }
996
Jim Grosbach6f482002015-05-18 18:43:14 +0000997 MCSymbol *DoneSym = Ctx.createTempSymbol();
Jim Grosbach13760bd2015-05-30 01:25:56 +0000998 const MCExpr *DoneExpr = MCSymbolRefExpr::create(DoneSym, Ctx);
Craig Topper49758aa2015-01-06 04:23:53 +0000999 EmitInstruction(Out, MCInstBuilder(X86::JE_1).addExpr(DoneExpr));
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +00001000
Yuri Gorsheninc107d142014-09-01 12:51:00 +00001001 EmitCallAsanReport(AccessSize, IsWrite, Ctx, Out, RegCtx);
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +00001002 EmitLabel(Out, DoneSym);
Evgeniy Stepanov49e26252014-03-14 08:58:04 +00001003}
1004
Evgeniy Stepanov4d04f662014-08-27 11:10:54 +00001005void X86AddressSanitizer64::InstrumentMOVSImpl(unsigned AccessSize,
1006 MCContext &Ctx,
1007 MCStreamer &Out) {
Yuri Gorsheninc107d142014-09-01 12:51:00 +00001008 StoreFlags(Out);
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +00001009
1010 // No need to test when RCX is equals to zero.
Jim Grosbach6f482002015-05-18 18:43:14 +00001011 MCSymbol *DoneSym = Ctx.createTempSymbol();
Jim Grosbach13760bd2015-05-30 01:25:56 +00001012 const MCExpr *DoneExpr = MCSymbolRefExpr::create(DoneSym, Ctx);
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +00001013 EmitInstruction(
1014 Out, MCInstBuilder(X86::TEST64rr).addReg(X86::RCX).addReg(X86::RCX));
Craig Topper49758aa2015-01-06 04:23:53 +00001015 EmitInstruction(Out, MCInstBuilder(X86::JE_1).addExpr(DoneExpr));
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +00001016
1017 // Instrument first and last elements in src and dst range.
1018 InstrumentMOVSBase(X86::RDI /* DstReg */, X86::RSI /* SrcReg */,
1019 X86::RCX /* CntReg */, AccessSize, Ctx, Out);
1020
1021 EmitLabel(Out, DoneSym);
Yuri Gorsheninc107d142014-09-01 12:51:00 +00001022 RestoreFlags(Out);
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +00001023}
1024
Evgeniy Stepanov50505532014-08-27 13:11:55 +00001025} // End anonymous namespace
Evgeniy Stepanov49e26252014-03-14 08:58:04 +00001026
Akira Hatanakab11ef082015-11-14 06:35:56 +00001027X86AsmInstrumentation::X86AsmInstrumentation(const MCSubtargetInfo *&STI)
Yuri Gorshenine8c81fd2014-10-07 11:03:09 +00001028 : STI(STI), InitialFrameReg(0) {}
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +00001029
Evgeniy Stepanov49e26252014-03-14 08:58:04 +00001030X86AsmInstrumentation::~X86AsmInstrumentation() {}
1031
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +00001032void X86AsmInstrumentation::InstrumentAndEmitInstruction(
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +00001033 const MCInst &Inst, OperandVector &Operands, MCContext &Ctx,
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +00001034 const MCInstrInfo &MII, MCStreamer &Out) {
1035 EmitInstruction(Out, Inst);
1036}
1037
1038void X86AsmInstrumentation::EmitInstruction(MCStreamer &Out,
1039 const MCInst &Inst) {
Akira Hatanakab11ef082015-11-14 06:35:56 +00001040 Out.EmitInstruction(Inst, *STI);
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +00001041}
Evgeniy Stepanov49e26252014-03-14 08:58:04 +00001042
Yuri Gorshenine8c81fd2014-10-07 11:03:09 +00001043unsigned X86AsmInstrumentation::GetFrameRegGeneric(const MCContext &Ctx,
1044 MCStreamer &Out) {
1045 if (!Out.getNumFrameInfos()) // No active dwarf frame
1046 return X86::NoRegister;
1047 const MCDwarfFrameInfo &Frame = Out.getDwarfFrameInfos().back();
1048 if (Frame.End) // Active dwarf frame is closed
1049 return X86::NoRegister;
1050 const MCRegisterInfo *MRI = Ctx.getRegisterInfo();
1051 if (!MRI) // No register info
1052 return X86::NoRegister;
1053
1054 if (InitialFrameReg) {
1055 // FrameReg is set explicitly, we're instrumenting a MachineFunction.
1056 return InitialFrameReg;
1057 }
1058
1059 return MRI->getLLVMRegNum(Frame.CurrentCfaRegister, true /* IsEH */);
1060}
1061
Evgeniy Stepanov50505532014-08-27 13:11:55 +00001062X86AsmInstrumentation *
1063CreateX86AsmInstrumentation(const MCTargetOptions &MCOptions,
Akira Hatanakab11ef082015-11-14 06:35:56 +00001064 const MCContext &Ctx, const MCSubtargetInfo *&STI) {
1065 Triple T(STI->getTargetTriple());
Daniel Sanders50f17232015-09-15 16:17:27 +00001066 const bool hasCompilerRTSupport = T.isOSLinux();
Evgeniy Stepanov3819f022014-05-07 07:54:11 +00001067 if (ClAsanInstrumentAssembly && hasCompilerRTSupport &&
1068 MCOptions.SanitizeAddress) {
Akira Hatanakab11ef082015-11-14 06:35:56 +00001069 if (STI->getFeatureBits()[X86::Mode32Bit] != 0)
Evgeniy Stepanov49e26252014-03-14 08:58:04 +00001070 return new X86AddressSanitizer32(STI);
Akira Hatanakab11ef082015-11-14 06:35:56 +00001071 if (STI->getFeatureBits()[X86::Mode64Bit] != 0)
Evgeniy Stepanov49e26252014-03-14 08:58:04 +00001072 return new X86AddressSanitizer64(STI);
1073 }
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +00001074 return new X86AsmInstrumentation(STI);
Evgeniy Stepanov49e26252014-03-14 08:58:04 +00001075}
1076
Hans Wennborgaa15bff2015-09-10 16:49:58 +00001077} // end llvm namespace