Revert "[asan-assembly-instrumentation] Prologue and epilogue are moved out from...
[oota-llvm.git] / lib / Target / X86 / AsmParser / X86AsmInstrumentation.cpp
1 //===-- 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"
14 #include "llvm/ADT/Triple.h"
15 #include "llvm/IR/Function.h"
16 #include "llvm/MC/MCContext.h"
17 #include "llvm/MC/MCInst.h"
18 #include "llvm/MC/MCInstBuilder.h"
19 #include "llvm/MC/MCInstrInfo.h"
20 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
21 #include "llvm/MC/MCStreamer.h"
22 #include "llvm/MC/MCSubtargetInfo.h"
23 #include "llvm/MC/MCTargetAsmParser.h"
24 #include "llvm/MC/MCTargetOptions.h"
25 #include "llvm/Support/CommandLine.h"
26
27 namespace llvm {
28 namespace {
29
30 static cl::opt<bool> ClAsanInstrumentAssembly(
31     "asan-instrument-assembly",
32     cl::desc("instrument assembly with AddressSanitizer checks"), cl::Hidden,
33     cl::init(false));
34
35 bool IsStackReg(unsigned Reg) {
36   return Reg == X86::RSP || Reg == X86::ESP || Reg == X86::SP;
37 }
38
39 std::string FuncName(unsigned AccessSize, bool IsWrite) {
40   return std::string("__asan_report_") + (IsWrite ? "store" : "load") +
41          utostr(AccessSize);
42 }
43
44 class X86AddressSanitizer : public X86AsmInstrumentation {
45 public:
46   X86AddressSanitizer(const MCSubtargetInfo &STI)
47       : X86AsmInstrumentation(STI), RepPrefix(false) {}
48   virtual ~X86AddressSanitizer() {}
49
50   // X86AsmInstrumentation implementation:
51   virtual void InstrumentAndEmitInstruction(const MCInst &Inst,
52                                             OperandVector &Operands,
53                                             MCContext &Ctx,
54                                             const MCInstrInfo &MII,
55                                             MCStreamer &Out) override {
56     InstrumentMOVS(Inst, Operands, Ctx, MII, Out);
57     if (RepPrefix)
58       EmitInstruction(Out, MCInstBuilder(X86::REP_PREFIX));
59
60     InstrumentMOV(Inst, Operands, Ctx, MII, Out);
61
62     RepPrefix = (Inst.getOpcode() == X86::REP_PREFIX);
63     if (!RepPrefix)
64       EmitInstruction(Out, Inst);
65   }
66
67   // Should be implemented differently in x86_32 and x86_64 subclasses.
68   virtual void InstrumentMemOperandSmallImpl(X86Operand &Op,
69                                              unsigned AccessSize, bool IsWrite,
70                                              MCContext &Ctx,
71                                              MCStreamer &Out) = 0;
72   virtual void InstrumentMemOperandLargeImpl(X86Operand &Op,
73                                              unsigned AccessSize, bool IsWrite,
74                                              MCContext &Ctx,
75                                              MCStreamer &Out) = 0;
76   virtual void InstrumentMOVSImpl(unsigned AccessSize, MCContext &Ctx,
77                                   MCStreamer &Out) = 0;
78
79   void InstrumentMemOperand(MCParsedAsmOperand &Op, unsigned AccessSize,
80                             bool IsWrite, MCContext &Ctx, MCStreamer &Out);
81   void InstrumentMOVSBase(unsigned DstReg, unsigned SrcReg, unsigned CntReg,
82                           unsigned AccessSize, MCContext &Ctx, MCStreamer &Out);
83   void InstrumentMOVS(const MCInst &Inst, OperandVector &Operands,
84                       MCContext &Ctx, const MCInstrInfo &MII, MCStreamer &Out);
85   void InstrumentMOV(const MCInst &Inst, OperandVector &Operands,
86                      MCContext &Ctx, const MCInstrInfo &MII, MCStreamer &Out);
87
88   void EmitLabel(MCStreamer &Out, MCSymbol *Label) { Out.EmitLabel(Label); }
89
90 protected:
91   // True when previous instruction was actually REP prefix.
92   bool RepPrefix;
93 };
94
95 void X86AddressSanitizer::InstrumentMemOperand(MCParsedAsmOperand &Op,
96                                                unsigned AccessSize,
97                                                bool IsWrite, MCContext &Ctx,
98                                                MCStreamer &Out) {
99   assert(Op.isMem() && "Op should be a memory operand.");
100   assert((AccessSize & (AccessSize - 1)) == 0 && AccessSize <= 16 &&
101          "AccessSize should be a power of two, less or equal than 16.");
102
103   X86Operand &MemOp = static_cast<X86Operand &>(Op);
104   // FIXME: get rid of this limitation.
105   if (IsStackReg(MemOp.getMemBaseReg()) || IsStackReg(MemOp.getMemIndexReg()))
106     return;
107
108   // FIXME: take into account load/store alignment.
109   if (AccessSize < 8)
110     InstrumentMemOperandSmallImpl(MemOp, AccessSize, IsWrite, Ctx, Out);
111   else
112     InstrumentMemOperandLargeImpl(MemOp, AccessSize, IsWrite, Ctx, Out);
113 }
114
115 void X86AddressSanitizer::InstrumentMOVSBase(unsigned DstReg, unsigned SrcReg,
116                                              unsigned CntReg,
117                                              unsigned AccessSize,
118                                              MCContext &Ctx, MCStreamer &Out) {
119   // FIXME: check whole ranges [DstReg .. DstReg + AccessSize * (CntReg - 1)]
120   // and [SrcReg .. SrcReg + AccessSize * (CntReg - 1)].
121
122   // FIXME: extract prolog and epilogue from InstrumentMemOperand()
123   // and optimize this sequence of InstrumentMemOperand() calls.
124
125   // Test (%SrcReg)
126   {
127     const MCExpr *Disp = MCConstantExpr::Create(0, Ctx);
128     std::unique_ptr<X86Operand> Op(X86Operand::CreateMem(
129         0, Disp, SrcReg, 0, AccessSize, SMLoc(), SMLoc()));
130     InstrumentMemOperand(*Op, AccessSize, false /* IsWrite */, Ctx, Out);
131   }
132
133   // Test -1(%SrcReg, %CntReg, AccessSize)
134   {
135     const MCExpr *Disp = MCConstantExpr::Create(-1, Ctx);
136     std::unique_ptr<X86Operand> Op(X86Operand::CreateMem(
137         0, Disp, SrcReg, CntReg, AccessSize, SMLoc(), SMLoc()));
138     InstrumentMemOperand(*Op, AccessSize, false /* IsWrite */, Ctx, Out);
139   }
140
141   // Test (%DstReg)
142   {
143     const MCExpr *Disp = MCConstantExpr::Create(0, Ctx);
144     std::unique_ptr<X86Operand> Op(X86Operand::CreateMem(
145         0, Disp, DstReg, 0, AccessSize, SMLoc(), SMLoc()));
146     InstrumentMemOperand(*Op, AccessSize, true /* IsWrite */, Ctx, Out);
147   }
148
149   // Test -1(%DstReg, %CntReg, AccessSize)
150   {
151     const MCExpr *Disp = MCConstantExpr::Create(-1, Ctx);
152     std::unique_ptr<X86Operand> Op(X86Operand::CreateMem(
153         0, Disp, DstReg, CntReg, AccessSize, SMLoc(), SMLoc()));
154     InstrumentMemOperand(*Op, AccessSize, true /* IsWrite */, Ctx, Out);
155   }
156 }
157
158 void X86AddressSanitizer::InstrumentMOVS(const MCInst &Inst,
159                                          OperandVector &Operands,
160                                          MCContext &Ctx, const MCInstrInfo &MII,
161                                          MCStreamer &Out) {
162   // Access size in bytes.
163   unsigned AccessSize = 0;
164
165   switch (Inst.getOpcode()) {
166   case X86::MOVSB:
167     AccessSize = 1;
168     break;
169   case X86::MOVSW:
170     AccessSize = 2;
171     break;
172   case X86::MOVSL:
173     AccessSize = 4;
174     break;
175   case X86::MOVSQ:
176     AccessSize = 8;
177     break;
178   default:
179     return;
180   }
181
182   InstrumentMOVSImpl(AccessSize, Ctx, Out);
183 }
184
185 void X86AddressSanitizer::InstrumentMOV(const MCInst &Inst,
186                                         OperandVector &Operands, MCContext &Ctx,
187                                         const MCInstrInfo &MII,
188                                         MCStreamer &Out) {
189   // Access size in bytes.
190   unsigned AccessSize = 0;
191
192   switch (Inst.getOpcode()) {
193   case X86::MOV8mi:
194   case X86::MOV8mr:
195   case X86::MOV8rm:
196     AccessSize = 1;
197     break;
198   case X86::MOV16mi:
199   case X86::MOV16mr:
200   case X86::MOV16rm:
201     AccessSize = 2;
202     break;
203   case X86::MOV32mi:
204   case X86::MOV32mr:
205   case X86::MOV32rm:
206     AccessSize = 4;
207     break;
208   case X86::MOV64mi32:
209   case X86::MOV64mr:
210   case X86::MOV64rm:
211     AccessSize = 8;
212     break;
213   case X86::MOVAPDmr:
214   case X86::MOVAPSmr:
215   case X86::MOVAPDrm:
216   case X86::MOVAPSrm:
217     AccessSize = 16;
218     break;
219   default:
220     return;
221   }
222
223   const bool IsWrite = MII.get(Inst.getOpcode()).mayStore();
224   for (unsigned Ix = 0; Ix < Operands.size(); ++Ix) {
225     assert(Operands[Ix]);
226     MCParsedAsmOperand &Op = *Operands[Ix];
227     if (Op.isMem())
228       InstrumentMemOperand(Op, AccessSize, IsWrite, Ctx, Out);
229   }
230 }
231
232 class X86AddressSanitizer32 : public X86AddressSanitizer {
233 public:
234   static const long kShadowOffset = 0x20000000;
235
236   X86AddressSanitizer32(const MCSubtargetInfo &STI)
237       : X86AddressSanitizer(STI) {}
238   virtual ~X86AddressSanitizer32() {}
239
240   virtual void InstrumentMemOperandSmallImpl(X86Operand &Op,
241                                              unsigned AccessSize, bool IsWrite,
242                                              MCContext &Ctx,
243                                              MCStreamer &Out) override;
244   virtual void InstrumentMemOperandLargeImpl(X86Operand &Op,
245                                              unsigned AccessSize, bool IsWrite,
246                                              MCContext &Ctx,
247                                              MCStreamer &Out) override;
248   virtual void InstrumentMOVSImpl(unsigned AccessSize, MCContext &Ctx,
249                                   MCStreamer &Out) override;
250
251 private:
252   void EmitCallAsanReport(MCContext &Ctx, MCStreamer &Out, unsigned AccessSize,
253                           bool IsWrite, unsigned AddressReg) {
254     EmitInstruction(Out, MCInstBuilder(X86::CLD));
255     EmitInstruction(Out, MCInstBuilder(X86::MMX_EMMS));
256
257     EmitInstruction(Out, MCInstBuilder(X86::AND64ri8)
258                              .addReg(X86::ESP)
259                              .addReg(X86::ESP)
260                              .addImm(-16));
261     EmitInstruction(Out, MCInstBuilder(X86::PUSH32r).addReg(AddressReg));
262
263     const std::string &Fn = FuncName(AccessSize, IsWrite);
264     MCSymbol *FnSym = Ctx.GetOrCreateSymbol(StringRef(Fn));
265     const MCSymbolRefExpr *FnExpr =
266         MCSymbolRefExpr::Create(FnSym, MCSymbolRefExpr::VK_PLT, Ctx);
267     EmitInstruction(Out, MCInstBuilder(X86::CALLpcrel32).addExpr(FnExpr));
268   }
269 };
270
271 void X86AddressSanitizer32::InstrumentMemOperandSmallImpl(X86Operand &Op,
272                                                           unsigned AccessSize,
273                                                           bool IsWrite,
274                                                           MCContext &Ctx,
275                                                           MCStreamer &Out) {
276   EmitInstruction(Out, MCInstBuilder(X86::PUSH32r).addReg(X86::EAX));
277   EmitInstruction(Out, MCInstBuilder(X86::PUSH32r).addReg(X86::ECX));
278   EmitInstruction(Out, MCInstBuilder(X86::PUSH32r).addReg(X86::EDX));
279   EmitInstruction(Out, MCInstBuilder(X86::PUSHF32));
280
281   {
282     MCInst Inst;
283     Inst.setOpcode(X86::LEA32r);
284     Inst.addOperand(MCOperand::CreateReg(X86::EAX));
285     Op.addMemOperands(Inst, 5);
286     EmitInstruction(Out, Inst);
287   }
288
289   EmitInstruction(
290       Out, MCInstBuilder(X86::MOV32rr).addReg(X86::ECX).addReg(X86::EAX));
291   EmitInstruction(
292       Out,
293       MCInstBuilder(X86::SHR32ri).addReg(X86::ECX).addReg(X86::ECX).addImm(3));
294
295   {
296     MCInst Inst;
297     Inst.setOpcode(X86::MOV8rm);
298     Inst.addOperand(MCOperand::CreateReg(X86::CL));
299     const MCExpr *Disp = MCConstantExpr::Create(kShadowOffset, Ctx);
300     std::unique_ptr<X86Operand> Op(
301         X86Operand::CreateMem(0, Disp, X86::ECX, 0, 1, SMLoc(), SMLoc()));
302     Op->addMemOperands(Inst, 5);
303     EmitInstruction(Out, Inst);
304   }
305
306   EmitInstruction(Out,
307                   MCInstBuilder(X86::TEST8rr).addReg(X86::CL).addReg(X86::CL));
308   MCSymbol *DoneSym = Ctx.CreateTempSymbol();
309   const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx);
310   EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr));
311
312   EmitInstruction(
313       Out, MCInstBuilder(X86::MOV32rr).addReg(X86::EDX).addReg(X86::EAX));
314   EmitInstruction(
315       Out,
316       MCInstBuilder(X86::AND32ri).addReg(X86::EDX).addReg(X86::EDX).addImm(7));
317
318   switch (AccessSize) {
319   case 1:
320     break;
321   case 2: {
322     MCInst Inst;
323     Inst.setOpcode(X86::LEA32r);
324     Inst.addOperand(MCOperand::CreateReg(X86::EDX));
325
326     const MCExpr *Disp = MCConstantExpr::Create(1, Ctx);
327     std::unique_ptr<X86Operand> Op(
328         X86Operand::CreateMem(0, Disp, X86::EDX, 0, 1, SMLoc(), SMLoc()));
329     Op->addMemOperands(Inst, 5);
330     EmitInstruction(Out, Inst);
331     break;
332   }
333   case 4:
334     EmitInstruction(Out, MCInstBuilder(X86::ADD32ri8)
335                              .addReg(X86::EDX)
336                              .addReg(X86::EDX)
337                              .addImm(3));
338     break;
339   default:
340     assert(false && "Incorrect access size");
341     break;
342   }
343
344   EmitInstruction(
345       Out, MCInstBuilder(X86::MOVSX32rr8).addReg(X86::ECX).addReg(X86::CL));
346   EmitInstruction(
347       Out, MCInstBuilder(X86::CMP32rr).addReg(X86::EDX).addReg(X86::ECX));
348   EmitInstruction(Out, MCInstBuilder(X86::JL_4).addExpr(DoneExpr));
349
350   EmitCallAsanReport(Ctx, Out, AccessSize, IsWrite, X86::EAX);
351   EmitLabel(Out, DoneSym);
352
353   EmitInstruction(Out, MCInstBuilder(X86::POPF32));
354   EmitInstruction(Out, MCInstBuilder(X86::POP32r).addReg(X86::EDX));
355   EmitInstruction(Out, MCInstBuilder(X86::POP32r).addReg(X86::ECX));
356   EmitInstruction(Out, MCInstBuilder(X86::POP32r).addReg(X86::EAX));
357 }
358
359 void X86AddressSanitizer32::InstrumentMemOperandLargeImpl(X86Operand &Op,
360                                                           unsigned AccessSize,
361                                                           bool IsWrite,
362                                                           MCContext &Ctx,
363                                                           MCStreamer &Out) {
364   EmitInstruction(Out, MCInstBuilder(X86::PUSH32r).addReg(X86::EAX));
365   EmitInstruction(Out, MCInstBuilder(X86::PUSH32r).addReg(X86::ECX));
366   EmitInstruction(Out, MCInstBuilder(X86::PUSHF32));
367
368   {
369     MCInst Inst;
370     Inst.setOpcode(X86::LEA32r);
371     Inst.addOperand(MCOperand::CreateReg(X86::EAX));
372     Op.addMemOperands(Inst, 5);
373     EmitInstruction(Out, Inst);
374   }
375   EmitInstruction(
376       Out, MCInstBuilder(X86::MOV32rr).addReg(X86::ECX).addReg(X86::EAX));
377   EmitInstruction(
378       Out,
379       MCInstBuilder(X86::SHR32ri).addReg(X86::ECX).addReg(X86::ECX).addImm(3));
380   {
381     MCInst Inst;
382     switch (AccessSize) {
383     case 8:
384       Inst.setOpcode(X86::CMP8mi);
385       break;
386     case 16:
387       Inst.setOpcode(X86::CMP16mi);
388       break;
389     default:
390       assert(false && "Incorrect access size");
391       break;
392     }
393     const MCExpr *Disp = MCConstantExpr::Create(kShadowOffset, Ctx);
394     std::unique_ptr<X86Operand> Op(
395         X86Operand::CreateMem(0, Disp, X86::ECX, 0, 1, SMLoc(), SMLoc()));
396     Op->addMemOperands(Inst, 5);
397     Inst.addOperand(MCOperand::CreateImm(0));
398     EmitInstruction(Out, Inst);
399   }
400   MCSymbol *DoneSym = Ctx.CreateTempSymbol();
401   const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx);
402   EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr));
403
404   EmitCallAsanReport(Ctx, Out, AccessSize, IsWrite, X86::EAX);
405   EmitLabel(Out, DoneSym);
406
407   EmitInstruction(Out, MCInstBuilder(X86::POPF32));
408   EmitInstruction(Out, MCInstBuilder(X86::POP32r).addReg(X86::ECX));
409   EmitInstruction(Out, MCInstBuilder(X86::POP32r).addReg(X86::EAX));
410 }
411
412 void X86AddressSanitizer32::InstrumentMOVSImpl(unsigned AccessSize,
413                                                MCContext &Ctx,
414                                                MCStreamer &Out) {
415   EmitInstruction(Out, MCInstBuilder(X86::PUSHF32));
416
417   // No need to test when ECX is equals to zero.
418   MCSymbol *DoneSym = Ctx.CreateTempSymbol();
419   const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx);
420   EmitInstruction(
421       Out, MCInstBuilder(X86::TEST32rr).addReg(X86::ECX).addReg(X86::ECX));
422   EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr));
423
424   // Instrument first and last elements in src and dst range.
425   InstrumentMOVSBase(X86::EDI /* DstReg */, X86::ESI /* SrcReg */,
426                      X86::ECX /* CntReg */, AccessSize, Ctx, Out);
427
428   EmitLabel(Out, DoneSym);
429   EmitInstruction(Out, MCInstBuilder(X86::POPF32));
430 }
431
432 class X86AddressSanitizer64 : public X86AddressSanitizer {
433 public:
434   static const long kShadowOffset = 0x7fff8000;
435
436   X86AddressSanitizer64(const MCSubtargetInfo &STI)
437       : X86AddressSanitizer(STI) {}
438   virtual ~X86AddressSanitizer64() {}
439
440   virtual void InstrumentMemOperandSmallImpl(X86Operand &Op,
441                                              unsigned AccessSize, bool IsWrite,
442                                              MCContext &Ctx,
443                                              MCStreamer &Out) override;
444   virtual void InstrumentMemOperandLargeImpl(X86Operand &Op,
445                                              unsigned AccessSize, bool IsWrite,
446                                              MCContext &Ctx,
447                                              MCStreamer &Out) override;
448   virtual void InstrumentMOVSImpl(unsigned AccessSize, MCContext &Ctx,
449                                   MCStreamer &Out) override;
450
451 private:
452   void EmitAdjustRSP(MCContext &Ctx, MCStreamer &Out, long Offset) {
453     MCInst Inst;
454     Inst.setOpcode(X86::LEA64r);
455     Inst.addOperand(MCOperand::CreateReg(X86::RSP));
456
457     const MCExpr *Disp = MCConstantExpr::Create(Offset, Ctx);
458     std::unique_ptr<X86Operand> Op(
459         X86Operand::CreateMem(0, Disp, X86::RSP, 0, 1, SMLoc(), SMLoc()));
460     Op->addMemOperands(Inst, 5);
461     EmitInstruction(Out, Inst);
462   }
463
464   void EmitCallAsanReport(MCContext &Ctx, MCStreamer &Out, unsigned AccessSize,
465                           bool IsWrite) {
466     EmitInstruction(Out, MCInstBuilder(X86::CLD));
467     EmitInstruction(Out, MCInstBuilder(X86::MMX_EMMS));
468
469     EmitInstruction(Out, MCInstBuilder(X86::AND64ri8)
470                              .addReg(X86::RSP)
471                              .addReg(X86::RSP)
472                              .addImm(-16));
473
474     const std::string &Fn = FuncName(AccessSize, IsWrite);
475     MCSymbol *FnSym = Ctx.GetOrCreateSymbol(StringRef(Fn));
476     const MCSymbolRefExpr *FnExpr =
477         MCSymbolRefExpr::Create(FnSym, MCSymbolRefExpr::VK_PLT, Ctx);
478     EmitInstruction(Out, MCInstBuilder(X86::CALL64pcrel32).addExpr(FnExpr));
479   }
480 };
481
482 void X86AddressSanitizer64::InstrumentMemOperandSmallImpl(X86Operand &Op,
483                                                           unsigned AccessSize,
484                                                           bool IsWrite,
485                                                           MCContext &Ctx,
486                                                           MCStreamer &Out) {
487   EmitAdjustRSP(Ctx, Out, -128);
488   EmitInstruction(Out, MCInstBuilder(X86::PUSH64r).addReg(X86::RAX));
489   EmitInstruction(Out, MCInstBuilder(X86::PUSH64r).addReg(X86::RCX));
490   EmitInstruction(Out, MCInstBuilder(X86::PUSH64r).addReg(X86::RDI));
491   EmitInstruction(Out, MCInstBuilder(X86::PUSHF64));
492   {
493     MCInst Inst;
494     Inst.setOpcode(X86::LEA64r);
495     Inst.addOperand(MCOperand::CreateReg(X86::RDI));
496     Op.addMemOperands(Inst, 5);
497     EmitInstruction(Out, Inst);
498   }
499   EmitInstruction(
500       Out, MCInstBuilder(X86::MOV64rr).addReg(X86::RAX).addReg(X86::RDI));
501   EmitInstruction(
502       Out,
503       MCInstBuilder(X86::SHR64ri).addReg(X86::RAX).addReg(X86::RAX).addImm(3));
504   {
505     MCInst Inst;
506     Inst.setOpcode(X86::MOV8rm);
507     Inst.addOperand(MCOperand::CreateReg(X86::AL));
508     const MCExpr *Disp = MCConstantExpr::Create(kShadowOffset, Ctx);
509     std::unique_ptr<X86Operand> Op(
510         X86Operand::CreateMem(0, Disp, X86::RAX, 0, 1, SMLoc(), SMLoc()));
511     Op->addMemOperands(Inst, 5);
512     EmitInstruction(Out, Inst);
513   }
514
515   EmitInstruction(Out,
516                   MCInstBuilder(X86::TEST8rr).addReg(X86::AL).addReg(X86::AL));
517   MCSymbol *DoneSym = Ctx.CreateTempSymbol();
518   const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx);
519   EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr));
520
521   EmitInstruction(
522       Out, MCInstBuilder(X86::MOV32rr).addReg(X86::ECX).addReg(X86::EDI));
523   EmitInstruction(
524       Out,
525       MCInstBuilder(X86::AND32ri).addReg(X86::ECX).addReg(X86::ECX).addImm(7));
526
527   switch (AccessSize) {
528   case 1:
529     break;
530   case 2: {
531     MCInst Inst;
532     Inst.setOpcode(X86::LEA32r);
533     Inst.addOperand(MCOperand::CreateReg(X86::ECX));
534
535     const MCExpr *Disp = MCConstantExpr::Create(1, Ctx);
536     std::unique_ptr<X86Operand> Op(
537         X86Operand::CreateMem(0, Disp, X86::ECX, 0, 1, SMLoc(), SMLoc()));
538     Op->addMemOperands(Inst, 5);
539     EmitInstruction(Out, Inst);
540     break;
541   }
542   case 4:
543     EmitInstruction(Out, MCInstBuilder(X86::ADD32ri8)
544                              .addReg(X86::ECX)
545                              .addReg(X86::ECX)
546                              .addImm(3));
547     break;
548   default:
549     assert(false && "Incorrect access size");
550     break;
551   }
552
553   EmitInstruction(
554       Out, MCInstBuilder(X86::MOVSX32rr8).addReg(X86::EAX).addReg(X86::AL));
555   EmitInstruction(
556       Out, MCInstBuilder(X86::CMP32rr).addReg(X86::ECX).addReg(X86::EAX));
557   EmitInstruction(Out, MCInstBuilder(X86::JL_4).addExpr(DoneExpr));
558
559   EmitCallAsanReport(Ctx, Out, AccessSize, IsWrite);
560   EmitLabel(Out, DoneSym);
561
562   EmitInstruction(Out, MCInstBuilder(X86::POPF64));
563   EmitInstruction(Out, MCInstBuilder(X86::POP64r).addReg(X86::RDI));
564   EmitInstruction(Out, MCInstBuilder(X86::POP64r).addReg(X86::RCX));
565   EmitInstruction(Out, MCInstBuilder(X86::POP64r).addReg(X86::RAX));
566   EmitAdjustRSP(Ctx, Out, 128);
567 }
568
569 void X86AddressSanitizer64::InstrumentMemOperandLargeImpl(X86Operand &Op,
570                                                           unsigned AccessSize,
571                                                           bool IsWrite,
572                                                           MCContext &Ctx,
573                                                           MCStreamer &Out) {
574   EmitAdjustRSP(Ctx, Out, -128);
575   EmitInstruction(Out, MCInstBuilder(X86::PUSH64r).addReg(X86::RAX));
576   EmitInstruction(Out, MCInstBuilder(X86::PUSHF64));
577
578   {
579     MCInst Inst;
580     Inst.setOpcode(X86::LEA64r);
581     Inst.addOperand(MCOperand::CreateReg(X86::RAX));
582     Op.addMemOperands(Inst, 5);
583     EmitInstruction(Out, Inst);
584   }
585   EmitInstruction(
586       Out,
587       MCInstBuilder(X86::SHR64ri).addReg(X86::RAX).addReg(X86::RAX).addImm(3));
588   {
589     MCInst Inst;
590     switch (AccessSize) {
591     case 8:
592       Inst.setOpcode(X86::CMP8mi);
593       break;
594     case 16:
595       Inst.setOpcode(X86::CMP16mi);
596       break;
597     default:
598       assert(false && "Incorrect access size");
599       break;
600     }
601     const MCExpr *Disp = MCConstantExpr::Create(kShadowOffset, Ctx);
602     std::unique_ptr<X86Operand> Op(
603         X86Operand::CreateMem(0, Disp, X86::RAX, 0, 1, SMLoc(), SMLoc()));
604     Op->addMemOperands(Inst, 5);
605     Inst.addOperand(MCOperand::CreateImm(0));
606     EmitInstruction(Out, Inst);
607   }
608
609   MCSymbol *DoneSym = Ctx.CreateTempSymbol();
610   const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx);
611   EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr));
612
613   EmitCallAsanReport(Ctx, Out, AccessSize, IsWrite);
614   EmitLabel(Out, DoneSym);
615
616   EmitInstruction(Out, MCInstBuilder(X86::POPF64));
617   EmitInstruction(Out, MCInstBuilder(X86::POP64r).addReg(X86::RAX));
618   EmitAdjustRSP(Ctx, Out, 128);
619 }
620
621 void X86AddressSanitizer64::InstrumentMOVSImpl(unsigned AccessSize,
622                                                MCContext &Ctx,
623                                                MCStreamer &Out) {
624   EmitInstruction(Out, MCInstBuilder(X86::PUSHF64));
625
626   // No need to test when RCX is equals to zero.
627   MCSymbol *DoneSym = Ctx.CreateTempSymbol();
628   const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx);
629   EmitInstruction(
630       Out, MCInstBuilder(X86::TEST64rr).addReg(X86::RCX).addReg(X86::RCX));
631   EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr));
632
633   // Instrument first and last elements in src and dst range.
634   InstrumentMOVSBase(X86::RDI /* DstReg */, X86::RSI /* SrcReg */,
635                      X86::RCX /* CntReg */, AccessSize, Ctx, Out);
636
637   EmitLabel(Out, DoneSym);
638   EmitInstruction(Out, MCInstBuilder(X86::POPF64));
639 }
640
641 } // End anonymous namespace
642
643 X86AsmInstrumentation::X86AsmInstrumentation(const MCSubtargetInfo &STI)
644     : STI(STI) {}
645
646 X86AsmInstrumentation::~X86AsmInstrumentation() {}
647
648 void X86AsmInstrumentation::InstrumentAndEmitInstruction(
649     const MCInst &Inst, OperandVector &Operands, MCContext &Ctx,
650     const MCInstrInfo &MII, MCStreamer &Out) {
651   EmitInstruction(Out, Inst);
652 }
653
654 void X86AsmInstrumentation::EmitInstruction(MCStreamer &Out,
655                                             const MCInst &Inst) {
656   Out.EmitInstruction(Inst, STI);
657 }
658
659 X86AsmInstrumentation *
660 CreateX86AsmInstrumentation(const MCTargetOptions &MCOptions,
661                             const MCContext &Ctx, const MCSubtargetInfo &STI) {
662   Triple T(STI.getTargetTriple());
663   const bool hasCompilerRTSupport = T.isOSLinux();
664   if (ClAsanInstrumentAssembly && hasCompilerRTSupport &&
665       MCOptions.SanitizeAddress) {
666     if ((STI.getFeatureBits() & X86::Mode32Bit) != 0)
667       return new X86AddressSanitizer32(STI);
668     if ((STI.getFeatureBits() & X86::Mode64Bit) != 0)
669       return new X86AddressSanitizer64(STI);
670   }
671   return new X86AsmInstrumentation(STI);
672 }
673
674 } // End llvm namespace