Skip to content

Commit 22afe19

Browse files
committed
DebugInfo: Rebuild dwp debug_info index column from v5 indexes more robustly
the v4 rebuilding is a best-effort because it's not possible to reliably parse the DWO ID as it requires the abbrev section (& if the index isn't trustworthy then there's no way to find the associated abbrev section contribution for a given info section contribution) But in v5 the DWO ID/type signature is in the header and can be rebuilt losslessly (only at the cost of performance of rescanning/parsing the headers of all the units), so let's implement that. the testing isn't /ideal/ - I think the testing should've been implemented as a hardcoded dwp file with a corrupted/incorrect index, then the test could've demonstrated that reparsing the index produces the right answer - but this is a quick port of the existing v5 test back to v4 so that we don't lose coverage on the v4 codepath now that it's separated from the v5 codepath. Differential Revision: https://reviews.llvm.org/D146662
1 parent 4d4c0f9 commit 22afe19

File tree

2 files changed

+132
-4
lines changed

2 files changed

+132
-4
lines changed

llvm/lib/DebugInfo/DWARF/DWARFContext.cpp

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
#include "llvm/Support/Error.h"
4949
#include "llvm/Support/Format.h"
5050
#include "llvm/Support/LEB128.h"
51+
#include "llvm/Support/FormatVariadic.h"
5152
#include "llvm/Support/MemoryBuffer.h"
5253
#include "llvm/Support/Path.h"
5354
#include "llvm/Support/raw_ostream.h"
@@ -779,7 +780,7 @@ bool DWARFContext::verify(raw_ostream &OS, DIDumpOptions DumpOpts) {
779780
return Success;
780781
}
781782

782-
void fixupIndex(const DWARFObject &DObj, DWARFContext &C,
783+
void fixupIndexV4(const DWARFObject &DObj, DWARFContext &C,
783784
DWARFUnitIndex &Index) {
784785
using EntryType = DWARFUnitIndex::Entry::SectionContribution;
785786
using EntryMap = DenseMap<uint32_t, EntryType>;
@@ -847,14 +848,62 @@ void fixupIndex(const DWARFObject &DObj, DWARFContext &C,
847848
return;
848849
}
849850

851+
void fixupIndexV5(const DWARFObject &DObj, DWARFContext &C,
852+
DWARFUnitIndex &Index) {
853+
DenseMap<uint64_t, uint64_t> Map;
854+
855+
DObj.forEachInfoDWOSections([&](const DWARFSection &S) {
856+
if (!(C.getParseCUTUIndexManually() ||
857+
S.Data.size() >= std::numeric_limits<uint32_t>::max()))
858+
return;
859+
DWARFDataExtractor Data(DObj, S, C.isLittleEndian(), 0);
860+
uint64_t Offset = 0;
861+
while (Data.isValidOffset(Offset)) {
862+
DWARFUnitHeader Header;
863+
if (!Header.extract(C, Data, &Offset, DWARFSectionKind::DW_SECT_INFO)) {
864+
logAllUnhandledErrors(
865+
createError("Failed to parse unit header in DWP file"), errs());
866+
break;
867+
}
868+
bool CU = Header.getUnitType() == DW_UT_split_compile;
869+
uint64_t Sig = CU ? *Header.getDWOId() : Header.getTypeHash();
870+
Map[Sig] = Header.getOffset();
871+
Offset = Header.getNextUnitOffset();
872+
}
873+
});
874+
for (DWARFUnitIndex::Entry &E : Index.getMutableRows()) {
875+
if (!E.isValid())
876+
continue;
877+
DWARFUnitIndex::Entry::SectionContribution &CUOff = E.getContribution();
878+
auto Iter = Map.find(E.getSignature());
879+
if (Iter == Map.end()) {
880+
logAllUnhandledErrors(
881+
createError("Could not find unit with signature 0x" +
882+
Twine::utohexstr(E.getSignature()) + " in the Map"),
883+
errs());
884+
break;
885+
}
886+
CUOff.setOffset(Iter->second);
887+
}
888+
}
889+
890+
void fixupIndex(const DWARFObject &DObj, DWARFContext &C,
891+
DWARFUnitIndex &Index) {
892+
if (Index.getVersion() < 5)
893+
fixupIndexV4(DObj, C, Index);
894+
else
895+
fixupIndexV5(DObj, C, Index);
896+
}
897+
850898
const DWARFUnitIndex &DWARFContext::getCUIndex() {
851899
if (CUIndex)
852900
return *CUIndex;
853901

854902
DataExtractor CUIndexData(DObj->getCUIndexSection(), isLittleEndian(), 0);
855903
CUIndex = std::make_unique<DWARFUnitIndex>(DW_SECT_INFO);
856-
CUIndex->parse(CUIndexData);
857-
fixupIndex(*DObj, *this, *CUIndex.get());
904+
bool IsParseSuccessful = CUIndex->parse(CUIndexData);
905+
if (IsParseSuccessful)
906+
fixupIndex(*DObj, *this, *CUIndex);
858907
return *CUIndex;
859908
}
860909

@@ -868,7 +917,7 @@ const DWARFUnitIndex &DWARFContext::getTUIndex() {
868917
// If we are parsing TU-index and for .debug_types section we don't need
869918
// to do anything.
870919
if (isParseSuccessful && TUIndex->getVersion() != 2)
871-
fixupIndex(*DObj, *this, *TUIndex.get());
920+
fixupIndex(*DObj, *this, *TUIndex);
872921
return *TUIndex;
873922
}
874923

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# This test checks if we can correctly parse manull cu and tu index for DWARF4.
2+
3+
# RUN: llvm-mc -triple x86_64-unknown-linux %s -filetype=obj -o %t.o \
4+
# RUN: -split-dwarf-file=%t.dwo -dwarf-version=4
5+
# RUN: llvm-dwp %t.dwo -o %t.dwp
6+
# RUN: llvm-dwarfdump -debug-info -debug-types -debug-cu-index -debug-tu-index %t.dwp | FileCheck %s
7+
# RUN: llvm-dwarfdump -debug-info -debug-types -debug-cu-index -debug-tu-index -manaully-generate-unit-index %t.dwp | FileCheck %s
8+
9+
## Note: In order to check whether the type unit index is generated
10+
## there is no need to add the missing DIEs for the structure type of the type unit.
11+
12+
# CHECK-DAG: .debug_info.dwo contents:
13+
# CHECK: 0x00000000: Compile Unit: length = 0x00000010, format = DWARF32, version = 0x0004, abbr_offset = 0x0000, addr_size = 0x08 (next unit at 0x00000014)
14+
# CHECK: DW_AT_GNU_dwo_id ([[CUID1:.*]])
15+
# CHECK-DAG: .debug_types.dwo contents:
16+
# CHECK: 0x00000000: Type Unit: length = 0x00000016, format = DWARF32, version = 0x0004, abbr_offset = 0x0000, addr_size = 0x08, name = '', type_signature = [[TUID1:.*]], type_offset = 0x0019 (next unit at 0x0000001a)
17+
# CHECK: 0x0000001a: Type Unit: length = 0x00000016, format = DWARF32, version = 0x0004, abbr_offset = 0x0000, addr_size = 0x08, name = '', type_signature = [[TUID2:.*]], type_offset = 0x0019 (next unit at 0x00000034)
18+
# CHECK-DAG: .debug_cu_index contents:
19+
# CHECK: version = 2, units = 1, slots = 2
20+
# CHECK: Index Signature INFO ABBREV
21+
# CHECK: 2 [[CUID1]] [0x0000000000000000, 0x0000000000000014) [0x00000000, 0x00000013)
22+
# CHECK-DAG: .debug_tu_index contents:
23+
# CHECK: version = 2, units = 2, slots = 4
24+
# CHECK: Index Signature TYPES ABBREV
25+
# CHECK: 1 [[TUID1]] [0x0000000000000000, 0x000000000000001a) [0x00000000, 0x00000013)
26+
# CHECK: 4 [[TUID2]] [0x000000000000001a, 0x0000000000000034) [0x00000000, 0x00000013)
27+
28+
.section .debug_types.dwo,"e",@progbits
29+
.long .Ldebug_info_dwo_end0-.Ldebug_info_dwo_start0 # Length of Unit
30+
.Ldebug_info_dwo_start0:
31+
.short 4 # DWARF version number
32+
.long 0 # Offset Into Abbrev. Section
33+
.byte 8 # Address Size (in bytes)
34+
.quad 5657452045627120676 # Type Signature
35+
.long 25 # Type DIE Offset
36+
.byte 2 # Abbrev [2] DW_TAG_type_unit
37+
.byte 3 # Abbrev [3] DW_TAG_structure_type
38+
.byte 0 # End Of Children Mark
39+
.Ldebug_info_dwo_end0:
40+
.section .debug_types.dwo,"e",@progbits
41+
.long .Ldebug_info_dwo_end1-.Ldebug_info_dwo_start1 # Length of Unit
42+
.Ldebug_info_dwo_start1:
43+
.short 4 # DWARF version number
44+
.long 0 # Offset Into Abbrev. Section
45+
.byte 8 # Address Size (in bytes)
46+
.quad -8528522068957683993 # Type Signature
47+
.long 25 # Type DIE Offset
48+
.byte 2 # Abbrev [2] DW_TAG_type_unit
49+
.byte 3 # Abbrev [3] DW_TAG_structure_type
50+
.byte 0 # End Of Children Mark
51+
.Ldebug_info_dwo_end1:
52+
.section .debug_info.dwo,"e",@progbits
53+
.long .Ldebug_info_dwo_end2-.Ldebug_info_dwo_start2 # Length of Unit
54+
.Ldebug_info_dwo_start2:
55+
.short 4 # DWARF version number
56+
.long 0 # Offset Into Abbrev. Section
57+
.byte 8 # Address Size (in bytes)
58+
.byte 1 # Abbrev [1] DW_TAG_compile_unit
59+
.quad -6619898858003450627 # DW_AT_GNU_dwo_id
60+
.Ldebug_info_dwo_end2:
61+
.section .debug_abbrev.dwo,"e",@progbits
62+
.byte 1 # Abbreviation Code
63+
.byte 17 # DW_TAG_compile_unit
64+
.byte 0 # DW_CHILDREN_no
65+
.ascii "\261B" # DW_AT_GNU_dwo_id
66+
.byte 7 # DW_FORM_data8
67+
.byte 0 # EOM(1)
68+
.byte 0 # EOM(2)
69+
.byte 2 # Abbreviation Code
70+
.byte 65 # DW_TAG_type_unit
71+
.byte 1 # DW_CHILDREN_yes
72+
.byte 0 # EOM
73+
.byte 0 # EOM
74+
.byte 3 # Abbreviation Code
75+
.byte 0x13 # DW_TAG_structure_unit
76+
.byte 0 # DW_CHILDREN_no
77+
.byte 0 # EOM
78+
.byte 0 # EOM
79+
.byte 0 # EOM

0 commit comments

Comments
 (0)