From 96b0873b25de4cb8c8e358be33f0e22c3048b267 Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Mon, 17 Dec 2018 21:49:35 +0000 Subject: [PATCH] [codeview] Flush labels before S_DEFRANGE* fragments This was a pre-existing bug that could be triggered with assembly like this: .p2align 2 .LtmpN: .cv_def_range "..." I noticed this when attempting to change clang to emit aligned symbol records. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@349403 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/MC/MCCodeView.h | 2 +- lib/MC/MCCodeView.cpp | 4 +- lib/MC/MCObjectStreamer.cpp | 6 +- test/MC/COFF/cv-def-range-align.s | 161 ++++++++++++++++++++++++++++++ 4 files changed, 169 insertions(+), 4 deletions(-) create mode 100644 test/MC/COFF/cv-def-range-align.s diff --git a/include/llvm/MC/MCCodeView.h b/include/llvm/MC/MCCodeView.h index 2678cf4388f..cef03a409f9 100644 --- a/include/llvm/MC/MCCodeView.h +++ b/include/llvm/MC/MCCodeView.h @@ -194,7 +194,7 @@ public: void encodeInlineLineTable(MCAsmLayout &Layout, MCCVInlineLineTableFragment &F); - void + MCFragment * emitDefRange(MCObjectStreamer &OS, ArrayRef> Ranges, StringRef FixedSizePortion); diff --git a/lib/MC/MCCodeView.cpp b/lib/MC/MCCodeView.cpp index 234b43e3d49..978ac789c31 100644 --- a/lib/MC/MCCodeView.cpp +++ b/lib/MC/MCCodeView.cpp @@ -432,13 +432,13 @@ void CodeViewContext::emitInlineLineTableForFunction(MCObjectStreamer &OS, OS.getCurrentSectionOnly()); } -void CodeViewContext::emitDefRange( +MCFragment *CodeViewContext::emitDefRange( MCObjectStreamer &OS, ArrayRef> Ranges, StringRef FixedSizePortion) { // Create and insert a fragment into the current section that will be encoded // later. - new MCCVDefRangeFragment(Ranges, FixedSizePortion, + return new MCCVDefRangeFragment(Ranges, FixedSizePortion, OS.getCurrentSectionOnly()); } diff --git a/lib/MC/MCObjectStreamer.cpp b/lib/MC/MCObjectStreamer.cpp index 248c5a1fe35..6ec705bdddb 100644 --- a/lib/MC/MCObjectStreamer.cpp +++ b/lib/MC/MCObjectStreamer.cpp @@ -497,7 +497,11 @@ void MCObjectStreamer::EmitCVInlineLinetableDirective( void MCObjectStreamer::EmitCVDefRangeDirective( ArrayRef> Ranges, StringRef FixedSizePortion) { - getContext().getCVContext().emitDefRange(*this, Ranges, FixedSizePortion); + MCFragment *Frag = + getContext().getCVContext().emitDefRange(*this, Ranges, FixedSizePortion); + // Attach labels that were pending before we created the defrange fragment to + // the beginning of the new fragment. + flushPendingLabels(Frag, 0); this->MCStreamer::EmitCVDefRangeDirective(Ranges, FixedSizePortion); } diff --git a/test/MC/COFF/cv-def-range-align.s b/test/MC/COFF/cv-def-range-align.s new file mode 100644 index 00000000000..57bd3bf2af5 --- /dev/null +++ b/test/MC/COFF/cv-def-range-align.s @@ -0,0 +1,161 @@ +# RUN: llvm-mc -triple x86_64-windows-msvc %s -filetype=obj -o %t.o +# RUN: llvm-pdbutil dump -symbols %t.o | FileCheck %s + +# We used to have a label flushing bug down below by the "BUG" comments that +# would cause the S_DEFRANGE_FRAMEPOINTER_REL records to appear missing. In +# practice, the label would extend past the def range, so it would appear that +# every local was optimized out or had no def ranges. + +# CHECK: S_GPROC32_ID {{.*}} `max` +# CHECK: S_LOCAL [size = {{.*}}] `a` +# CHECK: S_DEFRANGE_FRAMEPOINTER_REL +# CHECK: S_LOCAL [size = {{.*}}] `b` +# CHECK: S_DEFRANGE_FRAMEPOINTER_REL + + .text + .def @feat.00; + .scl 3; + .type 0; + .endef + .globl @feat.00 +.set @feat.00, 0 + .def max; + .scl 2; + .type 32; + .endef + .globl max # -- Begin function max + .p2align 4, 0x90 +max: # @max +.Lfunc_begin0: + .cv_func_id 0 + .cv_file 1 "C:\\src\\llvm-project\\build\\t.c" "44649E6EBC4FC8880991A1AF1F2D2990" 1 + .cv_loc 0 1 1 0 # t.c:1:0 +.seh_proc max +# %bb.0: # %entry + pushq %rax + .seh_stackalloc 8 + .seh_endprologue + movl %edx, 4(%rsp) + movl %ecx, (%rsp) +.Ltmp0: + .cv_loc 0 1 2 0 # t.c:2:0 + movl (%rsp), %eax + cmpl 4(%rsp), %eax + jle .LBB0_2 +# %bb.1: # %cond.true + movl (%rsp), %eax + jmp .LBB0_3 +.LBB0_2: # %cond.false + movl 4(%rsp), %eax +.LBB0_3: # %cond.end + popq %rcx + retq +.Ltmp1: +.Lfunc_end0: + .seh_handlerdata + .text + .seh_endproc + # -- End function + .section .debug$S,"dr" + .p2align 2 + .long 4 + .long 241 # Symbol subsection for max + .long .Ltmp7-.Ltmp6 # Subsection size +.Ltmp6: + .short .Ltmp9-.Ltmp8 # Record length +.Ltmp8: + .short 4423 # Record kind: S_GPROC32_ID + .long 0 # PtrParent + .long 0 # PtrEnd + .long 0 # PtrNext + .long .Lfunc_end0-max # Code size + .long 0 # Offset after prologue + .long 0 # Offset before epilogue + .long 4098 # Function type index + .secrel32 max # Function section relative address + .secidx max # Function section index + .byte 0 # Flags + .asciz "max" # Function name +.Ltmp9: + .short .Ltmp11-.Ltmp10 # Record length +.Ltmp10: + .short 4114 # Record kind: S_FRAMEPROC + .long 8 # FrameSize + .long 0 # Padding + .long 0 # Offset of padding + .long 0 # Bytes of callee saved registers + .long 0 # Exception handler offset + .short 0 # Exception handler section + .long 81920 # Flags (defines frame register) +.Ltmp11: + .short .Ltmp13-.Ltmp12 # Record length +.Ltmp12: + .short 4414 # Record kind: S_LOCAL + .long 18 # TypeIndex + .short 1 # Flags + .asciz "a" + # BUG + .p2align 2 +.Ltmp13: + .cv_def_range .Ltmp0 .Ltmp1, "B\021\000\000\000\000" + .short .Ltmp15-.Ltmp14 # Record length +.Ltmp14: + .short 4414 # Record kind: S_LOCAL + .long 18 # TypeIndex + .short 1 # Flags + .asciz "b" + # BUG + .p2align 2 +.Ltmp15: + .cv_def_range .Ltmp0 .Ltmp1, "B\021\004\000\000\000" + .short 2 # Record length + .short 4431 # Record kind: S_PROC_ID_END +.Ltmp7: + .p2align 2 + .cv_linetable 0, max, .Lfunc_end0 + .cv_filechecksums # File index to string table offset subsection + .cv_stringtable # String table + .long 241 + .long .Ltmp17-.Ltmp16 # Subsection size +.Ltmp16: +.Ltmp17: + .p2align 2 + .section .debug$T,"dr" + .p2align 2 + .long 4 # Debug section magic + # ArgList (0x1000) { + # TypeLeafKind: LF_ARGLIST (0x1201) + # NumArgs: 2 + # Arguments [ + # ArgType: long (0x12) + # ArgType: long (0x12) + # ] + # } + .byte 0x0e, 0x00, 0x01, 0x12 + .byte 0x02, 0x00, 0x00, 0x00 + .byte 0x12, 0x00, 0x00, 0x00 + .byte 0x12, 0x00, 0x00, 0x00 + # Procedure (0x1001) { + # TypeLeafKind: LF_PROCEDURE (0x1008) + # ReturnType: long (0x12) + # CallingConvention: NearC (0x0) + # FunctionOptions [ (0x0) + # ] + # NumParameters: 2 + # ArgListType: (long, long) (0x1000) + # } + .byte 0x0e, 0x00, 0x08, 0x10 + .byte 0x12, 0x00, 0x00, 0x00 + .byte 0x00, 0x00, 0x02, 0x00 + .byte 0x00, 0x10, 0x00, 0x00 + # FuncId (0x1002) { + # TypeLeafKind: LF_FUNC_ID (0x1601) + # ParentScope: 0x0 + # FunctionType: long (long, long) (0x1001) + # Name: max + # } + .byte 0x0e, 0x00, 0x01, 0x16 + .byte 0x00, 0x00, 0x00, 0x00 + .byte 0x01, 0x10, 0x00, 0x00 + .byte 0x6d, 0x61, 0x78, 0x00 + -- 2.50.1