33 if (DwarfVersion <= 4)
60 if (
Form == dwarf::DW_FORM_string)
61 return InfoData.
getCStr(&InfoOffset);
64 case dwarf::DW_FORM_strx1:
65 StrIndex = InfoData.
getU8(&InfoOffset);
67 case dwarf::DW_FORM_strx2:
68 StrIndex = InfoData.
getU16(&InfoOffset);
70 case dwarf::DW_FORM_strx3:
71 StrIndex = InfoData.
getU24(&InfoOffset);
73 case dwarf::DW_FORM_strx4:
74 StrIndex = InfoData.
getU32(&InfoOffset);
76 case dwarf::DW_FORM_strx:
77 case dwarf::DW_FORM_GNU_str_index:
81 return make_error<DWPError>(
82 "string field must be encoded with one of the following: "
83 "DW_FORM_string, DW_FORM_strx, DW_FORM_strx1, DW_FORM_strx2, "
84 "DW_FORM_strx3, DW_FORM_strx4, or DW_FORM_GNU_str_index.");
87 uint64_t StrOffsetsOffset = 4 * StrIndex;
92 return StrData.
getCStr(&StrOffset);
100 if (Header.Version >= 5 && Header.UnitType != dwarf::DW_UT_split_compile)
101 return make_error<DWPError>(
102 std::string(
"unit type DW_UT_split_compile type not found in "
103 "debug_info header. Unexpected unit type 0x" +
104 utostr(Header.UnitType) +
" found"));
112 if (
Tag != dwarf::DW_TAG_compile_unit)
113 return make_error<DWPError>(
"top level DIE is not a compile unit");
115 AbbrevData.
getU8(&AbbrevOffset);
123 case dwarf::DW_AT_name: {
125 Form, InfoData,
Offset, StrOffsets, Str, Header.Version);
131 case dwarf::DW_AT_GNU_dwo_name:
132 case dwarf::DW_AT_dwo_name: {
134 Form, InfoData,
Offset, StrOffsets, Str, Header.Version);
140 case dwarf::DW_AT_GNU_dwo_id:
149 if (!Header.Signature)
150 return make_error<DWPError>(
"compile unit missing dwo_id");
151 ID.Signature = *Header.Signature;
171 return Index + DW_SECT_INFO;
177 const auto *Off = Entry.getContribution(
Kind);
180 return Section.substr(Off->getOffset(), Off->getLength());
186 bool ContinueOnCuIndexOverflow) {
189 Twine(
" Section Contribution Offset overflow 4G. Previous Offset ") +
190 Twine(PrevOffset) +
Twine(
", After overflow offset ") +
193 if (ContinueOnCuIndexOverflow) {
197 return make_error<DWPError>(Msg);
204 unsigned TypesContributionIndex,
bool ContinueOnCuIndexOverflow) {
207 auto *
I =
E.getContributions();
210 auto P = TypeIndexEntries.
insert(std::make_pair(
E.getSignature(), TUEntry));
213 auto &Entry =
P.first->second;
215 Entry.Contributions[0] = {};
221 C.setOffset(
C.getOffset() +
I->getOffset());
222 C.setLength(
I->getLength());
225 auto &
C = Entry.Contributions[TypesContributionIndex];
230 C.setOffset(TypesOffset);
232 static_assert(
sizeof(OldOffset) ==
sizeof(TypesOffset));
233 TypesOffset +=
C.getLength();
234 if (OldOffset > TypesOffset) {
236 OldOffset, TypesOffset,
"Types", ContinueOnCuIndexOverflow))
245 MCSection *OutputTypes,
const std::vector<StringRef> &TypesSections,
247 bool ContinueOnCuIndexOverflow) {
255 Entry.Contributions[0] = {};
257 C.setOffset(TypesOffset);
266 Offset = PrevOffset +
C.getLength32();
268 auto P = TypeIndexEntries.
insert(std::make_pair(Signature, Entry));
272 Out.
emitBytes(Types.substr(PrevOffset,
C.getLength32()));
274 TypesOffset +=
C.getLength32();
275 if (OldOffset > TypesOffset) {
277 OldOffset, TypesOffset,
"types", ContinueOnCuIndexOverflow))
287 std::string Text =
"\'";
290 bool HasDWO = !DWOName.
empty();
291 bool HasDWP = !DWPName.
empty();
292 if (HasDWO || HasDWP) {
299 if (HasDWO && HasDWP)
301 if (!DWPName.
empty()) {
312 return make_error<DWPError>(
313 (
"failure while decompressing compressed section: '" +
Name +
"', " +
321 auto *Obj = dyn_cast<ELFObjectFileBase>(Sec.
getObject());
325 bool IsLE = isa<object::ELF32LEObjectFile>(Obj) ||
326 isa<object::ELF64LEObjectFile>(Obj);
327 bool Is64 = isa<object::ELF64LEObjectFile>(Obj) ||
328 isa<object::ELF64BEObjectFile>(Obj);
333 UncompressedSections.emplace_back();
334 if (
Error E = Dec->resizeAndDecompress(UncompressedSections.back()))
337 Contents = UncompressedSections.
back();
348 std::tie(Header.Length, Header.Format) =
351 return make_error<DWPError>(
"cannot parse compile unit length: " +
355 return make_error<DWPError>(
356 "compile unit exceeds .debug_info section range: " +
357 utostr(
Offset + Header.Length) +
" >= " + utostr(InfoData.
size()));
362 return make_error<DWPError>(
"cannot parse compile unit version: " +
366 if (Header.Version >= 5) {
369 MinHeaderLength = 16;
374 if (Header.Length < MinHeaderLength) {
375 return make_error<DWPError>(
"unit length is too small: expected at least " +
376 utostr(MinHeaderLength) +
" got " +
377 utostr(Header.Length) +
".");
379 if (Header.Version >= 5) {
384 if (Header.UnitType == dwarf::DW_UT_split_type) {
386 MinHeaderLength += 4;
387 if (Header.Length < MinHeaderLength)
388 return make_error<DWPError>(
"type unit is missing type offset");
398 Header.HeaderSize =
Offset;
408 if (CurStrSection.
empty() || CurStrOffsetSection.
empty())
416 while (
const char *S =
Data.getCStr(&LocalOffset)) {
417 OffsetRemapping[PrevOffset] =
418 Strings.getOffset(S, LocalOffset - PrevOffset);
419 PrevOffset = LocalOffset;
430 assert(HeaderSize <=
Size &&
"StrOffsetSection size is less than its header");
435 auto NewOffset = OffsetRemapping[OldOffset];
444 for (
const auto &
E : IndexEntries)
445 for (
size_t I = 0;
I != std::size(
E.second.Contributions); ++
I)
446 if (ContributionOffsets[
I])
448 ?
E.second.Contributions[
I].getOffset32()
449 :
E.second.Contributions[
I].getLength32()),
457 if (IndexEntries.
empty())
460 unsigned Columns = 0;
461 for (
auto &
C : ContributionOffsets)
468 for (
const auto &
P : IndexEntries) {
471 auto HP = ((S >> 32) & Mask) | 1;
473 assert(S != IndexEntries.
begin()[Buckets[
H] - 1].first &&
488 for (
const auto &
I : Buckets)
492 for (
const auto &
I : Buckets)
496 for (
size_t I = 0;
I != ContributionOffsets.
size(); ++
I)
497 if (ContributionOffsets[
I])
509 return make_error<DWPError>(
510 std::string(
"duplicate DWO ID (") + utohexstr(PrevE.first) +
") in " +
512 PrevE.second.DWOName) +
517 const StringMap<std::pair<MCSection *, DWARFSectionKind>> &KnownSections,
525 std::vector<StringRef> &CurTypesSection,
526 std::vector<StringRef> &CurInfoSection,
StringRef &AbbrevSection,
528 std::vector<std::pair<DWARFSectionKind, uint32_t>> &SectionLength) {
532 if (Section.isVirtual())
551 auto SectionPair = KnownSections.find(
Name);
552 if (SectionPair == KnownSections.end())
557 SectionLength.push_back(std::make_pair(
Kind, Contents.
size()));
560 if (
Kind == DW_SECT_ABBREV) {
561 AbbrevSection = Contents;
565 MCSection *OutSection = SectionPair->second.first;
566 if (OutSection == StrOffsetSection)
567 CurStrOffsetSection = Contents;
568 else if (OutSection == StrSection)
569 CurStrSection = Contents;
570 else if (OutSection == TypesSection)
571 CurTypesSection.push_back(Contents);
572 else if (OutSection == CUIndexSection)
573 CurCUIndexSection = Contents;
574 else if (OutSection == TUIndexSection)
575 CurTUIndexSection = Contents;
576 else if (OutSection == InfoSection)
577 CurInfoSection.push_back(Contents);
586 bool ContinueOnCuIndexOverflow) {
588 MCSection *
const StrSection = MCOFI.getDwarfStrDWOSection();
589 MCSection *
const StrOffsetSection = MCOFI.getDwarfStrOffDWOSection();
590 MCSection *
const TypesSection = MCOFI.getDwarfTypesDWOSection();
591 MCSection *
const CUIndexSection = MCOFI.getDwarfCUIndexSection();
592 MCSection *
const TUIndexSection = MCOFI.getDwarfTUIndexSection();
593 MCSection *
const InfoSection = MCOFI.getDwarfInfoDWOSection();
595 {
"debug_info.dwo", {InfoSection, DW_SECT_INFO}},
597 {
"debug_str_offsets.dwo", {StrOffsetSection, DW_SECT_STR_OFFSETS}},
600 {
"debug_line.dwo", {MCOFI.getDwarfLineDWOSection(), DW_SECT_LINE}},
601 {
"debug_macro.dwo", {MCOFI.getDwarfMacroDWOSection(), DW_SECT_MACRO}},
602 {
"debug_abbrev.dwo", {MCOFI.getDwarfAbbrevDWOSection(), DW_SECT_ABBREV}},
603 {
"debug_loclists.dwo",
604 {MCOFI.getDwarfLoclistsDWOSection(), DW_SECT_LOCLISTS}},
605 {
"debug_rnglists.dwo",
606 {MCOFI.getDwarfRnglistsDWOSection(), DW_SECT_RNGLISTS}},
613 uint32_t ContributionOffsets[8] = {};
622 std::deque<SmallString<32>> UncompressedSections;
624 for (
const auto &Input : Inputs) {
628 [&](std::unique_ptr<ECError> EC) ->
Error {
629 return createFileError(Input, Error(std::move(EC)));
633 auto &Obj = *ErrOrObj->getBinary();
640 std::vector<StringRef> CurTypesSection;
641 std::vector<StringRef> CurInfoSection;
649 std::vector<std::pair<DWARFSectionKind, uint32_t>> SectionLength;
651 for (
const auto &Section : Obj.sections())
653 KnownSections, StrSection, StrOffsetSection, TypesSection,
654 CUIndexSection, TUIndexSection, InfoSection, Section, Out,
655 UncompressedSections, ContributionOffsets, CurEntry,
656 CurStrSection, CurStrOffsetSection, CurTypesSection,
657 CurInfoSection, AbbrevSection, CurCUIndexSection,
658 CurTUIndexSection, SectionLength))
661 if (CurInfoSection.empty())
671 Version = Header.Version;
672 IndexVersion = Version < 5 ? 2 : 5;
673 }
else if (Version != Header.Version) {
674 return make_error<DWPError>(
"incompatible DWARF compile unit versions.");
678 CurStrOffsetSection, Header.Version);
680 for (
auto Pair : SectionLength) {
686 if (OldOffset > ContributionOffsets[
Index]) {
688 for (
auto &Section : Obj.sections()) {
689 if (SectionIndex ==
Index) {
691 OldOffset, ContributionOffsets[
Index], *Section.getName(),
692 ContinueOnCuIndexOverflow);
701 if (CurCUIndexSection.
empty()) {
702 bool FoundCUUnit =
false;
706 while (
Info.size() > UnitOffset) {
716 C.setOffset(InfoSectionOffset);
717 C.setLength(Header.Length + 4);
719 if (std::numeric_limits<uint32_t>::max() - InfoSectionOffset <
722 InfoSectionOffset, InfoSectionOffset +
C.getLength32(),
723 "debug_info", ContinueOnCuIndexOverflow))
727 UnitOffset +=
C.getLength32();
728 if (Header.Version < 5 ||
729 Header.UnitType == dwarf::DW_UT_split_compile) {
731 Header, AbbrevSection,
732 Info.substr(UnitOffset -
C.getLength32(),
C.getLength32()),
733 CurStrOffsetSection, CurStrSection);
737 const auto &
ID = *EID;
738 auto P = IndexEntries.
insert(std::make_pair(
ID.Signature, Entry));
741 P.first->second.Name =
ID.Name;
742 P.first->second.DWOName =
ID.DWOName;
745 }
else if (Header.UnitType == dwarf::DW_UT_split_type) {
746 auto P = TypeIndexEntries.
insert(
747 std::make_pair(*Header.Signature, Entry));
752 Info.substr(UnitOffset -
C.getLength32(),
C.getLength32()));
753 InfoSectionOffset +=
C.getLength32();
758 return make_error<DWPError>(
"no compile unit found in file: " + Input);
760 if (IndexVersion == 2) {
763 Out, TypeIndexEntries, TypesSection, CurTypesSection, CurEntry,
765 ContinueOnCuIndexOverflow))
771 if (CurInfoSection.size() != 1)
772 return make_error<DWPError>(
"expected exactly one occurrence of a debug "
773 "info section in a .dwp file");
777 DataExtractor CUIndexData(CurCUIndexSection, Obj.isLittleEndian(), 0);
778 if (!CUIndex.
parse(CUIndexData))
779 return make_error<DWPError>(
"failed to parse cu_index");
781 return make_error<DWPError>(
"incompatible cu_index versions, found " +
783 " and expecting " + utostr(IndexVersion));
787 auto *
I =
E.getContributions();
790 auto P = IndexEntries.
insert(std::make_pair(
E.getSignature(), CurEntry));
806 const auto &
ID = *EID;
809 auto &NewEntry =
P.first->second;
810 NewEntry.Name =
ID.Name;
811 NewEntry.DWOName =
ID.DWOName;
812 NewEntry.DWPName = Input;
818 C.setOffset(
C.getOffset() +
I->getOffset());
819 C.setLength(
I->getLength());
823 auto &
C = NewEntry.Contributions[
Index];
825 C.setOffset(InfoSectionOffset);
826 InfoSectionOffset +=
C.getLength32();
829 if (!CurTUIndexSection.
empty()) {
835 TUSectionKind = DW_SECT_INFO;
836 OutSection = InfoSection;
837 TypeInputSection = DwpSingleInfoSection;
840 if (CurTypesSection.size() != 1)
841 return make_error<DWPError>(
842 "multiple type unit sections in .dwp file");
845 OutSection = TypesSection;
846 TypeInputSection = CurTypesSection.
front();
850 DataExtractor TUIndexData(CurTUIndexSection, Obj.isLittleEndian(), 0);
851 if (!TUIndex.
parse(TUIndexData))
852 return make_error<DWPError>(
"failed to parse tu_index");
854 return make_error<DWPError>(
"incompatible tu_index versions, found " +
856 " and expecting " + utostr(IndexVersion));
858 unsigned TypesContributionIndex =
861 Out, TypeIndexEntries, TUIndex, OutSection, TypeInputSection,
862 CurEntry, ContributionOffsets[TypesContributionIndex],
863 TypesContributionIndex, ContinueOnCuIndexOverflow))
872 ContributionOffsets[0] = 0;
874 writeIndex(Out, MCOFI.getDwarfTUIndexSection(), ContributionOffsets,
875 TypeIndexEntries, IndexVersion);
882 ContributionOffsets[0] = 1;
885 writeIndex(Out, MCOFI.getDwarfCUIndexSection(), ContributionOffsets,
886 IndexEntries, IndexVersion);
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Analysis containing CSE Info
static uint64_t getCUAbbrev(StringRef Abbrev, uint64_t AbbrCode)
static Error addAllTypesFromDWP(MCStreamer &Out, MapVector< uint64_t, UnitIndexEntry > &TypeIndexEntries, const DWARFUnitIndex &TUIndex, MCSection *OutputTypes, StringRef Types, const UnitIndexEntry &TUEntry, uint32_t &TypesOffset, unsigned TypesContributionIndex, bool ContinueOnCuIndexOverflow)
static Error handleCompressedSection(std::deque< SmallString< 32 > > &UncompressedSections, SectionRef Sec, StringRef Name, StringRef &Contents)
static std::string buildDWODescription(StringRef Name, StringRef DWPName, StringRef DWOName)
static Error sectionOverflowErrorOrWarning(uint32_t PrevOffset, uint32_t OverflowedOffset, StringRef SectionName, bool ContinueOnCuIndexOverflow)
static uint64_t debugStrOffsetsHeaderSize(DataExtractor StrOffsetsData, uint16_t DwarfVersion)
static Expected< const char * > getIndexedString(dwarf::Form Form, DataExtractor InfoData, uint64_t &InfoOffset, StringRef StrOffsets, StringRef Str, uint16_t Version)
static unsigned getOnDiskSectionId(unsigned Index)
static Expected< CompileUnitIdentifiers > getCUIdentifiers(InfoSectionUnitHeader &Header, StringRef Abbrev, StringRef Info, StringRef StrOffsets, StringRef Str)
static Error addAllTypesFromTypesSection(MCStreamer &Out, MapVector< uint64_t, UnitIndexEntry > &TypeIndexEntries, MCSection *OutputTypes, const std::vector< StringRef > &TypesSections, const UnitIndexEntry &CUEntry, uint32_t &TypesOffset, bool ContinueOnCuIndexOverflow)
static mc::RegisterMCTargetOptionsFlags MCTargetOptionsFlags
static StringRef getSubsection(StringRef Section, const DWARFUnitIndex::Entry &Entry, DWARFSectionKind Kind)
static Error createError(StringRef Name, Error E)
static bool isSupportedSectionKind(DWARFSectionKind Kind)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static uint32_t getFlags(const Symbol *Sym)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
void setOffset(uint64_t Value)
void setLength(uint64_t Value)
uint32_t getLength32() const
uint64_t getOffset() const
uint32_t getVersion() const
bool parse(DataExtractor IndexData)
ArrayRef< DWARFSectionKind > getColumnKinds() const
ArrayRef< Entry > getRows() const
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
const MCObjectFileInfo * getObjectFileInfo() const
Instances of this class represent a uniqued identifier for a section in the current translation unit.
Streaming machine code generation interface.
MCContext & getContext() const
virtual void emitIntValue(uint64_t Value, unsigned Size)
Special case of EmitValue that avoids the client having to pass in a MCExpr for constant integers.
virtual void switchSection(MCSection *Section, const MCExpr *Subsection=nullptr)
Set the current section where code is being emitted to Section.
virtual void emitBytes(StringRef Data)
Emit the bytes in Data into the output.
This class implements a map that also provides access to all stored values in a deterministic order.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
void reserve(size_type N)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
StringRef - Represent a constant reference to a string, i.e.
constexpr bool empty() const
empty - Check if the string is empty.
char back() const
back - Get the last character in the string.
constexpr size_t size() const
size - Get the string size.
char front() const
front - Get the first character in the string.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
static void defaultWarningHandler(Error Warning)
Implement default handling for Warning.
static Expected< Decompressor > create(StringRef Name, StringRef Data, bool IsLE, bool Is64Bit)
Create decompressor object.
static Expected< OwningBinary< ObjectFile > > createObjectFile(StringRef ObjectPath)
This is a value type class that represents a single section in the list of sections in the object fil...
const ObjectFile * getObject() const
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
std::optional< const char * > toString(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract a string value from it.
@ DW_LENGTH_DWARF64
Indicator of 64-bit DWARF format.
This is an optimization pass for GlobalISel generic memory operations.
Error createFileError(const Twine &F, Error E)
Concatenate a source file path and/or name with an Error.
Error buildDuplicateError(const std::pair< uint64_t, UnitIndexEntry > &PrevE, const CompileUnitIdentifiers &ID, StringRef DWPName)
void writeIndex(MCStreamer &Out, MCSection *Section, ArrayRef< unsigned > ContributionOffsets, const MapVector< uint64_t, UnitIndexEntry > &IndexEntries, uint32_t IndexVersion)
Error handleErrors(Error E, HandlerTs &&... Hs)
Pass the ErrorInfo(s) contained in E to their respective handlers.
Error write(MCStreamer &Out, ArrayRef< std::string > Inputs, bool ContinueOnCuIndexOverflow)
void writeStringsAndOffsets(MCStreamer &Out, DWPStringPool &Strings, MCSection *StrOffsetSection, StringRef CurStrSection, StringRef CurStrOffsetSection, uint16_t Version)
DWARFSectionKind
The enum of section identifiers to be used in internal interfaces.
@ DW_SECT_EXT_unknown
Denotes a value read from an index section that does not correspond to any of the supported standards...
uint32_t serializeSectionKind(DWARFSectionKind Kind, unsigned IndexVersion)
Convert the internal value for a section kind to an on-disk value.
Error handleSection(const StringMap< std::pair< MCSection *, DWARFSectionKind > > &KnownSections, const MCSection *StrSection, const MCSection *StrOffsetSection, const MCSection *TypesSection, const MCSection *CUIndexSection, const MCSection *TUIndexSection, const MCSection *InfoSection, const object::SectionRef &Section, MCStreamer &Out, std::deque< SmallString< 32 > > &UncompressedSections, uint32_t(&ContributionOffsets)[8], UnitIndexEntry &CurEntry, StringRef &CurStrSection, StringRef &CurStrOffsetSection, std::vector< StringRef > &CurTypesSection, std::vector< StringRef > &CurInfoSection, StringRef &AbbrevSection, StringRef &CurCUIndexSection, StringRef &CurTUIndexSection, std::vector< std::pair< DWARFSectionKind, uint32_t > > &SectionLength)
void writeIndexTable(MCStreamer &Out, ArrayRef< unsigned > ContributionOffsets, const MapVector< uint64_t, UnitIndexEntry > &IndexEntries, const AccessField &Field)
unsigned getContributionIndex(DWARFSectionKind Kind, uint32_t IndexVersion)
Expected< InfoSectionUnitHeader > parseInfoSectionUnitHeader(StringRef Info)
constexpr uint64_t NextPowerOf2(uint64_t A)
Returns the next power of two (in 64-bits) that is strictly greater than A.
DWARFUnitIndex::Entry::SectionContribution Contributions[8]
Create this object with static storage to register mc-related command line options.