From 86e0844d1ce8a008d6ed286ee61d748c155c27e4 Mon Sep 17 00:00:00 2001 From: Yuri Gorshenin Date: Tue, 7 Oct 2014 11:03:09 +0000 Subject: [PATCH] [asan-asm-instrumentation] CFI directives are generated for .S files. Summary: CFI directives are generated for .S files. Reviewers: eugenis Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D5520 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@219199 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/MC/MCDwarf.h | 6 +- lib/MC/MCStreamer.cpp | 12 ++++ .../X86/AsmParser/X86AsmInstrumentation.cpp | 50 ++++++++++++++-- .../X86/AsmParser/X86AsmInstrumentation.h | 9 ++- lib/Target/X86/AsmParser/X86AsmParser.cpp | 2 +- .../AddressSanitizer/X86/asm_cfi.ll | 9 +++ .../AddressSanitizer/X86/asm_cfi.s | 58 +++++++++++++++++++ .../AddressSanitizer/X86/asm_mov.s | 12 ++-- .../AddressSanitizer/X86/asm_swap_intel.s | 14 ++--- 9 files changed, 147 insertions(+), 25 deletions(-) create mode 100644 test/Instrumentation/AddressSanitizer/X86/asm_cfi.s diff --git a/include/llvm/MC/MCDwarf.h b/include/llvm/MC/MCDwarf.h index 88fee2f8cc5..a221d269e0d 100644 --- a/include/llvm/MC/MCDwarf.h +++ b/include/llvm/MC/MCDwarf.h @@ -466,13 +466,15 @@ public: struct MCDwarfFrameInfo { MCDwarfFrameInfo() : Begin(nullptr), End(nullptr), Personality(nullptr), Lsda(nullptr), - Instructions(), PersonalityEncoding(), LsdaEncoding(0), - CompactUnwindEncoding(0), IsSignalFrame(false), IsSimple(false) {} + Instructions(), CurrentCfaRegister(0), PersonalityEncoding(), + LsdaEncoding(0), CompactUnwindEncoding(0), IsSignalFrame(false), + IsSimple(false) {} MCSymbol *Begin; MCSymbol *End; const MCSymbol *Personality; const MCSymbol *Lsda; std::vector Instructions; + unsigned CurrentCfaRegister; unsigned PersonalityEncoding; unsigned LsdaEncoding; uint32_t CompactUnwindEncoding; diff --git a/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp index f6620f07240..2bfb9ba1599 100644 --- a/lib/MC/MCStreamer.cpp +++ b/lib/MC/MCStreamer.cpp @@ -220,6 +220,16 @@ void MCStreamer::EmitCFIStartProc(bool IsSimple) { Frame.IsSimple = IsSimple; EmitCFIStartProcImpl(Frame); + const MCAsmInfo* MAI = Context.getAsmInfo(); + if (MAI) { + for (const MCCFIInstruction& Inst : MAI->getInitialFrameState()) { + if (Inst.getOperation() == MCCFIInstruction::OpDefCfa || + Inst.getOperation() == MCCFIInstruction::OpDefCfaRegister) { + Frame.CurrentCfaRegister = Inst.getRegister(); + } + } + } + DwarfFrameInfos.push_back(Frame); } @@ -251,6 +261,7 @@ void MCStreamer::EmitCFIDefCfa(int64_t Register, int64_t Offset) { MCCFIInstruction::createDefCfa(Label, Register, Offset); MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); CurFrame->Instructions.push_back(Instruction); + CurFrame->CurrentCfaRegister = static_cast(Register); } void MCStreamer::EmitCFIDefCfaOffset(int64_t Offset) { @@ -275,6 +286,7 @@ void MCStreamer::EmitCFIDefCfaRegister(int64_t Register) { MCCFIInstruction::createDefCfaRegister(Label, Register); MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); CurFrame->Instructions.push_back(Instruction); + CurFrame->CurrentCfaRegister = static_cast(Register); } void MCStreamer::EmitCFIOffset(int64_t Register, int64_t Offset) { diff --git a/lib/Target/X86/AsmParser/X86AsmInstrumentation.cpp b/lib/Target/X86/AsmParser/X86AsmInstrumentation.cpp index 68c1b2d8b23..974ee20461a 100644 --- a/lib/Target/X86/AsmParser/X86AsmInstrumentation.cpp +++ b/lib/Target/X86/AsmParser/X86AsmInstrumentation.cpp @@ -15,6 +15,7 @@ #include "llvm/ADT/Triple.h" #include "llvm/CodeGen/MachineValueType.h" #include "llvm/IR/Function.h" +#include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCInstBuilder.h" @@ -297,6 +298,13 @@ public: virtual ~X86AddressSanitizer32() {} + unsigned GetFrameReg(const MCContext &Ctx, MCStreamer &Out) { + unsigned FrameReg = GetFrameRegGeneric(Ctx, Out); + if (FrameReg == X86::NoRegister) + return FrameReg; + return getX86SubSuperRegister(FrameReg, MVT::i32); + } + virtual void StoreFlags(MCStreamer &Out) override { EmitInstruction(Out, MCInstBuilder(X86::PUSHF32)); } @@ -308,7 +316,8 @@ public: virtual void InstrumentMemOperandPrologue(const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) override { - const MCRegisterInfo* MRI = Ctx.getRegisterInfo(); + const MCRegisterInfo *MRI = Ctx.getRegisterInfo(); + unsigned FrameReg = GetFrameReg(Ctx, Out); if (MRI && FrameReg != X86::NoRegister) { EmitInstruction( Out, MCInstBuilder(X86::PUSH32r).addReg(X86::EBP)); @@ -348,6 +357,7 @@ public: EmitInstruction( Out, MCInstBuilder(X86::POP32r).addReg(RegCtx.addressReg(MVT::i32))); + unsigned FrameReg = GetFrameReg(Ctx, Out); if (Ctx.getRegisterInfo() && FrameReg != X86::NoRegister) { EmitInstruction( Out, MCInstBuilder(X86::POP32r).addReg(X86::EBP)); @@ -554,6 +564,13 @@ public: virtual ~X86AddressSanitizer64() {} + unsigned GetFrameReg(const MCContext &Ctx, MCStreamer &Out) { + unsigned FrameReg = GetFrameRegGeneric(Ctx, Out); + if (FrameReg == X86::NoRegister) + return FrameReg; + return getX86SubSuperRegister(FrameReg, MVT::i64); + } + virtual void StoreFlags(MCStreamer &Out) override { EmitInstruction(Out, MCInstBuilder(X86::PUSHF64)); } @@ -565,19 +582,20 @@ public: virtual void InstrumentMemOperandPrologue(const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) override { - const MCRegisterInfo *RegisterInfo = Ctx.getRegisterInfo(); - if (RegisterInfo && FrameReg != X86::NoRegister) { + const MCRegisterInfo *MRI = Ctx.getRegisterInfo(); + unsigned FrameReg = GetFrameReg(Ctx, Out); + if (MRI && FrameReg != X86::NoRegister) { EmitInstruction(Out, MCInstBuilder(X86::PUSH64r).addReg(X86::RBP)); if (FrameReg == X86::RSP) { Out.EmitCFIAdjustCfaOffset(8 /* byte size of the FrameReg */); Out.EmitCFIRelOffset( - RegisterInfo->getDwarfRegNum(X86::RBP, true /* IsEH */), 0); + MRI->getDwarfRegNum(X86::RBP, true /* IsEH */), 0); } EmitInstruction( Out, MCInstBuilder(X86::MOV64rr).addReg(X86::RBP).addReg(FrameReg)); Out.EmitCFIRememberState(); Out.EmitCFIDefCfaRegister( - RegisterInfo->getDwarfRegNum(X86::RBP, true /* IsEH */)); + MRI->getDwarfRegNum(X86::RBP, true /* IsEH */)); } EmitAdjustRSP(Ctx, Out, -128); @@ -606,6 +624,7 @@ public: Out, MCInstBuilder(X86::POP64r).addReg(RegCtx.shadowReg(MVT::i64))); EmitAdjustRSP(Ctx, Out, 128); + unsigned FrameReg = GetFrameReg(Ctx, Out); if (Ctx.getRegisterInfo() && FrameReg != X86::NoRegister) { EmitInstruction( Out, MCInstBuilder(X86::POP64r).addReg(X86::RBP)); @@ -820,7 +839,7 @@ void X86AddressSanitizer64::InstrumentMOVSImpl(unsigned AccessSize, } // End anonymous namespace X86AsmInstrumentation::X86AsmInstrumentation(const MCSubtargetInfo &STI) - : STI(STI), FrameReg(X86::NoRegister) {} + : STI(STI), InitialFrameReg(0) {} X86AsmInstrumentation::~X86AsmInstrumentation() {} @@ -835,6 +854,25 @@ void X86AsmInstrumentation::EmitInstruction(MCStreamer &Out, Out.EmitInstruction(Inst, STI); } +unsigned X86AsmInstrumentation::GetFrameRegGeneric(const MCContext &Ctx, + MCStreamer &Out) { + if (!Out.getNumFrameInfos()) // No active dwarf frame + return X86::NoRegister; + const MCDwarfFrameInfo &Frame = Out.getDwarfFrameInfos().back(); + if (Frame.End) // Active dwarf frame is closed + return X86::NoRegister; + const MCRegisterInfo *MRI = Ctx.getRegisterInfo(); + if (!MRI) // No register info + return X86::NoRegister; + + if (InitialFrameReg) { + // FrameReg is set explicitly, we're instrumenting a MachineFunction. + return InitialFrameReg; + } + + return MRI->getLLVMRegNum(Frame.CurrentCfaRegister, true /* IsEH */); +} + X86AsmInstrumentation * CreateX86AsmInstrumentation(const MCTargetOptions &MCOptions, const MCContext &Ctx, const MCSubtargetInfo &STI) { diff --git a/lib/Target/X86/AsmParser/X86AsmInstrumentation.h b/lib/Target/X86/AsmParser/X86AsmInstrumentation.h index aa2ed03a19b..19ebcc44f61 100644 --- a/lib/Target/X86/AsmParser/X86AsmInstrumentation.h +++ b/lib/Target/X86/AsmParser/X86AsmInstrumentation.h @@ -34,8 +34,9 @@ class X86AsmInstrumentation { public: virtual ~X86AsmInstrumentation(); - void SetFrameRegister(unsigned RegNo) { - FrameReg = RegNo; + // Sets frame register corresponding to a current frame. + void SetInitialFrameRegister(unsigned RegNo) { + InitialFrameReg = RegNo; } // Tries to instrument and emit instruction. @@ -51,11 +52,13 @@ protected: X86AsmInstrumentation(const MCSubtargetInfo &STI); + unsigned GetFrameRegGeneric(const MCContext &Ctx, MCStreamer &Out); + void EmitInstruction(MCStreamer &Out, const MCInst &Inst); const MCSubtargetInfo &STI; - unsigned FrameReg; + unsigned InitialFrameReg; }; } // End llvm namespace diff --git a/lib/Target/X86/AsmParser/X86AsmParser.cpp b/lib/Target/X86/AsmParser/X86AsmParser.cpp index 519ada2b4b9..0a2ad104f37 100644 --- a/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -973,7 +973,7 @@ bool X86AsmParser::ParseRegister(unsigned &RegNo, } void X86AsmParser::SetFrameRegister(unsigned RegNo) { - Instrumentation->SetFrameRegister(RegNo); + Instrumentation->SetInitialFrameRegister(RegNo); } std::unique_ptr X86AsmParser::DefaultMemSIOperand(SMLoc Loc) { diff --git a/test/Instrumentation/AddressSanitizer/X86/asm_cfi.ll b/test/Instrumentation/AddressSanitizer/X86/asm_cfi.ll index dfa418fb9ef..6bfb153ea93 100644 --- a/test/Instrumentation/AddressSanitizer/X86/asm_cfi.ll +++ b/test/Instrumentation/AddressSanitizer/X86/asm_cfi.ll @@ -41,5 +41,14 @@ entry: ret void } +; CHECK-LABEL: mov8b_rsp_no_cfi +; CHECK-NOT: .cfi{{[a-z_]+}} +define void @mov8b_rsp_no_cfi(i64* %dst, i64* %src) #2 { +entry: + tail call void asm sideeffect "movq ($0), %rax \0A\09movq %rax, ($1) \0A\09", "r,r,~{rax},~{memory},~{dirflag},~{fpsr},~{flags}"(i64* %src, i64* %dst) + ret void +} + attributes #0 = { nounwind sanitize_address uwtable "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" } attributes #1 = { nounwind sanitize_address uwtable "no-frame-pointer-elim"="false" } +attributes #2 = { nounwind sanitize_address "no-frame-pointer-elim"="false" } diff --git a/test/Instrumentation/AddressSanitizer/X86/asm_cfi.s b/test/Instrumentation/AddressSanitizer/X86/asm_cfi.s new file mode 100644 index 00000000000..ff7e4f76a75 --- /dev/null +++ b/test/Instrumentation/AddressSanitizer/X86/asm_cfi.s @@ -0,0 +1,58 @@ +# The test verifies that correct DWARF directives are emitted when +# assembly files are instrumented. + +# 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-NOT: .cfi_adjust_cfa_offset 8 +# CHECK: movl %ebp, %ebp +# CHECK: .cfi_remember_state +# CHECK: .cfi_def_cfa_register %ebp +# CHECK: popl %ebp +# CHECK: .cfi_restore_state +# CHECK-NOT: .cfi_adjust_cfa_offset -8 +# CHECK: retl + + .text + .globl swap_cfa_rbp + .type swap_cfa_rbp,@function +swap_cfa_rbp: # @swap_cfa_rbp + .cfi_startproc + pushl %ebp + .cfi_def_cfa_offset 8 + .cfi_offset %ebp, -8 + movl %esp, %ebp + .cfi_def_cfa_register %ebp + movl 8(%ebp), %eax + movl 12(%ebp), %ecx + movl (%ecx), %ecx + movl %ecx, (%eax) + popl %ebp + retl + .cfi_endproc + +# CHECK-LABEL: swap_cfa_rsp +# CHECK: pushl %ebp +# CHECK: .cfi_adjust_cfa_offset 4 +# CHECK: movl %esp, %ebp +# CHECK: .cfi_remember_state +# CHECK: .cfi_def_cfa_register %ebp +# CHECK: popl %ebp +# CHECK: .cfi_restore_state +# CHECK: retl + + .globl swap_cfa_rsp + .type swap_cfa_rsp,@function +swap_cfa_rsp: # @swap_cfa_rsp + .cfi_startproc + pushl %ebp + .cfi_offset %ebp, 0 + movl %esp, %ebp + movl 8(%ebp), %eax + movl 12(%ebp), %ecx + movl (%ecx), %ecx + movl %ecx, (%eax) + popl %ebp + retl + .cfi_endproc diff --git a/test/Instrumentation/AddressSanitizer/X86/asm_mov.s b/test/Instrumentation/AddressSanitizer/X86/asm_mov.s index 74a788cf4d5..14fc056d72f 100644 --- a/test/Instrumentation/AddressSanitizer/X86/asm_mov.s +++ b/test/Instrumentation/AddressSanitizer/X86/asm_mov.s @@ -10,13 +10,13 @@ # CHECK: callq __asan_report_load1@PLT # CHECK: leaq 128(%rsp), %rsp # -# CHECK-NEXT: movb (%rsi), %al +# CHECK: movb (%rsi), %al # -# CHECK-NEXT: leaq -128(%rsp), %rsp +# CHECK: leaq -128(%rsp), %rsp # CHECK: callq __asan_report_store1@PLT # CHECK: leaq 128(%rsp), %rsp # -# CHECK-NEXT: movb %al, (%rdi) +# CHECK: movb %al, (%rdi) mov1b: # @mov1b .cfi_startproc # BB#0: @@ -39,13 +39,13 @@ mov1b: # @mov1b # CHECK: callq __asan_report_load16@PLT # CHECK: leaq 128(%rsp), %rsp # -# CHECK-NEXT: movaps (%rsi), %xmm0 +# CHECK: movaps (%rsi), %xmm0 # -# CHECK-NEXT: leaq -128(%rsp), %rsp +# CHECK: leaq -128(%rsp), %rsp # CHECK: callq __asan_report_store16@PLT # CHECK: leaq 128(%rsp), %rsp # -# CHECK-NEXT: movaps %xmm0, (%rdi) +# CHECK: movaps %xmm0, (%rdi) mov16b: # @mov16b .cfi_startproc # BB#0: diff --git a/test/Instrumentation/AddressSanitizer/X86/asm_swap_intel.s b/test/Instrumentation/AddressSanitizer/X86/asm_swap_intel.s index ca3c54c1455..093c96b0efa 100644 --- a/test/Instrumentation/AddressSanitizer/X86/asm_swap_intel.s +++ b/test/Instrumentation/AddressSanitizer/X86/asm_swap_intel.s @@ -10,25 +10,25 @@ # CHECK: callq __asan_report_load8@PLT # CHECK: leaq 128(%rsp), %rsp # -# CHECK-NEXT: movq (%rcx), %rax +# CHECK: movq (%rcx), %rax # -# CHECK-NEXT: leaq -128(%rsp), %rsp +# CHECK: leaq -128(%rsp), %rsp # CHECK: callq __asan_report_load8@PLT # CHECK: leaq 128(%rsp), %rsp # -# CHECK-NEXT: movq (%rdx), %rbx +# CHECK: movq (%rdx), %rbx # -# CHECK-NEXT: leaq -128(%rsp), %rsp +# CHECK: leaq -128(%rsp), %rsp # CHECK: callq __asan_report_store8@PLT # CHECK: leaq 128(%rsp), %rsp # -# CHECK-NEXT: movq %rbx, (%rcx) +# CHECK: movq %rbx, (%rcx) # -# CHECK-NEXT: leaq -128(%rsp), %rsp +# CHECK: leaq -128(%rsp), %rsp # CHECK: callq __asan_report_store8@PLT # CHECK: leaq 128(%rsp), %rsp # -# CHECK-NEXT: movq %rax, (%rdx) +# CHECK: movq %rax, (%rdx) swap: # @swap .cfi_startproc # BB#0: