Home | History | Annotate | Download | only in dsymutil
      1 //===- tools/dsymutil/DebugMap.h - Generic debug map representation -------===//
      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     yaml::Hex64 ObjectAddress;
    121     yaml::Hex64 BinaryAddress;
    122     yaml::Hex32 Size;
    123     SymbolMapping(uint64_t ObjectAddress, uint64_t BinaryAddress, uint32_t Size)
    124         : ObjectAddress(ObjectAddress), BinaryAddress(BinaryAddress),
    125           Size(Size) {}
    126     /// For YAML IO support
    127     SymbolMapping() = default;
    128   };
    129 
    130   typedef StringMapEntry<SymbolMapping> DebugMapEntry;
    131 
    132   /// \brief Adds a symbol mapping to this DebugMapObject.
    133   /// \returns false if the symbol was already registered. The request
    134   /// is discarded in this case.
    135   bool addSymbol(llvm::StringRef SymName, uint64_t ObjectAddress,
    136                  uint64_t LinkedAddress, uint32_t Size);
    137 
    138   /// \brief Lookup a symbol mapping.
    139   /// \returns null if the symbol isn't found.
    140   const DebugMapEntry *lookupSymbol(StringRef SymbolName) const;
    141 
    142   /// \brief Lookup an objectfile address.
    143   /// \returns null if the address isn't found.
    144   const DebugMapEntry *lookupObjectAddress(uint64_t Address) const;
    145 
    146   llvm::StringRef getObjectFilename() const { return Filename; }
    147 
    148   sys::TimeValue getTimestamp() const { return Timestamp; }
    149 
    150   iterator_range<StringMap<SymbolMapping>::const_iterator> symbols() const {
    151     return make_range(Symbols.begin(), Symbols.end());
    152   }
    153 
    154   void print(raw_ostream &OS) const;
    155 #ifndef NDEBUG
    156   void dump() const;
    157 #endif
    158 private:
    159   friend class DebugMap;
    160   /// DebugMapObjects can only be constructed by the owning DebugMap.
    161   DebugMapObject(StringRef ObjectFilename, sys::TimeValue Timestamp);
    162 
    163   std::string Filename;
    164   sys::TimeValue Timestamp;
    165   StringMap<SymbolMapping> Symbols;
    166   DenseMap<uint64_t, DebugMapEntry *> AddressToMapping;
    167 
    168   /// For YAMLIO support.
    169   ///@{
    170   typedef std::pair<std::string, SymbolMapping> YAMLSymbolMapping;
    171   friend yaml::MappingTraits<dsymutil::DebugMapObject>;
    172   friend yaml::SequenceTraits<std::vector<std::unique_ptr<DebugMapObject>>>;
    173   friend yaml::SequenceTraits<std::vector<YAMLSymbolMapping>>;
    174   DebugMapObject() = default;
    175 
    176 public:
    177   DebugMapObject &operator=(DebugMapObject RHS) {
    178     std::swap(Filename, RHS.Filename);
    179     std::swap(Timestamp, RHS.Timestamp);
    180     std::swap(Symbols, RHS.Symbols);
    181     std::swap(AddressToMapping, RHS.AddressToMapping);
    182     return *this;
    183   }
    184   DebugMapObject(DebugMapObject &&RHS) {
    185     Filename = std::move(RHS.Filename);
    186     Timestamp = std::move(RHS.Timestamp);
    187     Symbols = std::move(RHS.Symbols);
    188     AddressToMapping = std::move(RHS.AddressToMapping);
    189   }
    190   ///@}
    191 };
    192 }
    193 }
    194 
    195 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::dsymutil::DebugMapObject::YAMLSymbolMapping)
    196 
    197 namespace llvm {
    198 namespace yaml {
    199 
    200 using namespace llvm::dsymutil;
    201 
    202 template <>
    203 struct MappingTraits<std::pair<std::string, DebugMapObject::SymbolMapping>> {
    204   static void mapping(IO &io,
    205                       std::pair<std::string, DebugMapObject::SymbolMapping> &s);
    206   static const bool flow = true;
    207 };
    208 
    209 template <> struct MappingTraits<dsymutil::DebugMapObject> {
    210   struct YamlDMO;
    211   static void mapping(IO &io, dsymutil::DebugMapObject &DMO);
    212 };
    213 
    214 template <> struct ScalarTraits<Triple> {
    215   static void output(const Triple &val, void *, llvm::raw_ostream &out);
    216   static StringRef input(StringRef scalar, void *, Triple &value);
    217   static bool mustQuote(StringRef) { return true; }
    218 };
    219 
    220 template <>
    221 struct SequenceTraits<std::vector<std::unique_ptr<dsymutil::DebugMapObject>>> {
    222   static size_t
    223   size(IO &io, std::vector<std::unique_ptr<dsymutil::DebugMapObject>> &seq);
    224   static dsymutil::DebugMapObject &
    225   element(IO &, std::vector<std::unique_ptr<dsymutil::DebugMapObject>> &seq,
    226           size_t index);
    227 };
    228 
    229 template <> struct MappingTraits<dsymutil::DebugMap> {
    230   static void mapping(IO &io, dsymutil::DebugMap &DM);
    231 };
    232 
    233 template <> struct MappingTraits<std::unique_ptr<dsymutil::DebugMap>> {
    234   static void mapping(IO &io, std::unique_ptr<dsymutil::DebugMap> &DM);
    235 };
    236 }
    237 }
    238 
    239 #endif // LLVM_TOOLS_DSYMUTIL_DEBUGMAP_H
    240