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());
187 bool &AnySectionOverflow) {
190 Twine(
" Section Contribution Offset overflow 4G. Previous Offset ") +
191 Twine(PrevOffset) +
Twine(
", After overflow offset ") +
194 if (OverflowOptValue == OnCuIndexOverflow::Continue) {
197 }
else if (OverflowOptValue == OnCuIndexOverflow::SoftStop) {
198 AnySectionOverflow =
true;
202 return make_error<DWPError>(Msg);
210 bool &AnySectionOverflow) {
213 auto *
I = E.getContributions();
216 auto P = TypeIndexEntries.
insert(std::make_pair(E.getSignature(), TUEntry));
219 auto &Entry =
P.first->second;
221 Entry.Contributions[0] = {};
227 C.setOffset(
C.getOffset() +
I->getOffset());
228 C.setLength(
I->getLength());
231 auto &
C = Entry.Contributions[TypesContributionIndex];
236 C.setOffset(TypesOffset);
238 static_assert(
sizeof(OldOffset) ==
sizeof(TypesOffset));
239 TypesOffset +=
C.getLength();
240 if (OldOffset > TypesOffset) {
242 "Types", OverflowOptValue,
245 if (AnySectionOverflow) {
246 TypesOffset = OldOffset;
256 MCSection *OutputTypes,
const std::vector<StringRef> &TypesSections,
263 while (Data.isValidOffset(
Offset)) {
266 Entry.Contributions[0] = {};
268 C.setOffset(TypesOffset);
271 C.setLength(Data.getU32(&
Offset) + 4);
276 auto Signature = Data.getU64(&
Offset);
277 Offset = PrevOffset +
C.getLength32();
279 auto P = TypeIndexEntries.
insert(std::make_pair(Signature, Entry));
283 Out.
emitBytes(Types.substr(PrevOffset,
C.getLength32()));
285 TypesOffset +=
C.getLength32();
286 if (OldOffset > TypesOffset) {
288 "Types", OverflowOptValue,
291 if (AnySectionOverflow) {
292 TypesOffset = OldOffset;
303 std::string Text =
"\'";
306 bool HasDWO = !DWOName.
empty();
307 bool HasDWP = !DWPName.
empty();
308 if (HasDWO || HasDWP) {
315 if (HasDWO && HasDWP)
317 if (!DWPName.
empty()) {
328 return make_error<DWPError>(
329 (
"failure while decompressing compressed section: '" +
Name +
"', " +
337 auto *Obj = dyn_cast<ELFObjectFileBase>(Sec.
getObject());
341 bool IsLE = isa<object::ELF32LEObjectFile>(Obj) ||
342 isa<object::ELF64LEObjectFile>(Obj);
343 bool Is64 = isa<object::ELF64LEObjectFile>(Obj) ||
344 isa<object::ELF64BEObjectFile>(Obj);
349 UncompressedSections.emplace_back();
350 if (
Error E = Dec->resizeAndDecompress(UncompressedSections.back()))
353 Contents = UncompressedSections.
back();
364 std::tie(Header.Length, Header.Format) =
367 return make_error<DWPError>(
"cannot parse compile unit length: " +
371 return make_error<DWPError>(
372 "compile unit exceeds .debug_info section range: " +
373 utostr(
Offset + Header.Length) +
" >= " + utostr(InfoData.
size()));
378 return make_error<DWPError>(
"cannot parse compile unit version: " +
382 if (Header.Version >= 5) {
385 MinHeaderLength = 16;
390 if (Header.Length < MinHeaderLength) {
391 return make_error<DWPError>(
"unit length is too small: expected at least " +
392 utostr(MinHeaderLength) +
" got " +
393 utostr(Header.Length) +
".");
395 if (Header.Version >= 5) {
400 if (Header.UnitType == dwarf::DW_UT_split_type) {
402 MinHeaderLength += 4;
403 if (Header.Length < MinHeaderLength)
404 return make_error<DWPError>(
"type unit is missing type offset");
414 Header.HeaderSize =
Offset;
424 auto NewOffset = OffsetRemapping[OldOffset];
435 if (CurStrSection.
empty() || CurStrOffsetSection.
empty())
443 while (
const char *S =
Data.getCStr(&LocalOffset)) {
444 OffsetRemapping[PrevOffset] =
445 Strings.getOffset(S, LocalOffset - PrevOffset);
446 PrevOffset = LocalOffset;
459 "StrOffsetSection size is less than its header");
464 if (HeaderSize == 8) {
465 ContributionSize =
Data.getU32(&HeaderLengthOffset);
466 }
else if (HeaderSize == 16) {
467 HeaderLengthOffset += 4;
468 ContributionSize =
Data.getU64(&HeaderLengthOffset);
470 ContributionEnd = ContributionSize + HeaderLengthOffset;
484 for (
const auto &E : IndexEntries)
485 for (
size_t I = 0;
I != std::size(E.second.Contributions); ++
I)
486 if (ContributionOffsets[
I])
488 ? E.second.Contributions[
I].getOffset32()
489 : E.second.Contributions[
I].getLength32()),
497 if (IndexEntries.
empty())
500 unsigned Columns = 0;
501 for (
auto &
C : ContributionOffsets)
508 for (
const auto &
P : IndexEntries) {
511 auto HP = ((S >> 32) & Mask) | 1;
513 assert(S != IndexEntries.
begin()[Buckets[
H] - 1].first &&
528 for (
const auto &
I : Buckets)
532 for (
const auto &
I : Buckets)
536 for (
size_t I = 0;
I != ContributionOffsets.
size(); ++
I)
537 if (ContributionOffsets[
I])
549 return make_error<DWPError>(
550 std::string(
"duplicate DWO ID (") + utohexstr(PrevE.first) +
") in " +
552 PrevE.second.DWOName) +
557 const StringMap<std::pair<MCSection *, DWARFSectionKind>> &KnownSections,
565 std::vector<StringRef> &CurTypesSection,
566 std::vector<StringRef> &CurInfoSection,
StringRef &AbbrevSection,
568 std::vector<std::pair<DWARFSectionKind, uint32_t>> &SectionLength) {
572 if (Section.isVirtual())
591 auto SectionPair = KnownSections.find(
Name);
592 if (SectionPair == KnownSections.end())
597 SectionLength.push_back(std::make_pair(
Kind, Contents.
size()));
600 if (
Kind == DW_SECT_ABBREV) {
601 AbbrevSection = Contents;
605 MCSection *OutSection = SectionPair->second.first;
606 if (OutSection == StrOffsetSection)
607 CurStrOffsetSection = Contents;
608 else if (OutSection == StrSection)
609 CurStrSection = Contents;
610 else if (OutSection == TypesSection)
611 CurTypesSection.push_back(Contents);
612 else if (OutSection == CUIndexSection)
613 CurCUIndexSection = Contents;
614 else if (OutSection == TUIndexSection)
615 CurTUIndexSection = Contents;
616 else if (OutSection == InfoSection)
617 CurInfoSection.push_back(Contents);
628 MCSection *
const StrSection = MCOFI.getDwarfStrDWOSection();
629 MCSection *
const StrOffsetSection = MCOFI.getDwarfStrOffDWOSection();
630 MCSection *
const TypesSection = MCOFI.getDwarfTypesDWOSection();
631 MCSection *
const CUIndexSection = MCOFI.getDwarfCUIndexSection();
632 MCSection *
const TUIndexSection = MCOFI.getDwarfTUIndexSection();
633 MCSection *
const InfoSection = MCOFI.getDwarfInfoDWOSection();
635 {
"debug_info.dwo", {InfoSection, DW_SECT_INFO}},
637 {
"debug_str_offsets.dwo", {StrOffsetSection, DW_SECT_STR_OFFSETS}},
640 {
"debug_line.dwo", {MCOFI.getDwarfLineDWOSection(), DW_SECT_LINE}},
641 {
"debug_macro.dwo", {MCOFI.getDwarfMacroDWOSection(), DW_SECT_MACRO}},
642 {
"debug_abbrev.dwo", {MCOFI.getDwarfAbbrevDWOSection(), DW_SECT_ABBREV}},
643 {
"debug_loclists.dwo",
644 {MCOFI.getDwarfLoclistsDWOSection(), DW_SECT_LOCLISTS}},
645 {
"debug_rnglists.dwo",
646 {MCOFI.getDwarfRnglistsDWOSection(), DW_SECT_RNGLISTS}},
653 uint32_t ContributionOffsets[8] = {};
656 bool AnySectionOverflow =
false;
663 std::deque<SmallString<32>> UncompressedSections;
665 for (
const auto &Input : Inputs) {
669 [&](std::unique_ptr<ECError> EC) ->
Error {
670 return createFileError(Input, Error(std::move(EC)));
674 auto &Obj = *ErrOrObj->getBinary();
681 std::vector<StringRef> CurTypesSection;
682 std::vector<StringRef> CurInfoSection;
690 std::vector<std::pair<DWARFSectionKind, uint32_t>> SectionLength;
692 for (
const auto &Section : Obj.sections())
694 KnownSections, StrSection, StrOffsetSection, TypesSection,
695 CUIndexSection, TUIndexSection, InfoSection, Section, Out,
696 UncompressedSections, ContributionOffsets, CurEntry,
697 CurStrSection, CurStrOffsetSection, CurTypesSection,
698 CurInfoSection, AbbrevSection, CurCUIndexSection,
699 CurTUIndexSection, SectionLength))
702 if (CurInfoSection.empty())
713 IndexVersion =
Version < 5 ? 2 : 5;
714 }
else if (
Version != Header.Version) {
715 return make_error<DWPError>(
"incompatible DWARF compile unit versions.");
719 CurStrOffsetSection, Header.Version);
721 for (
auto Pair : SectionLength) {
727 if (OldOffset > ContributionOffsets[
Index]) {
729 for (
auto &Section : Obj.sections()) {
730 if (SectionIndex ==
Index) {
732 OldOffset, ContributionOffsets[
Index], *Section.getName(),
733 OverflowOptValue, AnySectionOverflow))
738 if (AnySectionOverflow)
745 if (CurCUIndexSection.
empty()) {
746 bool FoundCUUnit =
false;
750 while (
Info.size() > UnitOffset) {
760 C.setOffset(InfoSectionOffset);
761 C.setLength(Header.Length + 4);
763 if (std::numeric_limits<uint32_t>::max() - InfoSectionOffset <
766 InfoSectionOffset, InfoSectionOffset +
C.getLength32(),
767 "debug_info", OverflowOptValue, AnySectionOverflow))
769 if (AnySectionOverflow) {
770 if (Header.Version < 5 ||
771 Header.UnitType == dwarf::DW_UT_split_compile)
777 UnitOffset +=
C.getLength32();
778 if (Header.Version < 5 ||
779 Header.UnitType == dwarf::DW_UT_split_compile) {
781 Header, AbbrevSection,
782 Info.substr(UnitOffset -
C.getLength32(),
C.getLength32()),
783 CurStrOffsetSection, CurStrSection);
787 const auto &
ID = *EID;
788 auto P = IndexEntries.
insert(std::make_pair(
ID.Signature, Entry));
791 P.first->second.Name =
ID.Name;
792 P.first->second.DWOName =
ID.DWOName;
795 }
else if (Header.UnitType == dwarf::DW_UT_split_type) {
796 auto P = TypeIndexEntries.
insert(
797 std::make_pair(*Header.Signature, Entry));
802 Info.substr(UnitOffset -
C.getLength32(),
C.getLength32()));
803 InfoSectionOffset +=
C.getLength32();
805 if (AnySectionOverflow)
810 return make_error<DWPError>(
"no compile unit found in file: " + Input);
812 if (IndexVersion == 2) {
815 Out, TypeIndexEntries, TypesSection, CurTypesSection, CurEntry,
817 OverflowOptValue, AnySectionOverflow))
820 if (AnySectionOverflow)
825 if (CurInfoSection.size() != 1)
826 return make_error<DWPError>(
"expected exactly one occurrence of a debug "
827 "info section in a .dwp file");
831 DataExtractor CUIndexData(CurCUIndexSection, Obj.isLittleEndian(), 0);
832 if (!CUIndex.
parse(CUIndexData))
833 return make_error<DWPError>(
"failed to parse cu_index");
835 return make_error<DWPError>(
"incompatible cu_index versions, found " +
837 " and expecting " + utostr(IndexVersion));
841 auto *
I = E.getContributions();
844 auto P = IndexEntries.
insert(std::make_pair(E.getSignature(), CurEntry));
860 const auto &
ID = *EID;
863 auto &NewEntry =
P.first->second;
864 NewEntry.Name =
ID.Name;
865 NewEntry.DWOName =
ID.DWOName;
866 NewEntry.DWPName = Input;
872 C.setOffset(
C.getOffset() +
I->getOffset());
873 C.setLength(
I->getLength());
877 auto &
C = NewEntry.Contributions[
Index];
879 C.setOffset(InfoSectionOffset);
880 InfoSectionOffset +=
C.getLength32();
883 if (!CurTUIndexSection.
empty()) {
889 TUSectionKind = DW_SECT_INFO;
890 OutSection = InfoSection;
891 TypeInputSection = DwpSingleInfoSection;
894 if (CurTypesSection.size() != 1)
895 return make_error<DWPError>(
896 "multiple type unit sections in .dwp file");
899 OutSection = TypesSection;
900 TypeInputSection = CurTypesSection.
front();
904 DataExtractor TUIndexData(CurTUIndexSection, Obj.isLittleEndian(), 0);
905 if (!TUIndex.
parse(TUIndexData))
906 return make_error<DWPError>(
"failed to parse tu_index");
908 return make_error<DWPError>(
"incompatible tu_index versions, found " +
910 " and expecting " + utostr(IndexVersion));
912 unsigned TypesContributionIndex =
915 Out, TypeIndexEntries, TUIndex, OutSection, TypeInputSection,
916 CurEntry, ContributionOffsets[TypesContributionIndex],
917 TypesContributionIndex, OverflowOptValue, AnySectionOverflow))
920 if (AnySectionOverflow)
928 ContributionOffsets[0] = 0;
930 writeIndex(Out, MCOFI.getDwarfTUIndexSection(), ContributionOffsets,
931 TypeIndexEntries, IndexVersion);
938 ContributionOffsets[0] = 1;
941 writeIndex(Out, MCOFI.getDwarfCUIndexSection(), ContributionOffsets,
942 IndexEntries, IndexVersion);
Analysis containing CSE Info
static uint64_t getCUAbbrev(StringRef Abbrev, uint64_t AbbrCode)
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 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 Error addAllTypesFromTypesSection(MCStreamer &Out, MapVector< uint64_t, UnitIndexEntry > &TypeIndexEntries, MCSection *OutputTypes, const std::vector< StringRef > &TypesSections, const UnitIndexEntry &CUEntry, uint32_t &TypesOffset, OnCuIndexOverflow OverflowOptValue, bool &AnySectionOverflow)
static unsigned getOnDiskSectionId(unsigned Index)
static Expected< CompileUnitIdentifiers > getCUIdentifiers(InfoSectionUnitHeader &Header, StringRef Abbrev, StringRef Info, StringRef StrOffsets, StringRef Str)
static Error sectionOverflowErrorOrWarning(uint32_t PrevOffset, uint32_t OverflowedOffset, StringRef SectionName, OnCuIndexOverflow OverflowOptValue, bool &AnySectionOverflow)
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)
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, OnCuIndexOverflow OverflowOptValue, bool &AnySectionOverflow)
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, uint32_t Subsec=0)
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.
static void writeNewOffsetsTo(MCStreamer &Out, DataExtractor &Data, DenseMap< uint64_t, uint32_t > &OffsetRemapping, uint64_t &Offset, uint64_t &Size)
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 write(MCStreamer &Out, ArrayRef< std::string > Inputs, OnCuIndexOverflow OverflowOptValue)
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.