Home | History | Annotate | Download | only in dsymutil
      1 //=== tools/dsymutil/DebugMap.h - Generic debug map representation -*- C++ -*-//
      2 //
      3 //                             The LLVM Linker
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 ///
     10 /// \file
     11 ///
     12 /// This file contains the class declaration of the DebugMap
     13 /// entity. A DebugMap lists all the object files linked together to
     14 /// produce an executable along with the linked address of all the
     15 /// atoms used in these object files.
     16 /// The DebugMap is an input to the DwarfLinker class that will
     17 /// extract the Dwarf debug information from the referenced object
     18 /// files and link their usefull debug info together.
     19 ///
     20 //===----------------------------------------------------------------------===//
     21 #ifndef LLVM_TOOLS_DSYMUTIL_DEBUGMAP_H
     22 #define LLVM_TOOLS_DSYMUTIL_DEBUGMAP_H
     23 
     24 #include "llvm/ADT/DenseMap.h"
     25 #include "llvm/ADT/StringMap.h"
     26 #include "llvm/ADT/Triple.h"
     27 #include "llvm/ADT/iterator_range.h"
     28 #include "llvm/Object/ObjectFile.h"
     29 #include "llvm/Support/ErrorOr.h"
     30 #include "llvm/Support/Format.h"
     31 #include "llvm/Support/Path.h"
     32 #include "llvm/Support/TimeValue.h"
     33 #include "llvm/Support/YAMLTraits.h"
     34 #include <vector>
     35 
     36 namespace llvm {
     37 class raw_ostream;
     38 
     39 namespace dsymutil {
     40 class DebugMapObject;
     41 
     42 /// \brief The DebugMap object stores the list of object files to
     43 /// query for debug information along with the mapping between the
     44 /// symbols' addresses in the object file to their linked address in
     45 /// the linked binary.
     46 ///
     47 /// A DebugMap producer could look like this:
     48 /// DebugMap *DM = new DebugMap();
     49 /// for (const auto &Obj: LinkedObjects) {
     50 ///     DebugMapObject &DMO = DM->addDebugMapObject(Obj.getPath());
     51 ///     for (const auto &Sym: Obj.getLinkedSymbols())
     52 ///         DMO.addSymbol(Sym.getName(), Sym.getObjectFileAddress(),
     53 ///                       Sym.getBinaryAddress());
     54 /// }
     55 ///
     56 /// A DebugMap consumer can then use the map to link the debug
     57 /// information. For example something along the lines of:
     58 /// for (const auto &DMO: DM->objects()) {
     59 ///     auto Obj = createBinary(DMO.getObjectFilename());
     60 ///     for (auto &DIE: Obj.getDwarfDIEs()) {
     61 ///         if (SymbolMapping *Sym = DMO.lookup(DIE.getName()))
     62 ///             DIE.relocate(Sym->ObjectAddress, Sym->BinaryAddress);
     63 ///         else
     64 ///             DIE.discardSubtree();
     65 ///     }
     66 /// }
     67 class DebugMap {
     68   Triple BinaryTriple;
     69   std::string BinaryPath;
     70   typedef std::vector<std::unique_ptr<DebugMapObject>> ObjectContainer;
     71   ObjectContainer Objects;
     72 
     73   /// For YAML IO support.
     74   ///@{
     75   friend yaml::MappingTraits<std::unique_ptr<DebugMap>>;
     76   friend yaml::MappingTraits<DebugMap>;
     77   DebugMap() = default;
     78   ///@}
     79 public:
     80   DebugMap(const Triple &BinaryTriple, StringRef BinaryPath)
     81       : BinaryTriple(BinaryTriple), BinaryPath(BinaryPath) {}
     82 
     83   typedef ObjectContainer::const_iterator const_iterator;
     84 
     85   iterator_range<const_iterator> objects() const {
     86     return make_range(begin(), end());
     87   }
     88 
     89   const_iterator begin() const { return Objects.begin(); }
     90 
     91   const_iterator end() const { return Objects.end(); }
     92 
     93   /// This function adds an DebugMapObject to the list owned by this
     94   /// debug map.
     95   DebugMapObject &addDebugMapObject(StringRef ObjectFilePath,
     96                                     sys::TimeValue Timestamp);
     97 
     98   const Triple &getTriple() const { return BinaryTriple; }
     99 
    100   StringRef getBinaryPath() const { return BinaryPath; }
    101 
    102   void print(raw_ostream &OS) const;
    103 
    104 #ifndef NDEBUG
    105   void dump() const;
    106 #endif
    107 
    108   /// Read a debug map for \a InputFile.
    109   static ErrorOr<std::vector<std::unique_ptr<DebugMap>>>
    110   parseYAMLDebugMap(StringRef InputFile, StringRef PrependPath, bool Verbose);
    111 };
    112 
    113 /// \brief The DebugMapObject represents one object file described by
    114 /// the DebugMap. It contains a list of mappings between addresses in
    115 /// the object file and in the linked binary for all the linked atoms
    116 /// in this object file.
    117 class DebugMapObject {
    118 public:
    119   struct SymbolMapping {
    120     Optional<yaml::Hex64> ObjectAddress;
    121     yaml::Hex64 BinaryAddress;
    122     yaml::Hex32 Size;
    123     SymbolMapping(Optional<uint64_t> ObjectAddr, uint64_t BinaryAddress,
    124                   uint32_t Size)
    125         : BinaryAddress(BinaryAddress), Size(Size) {
    126       if (ObjectAddr)
    127         ObjectAddress = *ObjectAddr;
    128     }
    129     /// For YAML IO support
    130     SymbolMapping() = default;
    131   };
    132 
    133   typedef StringMapEntry<SymbolMapping> DebugMapEntry;
    134 
    135   /// \brief Adds a symbol mapping to this DebugMapObject.
    136   /// \returns false if the symbol was already registered. The request
    137   /// is discarded in this case.
    138   bool addSymbol(llvm::StringRef SymName, Optional<uint64_t> ObjectAddress,
    139                  uint64_t LinkedAddress, uint32_t Size);
    140 
    141   /// \brief Lookup a symbol mapping.
    142   /// \returns null if the symbol isn't found.
    143   const DebugMapEntry *lookupSymbol(StringRef SymbolName) const;
    144 
    145   /// \brief Lookup an objectfile address.
    146   /// \returns null if the address isn't found.
    147   const DebugMapEntry *lookupObjectAddress(uint64_t Address) const;
    148 
    149   llvm::StringRef getObjectFilename() const { return Filename; }
    150 
    151   sys::TimeValue getTimestamp() const { return Timestamp; }
    152 
    153   iterator_range<StringMap<SymbolMapping>::const_iterator> symbols() const {
    154     return make_range(Symbols.begin(), Symbols.end());
    155   }
    156 
    157   void print(raw_ostream &OS) const;
    158 #ifndef NDEBUG
    159   void dump() const;
    160 #endif
    161 private:
    162   friend class DebugMap;
    163   /// DebugMapObjects can only be constructed by the owning DebugMap.
    164   DebugMapObject(StringRef ObjectFilename, sys::TimeValue Timestamp);
    165 
    166   std::string Filename;
    167   sys::TimeValue Timestamp;
    168   StringMap<SymbolMapping> Symbols;
    169   DenseMap<uint64_t, DebugMapEntry *> AddressToMapping;
    170 
    171   /// For YAMLIO support.
    172   ///@{
    173   typedef std::pair<std::string, SymbolMapping> YAMLSymbolMapping;
    174   friend yaml::MappingTraits<dsymutil::DebugMapObject>;
    175   friend yaml::SequenceTraits<std::vector<std::unique_ptr<DebugMapObject>>>;
    176   friend yaml::SequenceTraits<std::vector<YAMLSymbolMapping>>;
    177   DebugMapObject() = default;
    178 
    179 public:
    180   DebugMapObject &operator=(DebugMapObject RHS) {
    181     std::swap(Filename, RHS.Filename);
    182     std::swap(Timestamp, RHS.Timestamp);
    183     std::swap(Symbols, RHS.Symbols);
    184     std::swap(AddressToMapping, RHS.AddressToMapping);
    185     return *this;
    186   }
    187   DebugMapObject(DebugMapObject &&RHS) {
    188     Filename = std::move(RHS.Filename);
    189     Timestamp = std::move(RHS.Timestamp);
    190     Symbols = std::move(RHS.Symbols);
    191     AddressToMapping = std::move(RHS.AddressToMapping);
    192   }
    193   ///@}
    194 };
    195 }
    196 }
    197 
    198 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::dsymutil::DebugMapObject::YAMLSymbolMapping)
    199 
    200 namespace llvm {
    201 namespace yaml {
    202 
    203 using namespace llvm::dsymutil;
    204 
    205 template <>
    206 struct MappingTraits<std::pair<std::string, DebugMapObject::SymbolMapping>> {
    207   static void mapping(IO &io,
    208                       std::pair<std::string, DebugMapObject::SymbolMapping> &s);
    209   static const bool flow = true;
    210 };
    211 
    212 template <> struct MappingTraits<dsymutil::DebugMapObject> {
    213   struct YamlDMO;
    214   static void mapping(IO &io, dsymutil::DebugMapObject &DMO);
    215 };
    216 
    217 template <> struct ScalarTraits<Triple> {
    218   static void output(const Triple &val, void *, llvm::raw_ostream &out);
    219   static StringRef input(StringRef scalar, void *, Triple &value);
    220   static bool mustQuote(StringRef) { return true; }
    221 };
    222 
    223 template <>
    224 struct SequenceTraits<std::vector<std::unique_ptr<dsymutil::DebugMapObject>>> {
    225   static size_t
    226   size(IO &io, std::vector<std::unique_ptr<dsymutil::DebugMapObject>> &seq);
    227   static dsymutil::DebugMapObject &
    228   element(IO &, std::vector<std::unique_ptr<dsymutil::DebugMapObject>> &seq,
    229           size_t index);
    230 };
    231 
    232 template <> struct MappingTraits<dsymutil::DebugMap> {
    233   static void mapping(IO &io, dsymutil::DebugMap &DM);
    234 };
    235 
    236 template <> struct MappingTraits<std::unique_ptr<dsymutil::DebugMap>> {
    237   static void mapping(IO &io, std::unique_ptr<dsymutil::DebugMap> &DM);
    238 };
    239 }
    240 }
    241 
    242 #endif // LLVM_TOOLS_DSYMUTIL_DEBUGMAP_H
    243