Index: include/llvm/MC/MCDwarf.h =================================================================== --- include/llvm/MC/MCDwarf.h +++ include/llvm/MC/MCDwarf.h @@ -466,13 +466,14 @@ struct MCDwarfFrameInfo { MCDwarfFrameInfo() : Begin(nullptr), End(nullptr), Personality(nullptr), Lsda(nullptr), - Instructions(), PersonalityEncoding(), LsdaEncoding(0), + Instructions(), CfaRegister(0), PersonalityEncoding(), LsdaEncoding(0), CompactUnwindEncoding(0), IsSignalFrame(false), IsSimple(false) {} MCSymbol *Begin; MCSymbol *End; const MCSymbol *Personality; const MCSymbol *Lsda; std::vector Instructions; + unsigned CfaRegister; unsigned PersonalityEncoding; unsigned LsdaEncoding; uint32_t CompactUnwindEncoding; Index: lib/MC/MCStreamer.cpp =================================================================== --- lib/MC/MCStreamer.cpp +++ lib/MC/MCStreamer.cpp @@ -275,6 +275,7 @@ MCCFIInstruction::createDefCfaRegister(Label, Register); MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); CurFrame->Instructions.push_back(Instruction); + CurFrame->CfaRegister = 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,6 +34,7 @@ public: virtual ~X86AsmInstrumentation(); + // Sets frame register corresponding to a current frame. void SetFrameRegister(unsigned RegNo) { FrameReg = RegNo; } @@ -51,6 +52,8 @@ X86AsmInstrumentation(const MCSubtargetInfo &STI); + unsigned GetFrameRegGeneric(const MCContext &Ctx, MCStreamer &Out); + void EmitInstruction(MCStreamer &Out, const MCInst &Inst); const MCSubtargetInfo &STI; Index: lib/Target/X86/AsmParser/X86AsmInstrumentation.cpp =================================================================== --- lib/Target/X86/AsmParser/X86AsmInstrumentation.cpp +++ lib/Target/X86/AsmParser/X86AsmInstrumentation.cpp @@ -297,6 +297,10 @@ virtual ~X86AddressSanitizer32() {} + unsigned GetFrameReg(const MCContext &Ctx, MCStreamer &Out) { + return getX86SubSuperRegister(GetFrameRegGeneric(Ctx, Out), MVT::i32); + } + virtual void StoreFlags(MCStreamer &Out) override { EmitInstruction(Out, MCInstBuilder(X86::PUSHF32)); } @@ -308,7 +312,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 +353,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 +560,10 @@ virtual ~X86AddressSanitizer64() {} + unsigned GetFrameReg(const MCContext &Ctx, MCStreamer &Out) { + return getX86SubSuperRegister(GetFrameRegGeneric(Ctx, Out), MVT::i64); + } + virtual void StoreFlags(MCStreamer &Out) override { EmitInstruction(Out, MCInstBuilder(X86::PUSHF64)); } @@ -565,19 +575,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 +617,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)); @@ -835,6 +847,29 @@ 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 (FrameReg != X86::NoRegister) { + // FrameReg is set, we're instrumenting a MachineFunction. + return FrameReg; + } + + // FrameReg isn't set and we're instrumenting an inline assembly. + // If CFA register is not specified explicitly, let's assume that it's SP. + if (!Frame.CfaRegister) + return X86::RSP; + return MRI->getLLVMRegNum(Frame.CfaRegister, true /* IsEH */); +} + X86AsmInstrumentation * CreateX86AsmInstrumentation(const MCTargetOptions &MCOptions, const MCContext &Ctx, const MCSubtargetInfo &STI) { Index: test/Instrumentation/AddressSanitizer/X86/asm_cfi.s =================================================================== --- /dev/null +++ test/Instrumentation/AddressSanitizer/X86/asm_cfi.s @@ -0,0 +1,55 @@ +# 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: