Index: include/llvm/MC/MCDwarf.h =================================================================== --- include/llvm/MC/MCDwarf.h +++ include/llvm/MC/MCDwarf.h @@ -466,13 +466,15 @@ 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; Index: lib/MC/MCStreamer.cpp =================================================================== --- lib/MC/MCStreamer.cpp +++ lib/MC/MCStreamer.cpp @@ -220,6 +220,16 @@ 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 @@ 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 @@ 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) { Index: lib/Target/X86/AsmParser/X86AsmInstrumentation.h =================================================================== --- lib/Target/X86/AsmParser/X86AsmInstrumentation.h +++ lib/Target/X86/AsmParser/X86AsmInstrumentation.h @@ -34,8 +34,9 @@ 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 @@ 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 Index: lib/Target/X86/AsmParser/X86AsmInstrumentation.cpp =================================================================== --- lib/Target/X86/AsmParser/X86AsmInstrumentation.cpp +++ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ } // End anonymous namespace X86AsmInstrumentation::X86AsmInstrumentation(const MCSubtargetInfo &STI) - : STI(STI), FrameReg(X86::NoRegister) {} + : STI(STI), InitialFrameReg(0) {} X86AsmInstrumentation::~X86AsmInstrumentation() {} @@ -835,6 +854,25 @@ 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) { Index: lib/Target/X86/AsmParser/X86AsmParser.cpp =================================================================== --- lib/Target/X86/AsmParser/X86AsmParser.cpp +++ lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -973,7 +973,7 @@ } void X86AsmParser::SetFrameRegister(unsigned RegNo) { - Instrumentation->SetFrameRegister(RegNo); + Instrumentation->SetInitialFrameRegister(RegNo); } std::unique_ptr X86AsmParser::DefaultMemSIOperand(SMLoc Loc) { Index: test/Instrumentation/AddressSanitizer/X86/asm_cfi.ll =================================================================== --- test/Instrumentation/AddressSanitizer/X86/asm_cfi.ll +++ test/Instrumentation/AddressSanitizer/X86/asm_cfi.ll @@ -41,5 +41,14 @@ 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" } Index: test/Instrumentation/AddressSanitizer/X86/asm_cfi.s =================================================================== --- /dev/null +++ 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 Index: test/Instrumentation/AddressSanitizer/X86/asm_mov.s =================================================================== --- test/Instrumentation/AddressSanitizer/X86/asm_mov.s +++ 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 @@ # 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: 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 @@ -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: