| //=- tools/dsymutil/DebugMap.h - Generic debug map representation -*- C++ -*-=// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| /// \file |
| /// |
| /// This file contains the class declaration of the DebugMap |
| /// entity. A DebugMap lists all the object files linked together to |
| /// produce an executable along with the linked address of all the |
| /// atoms used in these object files. |
| /// The DebugMap is an input to the DwarfLinker class that will |
| /// extract the Dwarf debug information from the referenced object |
| /// files and link their usefull debug info together. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef LLVM_TOOLS_DSYMUTIL_DEBUGMAP_H |
| #define LLVM_TOOLS_DSYMUTIL_DEBUGMAP_H |
| |
| #include "llvm/ADT/DenseMap.h" |
| #include "llvm/ADT/Optional.h" |
| #include "llvm/ADT/StringMap.h" |
| #include "llvm/ADT/StringRef.h" |
| #include "llvm/ADT/Triple.h" |
| #include "llvm/ADT/iterator_range.h" |
| #include "llvm/Object/MachO.h" |
| #include "llvm/Support/Chrono.h" |
| #include "llvm/Support/ErrorOr.h" |
| #include "llvm/Support/YAMLTraits.h" |
| #include <chrono> |
| #include <cstddef> |
| #include <cstdint> |
| #include <memory> |
| #include <string> |
| #include <utility> |
| #include <vector> |
| |
| namespace llvm { |
| |
| class raw_ostream; |
| |
| namespace dsymutil { |
| |
| class DebugMapObject; |
| |
| /// The DebugMap object stores the list of object files to query for debug |
| /// information along with the mapping between the symbols' addresses in the |
| /// object file to their linked address in the linked binary. |
| /// |
| /// A DebugMap producer could look like this: |
| /// DebugMap *DM = new DebugMap(); |
| /// for (const auto &Obj: LinkedObjects) { |
| /// DebugMapObject &DMO = DM->addDebugMapObject(Obj.getPath()); |
| /// for (const auto &Sym: Obj.getLinkedSymbols()) |
| /// DMO.addSymbol(Sym.getName(), Sym.getObjectFileAddress(), |
| /// Sym.getBinaryAddress()); |
| /// } |
| /// |
| /// A DebugMap consumer can then use the map to link the debug |
| /// information. For example something along the lines of: |
| /// for (const auto &DMO: DM->objects()) { |
| /// auto Obj = createBinary(DMO.getObjectFilename()); |
| /// for (auto &DIE: Obj.getDwarfDIEs()) { |
| /// if (SymbolMapping *Sym = DMO.lookup(DIE.getName())) |
| /// DIE.relocate(Sym->ObjectAddress, Sym->BinaryAddress); |
| /// else |
| /// DIE.discardSubtree(); |
| /// } |
| /// } |
| class DebugMap { |
| Triple BinaryTriple; |
| std::string BinaryPath; |
| |
| using ObjectContainer = std::vector<std::unique_ptr<DebugMapObject>>; |
| |
| ObjectContainer Objects; |
| |
| /// For YAML IO support. |
| ///@{ |
| friend yaml::MappingTraits<std::unique_ptr<DebugMap>>; |
| friend yaml::MappingTraits<DebugMap>; |
| |
| DebugMap() = default; |
| ///@} |
| |
| public: |
| DebugMap(const Triple &BinaryTriple, StringRef BinaryPath) |
| : BinaryTriple(BinaryTriple), BinaryPath(BinaryPath) {} |
| |
| using const_iterator = ObjectContainer::const_iterator; |
| |
| iterator_range<const_iterator> objects() const { |
| return make_range(begin(), end()); |
| } |
| |
| const_iterator begin() const { return Objects.begin(); } |
| |
| const_iterator end() const { return Objects.end(); } |
| |
| unsigned getNumberOfObjects() const { return Objects.size(); } |
| |
| /// This function adds an DebugMapObject to the list owned by this |
| /// debug map. |
| DebugMapObject & |
| addDebugMapObject(StringRef ObjectFilePath, |
| sys::TimePoint<std::chrono::seconds> Timestamp, |
| uint8_t Type = llvm::MachO::N_OSO); |
| |
| const Triple &getTriple() const { return BinaryTriple; } |
| |
| StringRef getBinaryPath() const { return BinaryPath; } |
| |
| void print(raw_ostream &OS) const; |
| |
| #ifndef NDEBUG |
| void dump() const; |
| #endif |
| |
| /// Read a debug map for \a InputFile. |
| static ErrorOr<std::vector<std::unique_ptr<DebugMap>>> |
| parseYAMLDebugMap(StringRef InputFile, StringRef PrependPath, bool Verbose); |
| }; |
| |
| /// The DebugMapObject represents one object file described by the DebugMap. It |
| /// contains a list of mappings between addresses in the object file and in the |
| /// linked binary for all the linked atoms in this object file. |
| class DebugMapObject { |
| public: |
| struct SymbolMapping { |
| Optional<yaml::Hex64> ObjectAddress; |
| yaml::Hex64 BinaryAddress; |
| yaml::Hex32 Size; |
| |
| SymbolMapping(Optional<uint64_t> ObjectAddr, uint64_t BinaryAddress, |
| uint32_t Size) |
| : BinaryAddress(BinaryAddress), Size(Size) { |
| if (ObjectAddr) |
| ObjectAddress = *ObjectAddr; |
| } |
| |
| /// For YAML IO support |
| SymbolMapping() = default; |
| }; |
| |
| using YAMLSymbolMapping = std::pair<std::string, SymbolMapping>; |
| using DebugMapEntry = StringMapEntry<SymbolMapping>; |
| |
| /// Adds a symbol mapping to this DebugMapObject. |
| /// \returns false if the symbol was already registered. The request |
| /// is discarded in this case. |
| bool addSymbol(StringRef SymName, Optional<uint64_t> ObjectAddress, |
| uint64_t LinkedAddress, uint32_t Size); |
| |
| /// Lookup a symbol mapping. |
| /// \returns null if the symbol isn't found. |
| const DebugMapEntry *lookupSymbol(StringRef SymbolName) const; |
| |
| /// Lookup an object file address. |
| /// \returns null if the address isn't found. |
| const DebugMapEntry *lookupObjectAddress(uint64_t Address) const; |
| |
| StringRef getObjectFilename() const { return Filename; } |
| |
| sys::TimePoint<std::chrono::seconds> getTimestamp() const { |
| return Timestamp; |
| } |
| |
| uint8_t getType() const { return Type; } |
| |
| iterator_range<StringMap<SymbolMapping>::const_iterator> symbols() const { |
| return make_range(Symbols.begin(), Symbols.end()); |
| } |
| |
| bool empty() const { return Symbols.empty(); } |
| |
| void addWarning(StringRef Warning) { Warnings.push_back(Warning); } |
| const std::vector<std::string> &getWarnings() const { return Warnings; } |
| |
| void print(raw_ostream &OS) const; |
| #ifndef NDEBUG |
| void dump() const; |
| #endif |
| |
| private: |
| friend class DebugMap; |
| |
| /// DebugMapObjects can only be constructed by the owning DebugMap. |
| DebugMapObject(StringRef ObjectFilename, |
| sys::TimePoint<std::chrono::seconds> Timestamp, uint8_t Type); |
| |
| std::string Filename; |
| sys::TimePoint<std::chrono::seconds> Timestamp; |
| StringMap<SymbolMapping> Symbols; |
| DenseMap<uint64_t, DebugMapEntry *> AddressToMapping; |
| uint8_t Type; |
| |
| std::vector<std::string> Warnings; |
| |
| /// For YAMLIO support. |
| ///@{ |
| friend yaml::MappingTraits<dsymutil::DebugMapObject>; |
| friend yaml::SequenceTraits<std::vector<std::unique_ptr<DebugMapObject>>>; |
| |
| DebugMapObject() = default; |
| |
| public: |
| DebugMapObject(DebugMapObject &&) = default; |
| DebugMapObject &operator=(DebugMapObject &&) = default; |
| ///@} |
| }; |
| |
| } // end namespace dsymutil |
| } // end namespace llvm |
| |
| LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::dsymutil::DebugMapObject::YAMLSymbolMapping) |
| |
| namespace llvm { |
| namespace yaml { |
| |
| using namespace llvm::dsymutil; |
| |
| template <> |
| struct MappingTraits<std::pair<std::string, DebugMapObject::SymbolMapping>> { |
| static void mapping(IO &io, |
| std::pair<std::string, DebugMapObject::SymbolMapping> &s); |
| static const bool flow = true; |
| }; |
| |
| template <> struct MappingTraits<dsymutil::DebugMapObject> { |
| struct YamlDMO; |
| static void mapping(IO &io, dsymutil::DebugMapObject &DMO); |
| }; |
| |
| template <> struct ScalarTraits<Triple> { |
| static void output(const Triple &val, void *, raw_ostream &out); |
| static StringRef input(StringRef scalar, void *, Triple &value); |
| static QuotingType mustQuote(StringRef) { return QuotingType::Single; } |
| }; |
| |
| template <> |
| struct SequenceTraits<std::vector<std::unique_ptr<dsymutil::DebugMapObject>>> { |
| static size_t |
| size(IO &io, std::vector<std::unique_ptr<dsymutil::DebugMapObject>> &seq); |
| static dsymutil::DebugMapObject & |
| element(IO &, std::vector<std::unique_ptr<dsymutil::DebugMapObject>> &seq, |
| size_t index); |
| }; |
| |
| template <> struct MappingTraits<dsymutil::DebugMap> { |
| static void mapping(IO &io, dsymutil::DebugMap &DM); |
| }; |
| |
| template <> struct MappingTraits<std::unique_ptr<dsymutil::DebugMap>> { |
| static void mapping(IO &io, std::unique_ptr<dsymutil::DebugMap> &DM); |
| }; |
| |
| } // end namespace yaml |
| } // end namespace llvm |
| |
| #endif // LLVM_TOOLS_DSYMUTIL_DEBUGMAP_H |