diff --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h --- a/llvm/include/llvm/MC/MCStreamer.h +++ b/llvm/include/llvm/MC/MCStreamer.h @@ -214,6 +214,10 @@ std::unique_ptr TargetStreamer; std::vector DwarfFrameInfos; + // This is a pair of index into DwarfFrameInfos and the MCSection associated + // with the frame. Note, we use an index instead of an iterator because they + // can be invalidated in std::vector. + SmallVector, 1> FrameInfoStack; MCDwarfFrameInfo *getCurrentDwarfFrameInfo(); /// Similar to DwarfFrameInfos, but for SEH unwind info. Chained frames may diff --git a/llvm/lib/MC/MCStreamer.cpp b/llvm/lib/MC/MCStreamer.cpp --- a/llvm/lib/MC/MCStreamer.cpp +++ b/llvm/lib/MC/MCStreamer.cpp @@ -278,7 +278,7 @@ } bool MCStreamer::hasUnfinishedDwarfFrameInfo() { - return !DwarfFrameInfos.empty() && !DwarfFrameInfos.back().End; + return !FrameInfoStack.empty(); } MCDwarfFrameInfo *MCStreamer::getCurrentDwarfFrameInfo() { @@ -288,7 +288,7 @@ ".cfi_startproc and .cfi_endproc directives"); return nullptr; } - return &DwarfFrameInfos.back(); + return &DwarfFrameInfos[FrameInfoStack.back().first]; } bool MCStreamer::emitCVFileDirective(unsigned FileNo, StringRef Filename, @@ -445,7 +445,8 @@ void MCStreamer::emitCFISections(bool EH, bool Debug) {} void MCStreamer::emitCFIStartProc(bool IsSimple, SMLoc Loc) { - if (hasUnfinishedDwarfFrameInfo()) + if (!FrameInfoStack.empty() && + getCurrentSectionOnly() == FrameInfoStack.back().second) return getContext().reportError( Loc, "starting new .cfi frame before finishing the previous one"); @@ -464,6 +465,7 @@ } } + FrameInfoStack.emplace_back(DwarfFrameInfos.size(), getCurrentSectionOnly()); DwarfFrameInfos.push_back(Frame); } @@ -475,6 +477,7 @@ if (!CurFrame) return; emitCFIEndProcImpl(*CurFrame); + FrameInfoStack.pop_back(); } void MCStreamer::emitCFIEndProcImpl(MCDwarfFrameInfo &Frame) { diff --git a/llvm/test/MC/ELF/cfi-startproc-pushsection.s b/llvm/test/MC/ELF/cfi-startproc-pushsection.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/ELF/cfi-startproc-pushsection.s @@ -0,0 +1,45 @@ +// RUN: llvm-mc -filetype=obj -triple x86_64-linux %s -o - | llvm-dwarfdump --eh-frame - | FileCheck %s + +.section .text.a, "ax", %progbits +.cfi_startproc +.cfi_def_cfa %rsp, 0 + +.pushsection .text.b, "ax", %progbits +.cfi_startproc simple +.cfi_def_cfa %rsp, 8 +nop +ret + +.pushsection .text.c, "ax", %progbits +.cfi_startproc simple +.cfi_def_cfa %rsp, 16 +nop +nop +ret +.cfi_endproc +.popsection + +.cfi_endproc +.popsection + +.pushsection .text.d, "ax", %progbits +.cfi_startproc simple +.cfi_def_cfa %rsp, 24 +nop +nop +nop +ret +.cfi_endproc +.popsection + +ret +.cfi_endproc + +// CHECK: pc=00000000...00000001 +// CHECK: RSP +0 +// CHECK: pc=00000000...00000002 +// CHECK: RSP +8 +// CHECK: pc=00000000...00000003 +// CHECK: RSP +16 +// CHECK: pc=00000000...00000004 +// CHECK: RSP +24