blob: a365f62190d2b1a89685a1977f63c7359919a038 [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"
13#include "llvm/ADT/StringExtras.h"
Evgeniy Stepanov29865f72014-04-30 14:04:31 +000014#include "llvm/ADT/Triple.h"
Evgeniy Stepanov0a951b72014-04-23 11:16:03 +000015#include "llvm/IR/Function.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"
Evgeniy Stepanov49e26252014-03-14 08:58:04 +000021#include "llvm/MC/MCStreamer.h"
22#include "llvm/MC/MCSubtargetInfo.h"
David Blaikie960ea3f2014-06-08 16:18:35 +000023#include "llvm/MC/MCTargetAsmParser.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"
Evgeniy Stepanov49e26252014-03-14 08:58:04 +000026
27namespace llvm {
28namespace {
29
Evgeniy Stepanov3819f022014-05-07 07:54:11 +000030static cl::opt<bool> ClAsanInstrumentAssembly(
31 "asan-instrument-assembly",
32 cl::desc("instrument assembly with AddressSanitizer checks"), cl::Hidden,
33 cl::init(false));
34
Evgeniy Stepanov49e26252014-03-14 08:58:04 +000035bool IsStackReg(unsigned Reg) {
36 return Reg == X86::RSP || Reg == X86::ESP || Reg == X86::SP;
37}
38
39std::string FuncName(unsigned AccessSize, bool IsWrite) {
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +000040 return std::string("__asan_report_") + (IsWrite ? "store" : "load") +
41 utostr(AccessSize);
Evgeniy Stepanov49e26252014-03-14 08:58:04 +000042}
43
44class X86AddressSanitizer : public X86AsmInstrumentation {
45public:
Evgeniy Stepanov0a951b72014-04-23 11:16:03 +000046 X86AddressSanitizer(const MCSubtargetInfo &STI) : STI(STI) {}
Evgeniy Stepanov49e26252014-03-14 08:58:04 +000047 virtual ~X86AddressSanitizer() {}
48
49 // X86AsmInstrumentation implementation:
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +000050 virtual void InstrumentInstruction(
51 const MCInst &Inst, OperandVector &Operands, MCContext &Ctx,
52 const MCInstrInfo &MII, MCStreamer &Out) override {
Evgeniy Stepanovf4a36992014-04-24 13:29:34 +000053 InstrumentMOV(Inst, Operands, Ctx, MII, Out);
Evgeniy Stepanov49e26252014-03-14 08:58:04 +000054 }
55
56 // Should be implemented differently in x86_32 and x86_64 subclasses.
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +000057 virtual void InstrumentMemOperandSmallImpl(
58 X86Operand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx,
59 MCStreamer &Out) = 0;
60 virtual void InstrumentMemOperandLargeImpl(
61 X86Operand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx,
62 MCStreamer &Out) = 0;
Evgeniy Stepanov49e26252014-03-14 08:58:04 +000063
David Blaikie960ea3f2014-06-08 16:18:35 +000064 void InstrumentMemOperand(MCParsedAsmOperand &Op, unsigned AccessSize,
Evgeniy Stepanov49e26252014-03-14 08:58:04 +000065 bool IsWrite, MCContext &Ctx, MCStreamer &Out);
David Blaikie960ea3f2014-06-08 16:18:35 +000066 void InstrumentMOV(const MCInst &Inst, OperandVector &Operands,
Evgeniy Stepanovf4a36992014-04-24 13:29:34 +000067 MCContext &Ctx, const MCInstrInfo &MII, MCStreamer &Out);
Evgeniy Stepanov49e26252014-03-14 08:58:04 +000068 void EmitInstruction(MCStreamer &Out, const MCInst &Inst) {
69 Out.EmitInstruction(Inst, STI);
70 }
71
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +000072 void EmitLabel(MCStreamer &Out, MCSymbol *Label) { Out.EmitLabel(Label); }
73
Evgeniy Stepanov49e26252014-03-14 08:58:04 +000074protected:
Evgeniy Stepanov0a951b72014-04-23 11:16:03 +000075 const MCSubtargetInfo &STI;
Evgeniy Stepanov49e26252014-03-14 08:58:04 +000076};
77
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +000078void X86AddressSanitizer::InstrumentMemOperand(
79 MCParsedAsmOperand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx,
80 MCStreamer &Out) {
David Blaikie960ea3f2014-06-08 16:18:35 +000081 assert(Op.isMem() && "Op should be a memory operand.");
Evgeniy Stepanov49e26252014-03-14 08:58:04 +000082 assert((AccessSize & (AccessSize - 1)) == 0 && AccessSize <= 16 &&
83 "AccessSize should be a power of two, less or equal than 16.");
84
David Blaikie960ea3f2014-06-08 16:18:35 +000085 X86Operand &MemOp = static_cast<X86Operand &>(Op);
Evgeniy Stepanov49e26252014-03-14 08:58:04 +000086 // FIXME: get rid of this limitation.
David Blaikie960ea3f2014-06-08 16:18:35 +000087 if (IsStackReg(MemOp.getMemBaseReg()) || IsStackReg(MemOp.getMemIndexReg()))
Evgeniy Stepanov49e26252014-03-14 08:58:04 +000088 return;
89
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +000090 // FIXME: take into account load/store alignment.
91 if (AccessSize < 8)
92 InstrumentMemOperandSmallImpl(MemOp, AccessSize, IsWrite, Ctx, Out);
93 else
94 InstrumentMemOperandLargeImpl(MemOp, AccessSize, IsWrite, Ctx, Out);
Evgeniy Stepanov49e26252014-03-14 08:58:04 +000095}
96
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +000097void X86AddressSanitizer::InstrumentMOV(
98 const MCInst &Inst, OperandVector &Operands, MCContext &Ctx,
99 const MCInstrInfo &MII, MCStreamer &Out) {
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000100 // Access size in bytes.
101 unsigned AccessSize = 0;
Evgeniy Stepanovb6c47a52014-04-24 09:56:15 +0000102
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000103 switch (Inst.getOpcode()) {
104 case X86::MOV8mi:
105 case X86::MOV8mr:
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000106 case X86::MOV8rm:
107 AccessSize = 1;
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000108 break;
109 case X86::MOV16mi:
110 case X86::MOV16mr:
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000111 case X86::MOV16rm:
112 AccessSize = 2;
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000113 break;
114 case X86::MOV32mi:
115 case X86::MOV32mr:
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000116 case X86::MOV32rm:
117 AccessSize = 4;
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000118 break;
119 case X86::MOV64mi32:
120 case X86::MOV64mr:
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000121 case X86::MOV64rm:
122 AccessSize = 8;
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000123 break;
124 case X86::MOVAPDmr:
125 case X86::MOVAPSmr:
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000126 case X86::MOVAPDrm:
127 case X86::MOVAPSrm:
128 AccessSize = 16;
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000129 break;
Evgeniy Stepanovb6c47a52014-04-24 09:56:15 +0000130 default:
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000131 return;
Evgeniy Stepanovb6c47a52014-04-24 09:56:15 +0000132 }
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000133
Evgeniy Stepanovf4a36992014-04-24 13:29:34 +0000134 const bool IsWrite = MII.get(Inst.getOpcode()).mayStore();
Evgeniy Stepanovb6c47a52014-04-24 09:56:15 +0000135 for (unsigned Ix = 0; Ix < Operands.size(); ++Ix) {
David Blaikie960ea3f2014-06-08 16:18:35 +0000136 assert(Operands[Ix]);
137 MCParsedAsmOperand &Op = *Operands[Ix];
138 if (Op.isMem())
Evgeniy Stepanovb6c47a52014-04-24 09:56:15 +0000139 InstrumentMemOperand(Op, AccessSize, IsWrite, Ctx, Out);
140 }
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000141}
142
143class X86AddressSanitizer32 : public X86AddressSanitizer {
144public:
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000145 static const long kShadowOffset = 0x20000000;
146
Evgeniy Stepanov0a951b72014-04-23 11:16:03 +0000147 X86AddressSanitizer32(const MCSubtargetInfo &STI)
148 : X86AddressSanitizer(STI) {}
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000149 virtual ~X86AddressSanitizer32() {}
150
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000151 virtual void InstrumentMemOperandSmallImpl(
152 X86Operand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx,
153 MCStreamer &Out) override;
154 virtual void InstrumentMemOperandLargeImpl(
155 X86Operand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx,
156 MCStreamer &Out) override;
157
158 private:
159 void EmitCallAsanReport(MCContext &Ctx, MCStreamer &Out, unsigned AccessSize,
160 bool IsWrite, unsigned AddressReg) {
161 EmitInstruction(Out, MCInstBuilder(X86::CLD));
162 EmitInstruction(Out, MCInstBuilder(X86::MMX_EMMS));
163
164 EmitInstruction(Out, MCInstBuilder(X86::AND64ri8).addReg(X86::ESP)
165 .addReg(X86::ESP).addImm(-16));
166 EmitInstruction(Out, MCInstBuilder(X86::PUSH32r).addReg(AddressReg));
167
168
169 const std::string& Fn = FuncName(AccessSize, IsWrite);
170 MCSymbol *FnSym = Ctx.GetOrCreateSymbol(StringRef(Fn));
171 const MCSymbolRefExpr *FnExpr =
172 MCSymbolRefExpr::Create(FnSym, MCSymbolRefExpr::VK_PLT, Ctx);
173 EmitInstruction(Out, MCInstBuilder(X86::CALLpcrel32).addExpr(FnExpr));
174 }
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000175};
176
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000177void X86AddressSanitizer32::InstrumentMemOperandSmallImpl(
178 X86Operand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx,
179 MCStreamer &Out) {
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000180 EmitInstruction(Out, MCInstBuilder(X86::PUSH32r).addReg(X86::EAX));
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000181 EmitInstruction(Out, MCInstBuilder(X86::PUSH32r).addReg(X86::ECX));
182 EmitInstruction(Out, MCInstBuilder(X86::PUSH32r).addReg(X86::EDX));
183 EmitInstruction(Out, MCInstBuilder(X86::PUSHF32));
184
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000185 {
186 MCInst Inst;
187 Inst.setOpcode(X86::LEA32r);
188 Inst.addOperand(MCOperand::CreateReg(X86::EAX));
David Blaikie960ea3f2014-06-08 16:18:35 +0000189 Op.addMemOperands(Inst, 5);
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000190 EmitInstruction(Out, Inst);
191 }
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000192
193 EmitInstruction(
194 Out, MCInstBuilder(X86::MOV32rr).addReg(X86::ECX).addReg(X86::EAX));
195 EmitInstruction(Out, MCInstBuilder(X86::SHR32ri).addReg(X86::ECX)
196 .addReg(X86::ECX).addImm(3));
197
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000198 {
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000199 MCInst Inst;
200 Inst.setOpcode(X86::MOV8rm);
201 Inst.addOperand(MCOperand::CreateReg(X86::CL));
202 const MCExpr *Disp = MCConstantExpr::Create(kShadowOffset, Ctx);
203 std::unique_ptr<X86Operand> Op(
204 X86Operand::CreateMem(0, Disp, X86::ECX, 0, 1, SMLoc(), SMLoc()));
205 Op->addMemOperands(Inst, 5);
206 EmitInstruction(Out, Inst);
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000207 }
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000208
209 EmitInstruction(Out,
210 MCInstBuilder(X86::TEST8rr).addReg(X86::CL).addReg(X86::CL));
211 MCSymbol *DoneSym = Ctx.CreateTempSymbol();
212 const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx);
213 EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr));
214
215 EmitInstruction(
216 Out, MCInstBuilder(X86::MOV32rr).addReg(X86::EDX).addReg(X86::EAX));
217 EmitInstruction(Out, MCInstBuilder(X86::AND32ri).addReg(X86::EDX)
218 .addReg(X86::EDX).addImm(7));
219
220 switch (AccessSize) {
221 case 1:
222 break;
223 case 2: {
224 MCInst Inst;
225 Inst.setOpcode(X86::LEA32r);
226 Inst.addOperand(MCOperand::CreateReg(X86::EDX));
227
228 const MCExpr *Disp = MCConstantExpr::Create(1, Ctx);
229 std::unique_ptr<X86Operand> Op(
230 X86Operand::CreateMem(0, Disp, X86::EDX, 0, 1, SMLoc(), SMLoc()));
231 Op->addMemOperands(Inst, 5);
232 EmitInstruction(Out, Inst);
233 break;
234 }
235 case 4:
236 EmitInstruction(Out, MCInstBuilder(X86::ADD32ri8).addReg(X86::EDX)
237 .addReg(X86::EDX).addImm(3));
238 break;
239 default:
240 assert(false && "Incorrect access size");
241 break;
242 }
243
244 EmitInstruction(
245 Out, MCInstBuilder(X86::MOVSX32rr8).addReg(X86::ECX).addReg(X86::CL));
246 EmitInstruction(
247 Out, MCInstBuilder(X86::CMP32rr).addReg(X86::EDX).addReg(X86::ECX));
248 EmitInstruction(Out, MCInstBuilder(X86::JL_4).addExpr(DoneExpr));
249
250 EmitCallAsanReport(Ctx, Out, AccessSize, IsWrite, X86::EAX);
251 EmitLabel(Out, DoneSym);
252
253 EmitInstruction(Out, MCInstBuilder(X86::POPF32));
254 EmitInstruction(Out, MCInstBuilder(X86::POP32r).addReg(X86::EDX));
255 EmitInstruction(Out, MCInstBuilder(X86::POP32r).addReg(X86::ECX));
Evgeniy Stepanovfc9c78a2014-05-21 08:14:24 +0000256 EmitInstruction(Out, MCInstBuilder(X86::POP32r).addReg(X86::EAX));
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000257}
258
259void X86AddressSanitizer32::InstrumentMemOperandLargeImpl(
260 X86Operand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx,
261 MCStreamer &Out) {
262 EmitInstruction(Out, MCInstBuilder(X86::PUSH32r).addReg(X86::EAX));
263 EmitInstruction(Out, MCInstBuilder(X86::PUSH32r).addReg(X86::ECX));
264 EmitInstruction(Out, MCInstBuilder(X86::PUSHF32));
265
266 {
267 MCInst Inst;
268 Inst.setOpcode(X86::LEA32r);
269 Inst.addOperand(MCOperand::CreateReg(X86::EAX));
270 Op.addMemOperands(Inst, 5);
271 EmitInstruction(Out, Inst);
272 }
273 EmitInstruction(
274 Out, MCInstBuilder(X86::MOV32rr).addReg(X86::ECX).addReg(X86::EAX));
275 EmitInstruction(Out, MCInstBuilder(X86::SHR32ri).addReg(X86::ECX)
276 .addReg(X86::ECX).addImm(3));
277 {
278 MCInst Inst;
279 switch (AccessSize) {
280 case 8:
281 Inst.setOpcode(X86::CMP8mi);
282 break;
283 case 16:
284 Inst.setOpcode(X86::CMP16mi);
285 break;
286 default:
287 assert(false && "Incorrect access size");
288 break;
289 }
290 const MCExpr *Disp = MCConstantExpr::Create(kShadowOffset, Ctx);
291 std::unique_ptr<X86Operand> Op(
292 X86Operand::CreateMem(0, Disp, X86::ECX, 0, 1, SMLoc(), SMLoc()));
293 Op->addMemOperands(Inst, 5);
294 Inst.addOperand(MCOperand::CreateImm(0));
295 EmitInstruction(Out, Inst);
296 }
297 MCSymbol *DoneSym = Ctx.CreateTempSymbol();
298 const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx);
299 EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr));
300
301 EmitCallAsanReport(Ctx, Out, AccessSize, IsWrite, X86::EAX);
302 EmitLabel(Out, DoneSym);
303
304 EmitInstruction(Out, MCInstBuilder(X86::POPF32));
305 EmitInstruction(Out, MCInstBuilder(X86::POP32r).addReg(X86::ECX));
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000306 EmitInstruction(Out, MCInstBuilder(X86::POP32r).addReg(X86::EAX));
307}
308
309class X86AddressSanitizer64 : public X86AddressSanitizer {
310public:
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000311 static const long kShadowOffset = 0x7fff8000;
312
Evgeniy Stepanov0a951b72014-04-23 11:16:03 +0000313 X86AddressSanitizer64(const MCSubtargetInfo &STI)
314 : X86AddressSanitizer(STI) {}
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000315 virtual ~X86AddressSanitizer64() {}
316
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000317 virtual void InstrumentMemOperandSmallImpl(
318 X86Operand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx,
319 MCStreamer &Out) override;
320 virtual void InstrumentMemOperandLargeImpl(
321 X86Operand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx,
322 MCStreamer &Out) override;
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000323
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000324private:
325 void EmitAdjustRSP(MCContext &Ctx, MCStreamer &Out, long Offset) {
Evgeniy Stepanov9661ec02014-05-08 09:55:24 +0000326 MCInst Inst;
327 Inst.setOpcode(X86::LEA64r);
328 Inst.addOperand(MCOperand::CreateReg(X86::RSP));
329
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000330 const MCExpr *Disp = MCConstantExpr::Create(Offset, Ctx);
Benjamin Kramer8bbadc02014-05-09 09:48:03 +0000331 std::unique_ptr<X86Operand> Op(
332 X86Operand::CreateMem(0, Disp, X86::RSP, 0, 1, SMLoc(), SMLoc()));
Evgeniy Stepanov9661ec02014-05-08 09:55:24 +0000333 Op->addMemOperands(Inst, 5);
334 EmitInstruction(Out, Inst);
335 }
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000336
337 void EmitCallAsanReport(MCContext &Ctx, MCStreamer &Out, unsigned AccessSize,
338 bool IsWrite) {
339 EmitInstruction(Out, MCInstBuilder(X86::CLD));
340 EmitInstruction(Out, MCInstBuilder(X86::MMX_EMMS));
341
342 EmitInstruction(Out, MCInstBuilder(X86::AND64ri8).addReg(X86::RSP)
343 .addReg(X86::RSP).addImm(-16));
344
345 const std::string& Fn = FuncName(AccessSize, IsWrite);
346 MCSymbol *FnSym = Ctx.GetOrCreateSymbol(StringRef(Fn));
347 const MCSymbolRefExpr *FnExpr =
348 MCSymbolRefExpr::Create(FnSym, MCSymbolRefExpr::VK_PLT, Ctx);
349 EmitInstruction(Out, MCInstBuilder(X86::CALL64pcrel32).addExpr(FnExpr));
350 }
351};
352
353void X86AddressSanitizer64::InstrumentMemOperandSmallImpl(
354 X86Operand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx,
355 MCStreamer &Out) {
356 EmitAdjustRSP(Ctx, Out, -128);
357 EmitInstruction(Out, MCInstBuilder(X86::PUSH64r).addReg(X86::RAX));
358 EmitInstruction(Out, MCInstBuilder(X86::PUSH64r).addReg(X86::RCX));
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000359 EmitInstruction(Out, MCInstBuilder(X86::PUSH64r).addReg(X86::RDI));
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000360 EmitInstruction(Out, MCInstBuilder(X86::PUSHF64));
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000361 {
362 MCInst Inst;
363 Inst.setOpcode(X86::LEA64r);
364 Inst.addOperand(MCOperand::CreateReg(X86::RDI));
David Blaikie960ea3f2014-06-08 16:18:35 +0000365 Op.addMemOperands(Inst, 5);
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000366 EmitInstruction(Out, Inst);
367 }
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000368 EmitInstruction(
369 Out, MCInstBuilder(X86::MOV64rr).addReg(X86::RAX).addReg(X86::RDI));
370 EmitInstruction(Out, MCInstBuilder(X86::SHR64ri).addReg(X86::RAX)
371 .addReg(X86::RAX).addImm(3));
Evgeniy Stepanov9661ec02014-05-08 09:55:24 +0000372 {
373 MCInst Inst;
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000374 Inst.setOpcode(X86::MOV8rm);
375 Inst.addOperand(MCOperand::CreateReg(X86::AL));
376 const MCExpr *Disp = MCConstantExpr::Create(kShadowOffset, Ctx);
Benjamin Kramer8bbadc02014-05-09 09:48:03 +0000377 std::unique_ptr<X86Operand> Op(
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000378 X86Operand::CreateMem(0, Disp, X86::RAX, 0, 1, SMLoc(), SMLoc()));
Evgeniy Stepanov9661ec02014-05-08 09:55:24 +0000379 Op->addMemOperands(Inst, 5);
380 EmitInstruction(Out, Inst);
381 }
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000382
383 EmitInstruction(Out,
384 MCInstBuilder(X86::TEST8rr).addReg(X86::AL).addReg(X86::AL));
385 MCSymbol *DoneSym = Ctx.CreateTempSymbol();
386 const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx);
387 EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr));
388
389 EmitInstruction(
390 Out, MCInstBuilder(X86::MOV32rr).addReg(X86::ECX).addReg(X86::EDI));
391 EmitInstruction(Out, MCInstBuilder(X86::AND32ri).addReg(X86::ECX)
392 .addReg(X86::ECX).addImm(7));
393
394 switch (AccessSize) {
395 case 1:
396 break;
397 case 2: {
398 MCInst Inst;
399 Inst.setOpcode(X86::LEA32r);
400 Inst.addOperand(MCOperand::CreateReg(X86::ECX));
401
402 const MCExpr *Disp = MCConstantExpr::Create(1, Ctx);
403 std::unique_ptr<X86Operand> Op(
404 X86Operand::CreateMem(0, Disp, X86::ECX, 0, 1, SMLoc(), SMLoc()));
405 Op->addMemOperands(Inst, 5);
406 EmitInstruction(Out, Inst);
407 break;
408 }
409 case 4:
410 EmitInstruction(Out, MCInstBuilder(X86::ADD32ri8).addReg(X86::ECX)
411 .addReg(X86::ECX).addImm(3));
412 break;
413 default:
414 assert(false && "Incorrect access size");
415 break;
416 }
417
418 EmitInstruction(
419 Out, MCInstBuilder(X86::MOVSX32rr8).addReg(X86::EAX).addReg(X86::AL));
420 EmitInstruction(
421 Out, MCInstBuilder(X86::CMP32rr).addReg(X86::ECX).addReg(X86::EAX));
422 EmitInstruction(Out, MCInstBuilder(X86::JL_4).addExpr(DoneExpr));
423
424 EmitCallAsanReport(Ctx, Out, AccessSize, IsWrite);
425 EmitLabel(Out, DoneSym);
426
427 EmitInstruction(Out, MCInstBuilder(X86::POPF64));
428 EmitInstruction(Out, MCInstBuilder(X86::POP64r).addReg(X86::RDI));
429 EmitInstruction(Out, MCInstBuilder(X86::POP64r).addReg(X86::RCX));
430 EmitInstruction(Out, MCInstBuilder(X86::POP64r).addReg(X86::RAX));
431 EmitAdjustRSP(Ctx, Out, 128);
432}
433
434void X86AddressSanitizer64::InstrumentMemOperandLargeImpl(
435 X86Operand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx,
436 MCStreamer &Out) {
437 EmitAdjustRSP(Ctx, Out, -128);
438 EmitInstruction(Out, MCInstBuilder(X86::PUSH64r).addReg(X86::RAX));
439 EmitInstruction(Out, MCInstBuilder(X86::PUSHF64));
440
441 {
442 MCInst Inst;
443 Inst.setOpcode(X86::LEA64r);
444 Inst.addOperand(MCOperand::CreateReg(X86::RAX));
445 Op.addMemOperands(Inst, 5);
446 EmitInstruction(Out, Inst);
447 }
448 EmitInstruction(Out, MCInstBuilder(X86::SHR64ri).addReg(X86::RAX)
449 .addReg(X86::RAX).addImm(3));
450 {
451 MCInst Inst;
452 switch (AccessSize) {
453 case 8:
454 Inst.setOpcode(X86::CMP8mi);
455 break;
456 case 16:
457 Inst.setOpcode(X86::CMP16mi);
458 break;
459 default:
460 assert(false && "Incorrect access size");
461 break;
462 }
463 const MCExpr *Disp = MCConstantExpr::Create(kShadowOffset, Ctx);
464 std::unique_ptr<X86Operand> Op(
465 X86Operand::CreateMem(0, Disp, X86::RAX, 0, 1, SMLoc(), SMLoc()));
466 Op->addMemOperands(Inst, 5);
467 Inst.addOperand(MCOperand::CreateImm(0));
468 EmitInstruction(Out, Inst);
469 }
470
471 MCSymbol *DoneSym = Ctx.CreateTempSymbol();
472 const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx);
473 EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr));
474
475 EmitCallAsanReport(Ctx, Out, AccessSize, IsWrite);
476 EmitLabel(Out, DoneSym);
477
478 EmitInstruction(Out, MCInstBuilder(X86::POPF64));
479 EmitInstruction(Out, MCInstBuilder(X86::POP64r).addReg(X86::RAX));
480 EmitAdjustRSP(Ctx, Out, 128);
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000481}
482
483} // End anonymous namespace
484
485X86AsmInstrumentation::X86AsmInstrumentation() {}
486X86AsmInstrumentation::~X86AsmInstrumentation() {}
487
Evgeniy Stepanov6fa6c672014-07-07 13:57:37 +0000488void X86AsmInstrumentation::InstrumentInstruction(
489 const MCInst &Inst, OperandVector &Operands, MCContext &Ctx,
490 const MCInstrInfo &MII, MCStreamer &Out) {}
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000491
Evgeniy Stepanov0a951b72014-04-23 11:16:03 +0000492X86AsmInstrumentation *
Evgeniy Stepanov29865f72014-04-30 14:04:31 +0000493CreateX86AsmInstrumentation(const MCTargetOptions &MCOptions,
494 const MCContext &Ctx, const MCSubtargetInfo &STI) {
495 Triple T(STI.getTargetTriple());
496 const bool hasCompilerRTSupport = T.isOSLinux();
Evgeniy Stepanov3819f022014-05-07 07:54:11 +0000497 if (ClAsanInstrumentAssembly && hasCompilerRTSupport &&
498 MCOptions.SanitizeAddress) {
Evgeniy Stepanov49e26252014-03-14 08:58:04 +0000499 if ((STI.getFeatureBits() & X86::Mode32Bit) != 0)
500 return new X86AddressSanitizer32(STI);
501 if ((STI.getFeatureBits() & X86::Mode64Bit) != 0)
502 return new X86AddressSanitizer64(STI);
503 }
504 return new X86AsmInstrumentation();
505}
506
507} // End llvm namespace