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