Skip to content

Commit 9a9d449

Browse files
Merge pull request #7611 from rastogishubham/MCCASD5Stable
Add support for Dwarf 5 in MCCAS
2 parents 94becb7 + 407fd29 commit 9a9d449

File tree

8 files changed

+280
-26
lines changed

8 files changed

+280
-26
lines changed

llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ class DWARFFormValue {
7979

8080
dwarf::Form getForm() const { return Form; }
8181
uint64_t getRawUValue() const { return Value.uval; }
82+
int64_t getRawSValue() const { return Value.sval; }
8283

8384
bool isFormClass(FormClass FC) const;
8485
const DWARFUnit *getUnit() const { return U; }

llvm/include/llvm/MCCAS/MCCASDebugV1.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ namespace mccasformats {
2020
namespace v1 {
2121

2222
constexpr unsigned Dwarf4HeaderSize32Bit = 11;
23+
constexpr unsigned Dwarf5HeaderSize32Bit = 12;
2324

2425
/// Returns true if the values associated with a combination of Form and Attr
2526
/// are not expected to deduplicate.
@@ -72,6 +73,9 @@ struct DataWriter {
7273
/// Write ULEB128(V) to the data stream.
7374
void writeULEB128(uint64_t V) { encodeULEB128(V, DataStream); }
7475

76+
/// Write SLEB128(V) to the data stream.
77+
void writeSLEB128(int64_t V) { encodeSLEB128(V, DataStream); }
78+
7579
/// Write V to the data stream.
7680
void writeByte(uint8_t V) { DataStream << V; }
7781

llvm/include/llvm/MCCAS/MCCASObjectV1.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,7 @@ struct DwarfSectionsCache {
479479
MCSection *Line;
480480
MCSection *Str;
481481
MCSection *Abbrev;
482+
MCSection *StrOffsets;
482483
};
483484

484485
/// Queries `Asm` for all dwarf sections and returns an object with (possibly
@@ -580,6 +581,10 @@ class MCCASBuilder {
580581
struct CUSplit {
581582
SmallVector<MutableArrayRef<char>> SplitCUData;
582583
SmallVector<size_t> AbbrevOffsets;
584+
/// A list of Dwarf versions of the compile units, to help determine what
585+
/// the Compile Unit header format and size is like when creating
586+
/// CASObjects.
587+
SmallVector<uint16_t> DwarfVersions;
583588
};
584589
/// Split the data of the __debug_info section it into multiple pieces, one
585590
/// per Compile Unit(CU) and return them. The abbreviation offset for each CU

llvm/lib/MCCAS/MCCASDebugV1.cpp

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,13 @@ void AbbrevEntryWriter::writeAbbrevEntry(DWARFDie DIE) {
255255
if (Form == dwarf::Form::DW_FORM_strp)
256256
Form = dwarf::Form::DW_FORM_strp_cas;
257257
writeULEB128(Form);
258+
// Dwarf 5: Section 7.4:
259+
// The form DW_FORM_implicit_const has to be handled specially. It's
260+
// specification contains a third part, which is a signed LEB128 number.
261+
// This number is used as the value of the attribute with the aformentioned
262+
// form and nothing is stored in the .debug_info section.
263+
if (Form == dwarf::Form::DW_FORM_implicit_const)
264+
writeSLEB128(AttrValue.Value.getRawSValue());
258265
}
259266
}
260267

@@ -281,11 +288,32 @@ Expected<dwarf::Attribute> AbbrevEntryReader::readAttr() {
281288
return static_cast<dwarf::Attribute>(AttrAsInt);
282289
}
283290

291+
static Expected<int64_t> handleImplicitConst(BinaryStreamReader &Reader) {
292+
int64_t ImplicitVal;
293+
if (auto E = Reader.readSLEB128(ImplicitVal))
294+
return E;
295+
return ImplicitVal;
296+
}
297+
284298
Expected<dwarf::Form> AbbrevEntryReader::readForm() {
285299
uint64_t FormAsInt;
286300
if (auto E = DataStream.readULEB128(FormAsInt))
287301
return std::move(E);
288-
return static_cast<dwarf::Form>(FormAsInt);
302+
auto Form = static_cast<dwarf::Form>(FormAsInt);
303+
304+
// Dwarf 5: Section 7.4:
305+
// The form DW_FORM_implicit_const has to be handled specially. It's
306+
// specification contains a third part, which is a signed LEB128 number. This
307+
// number is used as the value of the attribute with the aformentioned form
308+
// and nothing is stored in the .debug_info section.
309+
310+
// Advance reader to beyond the implicit_const value, to read Forms correctly.
311+
if (Form == dwarf::Form::DW_FORM_implicit_const) {
312+
auto ImplicitVal = handleImplicitConst(DataStream);
313+
if (!ImplicitVal)
314+
return ImplicitVal.takeError();
315+
}
316+
return Form;
289317
}
290318

291319
uint64_t
@@ -330,6 +358,18 @@ mccasformats::v1::reconstructAbbrevSection(raw_ostream &OS,
330358
Form = dwarf::Form::DW_FORM_strp;
331359

332360
WrittenSize += encodeULEB128(Form, OS);
361+
362+
// Dwarf 5: Section 7.4:
363+
// The form DW_FORM_implicit_const has to be handled specially. It's
364+
// specification contains a third part, which is a signed LEB128 number.
365+
// This number is used as the value of the attribute with the
366+
// aformentioned form and nothing is stored in the .debug_info section.
367+
if (Form == dwarf::Form::DW_FORM_implicit_const) {
368+
auto ImplicitVal = handleImplicitConst(Reader);
369+
if (!ImplicitVal)
370+
handleAllErrors(ImplicitVal.takeError());
371+
WrittenSize += encodeSLEB128(*ImplicitVal, OS);
372+
}
333373
}
334374

335375
// Dwarf 5: Section 7.5.3:

llvm/lib/MCCAS/MCCASObjectV1.cpp

Lines changed: 107 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -79,17 +79,26 @@ class AbbrevSetWriter;
7979
/// debug info.
8080
class InMemoryCASDWARFObject : public DWARFObject {
8181
ArrayRef<char> DebugAbbrevSection;
82+
DWARFSection DebugStringOffsetsSection;
8283
bool IsLittleEndian;
8384

8485
public:
85-
InMemoryCASDWARFObject(ArrayRef<char> AbbrevContents, bool IsLittleEndian)
86-
: DebugAbbrevSection(AbbrevContents), IsLittleEndian(IsLittleEndian) {}
86+
InMemoryCASDWARFObject(ArrayRef<char> AbbrevContents,
87+
ArrayRef<char> StringOffsetsContents,
88+
bool IsLittleEndian)
89+
: DebugAbbrevSection(AbbrevContents),
90+
DebugStringOffsetsSection({toStringRef(StringOffsetsContents)}),
91+
IsLittleEndian(IsLittleEndian) {}
8792
bool isLittleEndian() const override { return IsLittleEndian; }
8893

8994
StringRef getAbbrevSection() const override {
9095
return toStringRef(DebugAbbrevSection);
9196
}
9297

98+
const DWARFSection &getStrOffsetsSection() const override {
99+
return DebugStringOffsetsSection;
100+
}
101+
93102
std::optional<RelocAddrEntry> find(const DWARFSection &Sec,
94103
uint64_t Pos) const override {
95104
return {};
@@ -103,12 +112,13 @@ class InMemoryCASDWARFObject : public DWARFObject {
103112
/// unit.
104113
Error partitionCUData(ArrayRef<char> DebugInfoData, uint64_t AbbrevOffset,
105114
DWARFContext *Ctx, MCCASBuilder &Builder,
106-
AbbrevSetWriter &AbbrevWriter);
115+
AbbrevSetWriter &AbbrevWriter, uint16_t DwarfVersion);
107116
};
108117

109118
struct CUInfo {
110119
uint64_t CUSize;
111120
uint32_t AbbrevOffset;
121+
uint16_t DwarfVersion;
112122
};
113123
static Expected<CUInfo> getAndSetDebugAbbrevOffsetAndSkip(
114124
MutableArrayRef<char> CUData, support::endianness Endian,
@@ -807,9 +817,23 @@ getLineTableLengthInfoAndVersion(DWARFDataExtractor &LineTableDataReader,
807817
auto Version = LineTableDataReader.getU16(OffsetPtr, &Err);
808818
if (Err)
809819
return std::move(Err);
810-
if (Version >= 5)
811-
return createStringError(inconvertibleErrorCode(),
812-
"DWARF 5 and above is not currently supported");
820+
if (Version >= 5) {
821+
// Dwarf 5 Section 6.2.4:
822+
// Line Table Header Format is now changed with an address_size and
823+
// segment_selector_size after the version. Parse both values from the
824+
// header.
825+
auto AddressSize = LineTableDataReader.getU8(OffsetPtr, &Err);
826+
if (Err)
827+
return std::move(Err);
828+
if (AddressSize != 8)
829+
return createStringError(
830+
inconvertibleErrorCode(),
831+
"Address size is not 8 bytes, unsupported architecture for MCCAS!");
832+
LineTableDataReader.getU8(OffsetPtr, &Err);
833+
if (Err)
834+
return std::move(Err);
835+
}
836+
813837
Prologue.Version = Version;
814838
// Since we do not support 64 bit DWARF, the prologue length is 4 bytes in
815839
// size.
@@ -1461,7 +1485,8 @@ DwarfSectionsCache mccasformats::v1::getDwarfSections(MCAssembler &Asm) {
14611485
Asm.getContext().getObjectFileInfo()->getDwarfInfoSection(),
14621486
Asm.getContext().getObjectFileInfo()->getDwarfLineSection(),
14631487
Asm.getContext().getObjectFileInfo()->getDwarfStrSection(),
1464-
Asm.getContext().getObjectFileInfo()->getDwarfAbbrevSection()};
1488+
Asm.getContext().getObjectFileInfo()->getDwarfAbbrevSection(),
1489+
Asm.getContext().getObjectFileInfo()->getDwarfStrOffSection()};
14651490
}
14661491

14671492
Error MCCASBuilder::prepare() {
@@ -1725,10 +1750,25 @@ getAndSetDebugAbbrevOffsetAndSkip(MutableArrayRef<char> CUData,
17251750
if (auto E = Reader.readInteger(DwarfVersion))
17261751
return std::move(E);
17271752

1728-
// TODO: Dwarf 5 has a different order for the next fields.
1729-
if (DwarfVersion != 4)
1730-
return createStringError(inconvertibleErrorCode(),
1731-
"Expected Dwarf 4 input");
1753+
if (DwarfVersion >= 5) {
1754+
// From Dwarf 5 Section 7.5.1.1:
1755+
// Compile Unit Header Format is now changed with unit_type and address_size
1756+
// after the version. Parse both values from the header.
1757+
uint8_t UnitType;
1758+
if (auto E = Reader.readInteger(UnitType))
1759+
return std::move(E);
1760+
if (UnitType != dwarf::DW_UT_compile)
1761+
return createStringError(
1762+
inconvertibleErrorCode(),
1763+
"Unit type is not DW_UT_compile, and is incompatible with MCCAS!");
1764+
uint8_t AddressSize;
1765+
if (auto E = Reader.readInteger(AddressSize))
1766+
return std::move(E);
1767+
if (AddressSize != 8)
1768+
return createStringError(
1769+
inconvertibleErrorCode(),
1770+
"Address size is not 8 bytes, unsupported architecture for MCCAS!");
1771+
}
17321772

17331773
// TODO: Handle Dwarf 64 format, which uses 8 bytes.
17341774
size_t AbbrevPosition = Reader.getOffset();
@@ -1750,7 +1790,7 @@ getAndSetDebugAbbrevOffsetAndSkip(MutableArrayRef<char> CUData,
17501790
if (auto E = Reader.skip(*Size))
17511791
return std::move(E);
17521792

1753-
return CUInfo{Reader.getOffset(), AbbrevOffset};
1793+
return CUInfo{Reader.getOffset(), AbbrevOffset, DwarfVersion};
17541794
}
17551795

17561796
/// Given a list of MCFragments, return a vector with the concatenation of their
@@ -1790,6 +1830,7 @@ MCCASBuilder::splitDebugInfoSectionData(MutableArrayRef<char> DebugInfoData) {
17901830
return Info.takeError();
17911831
Split.SplitCUData.push_back(DebugInfoData.take_front(Info->CUSize));
17921832
Split.AbbrevOffsets.push_back(Info->AbbrevOffset);
1833+
Split.DwarfVersions.push_back(Info->DwarfVersion);
17931834
DebugInfoData = DebugInfoData.drop_front(Info->CUSize);
17941835
}
17951836

@@ -1938,7 +1979,8 @@ Error InMemoryCASDWARFObject::partitionCUData(ArrayRef<char> DebugInfoData,
19381979
uint64_t AbbrevOffset,
19391980
DWARFContext *Ctx,
19401981
MCCASBuilder &Builder,
1941-
AbbrevSetWriter &AbbrevWriter) {
1982+
AbbrevSetWriter &AbbrevWriter,
1983+
uint16_t DwarfVersion) {
19421984
StringRef AbbrevSectionContribution =
19431985
getAbbrevSection().drop_front(AbbrevOffset);
19441986
DataExtractor Data(AbbrevSectionContribution, isLittleEndian(), 8);
@@ -1957,13 +1999,24 @@ Error InMemoryCASDWARFObject::partitionCUData(ArrayRef<char> DebugInfoData,
19571999

19582000
DWARFDie CUDie = DCU.getUnitDIE(false);
19592001
assert(CUDie);
1960-
// Copy 11 bytes which represents the 32-bit DWARF Header for DWARF4.
1961-
if (DebugInfoData.size() < Dwarf4HeaderSize32Bit)
1962-
return createStringError(inconvertibleErrorCode(),
1963-
"DebugInfoData is too small, it doesn't even "
1964-
"contain a 32-bit DWARF Header");
2002+
ArrayRef<char> HeaderData;
2003+
if (DwarfVersion >= 5) {
2004+
// Copy 12 bytes which represents the 32-bit DWARF Header for DWARF5.
2005+
if (DebugInfoData.size() < Dwarf5HeaderSize32Bit)
2006+
return createStringError(inconvertibleErrorCode(),
2007+
"DebugInfoData is too small, it doesn't even "
2008+
"contain a 32-bit DWARF5 Header");
2009+
2010+
HeaderData = DebugInfoData.take_front(Dwarf5HeaderSize32Bit);
2011+
} else {
2012+
// Copy 11 bytes which represents the 32-bit DWARF Header for DWARF4.
2013+
if (DebugInfoData.size() < Dwarf4HeaderSize32Bit)
2014+
return createStringError(inconvertibleErrorCode(),
2015+
"DebugInfoData is too small, it doesn't even "
2016+
"contain a 32-bit DWARF4 Header");
19652017

1966-
ArrayRef<char> HeaderData = DebugInfoData.take_front(Dwarf4HeaderSize32Bit);
2018+
HeaderData = DebugInfoData.take_front(Dwarf4HeaderSize32Bit);
2019+
}
19672020
Expected<DIETopLevelRef> Converted =
19682021
DIEToCASConverter(DebugInfoData, Builder)
19692022
.convert(CUDie, HeaderData, AbbrevWriter);
@@ -1993,20 +2046,32 @@ Error MCCASBuilder::splitDebugInfoAndAbbrevSections() {
19932046

19942047
Expected<SmallVector<char, 0>> FullAbbrevData =
19952048
mergeMCFragmentContents(AbbrevFragmentList);
2049+
19962050
if (!FullAbbrevData)
19972051
return FullAbbrevData.takeError();
19982052

1999-
InMemoryCASDWARFObject CASObj(
2000-
*FullAbbrevData, Asm.getBackend().Endian == support::endianness::little);
2053+
const MCSection::FragmentListType &StringOffsetsFragmentList =
2054+
DwarfSections.StrOffsets->getFragmentList();
2055+
2056+
Expected<SmallVector<char, 0>> FullStringOffsetsData =
2057+
mergeMCFragmentContents(StringOffsetsFragmentList);
2058+
2059+
if (!FullStringOffsetsData)
2060+
return FullStringOffsetsData.takeError();
2061+
2062+
InMemoryCASDWARFObject CASObj(*FullAbbrevData, *FullStringOffsetsData,
2063+
Asm.getBackend().Endian ==
2064+
support::endianness::little);
20012065
auto DWARFObj = std::make_unique<InMemoryCASDWARFObject>(CASObj);
20022066
auto DWARFContextHolder = std::make_unique<DWARFContext>(std::move(DWARFObj));
20032067
auto *DWARFCtx = DWARFContextHolder.get();
20042068

20052069
AbbrevSetWriter AbbrevWriter;
2006-
for (auto [CUData, AbbrevOffset] :
2007-
llvm::zip(SplitInfo->SplitCUData, SplitInfo->AbbrevOffsets)) {
2070+
for (auto [CUData, AbbrevOffset, DwarfVersion] :
2071+
llvm::zip(SplitInfo->SplitCUData, SplitInfo->AbbrevOffsets,
2072+
SplitInfo->DwarfVersions)) {
20082073
if (auto E = CASObj.partitionCUData(CUData, AbbrevOffset, DWARFCtx, *this,
2009-
AbbrevWriter))
2074+
AbbrevWriter, DwarfVersion))
20102075
return E;
20112076
}
20122077
return Error::success();
@@ -2162,6 +2227,8 @@ Error MCCASBuilder::createDebugStrSection() {
21622227
startSection(DwarfSections.Str);
21632228
for (auto DebugStringRef : *DebugStringRefs)
21642229
addNode(DebugStringRef);
2230+
if (auto E = createPaddingRef(DwarfSections.Str))
2231+
return E;
21652232
return finalizeSection<DebugStringSectionRef>();
21662233
}
21672234

@@ -3166,7 +3233,22 @@ Error mccasformats::v1::visitDebugInfo(
31663233
StringRef DistinctData = LoadedTopRef->DistinctData.getData();
31673234
BinaryStreamReader DistinctReader(DistinctData, support::endianness::little);
31683235
ArrayRef<char> HeaderData;
3169-
if (auto E = DistinctReader.readArray(HeaderData, Dwarf4HeaderSize32Bit))
3236+
3237+
auto BeginOffset = DistinctReader.getOffset();
3238+
auto Size = getSizeFromDwarfHeader(DistinctReader);
3239+
if (!Size)
3240+
return Size.takeError();
3241+
3242+
// 2-byte Dwarf version identifier.
3243+
uint16_t DwarfVersion;
3244+
if (auto E = DistinctReader.readInteger(DwarfVersion))
3245+
return E;
3246+
3247+
DistinctReader.setOffset(BeginOffset);
3248+
3249+
if (auto E = DistinctReader.readArray(
3250+
HeaderData,
3251+
DwarfVersion >= 5 ? Dwarf5HeaderSize32Bit : Dwarf4HeaderSize32Bit))
31703252
return E;
31713253
HeaderCallback(toStringRef(HeaderData));
31723254

0 commit comments

Comments
 (0)