[llvm] r339122 - [DebugInfo] Reduce debug_str_offsets section size
David Blaikie via llvm-commits
llvm-commits at lists.llvm.org
Mon Aug 27 17:08:23 PDT 2018
Any idea if there's work to add str_index support to the name tables?
I guess the idea is that it's more efficient to have one fewer indirections
for strings, and worth the cost in duplicate relocations/bytes/etc? *shrug*
(also one question inline \/)
On Tue, Aug 21, 2018 at 11:22 AM Pavel Labath via llvm-commits <
llvm-commits at lists.llvm.org> wrote:
> Author: labath
> Date: Tue Aug 7 02:54:52 2018
> New Revision: 339122
>
> URL: http://llvm.org/viewvc/llvm-project?rev=339122&view=rev
> Log:
> [DebugInfo] Reduce debug_str_offsets section size
>
> Summary:
> The accelerator tables use the debug_str section to store their strings.
> However, they do not support the indirect method of access that is
> available for the debug_info section (DW_FORM_strx et al.).
>
> Currently our code is assuming that all strings can/will be referenced
> indirectly, and puts all of them into the debug_str_offsets section.
> This is generally true for regular (unsplit) dwarf, but in the DWO case,
> most of the strings in the debug_str section will only be used from the
> accelerator tables. Therefore the contents of the debug_str_offsets
> section will be largely unused and bloating the main executable.
>
> This patch rectifies this by teaching the DwarfStringPool to
> differentiate between strings accessed directly and indirectly. When a
> user inserts a string into the pool it has to declare whether that
> string will be referenced directly or not. If at least one user requsts
> indirect access, that string will be assigned an index ID and put into
> debug_str_offsets table. Otherwise, the offset table is skipped.
>
> This approach reduces the overall binary size (when compiled with
> -gdwarf-5 -gsplit-dwarf) in my tests by about 2% (debug_str_offsets is
> shrunk by 99%).
>
> Reviewers: probinson, dblaikie, JDevlieghere
>
> Subscribers: aprantl, mgrang, llvm-commits
>
> Differential Revision: https://reviews.llvm.org/D49493
>
> Added:
> llvm/trunk/test/DebugInfo/X86/string-offsets-table-order.ll
> Modified:
> llvm/trunk/include/llvm/CodeGen/DwarfStringPoolEntry.h
> llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
> llvm/trunk/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp
> llvm/trunk/lib/CodeGen/AsmPrinter/DwarfStringPool.h
> llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
> llvm/trunk/test/DebugInfo/X86/string-offsets-table.ll
> llvm/trunk/tools/dsymutil/DwarfStreamer.cpp
> llvm/trunk/tools/dsymutil/MachOUtils.cpp
> llvm/trunk/tools/dsymutil/NonRelocatableStringpool.cpp
> llvm/trunk/tools/dsymutil/NonRelocatableStringpool.h
> llvm/trunk/unittests/CodeGen/DIEHashTest.cpp
> llvm/trunk/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp
> llvm/trunk/unittests/DebugInfo/DWARF/DwarfGenerator.cpp
>
> Modified: llvm/trunk/include/llvm/CodeGen/DwarfStringPoolEntry.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/DwarfStringPoolEntry.h?rev=339122&r1=339121&r2=339122&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/CodeGen/DwarfStringPoolEntry.h (original)
> +++ llvm/trunk/include/llvm/CodeGen/DwarfStringPoolEntry.h Tue Aug 7
> 02:54:52 2018
> @@ -10,6 +10,7 @@
> #ifndef LLVM_CODEGEN_DWARFSTRINGPOOLENTRY_H
> #define LLVM_CODEGEN_DWARFSTRINGPOOLENTRY_H
>
> +#include "llvm/ADT/PointerIntPair.h"
> #include "llvm/ADT/StringMap.h"
>
> namespace llvm {
> @@ -18,34 +19,52 @@ class MCSymbol;
>
> /// Data for a string pool entry.
> struct DwarfStringPoolEntry {
> + static constexpr unsigned NotIndexed = -1;
> +
> MCSymbol *Symbol;
> unsigned Offset;
> unsigned Index;
> +
> + bool isIndexed() const { return Index != NotIndexed; }
> };
>
> /// String pool entry reference.
> -struct DwarfStringPoolEntryRef {
> - const StringMapEntry<DwarfStringPoolEntry> *I = nullptr;
> +class DwarfStringPoolEntryRef {
> + PointerIntPair<const StringMapEntry<DwarfStringPoolEntry> *, 1, bool>
> + MapEntryAndIndexed;
> +
> + const StringMapEntry<DwarfStringPoolEntry> *getMapEntry() const {
> + return MapEntryAndIndexed.getPointer();
> + }
>
> public:
> DwarfStringPoolEntryRef() = default;
> - explicit DwarfStringPoolEntryRef(
> - const StringMapEntry<DwarfStringPoolEntry> &I)
> - : I(&I) {}
> + DwarfStringPoolEntryRef(const StringMapEntry<DwarfStringPoolEntry>
> &Entry,
> + bool Indexed)
> + : MapEntryAndIndexed(&Entry, Indexed) {}
>
> - explicit operator bool() const { return I; }
> + explicit operator bool() const { return getMapEntry(); }
> MCSymbol *getSymbol() const {
> - assert(I->second.Symbol && "No symbol available!");
> - return I->second.Symbol;
> + assert(getMapEntry()->second.Symbol && "No symbol available!");
> + return getMapEntry()->second.Symbol;
> }
> - unsigned getOffset() const { return I->second.Offset; }
> - unsigned getIndex() const { return I->second.Index; }
> - StringRef getString() const { return I->first(); }
> + unsigned getOffset() const { return getMapEntry()->second.Offset; }
> + bool isIndexed() const { return MapEntryAndIndexed.getInt(); }
> + unsigned getIndex() const {
> + assert(isIndexed());
> + assert(getMapEntry()->getValue().isIndexed());
> + return getMapEntry()->second.Index;
> + }
> + StringRef getString() const { return getMapEntry()->first(); }
> /// Return the entire string pool entry for convenience.
> - DwarfStringPoolEntry getEntry() const { return I->getValue(); }
> + DwarfStringPoolEntry getEntry() const { return
> getMapEntry()->getValue(); }
>
> - bool operator==(const DwarfStringPoolEntryRef &X) const { return I ==
> X.I; }
> - bool operator!=(const DwarfStringPoolEntryRef &X) const { return I !=
> X.I; }
> + bool operator==(const DwarfStringPoolEntryRef &X) const {
> + return getMapEntry() == X.getMapEntry();
> + }
> + bool operator!=(const DwarfStringPoolEntryRef &X) const {
> + return getMapEntry() != X.getMapEntry();
> + }
> };
>
> } // end namespace llvm
>
> Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp?rev=339122&r1=339121&r2=339122&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp (original)
> +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp Tue Aug 7 02:54:52
> 2018
> @@ -2437,8 +2437,7 @@ void DwarfDebug::addAccelNameImpl(AccelT
> return;
>
> DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder;
> - DwarfStringPoolEntryRef Ref =
> - Holder.getStringPool().getEntry(*Asm, Name);
> + DwarfStringPoolEntryRef Ref = Holder.getStringPool().getEntry(*Asm,
> Name);
>
> switch (getAccelTableKind()) {
> case AccelTableKind::Apple:
>
> Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp?rev=339122&r1=339121&r2=339122&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp (original)
> +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp Tue Aug 7
> 02:54:52 2018
> @@ -24,25 +24,39 @@ DwarfStringPool::DwarfStringPool(BumpPtr
> : Pool(A), Prefix(Prefix),
>
> ShouldCreateSymbols(Asm.MAI->doesDwarfUseRelocationsAcrossSections()) {}
>
> -DwarfStringPool::EntryRef DwarfStringPool::getEntry(AsmPrinter &Asm,
> - StringRef Str) {
> +StringMapEntry<DwarfStringPool::EntryTy> &
> +DwarfStringPool::getEntryImpl(AsmPrinter &Asm, StringRef Str) {
> auto I = Pool.insert(std::make_pair(Str, EntryTy()));
> + auto &Entry = I.first->second;
> if (I.second) {
> - auto &Entry = I.first->second;
> - Entry.Index = Pool.size() - 1;
> + Entry.Index = EntryTy::NotIndexed;
> Entry.Offset = NumBytes;
> Entry.Symbol = ShouldCreateSymbols ? Asm.createTempSymbol(Prefix) :
> nullptr;
>
> NumBytes += Str.size() + 1;
> assert(NumBytes > Entry.Offset && "Unexpected overflow");
> }
> - return EntryRef(*I.first);
> + return *I.first;
> +}
> +
> +DwarfStringPool::EntryRef DwarfStringPool::getEntry(AsmPrinter &Asm,
> + StringRef Str) {
> + auto &MapEntry = getEntryImpl(Asm, Str);
> + return EntryRef(MapEntry, false);
> +}
> +
> +DwarfStringPool::EntryRef DwarfStringPool::getIndexedEntry(AsmPrinter
> &Asm,
> + StringRef Str)
> {
> + auto &MapEntry = getEntryImpl(Asm, Str);
> + if (!MapEntry.getValue().isIndexed())
> + MapEntry.getValue().Index = NumIndexedStrings++;
> + return EntryRef(MapEntry, true);
> }
>
> void DwarfStringPool::emitStringOffsetsTableHeader(AsmPrinter &Asm,
> MCSection *Section,
> MCSymbol *StartSym) {
> - if (empty())
> + if (getNumIndexedStrings() == 0)
> return;
> Asm.OutStreamer->SwitchSection(Section);
> unsigned EntrySize = 4;
> @@ -51,7 +65,7 @@ void DwarfStringPool::emitStringOffsetsT
> // table. The header consists of an entry with the contribution's
> // size (not including the size of the length field), the DWARF version
> and
> // 2 bytes of padding.
> - Asm.emitInt32(size() * EntrySize + 4);
> + Asm.emitInt32(getNumIndexedStrings() * EntrySize + 4);
> Asm.emitInt16(Asm.getDwarfVersion());
> Asm.emitInt16(0);
> // Define the symbol that marks the start of the contribution. It is
> @@ -69,12 +83,18 @@ void DwarfStringPool::emit(AsmPrinter &A
> // Start the dwarf str section.
> Asm.OutStreamer->SwitchSection(StrSection);
>
> - // Get all of the string pool entries and put them in an array by their
> ID so
> - // we can sort them.
> - SmallVector<const StringMapEntry<EntryTy> *, 64> Entries(Pool.size());
> + // Get all of the string pool entries and sort them by their offset.
> + SmallVector<const StringMapEntry<EntryTy> *, 64> Entries;
> + Entries.reserve(Pool.size());
>
> for (const auto &E : Pool)
> - Entries[E.getValue().Index] = &E;
> + Entries.push_back(&E);
> +
> + llvm::sort(
> + Entries.begin(), Entries.end(),
> + [](const StringMapEntry<EntryTy> *A, const StringMapEntry<EntryTy>
> *B) {
> + return A->getValue().Offset < B->getValue().Offset;
> + });
>
> for (const auto &Entry : Entries) {
> assert(ShouldCreateSymbols ==
> static_cast<bool>(Entry->getValue().Symbol) &&
> @@ -93,6 +113,14 @@ void DwarfStringPool::emit(AsmPrinter &A
>
> // If we've got an offset section go ahead and emit that now as well.
> if (OffsetSection) {
> + // Now only take the indexed entries and put them in an array by
> their ID so
> + // we can emit them in order.
> + Entries.resize(NumIndexedStrings);
> + for (const auto &Entry : Pool) {
> + if (Entry.getValue().isIndexed())
> + Entries[Entry.getValue().Index] = &Entry;
> + }
> +
> Asm.OutStreamer->SwitchSection(OffsetSection);
> unsigned size = 4; // FIXME: DWARF64 is 8.
> for (const auto &Entry : Entries)
>
> Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfStringPool.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfStringPool.h?rev=339122&r1=339121&r2=339122&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfStringPool.h (original)
> +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfStringPool.h Tue Aug 7
> 02:54:52 2018
> @@ -30,8 +30,11 @@ class DwarfStringPool {
> StringMap<EntryTy, BumpPtrAllocator &> Pool;
> StringRef Prefix;
> unsigned NumBytes = 0;
> + unsigned NumIndexedStrings = 0;
> bool ShouldCreateSymbols;
>
> + StringMapEntry<EntryTy> &getEntryImpl(AsmPrinter &Asm, StringRef Str);
> +
> public:
> using EntryRef = DwarfStringPoolEntryRef;
>
> @@ -48,8 +51,15 @@ public:
>
> unsigned size() const { return Pool.size(); }
>
> + unsigned getNumIndexedStrings() const { return NumIndexedStrings; }
> +
> /// Get a reference to an entry in the string pool.
> EntryRef getEntry(AsmPrinter &Asm, StringRef Str);
> +
> + /// Same as getEntry, except that you can use EntryRef::getIndex to
> obtain a
> + /// unique ID of this entry (e.g., for use in indexed forms like
> + /// DW_FORM_strx).
> + EntryRef getIndexedEntry(AsmPrinter &Asm, StringRef Str);
> };
>
> } // end namespace llvm
>
> Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp?rev=339122&r1=339121&r2=339122&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp (original)
> +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp Tue Aug 7 02:54:52
> 2018
> @@ -243,9 +243,14 @@ void DwarfUnit::addString(DIE &Die, dwar
> DIEInlineString(String, DIEValueAllocator));
> return;
> }
> - auto StringPoolEntry = DU->getStringPool().getEntry(*Asm, String);
> dwarf::Form IxForm =
> isDwoUnit() ? dwarf::DW_FORM_GNU_str_index : dwarf::DW_FORM_strp;
> +
> + auto StringPoolEntry =
> + useSegmentedStringOffsetsTable() || IxForm ==
> dwarf::DW_FORM_GNU_str_index
> + ? DU->getStringPool().getIndexedEntry(*Asm, String)
> + : DU->getStringPool().getEntry(*Asm, String);
> +
> // For DWARF v5 and beyond, use the smallest strx? form possible.
> if (useSegmentedStringOffsetsTable()) {
> IxForm = dwarf::DW_FORM_strx1;
>
> Added: llvm/trunk/test/DebugInfo/X86/string-offsets-table-order.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/X86/string-offsets-table-order.ll?rev=339122&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/DebugInfo/X86/string-offsets-table-order.ll (added)
> +++ llvm/trunk/test/DebugInfo/X86/string-offsets-table-order.ll Tue Aug 7
> 02:54:52 2018
> @@ -0,0 +1,79 @@
> +; REQUIRES: object-emission
> +; RUN: llc -mtriple=x86_64-unknown-linux-gnu -split-dwarf-file=foo.dwo
> -filetype=obj < %s \
> +; RUN: | llvm-dwarfdump -v - | FileCheck %s
> +
> +; This triggers a situation where the order of entries in the .debug_str
> and
> +; .debug_str_offsets sections does not match and makes sure that all
> entries are
> +; still wired up correctly.
> +
> +; Produced with "clang -S -emit-llvm -gdwarf-5" from source "int X;",
> copied
> +; three times and modified by hand.
>
Could you describe in the comment what modifications were necessary?
> +
> +; CHECK: .debug_info contents:
> +; CHECK: DW_TAG_compile_unit
> +; CHECK: DW_AT_comp_dir [DW_FORM_strx1] ( indexed (00000001) string =
> "X3")
> +; CHECK: DW_TAG_compile_unit
> +; CHECK: DW_AT_comp_dir [DW_FORM_strx1] ( indexed (00000002) string =
> "X2")
> +; CHECK: DW_TAG_compile_unit
> +; CHECK: DW_AT_comp_dir [DW_FORM_strx1] ( indexed (00000003) string =
> "X1")
> +; CHECK: .debug_info.dwo contents:
> +
> +; CHECK: .debug_str contents:
> +; CHECK: 0x[[X3:[0-9a-f]*]]: "X3"
> +; CHECK: 0x[[X1:[0-9a-f]*]]: "X1"
> +; CHECK: 0x[[X2:[0-9a-f]*]]: "X2"
> +
> +; CHECK: .debug_str_offsets contents:
> +; CHECK: Format = DWARF32, Version = 5
> +; CHECK-NEXT: 00000000 "foo.dwo"
> +; CHECK-NEXT: [[X3]] "X3"
> +; CHECK-NEXT: [[X2]] "X2"
> +; CHECK-NEXT: [[X1]] "X1"
> +; CHECK-EMPTY:
> +
> +
> +
> +!llvm.dbg.cu = !{!10, !20, !30}
> +!llvm.module.flags = !{!0, !1, !2}
> +!llvm.ident = !{!3}
> +
> +!0 = !{i32 2, !"Dwarf Version", i32 5}
> +!1 = !{i32 2, !"Debug Info Version", i32 3}
> +!2 = !{i32 1, !"wchar_size", i32 4}
> +!3 = !{!"clang version 7.0.0 (trunk 337353) (llvm/trunk 337361)"}
> +
> +
> + at X1 = dso_local global i32 0, align 4, !dbg !11
> +
> +!10 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !13,
> producer: "clang version 7.0.0 (trunk 337353) (llvm/trunk 337361)",
> isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !14,
> globals: !15)
> +!11 = !DIGlobalVariableExpression(var: !12, expr: !DIExpression())
> +!12 = distinct !DIGlobalVariable(name: "X1", scope: !10, file: !16, line:
> 1, type: !17, isLocal: false, isDefinition: true)
> +!13 = !DIFile(filename: "-", directory: "X3", checksumkind: CSK_MD5,
> checksum: "f2e6e10e303927a308f1645fbf6f710e")
> +!14 = !{}
> +!15 = !{!11}
> +!16 = !DIFile(filename: "<stdin>", directory: "X3", checksumkind:
> CSK_MD5, checksum: "f2e6e10e303927a308f1645fbf6f710e")
> +!17 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
> +
> +
> + at X2 = dso_local global i32 0, align 4, !dbg !21
> +
> +!20 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !23,
> producer: "clang version 7.0.0 (trunk 337353) (llvm/trunk 337361)",
> isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !24,
> globals: !25)
> +!21 = !DIGlobalVariableExpression(var: !22, expr: !DIExpression())
> +!22 = distinct !DIGlobalVariable(name: "X2", scope: !20, file: !26, line:
> 1, type: !27, isLocal: false, isDefinition: true)
> +!23 = !DIFile(filename: "-", directory: "X2", checksumkind: CSK_MD5,
> checksum: "f2e6e10e303927a308f1645fbf6f710e")
> +!24 = !{}
> +!25 = !{!21}
> +!26 = !DIFile(filename: "<stdin>", directory: "X2", checksumkind:
> CSK_MD5, checksum: "f2e6e10e303927a308f1645fbf6f710e")
> +!27 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
> +
> +
> + at X3 = dso_local global i32 0, align 4, !dbg !31
> +
> +!30 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !33,
> producer: "clang version 7.0.0 (trunk 337353) (llvm/trunk 337361)",
> isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !34,
> globals: !35)
> +!31 = !DIGlobalVariableExpression(var: !32, expr: !DIExpression())
> +!32 = distinct !DIGlobalVariable(name: "X3", scope: !30, file: !36, line:
> 1, type: !37, isLocal: false, isDefinition: true)
> +!33 = !DIFile(filename: "-", directory: "X1", checksumkind: CSK_MD5,
> checksum: "f2e6e10e303927a308f1645fbf6f710e")
> +!34 = !{}
> +!35 = !{!31}
> +!36 = !DIFile(filename: "<stdin>", directory: "X1", checksumkind:
> CSK_MD5, checksum: "f2e6e10e303927a308f1645fbf6f710e")
> +!37 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
>
> Modified: llvm/trunk/test/DebugInfo/X86/string-offsets-table.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/X86/string-offsets-table.ll?rev=339122&r1=339121&r2=339122&view=diff
>
> ==============================================================================
> --- llvm/trunk/test/DebugInfo/X86/string-offsets-table.ll (original)
> +++ llvm/trunk/test/DebugInfo/X86/string-offsets-table.ll Tue Aug 7
> 02:54:52 2018
> @@ -1,7 +1,7 @@
> ; REQUIRES: object-emission
> ; RUN: llc -mtriple=x86_64-unknown-linux-gnu -filetype=obj < %s |
> llvm-dwarfdump -v - \
> ; RUN: | FileCheck --check-prefix=MONOLITHIC %s
> -; RUN: llc -mtriple=x86_64-unknown-linux-gnu -split-dwarf-file=%t.dwo
> -filetype=obj < %s \
> +; RUN: llc -mtriple=x86_64-unknown-linux-gnu -split-dwarf-file=foo.dwo
> -filetype=obj < %s \
> ; RUN: | llvm-dwarfdump -v - | FileCheck --check-prefix=SPLIT %s
>
> ; This basic test checks the emission of a DWARF v5 string offsets table
> in
> @@ -59,6 +59,8 @@
> ; SPLIT: DW_TAG_compile_unit
> ; SPLIT-NOT: {{DW_TAG|contents:}}
> ; SPLIT: DW_AT_str_offsets_base [DW_FORM_sec_offset] (0x00000008)
> +; SPLIT: DW_AT_GNU_dwo_name [DW_FORM_strx1] ( indexed (00000000)
> string = "foo.dwo")
> +; SPLIT: DW_AT_comp_dir [DW_FORM_strx1] ( indexed (00000001) string
> = "/home/test")
>
> ; Check for the split CU in .debug_info.dwo.
> ; SPLIT: .debug_info.dwo contents:
> @@ -79,10 +81,10 @@
> ;
> ; Extract the string offsets referenced in the main file by the skeleton
> unit.
> ; SPLIT: .debug_str contents:
> -; SPLIT-NEXT: 0x00000000:{{.*}}
> -; SPLIT-NEXT: 0x[[STRING2SPLIT:[0-9a-f]*]]{{.*}}
> -; SPLIT-NEXT: 0x[[STRING3SPLIT:[0-9a-f]*]]{{.*}}
> -; SPLIT-NEXT: 0x[[STRING4SPLIT:[0-9a-f]*]]{{.*}}
> +; SPLIT-NEXT: 0x00000000: "foo.dwo"
> +; SPLIT-NEXT: 0x[[STRING2SPLIT:[0-9a-f]*]]: "/home/test"
> +; SPLIT-NEXT: 0x[[STRING3SPLIT:[0-9a-f]*]]: "E"
> +; SPLIT-NEXT: 0x[[STRING4SPLIT:[0-9a-f]*]]: "glob"
> ;
> ; Extract the string offsets referenced in the .dwo file by the split
> unit.
> ; SPLIT: .debug_str.dwo contents:
> @@ -91,13 +93,15 @@
> ; SPLIT-NEXT: 0x[[STRING3DWO:[0-9a-f]*]]{{.*}}
> ;
> ; Check the string offsets sections in both the main and the .dwo files
> and
> -; verify that the extracted string offsets are referenced correctly.
> +; verify that the extracted string offsets are referenced correctly. The
> +; sections should contain only the offsets of strings that are actually
> +; referenced by the debug info.
> ; SPLIT: .debug_str_offsets contents:
> -; SPLIT-NEXT: 0x00000000: Contribution size = 20, Format = DWARF32,
> Version = 5
> -; SPLIT-NEXT: 0x00000008: 00000000{{.*}}
> -; SPLIT-NEXT: 0x0000000c: [[STRING2SPLIT]]
> -; SPLIT-NEXT: 0x00000010: [[STRING3SPLIT]]
> -; SPLIT-NEXT: 0x00000014: [[STRING4SPLIT]]
> +; SPLIT-NEXT: 0x00000000: Contribution size = 12, Format = DWARF32,
> Version = 5
> +; SPLIT-NEXT: 0x00000008: 00000000 "foo.dwo"
> +; SPLIT-NEXT: 0x0000000c: [[STRING2SPLIT]] "/home/test"
> +; SPLIT-EMPTY:
> +
> ; SPLIT: .debug_str_offsets.dwo contents:
> ; SPLIT-NEXT: 0x00000000: Contribution size = 36, Format = DWARF32,
> Version = 5
> ; SPLIT-NEXT: 0x00000008: 00000000{{.*}}
>
> Modified: llvm/trunk/tools/dsymutil/DwarfStreamer.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/DwarfStreamer.cpp?rev=339122&r1=339121&r2=339122&view=diff
>
> ==============================================================================
> --- llvm/trunk/tools/dsymutil/DwarfStreamer.cpp (original)
> +++ llvm/trunk/tools/dsymutil/DwarfStreamer.cpp Tue Aug 7 02:54:52 2018
> @@ -190,10 +190,8 @@ void DwarfStreamer::emitDIE(DIE &Die) {
> /// Emit the debug_str section stored in \p Pool.
> void DwarfStreamer::emitStrings(const NonRelocatableStringpool &Pool) {
> Asm->OutStreamer->SwitchSection(MOFI->getDwarfStrSection());
> - std::vector<DwarfStringPoolEntryRef> Entries = Pool.getEntries();
> + std::vector<DwarfStringPoolEntryRef> Entries =
> Pool.getEntriesForEmission();
> for (auto Entry : Entries) {
> - if (Entry.getIndex() == -1U)
> - break;
> // Emit the string itself.
> Asm->OutStreamer->EmitBytes(Entry.getString());
> // Emit a null terminator.
>
> Modified: llvm/trunk/tools/dsymutil/MachOUtils.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/MachOUtils.cpp?rev=339122&r1=339121&r2=339122&view=diff
>
> ==============================================================================
> --- llvm/trunk/tools/dsymutil/MachOUtils.cpp (original)
> +++ llvm/trunk/tools/dsymutil/MachOUtils.cpp Tue Aug 7 02:54:52 2018
> @@ -514,10 +514,9 @@ bool generateDsymCompanion(const DebugMa
> // Reproduce that behavior for now (there is corresponding code in
> // transferSymbol).
> OutFile << '\0';
> - std::vector<DwarfStringPoolEntryRef> Strings =
> NewStrings.getEntries();
> + std::vector<DwarfStringPoolEntryRef> Strings =
> + NewStrings.getEntriesForEmission();
> for (auto EntryRef : Strings) {
> - if (EntryRef.getIndex() == -1U)
> - break;
> OutFile.write(EntryRef.getString().data(),
> EntryRef.getString().size() + 1);
> }
>
> Modified: llvm/trunk/tools/dsymutil/NonRelocatableStringpool.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/NonRelocatableStringpool.cpp?rev=339122&r1=339121&r2=339122&view=diff
>
> ==============================================================================
> --- llvm/trunk/tools/dsymutil/NonRelocatableStringpool.cpp (original)
> +++ llvm/trunk/tools/dsymutil/NonRelocatableStringpool.cpp Tue Aug 7
> 02:54:52 2018
> @@ -18,27 +18,28 @@ DwarfStringPoolEntryRef NonRelocatableSt
>
> auto I = Strings.insert({S, DwarfStringPoolEntry()});
> auto &Entry = I.first->second;
> - if (I.second || Entry.Index == -1U) {
> + if (I.second || !Entry.isIndexed()) {
> Entry.Index = NumEntries++;
> Entry.Offset = CurrentEndOffset;
> Entry.Symbol = nullptr;
> CurrentEndOffset += S.size() + 1;
> }
> - return DwarfStringPoolEntryRef(*I.first);
> + return DwarfStringPoolEntryRef(*I.first, true);
> }
>
> StringRef NonRelocatableStringpool::internString(StringRef S) {
> - DwarfStringPoolEntry Entry{nullptr, 0, -1U};
> + DwarfStringPoolEntry Entry{nullptr, 0,
> DwarfStringPoolEntry::NotIndexed};
> auto InsertResult = Strings.insert({S, Entry});
> return InsertResult.first->getKey();
> }
>
> std::vector<DwarfStringPoolEntryRef>
> -NonRelocatableStringpool::getEntries() const {
> +NonRelocatableStringpool::getEntriesForEmission() const {
> std::vector<DwarfStringPoolEntryRef> Result;
> Result.reserve(Strings.size());
> for (const auto &E : Strings)
> - Result.emplace_back(E);
> + if (E.getValue().isIndexed())
> + Result.emplace_back(E, true);
> llvm::sort(
> Result.begin(), Result.end(),
> [](const DwarfStringPoolEntryRef A, const DwarfStringPoolEntryRef
> B) {
>
> Modified: llvm/trunk/tools/dsymutil/NonRelocatableStringpool.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/NonRelocatableStringpool.h?rev=339122&r1=339121&r2=339122&view=diff
>
> ==============================================================================
> --- llvm/trunk/tools/dsymutil/NonRelocatableStringpool.h (original)
> +++ llvm/trunk/tools/dsymutil/NonRelocatableStringpool.h Tue Aug 7
> 02:54:52 2018
> @@ -53,7 +53,9 @@ public:
>
> uint64_t getSize() { return CurrentEndOffset; }
>
> - std::vector<DwarfStringPoolEntryRef> getEntries() const;
> + /// Return the list of strings to be emitted. This does not contain the
> + /// strings which were added via internString only.
> + std::vector<DwarfStringPoolEntryRef> getEntriesForEmission() const;
>
> private:
> MapTy Strings;
>
> Modified: llvm/trunk/unittests/CodeGen/DIEHashTest.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/CodeGen/DIEHashTest.cpp?rev=339122&r1=339121&r2=339122&view=diff
>
> ==============================================================================
> --- llvm/trunk/unittests/CodeGen/DIEHashTest.cpp (original)
> +++ llvm/trunk/unittests/CodeGen/DIEHashTest.cpp Tue Aug 7 02:54:52 2018
> @@ -31,8 +31,8 @@ private:
> public:
> DIEString getString(StringRef S) {
> DwarfStringPoolEntry Entry = {nullptr, 1, 1};
> - return DIEString(
> - DwarfStringPoolEntryRef(*Pool.insert(std::make_pair(S,
> Entry)).first));
> + return DIEString(DwarfStringPoolEntryRef(
> + *Pool.insert(std::make_pair(S, Entry)).first, Entry.isIndexed()));
> }
> };
>
>
> Modified: llvm/trunk/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp?rev=339122&r1=339121&r2=339122&view=diff
>
> ==============================================================================
> --- llvm/trunk/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp (original)
> +++ llvm/trunk/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp Tue Aug 7
> 02:54:52 2018
> @@ -1007,6 +1007,99 @@ TEST(DWARFDebugInfo, TestDWARF32Version4
> TestAddresses<4, AddrType>();
> }
>
> +TEST(DWARFDebugInfo, TestStringOffsets) {
> + Triple Triple = getHostTripleForAddrSize(sizeof(void *));
> + if (!isConfigurationSupported(Triple))
> + return;
> +
> + const char *String1 = "Hello";
> + const char *String2 = "World";
> +
> + auto ExpectedDG = dwarfgen::Generator::create(Triple, 5);
> + ASSERT_THAT_EXPECTED(ExpectedDG, Succeeded());
> + dwarfgen::Generator *DG = ExpectedDG.get().get();
> + dwarfgen::CompileUnit &CU = DG->addCompileUnit();
> + dwarfgen::DIE CUDie = CU.getUnitDIE();
> +
> + CUDie.addStrOffsetsBaseAttribute();
> +
> + uint16_t Attr = DW_AT_lo_user;
> +
> + // Create our strings. First we create a non-indexed reference to
> String1,
> + // followed by an indexed String2. Finally, we add an indexed reference
> to
> + // String1.
> + const auto Attr1 = static_cast<dwarf::Attribute>(Attr++);
> + CUDie.addAttribute(Attr1, DW_FORM_strp, String1);
> +
> + const auto Attr2 = static_cast<dwarf::Attribute>(Attr++);
> + CUDie.addAttribute(Attr2, DW_FORM_strx, String2);
> +
> + const auto Attr3 = static_cast<dwarf::Attribute>(Attr++);
> + CUDie.addAttribute(Attr3, DW_FORM_strx, String1);
> +
> + // Generate the DWARF
> + StringRef FileBytes = DG->generate();
> + MemoryBufferRef FileBuffer(FileBytes, "dwarf");
> + auto Obj = object::ObjectFile::createObjectFile(FileBuffer);
> + ASSERT_TRUE((bool)Obj);
> + std::unique_ptr<DWARFContext> DwarfContext =
> DWARFContext::create(**Obj);
> + uint32_t NumCUs = DwarfContext->getNumCompileUnits();
> + ASSERT_EQ(NumCUs, 1u);
> + DWARFUnit *U = DwarfContext->getUnitAtIndex(0);
> + auto DieDG = U->getUnitDIE(false);
> + ASSERT_TRUE(DieDG.isValid());
> +
> + // Now make sure the string offsets came out properly. Attr2 should
> have index
> + // 0 (because it was the first indexed string) even though the string
> itself
> + // was added eariler.
> + auto Extracted1 = toString(DieDG.find(Attr1));
> + ASSERT_TRUE((bool)Extracted1);
> + EXPECT_STREQ(String1, *Extracted1);
> +
> + Optional<DWARFFormValue> Form2 = DieDG.find(Attr2);
> + ASSERT_TRUE((bool)Form2);
> + EXPECT_EQ(0u, Form2->getRawUValue());
> + auto Extracted2 = toString(Form2);
> + ASSERT_TRUE((bool)Extracted2);
> + EXPECT_STREQ(String2, *Extracted2);
> +
> + Optional<DWARFFormValue> Form3 = DieDG.find(Attr3);
> + ASSERT_TRUE((bool)Form3);
> + EXPECT_EQ(1u, Form3->getRawUValue());
> + auto Extracted3 = toString(Form3);
> + ASSERT_TRUE((bool)Extracted3);
> + EXPECT_STREQ(String1, *Extracted3);
> +}
> +
> +TEST(DWARFDebugInfo, TestEmptyStringOffsets) {
> + Triple Triple = getHostTripleForAddrSize(sizeof(void *));
> + if (!isConfigurationSupported(Triple))
> + return;
> +
> + const char *String1 = "Hello";
> +
> + auto ExpectedDG = dwarfgen::Generator::create(Triple, 5);
> + ASSERT_THAT_EXPECTED(ExpectedDG, Succeeded());
> + dwarfgen::Generator *DG = ExpectedDG.get().get();
> + dwarfgen::CompileUnit &CU = DG->addCompileUnit();
> + dwarfgen::DIE CUDie = CU.getUnitDIE();
> +
> + uint16_t Attr = DW_AT_lo_user;
> +
> + // We shall insert only one string. It will be referenced directly.
> + const auto Attr1 = static_cast<dwarf::Attribute>(Attr++);
> + CUDie.addAttribute(Attr1, DW_FORM_strp, String1);
> +
> + // Generate the DWARF
> + StringRef FileBytes = DG->generate();
> + MemoryBufferRef FileBuffer(FileBytes, "dwarf");
> + auto Obj = object::ObjectFile::createObjectFile(FileBuffer);
> + ASSERT_TRUE((bool)Obj);
> + std::unique_ptr<DWARFContext> DwarfContext =
> DWARFContext::create(**Obj);
> + EXPECT_TRUE(
> + DwarfContext->getDWARFObj().getStringOffsetSection().Data.empty());
> +}
> +
> TEST(DWARFDebugInfo, TestRelations) {
> Triple Triple = getHostTripleForAddrSize(sizeof(void *));
> if (!isConfigurationSupported(Triple))
>
> Modified: llvm/trunk/unittests/DebugInfo/DWARF/DwarfGenerator.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/DebugInfo/DWARF/DwarfGenerator.cpp?rev=339122&r1=339121&r2=339122&view=diff
>
> ==============================================================================
> --- llvm/trunk/unittests/DebugInfo/DWARF/DwarfGenerator.cpp (original)
> +++ llvm/trunk/unittests/DebugInfo/DWARF/DwarfGenerator.cpp Tue Aug 7
> 02:54:52 2018
> @@ -71,15 +71,20 @@ void dwarfgen::DIE::addAttribute(uint16_
> break;
>
> case DW_FORM_strp:
> + Die->addValue(
> + DG.getAllocator(), static_cast<dwarf::Attribute>(A), Form,
> + DIEString(DG.getStringPool().getEntry(*DG.getAsmPrinter(),
> String)));
> + break;
> +
> case DW_FORM_GNU_str_index:
> case DW_FORM_strx:
> case DW_FORM_strx1:
> case DW_FORM_strx2:
> case DW_FORM_strx3:
> case DW_FORM_strx4:
> - Die->addValue(
> - DG.getAllocator(), static_cast<dwarf::Attribute>(A), Form,
> - DIEString(DG.getStringPool().getEntry(*DG.getAsmPrinter(),
> String)));
> + Die->addValue(DG.getAllocator(), static_cast<dwarf::Attribute>(A),
> Form,
> + DIEString(DG.getStringPool().getIndexedEntry(
> + *DG.getAsmPrinter(), String)));
> break;
>
> default:
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20180827/842066e4/attachment.html>
More information about the llvm-commits
mailing list