31 if (DwarfVersion <= 4)
58 if (
Form == dwarf::DW_FORM_string)
59 return InfoData.
getCStr(&InfoOffset);
62 case dwarf::DW_FORM_strx1:
63 StrIndex = InfoData.
getU8(&InfoOffset);
65 case dwarf::DW_FORM_strx2:
66 StrIndex = InfoData.
getU16(&InfoOffset);
68 case dwarf::DW_FORM_strx3:
69 StrIndex = InfoData.
getU24(&InfoOffset);
71 case dwarf::DW_FORM_strx4:
72 StrIndex = InfoData.
getU32(&InfoOffset);
74 case dwarf::DW_FORM_strx:
75 case dwarf::DW_FORM_GNU_str_index:
79 return make_error<DWPError>(
80 "string field must be encoded with one of the following: "
81 "DW_FORM_string, DW_FORM_strx, DW_FORM_strx1, DW_FORM_strx2, "
82 "DW_FORM_strx3, DW_FORM_strx4, or DW_FORM_GNU_str_index.");
85 uint64_t StrOffsetsOffset = 4 * StrIndex;
90 return StrData.
getCStr(&StrOffset);
98 if (Header.Version >= 5 && Header.UnitType != dwarf::DW_UT_split_compile)
99 return make_error<DWPError>(
100 std::string(
"unit type DW_UT_split_compile type not found in "
101 "debug_info header. Unexpected unit type 0x" +
102 utostr(Header.UnitType) +
" found"));
110 if (
Tag != dwarf::DW_TAG_compile_unit)
111 return make_error<DWPError>(
"top level DIE is not a compile unit");
113 AbbrevData.
getU8(&AbbrevOffset);
121 case dwarf::DW_AT_name: {
123 Form, InfoData,
Offset, StrOffsets, Str, Header.Version);
129 case dwarf::DW_AT_GNU_dwo_name:
130 case dwarf::DW_AT_dwo_name: {
132 Form, InfoData,
Offset, StrOffsets, Str, Header.Version);
138 case dwarf::DW_AT_GNU_dwo_id:
147 if (!Header.Signature)
148 return make_error<DWPError>(
"compile unit missing dwo_id");
149 ID.Signature = *Header.Signature;
169 return Index + DW_SECT_INFO;
175 const auto *Off = Entry.getContribution(
Kind);
178 return Section.substr(Off->getOffset(), Off->getLength());
186 uint32_t &TypesOffset,
unsigned TypesContributionIndex) {
189 auto *
I =
E.getContributions();
192 auto P = TypeIndexEntries.
insert(std::make_pair(
E.getSignature(), TUEntry));
195 auto &Entry =
P.first->second;
197 Entry.Contributions[0] = {};
203 C.setOffset(
C.getOffset() +
I->getOffset());
204 C.setLength(
I->getLength());
207 auto &
C = Entry.Contributions[TypesContributionIndex];
212 C.setOffset(TypesOffset);
213 TypesOffset +=
C.getLength();
219 MCSection *OutputTypes,
const std::vector<StringRef> &TypesSections,
228 Entry.Contributions[0] = {};
230 C.setOffset(TypesOffset);
239 Offset = PrevOffset +
C.getLength32();
241 auto P = TypeIndexEntries.
insert(std::make_pair(Signature, Entry));
245 Out.
emitBytes(Types.substr(PrevOffset,
C.getLength32()));
246 TypesOffset +=
C.getLength32();
253 std::string
Text =
"\'";
256 bool HasDWO = !DWOName.
empty();
257 bool HasDWP = !DWPName.
empty();
258 if (HasDWO || HasDWP) {
265 if (HasDWO && HasDWP)
267 if (!DWPName.
empty()) {
278 return make_error<DWPError>(
279 (
"failure while decompressing compressed section: '" +
Name +
"', " +
287 auto *Obj = dyn_cast<ELFObjectFileBase>(Sec.
getObject());
291 bool IsLE = isa<object::ELF32LEObjectFile>(Obj) ||
292 isa<object::ELF64LEObjectFile>(Obj);
293 bool Is64 = isa<object::ELF64LEObjectFile>(Obj) ||
294 isa<object::ELF64BEObjectFile>(Obj);
299 UncompressedSections.emplace_back();
300 if (
Error E = Dec->resizeAndDecompress(UncompressedSections.back()))
303 Contents = UncompressedSections.
back();
314 std::tie(Header.Length, Header.Format) =
317 return make_error<DWPError>(
"cannot parse compile unit length: " +
321 return make_error<DWPError>(
322 "compile unit exceeds .debug_info section range: " +
323 utostr(
Offset + Header.Length) +
" >= " + utostr(InfoData.
size()));
328 return make_error<DWPError>(
"cannot parse compile unit version: " +
332 if (Header.Version >= 5) {
335 MinHeaderLength = 16;
340 if (Header.Length < MinHeaderLength) {
341 return make_error<DWPError>(
"unit length is too small: expected at least " +
342 utostr(MinHeaderLength) +
" got " +
343 utostr(Header.Length) +
".");
345 if (Header.Version >= 5) {
350 if (Header.UnitType == dwarf::DW_UT_split_type) {
352 MinHeaderLength += 4;
353 if (Header.Length < MinHeaderLength)
354 return make_error<DWPError>(
"type unit is missing type offset");
364 Header.HeaderSize =
Offset;
374 if (CurStrSection.
empty() || CurStrOffsetSection.
empty())
382 while (
const char *S =
Data.getCStr(&LocalOffset)) {
383 OffsetRemapping[PrevOffset] =
384 Strings.getOffset(S, LocalOffset - PrevOffset);
385 PrevOffset = LocalOffset;
396 assert(HeaderSize <=
Size &&
"StrOffsetSection size is less than its header");
401 auto NewOffset = OffsetRemapping[OldOffset];
410 for (
const auto &
E : IndexEntries)
411 for (
size_t I = 0;
I != std::size(
E.second.Contributions); ++
I)
412 if (ContributionOffsets[
I])
414 ?
E.second.Contributions[
I].getOffset32()
415 :
E.second.Contributions[
I].getLength32()),
423 if (IndexEntries.
empty())
426 unsigned Columns = 0;
427 for (
auto &
C : ContributionOffsets)
434 for (
const auto &
P : IndexEntries) {
437 auto HP = ((S >> 32) & Mask) | 1;
439 assert(S != IndexEntries.
begin()[Buckets[
H] - 1].first &&
454 for (
const auto &
I : Buckets)
458 for (
const auto &
I : Buckets)
462 for (
size_t I = 0;
I != ContributionOffsets.
size(); ++
I)
463 if (ContributionOffsets[
I])
475 return make_error<DWPError>(
476 std::string(
"duplicate DWO ID (") + utohexstr(PrevE.first) +
") in " +
478 PrevE.second.DWOName) +
483 const StringMap<std::pair<MCSection *, DWARFSectionKind>> &KnownSections,
491 std::vector<StringRef> &CurTypesSection,
492 std::vector<StringRef> &CurInfoSection,
StringRef &AbbrevSection,
494 std::vector<std::pair<DWARFSectionKind, uint32_t>> &SectionLength) {
498 if (Section.isVirtual())
517 auto SectionPair = KnownSections.find(
Name);
518 if (SectionPair == KnownSections.end())
523 SectionLength.push_back(std::make_pair(
Kind, Contents.
size()));
526 if (
Kind == DW_SECT_ABBREV) {
527 AbbrevSection = Contents;
531 MCSection *OutSection = SectionPair->second.first;
532 if (OutSection == StrOffsetSection)
533 CurStrOffsetSection = Contents;
534 else if (OutSection == StrSection)
535 CurStrSection = Contents;
536 else if (OutSection == TypesSection)
537 CurTypesSection.push_back(Contents);
538 else if (OutSection == CUIndexSection)
539 CurCUIndexSection = Contents;
540 else if (OutSection == TUIndexSection)
541 CurTUIndexSection = Contents;
542 else if (OutSection == InfoSection)
543 CurInfoSection.push_back(Contents);
553 MCSection *
const StrSection = MCOFI.getDwarfStrDWOSection();
554 MCSection *
const StrOffsetSection = MCOFI.getDwarfStrOffDWOSection();
555 MCSection *
const TypesSection = MCOFI.getDwarfTypesDWOSection();
556 MCSection *
const CUIndexSection = MCOFI.getDwarfCUIndexSection();
557 MCSection *
const TUIndexSection = MCOFI.getDwarfTUIndexSection();
558 MCSection *
const InfoSection = MCOFI.getDwarfInfoDWOSection();
560 {
"debug_info.dwo", {InfoSection, DW_SECT_INFO}},
562 {
"debug_str_offsets.dwo", {StrOffsetSection, DW_SECT_STR_OFFSETS}},
565 {
"debug_line.dwo", {MCOFI.getDwarfLineDWOSection(), DW_SECT_LINE}},
566 {
"debug_macro.dwo", {MCOFI.getDwarfMacroDWOSection(), DW_SECT_MACRO}},
567 {
"debug_abbrev.dwo", {MCOFI.getDwarfAbbrevDWOSection(), DW_SECT_ABBREV}},
568 {
"debug_loclists.dwo",
569 {MCOFI.getDwarfLoclistsDWOSection(), DW_SECT_LOCLISTS}},
570 {
"debug_rnglists.dwo",
571 {MCOFI.getDwarfRnglistsDWOSection(), DW_SECT_RNGLISTS}},
578 uint32_t ContributionOffsets[8] = {};
587 std::deque<SmallString<32>> UncompressedSections;
589 for (
const auto &Input : Inputs) {
593 [&](std::unique_ptr<ECError> EC) ->
Error {
594 return createFileError(Input, Error(std::move(EC)));
598 auto &Obj = *ErrOrObj->getBinary();
605 std::vector<StringRef> CurTypesSection;
606 std::vector<StringRef> CurInfoSection;
614 std::vector<std::pair<DWARFSectionKind, uint32_t>> SectionLength;
616 for (
const auto &Section : Obj.sections())
618 KnownSections, StrSection, StrOffsetSection, TypesSection,
619 CUIndexSection, TUIndexSection, InfoSection, Section, Out,
620 UncompressedSections, ContributionOffsets, CurEntry,
621 CurStrSection, CurStrOffsetSection, CurTypesSection,
622 CurInfoSection, AbbrevSection, CurCUIndexSection,
623 CurTUIndexSection, SectionLength))
626 if (CurInfoSection.empty())
636 Version = Header.Version;
637 IndexVersion = Version < 5 ? 2 : 5;
638 }
else if (Version != Header.Version) {
639 return make_error<DWPError>(
"incompatible DWARF compile unit versions.");
643 CurStrOffsetSection, Header.Version);
645 for (
auto Pair : SectionLength) {
654 if (CurCUIndexSection.
empty()) {
655 bool FoundCUUnit =
false;
659 while (
Info.size() > UnitOffset) {
669 C.setOffset(InfoSectionOffset);
670 C.setLength(Header.Length + 4);
672 if (std::numeric_limits<uint32_t>::max() - InfoSectionOffset <
674 return make_error<DWPError>(
675 "debug information section offset is greater than 4GB");
677 UnitOffset +=
C.getLength32();
678 if (Header.Version < 5 ||
679 Header.UnitType == dwarf::DW_UT_split_compile) {
681 Header, AbbrevSection,
682 Info.substr(UnitOffset -
C.getLength32(),
C.getLength32()),
683 CurStrOffsetSection, CurStrSection);
687 const auto &
ID = *EID;
688 auto P = IndexEntries.
insert(std::make_pair(
ID.Signature, Entry));
691 P.first->second.Name =
ID.Name;
692 P.first->second.DWOName =
ID.DWOName;
695 }
else if (Header.UnitType == dwarf::DW_UT_split_type) {
696 auto P = TypeIndexEntries.
insert(
697 std::make_pair(*Header.Signature, Entry));
702 Info.substr(UnitOffset -
C.getLength32(),
C.getLength32()));
703 InfoSectionOffset +=
C.getLength32();
708 return make_error<DWPError>(
"no compile unit found in file: " + Input);
710 if (IndexVersion == 2) {
713 Out, TypeIndexEntries, TypesSection, CurTypesSection, CurEntry,
719 if (CurInfoSection.size() != 1)
720 return make_error<DWPError>(
"expected exactly one occurrence of a debug "
721 "info section in a .dwp file");
725 DataExtractor CUIndexData(CurCUIndexSection, Obj.isLittleEndian(), 0);
726 if (!CUIndex.
parse(CUIndexData))
727 return make_error<DWPError>(
"failed to parse cu_index");
729 return make_error<DWPError>(
"incompatible cu_index versions, found " +
731 " and expecting " + utostr(IndexVersion));
735 auto *
I =
E.getContributions();
738 auto P = IndexEntries.
insert(std::make_pair(
E.getSignature(), CurEntry));
754 const auto &
ID = *EID;
757 auto &NewEntry =
P.first->second;
758 NewEntry.Name =
ID.Name;
759 NewEntry.DWOName =
ID.DWOName;
760 NewEntry.DWPName = Input;
766 C.setOffset(
C.getOffset() +
I->getOffset());
767 C.setLength(
I->getLength());
771 auto &
C = NewEntry.Contributions[
Index];
773 C.setOffset(InfoSectionOffset);
774 InfoSectionOffset +=
C.getLength32();
777 if (!CurTUIndexSection.
empty()) {
783 TUSectionKind = DW_SECT_INFO;
784 OutSection = InfoSection;
785 TypeInputSection = DwpSingleInfoSection;
788 if (CurTypesSection.size() != 1)
789 return make_error<DWPError>(
790 "multiple type unit sections in .dwp file");
793 OutSection = TypesSection;
794 TypeInputSection = CurTypesSection.
front();
798 DataExtractor TUIndexData(CurTUIndexSection, Obj.isLittleEndian(), 0);
799 if (!TUIndex.
parse(TUIndexData))
800 return make_error<DWPError>(
"failed to parse tu_index");
802 return make_error<DWPError>(
"incompatible tu_index versions, found " +
804 " and expecting " + utostr(IndexVersion));
806 unsigned TypesContributionIndex =
809 TypeInputSection, CurEntry,
810 ContributionOffsets[TypesContributionIndex],
811 TypesContributionIndex);
819 ContributionOffsets[0] = 0;
821 writeIndex(Out, MCOFI.getDwarfTUIndexSection(), ContributionOffsets,
822 TypeIndexEntries, IndexVersion);
829 ContributionOffsets[0] = 1;
832 writeIndex(Out, MCOFI.getDwarfCUIndexSection(), ContributionOffsets,
833 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 handleCompressedSection(std::deque< SmallString< 32 > > &UncompressedSections, SectionRef Sec, StringRef Name, StringRef &Contents)
static std::string buildDWODescription(StringRef Name, StringRef DWPName, StringRef DWOName)
static void addAllTypesFromTypesSection(MCStreamer &Out, MapVector< uint64_t, UnitIndexEntry > &TypeIndexEntries, MCSection *OutputTypes, const std::vector< StringRef > &TypesSections, const UnitIndexEntry &CUEntry, uint32_t &TypesOffset)
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 void addAllTypesFromDWP(MCStreamer &Out, MapVector< uint64_t, UnitIndexEntry > &TypeIndexEntries, const DWARFUnitIndex &TUIndex, MCSection *OutputTypes, StringRef Types, const UnitIndexEntry &TUEntry, uint32_t &TypesOffset, unsigned TypesContributionIndex)
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.
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 write(MCStreamer &Out, ArrayRef< std::string > Inputs)
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.
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.