123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442 |
- #pragma once
- #ifdef __GNUC__
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wunused-parameter"
- #endif
- //===- DWARFContext.h -------------------------------------------*- C++ -*-===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===/
- #ifndef LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H
- #define LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H
- #include "llvm/ADT/MapVector.h"
- #include "llvm/ADT/SmallString.h"
- #include "llvm/ADT/SmallVector.h"
- #include "llvm/ADT/StringMap.h"
- #include "llvm/ADT/StringRef.h"
- #include "llvm/ADT/iterator_range.h"
- #include "llvm/DebugInfo/DIContext.h"
- #include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
- #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
- #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
- #include "llvm/DebugInfo/DWARF/DWARFDebugAranges.h"
- #include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h"
- #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
- #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
- #include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h"
- #include "llvm/DebugInfo/DWARF/DWARFDie.h"
- #include "llvm/DebugInfo/DWARF/DWARFGdbIndex.h"
- #include "llvm/DebugInfo/DWARF/DWARFObject.h"
- #include "llvm/DebugInfo/DWARF/DWARFSection.h"
- #include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h"
- #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
- #include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
- #include "llvm/Object/Binary.h"
- #include "llvm/Object/ObjectFile.h"
- #include "llvm/Support/DataExtractor.h"
- #include "llvm/Support/Error.h"
- #include "llvm/Support/Host.h"
- #include <cstdint>
- #include <deque>
- #include <map>
- #include <memory>
- namespace llvm {
- class MCRegisterInfo;
- class MemoryBuffer;
- class raw_ostream;
- /// DWARFContext
- /// This data structure is the top level entity that deals with dwarf debug
- /// information parsing. The actual data is supplied through DWARFObj.
- class DWARFContext : public DIContext {
- DWARFUnitVector NormalUnits;
- std::unique_ptr<DWARFUnitIndex> CUIndex;
- std::unique_ptr<DWARFGdbIndex> GdbIndex;
- std::unique_ptr<DWARFUnitIndex> TUIndex;
- std::unique_ptr<DWARFDebugAbbrev> Abbrev;
- std::unique_ptr<DWARFDebugLoc> Loc;
- std::unique_ptr<DWARFDebugAranges> Aranges;
- std::unique_ptr<DWARFDebugLine> Line;
- std::unique_ptr<DWARFDebugFrame> DebugFrame;
- std::unique_ptr<DWARFDebugFrame> EHFrame;
- std::unique_ptr<DWARFDebugMacro> Macro;
- std::unique_ptr<DWARFDebugMacro> Macinfo;
- std::unique_ptr<DWARFDebugNames> Names;
- std::unique_ptr<AppleAcceleratorTable> AppleNames;
- std::unique_ptr<AppleAcceleratorTable> AppleTypes;
- std::unique_ptr<AppleAcceleratorTable> AppleNamespaces;
- std::unique_ptr<AppleAcceleratorTable> AppleObjC;
- DWARFUnitVector DWOUnits;
- std::unique_ptr<DWARFDebugAbbrev> AbbrevDWO;
- std::unique_ptr<DWARFDebugMacro> MacinfoDWO;
- std::unique_ptr<DWARFDebugMacro> MacroDWO;
- /// The maximum DWARF version of all units.
- unsigned MaxVersion = 0;
- struct DWOFile {
- object::OwningBinary<object::ObjectFile> File;
- std::unique_ptr<DWARFContext> Context;
- };
- StringMap<std::weak_ptr<DWOFile>> DWOFiles;
- std::weak_ptr<DWOFile> DWP;
- bool CheckedForDWP = false;
- std::string DWPName;
- std::unique_ptr<MCRegisterInfo> RegInfo;
- std::function<void(Error)> RecoverableErrorHandler =
- WithColor::defaultErrorHandler;
- std::function<void(Error)> WarningHandler = WithColor::defaultWarningHandler;
- /// Read compile units from the debug_info section (if necessary)
- /// and type units from the debug_types sections (if necessary)
- /// and store them in NormalUnits.
- void parseNormalUnits();
- /// Read compile units from the debug_info.dwo section (if necessary)
- /// and type units from the debug_types.dwo section (if necessary)
- /// and store them in DWOUnits.
- /// If \p Lazy is true, set up to parse but don't actually parse them.
- enum { EagerParse = false, LazyParse = true };
- void parseDWOUnits(bool Lazy = false);
- std::unique_ptr<const DWARFObject> DObj;
- /// Helper enum to distinguish between macro[.dwo] and macinfo[.dwo]
- /// section.
- enum MacroSecType {
- MacinfoSection,
- MacinfoDwoSection,
- MacroSection,
- MacroDwoSection
- };
- public:
- DWARFContext(std::unique_ptr<const DWARFObject> DObj,
- std::string DWPName = "",
- std::function<void(Error)> RecoverableErrorHandler =
- WithColor::defaultErrorHandler,
- std::function<void(Error)> WarningHandler =
- WithColor::defaultWarningHandler);
- ~DWARFContext();
- DWARFContext(DWARFContext &) = delete;
- DWARFContext &operator=(DWARFContext &) = delete;
- const DWARFObject &getDWARFObj() const { return *DObj; }
- static bool classof(const DIContext *DICtx) {
- return DICtx->getKind() == CK_DWARF;
- }
- /// Dump a textual representation to \p OS. If any \p DumpOffsets are present,
- /// dump only the record at the specified offset.
- void dump(raw_ostream &OS, DIDumpOptions DumpOpts,
- std::array<Optional<uint64_t>, DIDT_ID_Count> DumpOffsets);
- void dump(raw_ostream &OS, DIDumpOptions DumpOpts) override {
- std::array<Optional<uint64_t>, DIDT_ID_Count> DumpOffsets;
- dump(OS, DumpOpts, DumpOffsets);
- }
- bool verify(raw_ostream &OS, DIDumpOptions DumpOpts = {}) override;
- using unit_iterator_range = DWARFUnitVector::iterator_range;
- using compile_unit_range = DWARFUnitVector::compile_unit_range;
- /// Get units from .debug_info in this context.
- unit_iterator_range info_section_units() {
- parseNormalUnits();
- return unit_iterator_range(NormalUnits.begin(),
- NormalUnits.begin() +
- NormalUnits.getNumInfoUnits());
- }
- /// Get units from .debug_types in this context.
- unit_iterator_range types_section_units() {
- parseNormalUnits();
- return unit_iterator_range(
- NormalUnits.begin() + NormalUnits.getNumInfoUnits(), NormalUnits.end());
- }
- /// Get compile units in this context.
- compile_unit_range compile_units() {
- return make_filter_range(info_section_units(), isCompileUnit);
- }
- // If you want type_units(), it'll need to be a concat iterator of a filter of
- // TUs in info_section + all the (all type) units in types_section
- /// Get all normal compile/type units in this context.
- unit_iterator_range normal_units() {
- parseNormalUnits();
- return unit_iterator_range(NormalUnits.begin(), NormalUnits.end());
- }
- /// Get units from .debug_info..dwo in the DWO context.
- unit_iterator_range dwo_info_section_units() {
- parseDWOUnits();
- return unit_iterator_range(DWOUnits.begin(),
- DWOUnits.begin() + DWOUnits.getNumInfoUnits());
- }
- /// Get units from .debug_types.dwo in the DWO context.
- unit_iterator_range dwo_types_section_units() {
- parseDWOUnits();
- return unit_iterator_range(DWOUnits.begin() + DWOUnits.getNumInfoUnits(),
- DWOUnits.end());
- }
- /// Get compile units in the DWO context.
- compile_unit_range dwo_compile_units() {
- return make_filter_range(dwo_info_section_units(), isCompileUnit);
- }
- // If you want dwo_type_units(), it'll need to be a concat iterator of a
- // filter of TUs in dwo_info_section + all the (all type) units in
- // dwo_types_section.
- /// Get all units in the DWO context.
- unit_iterator_range dwo_units() {
- parseDWOUnits();
- return unit_iterator_range(DWOUnits.begin(), DWOUnits.end());
- }
- /// Get the number of compile units in this context.
- unsigned getNumCompileUnits() {
- parseNormalUnits();
- return NormalUnits.getNumInfoUnits();
- }
- /// Get the number of type units in this context.
- unsigned getNumTypeUnits() {
- parseNormalUnits();
- return NormalUnits.getNumTypesUnits();
- }
- /// Get the number of compile units in the DWO context.
- unsigned getNumDWOCompileUnits() {
- parseDWOUnits();
- return DWOUnits.getNumInfoUnits();
- }
- /// Get the number of type units in the DWO context.
- unsigned getNumDWOTypeUnits() {
- parseDWOUnits();
- return DWOUnits.getNumTypesUnits();
- }
- /// Get the unit at the specified index.
- DWARFUnit *getUnitAtIndex(unsigned index) {
- parseNormalUnits();
- return NormalUnits[index].get();
- }
- /// Get the unit at the specified index for the DWO units.
- DWARFUnit *getDWOUnitAtIndex(unsigned index) {
- parseDWOUnits();
- return DWOUnits[index].get();
- }
- DWARFCompileUnit *getDWOCompileUnitForHash(uint64_t Hash);
- /// Return the compile unit that includes an offset (relative to .debug_info).
- DWARFCompileUnit *getCompileUnitForOffset(uint64_t Offset);
- /// Get a DIE given an exact offset.
- DWARFDie getDIEForOffset(uint64_t Offset);
- unsigned getMaxVersion() {
- // Ensure info units have been parsed to discover MaxVersion
- info_section_units();
- return MaxVersion;
- }
- unsigned getMaxDWOVersion() {
- // Ensure DWO info units have been parsed to discover MaxVersion
- dwo_info_section_units();
- return MaxVersion;
- }
- void setMaxVersionIfGreater(unsigned Version) {
- if (Version > MaxVersion)
- MaxVersion = Version;
- }
- const DWARFUnitIndex &getCUIndex();
- DWARFGdbIndex &getGdbIndex();
- const DWARFUnitIndex &getTUIndex();
- /// Get a pointer to the parsed DebugAbbrev object.
- const DWARFDebugAbbrev *getDebugAbbrev();
- /// Get a pointer to the parsed DebugLoc object.
- const DWARFDebugLoc *getDebugLoc();
- /// Get a pointer to the parsed dwo abbreviations object.
- const DWARFDebugAbbrev *getDebugAbbrevDWO();
- /// Get a pointer to the parsed DebugAranges object.
- const DWARFDebugAranges *getDebugAranges();
- /// Get a pointer to the parsed frame information object.
- Expected<const DWARFDebugFrame *> getDebugFrame();
- /// Get a pointer to the parsed eh frame information object.
- Expected<const DWARFDebugFrame *> getEHFrame();
- /// Get a pointer to the parsed DebugMacinfo information object.
- const DWARFDebugMacro *getDebugMacinfo();
- /// Get a pointer to the parsed DebugMacinfoDWO information object.
- const DWARFDebugMacro *getDebugMacinfoDWO();
- /// Get a pointer to the parsed DebugMacro information object.
- const DWARFDebugMacro *getDebugMacro();
- /// Get a pointer to the parsed DebugMacroDWO information object.
- const DWARFDebugMacro *getDebugMacroDWO();
- /// Get a reference to the parsed accelerator table object.
- const DWARFDebugNames &getDebugNames();
- /// Get a reference to the parsed accelerator table object.
- const AppleAcceleratorTable &getAppleNames();
- /// Get a reference to the parsed accelerator table object.
- const AppleAcceleratorTable &getAppleTypes();
- /// Get a reference to the parsed accelerator table object.
- const AppleAcceleratorTable &getAppleNamespaces();
- /// Get a reference to the parsed accelerator table object.
- const AppleAcceleratorTable &getAppleObjC();
- /// Get a pointer to a parsed line table corresponding to a compile unit.
- /// Report any parsing issues as warnings on stderr.
- const DWARFDebugLine::LineTable *getLineTableForUnit(DWARFUnit *U);
- /// Get a pointer to a parsed line table corresponding to a compile unit.
- /// Report any recoverable parsing problems using the handler.
- Expected<const DWARFDebugLine::LineTable *>
- getLineTableForUnit(DWARFUnit *U,
- function_ref<void(Error)> RecoverableErrorHandler);
- DataExtractor getStringExtractor() const {
- return DataExtractor(DObj->getStrSection(), false, 0);
- }
- DataExtractor getStringDWOExtractor() const {
- return DataExtractor(DObj->getStrDWOSection(), false, 0);
- }
- DataExtractor getLineStringExtractor() const {
- return DataExtractor(DObj->getLineStrSection(), false, 0);
- }
- /// Wraps the returned DIEs for a given address.
- struct DIEsForAddress {
- DWARFCompileUnit *CompileUnit = nullptr;
- DWARFDie FunctionDIE;
- DWARFDie BlockDIE;
- explicit operator bool() const { return CompileUnit != nullptr; }
- };
- /// Get the compilation unit, the function DIE and lexical block DIE for the
- /// given address where applicable.
- /// TODO: change input parameter from "uint64_t Address"
- /// into "SectionedAddress Address"
- DIEsForAddress getDIEsForAddress(uint64_t Address);
- DILineInfo getLineInfoForAddress(
- object::SectionedAddress Address,
- DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
- DILineInfoTable getLineInfoForAddressRange(
- object::SectionedAddress Address, uint64_t Size,
- DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
- DIInliningInfo getInliningInfoForAddress(
- object::SectionedAddress Address,
- DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
- std::vector<DILocal>
- getLocalsForAddress(object::SectionedAddress Address) override;
- bool isLittleEndian() const { return DObj->isLittleEndian(); }
- static bool isSupportedVersion(unsigned version) {
- return version == 2 || version == 3 || version == 4 || version == 5;
- }
- static bool isAddressSizeSupported(unsigned AddressSize) {
- return AddressSize == 2 || AddressSize == 4 || AddressSize == 8;
- }
- std::shared_ptr<DWARFContext> getDWOContext(StringRef AbsolutePath);
- const MCRegisterInfo *getRegisterInfo() const { return RegInfo.get(); }
- function_ref<void(Error)> getRecoverableErrorHandler() {
- return RecoverableErrorHandler;
- }
- function_ref<void(Error)> getWarningHandler() { return WarningHandler; }
- static std::unique_ptr<DWARFContext>
- create(const object::ObjectFile &Obj, const LoadedObjectInfo *L = nullptr,
- std::string DWPName = "",
- std::function<void(Error)> RecoverableErrorHandler =
- WithColor::defaultErrorHandler,
- std::function<void(Error)> WarningHandler =
- WithColor::defaultWarningHandler);
- static std::unique_ptr<DWARFContext>
- create(const StringMap<std::unique_ptr<MemoryBuffer>> &Sections,
- uint8_t AddrSize, bool isLittleEndian = sys::IsLittleEndianHost,
- std::function<void(Error)> RecoverableErrorHandler =
- WithColor::defaultErrorHandler,
- std::function<void(Error)> WarningHandler =
- WithColor::defaultWarningHandler);
- /// Loads register info for the architecture of the provided object file.
- /// Improves readability of dumped DWARF expressions. Requires the caller to
- /// have initialized the relevant target descriptions.
- Error loadRegisterInfo(const object::ObjectFile &Obj);
- /// Get address size from CUs.
- /// TODO: refactor compile_units() to make this const.
- uint8_t getCUAddrSize();
- Triple::ArchType getArch() const {
- return getDWARFObj().getFile()->getArch();
- }
- /// Return the compile unit which contains instruction with provided
- /// address.
- /// TODO: change input parameter from "uint64_t Address"
- /// into "SectionedAddress Address"
- DWARFCompileUnit *getCompileUnitForAddress(uint64_t Address);
- private:
- /// Parse a macro[.dwo] or macinfo[.dwo] section.
- std::unique_ptr<DWARFDebugMacro>
- parseMacroOrMacinfo(MacroSecType SectionType);
- void addLocalsForDie(DWARFCompileUnit *CU, DWARFDie Subprogram, DWARFDie Die,
- std::vector<DILocal> &Result);
- };
- } // end namespace llvm
- #endif // LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H
- #ifdef __GNUC__
- #pragma GCC diagnostic pop
- #endif
|