Jonas Devlieghere | 928fea2 | 2018-06-27 16:13:40 +0000 | [diff] [blame] | 1 | //===- tools/dsymutil/DwarfLinker.h - Dwarf debug info linker ---*- C++ -*-===// |
| 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file is distributed under the University of Illinois Open Source |
| 6 | // License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | |
| 10 | #ifndef LLVM_TOOLS_DSYMUTIL_DWARFLINKER_H |
| 11 | #define LLVM_TOOLS_DSYMUTIL_DWARFLINKER_H |
| 12 | |
| 13 | #include "BinaryHolder.h" |
| 14 | #include "CompileUnit.h" |
| 15 | #include "DebugMap.h" |
| 16 | #include "DeclContext.h" |
| 17 | #include "DwarfStreamer.h" |
| 18 | #include "LinkUtils.h" |
| 19 | #include "llvm/DebugInfo/DWARF/DWARFContext.h" |
| 20 | |
| 21 | namespace llvm { |
| 22 | namespace dsymutil { |
| 23 | |
| 24 | /// Partial address range for debug map objects. Besides an offset, only the |
| 25 | /// HighPC is stored. The structure is stored in a map where the LowPC is the |
| 26 | /// key. |
| 27 | struct DebugMapObjectRange { |
| 28 | /// Function HighPC. |
| 29 | uint64_t HighPC; |
| 30 | /// Offset to apply to the linked address. |
| 31 | int64_t Offset; |
| 32 | |
| 33 | DebugMapObjectRange(uint64_t EndPC, int64_t Offset) |
| 34 | : HighPC(EndPC), Offset(Offset) {} |
| 35 | |
| 36 | DebugMapObjectRange() : HighPC(0), Offset(0) {} |
| 37 | }; |
| 38 | |
| 39 | /// Map LowPC to DebugMapObjectRange. |
| 40 | using RangesTy = std::map<uint64_t, DebugMapObjectRange>; |
| 41 | using UnitListTy = std::vector<std::unique_ptr<CompileUnit>>; |
| 42 | |
| 43 | /// The core of the Dwarf linking logic. |
| 44 | /// |
| 45 | /// The link of the dwarf information from the object files will be |
| 46 | /// driven by the selection of 'root DIEs', which are DIEs that |
| 47 | /// describe variables or functions that are present in the linked |
| 48 | /// binary (and thus have entries in the debug map). All the debug |
| 49 | /// information that will be linked (the DIEs, but also the line |
| 50 | /// tables, ranges, ...) is derived from that set of root DIEs. |
| 51 | /// |
| 52 | /// The root DIEs are identified because they contain relocations that |
| 53 | /// correspond to a debug map entry at specific places (the low_pc for |
| 54 | /// a function, the location for a variable). These relocations are |
| 55 | /// called ValidRelocs in the DwarfLinker and are gathered as a very |
| 56 | /// first step when we start processing a DebugMapObject. |
| 57 | class DwarfLinker { |
| 58 | public: |
Jonas Devlieghere | 9f33bbfe | 2018-06-29 16:51:52 +0000 | [diff] [blame] | 59 | DwarfLinker(raw_fd_ostream &OutFile, BinaryHolder &BinHolder, |
Jonas Devlieghere | 4d3e6c1 | 2018-06-29 16:50:41 +0000 | [diff] [blame] | 60 | const LinkOptions &Options) |
| 61 | : OutFile(OutFile), BinHolder(BinHolder), Options(Options) {} |
Jonas Devlieghere | 928fea2 | 2018-06-27 16:13:40 +0000 | [diff] [blame] | 62 | |
| 63 | /// Link the contents of the DebugMap. |
| 64 | bool link(const DebugMap &); |
| 65 | |
| 66 | void reportWarning(const Twine &Warning, const DebugMapObject &DMO, |
| 67 | const DWARFDie *DIE = nullptr) const; |
| 68 | |
| 69 | private: |
Jonas Devlieghere | 7c767bd | 2018-07-25 23:01:38 +0000 | [diff] [blame] | 70 | /// Remembers the oldest and newest DWARF version we've seen in a unit. |
| 71 | void updateDwarfVersion(unsigned Version) { |
| 72 | MaxDwarfVersion = std::max(MaxDwarfVersion, Version); |
| 73 | MinDwarfVersion = std::min(MinDwarfVersion, Version); |
Jonas Devlieghere | 928fea2 | 2018-06-27 16:13:40 +0000 | [diff] [blame] | 74 | } |
| 75 | |
Jonas Devlieghere | 7c767bd | 2018-07-25 23:01:38 +0000 | [diff] [blame] | 76 | /// Remembers the kinds of accelerator tables we've seen in a unit. |
| 77 | void updateAccelKind(DWARFContext &Dwarf); |
| 78 | |
Jonas Devlieghere | 928fea2 | 2018-06-27 16:13:40 +0000 | [diff] [blame] | 79 | /// Emit warnings as Dwarf compile units to leave a trail after linking. |
| 80 | bool emitPaperTrailWarnings(const DebugMapObject &DMO, const DebugMap &Map, |
| 81 | OffsetsStringPool &StringPool); |
| 82 | |
| 83 | /// Keeps track of relocations. |
| 84 | class RelocationManager { |
| 85 | struct ValidReloc { |
| 86 | uint32_t Offset; |
| 87 | uint32_t Size; |
| 88 | uint64_t Addend; |
| 89 | const DebugMapObject::DebugMapEntry *Mapping; |
| 90 | |
| 91 | ValidReloc(uint32_t Offset, uint32_t Size, uint64_t Addend, |
| 92 | const DebugMapObject::DebugMapEntry *Mapping) |
| 93 | : Offset(Offset), Size(Size), Addend(Addend), Mapping(Mapping) {} |
| 94 | |
| 95 | bool operator<(const ValidReloc &RHS) const { |
| 96 | return Offset < RHS.Offset; |
| 97 | } |
| 98 | }; |
| 99 | |
| 100 | const DwarfLinker &Linker; |
| 101 | |
| 102 | /// The valid relocations for the current DebugMapObject. |
| 103 | /// This vector is sorted by relocation offset. |
| 104 | std::vector<ValidReloc> ValidRelocs; |
| 105 | |
| 106 | /// Index into ValidRelocs of the next relocation to consider. As we walk |
| 107 | /// the DIEs in acsending file offset and as ValidRelocs is sorted by file |
| 108 | /// offset, keeping this index up to date is all we have to do to have a |
| 109 | /// cheap lookup during the root DIE selection and during DIE cloning. |
| 110 | unsigned NextValidReloc = 0; |
| 111 | |
| 112 | public: |
| 113 | RelocationManager(DwarfLinker &Linker) : Linker(Linker) {} |
| 114 | |
| 115 | bool hasValidRelocs() const { return !ValidRelocs.empty(); } |
| 116 | |
| 117 | /// Reset the NextValidReloc counter. |
| 118 | void resetValidRelocs() { NextValidReloc = 0; } |
| 119 | |
| 120 | /// \defgroup FindValidRelocations Translate debug map into a list |
| 121 | /// of relevant relocations |
| 122 | /// |
| 123 | /// @{ |
| 124 | bool findValidRelocsInDebugInfo(const object::ObjectFile &Obj, |
| 125 | const DebugMapObject &DMO); |
| 126 | |
| 127 | bool findValidRelocs(const object::SectionRef &Section, |
| 128 | const object::ObjectFile &Obj, |
| 129 | const DebugMapObject &DMO); |
| 130 | |
| 131 | void findValidRelocsMachO(const object::SectionRef &Section, |
| 132 | const object::MachOObjectFile &Obj, |
| 133 | const DebugMapObject &DMO); |
| 134 | /// @} |
| 135 | |
| 136 | bool hasValidRelocation(uint32_t StartOffset, uint32_t EndOffset, |
| 137 | CompileUnit::DIEInfo &Info); |
| 138 | |
| 139 | bool applyValidRelocs(MutableArrayRef<char> Data, uint32_t BaseOffset, |
| 140 | bool isLittleEndian); |
| 141 | }; |
| 142 | |
| 143 | /// Keeps track of data associated with one object during linking. |
| 144 | struct LinkContext { |
| 145 | DebugMapObject &DMO; |
Jonas Devlieghere | 928fea2 | 2018-06-27 16:13:40 +0000 | [diff] [blame] | 146 | const object::ObjectFile *ObjectFile; |
| 147 | RelocationManager RelocMgr; |
| 148 | std::unique_ptr<DWARFContext> DwarfContext; |
| 149 | RangesTy Ranges; |
| 150 | UnitListTy CompileUnits; |
| 151 | |
Jonas Devlieghere | 4d3e6c1 | 2018-06-29 16:50:41 +0000 | [diff] [blame] | 152 | LinkContext(const DebugMap &Map, DwarfLinker &Linker, DebugMapObject &DMO) |
| 153 | : DMO(DMO), RelocMgr(Linker) { |
Jonas Devlieghere | 928fea2 | 2018-06-27 16:13:40 +0000 | [diff] [blame] | 154 | // Swift ASTs are not object files. |
| 155 | if (DMO.getType() == MachO::N_AST) { |
| 156 | ObjectFile = nullptr; |
| 157 | return; |
| 158 | } |
Jonas Devlieghere | 4d3e6c1 | 2018-06-29 16:50:41 +0000 | [diff] [blame] | 159 | auto ErrOrObj = Linker.loadObject(DMO, Map); |
Jonas Devlieghere | 928fea2 | 2018-06-27 16:13:40 +0000 | [diff] [blame] | 160 | ObjectFile = ErrOrObj ? &*ErrOrObj : nullptr; |
| 161 | DwarfContext = ObjectFile ? DWARFContext::create(*ObjectFile) : nullptr; |
| 162 | } |
| 163 | |
Jonas Devlieghere | 7c767bd | 2018-07-25 23:01:38 +0000 | [diff] [blame] | 164 | /// Clear part of the context that's no longer needed when we're done with |
| 165 | /// the debug object. |
Jonas Devlieghere | 928fea2 | 2018-06-27 16:13:40 +0000 | [diff] [blame] | 166 | void Clear() { |
Jonas Devlieghere | 7c767bd | 2018-07-25 23:01:38 +0000 | [diff] [blame] | 167 | DwarfContext.reset(nullptr); |
Jonas Devlieghere | 928fea2 | 2018-06-27 16:13:40 +0000 | [diff] [blame] | 168 | CompileUnits.clear(); |
| 169 | Ranges.clear(); |
| 170 | } |
| 171 | }; |
| 172 | |
| 173 | /// Called at the start of a debug object link. |
| 174 | void startDebugObject(LinkContext &Context); |
| 175 | |
| 176 | /// Called at the end of a debug object link. |
| 177 | void endDebugObject(LinkContext &Context); |
| 178 | |
| 179 | /// \defgroup FindRootDIEs Find DIEs corresponding to debug map entries. |
| 180 | /// |
| 181 | /// @{ |
| 182 | /// Recursively walk the \p DIE tree and look for DIEs to |
| 183 | /// keep. Store that information in \p CU's DIEInfo. |
| 184 | /// |
| 185 | /// The return value indicates whether the DIE is incomplete. |
Jonas Devlieghere | 3289ee6 | 2018-08-01 13:24:39 +0000 | [diff] [blame] | 186 | void lookForDIEsToKeep(RelocationManager &RelocMgr, RangesTy &Ranges, |
Jonas Devlieghere | ea63d87 | 2018-06-28 15:01:42 +0000 | [diff] [blame] | 187 | const UnitListTy &Units, const DWARFDie &DIE, |
Jonas Devlieghere | 928fea2 | 2018-06-27 16:13:40 +0000 | [diff] [blame] | 188 | const DebugMapObject &DMO, CompileUnit &CU, |
| 189 | unsigned Flags); |
| 190 | |
| 191 | /// If this compile unit is really a skeleton CU that points to a |
| 192 | /// clang module, register it in ClangModules and return true. |
| 193 | /// |
| 194 | /// A skeleton CU is a CU without children, a DW_AT_gnu_dwo_name |
| 195 | /// pointing to the module, and a DW_AT_gnu_dwo_id with the module |
| 196 | /// hash. |
| 197 | bool registerModuleReference(const DWARFDie &CUDie, const DWARFUnit &Unit, |
| 198 | DebugMap &ModuleMap, const DebugMapObject &DMO, |
| 199 | RangesTy &Ranges, |
| 200 | OffsetsStringPool &OffsetsStringPool, |
| 201 | UniquingStringPool &UniquingStringPoolStringPool, |
Jonas Devlieghere | 60c6009 | 2018-09-07 10:29:22 +0000 | [diff] [blame] | 202 | DeclContextTree &ODRContexts, |
| 203 | uint64_t ModulesEndOffset, unsigned &UnitID, |
Adrian Prantl | 5309f16 | 2018-08-24 20:41:08 +0000 | [diff] [blame] | 204 | unsigned Indent = 0, bool Quiet = false); |
Jonas Devlieghere | 928fea2 | 2018-06-27 16:13:40 +0000 | [diff] [blame] | 205 | |
| 206 | /// Recursively add the debug info in this clang module .pcm |
| 207 | /// file (and all the modules imported by it in a bottom-up fashion) |
| 208 | /// to Units. |
| 209 | Error loadClangModule(StringRef Filename, StringRef ModulePath, |
| 210 | StringRef ModuleName, uint64_t DwoId, |
| 211 | DebugMap &ModuleMap, const DebugMapObject &DMO, |
| 212 | RangesTy &Ranges, OffsetsStringPool &OffsetsStringPool, |
| 213 | UniquingStringPool &UniquingStringPool, |
Jonas Devlieghere | 60c6009 | 2018-09-07 10:29:22 +0000 | [diff] [blame] | 214 | DeclContextTree &ODRContexts, uint64_t ModulesEndOffset, |
| 215 | unsigned &UnitID, unsigned Indent = 0, |
| 216 | bool Quiet = false); |
Jonas Devlieghere | 928fea2 | 2018-06-27 16:13:40 +0000 | [diff] [blame] | 217 | |
| 218 | /// Flags passed to DwarfLinker::lookForDIEsToKeep |
| 219 | enum TraversalFlags { |
| 220 | TF_Keep = 1 << 0, ///< Mark the traversed DIEs as kept. |
| 221 | TF_InFunctionScope = 1 << 1, ///< Current scope is a function scope. |
| 222 | TF_DependencyWalk = 1 << 2, ///< Walking the dependencies of a kept DIE. |
| 223 | TF_ParentWalk = 1 << 3, ///< Walking up the parents of a kept DIE. |
| 224 | TF_ODR = 1 << 4, ///< Use the ODR while keeping dependents. |
| 225 | TF_SkipPC = 1 << 5, ///< Skip all location attributes. |
| 226 | }; |
| 227 | |
| 228 | /// Mark the passed DIE as well as all the ones it depends on as kept. |
| 229 | void keepDIEAndDependencies(RelocationManager &RelocMgr, RangesTy &Ranges, |
Jonas Devlieghere | ea63d87 | 2018-06-28 15:01:42 +0000 | [diff] [blame] | 230 | const UnitListTy &Units, const DWARFDie &DIE, |
Jonas Devlieghere | 928fea2 | 2018-06-27 16:13:40 +0000 | [diff] [blame] | 231 | CompileUnit::DIEInfo &MyInfo, |
| 232 | const DebugMapObject &DMO, CompileUnit &CU, |
| 233 | bool UseODR); |
| 234 | |
| 235 | unsigned shouldKeepDIE(RelocationManager &RelocMgr, RangesTy &Ranges, |
| 236 | const DWARFDie &DIE, const DebugMapObject &DMO, |
| 237 | CompileUnit &Unit, CompileUnit::DIEInfo &MyInfo, |
| 238 | unsigned Flags); |
| 239 | |
| 240 | unsigned shouldKeepVariableDIE(RelocationManager &RelocMgr, |
| 241 | const DWARFDie &DIE, CompileUnit &Unit, |
| 242 | CompileUnit::DIEInfo &MyInfo, unsigned Flags); |
| 243 | |
| 244 | unsigned shouldKeepSubprogramDIE(RelocationManager &RelocMgr, |
| 245 | RangesTy &Ranges, const DWARFDie &DIE, |
| 246 | const DebugMapObject &DMO, CompileUnit &Unit, |
| 247 | CompileUnit::DIEInfo &MyInfo, |
| 248 | unsigned Flags); |
| 249 | |
| 250 | bool hasValidRelocation(uint32_t StartOffset, uint32_t EndOffset, |
| 251 | CompileUnit::DIEInfo &Info); |
| 252 | /// @} |
| 253 | |
| 254 | /// \defgroup Linking Methods used to link the debug information |
| 255 | /// |
| 256 | /// @{ |
| 257 | |
| 258 | class DIECloner { |
| 259 | DwarfLinker &Linker; |
| 260 | RelocationManager &RelocMgr; |
| 261 | |
| 262 | /// Allocator used for all the DIEValue objects. |
| 263 | BumpPtrAllocator &DIEAlloc; |
| 264 | |
| 265 | std::vector<std::unique_ptr<CompileUnit>> &CompileUnits; |
| 266 | LinkOptions Options; |
| 267 | |
| 268 | public: |
| 269 | DIECloner(DwarfLinker &Linker, RelocationManager &RelocMgr, |
| 270 | BumpPtrAllocator &DIEAlloc, |
| 271 | std::vector<std::unique_ptr<CompileUnit>> &CompileUnits, |
| 272 | LinkOptions &Options) |
| 273 | : Linker(Linker), RelocMgr(RelocMgr), DIEAlloc(DIEAlloc), |
| 274 | CompileUnits(CompileUnits), Options(Options) {} |
| 275 | |
| 276 | /// Recursively clone \p InputDIE into an tree of DIE objects |
| 277 | /// where useless (as decided by lookForDIEsToKeep()) bits have been |
| 278 | /// stripped out and addresses have been rewritten according to the |
| 279 | /// debug map. |
| 280 | /// |
| 281 | /// \param OutOffset is the offset the cloned DIE in the output |
| 282 | /// compile unit. |
| 283 | /// \param PCOffset (while cloning a function scope) is the offset |
| 284 | /// applied to the entry point of the function to get the linked address. |
| 285 | /// \param Die the output DIE to use, pass NULL to create one. |
| 286 | /// \returns the root of the cloned tree or null if nothing was selected. |
| 287 | DIE *cloneDIE(const DWARFDie &InputDIE, const DebugMapObject &DMO, |
| 288 | CompileUnit &U, OffsetsStringPool &StringPool, |
| 289 | int64_t PCOffset, uint32_t OutOffset, unsigned Flags, |
| 290 | DIE *Die = nullptr); |
| 291 | |
| 292 | /// Construct the output DIE tree by cloning the DIEs we |
| 293 | /// chose to keep above. If there are no valid relocs, then there's |
| 294 | /// nothing to clone/emit. |
| 295 | void cloneAllCompileUnits(DWARFContext &DwarfContext, |
| 296 | const DebugMapObject &DMO, RangesTy &Ranges, |
| 297 | OffsetsStringPool &StringPool); |
| 298 | |
| 299 | private: |
| 300 | using AttributeSpec = DWARFAbbreviationDeclaration::AttributeSpec; |
| 301 | |
| 302 | /// Information gathered and exchanged between the various |
| 303 | /// clone*Attributes helpers about the attributes of a particular DIE. |
| 304 | struct AttributesInfo { |
| 305 | /// Names. |
| 306 | DwarfStringPoolEntryRef Name, MangledName, NameWithoutTemplate; |
| 307 | |
| 308 | /// Offsets in the string pool. |
| 309 | uint32_t NameOffset = 0; |
| 310 | uint32_t MangledNameOffset = 0; |
| 311 | |
| 312 | /// Value of AT_low_pc in the input DIE |
| 313 | uint64_t OrigLowPc = std::numeric_limits<uint64_t>::max(); |
| 314 | |
| 315 | /// Value of AT_high_pc in the input DIE |
| 316 | uint64_t OrigHighPc = 0; |
| 317 | |
| 318 | /// Offset to apply to PC addresses inside a function. |
| 319 | int64_t PCOffset = 0; |
| 320 | |
| 321 | /// Does the DIE have a low_pc attribute? |
| 322 | bool HasLowPc = false; |
| 323 | |
| 324 | /// Does the DIE have a ranges attribute? |
| 325 | bool HasRanges = false; |
| 326 | |
| 327 | /// Is this DIE only a declaration? |
| 328 | bool IsDeclaration = false; |
| 329 | |
| 330 | AttributesInfo() = default; |
| 331 | }; |
| 332 | |
| 333 | /// Helper for cloneDIE. |
| 334 | unsigned cloneAttribute(DIE &Die, const DWARFDie &InputDIE, |
| 335 | const DebugMapObject &DMO, CompileUnit &U, |
| 336 | OffsetsStringPool &StringPool, |
| 337 | const DWARFFormValue &Val, |
| 338 | const AttributeSpec AttrSpec, unsigned AttrSize, |
| 339 | AttributesInfo &AttrInfo); |
| 340 | |
| 341 | /// Clone a string attribute described by \p AttrSpec and add |
| 342 | /// it to \p Die. |
| 343 | /// \returns the size of the new attribute. |
| 344 | unsigned cloneStringAttribute(DIE &Die, AttributeSpec AttrSpec, |
| 345 | const DWARFFormValue &Val, const DWARFUnit &U, |
| 346 | OffsetsStringPool &StringPool, |
| 347 | AttributesInfo &Info); |
| 348 | |
| 349 | /// Clone an attribute referencing another DIE and add |
| 350 | /// it to \p Die. |
| 351 | /// \returns the size of the new attribute. |
| 352 | unsigned cloneDieReferenceAttribute(DIE &Die, const DWARFDie &InputDIE, |
| 353 | AttributeSpec AttrSpec, |
| 354 | unsigned AttrSize, |
| 355 | const DWARFFormValue &Val, |
| 356 | const DebugMapObject &DMO, |
| 357 | CompileUnit &Unit); |
| 358 | |
| 359 | /// Clone an attribute referencing another DIE and add |
| 360 | /// it to \p Die. |
| 361 | /// \returns the size of the new attribute. |
| 362 | unsigned cloneBlockAttribute(DIE &Die, AttributeSpec AttrSpec, |
| 363 | const DWARFFormValue &Val, unsigned AttrSize); |
| 364 | |
| 365 | /// Clone an attribute referencing another DIE and add |
| 366 | /// it to \p Die. |
| 367 | /// \returns the size of the new attribute. |
| 368 | unsigned cloneAddressAttribute(DIE &Die, AttributeSpec AttrSpec, |
| 369 | const DWARFFormValue &Val, |
| 370 | const CompileUnit &Unit, |
| 371 | AttributesInfo &Info); |
| 372 | |
| 373 | /// Clone a scalar attribute and add it to \p Die. |
| 374 | /// \returns the size of the new attribute. |
| 375 | unsigned cloneScalarAttribute(DIE &Die, const DWARFDie &InputDIE, |
| 376 | const DebugMapObject &DMO, CompileUnit &U, |
| 377 | AttributeSpec AttrSpec, |
| 378 | const DWARFFormValue &Val, unsigned AttrSize, |
| 379 | AttributesInfo &Info); |
| 380 | |
| 381 | /// Get the potential name and mangled name for the entity |
| 382 | /// described by \p Die and store them in \Info if they are not |
| 383 | /// already there. |
| 384 | /// \returns is a name was found. |
| 385 | bool getDIENames(const DWARFDie &Die, AttributesInfo &Info, |
| 386 | OffsetsStringPool &StringPool, bool StripTemplate = false); |
| 387 | |
| 388 | /// Create a copy of abbreviation Abbrev. |
| 389 | void copyAbbrev(const DWARFAbbreviationDeclaration &Abbrev, bool hasODR); |
| 390 | |
| 391 | uint32_t hashFullyQualifiedName(DWARFDie DIE, CompileUnit &U, |
| 392 | const DebugMapObject &DMO, |
| 393 | int RecurseDepth = 0); |
| 394 | |
| 395 | /// Helper for cloneDIE. |
| 396 | void addObjCAccelerator(CompileUnit &Unit, const DIE *Die, |
| 397 | DwarfStringPoolEntryRef Name, |
| 398 | OffsetsStringPool &StringPool, bool SkipPubSection); |
| 399 | }; |
| 400 | |
| 401 | /// Assign an abbreviation number to \p Abbrev |
| 402 | void AssignAbbrev(DIEAbbrev &Abbrev); |
| 403 | |
| 404 | /// Compute and emit debug_ranges section for \p Unit, and |
| 405 | /// patch the attributes referencing it. |
| 406 | void patchRangesForUnit(const CompileUnit &Unit, DWARFContext &Dwarf, |
| 407 | const DebugMapObject &DMO) const; |
| 408 | |
| 409 | /// Generate and emit the DW_AT_ranges attribute for a compile_unit if it had |
| 410 | /// one. |
| 411 | void generateUnitRanges(CompileUnit &Unit) const; |
| 412 | |
| 413 | /// Extract the line tables from the original dwarf, extract the relevant |
| 414 | /// parts according to the linked function ranges and emit the result in the |
| 415 | /// debug_line section. |
| 416 | void patchLineTableForUnit(CompileUnit &Unit, DWARFContext &OrigDwarf, |
| 417 | RangesTy &Ranges, const DebugMapObject &DMO); |
| 418 | |
| 419 | /// Emit the accelerator entries for \p Unit. |
| 420 | void emitAcceleratorEntriesForUnit(CompileUnit &Unit); |
Jonas Devlieghere | 7c767bd | 2018-07-25 23:01:38 +0000 | [diff] [blame] | 421 | void emitDwarfAcceleratorEntriesForUnit(CompileUnit &Unit); |
| 422 | void emitAppleAcceleratorEntriesForUnit(CompileUnit &Unit); |
Jonas Devlieghere | 928fea2 | 2018-06-27 16:13:40 +0000 | [diff] [blame] | 423 | |
| 424 | /// Patch the frame info for an object file and emit it. |
| 425 | void patchFrameInfoForObject(const DebugMapObject &, RangesTy &Ranges, |
| 426 | DWARFContext &, unsigned AddressSize); |
| 427 | |
| 428 | /// FoldingSet that uniques the abbreviations. |
| 429 | FoldingSet<DIEAbbrev> AbbreviationsSet; |
| 430 | |
| 431 | /// Storage for the unique Abbreviations. |
| 432 | /// This is passed to AsmPrinter::emitDwarfAbbrevs(), thus it cannot be |
| 433 | /// changed to a vector of unique_ptrs. |
| 434 | std::vector<std::unique_ptr<DIEAbbrev>> Abbreviations; |
| 435 | |
| 436 | /// DIELoc objects that need to be destructed (but not freed!). |
| 437 | std::vector<DIELoc *> DIELocs; |
| 438 | |
| 439 | /// DIEBlock objects that need to be destructed (but not freed!). |
| 440 | std::vector<DIEBlock *> DIEBlocks; |
| 441 | |
| 442 | /// Allocator used for all the DIEValue objects. |
| 443 | BumpPtrAllocator DIEAlloc; |
| 444 | /// @} |
| 445 | |
| 446 | /// \defgroup Helpers Various helper methods. |
| 447 | /// |
| 448 | /// @{ |
| 449 | bool createStreamer(const Triple &TheTriple, raw_fd_ostream &OutFile); |
| 450 | |
| 451 | /// Attempt to load a debug object from disk. |
Jonas Devlieghere | 4d3e6c1 | 2018-06-29 16:50:41 +0000 | [diff] [blame] | 452 | ErrorOr<const object::ObjectFile &> loadObject(const DebugMapObject &Obj, |
Jonas Devlieghere | 928fea2 | 2018-06-27 16:13:40 +0000 | [diff] [blame] | 453 | const DebugMap &Map); |
| 454 | /// @} |
| 455 | |
| 456 | raw_fd_ostream &OutFile; |
Jonas Devlieghere | 9f33bbfe | 2018-06-29 16:51:52 +0000 | [diff] [blame] | 457 | BinaryHolder &BinHolder; |
Jonas Devlieghere | 928fea2 | 2018-06-27 16:13:40 +0000 | [diff] [blame] | 458 | LinkOptions Options; |
| 459 | std::unique_ptr<DwarfStreamer> Streamer; |
| 460 | uint64_t OutputDebugInfoSize; |
Jonas Devlieghere | 7c767bd | 2018-07-25 23:01:38 +0000 | [diff] [blame] | 461 | |
Jonas Devlieghere | 928fea2 | 2018-06-27 16:13:40 +0000 | [diff] [blame] | 462 | unsigned MaxDwarfVersion = 0; |
Jonas Devlieghere | 7c767bd | 2018-07-25 23:01:38 +0000 | [diff] [blame] | 463 | unsigned MinDwarfVersion = std::numeric_limits<unsigned>::max(); |
| 464 | |
| 465 | bool AtLeastOneAppleAccelTable = false; |
| 466 | bool AtLeastOneDwarfAccelTable = false; |
Jonas Devlieghere | 928fea2 | 2018-06-27 16:13:40 +0000 | [diff] [blame] | 467 | |
| 468 | /// The CIEs that have been emitted in the output section. The actual CIE |
| 469 | /// data serves a the key to this StringMap, this takes care of comparing the |
| 470 | /// semantics of CIEs defined in different object files. |
| 471 | StringMap<uint32_t> EmittedCIEs; |
| 472 | |
| 473 | /// Offset of the last CIE that has been emitted in the output |
| 474 | /// debug_frame section. |
| 475 | uint32_t LastCIEOffset = 0; |
| 476 | |
| 477 | /// Apple accelerator tables. |
Jonas Devlieghere | 7c767bd | 2018-07-25 23:01:38 +0000 | [diff] [blame] | 478 | AccelTable<DWARF5AccelTableStaticData> DebugNames; |
Jonas Devlieghere | 928fea2 | 2018-06-27 16:13:40 +0000 | [diff] [blame] | 479 | AccelTable<AppleAccelTableStaticOffsetData> AppleNames; |
| 480 | AccelTable<AppleAccelTableStaticOffsetData> AppleNamespaces; |
| 481 | AccelTable<AppleAccelTableStaticOffsetData> AppleObjc; |
| 482 | AccelTable<AppleAccelTableStaticTypeData> AppleTypes; |
| 483 | |
| 484 | /// Mapping the PCM filename to the DwoId. |
| 485 | StringMap<uint64_t> ClangModules; |
| 486 | |
| 487 | bool ModuleCacheHintDisplayed = false; |
| 488 | bool ArchiveHintDisplayed = false; |
| 489 | }; |
| 490 | |
| 491 | } // end namespace dsymutil |
| 492 | } // end namespace llvm |
| 493 | |
| 494 | #endif // LLVM_TOOLS_DSYMUTIL_DWARFLINKER_H |