blob: 1f1a9df10b3d467c87aaf327a867dac25816aedb [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
10#include "MCTargetDesc/X86BaseInfo.h"
11#include "X86AsmInstrumentation.h"
12#include "X86Operand.h"
Yuri Gorsheninc107d142014-09-01 12:51:00 +000013#include "X86RegisterInfo.h"
Evgeniy Stepanov49e26252014-03-14 08:58:04 +000014#include "llvm/ADT/StringExtras.h"
Evgeniy Stepanov29865f72014-04-30 14:04:31 +000015#include "llvm/ADT/Triple.h"
Yuri Gorsheninc107d142014-09-01 12:51:00 +000016#include "llvm/CodeGen/MachineValueType.h"
Evgeniy Stepanov0a951b72014-04-23 11:16:03 +000017#include "llvm/IR/Function.h"
Yuri Gorshenine8c81fd2014-10-07 11:03:09 +000018#include "llvm/MC/MCAsmInfo.h"
Evgeniy Stepanov49e26252014-03-14 08:58:04 +000019#include "llvm/MC/MCContext.h"
20#include "llvm/MC/MCInst.h"
21#include "llvm/MC/MCInstBuilder.h"
Evgeniy Stepanovf4a36992014-04-24 13:29:34 +000022#include "llvm/MC/MCInstrInfo.h"
Evgeniy Stepanov0a951b72014-04-23 11:16:03 +000023#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Evgeniy Stepanov49e26252014-03-14 08:58:04 +000024#include "llvm/MC/MCStreamer.h"
25#include "llvm/MC/MCSubtargetInfo.h"
David Blaikie960ea3f2014-06-08 16:18:35 +000026#include "llvm/MC/MCTargetAsmParser.h"
Evgeniy Stepanov0a951b72014-04-23 11:16:03 +000027#include "llvm/MC/MCTargetOptions.h"
Evgeniy Stepanov3819f022014-05-07 07:54:11 +000028#include "llvm/Support/CommandLine.h"
Yuri Gorshenin46853b52014-10-13 09:37:47 +000029#include <algorithm>
Evgeniy Stepanov49e26252014-03-14 08:58:04 +000030
31namespace llvm {
32namespace {
33
Evgeniy Stepanov3819f022014-05-07 07:54:11 +000034static cl::opt<bool> ClAsanInstrumentAssembly(
35 "asan-instrument-assembly",
36 cl::desc("instrument assembly with AddressSanitizer checks"), cl::Hidden,
37 cl::init(false));
38
Yuri Gorshenin46853b52014-10-13 09:37:47 +000039const int64_t MinAllowedDisplacement = std::numeric_limits<int32_t>::min();
40const int64_t MaxAllowedDisplacement = std::numeric_limits<int32_t>::max();
41
42int64_t ApplyBounds(int64_t Displacement) {
43 return std::max(std::min(MaxAllowedDisplacement, Displacement),
44 MinAllowedDisplacement);
Evgeniy Stepanov49e26252014-03-14 08:58:04 +000045}
46
Yuri Gorshenin46853b52014-10-13 09:37:47 +000047bool InBounds(int64_t Displacement) {
48 return Displacement >= MinAllowedDisplacement &&
49 Displacement <= MaxAllowedDisplacement;
50}
51
52bool IsStackReg(unsigned Reg) { return Reg == X86::RSP || Reg == X86::ESP; }
53
Yuri Gorsheninc107d142014-09-01 12:51:00 +000054bool IsSmallMemAccess(unsigned AccessSize) { return AccessSize < 8; }
55
Evgeniy Stepanov49e26252014-03-14 08:58:04 +000056std::string FuncName(unsigned AccessSize, bool IsWrite) {
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +000057 return std::string("__asan_report_") + (IsWrite ? "store" : "load") +
58 utostr(AccessSize);
Evgeniy Stepanov49e26252014-03-14 08:58:04 +000059}
60
61class X86AddressSanitizer : public X86AsmInstrumentation {
Evgeniy Stepanov50505532014-08-27 13:11:55 +000062public:
Yuri Gorsheninc107d142014-09-01 12:51:00 +000063 struct RegisterContext {
64 RegisterContext(unsigned AddressReg, unsigned ShadowReg,
65 unsigned ScratchReg)
66 : AddressReg(AddressReg), ShadowReg(ShadowReg), ScratchReg(ScratchReg) {
67 }
68
69 unsigned addressReg(MVT::SimpleValueType VT) const {
70 return getX86SubSuperRegister(AddressReg, VT);
71 }
72
73 unsigned shadowReg(MVT::SimpleValueType VT) const {
74 return getX86SubSuperRegister(ShadowReg, VT);
75 }
76
77 unsigned scratchReg(MVT::SimpleValueType VT) const {
78 return getX86SubSuperRegister(ScratchReg, VT);
79 }
80
81 const unsigned AddressReg;
82 const unsigned ShadowReg;
83 const unsigned ScratchReg;
84 };
85
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +000086 X86AddressSanitizer(const MCSubtargetInfo &STI)
Yuri Gorshenin46853b52014-10-13 09:37:47 +000087 : X86AsmInstrumentation(STI), RepPrefix(false), OrigSPOffset(0) {}
88
Evgeniy Stepanov49e26252014-03-14 08:58:04 +000089 virtual ~X86AddressSanitizer() {}
90
91 // X86AsmInstrumentation implementation:
Evgeniy Stepanov4d04f662014-08-27 11:10:54 +000092 virtual void InstrumentAndEmitInstruction(const MCInst &Inst,
93 OperandVector &Operands,
94 MCContext &Ctx,
95 const MCInstrInfo &MII,
96 MCStreamer &Out) override {
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +000097 InstrumentMOVS(Inst, Operands, Ctx, MII, Out);
Evgeniy Stepanov50505532014-08-27 13:11:55 +000098 if (RepPrefix)
99 EmitInstruction(Out, MCInstBuilder(X86::REP_PREFIX));
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000100
Evgeniy Stepanovf4a36992014-04-24 13:29:34 +0000101 InstrumentMOV(Inst, Operands, Ctx, MII, Out);
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000102
103 RepPrefix = (Inst.getOpcode() == X86::REP_PREFIX);
Evgeniy Stepanov50505532014-08-27 13:11:55 +0000104 if (!RepPrefix)
105 EmitInstruction(Out, Inst);
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000106 }
107
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000108 // Adjusts up stack and saves all registers used in instrumentation.
109 virtual void InstrumentMemOperandPrologue(const RegisterContext &RegCtx,
110 MCContext &Ctx,
111 MCStreamer &Out) = 0;
112
113 // Restores all registers used in instrumentation and adjusts stack.
114 virtual void InstrumentMemOperandEpilogue(const RegisterContext &RegCtx,
115 MCContext &Ctx,
116 MCStreamer &Out) = 0;
117
118 virtual void InstrumentMemOperandSmall(X86Operand &Op, unsigned AccessSize,
119 bool IsWrite,
120 const RegisterContext &RegCtx,
121 MCContext &Ctx, MCStreamer &Out) = 0;
122 virtual void InstrumentMemOperandLarge(X86Operand &Op, unsigned AccessSize,
123 bool IsWrite,
124 const RegisterContext &RegCtx,
125 MCContext &Ctx, MCStreamer &Out) = 0;
126
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000127 virtual void InstrumentMOVSImpl(unsigned AccessSize, MCContext &Ctx,
128 MCStreamer &Out) = 0;
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000129
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000130 void InstrumentMemOperand(X86Operand &Op, unsigned AccessSize, bool IsWrite,
131 const RegisterContext &RegCtx, MCContext &Ctx,
132 MCStreamer &Out);
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000133 void InstrumentMOVSBase(unsigned DstReg, unsigned SrcReg, unsigned CntReg,
134 unsigned AccessSize, MCContext &Ctx, MCStreamer &Out);
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000135
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000136 void InstrumentMOVS(const MCInst &Inst, OperandVector &Operands,
137 MCContext &Ctx, const MCInstrInfo &MII, MCStreamer &Out);
David Blaikie960ea3f2014-06-08 16:18:35 +0000138 void InstrumentMOV(const MCInst &Inst, OperandVector &Operands,
Evgeniy Stepanovf4a36992014-04-24 13:29:34 +0000139 MCContext &Ctx, const MCInstrInfo &MII, MCStreamer &Out);
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000140
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000141protected:
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000142 void EmitLabel(MCStreamer &Out, MCSymbol *Label) { Out.EmitLabel(Label); }
143
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000144 void EmitLEA(X86Operand &Op, MVT::SimpleValueType VT, unsigned Reg,
145 MCStreamer &Out) {
146 assert(VT == MVT::i32 || VT == MVT::i64);
147 MCInst Inst;
148 Inst.setOpcode(VT == MVT::i32 ? X86::LEA32r : X86::LEA64r);
149 Inst.addOperand(MCOperand::CreateReg(getX86SubSuperRegister(Reg, VT)));
150 Op.addMemOperands(Inst, 5);
151 EmitInstruction(Out, Inst);
152 }
153
154 void ComputeMemOperandAddress(X86Operand &Op, MVT::SimpleValueType VT,
155 unsigned Reg, MCContext &Ctx, MCStreamer &Out);
156
157 // Creates new memory operand with Displacement added to an original
158 // displacement. Residue will contain a residue which could happen when the
159 // total displacement exceeds 32-bit limitation.
160 std::unique_ptr<X86Operand> AddDisplacement(X86Operand &Op,
161 int64_t Displacement,
162 MCContext &Ctx, int64_t *Residue);
163
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000164 // True when previous instruction was actually REP prefix.
165 bool RepPrefix;
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000166
167 // Offset from the original SP register.
168 int64_t OrigSPOffset;
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000169};
170
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000171void X86AddressSanitizer::InstrumentMemOperand(
172 X86Operand &Op, unsigned AccessSize, bool IsWrite,
173 const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) {
David Blaikie960ea3f2014-06-08 16:18:35 +0000174 assert(Op.isMem() && "Op should be a memory operand.");
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000175 assert((AccessSize & (AccessSize - 1)) == 0 && AccessSize <= 16 &&
176 "AccessSize should be a power of two, less or equal than 16.");
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000177 // FIXME: take into account load/store alignment.
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000178 if (IsSmallMemAccess(AccessSize))
179 InstrumentMemOperandSmall(Op, AccessSize, IsWrite, RegCtx, Ctx, Out);
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000180 else
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000181 InstrumentMemOperandLarge(Op, AccessSize, IsWrite, RegCtx, Ctx, Out);
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000182}
183
Evgeniy Stepanov4d04f662014-08-27 11:10:54 +0000184void X86AddressSanitizer::InstrumentMOVSBase(unsigned DstReg, unsigned SrcReg,
185 unsigned CntReg,
186 unsigned AccessSize,
187 MCContext &Ctx, MCStreamer &Out) {
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000188 // FIXME: check whole ranges [DstReg .. DstReg + AccessSize * (CntReg - 1)]
189 // and [SrcReg .. SrcReg + AccessSize * (CntReg - 1)].
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000190 RegisterContext RegCtx(X86::RDX /* AddressReg */, X86::RAX /* ShadowReg */,
191 IsSmallMemAccess(AccessSize)
192 ? X86::RBX
193 : X86::NoRegister /* ScratchReg */);
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000194
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000195 InstrumentMemOperandPrologue(RegCtx, Ctx, Out);
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000196
197 // Test (%SrcReg)
198 {
199 const MCExpr *Disp = MCConstantExpr::Create(0, Ctx);
200 std::unique_ptr<X86Operand> Op(X86Operand::CreateMem(
201 0, Disp, SrcReg, 0, AccessSize, SMLoc(), SMLoc()));
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000202 InstrumentMemOperand(*Op, AccessSize, false /* IsWrite */, RegCtx, Ctx,
203 Out);
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000204 }
205
206 // Test -1(%SrcReg, %CntReg, AccessSize)
207 {
208 const MCExpr *Disp = MCConstantExpr::Create(-1, Ctx);
209 std::unique_ptr<X86Operand> Op(X86Operand::CreateMem(
210 0, Disp, SrcReg, CntReg, AccessSize, SMLoc(), SMLoc()));
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000211 InstrumentMemOperand(*Op, AccessSize, false /* IsWrite */, RegCtx, Ctx,
212 Out);
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000213 }
214
215 // Test (%DstReg)
216 {
217 const MCExpr *Disp = MCConstantExpr::Create(0, Ctx);
218 std::unique_ptr<X86Operand> Op(X86Operand::CreateMem(
219 0, Disp, DstReg, 0, AccessSize, SMLoc(), SMLoc()));
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000220 InstrumentMemOperand(*Op, AccessSize, true /* IsWrite */, RegCtx, Ctx, Out);
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000221 }
222
223 // Test -1(%DstReg, %CntReg, AccessSize)
224 {
225 const MCExpr *Disp = MCConstantExpr::Create(-1, Ctx);
226 std::unique_ptr<X86Operand> Op(X86Operand::CreateMem(
227 0, Disp, DstReg, CntReg, AccessSize, SMLoc(), SMLoc()));
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000228 InstrumentMemOperand(*Op, AccessSize, true /* IsWrite */, RegCtx, Ctx, Out);
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000229 }
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000230
231 InstrumentMemOperandEpilogue(RegCtx, Ctx, Out);
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000232}
233
Evgeniy Stepanov4d04f662014-08-27 11:10:54 +0000234void X86AddressSanitizer::InstrumentMOVS(const MCInst &Inst,
235 OperandVector &Operands,
236 MCContext &Ctx, const MCInstrInfo &MII,
237 MCStreamer &Out) {
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000238 // Access size in bytes.
239 unsigned AccessSize = 0;
240
241 switch (Inst.getOpcode()) {
Evgeniy Stepanov50505532014-08-27 13:11:55 +0000242 case X86::MOVSB:
243 AccessSize = 1;
244 break;
245 case X86::MOVSW:
246 AccessSize = 2;
247 break;
248 case X86::MOVSL:
249 AccessSize = 4;
250 break;
251 case X86::MOVSQ:
252 AccessSize = 8;
253 break;
254 default:
255 return;
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000256 }
257
258 InstrumentMOVSImpl(AccessSize, Ctx, Out);
259}
260
Evgeniy Stepanov4d04f662014-08-27 11:10:54 +0000261void X86AddressSanitizer::InstrumentMOV(const MCInst &Inst,
262 OperandVector &Operands, MCContext &Ctx,
263 const MCInstrInfo &MII,
264 MCStreamer &Out) {
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000265 // Access size in bytes.
266 unsigned AccessSize = 0;
Evgeniy Stepanovb6c47a52014-04-24 09:56:15 +0000267
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000268 switch (Inst.getOpcode()) {
Evgeniy Stepanov50505532014-08-27 13:11:55 +0000269 case X86::MOV8mi:
270 case X86::MOV8mr:
271 case X86::MOV8rm:
272 AccessSize = 1;
273 break;
274 case X86::MOV16mi:
275 case X86::MOV16mr:
276 case X86::MOV16rm:
277 AccessSize = 2;
278 break;
279 case X86::MOV32mi:
280 case X86::MOV32mr:
281 case X86::MOV32rm:
282 AccessSize = 4;
283 break;
284 case X86::MOV64mi32:
285 case X86::MOV64mr:
286 case X86::MOV64rm:
287 AccessSize = 8;
288 break;
289 case X86::MOVAPDmr:
290 case X86::MOVAPSmr:
291 case X86::MOVAPDrm:
292 case X86::MOVAPSrm:
293 AccessSize = 16;
294 break;
295 default:
296 return;
Evgeniy Stepanovb6c47a52014-04-24 09:56:15 +0000297 }
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000298
Evgeniy Stepanovf4a36992014-04-24 13:29:34 +0000299 const bool IsWrite = MII.get(Inst.getOpcode()).mayStore();
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000300 RegisterContext RegCtx(X86::RDI /* AddressReg */, X86::RAX /* ShadowReg */,
301 IsSmallMemAccess(AccessSize)
302 ? X86::RCX
303 : X86::NoRegister /* ScratchReg */);
304
Evgeniy Stepanovb6c47a52014-04-24 09:56:15 +0000305 for (unsigned Ix = 0; Ix < Operands.size(); ++Ix) {
David Blaikie960ea3f2014-06-08 16:18:35 +0000306 assert(Operands[Ix]);
307 MCParsedAsmOperand &Op = *Operands[Ix];
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000308 if (Op.isMem()) {
309 X86Operand &MemOp = static_cast<X86Operand &>(Op);
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000310 InstrumentMemOperandPrologue(RegCtx, Ctx, Out);
311 InstrumentMemOperand(MemOp, AccessSize, IsWrite, RegCtx, Ctx, Out);
312 InstrumentMemOperandEpilogue(RegCtx, Ctx, Out);
313 }
Evgeniy Stepanovb6c47a52014-04-24 09:56:15 +0000314 }
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000315}
316
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000317void X86AddressSanitizer::ComputeMemOperandAddress(X86Operand &Op,
318 MVT::SimpleValueType VT,
319 unsigned Reg, MCContext &Ctx,
320 MCStreamer &Out) {
321 int64_t Displacement = 0;
322 if (IsStackReg(Op.getMemBaseReg()))
323 Displacement -= OrigSPOffset;
324 if (IsStackReg(Op.getMemIndexReg()))
325 Displacement -= OrigSPOffset * Op.getMemScale();
326
327 assert(Displacement >= 0);
328
329 // Emit Op as is.
330 if (Displacement == 0) {
331 EmitLEA(Op, VT, Reg, Out);
332 return;
333 }
334
335 int64_t Residue;
336 std::unique_ptr<X86Operand> NewOp =
337 AddDisplacement(Op, Displacement, Ctx, &Residue);
338 EmitLEA(*NewOp, VT, Reg, Out);
339
340 while (Residue != 0) {
341 const MCConstantExpr *Disp =
342 MCConstantExpr::Create(ApplyBounds(Residue), Ctx);
343 std::unique_ptr<X86Operand> DispOp =
344 X86Operand::CreateMem(0, Disp, Reg, 0, 1, SMLoc(), SMLoc());
345 EmitLEA(*DispOp, VT, Reg, Out);
346 Residue -= Disp->getValue();
347 }
348}
349
350std::unique_ptr<X86Operand>
351X86AddressSanitizer::AddDisplacement(X86Operand &Op, int64_t Displacement,
352 MCContext &Ctx, int64_t *Residue) {
353 assert(Displacement >= 0);
354
355 if (Displacement == 0 ||
356 (Op.getMemDisp() && Op.getMemDisp()->getKind() != MCExpr::Constant)) {
357 *Residue = Displacement;
358 return X86Operand::CreateMem(Op.getMemSegReg(), Op.getMemDisp(),
359 Op.getMemBaseReg(), Op.getMemIndexReg(),
360 Op.getMemScale(), SMLoc(), SMLoc());
361 }
362
363 int64_t OrigDisplacement =
364 static_cast<const MCConstantExpr *>(Op.getMemDisp())->getValue();
365 assert(InBounds(OrigDisplacement));
366 Displacement += OrigDisplacement;
367
368 int64_t NewDisplacement = ApplyBounds(Displacement);
369 assert(InBounds(NewDisplacement));
370
371 *Residue = Displacement - NewDisplacement;
372 const MCExpr *Disp = MCConstantExpr::Create(NewDisplacement, Ctx);
373 return X86Operand::CreateMem(Op.getMemSegReg(), Disp, Op.getMemBaseReg(),
374 Op.getMemIndexReg(), Op.getMemScale(), SMLoc(),
375 SMLoc());
376}
377
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000378class X86AddressSanitizer32 : public X86AddressSanitizer {
Evgeniy Stepanov50505532014-08-27 13:11:55 +0000379public:
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000380 static const long kShadowOffset = 0x20000000;
381
Evgeniy Stepanov0a951b72014-04-23 11:16:03 +0000382 X86AddressSanitizer32(const MCSubtargetInfo &STI)
383 : X86AddressSanitizer(STI) {}
Yuri Gorshenin3939dec2014-09-10 09:45:49 +0000384
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000385 virtual ~X86AddressSanitizer32() {}
386
Yuri Gorshenine8c81fd2014-10-07 11:03:09 +0000387 unsigned GetFrameReg(const MCContext &Ctx, MCStreamer &Out) {
388 unsigned FrameReg = GetFrameRegGeneric(Ctx, Out);
389 if (FrameReg == X86::NoRegister)
390 return FrameReg;
391 return getX86SubSuperRegister(FrameReg, MVT::i32);
392 }
393
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000394 void SpillReg(MCStreamer &Out, unsigned Reg) {
395 EmitInstruction(Out, MCInstBuilder(X86::PUSH32r).addReg(Reg));
396 OrigSPOffset -= 4;
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000397 }
398
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000399 void RestoreReg(MCStreamer &Out, unsigned Reg) {
400 EmitInstruction(Out, MCInstBuilder(X86::POP32r).addReg(Reg));
401 OrigSPOffset += 4;
402 }
403
404 void StoreFlags(MCStreamer &Out) {
405 EmitInstruction(Out, MCInstBuilder(X86::PUSHF32));
406 OrigSPOffset -= 4;
407 }
408
409 void RestoreFlags(MCStreamer &Out) {
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000410 EmitInstruction(Out, MCInstBuilder(X86::POPF32));
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000411 OrigSPOffset += 4;
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000412 }
413
414 virtual void InstrumentMemOperandPrologue(const RegisterContext &RegCtx,
415 MCContext &Ctx,
416 MCStreamer &Out) override {
Yuri Gorshenine8c81fd2014-10-07 11:03:09 +0000417 const MCRegisterInfo *MRI = Ctx.getRegisterInfo();
418 unsigned FrameReg = GetFrameReg(Ctx, Out);
Yuri Gorshenin3939dec2014-09-10 09:45:49 +0000419 if (MRI && FrameReg != X86::NoRegister) {
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000420 SpillReg(Out, X86::EBP);
Yuri Gorshenin3939dec2014-09-10 09:45:49 +0000421 if (FrameReg == X86::ESP) {
422 Out.EmitCFIAdjustCfaOffset(4 /* byte size of the FrameReg */);
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000423 Out.EmitCFIRelOffset(MRI->getDwarfRegNum(X86::EBP, true /* IsEH */), 0);
Yuri Gorshenin3939dec2014-09-10 09:45:49 +0000424 }
425 EmitInstruction(
426 Out, MCInstBuilder(X86::MOV32rr).addReg(X86::EBP).addReg(FrameReg));
427 Out.EmitCFIRememberState();
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000428 Out.EmitCFIDefCfaRegister(MRI->getDwarfRegNum(X86::EBP, true /* IsEH */));
Yuri Gorshenin3939dec2014-09-10 09:45:49 +0000429 }
430
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000431 SpillReg(Out, RegCtx.addressReg(MVT::i32));
432 SpillReg(Out, RegCtx.shadowReg(MVT::i32));
433 if (RegCtx.ScratchReg != X86::NoRegister)
434 SpillReg(Out, RegCtx.scratchReg(MVT::i32));
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000435 StoreFlags(Out);
436 }
437
438 virtual void InstrumentMemOperandEpilogue(const RegisterContext &RegCtx,
439 MCContext &Ctx,
440 MCStreamer &Out) override {
441 RestoreFlags(Out);
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000442 if (RegCtx.ScratchReg != X86::NoRegister)
443 RestoreReg(Out, RegCtx.scratchReg(MVT::i32));
444 RestoreReg(Out, RegCtx.shadowReg(MVT::i32));
445 RestoreReg(Out, RegCtx.addressReg(MVT::i32));
Yuri Gorshenin3939dec2014-09-10 09:45:49 +0000446
Yuri Gorshenine8c81fd2014-10-07 11:03:09 +0000447 unsigned FrameReg = GetFrameReg(Ctx, Out);
Yuri Gorshenin3939dec2014-09-10 09:45:49 +0000448 if (Ctx.getRegisterInfo() && FrameReg != X86::NoRegister) {
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000449 RestoreReg(Out, X86::EBP);
Yuri Gorshenin3939dec2014-09-10 09:45:49 +0000450 Out.EmitCFIRestoreState();
451 if (FrameReg == X86::ESP)
452 Out.EmitCFIAdjustCfaOffset(-4 /* byte size of the FrameReg */);
453 }
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000454 }
455
456 virtual void InstrumentMemOperandSmall(X86Operand &Op, unsigned AccessSize,
457 bool IsWrite,
458 const RegisterContext &RegCtx,
459 MCContext &Ctx,
460 MCStreamer &Out) override;
461 virtual void InstrumentMemOperandLarge(X86Operand &Op, unsigned AccessSize,
462 bool IsWrite,
463 const RegisterContext &RegCtx,
464 MCContext &Ctx,
465 MCStreamer &Out) override;
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000466 virtual void InstrumentMOVSImpl(unsigned AccessSize, MCContext &Ctx,
467 MCStreamer &Out) override;
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000468
Evgeniy Stepanov50505532014-08-27 13:11:55 +0000469private:
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000470 void EmitCallAsanReport(unsigned AccessSize, bool IsWrite, MCContext &Ctx,
471 MCStreamer &Out, const RegisterContext &RegCtx) {
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000472 EmitInstruction(Out, MCInstBuilder(X86::CLD));
473 EmitInstruction(Out, MCInstBuilder(X86::MMX_EMMS));
474
Evgeniy Stepanov4d04f662014-08-27 11:10:54 +0000475 EmitInstruction(Out, MCInstBuilder(X86::AND64ri8)
476 .addReg(X86::ESP)
477 .addReg(X86::ESP)
478 .addImm(-16));
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000479 EmitInstruction(
480 Out, MCInstBuilder(X86::PUSH32r).addReg(RegCtx.addressReg(MVT::i32)));
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000481
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000482 const std::string &Fn = FuncName(AccessSize, IsWrite);
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000483 MCSymbol *FnSym = Ctx.GetOrCreateSymbol(StringRef(Fn));
484 const MCSymbolRefExpr *FnExpr =
485 MCSymbolRefExpr::Create(FnSym, MCSymbolRefExpr::VK_PLT, Ctx);
486 EmitInstruction(Out, MCInstBuilder(X86::CALLpcrel32).addExpr(FnExpr));
487 }
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000488};
489
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000490void X86AddressSanitizer32::InstrumentMemOperandSmall(
491 X86Operand &Op, unsigned AccessSize, bool IsWrite,
492 const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) {
493 unsigned AddressRegI32 = RegCtx.addressReg(MVT::i32);
494 unsigned ShadowRegI32 = RegCtx.shadowReg(MVT::i32);
495 unsigned ShadowRegI8 = RegCtx.shadowReg(MVT::i8);
496
497 assert(RegCtx.ScratchReg != X86::NoRegister);
498 unsigned ScratchRegI32 = RegCtx.scratchReg(MVT::i32);
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000499
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000500 ComputeMemOperandAddress(Op, MVT::i32, AddressRegI32, Ctx, Out);
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000501
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000502 EmitInstruction(Out, MCInstBuilder(X86::MOV32rr).addReg(ShadowRegI32).addReg(
503 AddressRegI32));
504 EmitInstruction(Out, MCInstBuilder(X86::SHR32ri)
505 .addReg(ShadowRegI32)
506 .addReg(ShadowRegI32)
507 .addImm(3));
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000508
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000509 {
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000510 MCInst Inst;
511 Inst.setOpcode(X86::MOV8rm);
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000512 Inst.addOperand(MCOperand::CreateReg(ShadowRegI8));
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000513 const MCExpr *Disp = MCConstantExpr::Create(kShadowOffset, Ctx);
514 std::unique_ptr<X86Operand> Op(
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000515 X86Operand::CreateMem(0, Disp, ShadowRegI32, 0, 1, SMLoc(), SMLoc()));
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000516 Op->addMemOperands(Inst, 5);
517 EmitInstruction(Out, Inst);
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000518 }
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000519
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000520 EmitInstruction(
521 Out, MCInstBuilder(X86::TEST8rr).addReg(ShadowRegI8).addReg(ShadowRegI8));
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000522 MCSymbol *DoneSym = Ctx.CreateTempSymbol();
523 const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx);
524 EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr));
525
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000526 EmitInstruction(Out, MCInstBuilder(X86::MOV32rr).addReg(ScratchRegI32).addReg(
527 AddressRegI32));
528 EmitInstruction(Out, MCInstBuilder(X86::AND32ri)
529 .addReg(ScratchRegI32)
530 .addReg(ScratchRegI32)
531 .addImm(7));
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000532
533 switch (AccessSize) {
Evgeniy Stepanov50505532014-08-27 13:11:55 +0000534 case 1:
535 break;
536 case 2: {
Evgeniy Stepanov50505532014-08-27 13:11:55 +0000537 const MCExpr *Disp = MCConstantExpr::Create(1, Ctx);
538 std::unique_ptr<X86Operand> Op(
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000539 X86Operand::CreateMem(0, Disp, ScratchRegI32, 0, 1, SMLoc(), SMLoc()));
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000540 EmitLEA(*Op, MVT::i32, ScratchRegI32, Out);
Evgeniy Stepanov50505532014-08-27 13:11:55 +0000541 break;
542 }
543 case 4:
544 EmitInstruction(Out, MCInstBuilder(X86::ADD32ri8)
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000545 .addReg(ScratchRegI32)
546 .addReg(ScratchRegI32)
Evgeniy Stepanov50505532014-08-27 13:11:55 +0000547 .addImm(3));
548 break;
549 default:
550 assert(false && "Incorrect access size");
551 break;
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000552 }
553
554 EmitInstruction(
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000555 Out,
556 MCInstBuilder(X86::MOVSX32rr8).addReg(ShadowRegI32).addReg(ShadowRegI8));
557 EmitInstruction(Out, MCInstBuilder(X86::CMP32rr).addReg(ScratchRegI32).addReg(
558 ShadowRegI32));
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000559 EmitInstruction(Out, MCInstBuilder(X86::JL_4).addExpr(DoneExpr));
560
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000561 EmitCallAsanReport(AccessSize, IsWrite, Ctx, Out, RegCtx);
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000562 EmitLabel(Out, DoneSym);
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000563}
564
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000565void X86AddressSanitizer32::InstrumentMemOperandLarge(
566 X86Operand &Op, unsigned AccessSize, bool IsWrite,
567 const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) {
568 unsigned AddressRegI32 = RegCtx.addressReg(MVT::i32);
569 unsigned ShadowRegI32 = RegCtx.shadowReg(MVT::i32);
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000570
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000571 ComputeMemOperandAddress(Op, MVT::i32, AddressRegI32, Ctx, Out);
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000572
573 EmitInstruction(Out, MCInstBuilder(X86::MOV32rr).addReg(ShadowRegI32).addReg(
574 AddressRegI32));
575 EmitInstruction(Out, MCInstBuilder(X86::SHR32ri)
576 .addReg(ShadowRegI32)
577 .addReg(ShadowRegI32)
578 .addImm(3));
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000579 {
580 MCInst Inst;
581 switch (AccessSize) {
Evgeniy Stepanov50505532014-08-27 13:11:55 +0000582 case 8:
583 Inst.setOpcode(X86::CMP8mi);
584 break;
585 case 16:
586 Inst.setOpcode(X86::CMP16mi);
587 break;
588 default:
589 assert(false && "Incorrect access size");
590 break;
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000591 }
592 const MCExpr *Disp = MCConstantExpr::Create(kShadowOffset, Ctx);
593 std::unique_ptr<X86Operand> Op(
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000594 X86Operand::CreateMem(0, Disp, ShadowRegI32, 0, 1, SMLoc(), SMLoc()));
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000595 Op->addMemOperands(Inst, 5);
596 Inst.addOperand(MCOperand::CreateImm(0));
597 EmitInstruction(Out, Inst);
598 }
599 MCSymbol *DoneSym = Ctx.CreateTempSymbol();
600 const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx);
601 EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr));
602
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000603 EmitCallAsanReport(AccessSize, IsWrite, Ctx, Out, RegCtx);
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000604 EmitLabel(Out, DoneSym);
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000605}
606
Evgeniy Stepanov4d04f662014-08-27 11:10:54 +0000607void X86AddressSanitizer32::InstrumentMOVSImpl(unsigned AccessSize,
608 MCContext &Ctx,
609 MCStreamer &Out) {
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000610 StoreFlags(Out);
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000611
612 // No need to test when ECX is equals to zero.
613 MCSymbol *DoneSym = Ctx.CreateTempSymbol();
614 const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx);
615 EmitInstruction(
616 Out, MCInstBuilder(X86::TEST32rr).addReg(X86::ECX).addReg(X86::ECX));
617 EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr));
618
619 // Instrument first and last elements in src and dst range.
620 InstrumentMOVSBase(X86::EDI /* DstReg */, X86::ESI /* SrcReg */,
621 X86::ECX /* CntReg */, AccessSize, Ctx, Out);
622
623 EmitLabel(Out, DoneSym);
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000624 RestoreFlags(Out);
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000625}
626
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000627class X86AddressSanitizer64 : public X86AddressSanitizer {
Evgeniy Stepanov50505532014-08-27 13:11:55 +0000628public:
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000629 static const long kShadowOffset = 0x7fff8000;
630
Evgeniy Stepanov0a951b72014-04-23 11:16:03 +0000631 X86AddressSanitizer64(const MCSubtargetInfo &STI)
632 : X86AddressSanitizer(STI) {}
Yuri Gorshenin3939dec2014-09-10 09:45:49 +0000633
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000634 virtual ~X86AddressSanitizer64() {}
635
Yuri Gorshenine8c81fd2014-10-07 11:03:09 +0000636 unsigned GetFrameReg(const MCContext &Ctx, MCStreamer &Out) {
637 unsigned FrameReg = GetFrameRegGeneric(Ctx, Out);
638 if (FrameReg == X86::NoRegister)
639 return FrameReg;
640 return getX86SubSuperRegister(FrameReg, MVT::i64);
641 }
642
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000643 void SpillReg(MCStreamer &Out, unsigned Reg) {
644 EmitInstruction(Out, MCInstBuilder(X86::PUSH64r).addReg(Reg));
645 OrigSPOffset -= 8;
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000646 }
647
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000648 void RestoreReg(MCStreamer &Out, unsigned Reg) {
649 EmitInstruction(Out, MCInstBuilder(X86::POP64r).addReg(Reg));
650 OrigSPOffset += 8;
651 }
652
653 void StoreFlags(MCStreamer &Out) {
654 EmitInstruction(Out, MCInstBuilder(X86::PUSHF64));
655 OrigSPOffset -= 8;
656 }
657
658 void RestoreFlags(MCStreamer &Out) {
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000659 EmitInstruction(Out, MCInstBuilder(X86::POPF64));
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000660 OrigSPOffset += 8;
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000661 }
662
663 virtual void InstrumentMemOperandPrologue(const RegisterContext &RegCtx,
664 MCContext &Ctx,
665 MCStreamer &Out) override {
Yuri Gorshenine8c81fd2014-10-07 11:03:09 +0000666 const MCRegisterInfo *MRI = Ctx.getRegisterInfo();
667 unsigned FrameReg = GetFrameReg(Ctx, Out);
668 if (MRI && FrameReg != X86::NoRegister) {
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000669 SpillReg(Out, X86::RBP);
Yuri Gorshenin3939dec2014-09-10 09:45:49 +0000670 if (FrameReg == X86::RSP) {
671 Out.EmitCFIAdjustCfaOffset(8 /* byte size of the FrameReg */);
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000672 Out.EmitCFIRelOffset(MRI->getDwarfRegNum(X86::RBP, true /* IsEH */), 0);
Yuri Gorshenin3939dec2014-09-10 09:45:49 +0000673 }
674 EmitInstruction(
675 Out, MCInstBuilder(X86::MOV64rr).addReg(X86::RBP).addReg(FrameReg));
676 Out.EmitCFIRememberState();
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000677 Out.EmitCFIDefCfaRegister(MRI->getDwarfRegNum(X86::RBP, true /* IsEH */));
Yuri Gorshenin3939dec2014-09-10 09:45:49 +0000678 }
679
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000680 EmitAdjustRSP(Ctx, Out, -128);
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000681 SpillReg(Out, RegCtx.shadowReg(MVT::i64));
682 SpillReg(Out, RegCtx.addressReg(MVT::i64));
683 if (RegCtx.ScratchReg != X86::NoRegister)
684 SpillReg(Out, RegCtx.scratchReg(MVT::i64));
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000685 StoreFlags(Out);
686 }
687
688 virtual void InstrumentMemOperandEpilogue(const RegisterContext &RegCtx,
689 MCContext &Ctx,
690 MCStreamer &Out) override {
691 RestoreFlags(Out);
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000692 if (RegCtx.ScratchReg != X86::NoRegister)
693 RestoreReg(Out, RegCtx.scratchReg(MVT::i64));
694 RestoreReg(Out, RegCtx.addressReg(MVT::i64));
695 RestoreReg(Out, RegCtx.shadowReg(MVT::i64));
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000696 EmitAdjustRSP(Ctx, Out, 128);
Yuri Gorshenin3939dec2014-09-10 09:45:49 +0000697
Yuri Gorshenine8c81fd2014-10-07 11:03:09 +0000698 unsigned FrameReg = GetFrameReg(Ctx, Out);
Yuri Gorshenin3939dec2014-09-10 09:45:49 +0000699 if (Ctx.getRegisterInfo() && FrameReg != X86::NoRegister) {
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000700 RestoreReg(Out, X86::RBP);
Yuri Gorshenin3939dec2014-09-10 09:45:49 +0000701 Out.EmitCFIRestoreState();
702 if (FrameReg == X86::RSP)
703 Out.EmitCFIAdjustCfaOffset(-8 /* byte size of the FrameReg */);
704 }
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000705 }
706
707 virtual void InstrumentMemOperandSmall(X86Operand &Op, unsigned AccessSize,
708 bool IsWrite,
709 const RegisterContext &RegCtx,
710 MCContext &Ctx,
711 MCStreamer &Out) override;
712 virtual void InstrumentMemOperandLarge(X86Operand &Op, unsigned AccessSize,
713 bool IsWrite,
714 const RegisterContext &RegCtx,
715 MCContext &Ctx,
716 MCStreamer &Out) override;
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000717 virtual void InstrumentMOVSImpl(unsigned AccessSize, MCContext &Ctx,
718 MCStreamer &Out) override;
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000719
Evgeniy Stepanov50505532014-08-27 13:11:55 +0000720private:
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000721 void EmitAdjustRSP(MCContext &Ctx, MCStreamer &Out, long Offset) {
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000722 const MCExpr *Disp = MCConstantExpr::Create(Offset, Ctx);
Benjamin Kramer8bbadc02014-05-09 09:48:03 +0000723 std::unique_ptr<X86Operand> Op(
724 X86Operand::CreateMem(0, Disp, X86::RSP, 0, 1, SMLoc(), SMLoc()));
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000725 EmitLEA(*Op, MVT::i64, X86::RSP, Out);
726 OrigSPOffset += Offset;
Evgeniy Stepanov9661ec02014-05-08 09:55:24 +0000727 }
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000728
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000729 void EmitCallAsanReport(unsigned AccessSize, bool IsWrite, MCContext &Ctx,
730 MCStreamer &Out, const RegisterContext &RegCtx) {
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000731 EmitInstruction(Out, MCInstBuilder(X86::CLD));
732 EmitInstruction(Out, MCInstBuilder(X86::MMX_EMMS));
733
Evgeniy Stepanov4d04f662014-08-27 11:10:54 +0000734 EmitInstruction(Out, MCInstBuilder(X86::AND64ri8)
735 .addReg(X86::RSP)
736 .addReg(X86::RSP)
737 .addImm(-16));
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000738
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000739 if (RegCtx.AddressReg != X86::RDI) {
740 EmitInstruction(Out, MCInstBuilder(X86::MOV64rr).addReg(X86::RDI).addReg(
741 RegCtx.addressReg(MVT::i64)));
742 }
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000743 const std::string &Fn = FuncName(AccessSize, IsWrite);
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000744 MCSymbol *FnSym = Ctx.GetOrCreateSymbol(StringRef(Fn));
745 const MCSymbolRefExpr *FnExpr =
746 MCSymbolRefExpr::Create(FnSym, MCSymbolRefExpr::VK_PLT, Ctx);
747 EmitInstruction(Out, MCInstBuilder(X86::CALL64pcrel32).addExpr(FnExpr));
748 }
749};
750
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000751void X86AddressSanitizer64::InstrumentMemOperandSmall(
752 X86Operand &Op, unsigned AccessSize, bool IsWrite,
753 const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) {
754 unsigned AddressRegI64 = RegCtx.addressReg(MVT::i64);
755 unsigned AddressRegI32 = RegCtx.addressReg(MVT::i32);
756 unsigned ShadowRegI64 = RegCtx.shadowReg(MVT::i64);
757 unsigned ShadowRegI32 = RegCtx.shadowReg(MVT::i32);
758 unsigned ShadowRegI8 = RegCtx.shadowReg(MVT::i8);
759
760 assert(RegCtx.ScratchReg != X86::NoRegister);
761 unsigned ScratchRegI32 = RegCtx.scratchReg(MVT::i32);
762
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000763 ComputeMemOperandAddress(Op, MVT::i64, AddressRegI64, Ctx, Out);
764
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000765 EmitInstruction(Out, MCInstBuilder(X86::MOV64rr).addReg(ShadowRegI64).addReg(
766 AddressRegI64));
767 EmitInstruction(Out, MCInstBuilder(X86::SHR64ri)
768 .addReg(ShadowRegI64)
769 .addReg(ShadowRegI64)
770 .addImm(3));
Evgeniy Stepanov9661ec02014-05-08 09:55:24 +0000771 {
772 MCInst Inst;
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000773 Inst.setOpcode(X86::MOV8rm);
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000774 Inst.addOperand(MCOperand::CreateReg(ShadowRegI8));
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000775 const MCExpr *Disp = MCConstantExpr::Create(kShadowOffset, Ctx);
Benjamin Kramer8bbadc02014-05-09 09:48:03 +0000776 std::unique_ptr<X86Operand> Op(
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000777 X86Operand::CreateMem(0, Disp, ShadowRegI64, 0, 1, SMLoc(), SMLoc()));
Evgeniy Stepanov9661ec02014-05-08 09:55:24 +0000778 Op->addMemOperands(Inst, 5);
779 EmitInstruction(Out, Inst);
780 }
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000781
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000782 EmitInstruction(
783 Out, MCInstBuilder(X86::TEST8rr).addReg(ShadowRegI8).addReg(ShadowRegI8));
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000784 MCSymbol *DoneSym = Ctx.CreateTempSymbol();
785 const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx);
786 EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr));
787
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000788 EmitInstruction(Out, MCInstBuilder(X86::MOV32rr).addReg(ScratchRegI32).addReg(
789 AddressRegI32));
790 EmitInstruction(Out, MCInstBuilder(X86::AND32ri)
791 .addReg(ScratchRegI32)
792 .addReg(ScratchRegI32)
793 .addImm(7));
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000794
795 switch (AccessSize) {
Evgeniy Stepanov50505532014-08-27 13:11:55 +0000796 case 1:
797 break;
798 case 2: {
Evgeniy Stepanov50505532014-08-27 13:11:55 +0000799 const MCExpr *Disp = MCConstantExpr::Create(1, Ctx);
800 std::unique_ptr<X86Operand> Op(
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000801 X86Operand::CreateMem(0, Disp, ScratchRegI32, 0, 1, SMLoc(), SMLoc()));
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000802 EmitLEA(*Op, MVT::i32, ScratchRegI32, Out);
Evgeniy Stepanov50505532014-08-27 13:11:55 +0000803 break;
804 }
805 case 4:
806 EmitInstruction(Out, MCInstBuilder(X86::ADD32ri8)
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000807 .addReg(ScratchRegI32)
808 .addReg(ScratchRegI32)
Evgeniy Stepanov50505532014-08-27 13:11:55 +0000809 .addImm(3));
810 break;
811 default:
812 assert(false && "Incorrect access size");
813 break;
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000814 }
815
816 EmitInstruction(
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000817 Out,
818 MCInstBuilder(X86::MOVSX32rr8).addReg(ShadowRegI32).addReg(ShadowRegI8));
819 EmitInstruction(Out, MCInstBuilder(X86::CMP32rr).addReg(ScratchRegI32).addReg(
820 ShadowRegI32));
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000821 EmitInstruction(Out, MCInstBuilder(X86::JL_4).addExpr(DoneExpr));
822
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000823 EmitCallAsanReport(AccessSize, IsWrite, Ctx, Out, RegCtx);
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000824 EmitLabel(Out, DoneSym);
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000825}
826
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000827void X86AddressSanitizer64::InstrumentMemOperandLarge(
828 X86Operand &Op, unsigned AccessSize, bool IsWrite,
829 const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) {
830 unsigned AddressRegI64 = RegCtx.addressReg(MVT::i64);
831 unsigned ShadowRegI64 = RegCtx.shadowReg(MVT::i64);
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000832
Yuri Gorshenin46853b52014-10-13 09:37:47 +0000833 ComputeMemOperandAddress(Op, MVT::i64, AddressRegI64, Ctx, Out);
834
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000835 EmitInstruction(Out, MCInstBuilder(X86::MOV64rr).addReg(ShadowRegI64).addReg(
836 AddressRegI64));
837 EmitInstruction(Out, MCInstBuilder(X86::SHR64ri)
838 .addReg(ShadowRegI64)
839 .addReg(ShadowRegI64)
840 .addImm(3));
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000841 {
842 MCInst Inst;
843 switch (AccessSize) {
Evgeniy Stepanov50505532014-08-27 13:11:55 +0000844 case 8:
845 Inst.setOpcode(X86::CMP8mi);
846 break;
847 case 16:
848 Inst.setOpcode(X86::CMP16mi);
849 break;
850 default:
851 assert(false && "Incorrect access size");
852 break;
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000853 }
854 const MCExpr *Disp = MCConstantExpr::Create(kShadowOffset, Ctx);
855 std::unique_ptr<X86Operand> Op(
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000856 X86Operand::CreateMem(0, Disp, ShadowRegI64, 0, 1, SMLoc(), SMLoc()));
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000857 Op->addMemOperands(Inst, 5);
858 Inst.addOperand(MCOperand::CreateImm(0));
859 EmitInstruction(Out, Inst);
860 }
861
862 MCSymbol *DoneSym = Ctx.CreateTempSymbol();
863 const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx);
864 EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr));
865
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000866 EmitCallAsanReport(AccessSize, IsWrite, Ctx, Out, RegCtx);
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000867 EmitLabel(Out, DoneSym);
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000868}
869
Evgeniy Stepanov4d04f662014-08-27 11:10:54 +0000870void X86AddressSanitizer64::InstrumentMOVSImpl(unsigned AccessSize,
871 MCContext &Ctx,
872 MCStreamer &Out) {
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000873 StoreFlags(Out);
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000874
875 // No need to test when RCX is equals to zero.
876 MCSymbol *DoneSym = Ctx.CreateTempSymbol();
877 const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx);
878 EmitInstruction(
879 Out, MCInstBuilder(X86::TEST64rr).addReg(X86::RCX).addReg(X86::RCX));
880 EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr));
881
882 // Instrument first and last elements in src and dst range.
883 InstrumentMOVSBase(X86::RDI /* DstReg */, X86::RSI /* SrcReg */,
884 X86::RCX /* CntReg */, AccessSize, Ctx, Out);
885
886 EmitLabel(Out, DoneSym);
Yuri Gorsheninc107d142014-09-01 12:51:00 +0000887 RestoreFlags(Out);
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000888}
889
Evgeniy Stepanov50505532014-08-27 13:11:55 +0000890} // End anonymous namespace
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000891
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000892X86AsmInstrumentation::X86AsmInstrumentation(const MCSubtargetInfo &STI)
Yuri Gorshenine8c81fd2014-10-07 11:03:09 +0000893 : STI(STI), InitialFrameReg(0) {}
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000894
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000895X86AsmInstrumentation::~X86AsmInstrumentation() {}
896
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000897void X86AsmInstrumentation::InstrumentAndEmitInstruction(
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000898 const MCInst &Inst, OperandVector &Operands, MCContext &Ctx,
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000899 const MCInstrInfo &MII, MCStreamer &Out) {
900 EmitInstruction(Out, Inst);
901}
902
903void X86AsmInstrumentation::EmitInstruction(MCStreamer &Out,
904 const MCInst &Inst) {
905 Out.EmitInstruction(Inst, STI);
906}
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000907
Yuri Gorshenine8c81fd2014-10-07 11:03:09 +0000908unsigned X86AsmInstrumentation::GetFrameRegGeneric(const MCContext &Ctx,
909 MCStreamer &Out) {
910 if (!Out.getNumFrameInfos()) // No active dwarf frame
911 return X86::NoRegister;
912 const MCDwarfFrameInfo &Frame = Out.getDwarfFrameInfos().back();
913 if (Frame.End) // Active dwarf frame is closed
914 return X86::NoRegister;
915 const MCRegisterInfo *MRI = Ctx.getRegisterInfo();
916 if (!MRI) // No register info
917 return X86::NoRegister;
918
919 if (InitialFrameReg) {
920 // FrameReg is set explicitly, we're instrumenting a MachineFunction.
921 return InitialFrameReg;
922 }
923
924 return MRI->getLLVMRegNum(Frame.CurrentCfaRegister, true /* IsEH */);
925}
926
Evgeniy Stepanov50505532014-08-27 13:11:55 +0000927X86AsmInstrumentation *
928CreateX86AsmInstrumentation(const MCTargetOptions &MCOptions,
929 const MCContext &Ctx, const MCSubtargetInfo &STI) {
Evgeniy Stepanov29865f72014-04-30 14:04:31 +0000930 Triple T(STI.getTargetTriple());
931 const bool hasCompilerRTSupport = T.isOSLinux();
Evgeniy Stepanov3819f022014-05-07 07:54:11 +0000932 if (ClAsanInstrumentAssembly && hasCompilerRTSupport &&
933 MCOptions.SanitizeAddress) {
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000934 if ((STI.getFeatureBits() & X86::Mode32Bit) != 0)
935 return new X86AddressSanitizer32(STI);
936 if ((STI.getFeatureBits() & X86::Mode64Bit) != 0)
937 return new X86AddressSanitizer64(STI);
938 }
Evgeniy Stepanov77ad8662014-07-31 09:11:04 +0000939 return new X86AsmInstrumentation(STI);
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000940}
941
Evgeniy Stepanov50505532014-08-27 13:11:55 +0000942} // End llvm namespace