Index: lib/Target/X86/AsmParser/X86AsmInstrumentation.cpp =================================================================== --- lib/Target/X86/AsmParser/X86AsmInstrumentation.cpp +++ lib/Target/X86/AsmParser/X86AsmInstrumentation.cpp @@ -27,6 +27,8 @@ #include "llvm/MC/MCTargetOptions.h" #include "llvm/Support/CommandLine.h" #include +#include +#include namespace llvm { namespace { @@ -58,6 +60,16 @@ utostr(AccessSize); } +unsigned ChooseFrameRegister(const std::vector &BusyRegs) { + static const unsigned Candidates[] = { X86::RBP, X86::RAX, X86::RBX, X86::RCX, + X86::RDX, X86::RDI, X86::RSI }; + for (unsigned Reg : Candidates) { + if (!std::count(BusyRegs.begin(), BusyRegs.end(), Reg)) + return Reg; + } + return X86::NoRegister; +} + class X86AddressSanitizer : public X86AsmInstrumentation { public: struct RegisterContext { @@ -106,12 +118,14 @@ } // Adjusts up stack and saves all registers used in instrumentation. - virtual void InstrumentMemOperandPrologue(const RegisterContext &RegCtx, + virtual void InstrumentMemOperandPrologue(unsigned LocalFrameReg, + const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) = 0; // Restores all registers used in instrumentation and adjusts stack. - virtual void InstrumentMemOperandEpilogue(const RegisterContext &RegCtx, + virtual void InstrumentMemOperandEpilogue(unsigned LocalFrameReg, + const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) = 0; @@ -192,7 +206,13 @@ ? X86::RBX : X86::NoRegister /* ScratchReg */); - InstrumentMemOperandPrologue(RegCtx, Ctx, Out); + unsigned LocalFrameReg = ChooseFrameRegister( + std::vector{ X86::RDX, X86::RAX, X86::RBX, + getX86SubSuperRegister(DstReg, MVT::i64), + getX86SubSuperRegister(SrcReg, MVT::i64), + getX86SubSuperRegister(CntReg, MVT::i64) }); + assert(LocalFrameReg != X86::NoRegister); + InstrumentMemOperandPrologue(LocalFrameReg, RegCtx, Ctx, Out); // Test (%SrcReg) { @@ -228,7 +248,7 @@ InstrumentMemOperand(*Op, AccessSize, true /* IsWrite */, RegCtx, Ctx, Out); } - InstrumentMemOperandEpilogue(RegCtx, Ctx, Out); + InstrumentMemOperandEpilogue(LocalFrameReg, RegCtx, Ctx, Out); } void X86AddressSanitizer::InstrumentMOVS(const MCInst &Inst, @@ -307,9 +327,21 @@ MCParsedAsmOperand &Op = *Operands[Ix]; if (Op.isMem()) { X86Operand &MemOp = static_cast(Op); - InstrumentMemOperandPrologue(RegCtx, Ctx, Out); + std::vector BusyRegs = { RegCtx.AddressReg, RegCtx.ShadowReg, + RegCtx.ScratchReg }; + if (MemOp.getMemBaseReg() != X86::NoRegister) { + BusyRegs.push_back( + getX86SubSuperRegister(MemOp.getMemBaseReg(), MVT::i64)); + } + if (MemOp.getMemIndexReg() != X86::NoRegister) { + BusyRegs.push_back( + getX86SubSuperRegister(MemOp.getMemIndexReg(), MVT::i64)); + } + unsigned LocalFrameReg = ChooseFrameRegister(BusyRegs); + assert(LocalFrameReg != X86::NoRegister); + InstrumentMemOperandPrologue(LocalFrameReg, RegCtx, Ctx, Out); InstrumentMemOperand(MemOp, AccessSize, IsWrite, RegCtx, Ctx, Out); - InstrumentMemOperandEpilogue(RegCtx, Ctx, Out); + InstrumentMemOperandEpilogue(LocalFrameReg, RegCtx, Ctx, Out); } } } @@ -411,21 +443,27 @@ OrigSPOffset += 4; } - virtual void InstrumentMemOperandPrologue(const RegisterContext &RegCtx, + virtual void InstrumentMemOperandPrologue(unsigned LocalFrameReg, + const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) override { + LocalFrameReg = getX86SubSuperRegister(LocalFrameReg, MVT::i32); + const MCRegisterInfo *MRI = Ctx.getRegisterInfo(); unsigned FrameReg = GetFrameReg(Ctx, Out); if (MRI && FrameReg != X86::NoRegister) { - SpillReg(Out, X86::EBP); + SpillReg(Out, LocalFrameReg); if (FrameReg == X86::ESP) { - Out.EmitCFIAdjustCfaOffset(4 /* byte size of the FrameReg */); - Out.EmitCFIRelOffset(MRI->getDwarfRegNum(X86::EBP, true /* IsEH */), 0); + Out.EmitCFIAdjustCfaOffset(4 /* byte size of the LocalFrameReg */); + Out.EmitCFIRelOffset( + MRI->getDwarfRegNum(LocalFrameReg, true /* IsEH */), 0); } EmitInstruction( - Out, MCInstBuilder(X86::MOV32rr).addReg(X86::EBP).addReg(FrameReg)); + Out, + MCInstBuilder(X86::MOV32rr).addReg(LocalFrameReg).addReg(FrameReg)); Out.EmitCFIRememberState(); - Out.EmitCFIDefCfaRegister(MRI->getDwarfRegNum(X86::EBP, true /* IsEH */)); + Out.EmitCFIDefCfaRegister( + MRI->getDwarfRegNum(LocalFrameReg, true /* IsEH */)); } SpillReg(Out, RegCtx.addressReg(MVT::i32)); @@ -435,9 +473,12 @@ StoreFlags(Out); } - virtual void InstrumentMemOperandEpilogue(const RegisterContext &RegCtx, + virtual void InstrumentMemOperandEpilogue(unsigned LocalFrameReg, + const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) override { + LocalFrameReg = getX86SubSuperRegister(LocalFrameReg, MVT::i32); + RestoreFlags(Out); if (RegCtx.ScratchReg != X86::NoRegister) RestoreReg(Out, RegCtx.scratchReg(MVT::i32)); @@ -446,10 +487,10 @@ unsigned FrameReg = GetFrameReg(Ctx, Out); if (Ctx.getRegisterInfo() && FrameReg != X86::NoRegister) { - RestoreReg(Out, X86::EBP); + RestoreReg(Out, LocalFrameReg); Out.EmitCFIRestoreState(); if (FrameReg == X86::ESP) - Out.EmitCFIAdjustCfaOffset(-4 /* byte size of the FrameReg */); + Out.EmitCFIAdjustCfaOffset(-4 /* byte size of the LocalFrameReg */); } } @@ -660,21 +701,27 @@ OrigSPOffset += 8; } - virtual void InstrumentMemOperandPrologue(const RegisterContext &RegCtx, + virtual void InstrumentMemOperandPrologue(unsigned LocalFrameReg, + const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) override { + LocalFrameReg = getX86SubSuperRegister(LocalFrameReg, MVT::i64); + const MCRegisterInfo *MRI = Ctx.getRegisterInfo(); unsigned FrameReg = GetFrameReg(Ctx, Out); if (MRI && FrameReg != X86::NoRegister) { SpillReg(Out, X86::RBP); if (FrameReg == X86::RSP) { - Out.EmitCFIAdjustCfaOffset(8 /* byte size of the FrameReg */); - Out.EmitCFIRelOffset(MRI->getDwarfRegNum(X86::RBP, true /* IsEH */), 0); + Out.EmitCFIAdjustCfaOffset(8 /* byte size of the LocalFrameReg */); + Out.EmitCFIRelOffset( + MRI->getDwarfRegNum(LocalFrameReg, true /* IsEH */), 0); } EmitInstruction( - Out, MCInstBuilder(X86::MOV64rr).addReg(X86::RBP).addReg(FrameReg)); + Out, + MCInstBuilder(X86::MOV64rr).addReg(LocalFrameReg).addReg(FrameReg)); Out.EmitCFIRememberState(); - Out.EmitCFIDefCfaRegister(MRI->getDwarfRegNum(X86::RBP, true /* IsEH */)); + Out.EmitCFIDefCfaRegister( + MRI->getDwarfRegNum(LocalFrameReg, true /* IsEH */)); } EmitAdjustRSP(Ctx, Out, -128); @@ -685,9 +732,12 @@ StoreFlags(Out); } - virtual void InstrumentMemOperandEpilogue(const RegisterContext &RegCtx, + virtual void InstrumentMemOperandEpilogue(unsigned LocalFrameReg, + const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) override { + LocalFrameReg = getX86SubSuperRegister(LocalFrameReg, MVT::i64); + RestoreFlags(Out); if (RegCtx.ScratchReg != X86::NoRegister) RestoreReg(Out, RegCtx.scratchReg(MVT::i64)); @@ -697,10 +747,10 @@ unsigned FrameReg = GetFrameReg(Ctx, Out); if (Ctx.getRegisterInfo() && FrameReg != X86::NoRegister) { - RestoreReg(Out, X86::RBP); + RestoreReg(Out, LocalFrameReg); Out.EmitCFIRestoreState(); if (FrameReg == X86::RSP) - Out.EmitCFIAdjustCfaOffset(-8 /* byte size of the FrameReg */); + Out.EmitCFIAdjustCfaOffset(-8 /* byte size of the LocalFrameReg */); } } Index: test/Instrumentation/AddressSanitizer/X86/asm_cfi.s =================================================================== --- test/Instrumentation/AddressSanitizer/X86/asm_cfi.s +++ test/Instrumentation/AddressSanitizer/X86/asm_cfi.s @@ -4,12 +4,12 @@ # RUN: llvm-mc %s -triple=i386-unknown-linux-gnu -asm-instrumentation=address -asan-instrument-assembly | FileCheck %s # CHECK-LABEL: swap_cfa_rbp -# CHECK: pushl %ebp +# CHECK: pushl %ebx # CHECK-NOT: .cfi_adjust_cfa_offset 8 -# CHECK: movl %ebp, %ebp +# CHECK: movl %ebp, %ebx # CHECK: .cfi_remember_state -# CHECK: .cfi_def_cfa_register %ebp -# CHECK: popl %ebp +# CHECK: .cfi_def_cfa_register %ebx +# CHECK: popl %ebx # CHECK: .cfi_restore_state # CHECK-NOT: .cfi_adjust_cfa_offset -8 # CHECK: retl @@ -33,12 +33,12 @@ .cfi_endproc # CHECK-LABEL: swap_cfa_rsp -# CHECK: pushl %ebp +# CHECK: pushl %ebx # CHECK: .cfi_adjust_cfa_offset 4 -# CHECK: movl %esp, %ebp +# CHECK: movl %esp, %ebx # CHECK: .cfi_remember_state -# CHECK: .cfi_def_cfa_register %ebp -# CHECK: popl %ebp +# CHECK: .cfi_def_cfa_register %ebx +# CHECK: popl %ebx # CHECK: .cfi_restore_state # CHECK: retl