Index: lib/Target/X86/AsmParser/X86AsmInstrumentation.cpp =================================================================== --- lib/Target/X86/AsmParser/X86AsmInstrumentation.cpp +++ lib/Target/X86/AsmParser/X86AsmInstrumentation.cpp @@ -37,8 +37,8 @@ } std::string FuncName(unsigned AccessSize, bool IsWrite) { - return std::string("__sanitizer_sanitize_") + (IsWrite ? "store" : "load") + - (utostr(AccessSize)); + return std::string("__asan_report_") + (IsWrite ? "store" : "load") + + utostr(AccessSize); } class X86AddressSanitizer : public X86AsmInstrumentation { @@ -47,17 +47,19 @@ virtual ~X86AddressSanitizer() {} // X86AsmInstrumentation implementation: - virtual void InstrumentInstruction(const MCInst &Inst, - OperandVector &Operands, MCContext &Ctx, - const MCInstrInfo &MII, - MCStreamer &Out) override { + virtual void InstrumentInstruction( + const MCInst &Inst, OperandVector &Operands, 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. - virtual void InstrumentMemOperandImpl(X86Operand &Op, unsigned AccessSize, - bool IsWrite, MCContext &Ctx, - MCStreamer &Out) = 0; + virtual void InstrumentMemOperandSmallImpl( + X86Operand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx, + MCStreamer &Out) = 0; + virtual void InstrumentMemOperandLargeImpl( + X86Operand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx, + MCStreamer &Out) = 0; void InstrumentMemOperand(MCParsedAsmOperand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx, MCStreamer &Out); @@ -67,14 +69,15 @@ Out.EmitInstruction(Inst, STI); } + void EmitLabel(MCStreamer &Out, MCSymbol *Label) { Out.EmitLabel(Label); } + protected: const MCSubtargetInfo &STI; }; -void X86AddressSanitizer::InstrumentMemOperand(MCParsedAsmOperand &Op, - unsigned AccessSize, - bool IsWrite, MCContext &Ctx, - MCStreamer &Out) { +void X86AddressSanitizer::InstrumentMemOperand( + MCParsedAsmOperand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx, + MCStreamer &Out) { assert(Op.isMem() && "Op should be a memory operand."); assert((AccessSize & (AccessSize - 1)) == 0 && AccessSize <= 16 && "AccessSize should be a power of two, less or equal than 16."); @@ -84,13 +87,16 @@ if (IsStackReg(MemOp.getMemBaseReg()) || IsStackReg(MemOp.getMemIndexReg())) return; - InstrumentMemOperandImpl(MemOp, AccessSize, IsWrite, Ctx, Out); + // FIXME: take into account load/store alignment. + if (AccessSize < 8) + InstrumentMemOperandSmallImpl(MemOp, AccessSize, IsWrite, Ctx, Out); + else + InstrumentMemOperandLargeImpl(MemOp, AccessSize, IsWrite, Ctx, Out); } -void X86AddressSanitizer::InstrumentMOV(const MCInst &Inst, - OperandVector &Operands, MCContext &Ctx, - const MCInstrInfo &MII, - MCStreamer &Out) { +void X86AddressSanitizer::InstrumentMOV( + const MCInst &Inst, OperandVector &Operands, MCContext &Ctx, + const MCInstrInfo &MII, MCStreamer &Out) { // Access size in bytes. unsigned AccessSize = 0; @@ -136,22 +142,46 @@ class X86AddressSanitizer32 : public X86AddressSanitizer { public: + static const long kShadowOffset = 0x20000000; + X86AddressSanitizer32(const MCSubtargetInfo &STI) : X86AddressSanitizer(STI) {} virtual ~X86AddressSanitizer32() {} - virtual void InstrumentMemOperandImpl(X86Operand &Op, unsigned AccessSize, - bool IsWrite, MCContext &Ctx, - MCStreamer &Out) override; + virtual void InstrumentMemOperandSmallImpl( + X86Operand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx, + MCStreamer &Out) override; + virtual void InstrumentMemOperandLargeImpl( + X86Operand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx, + MCStreamer &Out) override; + + private: + void EmitCallAsanReport(MCContext &Ctx, MCStreamer &Out, unsigned AccessSize, + bool IsWrite, unsigned AddressReg) { + EmitInstruction(Out, MCInstBuilder(X86::CLD)); + EmitInstruction(Out, MCInstBuilder(X86::MMX_EMMS)); + + EmitInstruction(Out, MCInstBuilder(X86::AND64ri8).addReg(X86::ESP) + .addReg(X86::ESP).addImm(-16)); + EmitInstruction(Out, MCInstBuilder(X86::PUSH32r).addReg(AddressReg)); + + + const std::string& Fn = FuncName(AccessSize, IsWrite); + MCSymbol *FnSym = Ctx.GetOrCreateSymbol(StringRef(Fn)); + const MCSymbolRefExpr *FnExpr = + MCSymbolRefExpr::Create(FnSym, MCSymbolRefExpr::VK_PLT, Ctx); + EmitInstruction(Out, MCInstBuilder(X86::CALLpcrel32).addExpr(FnExpr)); + } }; -void X86AddressSanitizer32::InstrumentMemOperandImpl(X86Operand &Op, - unsigned AccessSize, - bool IsWrite, - MCContext &Ctx, - MCStreamer &Out) { - // FIXME: emit .cfi directives for correct stack unwinding. +void X86AddressSanitizer32::InstrumentMemOperandSmallImpl( + X86Operand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx, + MCStreamer &Out) { EmitInstruction(Out, MCInstBuilder(X86::PUSH32r).addReg(X86::EAX)); + EmitInstruction(Out, MCInstBuilder(X86::PUSH32r).addReg(X86::ECX)); + EmitInstruction(Out, MCInstBuilder(X86::PUSH32r).addReg(X86::EDX)); + EmitInstruction(Out, MCInstBuilder(X86::PUSHF32)); + { MCInst Inst; Inst.setOpcode(X86::LEA32r); @@ -159,50 +189,175 @@ Op.addMemOperands(Inst, 5); EmitInstruction(Out, Inst); } - EmitInstruction(Out, MCInstBuilder(X86::PUSH32r).addReg(X86::EAX)); + + EmitInstruction( + Out, MCInstBuilder(X86::MOV32rr).addReg(X86::ECX).addReg(X86::EAX)); + EmitInstruction(Out, MCInstBuilder(X86::SHR32ri).addReg(X86::ECX) + .addReg(X86::ECX).addImm(3)); + { - const std::string Func = FuncName(AccessSize, IsWrite); - const MCSymbol *FuncSym = Ctx.GetOrCreateSymbol(StringRef(Func)); - const MCSymbolRefExpr *FuncExpr = - MCSymbolRefExpr::Create(FuncSym, MCSymbolRefExpr::VK_PLT, Ctx); - EmitInstruction(Out, MCInstBuilder(X86::CALLpcrel32).addExpr(FuncExpr)); + MCInst Inst; + Inst.setOpcode(X86::MOV8rm); + Inst.addOperand(MCOperand::CreateReg(X86::CL)); + const MCExpr *Disp = MCConstantExpr::Create(kShadowOffset, Ctx); + std::unique_ptr Op( + X86Operand::CreateMem(0, Disp, X86::ECX, 0, 1, SMLoc(), SMLoc())); + Op->addMemOperands(Inst, 5); + EmitInstruction(Out, Inst); + } + + EmitInstruction(Out, + MCInstBuilder(X86::TEST8rr).addReg(X86::CL).addReg(X86::CL)); + MCSymbol *DoneSym = Ctx.CreateTempSymbol(); + const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx); + EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr)); + + EmitInstruction( + Out, MCInstBuilder(X86::MOV32rr).addReg(X86::EDX).addReg(X86::EAX)); + EmitInstruction(Out, MCInstBuilder(X86::AND32ri).addReg(X86::EDX) + .addReg(X86::EDX).addImm(7)); + + switch (AccessSize) { + case 1: + break; + case 2: { + MCInst Inst; + Inst.setOpcode(X86::LEA32r); + Inst.addOperand(MCOperand::CreateReg(X86::EDX)); + + const MCExpr *Disp = MCConstantExpr::Create(1, Ctx); + std::unique_ptr Op( + X86Operand::CreateMem(0, Disp, X86::EDX, 0, 1, SMLoc(), SMLoc())); + Op->addMemOperands(Inst, 5); + EmitInstruction(Out, Inst); + break; } + case 4: + EmitInstruction(Out, MCInstBuilder(X86::ADD32ri8).addReg(X86::EDX) + .addReg(X86::EDX).addImm(3)); + break; + default: + assert(false && "Incorrect access size"); + break; + } + + EmitInstruction( + Out, MCInstBuilder(X86::MOVSX32rr8).addReg(X86::ECX).addReg(X86::CL)); + EmitInstruction( + Out, MCInstBuilder(X86::CMP32rr).addReg(X86::EDX).addReg(X86::ECX)); + EmitInstruction(Out, MCInstBuilder(X86::JL_4).addExpr(DoneExpr)); + + EmitCallAsanReport(Ctx, Out, AccessSize, IsWrite, X86::EAX); + EmitLabel(Out, DoneSym); + + EmitInstruction(Out, MCInstBuilder(X86::POPF32)); + EmitInstruction(Out, MCInstBuilder(X86::POP32r).addReg(X86::EDX)); + EmitInstruction(Out, MCInstBuilder(X86::POP32r).addReg(X86::ECX)); EmitInstruction(Out, MCInstBuilder(X86::POP32r).addReg(X86::EAX)); +} + +void X86AddressSanitizer32::InstrumentMemOperandLargeImpl( + X86Operand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx, + MCStreamer &Out) { + EmitInstruction(Out, MCInstBuilder(X86::PUSH32r).addReg(X86::EAX)); + EmitInstruction(Out, MCInstBuilder(X86::PUSH32r).addReg(X86::ECX)); + EmitInstruction(Out, MCInstBuilder(X86::PUSHF32)); + + { + MCInst Inst; + Inst.setOpcode(X86::LEA32r); + Inst.addOperand(MCOperand::CreateReg(X86::EAX)); + Op.addMemOperands(Inst, 5); + EmitInstruction(Out, Inst); + } + EmitInstruction( + Out, MCInstBuilder(X86::MOV32rr).addReg(X86::ECX).addReg(X86::EAX)); + EmitInstruction(Out, MCInstBuilder(X86::SHR32ri).addReg(X86::ECX) + .addReg(X86::ECX).addImm(3)); + { + MCInst Inst; + switch (AccessSize) { + case 8: + Inst.setOpcode(X86::CMP8mi); + break; + case 16: + Inst.setOpcode(X86::CMP16mi); + break; + default: + assert(false && "Incorrect access size"); + break; + } + const MCExpr *Disp = MCConstantExpr::Create(kShadowOffset, Ctx); + std::unique_ptr Op( + X86Operand::CreateMem(0, Disp, X86::ECX, 0, 1, SMLoc(), SMLoc())); + Op->addMemOperands(Inst, 5); + Inst.addOperand(MCOperand::CreateImm(0)); + EmitInstruction(Out, Inst); + } + MCSymbol *DoneSym = Ctx.CreateTempSymbol(); + const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx); + EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr)); + + EmitCallAsanReport(Ctx, Out, AccessSize, IsWrite, X86::EAX); + EmitLabel(Out, DoneSym); + + EmitInstruction(Out, MCInstBuilder(X86::POPF32)); + EmitInstruction(Out, MCInstBuilder(X86::POP32r).addReg(X86::ECX)); EmitInstruction(Out, MCInstBuilder(X86::POP32r).addReg(X86::EAX)); } class X86AddressSanitizer64 : public X86AddressSanitizer { public: + static const long kShadowOffset = 0x7fff8000; + X86AddressSanitizer64(const MCSubtargetInfo &STI) : X86AddressSanitizer(STI) {} virtual ~X86AddressSanitizer64() {} - virtual void InstrumentMemOperandImpl(X86Operand &Op, unsigned AccessSize, - bool IsWrite, MCContext &Ctx, - MCStreamer &Out) override; -}; - -void X86AddressSanitizer64::InstrumentMemOperandImpl(X86Operand &Op, - unsigned AccessSize, - bool IsWrite, - MCContext &Ctx, - MCStreamer &Out) { - // FIXME: emit .cfi directives for correct stack unwinding. + virtual void InstrumentMemOperandSmallImpl( + X86Operand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx, + MCStreamer &Out) override; + virtual void InstrumentMemOperandLargeImpl( + X86Operand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx, + MCStreamer &Out) override; - // Set %rsp below current red zone (128 bytes wide) using LEA instruction to - // preserve flags. - { +private: + void EmitAdjustRSP(MCContext &Ctx, MCStreamer &Out, long Offset) { MCInst Inst; Inst.setOpcode(X86::LEA64r); Inst.addOperand(MCOperand::CreateReg(X86::RSP)); - const MCExpr *Disp = MCConstantExpr::Create(-128, Ctx); + const MCExpr *Disp = MCConstantExpr::Create(Offset, Ctx); std::unique_ptr Op( X86Operand::CreateMem(0, Disp, X86::RSP, 0, 1, SMLoc(), SMLoc())); Op->addMemOperands(Inst, 5); EmitInstruction(Out, Inst); } + + void EmitCallAsanReport(MCContext &Ctx, MCStreamer &Out, unsigned AccessSize, + bool IsWrite) { + EmitInstruction(Out, MCInstBuilder(X86::CLD)); + EmitInstruction(Out, MCInstBuilder(X86::MMX_EMMS)); + + EmitInstruction(Out, MCInstBuilder(X86::AND64ri8).addReg(X86::RSP) + .addReg(X86::RSP).addImm(-16)); + + const std::string& Fn = FuncName(AccessSize, IsWrite); + MCSymbol *FnSym = Ctx.GetOrCreateSymbol(StringRef(Fn)); + const MCSymbolRefExpr *FnExpr = + MCSymbolRefExpr::Create(FnSym, MCSymbolRefExpr::VK_PLT, Ctx); + EmitInstruction(Out, MCInstBuilder(X86::CALL64pcrel32).addExpr(FnExpr)); + } +}; + +void X86AddressSanitizer64::InstrumentMemOperandSmallImpl( + X86Operand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx, + MCStreamer &Out) { + EmitAdjustRSP(Ctx, Out, -128); + EmitInstruction(Out, MCInstBuilder(X86::PUSH64r).addReg(X86::RAX)); + EmitInstruction(Out, MCInstBuilder(X86::PUSH64r).addReg(X86::RCX)); EmitInstruction(Out, MCInstBuilder(X86::PUSH64r).addReg(X86::RDI)); + EmitInstruction(Out, MCInstBuilder(X86::PUSHF64)); { MCInst Inst; Inst.setOpcode(X86::LEA64r); @@ -210,27 +365,119 @@ Op.addMemOperands(Inst, 5); EmitInstruction(Out, Inst); } + EmitInstruction( + Out, MCInstBuilder(X86::MOV64rr).addReg(X86::RAX).addReg(X86::RDI)); + EmitInstruction(Out, MCInstBuilder(X86::SHR64ri).addReg(X86::RAX) + .addReg(X86::RAX).addImm(3)); { - const std::string Func = FuncName(AccessSize, IsWrite); - const MCSymbol *FuncSym = Ctx.GetOrCreateSymbol(StringRef(Func)); - const MCSymbolRefExpr *FuncExpr = - MCSymbolRefExpr::Create(FuncSym, MCSymbolRefExpr::VK_PLT, Ctx); - EmitInstruction(Out, MCInstBuilder(X86::CALL64pcrel32).addExpr(FuncExpr)); + MCInst Inst; + Inst.setOpcode(X86::MOV8rm); + Inst.addOperand(MCOperand::CreateReg(X86::AL)); + const MCExpr *Disp = MCConstantExpr::Create(kShadowOffset, Ctx); + std::unique_ptr Op( + X86Operand::CreateMem(0, Disp, X86::RAX, 0, 1, SMLoc(), SMLoc())); + Op->addMemOperands(Inst, 5); + EmitInstruction(Out, Inst); } + + EmitInstruction(Out, + MCInstBuilder(X86::TEST8rr).addReg(X86::AL).addReg(X86::AL)); + MCSymbol *DoneSym = Ctx.CreateTempSymbol(); + const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx); + EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr)); + + EmitInstruction( + Out, MCInstBuilder(X86::MOV32rr).addReg(X86::ECX).addReg(X86::EDI)); + EmitInstruction(Out, MCInstBuilder(X86::AND32ri).addReg(X86::ECX) + .addReg(X86::ECX).addImm(7)); + + switch (AccessSize) { + case 1: + break; + case 2: { + MCInst Inst; + Inst.setOpcode(X86::LEA32r); + Inst.addOperand(MCOperand::CreateReg(X86::ECX)); + + const MCExpr *Disp = MCConstantExpr::Create(1, Ctx); + std::unique_ptr Op( + X86Operand::CreateMem(0, Disp, X86::ECX, 0, 1, SMLoc(), SMLoc())); + Op->addMemOperands(Inst, 5); + EmitInstruction(Out, Inst); + break; + } + case 4: + EmitInstruction(Out, MCInstBuilder(X86::ADD32ri8).addReg(X86::ECX) + .addReg(X86::ECX).addImm(3)); + break; + default: + assert(false && "Incorrect access size"); + break; + } + + EmitInstruction( + Out, MCInstBuilder(X86::MOVSX32rr8).addReg(X86::EAX).addReg(X86::AL)); + EmitInstruction( + Out, MCInstBuilder(X86::CMP32rr).addReg(X86::ECX).addReg(X86::EAX)); + EmitInstruction(Out, MCInstBuilder(X86::JL_4).addExpr(DoneExpr)); + + EmitCallAsanReport(Ctx, Out, AccessSize, IsWrite); + EmitLabel(Out, DoneSym); + + EmitInstruction(Out, MCInstBuilder(X86::POPF64)); EmitInstruction(Out, MCInstBuilder(X86::POP64r).addReg(X86::RDI)); + EmitInstruction(Out, MCInstBuilder(X86::POP64r).addReg(X86::RCX)); + EmitInstruction(Out, MCInstBuilder(X86::POP64r).addReg(X86::RAX)); + EmitAdjustRSP(Ctx, Out, 128); +} + +void X86AddressSanitizer64::InstrumentMemOperandLargeImpl( + X86Operand &Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx, + MCStreamer &Out) { + EmitAdjustRSP(Ctx, Out, -128); + EmitInstruction(Out, MCInstBuilder(X86::PUSH64r).addReg(X86::RAX)); + EmitInstruction(Out, MCInstBuilder(X86::PUSHF64)); - // Restore old %rsp value. { MCInst Inst; Inst.setOpcode(X86::LEA64r); - Inst.addOperand(MCOperand::CreateReg(X86::RSP)); - - const MCExpr *Disp = MCConstantExpr::Create(128, Ctx); + Inst.addOperand(MCOperand::CreateReg(X86::RAX)); + Op.addMemOperands(Inst, 5); + EmitInstruction(Out, Inst); + } + EmitInstruction(Out, MCInstBuilder(X86::SHR64ri).addReg(X86::RAX) + .addReg(X86::RAX).addImm(3)); + { + MCInst Inst; + switch (AccessSize) { + case 8: + Inst.setOpcode(X86::CMP8mi); + break; + case 16: + Inst.setOpcode(X86::CMP16mi); + break; + default: + assert(false && "Incorrect access size"); + break; + } + const MCExpr *Disp = MCConstantExpr::Create(kShadowOffset, Ctx); std::unique_ptr Op( - X86Operand::CreateMem(0, Disp, X86::RSP, 0, 1, SMLoc(), SMLoc())); + X86Operand::CreateMem(0, Disp, X86::RAX, 0, 1, SMLoc(), SMLoc())); Op->addMemOperands(Inst, 5); + Inst.addOperand(MCOperand::CreateImm(0)); EmitInstruction(Out, Inst); } + + MCSymbol *DoneSym = Ctx.CreateTempSymbol(); + const MCExpr *DoneExpr = MCSymbolRefExpr::Create(DoneSym, Ctx); + EmitInstruction(Out, MCInstBuilder(X86::JE_4).addExpr(DoneExpr)); + + EmitCallAsanReport(Ctx, Out, AccessSize, IsWrite); + EmitLabel(Out, DoneSym); + + EmitInstruction(Out, MCInstBuilder(X86::POPF64)); + EmitInstruction(Out, MCInstBuilder(X86::POP64r).addReg(X86::RAX)); + EmitAdjustRSP(Ctx, Out, 128); } } // End anonymous namespace @@ -238,11 +485,9 @@ X86AsmInstrumentation::X86AsmInstrumentation() {} X86AsmInstrumentation::~X86AsmInstrumentation() {} -void X86AsmInstrumentation::InstrumentInstruction(const MCInst &Inst, - OperandVector &Operands, - MCContext &Ctx, - const MCInstrInfo &MII, - MCStreamer &Out) {} +void X86AsmInstrumentation::InstrumentInstruction( + const MCInst &Inst, OperandVector &Operands, MCContext &Ctx, + const MCInstrInfo &MII, MCStreamer &Out) {} X86AsmInstrumentation * CreateX86AsmInstrumentation(const MCTargetOptions &MCOptions, Index: test/Instrumentation/AddressSanitizer/X86/asm_attr.ll =================================================================== --- test/Instrumentation/AddressSanitizer/X86/asm_attr.ll +++ test/Instrumentation/AddressSanitizer/X86/asm_attr.ll @@ -4,16 +4,16 @@ target triple = "x86_64-unknown-linux-gnu" ; CHECK-LABEL: mov_no_attr -; CHECK-NOT: callq __sanitizer_sanitize_load8@PLT -; CHECK-NOT: callq __sanitizer_sanitize_store8@PLT +; CHECK-NOT: callq __asan_report_load@PLT +; CHECK-NOT: callq __asan_report_store@PLT define void @mov_no_attr(i64* %dst, i64* %src) { tail call void asm sideeffect "movq ($1), %rax \0A\09movq %rax, ($0) \0A\09", "r,r,~{memory},~{rax},~{dirflag},~{fpsr},~{flags}"(i64* %dst, i64* %src) ret void } ; CHECK-LABEL: mov_sanitize -; CHECK: callq __sanitizer_sanitize_load8@PLT -; CHECK: callq __sanitizer_sanitize_store8@PLT +; CHECK: callq __asan_report_load8@PLT +; CHECK: callq __asan_report_store8@PLT define void @mov_sanitize(i64* %dst, i64* %src) sanitize_address { tail call void asm sideeffect "movq ($1), %rax \0A\09movq %rax, ($0) \0A\09", "r,r,~{memory},~{rax},~{dirflag},~{fpsr},~{flags}"(i64* %dst, i64* %src) ret void Index: test/Instrumentation/AddressSanitizer/X86/asm_mov.ll =================================================================== --- test/Instrumentation/AddressSanitizer/X86/asm_mov.ll +++ test/Instrumentation/AddressSanitizer/X86/asm_mov.ll @@ -5,18 +5,35 @@ ; CHECK-LABEL: mov1b ; CHECK: leaq -128(%rsp), %rsp +; CHECK-NEXT: pushq %rax +; CHECK-NEXT: pushq %rcx ; CHECK-NEXT: pushq %rdi +; CHECK-NEXT: pushfq ; CHECK-NEXT: leaq {{.*}}, %rdi -; CHECK-NEXT: callq __sanitizer_sanitize_load1@PLT +; CHECK-NEXT: movq %rdi, %rax +; CHECK-NEXT: shrq $3, %rax +; CHECK-NEXT: movb 2147450880(%rax), %al +; CHECK-NEXT: testb %al, %al +; CHECK-NEXT: je [[A:.*]] +; CHECK-NEXT: movl %edi, %ecx +; CHECK-NEXT: andl $7, %ecx +; CHECK-NEXT: movsbl %al, %eax +; CHECK-NEXT: cmpl %eax, %ecx +; CHECK-NEXT: jl {{.*}} +; CHECK-NEXT: cld +; CHECK-NEXT: emms +; CHECK-NEXT: andq $-16, %rsp +; CHECK-NEXT: callq __asan_report_load1@PLT +; CHECK-NEXT: [[A]]: +; CHECK-NEXT: popfq ; CHECK-NEXT: popq %rdi +; CHECK-NEXT: popq %rcx +; CHECK-NEXT: popq %rax ; CHECK-NEXT: leaq 128(%rsp), %rsp ; CHECK: leaq -128(%rsp), %rsp -; CHECK-NEXT: pushq %rdi -; CHECK-NEXT: leaq {{.*}}, %rdi -; CHECK-NEXT: callq __sanitizer_sanitize_store1@PLT -; CHECK-NEXT: popq %rdi -; CHECK-NEXT: leaq 128(%rsp), %rsp +; CHECK: callq __asan_report_store1@PLT +; CHECK: leaq 128(%rsp), %rsp ; CHECK: movb {{.*}}, {{.*}} define void @mov1b(i8* %dst, i8* %src) #0 { @@ -27,18 +44,14 @@ ; CHECK-LABEL: mov2b ; CHECK: leaq -128(%rsp), %rsp -; CHECK-NEXT: pushq %rdi -; CHECK-NEXT: leaq {{.*}}, %rdi -; CHECK-NEXT: callq __sanitizer_sanitize_load2@PLT -; CHECK-NEXT: popq %rdi -; CHECK-NEXT: leaq 128(%rsp), %rsp +; CHECK: leal 1(%ecx), %ecx +; CHECK: callq __asan_report_load2@PLT +; CHECK: leaq 128(%rsp), %rsp ; CHECK: leaq -128(%rsp), %rsp -; CHECK-NEXT: pushq %rdi -; CHECK-NEXT: leaq {{.*}}, %rdi -; CHECK-NEXT: callq __sanitizer_sanitize_store2@PLT -; CHECK-NEXT: popq %rdi -; CHECK-NEXT: leaq 128(%rsp), %rsp +; CHECK: leal 1(%ecx), %ecx +; CHECK: callq __asan_report_store2@PLT +; CHECK: leaq 128(%rsp), %rsp ; CHECK: movw {{.*}}, {{.*}} define void @mov2b(i16* %dst, i16* %src) #0 { @@ -49,18 +62,14 @@ ; CHECK-LABEL: mov4b ; CHECK: leaq -128(%rsp), %rsp -; CHECK-NEXT: pushq %rdi -; CHECK-NEXT: leaq {{.*}}, %rdi -; CHECK-NEXT: callq __sanitizer_sanitize_load4@PLT -; CHECK-NEXT: popq %rdi -; CHECK-NEXT: leaq 128(%rsp), %rsp +; CHECK: addl $3, %ecx +; CHECK: callq __asan_report_load4@PLT +; CHECK: leaq 128(%rsp), %rsp ; CHECK: leaq -128(%rsp), %rsp -; CHECK-NEXT: pushq %rdi -; CHECK-NEXT: leaq {{.*}}, %rdi -; CHECK-NEXT: callq __sanitizer_sanitize_store4@PLT -; CHECK-NEXT: popq %rdi -; CHECK-NEXT: leaq 128(%rsp), %rsp +; CHECK: addl $3, %ecx +; CHECK: callq __asan_report_store4@PLT +; CHECK: leaq 128(%rsp), %rsp ; CHECK: movl {{.*}}, {{.*}} define void @mov4b(i32* %dst, i32* %src) #0 { @@ -71,17 +80,35 @@ ; CHECK-LABEL: mov8b ; CHECK: leaq -128(%rsp), %rsp -; CHECK-NEXT: pushq %rdi -; CHECK-NEXT: leaq {{.*}}, %rdi -; CHECK-NEXT: callq __sanitizer_sanitize_load8@PLT -; CHECK-NEXT: popq %rdi +; CHECK-NEXT: pushq %rax +; CHECK-NEXT: pushfq +; CHECK-NEXT: leaq {{.*}}, %rax +; CHECK-NEXT: shrq $3, %rax +; CHECK-NEXT: cmpb $0, 2147450880(%rax) +; CHECK-NEXT: je [[A:.*]] +; CHECK-NEXT: cld +; CHECK-NEXT: emms +; CHECK-NEXT: andq $-16, %rsp +; CHECK-NEXT: callq __asan_report_load8@PLT +; CHECK-NEXT: [[A]]: +; CHECK-NEXT: popfq +; CHECK-NEXT: popq %rax ; CHECK-NEXT: leaq 128(%rsp), %rsp ; CHECK: leaq -128(%rsp), %rsp -; CHECK-NEXT: pushq %rdi -; CHECK-NEXT: leaq {{.*}}, %rdi -; CHECK-NEXT: callq __sanitizer_sanitize_store8@PLT -; CHECK-NEXT: popq %rdi +; CHECK-NEXT: pushq %rax +; CHECK-NEXT: pushfq +; CHECK-NEXT: leaq {{.*}}, %rax +; CHECK-NEXT: shrq $3, %rax +; CHECK-NEXT: cmpb $0, 2147450880(%rax) +; CHECK-NEXT: je [[A:.*]] +; CHECK-NEXT: cld +; CHECK-NEXT: emms +; CHECK-NEXT: andq $-16, %rsp +; CHECK-NEXT: callq __asan_report_store8@PLT +; CHECK-NEXT: [[A]]: +; CHECK-NEXT: popfq +; CHECK-NEXT: popq %rax ; CHECK-NEXT: leaq 128(%rsp), %rsp ; CHECK: movq {{.*}}, {{.*}} @@ -93,18 +120,14 @@ ; CHECK-LABEL: mov16b ; CHECK: leaq -128(%rsp), %rsp -; CHECK-NEXT: pushq %rdi -; CHECK-NEXT: leaq {{.*}}, %rdi -; CHECK-NEXT: callq __sanitizer_sanitize_load16@PLT -; CHECK-NEXT: popq %rdi -; CHECK-NEXT: leaq 128(%rsp), %rsp +; CHECK: cmpw $0, 2147450880(%rax) +; CHECK: callq __asan_report_load16@PLT +; CHECK: leaq 128(%rsp), %rsp ; CHECK: leaq -128(%rsp), %rsp -; CHECK-NEXT: pushq %rdi -; CHECK-NEXT: leaq {{.*}}, %rdi -; CHECK-NEXT: callq __sanitizer_sanitize_store16@PLT -; CHECK-NEXT: popq %rdi -; CHECK-NEXT: leaq 128(%rsp), %rsp +; CHECK: cmpw $0, 2147450880(%rax) +; CHECK: callq __asan_report_store16@PLT +; CHECK: leaq 128(%rsp), %rsp ; CHECK: movaps {{.*}}, {{.*}} define void @mov16b(<2 x i64>* %dst, <2 x i64>* %src) #0 { Index: test/Instrumentation/AddressSanitizer/X86/asm_mov.s =================================================================== --- test/Instrumentation/AddressSanitizer/X86/asm_mov.s +++ test/Instrumentation/AddressSanitizer/X86/asm_mov.s @@ -7,20 +7,14 @@ # CHECK-LABEL: mov1b: # # CHECK: leaq -128(%rsp), %rsp -# CHECK-NEXT: pushq %rdi -# CHECK-NEXT: leaq (%rsi), %rdi -# CHECK-NEXT: callq __sanitizer_sanitize_load1@PLT -# CHECK-NEXT: popq %rdi -# CHECK-NEXT: leaq 128(%rsp), %rsp +# CHECK: callq __asan_report_load1@PLT +# CHECK: leaq 128(%rsp), %rsp # # CHECK-NEXT: movb (%rsi), %al # # CHECK-NEXT: leaq -128(%rsp), %rsp -# CHECK-NEXT: pushq %rdi -# CHECK-NEXT: leaq (%rdi), %rdi -# CHECK-NEXT: callq __sanitizer_sanitize_store1@PLT -# CHECK-NEXT: popq %rdi -# CHECK-NEXT: leaq 128(%rsp), %rsp +# CHECK: callq __asan_report_store1@PLT +# CHECK: leaq 128(%rsp), %rsp # # CHECK-NEXT: movb %al, (%rdi) mov1b: # @mov1b @@ -42,20 +36,14 @@ # CHECK-LABEL: mov16b: # # CHECK: leaq -128(%rsp), %rsp -# CHECK-NEXT: pushq %rdi -# CHECK-NEXT: leaq (%rsi), %rdi -# CHECK-NEXT: callq __sanitizer_sanitize_load16@PLT -# CHECK-NEXT: popq %rdi -# CHECK-NEXT: leaq 128(%rsp), %rsp +# CHECK: callq __asan_report_load16@PLT +# CHECK: leaq 128(%rsp), %rsp # # CHECK-NEXT: movaps (%rsi), %xmm0 # # CHECK-NEXT: leaq -128(%rsp), %rsp -# CHECK-NEXT: pushq %rdi -# CHECK-NEXT: leaq (%rdi), %rdi -# CHECK-NEXT: callq __sanitizer_sanitize_store16@PLT -# CHECK-NEXT: popq %rdi -# CHECK-NEXT: leaq 128(%rsp), %rsp +# CHECK: callq __asan_report_store16@PLT +# CHECK: leaq 128(%rsp), %rsp # # CHECK-NEXT: movaps %xmm0, (%rdi) mov16b: # @mov16b Index: test/Instrumentation/AddressSanitizer/X86/asm_mov_no_instrumentation.s =================================================================== --- test/Instrumentation/AddressSanitizer/X86/asm_mov_no_instrumentation.s +++ test/Instrumentation/AddressSanitizer/X86/asm_mov_no_instrumentation.s @@ -5,8 +5,8 @@ .align 16, 0x90 .type mov1b,@function # CHECK-LABEL: mov1b -# CHECK-NOT: callq __sanitizer_sanitize_load1@PLT -# CHECK-NOT: callq __sanitizer_sanitize_store1@PLT +# CHECK-NOT: callq __asan_report_load1@PLT +# CHECK-NOT: callq __asan_report_store1@PLT mov1b: # @mov1b .cfi_startproc # BB#0: Index: test/Instrumentation/AddressSanitizer/X86/asm_swap_intel.s =================================================================== --- test/Instrumentation/AddressSanitizer/X86/asm_swap_intel.s +++ test/Instrumentation/AddressSanitizer/X86/asm_swap_intel.s @@ -7,38 +7,26 @@ # CHECK-LABEL: swap: # # CHECK: leaq -128(%rsp), %rsp -# CHECK-NEXT: pushq %rdi -# CHECK-NEXT: leaq (%rcx), %rdi -# CHECK-NEXT: callq __sanitizer_sanitize_load8@PLT -# CHECK-NEXT: popq %rdi -# CHECK-NEXT: leaq 128(%rsp), %rsp +# CHECK: callq __asan_report_load8@PLT +# CHECK: leaq 128(%rsp), %rsp # # CHECK-NEXT: movq (%rcx), %rax # # CHECK-NEXT: leaq -128(%rsp), %rsp -# CHECK-NEXT: pushq %rdi -# CHECK-NEXT: leaq (%rdx), %rdi -# CHECK-NEXT: callq __sanitizer_sanitize_load8@PLT -# CHECK-NEXT: popq %rdi -# CHECK-NEXT: leaq 128(%rsp), %rsp +# CHECK: callq __asan_report_load8@PLT +# CHECK: leaq 128(%rsp), %rsp # # CHECK-NEXT: movq (%rdx), %rbx # -# CHECK: leaq -128(%rsp), %rsp -# CHECK-NEXT: pushq %rdi -# CHECK-NEXT: leaq (%rcx), %rdi -# CHECK-NEXT: callq __sanitizer_sanitize_store8@PLT -# CHECK-NEXT: popq %rdi -# CHECK-NEXT: leaq 128(%rsp), %rsp +# CHECK-NEXT: leaq -128(%rsp), %rsp +# CHECK: callq __asan_report_store8@PLT +# CHECK: leaq 128(%rsp), %rsp # # CHECK-NEXT: movq %rbx, (%rcx) # # CHECK-NEXT: leaq -128(%rsp), %rsp -# CHECK-NEXT: pushq %rdi -# CHECK-NEXT: leaq (%rdx), %rdi -# CHECK-NEXT: callq __sanitizer_sanitize_store8@PLT -# CHECK-NEXT: popq %rdi -# CHECK-NEXT: leaq 128(%rsp), %rsp +# CHECK: callq __asan_report_store8@PLT +# CHECK: leaq 128(%rsp), %rsp # # CHECK-NEXT: movq %rax, (%rdx) swap: # @swap