Skip to content

Commit 12e832c

Browse files
committed
[DWARFYAML] Make the debug_abbrev_offset field optional.
This patch helps make the debug_abbrev_offset field optional. We don't need to calculate the value of this field in the future. Reviewed By: jhenderson Differential Revision: https://reviews.llvm.org/D86614
1 parent 97febb1 commit 12e832c

File tree

5 files changed

+115
-64
lines changed

5 files changed

+115
-64
lines changed

llvm/include/llvm/ObjectYAML/DWARFYAML.h

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ struct Unit {
113113
Optional<uint8_t> AddrSize;
114114
llvm::dwarf::UnitType Type; // Added in DWARF 5
115115
Optional<uint64_t> AbbrevTableID;
116-
yaml::Hex64 AbbrOffset;
116+
Optional<yaml::Hex64> AbbrOffset;
117117
std::vector<Entry> Entries;
118118
};
119119

@@ -231,10 +231,17 @@ struct Data {
231231
bool isEmpty() const;
232232

233233
SetVector<StringRef> getNonEmptySectionNames() const;
234-
Expected<uint64_t> getAbbrevTableIndexByID(uint64_t ID) const;
234+
235+
struct AbbrevTableInfo {
236+
uint64_t Index;
237+
uint64_t Offset;
238+
};
239+
Expected<AbbrevTableInfo> getAbbrevTableInfoByID(uint64_t ID) const;
240+
StringRef getAbbrevTableContentByIndex(uint64_t Index) const;
235241

236242
private:
237-
mutable std::unordered_map<uint64_t, uint64_t> AbbrevTableID2Index;
243+
mutable std::unordered_map<uint64_t, AbbrevTableInfo> AbbrevTableInfoMap;
244+
mutable std::unordered_map<uint64_t, std::string> AbbrevTableContents;
238245
};
239246

240247
} // end namespace DWARFYAML

llvm/lib/ObjectYAML/DWARFEmitter.cpp

Lines changed: 60 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -94,28 +94,45 @@ Error DWARFYAML::emitDebugStr(raw_ostream &OS, const DWARFYAML::Data &DI) {
9494
return Error::success();
9595
}
9696

97-
Error DWARFYAML::emitDebugAbbrev(raw_ostream &OS, const DWARFYAML::Data &DI) {
98-
for (const DWARFYAML::AbbrevTable &AbbrevTable : DI.DebugAbbrev) {
99-
uint64_t AbbrevCode = 0;
100-
for (const DWARFYAML::Abbrev &AbbrevDecl : AbbrevTable.Table) {
101-
AbbrevCode =
102-
AbbrevDecl.Code ? (uint64_t)*AbbrevDecl.Code : AbbrevCode + 1;
103-
encodeULEB128(AbbrevCode, OS);
104-
encodeULEB128(AbbrevDecl.Tag, OS);
105-
OS.write(AbbrevDecl.Children);
106-
for (auto Attr : AbbrevDecl.Attributes) {
107-
encodeULEB128(Attr.Attribute, OS);
108-
encodeULEB128(Attr.Form, OS);
109-
if (Attr.Form == dwarf::DW_FORM_implicit_const)
110-
encodeSLEB128(Attr.Value, OS);
111-
}
112-
encodeULEB128(0, OS);
113-
encodeULEB128(0, OS);
97+
StringRef DWARFYAML::Data::getAbbrevTableContentByIndex(uint64_t Index) const {
98+
assert(Index < DebugAbbrev.size() &&
99+
"Index should be less than the size of DebugAbbrev array");
100+
auto It = AbbrevTableContents.find(Index);
101+
if (It != AbbrevTableContents.cend())
102+
return It->second;
103+
104+
std::string AbbrevTableBuffer;
105+
raw_string_ostream OS(AbbrevTableBuffer);
106+
107+
uint64_t AbbrevCode = 0;
108+
for (const DWARFYAML::Abbrev &AbbrevDecl : DebugAbbrev[Index].Table) {
109+
AbbrevCode = AbbrevDecl.Code ? (uint64_t)*AbbrevDecl.Code : AbbrevCode + 1;
110+
encodeULEB128(AbbrevCode, OS);
111+
encodeULEB128(AbbrevDecl.Tag, OS);
112+
OS.write(AbbrevDecl.Children);
113+
for (auto Attr : AbbrevDecl.Attributes) {
114+
encodeULEB128(Attr.Attribute, OS);
115+
encodeULEB128(Attr.Form, OS);
116+
if (Attr.Form == dwarf::DW_FORM_implicit_const)
117+
encodeSLEB128(Attr.Value, OS);
114118
}
119+
encodeULEB128(0, OS);
120+
encodeULEB128(0, OS);
121+
}
122+
123+
// The abbreviations for a given compilation unit end with an entry
124+
// consisting of a 0 byte for the abbreviation code.
125+
OS.write_zeros(1);
126+
127+
AbbrevTableContents.insert({Index, AbbrevTableBuffer});
128+
129+
return AbbrevTableContents[Index];
130+
}
115131

116-
// The abbreviations for a given compilation unit end with an entry
117-
// consisting of a 0 byte for the abbreviation code.
118-
OS.write_zeros(1);
132+
Error DWARFYAML::emitDebugAbbrev(raw_ostream &OS, const DWARFYAML::Data &DI) {
133+
for (uint64_t I = 0; I < DI.DebugAbbrev.size(); ++I) {
134+
StringRef AbbrevTableContent = DI.getAbbrevTableContentByIndex(I);
135+
OS.write(AbbrevTableContent.data(), AbbrevTableContent.size());
119136
}
120137

121138
return Error::success();
@@ -257,16 +274,16 @@ static Expected<uint64_t> writeDIE(const DWARFYAML::Data &DI, uint64_t CUIndex,
257274
if (AbbrCode == 0 || Entry.Values.empty())
258275
return OS.tell() - EntryBegin;
259276

260-
Expected<uint64_t> AbbrevTableIndexOrErr =
261-
DI.getAbbrevTableIndexByID(AbbrevTableID);
262-
if (!AbbrevTableIndexOrErr)
277+
Expected<DWARFYAML::Data::AbbrevTableInfo> AbbrevTableInfoOrErr =
278+
DI.getAbbrevTableInfoByID(AbbrevTableID);
279+
if (!AbbrevTableInfoOrErr)
263280
return createStringError(errc::invalid_argument,
264-
toString(AbbrevTableIndexOrErr.takeError()) +
281+
toString(AbbrevTableInfoOrErr.takeError()) +
265282
" for compilation unit with index " +
266283
utostr(CUIndex));
267284

268285
ArrayRef<DWARFYAML::Abbrev> AbbrevDecls(
269-
DI.DebugAbbrev[*AbbrevTableIndexOrErr].Table);
286+
DI.DebugAbbrev[AbbrevTableInfoOrErr->Index].Table);
270287

271288
if (AbbrCode > AbbrevDecls.size())
272289
return createStringError(
@@ -425,12 +442,28 @@ Error DWARFYAML::emitDebugInfo(raw_ostream &OS, const DWARFYAML::Data &DI) {
425442

426443
writeInitialLength(Unit.Format, Length, OS, DI.IsLittleEndian);
427444
writeInteger((uint16_t)Unit.Version, OS, DI.IsLittleEndian);
445+
446+
uint64_t AbbrevTableOffset = 0;
447+
if (Unit.AbbrOffset) {
448+
AbbrevTableOffset = *Unit.AbbrOffset;
449+
} else {
450+
if (Expected<DWARFYAML::Data::AbbrevTableInfo> AbbrevTableInfoOrErr =
451+
DI.getAbbrevTableInfoByID(AbbrevTableID)) {
452+
AbbrevTableOffset = AbbrevTableInfoOrErr->Offset;
453+
} else {
454+
// The current compilation unit may not have DIEs and it will not be
455+
// able to find the associated abbrev table. We consume the error and
456+
// assign 0 to the debug_abbrev_offset in such circumstances.
457+
consumeError(AbbrevTableInfoOrErr.takeError());
458+
}
459+
}
460+
428461
if (Unit.Version >= 5) {
429462
writeInteger((uint8_t)Unit.Type, OS, DI.IsLittleEndian);
430463
writeInteger((uint8_t)AddrSize, OS, DI.IsLittleEndian);
431-
writeDWARFOffset(Unit.AbbrOffset, Unit.Format, OS, DI.IsLittleEndian);
464+
writeDWARFOffset(AbbrevTableOffset, Unit.Format, OS, DI.IsLittleEndian);
432465
} else {
433-
writeDWARFOffset(Unit.AbbrOffset, Unit.Format, OS, DI.IsLittleEndian);
466+
writeDWARFOffset(AbbrevTableOffset, Unit.Format, OS, DI.IsLittleEndian);
434467
writeInteger((uint8_t)AddrSize, OS, DI.IsLittleEndian);
435468
}
436469

llvm/lib/ObjectYAML/DWARFYAML.cpp

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -55,25 +55,31 @@ SetVector<StringRef> DWARFYAML::Data::getNonEmptySectionNames() const {
5555
return SecNames;
5656
}
5757

58-
Expected<uint64_t> DWARFYAML::Data::getAbbrevTableIndexByID(uint64_t ID) const {
59-
if (AbbrevTableID2Index.empty()) {
58+
Expected<DWARFYAML::Data::AbbrevTableInfo>
59+
DWARFYAML::Data::getAbbrevTableInfoByID(uint64_t ID) const {
60+
if (AbbrevTableInfoMap.empty()) {
61+
uint64_t AbbrevTableOffset = 0;
6062
for (auto &AbbrevTable : enumerate(DebugAbbrev)) {
6163
// If the abbrev table's ID isn't specified, we use the index as its ID.
6264
uint64_t AbbrevTableID =
6365
AbbrevTable.value().ID.getValueOr(AbbrevTable.index());
64-
auto It =
65-
AbbrevTableID2Index.insert({AbbrevTableID, AbbrevTable.index()});
66+
auto It = AbbrevTableInfoMap.insert(
67+
{AbbrevTableID, AbbrevTableInfo{/*Index=*/AbbrevTable.index(),
68+
/*Offset=*/AbbrevTableOffset}});
6669
if (!It.second)
6770
return createStringError(
6871
errc::invalid_argument,
6972
"the ID (%" PRIu64 ") of abbrev table with index %zu has been used "
7073
"by abbrev table with index %" PRIu64,
71-
AbbrevTableID, AbbrevTable.index(), It.first->second);
74+
AbbrevTableID, AbbrevTable.index(), It.first->second.Index);
75+
76+
AbbrevTableOffset +=
77+
getAbbrevTableContentByIndex(AbbrevTable.index()).size();
7278
}
7379
}
7480

75-
auto It = AbbrevTableID2Index.find(ID);
76-
if (It == AbbrevTableID2Index.end())
81+
auto It = AbbrevTableInfoMap.find(ID);
82+
if (It == AbbrevTableInfoMap.end())
7783
return createStringError(errc::invalid_argument,
7884
"cannot find abbrev table whose ID is %" PRIu64,
7985
ID);
@@ -182,7 +188,7 @@ void MappingTraits<DWARFYAML::Unit>::mapping(IO &IO, DWARFYAML::Unit &Unit) {
182188
if (Unit.Version >= 5)
183189
IO.mapRequired("UnitType", Unit.Type);
184190
IO.mapOptional("AbbrevTableID", Unit.AbbrevTableID);
185-
IO.mapRequired("AbbrOffset", Unit.AbbrOffset);
191+
IO.mapOptional("AbbrOffset", Unit.AbbrOffset);
186192
IO.mapOptional("AddrSize", Unit.AddrSize);
187193
IO.mapOptional("Entries", Unit.Entries);
188194
}

llvm/test/tools/yaml2obj/ELF/DWARF/debug-info.yaml

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -902,7 +902,8 @@ DWARF:
902902
- Value: 0x1234
903903

904904
## o) Test that yaml2obj is able to generate compilation units according to the
905-
## associated abbrev table that is referenced by the 'AbbrevTableID'.
905+
## associated abbrev table that is referenced by the 'AbbrevTableID' and infer
906+
## the value of the debug_abbrev_offset field.
906907

907908
# RUN: yaml2obj --docnum=17 %s -o %t17.o
908909
# RUN: llvm-readelf --hex-dump=.debug_info %t17.o | FileCheck %s --check-prefix=MULTI-TABLES
@@ -972,29 +973,54 @@ DWARF:
972973
debug_info:
973974
- Version: 4
974975
AbbrevTableID: 2
975-
AbbrOffset: 8
976976
Entries:
977977
- AbbrCode: 1
978978
Values:
979979
- Value: 0x1234
980980
- Version: 4
981981
AbbrevTableID: 2
982-
AbbrOffset: 8
983982
Entries:
984983
- AbbrCode: 1
985984
Values:
986985
- Value: 0x4321
987986
- Version: 4
988987
AbbrevTableID: 0
989-
AbbrOffset: 0
990988
Entries:
991989
- AbbrCode: 1
992990
Values:
993991
- Value: 0x5678
994992
- Version: 4
995993
AbbrevTableID: 1
996-
AbbrOffset: 16
997994
Entries:
998995
- AbbrCode: 1
999996
Values:
1000997
- Value: 0x8765
998+
999+
## p) Test that when the debug_abbrev_offset field isn't specified and there is no associated
1000+
## abbrev table, yaml2obj will assign 0 to the debug_abbrev_offset field.
1001+
1002+
# RUN: yaml2obj --docnum=18 %s -o %t18.o
1003+
# RUN: llvm-readelf --hex-dump=.debug_info %t18.o | FileCheck %s --check-prefix=ZERO-OFFSET
1004+
1005+
# ZERO-OFFSET: Hex dump of section '.debug_info':
1006+
# ZERO-OFFSET-NEXT: 0x00000000 07000000 04000000 000008 ...........
1007+
## ^------- unit_length (4-byte)
1008+
## ^--- version (2-byte)
1009+
## ^-------- debug_abbrev_offset (4-byte)
1010+
## ^- address_size (1-byte)
1011+
1012+
--- !ELF
1013+
FileHeader:
1014+
Class: ELFCLASS64
1015+
Data: ELFDATA2LSB
1016+
Type: ET_EXEC
1017+
DWARF:
1018+
debug_info:
1019+
- Version: 4
1020+
AbbrevTableID: [[ABBREVID=<none>]]
1021+
1022+
## q) Test that when we assign an invalid 'AbbrevTableID' that doesn't point to an abbrev table,
1023+
## yaml2obj will assign 0 to the debug_abbrev_offset field.
1024+
1025+
# RUN: yaml2obj --docnum=18 -DABBREVID=2 %s -o %t18.o
1026+
# RUN: llvm-readelf --hex-dump=.debug_info %t18.o | FileCheck %s --check-prefix=ZERO-OFFSET

0 commit comments

Comments
 (0)