Home | History | Annotate | Line # | Download | only in DWARFLinker
      1 //===- DWARFLinker.h --------------------------------------------*- 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 #ifndef LLVM_DWARFLINKER_DWARFLINKER_H
     10 #define LLVM_DWARFLINKER_DWARFLINKER_H
     11 
     12 #include "llvm/CodeGen/AccelTable.h"
     13 #include "llvm/CodeGen/NonRelocatableStringpool.h"
     14 #include "llvm/DWARFLinker/DWARFLinkerDeclContext.h"
     15 #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
     16 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
     17 #include "llvm/MC/MCDwarf.h"
     18 #include <map>
     19 
     20 namespace llvm {
     21 
     22 enum class DwarfLinkerClient { Dsymutil, LLD, General };
     23 
     24 /// The kind of accelerator tables we should emit.
     25 enum class AccelTableKind {
     26   Apple,   ///< .apple_names, .apple_namespaces, .apple_types, .apple_objc.
     27   Dwarf,   ///< DWARF v5 .debug_names.
     28   Default, ///< Dwarf for DWARF5 or later, Apple otherwise.
     29   Pub,     ///< .debug_pubnames, .debug_pubtypes
     30 };
     31 
     32 /// Partial address range. Besides an offset, only the
     33 /// HighPC is stored. The structure is stored in a map where the LowPC is the
     34 /// key.
     35 struct ObjFileAddressRange {
     36   /// Function HighPC.
     37   uint64_t HighPC;
     38   /// Offset to apply to the linked address.
     39   /// should be 0 for not-linked object file.
     40   int64_t Offset;
     41 
     42   ObjFileAddressRange(uint64_t EndPC, int64_t Offset)
     43       : HighPC(EndPC), Offset(Offset) {}
     44 
     45   ObjFileAddressRange() : HighPC(0), Offset(0) {}
     46 };
     47 
     48 /// Map LowPC to ObjFileAddressRange.
     49 using RangesTy = std::map<uint64_t, ObjFileAddressRange>;
     50 
     51 /// AddressesMap represents information about valid addresses used
     52 /// by debug information. Valid addresses are those which points to
     53 /// live code sections. i.e. relocations for these addresses point
     54 /// into sections which would be/are placed into resulting binary.
     55 class AddressesMap {
     56 public:
     57   virtual ~AddressesMap();
     58 
     59   /// Returns true if represented addresses are from linked file.
     60   /// Returns false if represented addresses are from not-linked
     61   /// object file.
     62   virtual bool areRelocationsResolved() const = 0;
     63 
     64   /// Checks that there are valid relocations against a .debug_info
     65   /// section.
     66   virtual bool hasValidRelocs() = 0;
     67 
     68   /// Checks that the specified DIE has a DW_AT_Location attribute
     69   /// that references into a live code section.
     70   ///
     71   /// \returns true and sets Info.InDebugMap if it is the case.
     72   virtual bool hasLiveMemoryLocation(const DWARFDie &DIE,
     73                                      CompileUnit::DIEInfo &Info) = 0;
     74 
     75   /// Checks that the specified DIE has a DW_AT_Low_pc attribute
     76   /// that references into a live code section.
     77   ///
     78   /// \returns true and sets Info.InDebugMap if it is the case.
     79   virtual bool hasLiveAddressRange(const DWARFDie &DIE,
     80                                    CompileUnit::DIEInfo &Info) = 0;
     81 
     82   /// Apply the valid relocations to the buffer \p Data, taking into
     83   /// account that Data is at \p BaseOffset in the debug_info section.
     84   ///
     85   /// \returns true whether any reloc has been applied.
     86   virtual bool applyValidRelocs(MutableArrayRef<char> Data, uint64_t BaseOffset,
     87                                 bool IsLittleEndian) = 0;
     88 
     89   /// Relocate the given address offset if a valid relocation exists.
     90   virtual llvm::Expected<uint64_t> relocateIndexedAddr(uint64_t StartOffset,
     91                                                        uint64_t EndOffset) = 0;
     92 
     93   /// Returns all valid functions address ranges(i.e., those ranges
     94   /// which points to sections with code).
     95   virtual RangesTy &getValidAddressRanges() = 0;
     96 
     97   /// Erases all data.
     98   virtual void clear() = 0;
     99 };
    100 
    101 /// DwarfEmitter presents interface to generate all debug info tables.
    102 class DwarfEmitter {
    103 public:
    104   virtual ~DwarfEmitter();
    105 
    106   /// Emit DIE containing warnings.
    107   virtual void emitPaperTrailWarningsDie(DIE &Die) = 0;
    108 
    109   /// Emit section named SecName with data SecData.
    110   virtual void emitSectionContents(StringRef SecData, StringRef SecName) = 0;
    111 
    112   /// Emit the abbreviation table \p Abbrevs to the debug_abbrev section.
    113   virtual void
    114   emitAbbrevs(const std::vector<std::unique_ptr<DIEAbbrev>> &Abbrevs,
    115               unsigned DwarfVersion) = 0;
    116 
    117   /// Emit the string table described by \p Pool.
    118   virtual void emitStrings(const NonRelocatableStringpool &Pool) = 0;
    119 
    120   /// Emit DWARF debug names.
    121   virtual void
    122   emitDebugNames(AccelTable<DWARF5AccelTableStaticData> &Table) = 0;
    123 
    124   /// Emit Apple namespaces accelerator table.
    125   virtual void
    126   emitAppleNamespaces(AccelTable<AppleAccelTableStaticOffsetData> &Table) = 0;
    127 
    128   /// Emit Apple names accelerator table.
    129   virtual void
    130   emitAppleNames(AccelTable<AppleAccelTableStaticOffsetData> &Table) = 0;
    131 
    132   /// Emit Apple Objective-C accelerator table.
    133   virtual void
    134   emitAppleObjc(AccelTable<AppleAccelTableStaticOffsetData> &Table) = 0;
    135 
    136   /// Emit Apple type accelerator table.
    137   virtual void
    138   emitAppleTypes(AccelTable<AppleAccelTableStaticTypeData> &Table) = 0;
    139 
    140   /// Emit debug_ranges for \p FuncRange by translating the
    141   /// original \p Entries.
    142   virtual void emitRangesEntries(
    143       int64_t UnitPcOffset, uint64_t OrigLowPc,
    144       const FunctionIntervals::const_iterator &FuncRange,
    145       const std::vector<DWARFDebugRangeList::RangeListEntry> &Entries,
    146       unsigned AddressSize) = 0;
    147 
    148   /// Emit debug_aranges entries for \p Unit and if \p DoRangesSection is true,
    149   /// also emit the debug_ranges entries for the DW_TAG_compile_unit's
    150   /// DW_AT_ranges attribute.
    151   virtual void emitUnitRangesEntries(CompileUnit &Unit,
    152                                      bool DoRangesSection) = 0;
    153 
    154   /// Copy the debug_line over to the updated binary while unobfuscating the
    155   /// file names and directories.
    156   virtual void translateLineTable(DataExtractor LineData, uint64_t Offset) = 0;
    157 
    158   /// Emit the line table described in \p Rows into the debug_line section.
    159   virtual void emitLineTableForUnit(MCDwarfLineTableParams Params,
    160                                     StringRef PrologueBytes,
    161                                     unsigned MinInstLength,
    162                                     std::vector<DWARFDebugLine::Row> &Rows,
    163                                     unsigned AdddressSize) = 0;
    164 
    165   /// Emit the .debug_pubnames contribution for \p Unit.
    166   virtual void emitPubNamesForUnit(const CompileUnit &Unit) = 0;
    167 
    168   /// Emit the .debug_pubtypes contribution for \p Unit.
    169   virtual void emitPubTypesForUnit(const CompileUnit &Unit) = 0;
    170 
    171   /// Emit a CIE.
    172   virtual void emitCIE(StringRef CIEBytes) = 0;
    173 
    174   /// Emit an FDE with data \p Bytes.
    175   virtual void emitFDE(uint32_t CIEOffset, uint32_t AddreSize, uint32_t Address,
    176                        StringRef Bytes) = 0;
    177 
    178   /// Emit the debug_loc contribution for \p Unit by copying the entries from
    179   /// \p Dwarf and offsetting them. Update the location attributes to point to
    180   /// the new entries.
    181   virtual void emitLocationsForUnit(
    182       const CompileUnit &Unit, DWARFContext &Dwarf,
    183       std::function<void(StringRef, SmallVectorImpl<uint8_t> &)>
    184           ProcessExpr) = 0;
    185 
    186   /// Emit the compilation unit header for \p Unit in the
    187   /// debug_info section.
    188   ///
    189   /// As a side effect, this also switches the current Dwarf version
    190   /// of the MC layer to the one of U.getOrigUnit().
    191   virtual void emitCompileUnitHeader(CompileUnit &Unit,
    192                                      unsigned DwarfVersion) = 0;
    193 
    194   /// Recursively emit the DIE tree rooted at \p Die.
    195   virtual void emitDIE(DIE &Die) = 0;
    196 
    197   /// Returns size of generated .debug_line section.
    198   virtual uint64_t getLineSectionSize() const = 0;
    199 
    200   /// Returns size of generated .debug_frame section.
    201   virtual uint64_t getFrameSectionSize() const = 0;
    202 
    203   /// Returns size of generated .debug_ranges section.
    204   virtual uint64_t getRangesSectionSize() const = 0;
    205 
    206   /// Returns size of generated .debug_info section.
    207   virtual uint64_t getDebugInfoSectionSize() const = 0;
    208 };
    209 
    210 using UnitListTy = std::vector<std::unique_ptr<CompileUnit>>;
    211 
    212 /// this class represents DWARF information for source file
    213 /// and it`s address map.
    214 class DWARFFile {
    215 public:
    216   DWARFFile(StringRef Name, DWARFContext *Dwarf, AddressesMap *Addresses,
    217             const std::vector<std::string> &Warnings)
    218       : FileName(Name), Dwarf(Dwarf), Addresses(Addresses), Warnings(Warnings) {
    219   }
    220 
    221   /// object file name.
    222   StringRef FileName;
    223   /// source DWARF information.
    224   DWARFContext *Dwarf = nullptr;
    225   /// helpful address information(list of valid address ranges, relocations).
    226   AddressesMap *Addresses = nullptr;
    227   /// warnings for object file.
    228   const std::vector<std::string> &Warnings;
    229 };
    230 
    231 typedef std::function<void(const Twine &Warning, StringRef Context,
    232                            const DWARFDie *DIE)>
    233     messageHandler;
    234 typedef std::function<ErrorOr<DWARFFile &>(StringRef ContainerName,
    235                                            StringRef Path)>
    236     objFileLoader;
    237 typedef std::map<std::string, std::string> swiftInterfacesMap;
    238 typedef std::map<std::string, std::string> objectPrefixMap;
    239 
    240 /// The core of the Dwarf linking logic.
    241 ///
    242 /// The generation of the dwarf information from the object files will be
    243 /// driven by the selection of 'root DIEs', which are DIEs that
    244 /// describe variables or functions that resolves to the corresponding
    245 /// code section(and thus have entries in the Addresses map). All the debug
    246 /// information that will be generated(the DIEs, but also the line
    247 /// tables, ranges, ...) is derived from that set of root DIEs.
    248 ///
    249 /// The root DIEs are identified because they contain relocations that
    250 /// points to code section(the low_pc for a function, the location for
    251 /// a variable). These relocations are called ValidRelocs in the
    252 /// AddressesInfo and are gathered as a very first step when we start
    253 /// processing a object file.
    254 class DWARFLinker {
    255 public:
    256   DWARFLinker(DwarfEmitter *Emitter,
    257               DwarfLinkerClient ClientID = DwarfLinkerClient::General)
    258       : TheDwarfEmitter(Emitter), DwarfLinkerClientID(ClientID) {}
    259 
    260   /// Add object file to be linked.
    261   void addObjectFile(DWARFFile &File);
    262 
    263   /// Link debug info for added objFiles. Object
    264   /// files are linked all together.
    265   bool link();
    266 
    267   /// A number of methods setting various linking options:
    268 
    269   /// Allows to generate log of linking process to the standard output.
    270   void setVerbosity(bool Verbose) { Options.Verbose = Verbose; }
    271 
    272   /// Print statistics to standard output.
    273   void setStatistics(bool Statistics) { Options.Statistics = Statistics; }
    274 
    275   /// Do not emit linked dwarf info.
    276   void setNoOutput(bool NoOut) { Options.NoOutput = NoOut; }
    277 
    278   /// Do not unique types according to ODR.
    279   void setNoODR(bool NoODR) { Options.NoODR = NoODR; }
    280 
    281   /// update existing DWARF info(for the linked binary).
    282   void setUpdate(bool Update) { Options.Update = Update; }
    283 
    284   /// Set whether to keep the enclosing function for a static variable.
    285   void setKeepFunctionForStatic(bool KeepFunctionForStatic) {
    286     Options.KeepFunctionForStatic = KeepFunctionForStatic;
    287   }
    288 
    289   /// Use specified number of threads for parallel files linking.
    290   void setNumThreads(unsigned NumThreads) { Options.Threads = NumThreads; }
    291 
    292   /// Set kind of accelerator tables to be generated.
    293   void setAccelTableKind(AccelTableKind Kind) {
    294     Options.TheAccelTableKind = Kind;
    295   }
    296 
    297   /// Set prepend path for clang modules.
    298   void setPrependPath(const std::string &Ppath) { Options.PrependPath = Ppath; }
    299 
    300   /// Set translator which would be used for strings.
    301   void
    302   setStringsTranslator(std::function<StringRef(StringRef)> StringsTranslator) {
    303     this->StringsTranslator = StringsTranslator;
    304   }
    305 
    306   /// Set estimated objects files amount, for preliminary data allocation.
    307   void setEstimatedObjfilesAmount(unsigned ObjFilesNum) {
    308     ObjectContexts.reserve(ObjFilesNum);
    309   }
    310 
    311   /// Set warning handler which would be used to report warnings.
    312   void setWarningHandler(messageHandler Handler) {
    313     Options.WarningHandler = Handler;
    314   }
    315 
    316   /// Set error handler which would be used to report errors.
    317   void setErrorHandler(messageHandler Handler) {
    318     Options.ErrorHandler = Handler;
    319   }
    320 
    321   /// Set object files loader which would be used to load
    322   /// additional objects for splitted dwarf.
    323   void setObjFileLoader(objFileLoader Loader) {
    324     Options.ObjFileLoader = Loader;
    325   }
    326 
    327   /// Set map for Swift interfaces.
    328   void setSwiftInterfacesMap(swiftInterfacesMap *Map) {
    329     Options.ParseableSwiftInterfaces = Map;
    330   }
    331 
    332   /// Set prefix map for objects.
    333   void setObjectPrefixMap(objectPrefixMap *Map) {
    334     Options.ObjectPrefixMap = Map;
    335   }
    336 
    337 private:
    338   /// Flags passed to DwarfLinker::lookForDIEsToKeep
    339   enum TraversalFlags {
    340     TF_Keep = 1 << 0,            ///< Mark the traversed DIEs as kept.
    341     TF_InFunctionScope = 1 << 1, ///< Current scope is a function scope.
    342     TF_DependencyWalk = 1 << 2,  ///< Walking the dependencies of a kept DIE.
    343     TF_ParentWalk = 1 << 3,      ///< Walking up the parents of a kept DIE.
    344     TF_ODR = 1 << 4,             ///< Use the ODR while keeping dependents.
    345     TF_SkipPC = 1 << 5,          ///< Skip all location attributes.
    346   };
    347 
    348   /// The  distinct types of work performed by the work loop.
    349   enum class WorklistItemType {
    350     /// Given a DIE, look for DIEs to be kept.
    351     LookForDIEsToKeep,
    352     /// Given a DIE, look for children of this DIE to be kept.
    353     LookForChildDIEsToKeep,
    354     /// Given a DIE, look for DIEs referencing this DIE to be kept.
    355     LookForRefDIEsToKeep,
    356     /// Given a DIE, look for parent DIEs to be kept.
    357     LookForParentDIEsToKeep,
    358     /// Given a DIE, update its incompleteness based on whether its children are
    359     /// incomplete.
    360     UpdateChildIncompleteness,
    361     /// Given a DIE, update its incompleteness based on whether the DIEs it
    362     /// references are incomplete.
    363     UpdateRefIncompleteness,
    364   };
    365 
    366   /// This class represents an item in the work list. The type defines what kind
    367   /// of work needs to be performed when processing the current item. The flags
    368   /// and info fields are optional based on the type.
    369   struct WorklistItem {
    370     DWARFDie Die;
    371     WorklistItemType Type;
    372     CompileUnit &CU;
    373     unsigned Flags;
    374     union {
    375       const unsigned AncestorIdx;
    376       CompileUnit::DIEInfo *OtherInfo;
    377     };
    378 
    379     WorklistItem(DWARFDie Die, CompileUnit &CU, unsigned Flags,
    380                  WorklistItemType T = WorklistItemType::LookForDIEsToKeep)
    381         : Die(Die), Type(T), CU(CU), Flags(Flags), AncestorIdx(0) {}
    382 
    383     WorklistItem(DWARFDie Die, CompileUnit &CU, WorklistItemType T,
    384                  CompileUnit::DIEInfo *OtherInfo = nullptr)
    385         : Die(Die), Type(T), CU(CU), Flags(0), OtherInfo(OtherInfo) {}
    386 
    387     WorklistItem(unsigned AncestorIdx, CompileUnit &CU, unsigned Flags)
    388         : Die(), Type(WorklistItemType::LookForParentDIEsToKeep), CU(CU),
    389           Flags(Flags), AncestorIdx(AncestorIdx) {}
    390   };
    391 
    392   /// returns true if we need to translate strings.
    393   bool needToTranslateStrings() { return StringsTranslator != nullptr; }
    394 
    395   void reportWarning(const Twine &Warning, const DWARFFile &File,
    396                      const DWARFDie *DIE = nullptr) const {
    397     if (Options.WarningHandler != nullptr)
    398       Options.WarningHandler(Warning, File.FileName, DIE);
    399   }
    400 
    401   void reportError(const Twine &Warning, const DWARFFile &File,
    402                    const DWARFDie *DIE = nullptr) const {
    403     if (Options.ErrorHandler != nullptr)
    404       Options.ErrorHandler(Warning, File.FileName, DIE);
    405   }
    406 
    407   /// Remembers the oldest and newest DWARF version we've seen in a unit.
    408   void updateDwarfVersion(unsigned Version) {
    409     MaxDwarfVersion = std::max(MaxDwarfVersion, Version);
    410     MinDwarfVersion = std::min(MinDwarfVersion, Version);
    411   }
    412 
    413   /// Remembers the kinds of accelerator tables we've seen in a unit.
    414   void updateAccelKind(DWARFContext &Dwarf);
    415 
    416   /// Emit warnings as Dwarf compile units to leave a trail after linking.
    417   bool emitPaperTrailWarnings(const DWARFFile &File,
    418                               OffsetsStringPool &StringPool);
    419 
    420   void copyInvariantDebugSection(DWARFContext &Dwarf);
    421 
    422   /// Keeps track of data associated with one object during linking.
    423   struct LinkContext {
    424     DWARFFile &File;
    425     UnitListTy CompileUnits;
    426     bool Skip = false;
    427 
    428     LinkContext(DWARFFile &File) : File(File) {}
    429 
    430     /// Clear part of the context that's no longer needed when we're done with
    431     /// the debug object.
    432     void clear() {
    433       CompileUnits.clear();
    434       File.Addresses->clear();
    435     }
    436   };
    437 
    438   /// Called before emitting object data
    439   void cleanupAuxiliarryData(LinkContext &Context);
    440 
    441   /// Look at the parent of the given DIE and decide whether they should be
    442   /// kept.
    443   void lookForParentDIEsToKeep(unsigned AncestorIdx, CompileUnit &CU,
    444                                unsigned Flags,
    445                                SmallVectorImpl<WorklistItem> &Worklist);
    446 
    447   /// Look at the children of the given DIE and decide whether they should be
    448   /// kept.
    449   void lookForChildDIEsToKeep(const DWARFDie &Die, CompileUnit &CU,
    450                               unsigned Flags,
    451                               SmallVectorImpl<WorklistItem> &Worklist);
    452 
    453   /// Look at DIEs referenced by the given DIE and decide whether they should be
    454   /// kept. All DIEs referenced though attributes should be kept.
    455   void lookForRefDIEsToKeep(const DWARFDie &Die, CompileUnit &CU,
    456                             unsigned Flags, const UnitListTy &Units,
    457                             const DWARFFile &File,
    458                             SmallVectorImpl<WorklistItem> &Worklist);
    459 
    460   /// \defgroup FindRootDIEs Find DIEs corresponding to Address map entries.
    461   ///
    462   /// @{
    463   /// Recursively walk the \p DIE tree and look for DIEs to
    464   /// keep. Store that information in \p CU's DIEInfo.
    465   ///
    466   /// The return value indicates whether the DIE is incomplete.
    467   void lookForDIEsToKeep(AddressesMap &RelocMgr, RangesTy &Ranges,
    468                          const UnitListTy &Units, const DWARFDie &DIE,
    469                          const DWARFFile &File, CompileUnit &CU,
    470                          unsigned Flags);
    471 
    472   /// If this compile unit is really a skeleton CU that points to a
    473   /// clang module, register it in ClangModules and return true.
    474   ///
    475   /// A skeleton CU is a CU without children, a DW_AT_gnu_dwo_name
    476   /// pointing to the module, and a DW_AT_gnu_dwo_id with the module
    477   /// hash.
    478   bool registerModuleReference(DWARFDie CUDie, const DWARFUnit &Unit,
    479                                const DWARFFile &File,
    480                                OffsetsStringPool &OffsetsStringPool,
    481                                DeclContextTree &ODRContexts,
    482                                uint64_t ModulesEndOffset, unsigned &UnitID,
    483                                bool IsLittleEndian, unsigned Indent = 0,
    484                                bool Quiet = false);
    485 
    486   /// Recursively add the debug info in this clang module .pcm
    487   /// file (and all the modules imported by it in a bottom-up fashion)
    488   /// to Units.
    489   Error loadClangModule(DWARFDie CUDie, StringRef FilePath,
    490                         StringRef ModuleName, uint64_t DwoId,
    491                         const DWARFFile &File,
    492                         OffsetsStringPool &OffsetsStringPool,
    493                         DeclContextTree &ODRContexts, uint64_t ModulesEndOffset,
    494                         unsigned &UnitID, bool IsLittleEndian,
    495                         unsigned Indent = 0, bool Quiet = false);
    496 
    497   /// Mark the passed DIE as well as all the ones it depends on as kept.
    498   void keepDIEAndDependencies(AddressesMap &RelocMgr, RangesTy &Ranges,
    499                               const UnitListTy &Units, const DWARFDie &DIE,
    500                               CompileUnit::DIEInfo &MyInfo,
    501                               const DWARFFile &File, CompileUnit &CU,
    502                               bool UseODR);
    503 
    504   unsigned shouldKeepDIE(AddressesMap &RelocMgr, RangesTy &Ranges,
    505                          const DWARFDie &DIE, const DWARFFile &File,
    506                          CompileUnit &Unit, CompileUnit::DIEInfo &MyInfo,
    507                          unsigned Flags);
    508 
    509   /// Check if a variable describing DIE should be kept.
    510   /// \returns updated TraversalFlags.
    511   unsigned shouldKeepVariableDIE(AddressesMap &RelocMgr, const DWARFDie &DIE,
    512                                  CompileUnit::DIEInfo &MyInfo, unsigned Flags);
    513 
    514   unsigned shouldKeepSubprogramDIE(AddressesMap &RelocMgr, RangesTy &Ranges,
    515                                    const DWARFDie &DIE, const DWARFFile &File,
    516                                    CompileUnit &Unit,
    517                                    CompileUnit::DIEInfo &MyInfo,
    518                                    unsigned Flags);
    519 
    520   /// Resolve the DIE attribute reference that has been extracted in \p
    521   /// RefValue. The resulting DIE might be in another CompileUnit which is
    522   /// stored into \p ReferencedCU. \returns null if resolving fails for any
    523   /// reason.
    524   DWARFDie resolveDIEReference(const DWARFFile &File, const UnitListTy &Units,
    525                                const DWARFFormValue &RefValue,
    526                                const DWARFDie &DIE, CompileUnit *&RefCU);
    527 
    528   /// @}
    529 
    530   /// \defgroup Methods used to link the debug information
    531   ///
    532   /// @{
    533 
    534   struct DWARFLinkerOptions;
    535 
    536   class DIECloner {
    537     DWARFLinker &Linker;
    538     DwarfEmitter *Emitter;
    539     DWARFFile &ObjFile;
    540 
    541     /// Allocator used for all the DIEValue objects.
    542     BumpPtrAllocator &DIEAlloc;
    543 
    544     std::vector<std::unique_ptr<CompileUnit>> &CompileUnits;
    545 
    546     bool Update;
    547 
    548   public:
    549     DIECloner(DWARFLinker &Linker, DwarfEmitter *Emitter, DWARFFile &ObjFile,
    550               BumpPtrAllocator &DIEAlloc,
    551               std::vector<std::unique_ptr<CompileUnit>> &CompileUnits,
    552               bool Update)
    553         : Linker(Linker), Emitter(Emitter), ObjFile(ObjFile),
    554           DIEAlloc(DIEAlloc), CompileUnits(CompileUnits), Update(Update) {}
    555 
    556     /// Recursively clone \p InputDIE into an tree of DIE objects
    557     /// where useless (as decided by lookForDIEsToKeep()) bits have been
    558     /// stripped out and addresses have been rewritten according to the
    559     /// address map.
    560     ///
    561     /// \param OutOffset is the offset the cloned DIE in the output
    562     /// compile unit.
    563     /// \param PCOffset (while cloning a function scope) is the offset
    564     /// applied to the entry point of the function to get the linked address.
    565     /// \param Die the output DIE to use, pass NULL to create one.
    566     /// \returns the root of the cloned tree or null if nothing was selected.
    567     DIE *cloneDIE(const DWARFDie &InputDIE, const DWARFFile &File,
    568                   CompileUnit &U, OffsetsStringPool &StringPool,
    569                   int64_t PCOffset, uint32_t OutOffset, unsigned Flags,
    570                   bool IsLittleEndian, DIE *Die = nullptr);
    571 
    572     /// Construct the output DIE tree by cloning the DIEs we
    573     /// chose to keep above. If there are no valid relocs, then there's
    574     /// nothing to clone/emit.
    575     uint64_t cloneAllCompileUnits(DWARFContext &DwarfContext,
    576                                   const DWARFFile &File,
    577                                   OffsetsStringPool &StringPool,
    578                                   bool IsLittleEndian);
    579 
    580   private:
    581     using AttributeSpec = DWARFAbbreviationDeclaration::AttributeSpec;
    582 
    583     /// Information gathered and exchanged between the various
    584     /// clone*Attributes helpers about the attributes of a particular DIE.
    585     struct AttributesInfo {
    586       /// Names.
    587       DwarfStringPoolEntryRef Name, MangledName, NameWithoutTemplate;
    588 
    589       /// Offsets in the string pool.
    590       uint32_t NameOffset = 0;
    591       uint32_t MangledNameOffset = 0;
    592 
    593       /// Value of AT_low_pc in the input DIE
    594       uint64_t OrigLowPc = std::numeric_limits<uint64_t>::max();
    595 
    596       /// Value of AT_high_pc in the input DIE
    597       uint64_t OrigHighPc = 0;
    598 
    599       /// Value of DW_AT_call_return_pc in the input DIE
    600       uint64_t OrigCallReturnPc = 0;
    601 
    602       /// Value of DW_AT_call_pc in the input DIE
    603       uint64_t OrigCallPc = 0;
    604 
    605       /// Offset to apply to PC addresses inside a function.
    606       int64_t PCOffset = 0;
    607 
    608       /// Does the DIE have a low_pc attribute?
    609       bool HasLowPc = false;
    610 
    611       /// Does the DIE have a ranges attribute?
    612       bool HasRanges = false;
    613 
    614       /// Is this DIE only a declaration?
    615       bool IsDeclaration = false;
    616 
    617       AttributesInfo() = default;
    618     };
    619 
    620     /// Helper for cloneDIE.
    621     unsigned cloneAttribute(DIE &Die, const DWARFDie &InputDIE,
    622                             const DWARFFile &File, CompileUnit &U,
    623                             OffsetsStringPool &StringPool,
    624                             const DWARFFormValue &Val,
    625                             const AttributeSpec AttrSpec, unsigned AttrSize,
    626                             AttributesInfo &AttrInfo, bool IsLittleEndian);
    627 
    628     /// Clone a string attribute described by \p AttrSpec and add
    629     /// it to \p Die.
    630     /// \returns the size of the new attribute.
    631     unsigned cloneStringAttribute(DIE &Die, AttributeSpec AttrSpec,
    632                                   const DWARFFormValue &Val, const DWARFUnit &U,
    633                                   OffsetsStringPool &StringPool,
    634                                   AttributesInfo &Info);
    635 
    636     /// Clone an attribute referencing another DIE and add
    637     /// it to \p Die.
    638     /// \returns the size of the new attribute.
    639     unsigned cloneDieReferenceAttribute(DIE &Die, const DWARFDie &InputDIE,
    640                                         AttributeSpec AttrSpec,
    641                                         unsigned AttrSize,
    642                                         const DWARFFormValue &Val,
    643                                         const DWARFFile &File,
    644                                         CompileUnit &Unit);
    645 
    646     /// Clone a DWARF expression that may be referencing another DIE.
    647     void cloneExpression(DataExtractor &Data, DWARFExpression Expression,
    648                          const DWARFFile &File, CompileUnit &Unit,
    649                          SmallVectorImpl<uint8_t> &OutputBuffer);
    650 
    651     /// Clone an attribute referencing another DIE and add
    652     /// it to \p Die.
    653     /// \returns the size of the new attribute.
    654     unsigned cloneBlockAttribute(DIE &Die, const DWARFFile &File,
    655                                  CompileUnit &Unit, AttributeSpec AttrSpec,
    656                                  const DWARFFormValue &Val, unsigned AttrSize,
    657                                  bool IsLittleEndian);
    658 
    659     /// Clone an attribute referencing another DIE and add
    660     /// it to \p Die.
    661     /// \returns the size of the new attribute.
    662     unsigned cloneAddressAttribute(DIE &Die, AttributeSpec AttrSpec,
    663                                    const DWARFFormValue &Val,
    664                                    const CompileUnit &Unit,
    665                                    AttributesInfo &Info);
    666 
    667     /// Clone a scalar attribute  and add it to \p Die.
    668     /// \returns the size of the new attribute.
    669     unsigned cloneScalarAttribute(DIE &Die, const DWARFDie &InputDIE,
    670                                   const DWARFFile &File, CompileUnit &U,
    671                                   AttributeSpec AttrSpec,
    672                                   const DWARFFormValue &Val, unsigned AttrSize,
    673                                   AttributesInfo &Info);
    674 
    675     /// Get the potential name and mangled name for the entity
    676     /// described by \p Die and store them in \Info if they are not
    677     /// already there.
    678     /// \returns is a name was found.
    679     bool getDIENames(const DWARFDie &Die, AttributesInfo &Info,
    680                      OffsetsStringPool &StringPool, bool StripTemplate = false);
    681 
    682     /// Create a copy of abbreviation Abbrev.
    683     void copyAbbrev(const DWARFAbbreviationDeclaration &Abbrev, bool hasODR);
    684 
    685     uint32_t hashFullyQualifiedName(DWARFDie DIE, CompileUnit &U,
    686                                     const DWARFFile &File,
    687                                     int RecurseDepth = 0);
    688 
    689     /// Helper for cloneDIE.
    690     void addObjCAccelerator(CompileUnit &Unit, const DIE *Die,
    691                             DwarfStringPoolEntryRef Name,
    692                             OffsetsStringPool &StringPool, bool SkipPubSection);
    693   };
    694 
    695   /// Assign an abbreviation number to \p Abbrev
    696   void assignAbbrev(DIEAbbrev &Abbrev);
    697 
    698   /// Compute and emit debug_ranges section for \p Unit, and
    699   /// patch the attributes referencing it.
    700   void patchRangesForUnit(const CompileUnit &Unit, DWARFContext &Dwarf,
    701                           const DWARFFile &File) const;
    702 
    703   /// Generate and emit the DW_AT_ranges attribute for a compile_unit if it had
    704   /// one.
    705   void generateUnitRanges(CompileUnit &Unit) const;
    706 
    707   /// Extract the line tables from the original dwarf, extract the relevant
    708   /// parts according to the linked function ranges and emit the result in the
    709   /// debug_line section.
    710   void patchLineTableForUnit(CompileUnit &Unit, DWARFContext &OrigDwarf,
    711                              const DWARFFile &File);
    712 
    713   /// Emit the accelerator entries for \p Unit.
    714   void emitAcceleratorEntriesForUnit(CompileUnit &Unit);
    715   void emitDwarfAcceleratorEntriesForUnit(CompileUnit &Unit);
    716   void emitAppleAcceleratorEntriesForUnit(CompileUnit &Unit);
    717   void emitPubAcceleratorEntriesForUnit(CompileUnit &Unit);
    718 
    719   /// Patch the frame info for an object file and emit it.
    720   void patchFrameInfoForObject(const DWARFFile &, RangesTy &Ranges,
    721                                DWARFContext &, unsigned AddressSize);
    722 
    723   /// FoldingSet that uniques the abbreviations.
    724   FoldingSet<DIEAbbrev> AbbreviationsSet;
    725 
    726   /// Storage for the unique Abbreviations.
    727   /// This is passed to AsmPrinter::emitDwarfAbbrevs(), thus it cannot be
    728   /// changed to a vector of unique_ptrs.
    729   std::vector<std::unique_ptr<DIEAbbrev>> Abbreviations;
    730 
    731   /// DIELoc objects that need to be destructed (but not freed!).
    732   std::vector<DIELoc *> DIELocs;
    733 
    734   /// DIEBlock objects that need to be destructed (but not freed!).
    735   std::vector<DIEBlock *> DIEBlocks;
    736 
    737   /// Allocator used for all the DIEValue objects.
    738   BumpPtrAllocator DIEAlloc;
    739   /// @}
    740 
    741   DwarfEmitter *TheDwarfEmitter;
    742   std::vector<LinkContext> ObjectContexts;
    743 
    744   unsigned MaxDwarfVersion = 0;
    745   unsigned MinDwarfVersion = std::numeric_limits<unsigned>::max();
    746 
    747   bool AtLeastOneAppleAccelTable = false;
    748   bool AtLeastOneDwarfAccelTable = false;
    749 
    750   /// The CIEs that have been emitted in the output section. The actual CIE
    751   /// data serves a the key to this StringMap, this takes care of comparing the
    752   /// semantics of CIEs defined in different object files.
    753   StringMap<uint32_t> EmittedCIEs;
    754 
    755   /// Offset of the last CIE that has been emitted in the output
    756   /// debug_frame section.
    757   uint32_t LastCIEOffset = 0;
    758 
    759   /// Apple accelerator tables.
    760   AccelTable<DWARF5AccelTableStaticData> DebugNames;
    761   AccelTable<AppleAccelTableStaticOffsetData> AppleNames;
    762   AccelTable<AppleAccelTableStaticOffsetData> AppleNamespaces;
    763   AccelTable<AppleAccelTableStaticOffsetData> AppleObjc;
    764   AccelTable<AppleAccelTableStaticTypeData> AppleTypes;
    765 
    766   /// Mapping the PCM filename to the DwoId.
    767   StringMap<uint64_t> ClangModules;
    768 
    769   DwarfLinkerClient DwarfLinkerClientID;
    770 
    771   std::function<StringRef(StringRef)> StringsTranslator = nullptr;
    772 
    773   /// linking options
    774   struct DWARFLinkerOptions {
    775     /// Generate processing log to the standard output.
    776     bool Verbose = false;
    777 
    778     /// Print statistics.
    779     bool Statistics = false;
    780 
    781     /// Skip emitting output
    782     bool NoOutput = false;
    783 
    784     /// Do not unique types according to ODR
    785     bool NoODR = false;
    786 
    787     /// Update
    788     bool Update = false;
    789 
    790     /// Whether we want a static variable to force us to keep its enclosing
    791     /// function.
    792     bool KeepFunctionForStatic = false;
    793 
    794     /// Number of threads.
    795     unsigned Threads = 1;
    796 
    797     /// The accelerator table kind
    798     AccelTableKind TheAccelTableKind = AccelTableKind::Default;
    799 
    800     /// Prepend path for the clang modules.
    801     std::string PrependPath;
    802 
    803     // warning handler
    804     messageHandler WarningHandler = nullptr;
    805 
    806     // error handler
    807     messageHandler ErrorHandler = nullptr;
    808 
    809     objFileLoader ObjFileLoader = nullptr;
    810 
    811     /// A list of all .swiftinterface files referenced by the debug
    812     /// info, mapping Module name to path on disk. The entries need to
    813     /// be uniqued and sorted and there are only few entries expected
    814     /// per compile unit, which is why this is a std::map.
    815     /// this is dsymutil specific fag.
    816     swiftInterfacesMap *ParseableSwiftInterfaces = nullptr;
    817 
    818     /// A list of remappings to apply to file paths.
    819     objectPrefixMap *ObjectPrefixMap = nullptr;
    820   } Options;
    821 };
    822 
    823 } // end namespace llvm
    824 
    825 #endif // LLVM_DWARFLINKER_DWARFLINKER_H
    826