1 //===- DWARFDebugPubTable.cpp ---------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "llvm/DebugInfo/DWARF/DWARFDebugPubTable.h"
10 #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
11 #include "llvm/ADT/StringRef.h"
12 #include "llvm/BinaryFormat/Dwarf.h"
13 #include "llvm/Support/DataExtractor.h"
14 #include "llvm/Support/Errc.h"
15 #include "llvm/Support/Format.h"
16 #include "llvm/Support/raw_ostream.h"
20 using namespace dwarf
;
22 void DWARFDebugPubTable::extract(
23 DWARFDataExtractor Data
, bool GnuStyle
,
24 function_ref
<void(Error
)> RecoverableErrorHandler
) {
25 this->GnuStyle
= GnuStyle
;
28 while (Data
.isValidOffset(Offset
)) {
29 uint64_t SetOffset
= Offset
;
31 Set
&NewSet
= Sets
.back();
33 DataExtractor::Cursor
C(Offset
);
34 std::tie(NewSet
.Length
, NewSet
.Format
) = Data
.getInitialLength(C
);
36 // Drop the newly added set because it does not contain anything useful
39 RecoverableErrorHandler(createStringError(
40 errc::invalid_argument
,
41 "name lookup table at offset 0x%" PRIx64
" parsing failed: %s",
42 SetOffset
, toString(C
.takeError()).c_str()));
46 Offset
= C
.tell() + NewSet
.Length
;
47 DWARFDataExtractor
SetData(Data
, Offset
);
48 const unsigned OffsetSize
= dwarf::getDwarfOffsetByteSize(NewSet
.Format
);
50 NewSet
.Version
= SetData
.getU16(C
);
51 NewSet
.Offset
= SetData
.getRelocatedValue(C
, OffsetSize
);
52 NewSet
.Size
= SetData
.getUnsigned(C
, OffsetSize
);
55 // Preserve the newly added set because at least some fields of the header
56 // are read and can be dumped.
57 RecoverableErrorHandler(
58 createStringError(errc::invalid_argument
,
59 "name lookup table at offset 0x%" PRIx64
60 " does not have a complete header: %s",
61 SetOffset
, toString(C
.takeError()).c_str()));
66 uint64_t DieRef
= SetData
.getUnsigned(C
, OffsetSize
);
69 uint8_t IndexEntryValue
= GnuStyle
? SetData
.getU8(C
) : 0;
70 StringRef Name
= SetData
.getCStrRef(C
);
72 NewSet
.Entries
.push_back(
73 {DieRef
, PubIndexEntryDescriptor(IndexEntryValue
), Name
});
77 RecoverableErrorHandler(createStringError(
78 errc::invalid_argument
,
79 "name lookup table at offset 0x%" PRIx64
" parsing failed: %s",
80 SetOffset
, toString(C
.takeError()).c_str()));
83 if (C
.tell() != Offset
)
84 RecoverableErrorHandler(createStringError(
85 errc::invalid_argument
,
86 "name lookup table at offset 0x%" PRIx64
87 " has a terminator at offset 0x%" PRIx64
88 " before the expected end at 0x%" PRIx64
,
89 SetOffset
, C
.tell() - OffsetSize
, Offset
- OffsetSize
));
93 void DWARFDebugPubTable::dump(raw_ostream
&OS
) const {
94 for (const Set
&S
: Sets
) {
95 int OffsetDumpWidth
= 2 * dwarf::getDwarfOffsetByteSize(S
.Format
);
96 OS
<< "length = " << format("0x%0*" PRIx64
, OffsetDumpWidth
, S
.Length
);
97 OS
<< ", format = " << dwarf::FormatString(S
.Format
);
98 OS
<< ", version = " << format("0x%04x", S
.Version
);
99 OS
<< ", unit_offset = "
100 << format("0x%0*" PRIx64
, OffsetDumpWidth
, S
.Offset
);
101 OS
<< ", unit_size = " << format("0x%0*" PRIx64
, OffsetDumpWidth
, S
.Size
)
103 OS
<< (GnuStyle
? "Offset Linkage Kind Name\n"
106 for (const Entry
&E
: S
.Entries
) {
107 OS
<< format("0x%0*" PRIx64
" ", OffsetDumpWidth
, E
.SecOffset
);
109 StringRef EntryLinkage
=
110 GDBIndexEntryLinkageString(E
.Descriptor
.Linkage
);
111 StringRef EntryKind
= dwarf::GDBIndexEntryKindString(E
.Descriptor
.Kind
);
112 OS
<< format("%-8s", EntryLinkage
.data()) << ' '
113 << format("%-8s", EntryKind
.data()) << ' ';
115 OS
<< '\"' << E
.Name
<< "\"\n";