Changeset View
Standalone View
llvm/lib/ObjectYAML/DWARFEmitter.cpp
Show First 20 Lines • Show All 79 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
static void writeDWARFOffset(uint64_t Offset, dwarf::DwarfFormat Format, | static void writeDWARFOffset(uint64_t Offset, dwarf::DwarfFormat Format, | ||||
raw_ostream &OS, bool IsLittleEndian) { | raw_ostream &OS, bool IsLittleEndian) { | ||||
cantFail(writeVariableSizedInteger(Offset, Format == dwarf::DWARF64 ? 8 : 4, | cantFail(writeVariableSizedInteger(Offset, Format == dwarf::DWARF64 ? 8 : 4, | ||||
OS, IsLittleEndian)); | OS, IsLittleEndian)); | ||||
} | } | ||||
Error DWARFYAML::emitDebugStr(raw_ostream &OS, const DWARFYAML::Data &DI) { | DWARFYAML::DWARFState::DWARFState(DWARFYAML::Data &DI, Error &Err) : DWARF(DI) { | ||||
ErrorAsOutParameter EAO(&Err); | |||||
labath: If you'd do all this work in the factory function and then just pass in a finished map to the… | |||||
HiguoxingAuthorUnsubmitted DWARFYAML::DWARFState is merged into DWARFYAML::Data, so we don't need ErrorAsOutParameter any more. Higuoxing: `DWARFYAML::DWARFState` is merged into `DWARFYAML::Data`, so we don't need… | |||||
for (uint64_t I = 0; I < DI.DebugAbbrev.size(); ++I) { | |||||
labathUnsubmitted consider: for (auto &Abbr : enumerate(DI.DebugAbbrev)) labath: consider: `for (auto &Abbr : enumerate(DI.DebugAbbrev))` | |||||
// If the abbrev table's ID isn't specified, we use the index as its ID. | |||||
jhendersonUnsubmitted Maybe to avoid weird errors, it might make sense to disallow mixing the two methods, i.e. if one table has an explicit ID, the others all must do too. What do you think? It may not be worth it if the code is more complex, I don't know. jhenderson: Maybe to avoid weird errors, it might make sense to disallow mixing the two methods, i.e. if… | |||||
HiguoxingAuthorUnsubmitted I think it's a little bit difficult to distinguish these 2 situations. Besides, sometimes we might want to add one compilation unit to a test case and let it reference an existing abbrev table. We don't need to mutate the whole test case to add IDs. What do think of it? Higuoxing: I think it's a little bit difficult to distinguish these 2 situations. Besides, sometimes we… | |||||
jhendersonUnsubmitted Leave it as is. I wasn't convinced by my own statement, so I think what you've got is fine. jhenderson: Leave it as is. I wasn't convinced by my own statement, so I think what you've got is fine. | |||||
uint64_t ID = I; | |||||
if (DI.DebugAbbrev[I].ID) | |||||
ID = *DI.DebugAbbrev[I].ID; | |||||
labathUnsubmitted ID = DI.DebugAbbrev[I].ID.getValueOr(I) labath: `ID = DI.DebugAbbrev[I].ID.getValueOr(I)` | |||||
if (AbbrevID2Index.count(ID)) { | |||||
Err = createStringError(errc::invalid_argument, | |||||
"the ID (%" PRIu64 | |||||
") of abbrev table with index %" PRIu64 | |||||
" has been used", | |||||
ID, I); | |||||
return; | |||||
} | |||||
AbbrevID2Index.insert({ID, I}); | |||||
jhendersonUnsubmitted Could you use the return value of insert to identify whether the key already exists in the map? That way, you don't need the explicit count call. jhenderson: Could you use the return value of `insert` to identify whether the key already exists in the… | |||||
} | |||||
} | |||||
Optional<uint64_t> | |||||
DWARFYAML::DWARFState::getAbbrevTableIndexByID(uint64_t ID) const { | |||||
auto It = AbbrevID2Index.find(ID); | |||||
if (It == AbbrevID2Index.end()) | |||||
return None; | |||||
return It->second; | |||||
} | |||||
Expected<DWARFYAML::DWARFState> | |||||
DWARFYAML::DWARFState::create(DWARFYAML::Data &DI) { | |||||
Error Err = Error::success(); | |||||
DWARFState DS(DI, Err); | |||||
if (Err) | |||||
return std::move(Err); | |||||
return std::move(DS); | |||||
} | |||||
Error DWARFYAML::emitDebugStr(raw_ostream &OS, const DWARFState &DS) { | |||||
const DWARFYAML::Data &DI = DS.getDWARFData(); | |||||
for (auto Str : DI.DebugStrings) { | for (auto Str : DI.DebugStrings) { | ||||
OS.write(Str.data(), Str.size()); | OS.write(Str.data(), Str.size()); | ||||
OS.write('\0'); | OS.write('\0'); | ||||
} | } | ||||
return Error::success(); | return Error::success(); | ||||
} | } | ||||
Error DWARFYAML::emitDebugAbbrev(raw_ostream &OS, const DWARFYAML::Data &DI) { | Error DWARFYAML::emitDebugAbbrev(raw_ostream &OS, const DWARFState &DS) { | ||||
const DWARFYAML::Data &DI = DS.getDWARFData(); | |||||
for (const DWARFYAML::AbbrevTable &AbbrevTable : DI.DebugAbbrev) { | |||||
uint64_t AbbrevCode = 0; | uint64_t AbbrevCode = 0; | ||||
for (auto AbbrevDecl : DI.AbbrevDecls) { | for (auto AbbrevDecl : AbbrevTable.Table) { | ||||
AbbrevCode = AbbrevDecl.Code ? (uint64_t)*AbbrevDecl.Code : AbbrevCode + 1; | AbbrevCode = | ||||
AbbrevDecl.Code ? (uint64_t)*AbbrevDecl.Code : AbbrevCode + 1; | |||||
encodeULEB128(AbbrevCode, OS); | encodeULEB128(AbbrevCode, OS); | ||||
encodeULEB128(AbbrevDecl.Tag, OS); | encodeULEB128(AbbrevDecl.Tag, OS); | ||||
OS.write(AbbrevDecl.Children); | OS.write(AbbrevDecl.Children); | ||||
for (auto Attr : AbbrevDecl.Attributes) { | for (auto Attr : AbbrevDecl.Attributes) { | ||||
encodeULEB128(Attr.Attribute, OS); | encodeULEB128(Attr.Attribute, OS); | ||||
encodeULEB128(Attr.Form, OS); | encodeULEB128(Attr.Form, OS); | ||||
if (Attr.Form == dwarf::DW_FORM_implicit_const) | if (Attr.Form == dwarf::DW_FORM_implicit_const) | ||||
encodeSLEB128(Attr.Value, OS); | encodeSLEB128(Attr.Value, OS); | ||||
} | } | ||||
encodeULEB128(0, OS); | encodeULEB128(0, OS); | ||||
encodeULEB128(0, OS); | encodeULEB128(0, OS); | ||||
} | } | ||||
// The abbreviations for a given compilation unit end with an entry consisting | // The abbreviations for a given compilation unit end with an entry | ||||
// of a 0 byte for the abbreviation code. | // consisting of a 0 byte for the abbreviation code. | ||||
OS.write_zeros(1); | OS.write_zeros(1); | ||||
} | |||||
return Error::success(); | return Error::success(); | ||||
} | } | ||||
Error DWARFYAML::emitDebugAranges(raw_ostream &OS, const DWARFYAML::Data &DI) { | Error DWARFYAML::emitDebugAranges(raw_ostream &OS, const DWARFState &DS) { | ||||
const DWARFYAML::Data &DI = DS.getDWARFData(); | |||||
assert(DI.DebugAranges && "unexpected emitDebugAranges() call"); | assert(DI.DebugAranges && "unexpected emitDebugAranges() call"); | ||||
for (auto Range : *DI.DebugAranges) { | for (auto Range : *DI.DebugAranges) { | ||||
uint8_t AddrSize; | uint8_t AddrSize; | ||||
if (Range.AddrSize) | if (Range.AddrSize) | ||||
AddrSize = *Range.AddrSize; | AddrSize = *Range.AddrSize; | ||||
else | else | ||||
AddrSize = DI.Is64BitAddrSize ? 8 : 4; | AddrSize = DI.Is64BitAddrSize ? 8 : 4; | ||||
Show All 32 Lines | for (auto Descriptor : Range.Descriptors) { | ||||
DI.IsLittleEndian)); | DI.IsLittleEndian)); | ||||
} | } | ||||
ZeroFillBytes(OS, AddrSize * 2); | ZeroFillBytes(OS, AddrSize * 2); | ||||
} | } | ||||
return Error::success(); | return Error::success(); | ||||
} | } | ||||
Error DWARFYAML::emitDebugRanges(raw_ostream &OS, const DWARFYAML::Data &DI) { | Error DWARFYAML::emitDebugRanges(raw_ostream &OS, const DWARFState &DS) { | ||||
const DWARFYAML::Data &DI = DS.getDWARFData(); | |||||
const size_t RangesOffset = OS.tell(); | const size_t RangesOffset = OS.tell(); | ||||
uint64_t EntryIndex = 0; | uint64_t EntryIndex = 0; | ||||
for (auto DebugRanges : DI.DebugRanges) { | for (auto DebugRanges : DI.DebugRanges) { | ||||
const size_t CurrOffset = OS.tell() - RangesOffset; | const size_t CurrOffset = OS.tell() - RangesOffset; | ||||
if (DebugRanges.Offset && (uint64_t)*DebugRanges.Offset < CurrOffset) | if (DebugRanges.Offset && (uint64_t)*DebugRanges.Offset < CurrOffset) | ||||
return createStringError(errc::invalid_argument, | return createStringError(errc::invalid_argument, | ||||
"'Offset' for 'debug_ranges' with index " + | "'Offset' for 'debug_ranges' with index " + | ||||
Twine(EntryIndex) + | Twine(EntryIndex) + | ||||
Show All 37 Lines | if (IsGNUPubSec) | ||||
writeInteger((uint8_t)Entry.Descriptor, OS, IsLittleEndian); | writeInteger((uint8_t)Entry.Descriptor, OS, IsLittleEndian); | ||||
OS.write(Entry.Name.data(), Entry.Name.size()); | OS.write(Entry.Name.data(), Entry.Name.size()); | ||||
OS.write('\0'); | OS.write('\0'); | ||||
} | } | ||||
return Error::success(); | return Error::success(); | ||||
} | } | ||||
Error DWARFYAML::emitDebugPubnames(raw_ostream &OS, const Data &DI) { | Error DWARFYAML::emitDebugPubnames(raw_ostream &OS, const DWARFState &DS) { | ||||
const DWARFYAML::Data &DI = DS.getDWARFData(); | |||||
assert(DI.PubNames && "unexpected emitDebugPubnames() call"); | assert(DI.PubNames && "unexpected emitDebugPubnames() call"); | ||||
return emitPubSection(OS, *DI.PubNames, DI.IsLittleEndian); | return emitPubSection(OS, *DI.PubNames, DI.IsLittleEndian); | ||||
} | } | ||||
Error DWARFYAML::emitDebugPubtypes(raw_ostream &OS, const Data &DI) { | Error DWARFYAML::emitDebugPubtypes(raw_ostream &OS, const DWARFState &DS) { | ||||
const DWARFYAML::Data &DI = DS.getDWARFData(); | |||||
assert(DI.PubTypes && "unexpected emitDebugPubtypes() call"); | assert(DI.PubTypes && "unexpected emitDebugPubtypes() call"); | ||||
return emitPubSection(OS, *DI.PubTypes, DI.IsLittleEndian); | return emitPubSection(OS, *DI.PubTypes, DI.IsLittleEndian); | ||||
} | } | ||||
Error DWARFYAML::emitDebugGNUPubnames(raw_ostream &OS, const Data &DI) { | Error DWARFYAML::emitDebugGNUPubnames(raw_ostream &OS, const DWARFState &DS) { | ||||
const DWARFYAML::Data &DI = DS.getDWARFData(); | |||||
assert(DI.GNUPubNames && "unexpected emitDebugGNUPubnames() call"); | assert(DI.GNUPubNames && "unexpected emitDebugGNUPubnames() call"); | ||||
return emitPubSection(OS, *DI.GNUPubNames, DI.IsLittleEndian, | return emitPubSection(OS, *DI.GNUPubNames, DI.IsLittleEndian, | ||||
/*IsGNUStyle=*/true); | /*IsGNUStyle=*/true); | ||||
} | } | ||||
Error DWARFYAML::emitDebugGNUPubtypes(raw_ostream &OS, const Data &DI) { | Error DWARFYAML::emitDebugGNUPubtypes(raw_ostream &OS, const DWARFState &DS) { | ||||
const DWARFYAML::Data &DI = DS.getDWARFData(); | |||||
assert(DI.GNUPubTypes && "unexpected emitDebugGNUPubtypes() call"); | assert(DI.GNUPubTypes && "unexpected emitDebugGNUPubtypes() call"); | ||||
return emitPubSection(OS, *DI.GNUPubTypes, DI.IsLittleEndian, | return emitPubSection(OS, *DI.GNUPubTypes, DI.IsLittleEndian, | ||||
/*IsGNUStyle=*/true); | /*IsGNUStyle=*/true); | ||||
} | } | ||||
static Expected<uint64_t> writeDIE(ArrayRef<DWARFYAML::Abbrev> AbbrevDecls, | static Expected<uint64_t> writeDIE(const DWARFYAML::DWARFState &DS, | ||||
uint64_t AbbrevTableID, | |||||
const dwarf::FormParams &Params, | const dwarf::FormParams &Params, | ||||
const DWARFYAML::Entry &Entry, | const DWARFYAML::Entry &Entry, | ||||
raw_ostream &OS, bool IsLittleEndian) { | raw_ostream &OS, bool IsLittleEndian) { | ||||
uint64_t EntryBegin = OS.tell(); | uint64_t EntryBegin = OS.tell(); | ||||
encodeULEB128(Entry.AbbrCode, OS); | encodeULEB128(Entry.AbbrCode, OS); | ||||
uint32_t AbbrCode = Entry.AbbrCode; | uint32_t AbbrCode = Entry.AbbrCode; | ||||
if (AbbrCode == 0 || Entry.Values.empty()) | if (AbbrCode == 0 || Entry.Values.empty()) | ||||
return OS.tell() - EntryBegin; | return OS.tell() - EntryBegin; | ||||
Optional<uint64_t> AbbrevTableIndex = | |||||
DS.getAbbrevTableIndexByID(AbbrevTableID); | |||||
if (!AbbrevTableIndex) | |||||
return createStringError(errc::invalid_argument, | |||||
"cannot find abbrev table whose ID is " + | |||||
utostr(AbbrevTableID)); | |||||
ArrayRef<DWARFYAML::Abbrev> AbbrevDecls( | |||||
DS.getDWARFData().DebugAbbrev[*AbbrevTableIndex].Table); | |||||
jhendersonUnsubmitted It might make more sense to do this work in the caller of this function, and to maintain this function's interface. jhenderson: It might make more sense to do this work in the caller of this function, and to maintain this… | |||||
HiguoxingAuthorUnsubmitted This is discussed in D86194 Higuoxing: This is discussed in [D86194](https://reviews.llvm.org/D86194#inline-796173) | |||||
if (AbbrCode > AbbrevDecls.size()) | if (AbbrCode > AbbrevDecls.size()) | ||||
return createStringError( | return createStringError( | ||||
errc::invalid_argument, | errc::invalid_argument, | ||||
"abbrev code must be less than or equal to the number of " | "abbrev code must be less than or equal to the number of " | ||||
"entries in abbreviation table"); | "entries in abbreviation table"); | ||||
const DWARFYAML::Abbrev &Abbrev = AbbrevDecls[AbbrCode - 1]; | const DWARFYAML::Abbrev &Abbrev = AbbrevDecls[AbbrCode - 1]; | ||||
auto FormVal = Entry.Values.begin(); | auto FormVal = Entry.Values.begin(); | ||||
auto AbbrForm = Abbrev.Attributes.begin(); | auto AbbrForm = Abbrev.Attributes.begin(); | ||||
▲ Show 20 Lines • Show All 104 Lines • ▼ Show 20 Lines | do { | ||||
break; | break; | ||||
} | } | ||||
} while (Indirect); | } while (Indirect); | ||||
} | } | ||||
return OS.tell() - EntryBegin; | return OS.tell() - EntryBegin; | ||||
} | } | ||||
Error DWARFYAML::emitDebugInfo(raw_ostream &OS, const DWARFYAML::Data &DI) { | Error DWARFYAML::emitDebugInfo(raw_ostream &OS, const DWARFState &DS) { | ||||
for (const DWARFYAML::Unit &Unit : DI.CompileUnits) { | const DWARFYAML::Data &DI = DS.getDWARFData(); | ||||
for (uint64_t I = 0; I < DI.CompileUnits.size(); ++I) { | |||||
const DWARFYAML::Unit &Unit = DI.CompileUnits[I]; | |||||
uint8_t AddrSize; | uint8_t AddrSize; | ||||
if (Unit.AddrSize) | if (Unit.AddrSize) | ||||
AddrSize = *Unit.AddrSize; | AddrSize = *Unit.AddrSize; | ||||
else | else | ||||
AddrSize = DI.Is64BitAddrSize ? 8 : 4; | AddrSize = DI.Is64BitAddrSize ? 8 : 4; | ||||
dwarf::FormParams Params = {Unit.Version, AddrSize, Unit.Format}; | dwarf::FormParams Params = {Unit.Version, AddrSize, Unit.Format}; | ||||
uint64_t Length = 3; // sizeof(version) + sizeof(address_size) | uint64_t Length = 3; // sizeof(version) + sizeof(address_size) | ||||
Length += Unit.Version >= 5 ? 1 : 0; // sizeof(unit_type) | Length += Unit.Version >= 5 ? 1 : 0; // sizeof(unit_type) | ||||
Length += Params.getDwarfOffsetByteSize(); // sizeof(debug_abbrev_offset) | Length += Params.getDwarfOffsetByteSize(); // sizeof(debug_abbrev_offset) | ||||
// Since the length of the current compilation unit is undetermined yet, we | // Since the length of the current compilation unit is undetermined yet, we | ||||
// firstly write the content of the compilation unit to a buffer to | // firstly write the content of the compilation unit to a buffer to | ||||
// calculate it and then serialize the buffer content to the actual output | // calculate it and then serialize the buffer content to the actual output | ||||
// stream. | // stream. | ||||
std::string EntryBuffer; | std::string EntryBuffer; | ||||
raw_string_ostream EntryBufferOS(EntryBuffer); | raw_string_ostream EntryBufferOS(EntryBuffer); | ||||
// If the abbrev table's ID isn't specified, we use the compilation unit's | |||||
// index as the ID. | |||||
uint64_t AbbrevTableID = I; | |||||
if (Unit.AbbrevTableID) | |||||
AbbrevTableID = *Unit.AbbrevTableID; | |||||
for (const DWARFYAML::Entry &Entry : Unit.Entries) { | for (const DWARFYAML::Entry &Entry : Unit.Entries) { | ||||
if (Expected<uint64_t> EntryLength = writeDIE( | if (Expected<uint64_t> EntryLength = | ||||
DI.AbbrevDecls, Params, Entry, EntryBufferOS, DI.IsLittleEndian)) | writeDIE(DS, AbbrevTableID, Params, Entry, EntryBufferOS, | ||||
DI.IsLittleEndian)) | |||||
Length += *EntryLength; | Length += *EntryLength; | ||||
else | else | ||||
return EntryLength.takeError(); | return EntryLength.takeError(); | ||||
} | } | ||||
// If the length is specified in the YAML description, we use it instead of | // If the length is specified in the YAML description, we use it instead of | ||||
// the actual length. | // the actual length. | ||||
if (Unit.Length) | if (Unit.Length) | ||||
Show All 19 Lines | |||||
static void emitFileEntry(raw_ostream &OS, const DWARFYAML::File &File) { | static void emitFileEntry(raw_ostream &OS, const DWARFYAML::File &File) { | ||||
OS.write(File.Name.data(), File.Name.size()); | OS.write(File.Name.data(), File.Name.size()); | ||||
OS.write('\0'); | OS.write('\0'); | ||||
encodeULEB128(File.DirIdx, OS); | encodeULEB128(File.DirIdx, OS); | ||||
encodeULEB128(File.ModTime, OS); | encodeULEB128(File.ModTime, OS); | ||||
encodeULEB128(File.Length, OS); | encodeULEB128(File.Length, OS); | ||||
} | } | ||||
Error DWARFYAML::emitDebugLine(raw_ostream &OS, const DWARFYAML::Data &DI) { | Error DWARFYAML::emitDebugLine(raw_ostream &OS, const DWARFState &DS) { | ||||
const DWARFYAML::Data &DI = DS.getDWARFData(); | |||||
for (const auto &LineTable : DI.DebugLines) { | for (const auto &LineTable : DI.DebugLines) { | ||||
writeInitialLength(LineTable.Format, LineTable.Length, OS, | writeInitialLength(LineTable.Format, LineTable.Length, OS, | ||||
DI.IsLittleEndian); | DI.IsLittleEndian); | ||||
uint64_t SizeOfPrologueLength = LineTable.Format == dwarf::DWARF64 ? 8 : 4; | uint64_t SizeOfPrologueLength = LineTable.Format == dwarf::DWARF64 ? 8 : 4; | ||||
writeInteger((uint16_t)LineTable.Version, OS, DI.IsLittleEndian); | writeInteger((uint16_t)LineTable.Version, OS, DI.IsLittleEndian); | ||||
cantFail(writeVariableSizedInteger( | cantFail(writeVariableSizedInteger( | ||||
LineTable.PrologueLength, SizeOfPrologueLength, OS, DI.IsLittleEndian)); | LineTable.PrologueLength, SizeOfPrologueLength, OS, DI.IsLittleEndian)); | ||||
writeInteger((uint8_t)LineTable.MinInstLength, OS, DI.IsLittleEndian); | writeInteger((uint8_t)LineTable.MinInstLength, OS, DI.IsLittleEndian); | ||||
▲ Show 20 Lines • Show All 73 Lines • ▼ Show 20 Lines | for (auto Op : LineTable.Opcodes) { | ||||
} | } | ||||
} | } | ||||
} | } | ||||
} | } | ||||
return Error::success(); | return Error::success(); | ||||
} | } | ||||
Error DWARFYAML::emitDebugAddr(raw_ostream &OS, const Data &DI) { | Error DWARFYAML::emitDebugAddr(raw_ostream &OS, const DWARFState &DS) { | ||||
const DWARFYAML::Data &DI = DS.getDWARFData(); | |||||
for (const AddrTableEntry &TableEntry : DI.DebugAddr) { | for (const AddrTableEntry &TableEntry : DI.DebugAddr) { | ||||
uint8_t AddrSize; | uint8_t AddrSize; | ||||
if (TableEntry.AddrSize) | if (TableEntry.AddrSize) | ||||
AddrSize = *TableEntry.AddrSize; | AddrSize = *TableEntry.AddrSize; | ||||
else | else | ||||
AddrSize = DI.Is64BitAddrSize ? 8 : 4; | AddrSize = DI.Is64BitAddrSize ? 8 : 4; | ||||
uint64_t Length; | uint64_t Length; | ||||
Show All 24 Lines | for (const SegAddrPair &Pair : TableEntry.SegAddrPairs) { | ||||
"unable to write debug_addr address: %s", | "unable to write debug_addr address: %s", | ||||
toString(std::move(Err)).c_str()); | toString(std::move(Err)).c_str()); | ||||
} | } | ||||
} | } | ||||
return Error::success(); | return Error::success(); | ||||
} | } | ||||
Error DWARFYAML::emitDebugStrOffsets(raw_ostream &OS, const Data &DI) { | Error DWARFYAML::emitDebugStrOffsets(raw_ostream &OS, const DWARFState &DS) { | ||||
const DWARFYAML::Data &DI = DS.getDWARFData(); | |||||
assert(DI.DebugStrOffsets && "unexpected emitDebugStrOffsets() call"); | assert(DI.DebugStrOffsets && "unexpected emitDebugStrOffsets() call"); | ||||
for (const DWARFYAML::StringOffsetsTable &Table : *DI.DebugStrOffsets) { | for (const DWARFYAML::StringOffsetsTable &Table : *DI.DebugStrOffsets) { | ||||
uint64_t Length; | uint64_t Length; | ||||
if (Table.Length) | if (Table.Length) | ||||
Length = *Table.Length; | Length = *Table.Length; | ||||
else | else | ||||
// sizeof(version) + sizeof(padding) = 4 | // sizeof(version) + sizeof(padding) = 4 | ||||
Length = | Length = | ||||
▲ Show 20 Lines • Show All 307 Lines • ▼ Show 20 Lines | else if (OffsetEntryCount != 0) | ||||
EmitOffsets(Offsets, OffsetsSize); | EmitOffsets(Offsets, OffsetsSize); | ||||
OS.write(ListBuffer.data(), ListBuffer.size()); | OS.write(ListBuffer.data(), ListBuffer.size()); | ||||
} | } | ||||
return Error::success(); | return Error::success(); | ||||
} | } | ||||
Error DWARFYAML::emitDebugRnglists(raw_ostream &OS, const Data &DI) { | Error DWARFYAML::emitDebugRnglists(raw_ostream &OS, const DWARFState &DS) { | ||||
const DWARFYAML::Data &DI = DS.getDWARFData(); | |||||
assert(DI.DebugRnglists && "unexpected emitDebugRnglists() call"); | assert(DI.DebugRnglists && "unexpected emitDebugRnglists() call"); | ||||
return writeDWARFLists<DWARFYAML::RnglistEntry>( | return writeDWARFLists<DWARFYAML::RnglistEntry>( | ||||
OS, *DI.DebugRnglists, DI.IsLittleEndian, DI.Is64BitAddrSize); | OS, *DI.DebugRnglists, DI.IsLittleEndian, DI.Is64BitAddrSize); | ||||
} | } | ||||
Error DWARFYAML::emitDebugLoclists(raw_ostream &OS, const Data &DI) { | Error DWARFYAML::emitDebugLoclists(raw_ostream &OS, const DWARFState &DS) { | ||||
const DWARFYAML::Data &DI = DS.getDWARFData(); | |||||
assert(DI.DebugLoclists && "unexpected emitDebugRnglists() call"); | assert(DI.DebugLoclists && "unexpected emitDebugRnglists() call"); | ||||
return writeDWARFLists<DWARFYAML::LoclistEntry>( | return writeDWARFLists<DWARFYAML::LoclistEntry>( | ||||
OS, *DI.DebugLoclists, DI.IsLittleEndian, DI.Is64BitAddrSize); | OS, *DI.DebugLoclists, DI.IsLittleEndian, DI.Is64BitAddrSize); | ||||
} | } | ||||
std::function<Error(raw_ostream &, const DWARFYAML::Data &)> | std::function<Error(raw_ostream &, const DWARFYAML::DWARFState &)> | ||||
DWARFYAML::getDWARFEmitterByName(StringRef SecName) { | DWARFYAML::getDWARFEmitterByName(StringRef SecName) { | ||||
auto EmitFunc = | auto EmitFunc = | ||||
StringSwitch< | StringSwitch< | ||||
std::function<Error(raw_ostream &, const DWARFYAML::Data &)>>(SecName) | std::function<Error(raw_ostream &, const DWARFYAML::DWARFState &)>>( | ||||
SecName) | |||||
.Case("debug_abbrev", DWARFYAML::emitDebugAbbrev) | .Case("debug_abbrev", DWARFYAML::emitDebugAbbrev) | ||||
.Case("debug_addr", DWARFYAML::emitDebugAddr) | .Case("debug_addr", DWARFYAML::emitDebugAddr) | ||||
.Case("debug_aranges", DWARFYAML::emitDebugAranges) | .Case("debug_aranges", DWARFYAML::emitDebugAranges) | ||||
.Case("debug_gnu_pubnames", DWARFYAML::emitDebugGNUPubnames) | .Case("debug_gnu_pubnames", DWARFYAML::emitDebugGNUPubnames) | ||||
.Case("debug_gnu_pubtypes", DWARFYAML::emitDebugGNUPubtypes) | .Case("debug_gnu_pubtypes", DWARFYAML::emitDebugGNUPubtypes) | ||||
.Case("debug_info", DWARFYAML::emitDebugInfo) | .Case("debug_info", DWARFYAML::emitDebugInfo) | ||||
.Case("debug_line", DWARFYAML::emitDebugLine) | .Case("debug_line", DWARFYAML::emitDebugLine) | ||||
.Case("debug_loclists", DWARFYAML::emitDebugLoclists) | .Case("debug_loclists", DWARFYAML::emitDebugLoclists) | ||||
.Case("debug_pubnames", DWARFYAML::emitDebugPubnames) | .Case("debug_pubnames", DWARFYAML::emitDebugPubnames) | ||||
.Case("debug_pubtypes", DWARFYAML::emitDebugPubtypes) | .Case("debug_pubtypes", DWARFYAML::emitDebugPubtypes) | ||||
.Case("debug_ranges", DWARFYAML::emitDebugRanges) | .Case("debug_ranges", DWARFYAML::emitDebugRanges) | ||||
.Case("debug_rnglists", DWARFYAML::emitDebugRnglists) | .Case("debug_rnglists", DWARFYAML::emitDebugRnglists) | ||||
.Case("debug_str", DWARFYAML::emitDebugStr) | .Case("debug_str", DWARFYAML::emitDebugStr) | ||||
.Case("debug_str_offsets", DWARFYAML::emitDebugStrOffsets) | .Case("debug_str_offsets", DWARFYAML::emitDebugStrOffsets) | ||||
.Default([&](raw_ostream &, const DWARFYAML::Data &) { | .Default([&](raw_ostream &, const DWARFYAML::DWARFState &) { | ||||
return createStringError(errc::not_supported, | return createStringError(errc::not_supported, | ||||
SecName + " is not supported"); | SecName + " is not supported"); | ||||
}); | }); | ||||
return EmitFunc; | return EmitFunc; | ||||
} | } | ||||
static Error | static Error | ||||
emitDebugSectionImpl(const DWARFYAML::Data &DI, StringRef Sec, | emitDebugSectionImpl(const DWARFYAML::DWARFState &DS, StringRef Sec, | ||||
StringMap<std::unique_ptr<MemoryBuffer>> &OutputBuffers) { | StringMap<std::unique_ptr<MemoryBuffer>> &OutputBuffers) { | ||||
std::string Data; | std::string Data; | ||||
raw_string_ostream DebugInfoStream(Data); | raw_string_ostream DebugInfoStream(Data); | ||||
auto EmitFunc = DWARFYAML::getDWARFEmitterByName(Sec); | auto EmitFunc = DWARFYAML::getDWARFEmitterByName(Sec); | ||||
if (Error Err = EmitFunc(DebugInfoStream, DI)) | if (Error Err = EmitFunc(DebugInfoStream, DS)) | ||||
return Err; | return Err; | ||||
DebugInfoStream.flush(); | DebugInfoStream.flush(); | ||||
if (!Data.empty()) | if (!Data.empty()) | ||||
OutputBuffers[Sec] = MemoryBuffer::getMemBufferCopy(Data); | OutputBuffers[Sec] = MemoryBuffer::getMemBufferCopy(Data); | ||||
return Error::success(); | return Error::success(); | ||||
} | } | ||||
Show All 15 Lines | DWARFYAML::emitDebugSections(StringRef YAMLString, bool IsLittleEndian, | ||||
YIn >> DI; | YIn >> DI; | ||||
if (YIn.error()) | if (YIn.error()) | ||||
return createStringError(YIn.error(), GeneratedDiag.getMessage()); | return createStringError(YIn.error(), GeneratedDiag.getMessage()); | ||||
StringMap<std::unique_ptr<MemoryBuffer>> DebugSections; | StringMap<std::unique_ptr<MemoryBuffer>> DebugSections; | ||||
Error Err = Error::success(); | Error Err = Error::success(); | ||||
cantFail(std::move(Err)); | cantFail(std::move(Err)); | ||||
Expected<DWARFState> DSOrErr = DWARFState::create(DI); | |||||
if (!DSOrErr) | |||||
return DSOrErr.takeError(); | |||||
for (StringRef SecName : DI.getNonEmptySectionNames()) | for (StringRef SecName : DI.getNonEmptySectionNames()) | ||||
Err = joinErrors(std::move(Err), | Err = joinErrors(std::move(Err), | ||||
emitDebugSectionImpl(DI, SecName, DebugSections)); | emitDebugSectionImpl(*DSOrErr, SecName, DebugSections)); | ||||
if (Err) | if (Err) | ||||
return std::move(Err); | return std::move(Err); | ||||
return std::move(DebugSections); | return std::move(DebugSections); | ||||
} | } |
If you'd do all this work in the factory function and then just pass in a finished map to the constructor, there'd be no need for the ErrorAsOutParameter thingy.