mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-04-05 17:39:16 +00:00
[asan] Generate asm instrumentation in MC.
Generate entire ASan asm instrumentation in MC without relying on runtime helper functions. Patch by Yuri Gorshenin. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@212455 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
e3bf8ea879
commit
5ba71b01d8
@ -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 {
|
||||
@ -47,17 +47,19 @@ public:
|
||||
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 @@ public:
|
||||
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 @@ 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;
|
||||
|
||||
@ -136,22 +142,46 @@ 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);
|
||||
@ -159,50 +189,175 @@ void X86AddressSanitizer32::InstrumentMemOperandImpl(X86Operand &Op,
|
||||
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;
|
||||
};
|
||||
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;
|
||||
|
||||
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) 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);
|
||||
@ -210,27 +365,119 @@ void X86AddressSanitizer64::InstrumentMemOperandImpl(X86Operand &Op,
|
||||
Op.addMemOperands(Inst, 5);
|
||||
EmitInstruction(Out, Inst);
|
||||
}
|
||||
{
|
||||
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));
|
||||
}
|
||||
EmitInstruction(Out, MCInstBuilder(X86::POP64r).addReg(X86::RDI));
|
||||
|
||||
// Restore old %rsp value.
|
||||
EmitInstruction(
|
||||
Out, MCInstBuilder(X86::MOV64rr).addReg(X86::RAX).addReg(X86::RDI));
|
||||
EmitInstruction(Out, MCInstBuilder(X86::SHR64ri).addReg(X86::RAX)
|
||||
.addReg(X86::RAX).addImm(3));
|
||||
{
|
||||
MCInst Inst;
|
||||
Inst.setOpcode(X86::LEA64r);
|
||||
Inst.addOperand(MCOperand::CreateReg(X86::RSP));
|
||||
|
||||
const MCExpr *Disp = MCConstantExpr::Create(128, Ctx);
|
||||
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::RSP, 0, 1, SMLoc(), SMLoc()));
|
||||
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));
|
||||
|
||||
{
|
||||
MCInst Inst;
|
||||
Inst.setOpcode(X86::LEA64r);
|
||||
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::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 @@ void X86AddressSanitizer64::InstrumentMemOperandImpl(X86Operand &Op,
|
||||
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,
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
@ -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 {
|
||||
@ -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 {
|
||||
@ -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 {{.*}}, {{.*}}
|
||||
@ -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 {
|
||||
|
@ -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 @@ 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
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user