diff options
Diffstat (limited to 'lib/Target/X86/AsmParser/X86AsmInstrumentation.cpp')
-rw-r--r-- | lib/Target/X86/AsmParser/X86AsmInstrumentation.cpp | 122 |
1 files changed, 70 insertions, 52 deletions
diff --git a/lib/Target/X86/AsmParser/X86AsmInstrumentation.cpp b/lib/Target/X86/AsmParser/X86AsmInstrumentation.cpp index db292284b5..f3e6b3f419 100644 --- a/lib/Target/X86/AsmParser/X86AsmInstrumentation.cpp +++ b/lib/Target/X86/AsmParser/X86AsmInstrumentation.cpp @@ -11,21 +11,25 @@ #include "X86AsmInstrumentation.h" #include "X86Operand.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/Triple.h" +#include "llvm/IR/Function.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCInstBuilder.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCParser/MCParsedAsmOperand.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/MC/MCTargetOptions.h" #include "llvm/Support/CommandLine.h" -#include "llvm/Support/Compiler.h" -#include "llvm/MC/MCParser/MCParsedAsmOperand.h" namespace llvm { namespace { -static cl::opt<bool> ClAsanInstrumentInlineAssembly( - "asan-instrument-inline-assembly", cl::desc("instrument inline assembly"), - cl::Hidden, cl::init(false)); +static cl::opt<bool> ClAsanInstrumentAssembly( + "asan-instrument-assembly", + cl::desc("instrument assembly with AddressSanitizer checks"), cl::Hidden, + cl::init(false)); bool IsStackReg(unsigned Reg) { return Reg == X86::RSP || Reg == X86::ESP || Reg == X86::SP; @@ -38,14 +42,14 @@ std::string FuncName(unsigned AccessSize, bool IsWrite) { class X86AddressSanitizer : public X86AsmInstrumentation { public: - X86AddressSanitizer(MCSubtargetInfo &sti) : STI(sti) {} + X86AddressSanitizer(const MCSubtargetInfo &STI) : STI(STI) {} virtual ~X86AddressSanitizer() {} // X86AsmInstrumentation implementation: virtual void InstrumentInstruction( const MCInst &Inst, SmallVectorImpl<MCParsedAsmOperand *> &Operands, - MCContext &Ctx, MCStreamer &Out) override { - InstrumentMOV(Inst, Operands, Ctx, Out); + MCContext &Ctx, const MCInstrInfo &MII, MCStreamer &Out) override { + InstrumentMOV(Inst, Operands, Ctx, MII, Out); } // Should be implemented differently in x86_32 and x86_64 subclasses. @@ -57,13 +61,13 @@ public: bool IsWrite, MCContext &Ctx, MCStreamer &Out); void InstrumentMOV(const MCInst &Inst, SmallVectorImpl<MCParsedAsmOperand *> &Operands, - MCContext &Ctx, MCStreamer &Out); + MCContext &Ctx, const MCInstrInfo &MII, MCStreamer &Out); void EmitInstruction(MCStreamer &Out, const MCInst &Inst) { Out.EmitInstruction(Inst, STI); } protected: - MCSubtargetInfo &STI; + const MCSubtargetInfo &STI; }; void X86AddressSanitizer::InstrumentMemOperand( @@ -83,68 +87,53 @@ void X86AddressSanitizer::InstrumentMemOperand( void X86AddressSanitizer::InstrumentMOV( const MCInst &Inst, SmallVectorImpl<MCParsedAsmOperand *> &Operands, - MCContext &Ctx, MCStreamer &Out) { + MCContext &Ctx, const MCInstrInfo &MII, MCStreamer &Out) { // Access size in bytes. unsigned AccessSize = 0; - unsigned long OpIx = Operands.size(); + switch (Inst.getOpcode()) { case X86::MOV8mi: case X86::MOV8mr: - AccessSize = 1; - OpIx = 2; - break; case X86::MOV8rm: AccessSize = 1; - OpIx = 1; break; case X86::MOV16mi: case X86::MOV16mr: - AccessSize = 2; - OpIx = 2; - break; case X86::MOV16rm: AccessSize = 2; - OpIx = 1; break; case X86::MOV32mi: case X86::MOV32mr: - AccessSize = 4; - OpIx = 2; - break; case X86::MOV32rm: AccessSize = 4; - OpIx = 1; break; case X86::MOV64mi32: case X86::MOV64mr: - AccessSize = 8; - OpIx = 2; - break; case X86::MOV64rm: AccessSize = 8; - OpIx = 1; break; case X86::MOVAPDmr: case X86::MOVAPSmr: - AccessSize = 16; - OpIx = 2; - break; case X86::MOVAPDrm: case X86::MOVAPSrm: AccessSize = 16; - OpIx = 1; break; - } - if (OpIx >= Operands.size()) + default: return; + } - const bool IsWrite = (OpIx != 1); - InstrumentMemOperand(Operands[OpIx], AccessSize, IsWrite, Ctx, Out); + const bool IsWrite = MII.get(Inst.getOpcode()).mayStore(); + for (unsigned Ix = 0; Ix < Operands.size(); ++Ix) { + MCParsedAsmOperand *Op = Operands[Ix]; + if (Op && Op->isMem()) + InstrumentMemOperand(Op, AccessSize, IsWrite, Ctx, Out); + } } class X86AddressSanitizer32 : public X86AddressSanitizer { public: - X86AddressSanitizer32(MCSubtargetInfo &sti) : X86AddressSanitizer(sti) {} + X86AddressSanitizer32(const MCSubtargetInfo &STI) + : X86AddressSanitizer(STI) {} virtual ~X86AddressSanitizer32() {} virtual void InstrumentMemOperandImpl(X86Operand *Op, unsigned AccessSize, @@ -172,14 +161,14 @@ void X86AddressSanitizer32::InstrumentMemOperandImpl( MCSymbolRefExpr::Create(FuncSym, MCSymbolRefExpr::VK_PLT, Ctx); EmitInstruction(Out, MCInstBuilder(X86::CALLpcrel32).addExpr(FuncExpr)); } - EmitInstruction(Out, MCInstBuilder(X86::ADD32ri).addReg(X86::ESP) - .addReg(X86::ESP).addImm(4)); + EmitInstruction(Out, MCInstBuilder(X86::POP32r).addReg(X86::EAX)); EmitInstruction(Out, MCInstBuilder(X86::POP32r).addReg(X86::EAX)); } class X86AddressSanitizer64 : public X86AddressSanitizer { public: - X86AddressSanitizer64(MCSubtargetInfo &sti) : X86AddressSanitizer(sti) {} + X86AddressSanitizer64(const MCSubtargetInfo &STI) + : X86AddressSanitizer(STI) {} virtual ~X86AddressSanitizer64() {} virtual void InstrumentMemOperandImpl(X86Operand *Op, unsigned AccessSize, @@ -187,13 +176,26 @@ public: MCStreamer &Out) override; }; -void X86AddressSanitizer64::InstrumentMemOperandImpl( - X86Operand *Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx, - MCStreamer &Out) { +void X86AddressSanitizer64::InstrumentMemOperandImpl(X86Operand *Op, + unsigned AccessSize, + bool IsWrite, + MCContext &Ctx, + MCStreamer &Out) { // FIXME: emit .cfi directives for correct stack unwinding. - // Set %rsp below current red zone (128 bytes wide) - EmitInstruction(Out, MCInstBuilder(X86::SUB64ri32).addReg(X86::RSP) - .addReg(X86::RSP).addImm(128)); + + // Set %rsp below current red zone (128 bytes wide) using LEA instruction to + // preserve flags. + { + MCInst Inst; + Inst.setOpcode(X86::LEA64r); + Inst.addOperand(MCOperand::CreateReg(X86::RSP)); + + const MCExpr *Disp = MCConstantExpr::Create(-128, Ctx); + std::unique_ptr<X86Operand> Op( + X86Operand::CreateMem(0, Disp, X86::RSP, 0, 1, SMLoc(), SMLoc())); + Op->addMemOperands(Inst, 5); + EmitInstruction(Out, Inst); + } EmitInstruction(Out, MCInstBuilder(X86::PUSH64r).addReg(X86::RDI)); { MCInst Inst; @@ -210,8 +212,19 @@ void X86AddressSanitizer64::InstrumentMemOperandImpl( EmitInstruction(Out, MCInstBuilder(X86::CALL64pcrel32).addExpr(FuncExpr)); } EmitInstruction(Out, MCInstBuilder(X86::POP64r).addReg(X86::RDI)); - EmitInstruction(Out, MCInstBuilder(X86::ADD64ri32).addReg(X86::RSP) - .addReg(X86::RSP).addImm(128)); + + // Restore old %rsp value. + { + MCInst Inst; + Inst.setOpcode(X86::LEA64r); + Inst.addOperand(MCOperand::CreateReg(X86::RSP)); + + const MCExpr *Disp = MCConstantExpr::Create(128, Ctx); + std::unique_ptr<X86Operand> Op( + X86Operand::CreateMem(0, Disp, X86::RSP, 0, 1, SMLoc(), SMLoc())); + Op->addMemOperands(Inst, 5); + EmitInstruction(Out, Inst); + } } } // End anonymous namespace @@ -221,10 +234,15 @@ X86AsmInstrumentation::~X86AsmInstrumentation() {} void X86AsmInstrumentation::InstrumentInstruction( const MCInst &Inst, SmallVectorImpl<MCParsedAsmOperand *> &Operands, - MCContext &Ctx, MCStreamer &Out) {} - -X86AsmInstrumentation *CreateX86AsmInstrumentation(MCSubtargetInfo &STI) { - if (ClAsanInstrumentInlineAssembly) { + MCContext &Ctx, const MCInstrInfo &MII, MCStreamer &Out) {} + +X86AsmInstrumentation * +CreateX86AsmInstrumentation(const MCTargetOptions &MCOptions, + const MCContext &Ctx, const MCSubtargetInfo &STI) { + Triple T(STI.getTargetTriple()); + const bool hasCompilerRTSupport = T.isOSLinux(); + if (ClAsanInstrumentAssembly && hasCompilerRTSupport && + MCOptions.SanitizeAddress) { if ((STI.getFeatureBits() & X86::Mode32Bit) != 0) return new X86AddressSanitizer32(STI); if ((STI.getFeatureBits() & X86::Mode64Bit) != 0) |