371 changes: 308 additions & 63 deletions llvm/lib/Target/X86/AsmParser/X86AsmInstrumentation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ bool IsStackReg(unsigned Reg) {
}

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 {
Expand All @@ -47,17 +47,19 @@ class X86AddressSanitizer : public X86AsmInstrumentation {
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);
Expand All @@ -67,14 +69,15 @@ class X86AddressSanitizer : public X86AsmInstrumentation {
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.");
Expand All @@ -84,13 +87,16 @@ void X86AddressSanitizer::InstrumentMemOperand(MCParsedAsmOperand &Op,
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;

Expand Down Expand Up @@ -136,113 +142,352 @@ void X86AddressSanitizer::InstrumentMOV(const MCInst &Inst,

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);
Inst.addOperand(MCOperand::CreateReg(X86::EAX));
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<X86Operand> 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<X86Operand> 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<X86Operand> 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<X86Operand> 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);
Inst.addOperand(MCOperand::CreateReg(X86::RDI));
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<X86Operand> 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<X86Operand> 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<X86Operand> 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

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,
Expand Down
8 changes: 4 additions & 4 deletions llvm/test/Instrumentation/AddressSanitizer/X86/asm_attr.ll
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@ target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
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
Expand Down
111 changes: 67 additions & 44 deletions llvm/test/Instrumentation/AddressSanitizer/X86/asm_mov.ll
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,35 @@ target triple = "x86_64-unknown-linux-gnu"

; 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 {
Expand All @@ -27,18 +44,14 @@ entry:

; 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 {
Expand All @@ -49,18 +62,14 @@ entry:

; 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 {
Expand All @@ -71,17 +80,35 @@ entry:

; 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 {{.*}}, {{.*}}
Expand All @@ -93,18 +120,14 @@ entry:

; 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 {
Expand Down
28 changes: 8 additions & 20 deletions llvm/test/Instrumentation/AddressSanitizer/X86/asm_mov.s
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -42,20 +36,14 @@ mov1b: # @mov1b
# 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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
30 changes: 9 additions & 21 deletions llvm/test/Instrumentation/AddressSanitizer/X86/asm_swap_intel.s
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down