Index: include/llvm/DebugInfo/DWARF/DWARFContext.h =================================================================== --- include/llvm/DebugInfo/DWARF/DWARFContext.h +++ include/llvm/DebugInfo/DWARF/DWARFContext.h @@ -45,10 +45,124 @@ class MemoryBuffer; class raw_ostream; +// This is responsible for low level access to the object file. It +// knows how to find the required sections and compute relocated +// values. +// The default implementations are unreachable instead of pure virtual because +// not all clients need all sections. +class DWARFObj { +public: + virtual ~DWARFObj() {} + virtual StringRef getFileName() const { llvm_unreachable("unimplemented"); } + virtual bool isLittleEndian() const { llvm_unreachable("unimplemented"); } + virtual uint8_t getAddressSize() const { llvm_unreachable("unimplemented"); } + virtual const DWARFSection &getInfoSection() const { + llvm_unreachable("unimplemented"); + } + virtual void + forEachTypesSections(function_ref F) const { + llvm_unreachable("unimplemented"); + } + virtual StringRef getAbbrevSection() const { + llvm_unreachable("unimplemented"); + } + virtual const DWARFSection &getLocSection() const { + llvm_unreachable("unimplemented"); + } + virtual StringRef getARangeSection() const { + llvm_unreachable("unimplemented"); + } + virtual StringRef getDebugFrameSection() const { + llvm_unreachable("unimplemented"); + } + virtual StringRef getEHFrameSection() const { + llvm_unreachable("unimplemented"); + } + virtual const DWARFSection &getLineSection() const { + llvm_unreachable("unimplemented"); + } + virtual StringRef getStringSection() const { + llvm_unreachable("unimplemented"); + } + virtual const DWARFSection &getRangeSection() const { + llvm_unreachable("unimplemented"); + } + virtual StringRef getMacinfoSection() const { + llvm_unreachable("unimplemented"); + } + virtual StringRef getPubNamesSection() const { + llvm_unreachable("unimplemented"); + } + virtual StringRef getPubTypesSection() const { + llvm_unreachable("unimplemented"); + } + virtual StringRef getGnuPubNamesSection() const { + llvm_unreachable("unimplemented"); + } + virtual StringRef getGnuPubTypesSection() const { + llvm_unreachable("unimplemented"); + } + virtual const DWARFSection &getStringOffsetSection() const { + llvm_unreachable("unimplemented"); + } + virtual const DWARFSection &getInfoDWOSection() const { + llvm_unreachable("unimplemented"); + } + virtual void + forEachTypesDWOSections(function_ref F) const { + llvm_unreachable("unimplemented"); + } + virtual StringRef getAbbrevDWOSection() const { + llvm_unreachable("unimplemented"); + } + virtual const DWARFSection &getLineDWOSection() const { + llvm_unreachable("unimplemented"); + } + virtual const DWARFSection &getLocDWOSection() const { + llvm_unreachable("unimplemented"); + } + virtual StringRef getStringDWOSection() const { + llvm_unreachable("unimplemented"); + } + virtual const DWARFSection &getStringOffsetDWOSection() const { + llvm_unreachable("unimplemented"); + } + virtual const DWARFSection &getRangeDWOSection() const { + llvm_unreachable("unimplemented"); + } + virtual const DWARFSection &getAddrSection() const { + llvm_unreachable("unimplemented"); + } + virtual const DWARFSection &getAppleNamesSection() const { + llvm_unreachable("unimplemented"); + } + virtual const DWARFSection &getAppleTypesSection() const { + llvm_unreachable("unimplemented"); + } + virtual const DWARFSection &getAppleNamespacesSection() const { + llvm_unreachable("unimplemented"); + } + virtual const DWARFSection &getAppleObjCSection() const { + llvm_unreachable("unimplemented"); + } + virtual StringRef getCUIndexSection() const { + llvm_unreachable("unimplemented"); + } + virtual StringRef getGdbIndexSection() const { + llvm_unreachable("unimplemented"); + } + virtual StringRef getTUIndexSection() const { + llvm_unreachable("unimplemented"); + } + virtual Optional find(const DWARFSection &Sec, + uint64_t Pos) const { + llvm_unreachable("unimplemented"); + } +}; + /// DWARFContext /// This data structure is the top level entity that deals with dwarf debug -/// information parsing. The actual data is supplied through pure virtual -/// methods that a concrete implementation provides. +/// information parsing. The actual data is supplied through DWARFObj. class DWARFContext : public DIContext { DWARFUnitSection CUs; std::deque> TUs; @@ -95,11 +209,16 @@ /// and store them in DWOTUs. void parseDWOTypeUnits(); +protected: + const DWARFObj &Obj; + public: - DWARFContext() : DIContext(CK_DWARF) {} + DWARFContext(const DWARFObj &Obj) : DIContext(CK_DWARF), Obj(Obj) {} DWARFContext(DWARFContext &) = delete; DWARFContext &operator=(DWARFContext &) = delete; + const DWARFObj &getDWARFObj() const { return Obj; } + static bool classof(const DIContext *DICtx) { return DICtx->getKind() == CK_DWARF; } @@ -222,49 +341,63 @@ DIInliningInfo getInliningInfoForAddress(uint64_t Address, DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; - virtual StringRef getFileName() const = 0; - virtual bool isLittleEndian() const = 0; - virtual uint8_t getAddressSize() const = 0; - virtual const DWARFSection &getInfoSection() = 0; - virtual void forEachTypesSections(function_ref F) = 0; - virtual StringRef getAbbrevSection() = 0; - virtual const DWARFSection &getLocSection() = 0; - virtual StringRef getARangeSection() = 0; - virtual StringRef getDebugFrameSection() = 0; - virtual StringRef getEHFrameSection() = 0; - virtual const DWARFSection &getLineSection() = 0; - virtual StringRef getStringSection() = 0; - virtual const DWARFSection& getRangeSection() = 0; - virtual StringRef getMacinfoSection() = 0; - virtual StringRef getPubNamesSection() = 0; - virtual StringRef getPubTypesSection() = 0; - virtual StringRef getGnuPubNamesSection() = 0; - virtual StringRef getGnuPubTypesSection() = 0; + StringRef getFileName() const { return Obj.getFileName(); } + bool isLittleEndian() const { return Obj.isLittleEndian(); } + uint8_t getAddressSize() const { return Obj.getAddressSize(); } + const DWARFSection &getInfoSection() { return Obj.getInfoSection(); } + void forEachTypesSections(function_ref F) { + Obj.forEachTypesSections(F); + } + StringRef getAbbrevSection() { return Obj.getAbbrevSection(); } + const DWARFSection &getLocSection() { return Obj.getLocSection(); } + StringRef getARangeSection() { return Obj.getARangeSection(); } + StringRef getDebugFrameSection() { return Obj.getDebugFrameSection(); } + StringRef getEHFrameSection() { return Obj.getEHFrameSection(); } + const DWARFSection &getLineSection() { return Obj.getLineSection(); } + StringRef getStringSection() { return Obj.getStringSection(); } + const DWARFSection &getRangeSection() { return Obj.getRangeSection(); } + StringRef getMacinfoSection() { return Obj.getMacinfoSection(); } + StringRef getPubNamesSection() { return Obj.getPubNamesSection(); } + StringRef getPubTypesSection() { return Obj.getPubTypesSection(); } + StringRef getGnuPubNamesSection() { return Obj.getGnuPubNamesSection(); } + StringRef getGnuPubTypesSection() { return Obj.getGnuPubTypesSection(); } /// DWARF v5 /// @{ - virtual const DWARFSection &getStringOffsetSection() = 0; + const DWARFSection &getStringOffsetSection() { + return Obj.getStringOffsetSection(); + } /// @} // Sections for DWARF5 split dwarf proposal. - virtual const DWARFSection &getInfoDWOSection() = 0; - virtual void - forEachTypesDWOSections(function_ref F) = 0; - virtual StringRef getAbbrevDWOSection() = 0; - virtual const DWARFSection &getLineDWOSection() = 0; - virtual const DWARFSection &getLocDWOSection() = 0; - virtual StringRef getStringDWOSection() = 0; - virtual const DWARFSection &getStringOffsetDWOSection() = 0; - virtual const DWARFSection &getRangeDWOSection() = 0; - virtual const DWARFSection &getAddrSection() = 0; - virtual const DWARFSection& getAppleNamesSection() = 0; - virtual const DWARFSection& getAppleTypesSection() = 0; - virtual const DWARFSection& getAppleNamespacesSection() = 0; - virtual const DWARFSection& getAppleObjCSection() = 0; - virtual StringRef getCUIndexSection() = 0; - virtual StringRef getGdbIndexSection() = 0; - virtual StringRef getTUIndexSection() = 0; - + const DWARFSection &getInfoDWOSection() { return Obj.getInfoDWOSection(); } + void forEachTypesDWOSections(function_ref F) { + Obj.forEachTypesDWOSections(F); + } + StringRef getAbbrevDWOSection() { return Obj.getAbbrevDWOSection(); } + const DWARFSection &getLineDWOSection() { return Obj.getLineDWOSection(); } + const DWARFSection &getLocDWOSection() { return Obj.getLocDWOSection(); } + StringRef getStringDWOSection() { return Obj.getStringDWOSection(); } + const DWARFSection &getStringOffsetDWOSection() { + return Obj.getStringOffsetDWOSection(); + } + const DWARFSection &getRangeDWOSection() { return Obj.getRangeDWOSection(); } + const DWARFSection &getAddrSection() { return Obj.getAddrSection(); } + const DWARFSection &getAppleNamesSection() { + return Obj.getAppleNamesSection(); + } + const DWARFSection &getAppleTypesSection() { + return Obj.getAppleTypesSection(); + } + const DWARFSection &getAppleNamespacesSection() { + return Obj.getAppleNamespacesSection(); + } + const DWARFSection &getAppleObjCSection() { + return Obj.getAppleObjCSection(); + } + StringRef getCUIndexSection() { return Obj.getCUIndexSection(); } + StringRef getGdbIndexSection() { return Obj.getGdbIndexSection(); } + StringRef getTUIndexSection() { return Obj.getTUIndexSection(); } static bool isSupportedVersion(unsigned version) { return version == 2 || version == 3 || version == 4 || version == 5; } @@ -289,62 +422,7 @@ /// DWARFContext. It assumes all content is available in memory and stores /// pointers to it. class DWARFContextInMemory : public DWARFContext { - virtual void anchor(); - - using TypeSectionMap = MapVector>; - - StringRef FileName; - bool IsLittleEndian; - uint8_t AddressSize; - DWARFSection InfoSection; - TypeSectionMap TypesSections; - StringRef AbbrevSection; - DWARFSection LocSection; - StringRef ARangeSection; - StringRef DebugFrameSection; - StringRef EHFrameSection; - DWARFSection LineSection; - StringRef StringSection; - DWARFSection RangeSection; - StringRef MacinfoSection; - StringRef PubNamesSection; - StringRef PubTypesSection; - StringRef GnuPubNamesSection; - StringRef GnuPubTypesSection; - - /// DWARF v5 - /// @{ - DWARFSection StringOffsetSection; - /// @} - - // Sections for DWARF5 split dwarf proposal. - DWARFSection InfoDWOSection; - TypeSectionMap TypesDWOSections; - StringRef AbbrevDWOSection; - DWARFSection LineDWOSection; - DWARFSection LocDWOSection; - StringRef StringDWOSection; - DWARFSection StringOffsetDWOSection; - DWARFSection RangeDWOSection; - DWARFSection AddrSection; - DWARFSection AppleNamesSection; - DWARFSection AppleTypesSection; - DWARFSection AppleNamespacesSection; - DWARFSection AppleObjCSection; - StringRef CUIndexSection; - StringRef GdbIndexSection; - StringRef TUIndexSection; - - SmallVector, 4> UncompressedSections; - - DWARFSection *mapNameToDWARFSection(StringRef Name); - StringRef *mapSectionToMember(StringRef Name); - - /// If Sec is compressed section, decompresses and updates its contents - /// provided by Data. Otherwise leaves it unchanged. - Error maybeDecompress(const object::SectionRef &Sec, StringRef Name, - StringRef &Data); + std::unique_ptr DObj; /// Function used to handle default error reporting policy. Prints a error /// message and returns Continue, so DWARF context ignores the error. @@ -359,61 +437,6 @@ uint8_t AddrSize, bool isLittleEndian = sys::IsLittleEndianHost); - StringRef getFileName() const override { return FileName; } - bool isLittleEndian() const override { return IsLittleEndian; } - uint8_t getAddressSize() const override { return AddressSize; } - const DWARFSection &getInfoSection() override { return InfoSection; } - void forEachTypesSections(function_ref F) override { - for (auto &P : TypesSections) - F(P.second); - } - StringRef getAbbrevSection() override { return AbbrevSection; } - const DWARFSection &getLocSection() override { return LocSection; } - StringRef getARangeSection() override { return ARangeSection; } - StringRef getDebugFrameSection() override { return DebugFrameSection; } - StringRef getEHFrameSection() override { return EHFrameSection; } - const DWARFSection &getLineSection() override { return LineSection; } - StringRef getStringSection() override { return StringSection; } - const DWARFSection &getRangeSection() override { return RangeSection; } - StringRef getMacinfoSection() override { return MacinfoSection; } - StringRef getPubNamesSection() override { return PubNamesSection; } - StringRef getPubTypesSection() override { return PubTypesSection; } - StringRef getGnuPubNamesSection() override { return GnuPubNamesSection; } - StringRef getGnuPubTypesSection() override { return GnuPubTypesSection; } - const DWARFSection& getAppleNamesSection() override { return AppleNamesSection; } - const DWARFSection& getAppleTypesSection() override { return AppleTypesSection; } - const DWARFSection& getAppleNamespacesSection() override { return AppleNamespacesSection; } - const DWARFSection& getAppleObjCSection() override { return AppleObjCSection; } - - // DWARF v5 - const DWARFSection &getStringOffsetSection() override { - return StringOffsetSection; - } - - // Sections for DWARF5 split dwarf proposal. - const DWARFSection &getInfoDWOSection() override { return InfoDWOSection; } - - void forEachTypesDWOSections(function_ref F) override { - for (auto &P : TypesDWOSections) - F(P.second); - } - - StringRef getAbbrevDWOSection() override { return AbbrevDWOSection; } - const DWARFSection &getLineDWOSection() override { return LineDWOSection; } - const DWARFSection &getLocDWOSection() override { return LocDWOSection; } - StringRef getStringDWOSection() override { return StringDWOSection; } - - const DWARFSection &getStringOffsetDWOSection() override { - return StringOffsetDWOSection; - } - - const DWARFSection &getRangeDWOSection() override { return RangeDWOSection; } - - const DWARFSection &getAddrSection() override { return AddrSection; } - - StringRef getCUIndexSection() override { return CUIndexSection; } - StringRef getGdbIndexSection() override { return GdbIndexSection; } - StringRef getTUIndexSection() override { return TUIndexSection; } }; } // end namespace llvm Index: include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h =================================================================== --- include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h +++ include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h @@ -14,18 +14,21 @@ #include "llvm/Support/DataExtractor.h" namespace llvm { +class DWARFObj; /// A DataExtractor (typically for an in-memory copy of an object-file section) /// plus a relocation map for that section, if there is one. class DWARFDataExtractor : public DataExtractor { - const RelocAddrMap *RelocMap = nullptr; + const DWARFObj *Obj = nullptr; + const DWARFSection *Section = nullptr; + public: /// Constructor for the normal case of extracting data from a DWARF section. /// The DWARFSection's lifetime must be at least as long as the extractor's. - DWARFDataExtractor(const DWARFSection &Section, bool IsLittleEndian, - uint8_t AddressSize) - : DataExtractor(Section.Data, IsLittleEndian, AddressSize), - RelocMap(&Section.Relocs) {} + DWARFDataExtractor(const DWARFObj &Obj, const DWARFSection &Section, + bool IsLittleEndian, uint8_t AddressSize) + : DataExtractor(Section.Data, IsLittleEndian, AddressSize), Obj(&Obj), + Section(&Section) {} /// Constructor for cases when there are no relocations. DWARFDataExtractor(StringRef Data, bool IsLittleEndian, uint8_t AddressSize) Index: include/llvm/DebugInfo/DWARF/DWARFSection.h =================================================================== --- include/llvm/DebugInfo/DWARF/DWARFSection.h +++ include/llvm/DebugInfo/DWARF/DWARFSection.h @@ -17,6 +17,9 @@ struct DWARFSection { StringRef Data; +}; + +struct DWARFSectionMap final : public DWARFSection { RelocAddrMap Relocs; }; Index: include/llvm/DebugInfo/DWARF/DWARFUnit.h =================================================================== --- include/llvm/DebugInfo/DWARF/DWARFUnit.h +++ include/llvm/DebugInfo/DWARF/DWARFUnit.h @@ -197,19 +197,12 @@ bool getAddrOffsetSectionItem(uint32_t Index, uint64_t &Result) const; bool getStringOffsetSectionItem(uint32_t Index, uint64_t &Result) const; - DWARFDataExtractor getDebugInfoExtractor() const { - return DWARFDataExtractor(InfoSection, isLittleEndian, - getAddressByteSize()); - } + DWARFDataExtractor getDebugInfoExtractor() const; DataExtractor getStringExtractor() const { return DataExtractor(StringSection, false, 0); } - const RelocAddrMap *getRelocMap() const { return &InfoSection.Relocs; } - const RelocAddrMap &getStringOffsetsRelocMap() const { - return StringOffsetSection.Relocs; - } bool extract(DataExtractor debug_info, uint32_t* offset_ptr); Index: lib/DebugInfo/DWARF/DWARFContext.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFContext.cpp +++ lib/DebugInfo/DWARF/DWARFContext.cpp @@ -60,9 +60,9 @@ using FunctionNameKind = DILineInfoSpecifier::FunctionNameKind; static void dumpAccelSection(raw_ostream &OS, StringRef Name, - const DWARFSection& Section, StringRef StringSection, - bool LittleEndian) { - DWARFDataExtractor AccelSection(Section, LittleEndian, 0); + const DWARFObj &Obj, const DWARFSection &Section, + StringRef StringSection, bool LittleEndian) { + DWARFDataExtractor AccelSection(Obj, Section, LittleEndian, 0); DataExtractor StrData(StringSection, LittleEndian, 0); OS << "\n." << Name << " contents:\n"; DWARFAcceleratorTable Accel(AccelSection, StrData); @@ -73,9 +73,10 @@ static void dumpDWARFv5StringOffsetsSection(raw_ostream &OS, StringRef SectionName, + const DWARFObj &Obj, const DWARFSection &StringOffsetsSection, StringRef StringSection, bool LittleEndian) { - DWARFDataExtractor StrOffsetExt(StringOffsetsSection, LittleEndian, 0); + DWARFDataExtractor StrOffsetExt(Obj, StringOffsetsSection, LittleEndian, 0); uint32_t Offset = 0; uint64_t SectionSize = StringOffsetsSection.Data.size(); @@ -153,6 +154,7 @@ // monolithic series of string offsets, as generated by the pre-DWARF v5 // implementation of split DWARF. static void dumpStringOffsetsSection(raw_ostream &OS, StringRef SectionName, + const DWARFObj &Obj, const DWARFSection &StringOffsetsSection, StringRef StringSection, bool LittleEndian, unsigned MaxVersion) { @@ -163,7 +165,7 @@ // we assume that the section is formatted like a DWARF v5 string offsets // section. if (MaxVersion >= 5) - dumpDWARFv5StringOffsetsSection(OS, SectionName, StringOffsetsSection, + dumpDWARFv5StringOffsetsSection(OS, SectionName, Obj, StringOffsetsSection, StringSection, LittleEndian); else { DataExtractor strOffsetExt(StringOffsetsSection.Data, LittleEndian, 0); @@ -274,7 +276,7 @@ if (!CUDIE) continue; if (auto StmtOffset = toSectionOffset(CUDIE.find(DW_AT_stmt_list))) { - DWARFDataExtractor lineData(getLineSection(), isLittleEndian(), + DWARFDataExtractor lineData(Obj, getLineSection(), isLittleEndian(), savedAddressByteSize); DWARFDebugLine::LineTable LineTable; uint32_t Offset = *StmtOffset; @@ -297,7 +299,7 @@ if (DumpType == DIDT_All || DumpType == DIDT_LineDwo) { OS << "\n.debug_line.dwo contents:\n"; unsigned stmtOffset = 0; - DWARFDataExtractor lineData(getLineDWOSection(), isLittleEndian(), + DWARFDataExtractor lineData(Obj, getLineDWOSection(), isLittleEndian(), savedAddressByteSize); DWARFDebugLine::LineTable LineTable; while (LineTable.Prologue.parse(lineData, &stmtOffset)) { @@ -335,7 +337,7 @@ // sizes, but for simplicity we just use the address byte size of the last // compile unit (there is no easy and fast way to associate address range // list and the compile unit it describes). - DWARFDataExtractor rangesData(getRangeSection(), isLittleEndian(), + DWARFDataExtractor rangesData(Obj, getRangeSection(), isLittleEndian(), savedAddressByteSize); offset = 0; DWARFDebugRangeList rangeList; @@ -362,12 +364,12 @@ .dump("debug_gnu_pubtypes", OS); if (DumpType == DIDT_All || DumpType == DIDT_StrOffsets) - dumpStringOffsetsSection(OS, "debug_str_offsets", getStringOffsetSection(), - getStringSection(), isLittleEndian(), - getMaxVersion()); + dumpStringOffsetsSection(OS, "debug_str_offsets", Obj, + getStringOffsetSection(), getStringSection(), + isLittleEndian(), getMaxVersion()); if (DumpType == DIDT_All || DumpType == DIDT_StrOffsetsDwo) { - dumpStringOffsetsSection(OS, "debug_str_offsets.dwo", + dumpStringOffsetsSection(OS, "debug_str_offsets.dwo", Obj, getStringOffsetDWOSection(), getStringDWOSection(), isLittleEndian(), getMaxVersion()); } @@ -379,19 +381,19 @@ } if (DumpType == DIDT_All || DumpType == DIDT_AppleNames) - dumpAccelSection(OS, "apple_names", getAppleNamesSection(), + dumpAccelSection(OS, "apple_names", Obj, getAppleNamesSection(), getStringSection(), isLittleEndian()); if (DumpType == DIDT_All || DumpType == DIDT_AppleTypes) - dumpAccelSection(OS, "apple_types", getAppleTypesSection(), + dumpAccelSection(OS, "apple_types", Obj, getAppleTypesSection(), getStringSection(), isLittleEndian()); if (DumpType == DIDT_All || DumpType == DIDT_AppleNamespaces) - dumpAccelSection(OS, "apple_namespaces", getAppleNamespacesSection(), + dumpAccelSection(OS, "apple_namespaces", Obj, getAppleNamespacesSection(), getStringSection(), isLittleEndian()); if (DumpType == DIDT_All || DumpType == DIDT_AppleObjC) - dumpAccelSection(OS, "apple_objc", getAppleObjCSection(), + dumpAccelSection(OS, "apple_objc", Obj, getAppleObjCSection(), getStringSection(), isLittleEndian()); } @@ -489,7 +491,7 @@ Loc.reset(new DWARFDebugLoc); // assume all compile units have the same address byte size if (getNumCompileUnits()) { - DWARFDataExtractor LocData(getLocSection(), isLittleEndian(), + DWARFDataExtractor LocData(Obj, getLocSection(), isLittleEndian(), getCompileUnitAtIndex(0)->getAddressByteSize()); Loc->parse(LocData); } @@ -579,7 +581,7 @@ return nullptr; // We have to parse it first. - DWARFDataExtractor lineData(U->getLineSection(), isLittleEndian(), + DWARFDataExtractor lineData(Obj, U->getLineSection(), isLittleEndian(), U->getAddressByteSize()); return Line->getOrParseLineTable(lineData, stmtOffset); } @@ -906,208 +908,355 @@ return MachObj->isRelocationScattered(RelocInfo); } -Error DWARFContextInMemory::maybeDecompress(const SectionRef &Sec, - StringRef Name, StringRef &Data) { - if (!Decompressor::isCompressed(Sec)) - return Error::success(); +ErrorPolicy DWARFContextInMemory::defaultErrorHandler(Error E) { + errs() << "error: " + toString(std::move(E)) << '\n'; + return ErrorPolicy::Continue; +} - Expected Decompressor = - Decompressor::create(Name, Data, IsLittleEndian, AddressSize == 8); - if (!Decompressor) - return Decompressor.takeError(); +class DWARFObjInMemory final : public DWARFObj { + bool IsLittleEndian; + uint8_t AddressSize; + StringRef FileName; + + using TypeSectionMap = MapVector>; + + TypeSectionMap TypesSections; + TypeSectionMap TypesDWOSections; + + DWARFSectionMap InfoSection; + DWARFSectionMap LocSection; + DWARFSectionMap LineSection; + DWARFSectionMap RangeSection; + DWARFSectionMap StringOffsetSection; + DWARFSectionMap InfoDWOSection; + DWARFSectionMap LineDWOSection; + DWARFSectionMap LocDWOSection; + DWARFSectionMap StringOffsetDWOSection; + DWARFSectionMap RangeDWOSection; + DWARFSectionMap AddrSection; + DWARFSectionMap AppleNamesSection; + DWARFSectionMap AppleTypesSection; + DWARFSectionMap AppleNamespacesSection; + DWARFSectionMap AppleObjCSection; + + DWARFSectionMap *mapNameToDWARFSection(StringRef Name) { + return StringSwitch(Name) + .Case("debug_info", &InfoSection) + .Case("debug_loc", &LocSection) + .Case("debug_line", &LineSection) + .Case("debug_str_offsets", &StringOffsetSection) + .Case("debug_ranges", &RangeSection) + .Case("debug_info.dwo", &InfoDWOSection) + .Case("debug_loc.dwo", &LocDWOSection) + .Case("debug_line.dwo", &LineDWOSection) + .Case("debug_str_offsets.dwo", &StringOffsetDWOSection) + .Case("debug_addr", &AddrSection) + .Case("apple_names", &AppleNamesSection) + .Case("apple_types", &AppleTypesSection) + .Case("apple_namespaces", &AppleNamespacesSection) + .Case("apple_namespac", &AppleNamespacesSection) + .Case("apple_objc", &AppleObjCSection) + .Default(nullptr); + } - SmallString<32> Out; - if (auto Err = Decompressor->resizeAndDecompress(Out)) - return Err; + StringRef AbbrevSection; + StringRef ARangeSection; + StringRef DebugFrameSection; + StringRef EHFrameSection; + StringRef StringSection; + StringRef MacinfoSection; + StringRef PubNamesSection; + StringRef PubTypesSection; + StringRef GnuPubNamesSection; + StringRef AbbrevDWOSection; + StringRef StringDWOSection; + StringRef GnuPubTypesSection; + StringRef CUIndexSection; + StringRef GdbIndexSection; + StringRef TUIndexSection; + + SmallVector, 4> UncompressedSections; + + StringRef *mapSectionToMember(StringRef Name) { + if (DWARFSection *Sec = mapNameToDWARFSection(Name)) + return &Sec->Data; + return StringSwitch(Name) + .Case("debug_abbrev", &AbbrevSection) + .Case("debug_aranges", &ARangeSection) + .Case("debug_frame", &DebugFrameSection) + .Case("eh_frame", &EHFrameSection) + .Case("debug_str", &StringSection) + .Case("debug_macinfo", &MacinfoSection) + .Case("debug_pubnames", &PubNamesSection) + .Case("debug_pubtypes", &PubTypesSection) + .Case("debug_gnu_pubnames", &GnuPubNamesSection) + .Case("debug_gnu_pubtypes", &GnuPubTypesSection) + .Case("debug_abbrev.dwo", &AbbrevDWOSection) + .Case("debug_str.dwo", &StringDWOSection) + .Case("debug_cu_index", &CUIndexSection) + .Case("debug_tu_index", &TUIndexSection) + .Case("gdb_index", &GdbIndexSection) + // Any more debug info sections go here. + .Default(nullptr); + } - UncompressedSections.emplace_back(std::move(Out)); - Data = UncompressedSections.back(); + /// If Sec is compressed section, decompresses and updates its contents + /// provided by Data. Otherwise leaves it unchanged. + Error maybeDecompress(const object::SectionRef &Sec, StringRef Name, + StringRef &Data) { + if (!Decompressor::isCompressed(Sec)) + return Error::success(); - return Error::success(); -} + Expected Decompressor = + Decompressor::create(Name, Data, IsLittleEndian, AddressSize == 8); + if (!Decompressor) + return Decompressor.takeError(); -ErrorPolicy DWARFContextInMemory::defaultErrorHandler(Error E) { - errs() << "error: " + toString(std::move(E)) << '\n'; - return ErrorPolicy::Continue; -} + SmallString<32> Out; + if (auto Err = Decompressor->resizeAndDecompress(Out)) + return Err; -DWARFContextInMemory::DWARFContextInMemory( - const object::ObjectFile &Obj, const LoadedObjectInfo *L, - function_ref HandleError) - : FileName(Obj.getFileName()), IsLittleEndian(Obj.isLittleEndian()), - AddressSize(Obj.getBytesInAddress()) { - for (const SectionRef &Section : Obj.sections()) { - StringRef Name; - Section.getName(Name); - // Skip BSS and Virtual sections, they aren't interesting. - if (Section.isBSS() || Section.isVirtual()) - continue; - - StringRef Data; - section_iterator RelocatedSection = Section.getRelocatedSection(); - // Try to obtain an already relocated version of this section. - // Else use the unrelocated section from the object file. We'll have to - // apply relocations ourselves later. - if (!L || !L->getLoadedSectionContents(*RelocatedSection, Data)) - Section.getContents(Data); - - if (auto Err = maybeDecompress(Section, Name, Data)) { - ErrorPolicy EP = HandleError( - createError("failed to decompress '" + Name + "', ", std::move(Err))); - if (EP == ErrorPolicy::Halt) - return; - continue; - } + UncompressedSections.emplace_back(std::move(Out)); + Data = UncompressedSections.back(); + + return Error::success(); + } - // Compressed sections names in GNU style starts from ".z", - // at this point section is decompressed and we drop compression prefix. - Name = Name.substr( - Name.find_first_not_of("._z")); // Skip ".", "z" and "_" prefixes. +public: + DWARFObjInMemory(const StringMap> &Sections, + uint8_t AddrSize, bool IsLittleEndian) + : IsLittleEndian(IsLittleEndian) { + for (const auto &SecIt : Sections) { + if (StringRef *SectionData = mapSectionToMember(SecIt.first())) + *SectionData = SecIt.second->getBuffer(); + } + } + DWARFObjInMemory(const object::ObjectFile &Obj, const LoadedObjectInfo *L, + function_ref HandleError) + : IsLittleEndian(Obj.isLittleEndian()), + AddressSize(Obj.getBytesInAddress()), FileName(Obj.getFileName()) { + + for (const SectionRef &Section : Obj.sections()) { + StringRef Name; + Section.getName(Name); + // Skip BSS and Virtual sections, they aren't interesting. + if (Section.isBSS() || Section.isVirtual()) + continue; - // Map platform specific debug section names to DWARF standard section - // names. - Name = Obj.mapDebugSectionName(Name); + StringRef Data; + section_iterator RelocatedSection = Section.getRelocatedSection(); + // Try to obtain an already relocated version of this section. + // Else use the unrelocated section from the object file. We'll have to + // apply relocations ourselves later. + if (!L || !L->getLoadedSectionContents(*RelocatedSection, Data)) + Section.getContents(Data); + + if (auto Err = maybeDecompress(Section, Name, Data)) { + ErrorPolicy EP = HandleError(createError( + "failed to decompress '" + Name + "', ", std::move(Err))); + if (EP == ErrorPolicy::Halt) + return; + continue; + } - if (StringRef *SectionData = mapSectionToMember(Name)) { - *SectionData = Data; - if (Name == "debug_ranges") { - // FIXME: Use the other dwo range section when we emit it. - RangeDWOSection.Data = Data; + // Compressed sections names in GNU style starts from ".z", + // at this point section is decompressed and we drop compression prefix. + Name = Name.substr( + Name.find_first_not_of("._z")); // Skip ".", "z" and "_" prefixes. + + // Map platform specific debug section names to DWARF standard section + // names. + Name = Obj.mapDebugSectionName(Name); + + if (StringRef *SectionData = mapSectionToMember(Name)) { + *SectionData = Data; + if (Name == "debug_ranges") { + // FIXME: Use the other dwo range section when we emit it. + RangeDWOSection.Data = Data; + } + } else if (Name == "debug_types") { + // Find debug_types data by section rather than name as there are + // multiple, comdat grouped, debug_types sections. + TypesSections[Section].Data = Data; + } else if (Name == "debug_types.dwo") { + TypesDWOSections[Section].Data = Data; } - } else if (Name == "debug_types") { - // Find debug_types data by section rather than name as there are - // multiple, comdat grouped, debug_types sections. - TypesSections[Section].Data = Data; - } else if (Name == "debug_types.dwo") { - TypesDWOSections[Section].Data = Data; - } - if (RelocatedSection == Obj.section_end()) - continue; - - StringRef RelSecName; - StringRef RelSecData; - RelocatedSection->getName(RelSecName); - - // If the section we're relocating was relocated already by the JIT, - // then we used the relocated version above, so we do not need to process - // relocations for it now. - if (L && L->getLoadedSectionContents(*RelocatedSection, RelSecData)) - continue; - - // In Mach-o files, the relocations do not need to be applied if - // there is no load offset to apply. The value read at the - // relocation point already factors in the section address - // (actually applying the relocations will produce wrong results - // as the section address will be added twice). - if (!L && isa(&Obj)) - continue; - - RelSecName = RelSecName.substr( - RelSecName.find_first_not_of("._z")); // Skip . and _ prefixes. - - // TODO: Add support for relocations in other sections as needed. - // Record relocations for the debug_info and debug_line sections. - DWARFSection *Sec = mapNameToDWARFSection(RelSecName); - RelocAddrMap *Map = Sec ? &Sec->Relocs : nullptr; - if (!Map) { - // Find debug_types relocs by section rather than name as there are - // multiple, comdat grouped, debug_types sections. - if (RelSecName == "debug_types") - Map = &TypesSections[*RelocatedSection].Relocs; - else if (RelSecName == "debug_types.dwo") - Map = &TypesDWOSections[*RelocatedSection].Relocs; - else + if (RelocatedSection == Obj.section_end()) continue; - } - if (Section.relocation_begin() == Section.relocation_end()) - continue; + StringRef RelSecName; + StringRef RelSecData; + RelocatedSection->getName(RelSecName); - // Symbol to [address, section index] cache mapping. - std::map AddrCache; - for (const RelocationRef &Reloc : Section.relocations()) { - // FIXME: it's not clear how to correctly handle scattered - // relocations. - if (isRelocScattered(Obj, Reloc)) + // If the section we're relocating was relocated already by the JIT, + // then we used the relocated version above, so we do not need to process + // relocations for it now. + if (L && L->getLoadedSectionContents(*RelocatedSection, RelSecData)) continue; - Expected SymInfoOrErr = getSymbolInfo(Obj, Reloc, L, AddrCache); - if (!SymInfoOrErr) { - if (HandleError(SymInfoOrErr.takeError()) == ErrorPolicy::Halt) - return; + // In Mach-o files, the relocations do not need to be applied if + // there is no load offset to apply. The value read at the + // relocation point already factors in the section address + // (actually applying the relocations will produce wrong results + // as the section address will be added twice). + if (!L && isa(&Obj)) continue; + + RelSecName = RelSecName.substr( + RelSecName.find_first_not_of("._z")); // Skip . and _ prefixes. + + // TODO: Add support for relocations in other sections as needed. + // Record relocations for the debug_info and debug_line sections. + DWARFSectionMap *Sec = mapNameToDWARFSection(RelSecName); + RelocAddrMap *Map = Sec ? &Sec->Relocs : nullptr; + if (!Map) { + // Find debug_types relocs by section rather than name as there are + // multiple, comdat grouped, debug_types sections. + if (RelSecName == "debug_types") + Map = + &static_cast(TypesSections[*RelocatedSection]) + .Relocs; + else if (RelSecName == "debug_types.dwo") + Map = &static_cast( + TypesDWOSections[*RelocatedSection]) + .Relocs; + else + continue; } - object::RelocVisitor V(Obj); - uint64_t Val = V.visit(Reloc.getType(), Reloc, SymInfoOrErr->Address); - if (V.error()) { - SmallString<32> Type; - Reloc.getTypeName(Type); - ErrorPolicy EP = HandleError( - createError("failed to compute relocation: " + Type + ", ", - errorCodeToError(object_error::parse_failed))); - if (EP == ErrorPolicy::Halt) - return; + if (Section.relocation_begin() == Section.relocation_end()) continue; + + // Symbol to [address, section index] cache mapping. + std::map AddrCache; + for (const RelocationRef &Reloc : Section.relocations()) { + // FIXME: it's not clear how to correctly handle scattered + // relocations. + if (isRelocScattered(Obj, Reloc)) + continue; + + Expected SymInfoOrErr = + getSymbolInfo(Obj, Reloc, L, AddrCache); + if (!SymInfoOrErr) { + if (HandleError(SymInfoOrErr.takeError()) == ErrorPolicy::Halt) + return; + continue; + } + + object::RelocVisitor V(Obj); + uint64_t Val = V.visit(Reloc.getType(), Reloc, SymInfoOrErr->Address); + if (V.error()) { + SmallString<32> Type; + Reloc.getTypeName(Type); + ErrorPolicy EP = HandleError( + createError("failed to compute relocation: " + Type + ", ", + errorCodeToError(object_error::parse_failed))); + if (EP == ErrorPolicy::Halt) + return; + continue; + } + RelocAddrEntry Rel = {SymInfoOrErr->SectionIndex, Val}; + Map->insert({Reloc.getOffset(), Rel}); } - RelocAddrEntry Rel = {SymInfoOrErr->SectionIndex, Val}; - Map->insert({Reloc.getOffset(), Rel}); } } -} -DWARFContextInMemory::DWARFContextInMemory( - const StringMap> &Sections, uint8_t AddrSize, - bool isLittleEndian) - : IsLittleEndian(isLittleEndian), AddressSize(AddrSize) { - for (const auto &SecIt : Sections) { - if (StringRef *SectionData = mapSectionToMember(SecIt.first())) - *SectionData = SecIt.second->getBuffer(); + Optional find(const DWARFSection &S, + uint64_t Pos) const override { + auto &Sec = static_cast(S); + RelocAddrMap::const_iterator AI = Sec.Relocs.find(Pos); + if (AI == Sec.Relocs.end()) + return None; + return AI->second; } -} -DWARFSection *DWARFContextInMemory::mapNameToDWARFSection(StringRef Name) { - return StringSwitch(Name) - .Case("debug_info", &InfoSection) - .Case("debug_loc", &LocSection) - .Case("debug_line", &LineSection) - .Case("debug_str_offsets", &StringOffsetSection) - .Case("debug_ranges", &RangeSection) - .Case("debug_info.dwo", &InfoDWOSection) - .Case("debug_loc.dwo", &LocDWOSection) - .Case("debug_line.dwo", &LineDWOSection) - .Case("debug_str_offsets.dwo", &StringOffsetDWOSection) - .Case("debug_addr", &AddrSection) - .Case("apple_names", &AppleNamesSection) - .Case("apple_types", &AppleTypesSection) - .Case("apple_namespaces", &AppleNamespacesSection) - .Case("apple_namespac", &AppleNamespacesSection) - .Case("apple_objc", &AppleObjCSection) - .Default(nullptr); -} + bool isLittleEndian() const override { return IsLittleEndian; } + StringRef getAbbrevDWOSection() const override { return AbbrevDWOSection; } + const DWARFSection &getLineDWOSection() const override { + return LineDWOSection; + } + const DWARFSection &getLocDWOSection() const override { + return LocDWOSection; + } + StringRef getStringDWOSection() const override { return StringDWOSection; } + const DWARFSection &getStringOffsetDWOSection() const override { + return StringOffsetDWOSection; + } + const DWARFSection &getRangeDWOSection() const override { + return RangeDWOSection; + } + const DWARFSection &getAddrSection() const override { return AddrSection; } + StringRef getCUIndexSection() const override { return CUIndexSection; } + StringRef getGdbIndexSection() const override { return GdbIndexSection; } + StringRef getTUIndexSection() const override { return TUIndexSection; } + + // DWARF v5 + const DWARFSection &getStringOffsetSection() const override { + return StringOffsetSection; + } + + // Sections for DWARF5 split dwarf proposal. + const DWARFSection &getInfoDWOSection() const override { + return InfoDWOSection; + } + void forEachTypesDWOSections( + function_ref F) const override { + for (auto &P : TypesDWOSections) + F(P.second); + } -StringRef *DWARFContextInMemory::mapSectionToMember(StringRef Name) { - if (DWARFSection *Sec = mapNameToDWARFSection(Name)) - return &Sec->Data; - return StringSwitch(Name) - .Case("debug_abbrev", &AbbrevSection) - .Case("debug_aranges", &ARangeSection) - .Case("debug_frame", &DebugFrameSection) - .Case("eh_frame", &EHFrameSection) - .Case("debug_str", &StringSection) - .Case("debug_macinfo", &MacinfoSection) - .Case("debug_pubnames", &PubNamesSection) - .Case("debug_pubtypes", &PubTypesSection) - .Case("debug_gnu_pubnames", &GnuPubNamesSection) - .Case("debug_gnu_pubtypes", &GnuPubTypesSection) - .Case("debug_abbrev.dwo", &AbbrevDWOSection) - .Case("debug_str.dwo", &StringDWOSection) - .Case("debug_cu_index", &CUIndexSection) - .Case("debug_tu_index", &TUIndexSection) - .Case("gdb_index", &GdbIndexSection) - // Any more debug info sections go here. - .Default(nullptr); + StringRef getAbbrevSection() const override { return AbbrevSection; } + const DWARFSection &getLocSection() const override { return LocSection; } + StringRef getARangeSection() const override { return ARangeSection; } + StringRef getDebugFrameSection() const override { return DebugFrameSection; } + StringRef getEHFrameSection() const override { return EHFrameSection; } + const DWARFSection &getLineSection() const override { return LineSection; } + StringRef getStringSection() const override { return StringSection; } + const DWARFSection &getRangeSection() const override { return RangeSection; } + StringRef getMacinfoSection() const override { return MacinfoSection; } + StringRef getPubNamesSection() const override { return PubNamesSection; } + StringRef getPubTypesSection() const override { return PubTypesSection; } + StringRef getGnuPubNamesSection() const override { + return GnuPubNamesSection; + } + StringRef getGnuPubTypesSection() const override { + return GnuPubTypesSection; + } + const DWARFSection &getAppleNamesSection() const override { + return AppleNamesSection; + } + const DWARFSection &getAppleTypesSection() const override { + return AppleTypesSection; + } + const DWARFSection &getAppleNamespacesSection() const override { + return AppleNamespacesSection; + } + const DWARFSection &getAppleObjCSection() const override { + return AppleObjCSection; + } + + StringRef getFileName() const override { return FileName; } + uint8_t getAddressSize() const override { return AddressSize; } + const DWARFSection &getInfoSection() const override { return InfoSection; } + void forEachTypesSections( + function_ref F) const override { + for (auto &P : TypesSections) + F(P.second); + } +}; + +DWARFContextInMemory::DWARFContextInMemory( + const object::ObjectFile &Obj, const LoadedObjectInfo *L, + function_ref HandleError) + : DWARFContext(*new DWARFObjInMemory(Obj, L, HandleError)) { + DObj.reset(&this->Obj); } -void DWARFContextInMemory::anchor() {} +DWARFContextInMemory::DWARFContextInMemory( + const StringMap> &Sections, uint8_t AddrSize, + bool IsLittleEndian) + : DWARFContext(*new DWARFObjInMemory(Sections, AddrSize, IsLittleEndian)) { + DObj.reset(&this->Obj); +} Index: lib/DebugInfo/DWARF/DWARFDataExtractor.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFDataExtractor.cpp +++ lib/DebugInfo/DWARF/DWARFDataExtractor.cpp @@ -8,17 +8,18 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" +#include "llvm/DebugInfo/DWARF/DWARFContext.h" using namespace llvm; uint64_t DWARFDataExtractor::getRelocatedValue(uint32_t Size, uint32_t *Off, uint64_t *SecNdx) const { - if (!RelocMap) + if (!Section) return getUnsigned(Off, Size); - RelocAddrMap::const_iterator AI = RelocMap->find(*Off); - if (AI == RelocMap->end()) + Optional Rel = Obj->find(*Section, *Off); + if (!Rel) return getUnsigned(Off, Size); if (SecNdx) - *SecNdx = AI->second.SectionIndex; - return getUnsigned(Off, Size) + AI->second.Value; + *SecNdx = Rel->SectionIndex; + return getUnsigned(Off, Size) + Rel->Value; } Index: lib/DebugInfo/DWARF/DWARFUnit.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFUnit.cpp +++ lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -59,13 +59,18 @@ DWARFUnit::~DWARFUnit() = default; +DWARFDataExtractor DWARFUnit::getDebugInfoExtractor() const { + return DWARFDataExtractor(Context.getDWARFObj(), InfoSection, isLittleEndian, + getAddressByteSize()); +} + bool DWARFUnit::getAddrOffsetSectionItem(uint32_t Index, uint64_t &Result) const { uint32_t Offset = AddrOffsetSectionBase + Index * getAddressByteSize(); if (AddrOffsetSection->Data.size() < Offset + getAddressByteSize()) return false; - DWARFDataExtractor DA(*AddrOffsetSection, isLittleEndian, - getAddressByteSize()); + DWARFDataExtractor DA(Context.getDWARFObj(), *AddrOffsetSection, + isLittleEndian, getAddressByteSize()); Result = DA.getRelocatedAddress(&Offset); return true; } @@ -76,7 +81,8 @@ uint32_t Offset = StringOffsetSectionBase + Index * ItemSize; if (StringOffsetSection.Data.size() < Offset + ItemSize) return false; - DWARFDataExtractor DA(StringOffsetSection, isLittleEndian, 0); + DWARFDataExtractor DA(Context.getDWARFObj(), StringOffsetSection, + isLittleEndian, 0); Result = DA.getRelocatedValue(ItemSize, &Offset); return true; } @@ -141,8 +147,8 @@ DWARFDebugRangeList &RangeList) const { // Require that compile unit is extracted. assert(!DieArray.empty()); - DWARFDataExtractor RangesData(*RangeSection, isLittleEndian, - getAddressByteSize()); + DWARFDataExtractor RangesData(Context.getDWARFObj(), *RangeSection, + isLittleEndian, getAddressByteSize()); uint32_t ActualRangeListOffset = RangeSectionBase + RangeListOffset; return RangeList.extract(RangesData, &ActualRangeListOffset); } Index: lib/DebugInfo/DWARF/DWARFVerifier.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFVerifier.cpp +++ lib/DebugInfo/DWARF/DWARFVerifier.cpp @@ -280,7 +280,8 @@ bool DWARFVerifier::handleAppleNames() { NumAppleNamesErrors = 0; - DWARFDataExtractor AppleNamesSection(DCtx.getAppleNamesSection(), + DWARFDataExtractor AppleNamesSection(DCtx.getDWARFObj(), + DCtx.getAppleNamesSection(), DCtx.isLittleEndian(), 0); DataExtractor StrData(DCtx.getStringSection(), DCtx.isLittleEndian(), 0); DWARFAcceleratorTable AppleNames(AppleNamesSection, StrData); Index: tools/dsymutil/DwarfLinker.cpp =================================================================== --- tools/dsymutil/DwarfLinker.cpp +++ tools/dsymutil/DwarfLinker.cpp @@ -2873,7 +2873,8 @@ DWARFDebugRangeList RangeList; const auto &FunctionRanges = Unit.getFunctionRanges(); unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize(); - DWARFDataExtractor RangeExtractor(OrigDwarf.getRangeSection(), + DWARFDataExtractor RangeExtractor(OrigDwarf.getDWARFObj(), + OrigDwarf.getRangeSection(), OrigDwarf.isLittleEndian(), AddressSize); auto InvalidRange = FunctionRanges.end(), CurrRange = InvalidRange; DWARFUnit &OrigUnit = Unit.getOrigUnit(); @@ -2984,9 +2985,9 @@ // Parse the original line info for the unit. DWARFDebugLine::LineTable LineTable; uint32_t StmtOffset = *StmtList; - DWARFDataExtractor LineExtractor(OrigDwarf.getLineSection(), - OrigDwarf.isLittleEndian(), - Unit.getOrigUnit().getAddressByteSize()); + DWARFDataExtractor LineExtractor( + OrigDwarf.getDWARFObj(), OrigDwarf.getLineSection(), + OrigDwarf.isLittleEndian(), Unit.getOrigUnit().getAddressByteSize()); LineTable.parse(LineExtractor, &StmtOffset); // This vector is the output line table.