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