Skip to content

[llvm-dwp] Fix merging of debug_str_offsets with multiple contributions #90461

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 33 additions & 9 deletions llvm/lib/DWP/DWP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,17 @@ Expected<InfoSectionUnitHeader> parseInfoSectionUnitHeader(StringRef Info) {
return Header;
}

static void writeNewOffsetsTo(MCStreamer &Out, DataExtractor &Data,
DenseMap<uint64_t, uint32_t> &OffsetRemapping,
uint64_t &Offset, uint64_t &Size) {

while (Offset < Size) {
auto OldOffset = Data.getU32(&Offset);
auto NewOffset = OffsetRemapping[OldOffset];
Out.emitIntValue(NewOffset, 4);
}
}

void writeStringsAndOffsets(MCStreamer &Out, DWPStringPool &Strings,
MCSection *StrOffsetSection,
StringRef CurStrSection,
Expand All @@ -439,17 +450,30 @@ void writeStringsAndOffsets(MCStreamer &Out, DWPStringPool &Strings,

Out.switchSection(StrOffsetSection);

uint64_t HeaderSize = debugStrOffsetsHeaderSize(Data, Version);
uint64_t Offset = 0;
uint64_t Size = CurStrOffsetSection.size();
// FIXME: This can be caused by bad input and should be handled as such.
assert(HeaderSize <= Size && "StrOffsetSection size is less than its header");
// Copy the header to the output.
Out.emitBytes(Data.getBytes(&Offset, HeaderSize));
while (Offset < Size) {
auto OldOffset = Data.getU32(&Offset);
auto NewOffset = OffsetRemapping[OldOffset];
Out.emitIntValue(NewOffset, 4);
if (Version > 4) {
while (Offset < Size) {
uint64_t HeaderSize = debugStrOffsetsHeaderSize(Data, Version);
assert(HeaderSize <= Size - Offset &&
"StrOffsetSection size is less than its header");

uint64_t ContributionEnd = 0;
uint64_t ContributionSize = 0;
uint64_t HeaderLengthOffset = Offset;
if (HeaderSize == 8) {
ContributionSize = Data.getU32(&HeaderLengthOffset);
} else if (HeaderSize == 16) {
HeaderLengthOffset += 4; // skip the dwarf64 marker
ContributionSize = Data.getU64(&HeaderLengthOffset);
}
ContributionEnd = ContributionSize + HeaderLengthOffset;
Out.emitBytes(Data.getBytes(&Offset, HeaderSize));
writeNewOffsetsTo(Out, Data, OffsetRemapping, Offset, ContributionEnd);
}

} else {
writeNewOffsetsTo(Out, Data, OffsetRemapping, Offset, Size);
}
}

Expand Down
5 changes: 5 additions & 0 deletions llvm/test/tools/llvm-dwp/X86/merge.test
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,8 @@ CHECK: Index Signature INFO ABBREV
CHECK-DAG: [[DWOC]] [0x00000000[[#COFF]], 0x00000000[[#AOFF]]) [0x0000[[CAOFF]], 0x0000[[AAOFF]]) [0x00000000, 0x00000011) [0x00000000, 0x00000018)
CHECK-DAG: [[DWOA]] [0x00000000[[#AOFF]], 0x00000000[[#BOFF]]) [0x0000[[AAOFF]], 0x0000[[BAOFF]]) [0x00000011, 0x00000022) [0x00000018, 0x00000028)
CHECK-DAG: [[DWOB]] [0x00000000[[#BOFF]], 0x00000000[[#XOFF]]) [0x0000[[BAOFF]], 0x000000c3) [0x00000022, 0x00000033) [0x00000028, 0x0000003c)

CHECK-LABEL: .debug_str_offsets.dwo contents:
CHECK: Contribution size = 24, Format = DWARF32, Version = 4
CHECK: Contribution size = 16, Format = DWARF32, Version = 4
CHECK: Contribution size = 20, Format = DWARF32, Version = 4
152 changes: 152 additions & 0 deletions llvm/test/tools/llvm-dwp/X86/merge_v5.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
RUN: rm -rf %t && split-file %s %t && cd %t
RUN: llc a.ll -o a.o -filetype=obj --split-dwarf-output=a.dwo --split-dwarf-file=a.dwo
RUN: llc b.ll -o b.o -filetype=obj --split-dwarf-output=b.dwo --split-dwarf-file=b.dwo
RUN: llc c.ll -o c.o -filetype=obj --split-dwarf-output=c.dwo --split-dwarf-file=c.dwo
RUN: llvm-dwp a.dwo b.dwo -o ab.dwp
RUN: llvm-dwp c.dwo ab.dwp -o merged.dwp
RUN: llvm-dwarfdump -v merged.dwp | FileCheck --check-prefix=CHECK %s


CHECK-LABEL: .debug_str_offsets.dwo contents:
CHECK: Contribution size = 32, Format = DWARF32, Version = 5
CHECK: 0x00000008: 00000000 "_Z1cv"
CHECK: 0x0000000c: 00000006 "c"
CHECK: 0x00000010: 00000008 "int"
CHECK: 0x00000014: 0000000c "baz"
CHECK: 0x00000018: 00000010 ""
CHECK: 0x0000001c: 00000011 "c.cpp"
CHECK: 0x00000020: 00000017 "c.dwo"
CHECK: Contribution size = 24, Format = DWARF32, Version = 5
CHECK: 0x0000002c: 0000001d "a"
CHECK: 0x00000030: 0000001f "foo"
CHECK: 0x00000034: 00000010 ""
CHECK: 0x00000038: 00000023 "a.cpp"
CHECK: 0x0000003c: 00000029 "a.dwo"
CHECK: Contribution size = 28, Format = DWARF32, Version = 5
CHECK: 0x00000048: 0000002f "_Z1b3bar"
CHECK: 0x0000004c: 00000038 "b"
CHECK: 0x00000050: 0000003a "bar"
CHECK: 0x00000054: 00000010 ""
CHECK: 0x00000058: 0000003e "b.cpp"
CHECK: 0x0000005c: 00000044 "b.dwo"
;--- a.cpp
struct foo { };
foo a;
;--- b.cpp
struct bar { };
void b(bar) {
}
;--- c.cpp
typedef int baz;
baz c() {
}
;--- gen
clang --target=x86_64-linux -g3 -S -emit-llvm -gsplit-dwarf a.cpp -o -
echo '#--- b.ll'
clang --target=x86_64-linux -g3 -S -emit-llvm -gsplit-dwarf b.cpp -o -
echo '#--- c.ll'
clang --target=x86_64-linux -g3 -S -emit-llvm -gsplit-dwarf c.cpp -o -
;--- a.ll
; ModuleID = 'a.cpp'
source_filename = "a.cpp"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux"

%struct.foo = type { i8 }

@a = dso_local global %struct.foo zeroinitializer, align 1, !dbg !0

!llvm.dbg.cu = !{!2}
!llvm.module.flags = !{!7, !8, !9, !10, !11, !12, !13}

!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 2, type: !5, isLocal: false, isDefinition: true)
!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, isOptimized: false, runtimeVersion: 0, splitDebugFilename: "a.dwo", emissionKind: FullDebug, globals: !4, splitDebugInlining: false, nameTableKind: GNU)
!3 = !DIFile(filename: "a.cpp", directory: "/proc/self/cwd", checksumkind: CSK_MD5, checksum: "394299a94a96cb48c0c9c95d7baf01f5")
!4 = !{!0}
!5 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "foo", file: !3, line: 1, size: 8, flags: DIFlagTypePassByValue, elements: !6, identifier: "_ZTS3foo")
!6 = !{}
!7 = !{i32 7, !"Dwarf Version", i32 5}
!8 = !{i32 2, !"Debug Info Version", i32 3}
!9 = !{i32 1, !"wchar_size", i32 4}
!10 = !{i32 8, !"PIC Level", i32 2}
!11 = !{i32 7, !"PIE Level", i32 2}
!12 = !{i32 7, !"uwtable", i32 2}
!13 = !{i32 7, !"frame-pointer", i32 2}
#--- b.ll
; ModuleID = 'b.cpp'
source_filename = "b.cpp"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux"

%struct.bar = type { i8 }

; Function Attrs: mustprogress noinline nounwind optnone uwtable
define dso_local void @_Z1b3bar() #0 !dbg !9 {
%1 = alloca %struct.bar, align 1
call void @llvm.dbg.declare(metadata ptr %1, metadata !14, metadata !DIExpression()), !dbg !15
ret void, !dbg !16
}

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare void @llvm.dbg.declare(metadata, metadata, metadata) #1

attributes #0 = { mustprogress noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
attributes #1 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!2, !3, !4, !5, !6, !7, !8}

!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, isOptimized: false, runtimeVersion: 0, splitDebugFilename: "b.dwo", emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: GNU)
!1 = !DIFile(filename: "b.cpp", directory: "/proc/self/cwd", checksumkind: CSK_MD5, checksum: "8195382ac12baa5edfe47e2e4725f4a7")
!2 = !{i32 7, !"Dwarf Version", i32 5}
!3 = !{i32 2, !"Debug Info Version", i32 3}
!4 = !{i32 1, !"wchar_size", i32 4}
!5 = !{i32 8, !"PIC Level", i32 2}
!6 = !{i32 7, !"PIE Level", i32 2}
!7 = !{i32 7, !"uwtable", i32 2}
!8 = !{i32 7, !"frame-pointer", i32 2}
!9 = distinct !DISubprogram(name: "b", linkageName: "_Z1b3bar", scope: !1, file: !1, line: 2, type: !10, scopeLine: 2, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !13)
!10 = !DISubroutineType(types: !11)
!11 = !{null, !12}
!12 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "bar", file: !1, line: 1, size: 8, flags: DIFlagTypePassByValue, elements: !13, identifier: "_ZTS3bar")
!13 = !{}
!14 = !DILocalVariable(arg: 1, scope: !9, file: !1, line: 2, type: !12)
!15 = !DILocation(line: 2, column: 13, scope: !9)
!16 = !DILocation(line: 3, column: 3, scope: !9)
#--- c.ll
; ModuleID = 'c.cpp'
source_filename = "c.cpp"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux"

; Function Attrs: mustprogress noinline nounwind optnone uwtable
define dso_local noundef i32 @_Z1cv() #0 !dbg !9 {
call void @llvm.trap(), !dbg !14
unreachable, !dbg !14
}

; Function Attrs: cold noreturn nounwind memory(inaccessiblemem: write)
declare void @llvm.trap() #1

attributes #0 = { mustprogress noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
attributes #1 = { cold noreturn nounwind memory(inaccessiblemem: write) }

!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!2, !3, !4, !5, !6, !7, !8}

!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, isOptimized: false, runtimeVersion: 0, splitDebugFilename: "c.dwo", emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: GNU)
!1 = !DIFile(filename: "c.cpp", directory: "/proc/self/cwd", checksumkind: CSK_MD5, checksum: "e508eeb01e2e608fe8713f9132696ef5")
!2 = !{i32 7, !"Dwarf Version", i32 5}
!3 = !{i32 2, !"Debug Info Version", i32 3}
!4 = !{i32 1, !"wchar_size", i32 4}
!5 = !{i32 8, !"PIC Level", i32 2}
!6 = !{i32 7, !"PIE Level", i32 2}
!7 = !{i32 7, !"uwtable", i32 2}
!8 = !{i32 7, !"frame-pointer", i32 2}
!9 = distinct !DISubprogram(name: "c", linkageName: "_Z1cv", scope: !1, file: !1, line: 2, type: !10, scopeLine: 2, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0)
!10 = !DISubroutineType(types: !11)
!11 = !{!12}
!12 = !DIDerivedType(tag: DW_TAG_typedef, name: "baz", file: !1, line: 1, baseType: !13)
!13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!14 = !DILocation(line: 2, column: 11, scope: !9)
Loading