Frederic Riss | 31e081e | 2014-12-12 17:31:24 +0000 | [diff] [blame] | 1 | //===- tools/dsymutil/DwarfLinker.cpp - Dwarf debug info linker -----------===// |
| 2 | // |
Jonas Devlieghere | 928fea2 | 2018-06-27 16:13:40 +0000 | [diff] [blame] | 3 | // The LLVM Compiler Infrastructure |
Frederic Riss | 31e081e | 2014-12-12 17:31:24 +0000 | [diff] [blame] | 4 | // |
| 5 | // This file is distributed under the University of Illinois Open Source |
| 6 | // License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
Eugene Zelenko | 66f724e | 2017-11-01 21:16:06 +0000 | [diff] [blame] | 9 | |
Jonas Devlieghere | 928fea2 | 2018-06-27 16:13:40 +0000 | [diff] [blame] | 10 | #include "DwarfLinker.h" |
Frederic Riss | b616a18 | 2015-01-28 18:27:01 +0000 | [diff] [blame] | 11 | #include "BinaryHolder.h" |
| 12 | #include "DebugMap.h" |
Jonas Devlieghere | 928fea2 | 2018-06-27 16:13:40 +0000 | [diff] [blame] | 13 | #include "DeclContext.h" |
| 14 | #include "DwarfStreamer.h" |
Frederic Riss | ef8ad01 | 2015-09-02 16:49:13 +0000 | [diff] [blame] | 15 | #include "MachOUtils.h" |
Frederic Riss | fe89383 | 2015-08-26 05:09:52 +0000 | [diff] [blame] | 16 | #include "NonRelocatableStringpool.h" |
Zachary Turner | 19ca2b0 | 2017-06-07 03:48:56 +0000 | [diff] [blame] | 17 | #include "dsymutil.h" |
Eugene Zelenko | 66f724e | 2017-11-01 21:16:06 +0000 | [diff] [blame] | 18 | #include "llvm/ADT/ArrayRef.h" |
Jonas Devlieghere | b936520 | 2018-03-13 14:27:15 +0000 | [diff] [blame] | 19 | #include "llvm/ADT/BitVector.h" |
Eugene Zelenko | 66f724e | 2017-11-01 21:16:06 +0000 | [diff] [blame] | 20 | #include "llvm/ADT/DenseMap.h" |
| 21 | #include "llvm/ADT/DenseMapInfo.h" |
| 22 | #include "llvm/ADT/DenseSet.h" |
| 23 | #include "llvm/ADT/FoldingSet.h" |
| 24 | #include "llvm/ADT/Hashing.h" |
Frederic Riss | 63a0e36 | 2015-03-12 18:45:10 +0000 | [diff] [blame] | 25 | #include "llvm/ADT/IntervalMap.h" |
Eugene Zelenko | 66f724e | 2017-11-01 21:16:06 +0000 | [diff] [blame] | 26 | #include "llvm/ADT/None.h" |
| 27 | #include "llvm/ADT/Optional.h" |
| 28 | #include "llvm/ADT/PointerIntPair.h" |
Frederic Riss | fb14969 | 2015-03-11 18:46:01 +0000 | [diff] [blame] | 29 | #include "llvm/ADT/STLExtras.h" |
Eugene Zelenko | 66f724e | 2017-11-01 21:16:06 +0000 | [diff] [blame] | 30 | #include "llvm/ADT/SmallString.h" |
Zachary Turner | 19ca2b0 | 2017-06-07 03:48:56 +0000 | [diff] [blame] | 31 | #include "llvm/ADT/StringMap.h" |
Eugene Zelenko | 66f724e | 2017-11-01 21:16:06 +0000 | [diff] [blame] | 32 | #include "llvm/ADT/StringRef.h" |
| 33 | #include "llvm/ADT/Triple.h" |
| 34 | #include "llvm/ADT/Twine.h" |
Zachary Turner | 19ca2b0 | 2017-06-07 03:48:56 +0000 | [diff] [blame] | 35 | #include "llvm/BinaryFormat/Dwarf.h" |
Eugene Zelenko | 66f724e | 2017-11-01 21:16:06 +0000 | [diff] [blame] | 36 | #include "llvm/BinaryFormat/MachO.h" |
Jonas Devlieghere | a9aab59 | 2018-01-29 14:52:50 +0000 | [diff] [blame] | 37 | #include "llvm/CodeGen/AccelTable.h" |
Frederic Riss | 2929a7a | 2015-02-28 00:29:11 +0000 | [diff] [blame] | 38 | #include "llvm/CodeGen/AsmPrinter.h" |
Frederic Riss | d0d92e7 | 2015-03-04 22:07:44 +0000 | [diff] [blame] | 39 | #include "llvm/CodeGen/DIE.h" |
Frederic Riss | 309fcf8 | 2015-07-21 22:41:43 +0000 | [diff] [blame] | 40 | #include "llvm/Config/config.h" |
Eugene Zelenko | 66f724e | 2017-11-01 21:16:06 +0000 | [diff] [blame] | 41 | #include "llvm/DebugInfo/DIContext.h" |
| 42 | #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" |
Zachary Turner | 50418a0 | 2015-01-30 18:07:45 +0000 | [diff] [blame] | 43 | #include "llvm/DebugInfo/DWARF/DWARFContext.h" |
Eugene Zelenko | 66f724e | 2017-11-01 21:16:06 +0000 | [diff] [blame] | 44 | #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" |
| 45 | #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h" |
Wolfgang Pieb | daecf94 | 2018-10-31 01:12:58 +0000 | [diff] [blame] | 46 | #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" |
Eugene Zelenko | 66f724e | 2017-11-01 21:16:06 +0000 | [diff] [blame] | 47 | #include "llvm/DebugInfo/DWARF/DWARFDie.h" |
Frederic Riss | 5bdb2cd | 2015-02-13 23:18:29 +0000 | [diff] [blame] | 48 | #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" |
Eugene Zelenko | 66f724e | 2017-11-01 21:16:06 +0000 | [diff] [blame] | 49 | #include "llvm/DebugInfo/DWARF/DWARFSection.h" |
| 50 | #include "llvm/DebugInfo/DWARF/DWARFUnit.h" |
Frederic Riss | 2929a7a | 2015-02-28 00:29:11 +0000 | [diff] [blame] | 51 | #include "llvm/MC/MCAsmBackend.h" |
| 52 | #include "llvm/MC/MCAsmInfo.h" |
Frederic Riss | 2929a7a | 2015-02-28 00:29:11 +0000 | [diff] [blame] | 53 | #include "llvm/MC/MCCodeEmitter.h" |
Zachary Turner | 19ca2b0 | 2017-06-07 03:48:56 +0000 | [diff] [blame] | 54 | #include "llvm/MC/MCContext.h" |
Frederic Riss | e6412a6 | 2015-03-15 20:45:43 +0000 | [diff] [blame] | 55 | #include "llvm/MC/MCDwarf.h" |
Frederic Riss | 2929a7a | 2015-02-28 00:29:11 +0000 | [diff] [blame] | 56 | #include "llvm/MC/MCInstrInfo.h" |
| 57 | #include "llvm/MC/MCObjectFileInfo.h" |
Peter Collingbourne | 17a9814 | 2018-05-18 18:26:45 +0000 | [diff] [blame] | 58 | #include "llvm/MC/MCObjectWriter.h" |
Frederic Riss | 2929a7a | 2015-02-28 00:29:11 +0000 | [diff] [blame] | 59 | #include "llvm/MC/MCRegisterInfo.h" |
Eugene Zelenko | 66f724e | 2017-11-01 21:16:06 +0000 | [diff] [blame] | 60 | #include "llvm/MC/MCSection.h" |
Frederic Riss | 2929a7a | 2015-02-28 00:29:11 +0000 | [diff] [blame] | 61 | #include "llvm/MC/MCStreamer.h" |
Pete Cooper | fc9bfcd | 2015-05-15 22:19:42 +0000 | [diff] [blame] | 62 | #include "llvm/MC/MCSubtargetInfo.h" |
Eugene Zelenko | 66f724e | 2017-11-01 21:16:06 +0000 | [diff] [blame] | 63 | #include "llvm/MC/MCTargetOptions.h" |
Frederic Riss | 16acc91 | 2015-02-13 23:18:22 +0000 | [diff] [blame] | 64 | #include "llvm/Object/MachO.h" |
Eugene Zelenko | 66f724e | 2017-11-01 21:16:06 +0000 | [diff] [blame] | 65 | #include "llvm/Object/ObjectFile.h" |
| 66 | #include "llvm/Object/SymbolicFile.h" |
| 67 | #include "llvm/Support/Allocator.h" |
| 68 | #include "llvm/Support/Casting.h" |
| 69 | #include "llvm/Support/Compiler.h" |
Jonas Devlieghere | a9aab59 | 2018-01-29 14:52:50 +0000 | [diff] [blame] | 70 | #include "llvm/Support/DJB.h" |
Eugene Zelenko | 66f724e | 2017-11-01 21:16:06 +0000 | [diff] [blame] | 71 | #include "llvm/Support/DataExtractor.h" |
| 72 | #include "llvm/Support/Error.h" |
| 73 | #include "llvm/Support/ErrorHandling.h" |
| 74 | #include "llvm/Support/ErrorOr.h" |
| 75 | #include "llvm/Support/FileSystem.h" |
| 76 | #include "llvm/Support/Format.h" |
Frederic Riss | 2e2ed16 | 2015-02-13 23:18:34 +0000 | [diff] [blame] | 77 | #include "llvm/Support/LEB128.h" |
Eugene Zelenko | 66f724e | 2017-11-01 21:16:06 +0000 | [diff] [blame] | 78 | #include "llvm/Support/MathExtras.h" |
| 79 | #include "llvm/Support/MemoryBuffer.h" |
| 80 | #include "llvm/Support/Path.h" |
Frederic Riss | 2929a7a | 2015-02-28 00:29:11 +0000 | [diff] [blame] | 81 | #include "llvm/Support/TargetRegistry.h" |
Jonas Devlieghere | b936520 | 2018-03-13 14:27:15 +0000 | [diff] [blame] | 82 | #include "llvm/Support/ThreadPool.h" |
Jonas Devlieghere | ac330ef | 2017-10-31 13:54:15 +0000 | [diff] [blame] | 83 | #include "llvm/Support/ToolOutputFile.h" |
Jonas Devlieghere | 5baab4c | 2018-04-14 21:36:42 +0000 | [diff] [blame] | 84 | #include "llvm/Support/WithColor.h" |
Eugene Zelenko | 66f724e | 2017-11-01 21:16:06 +0000 | [diff] [blame] | 85 | #include "llvm/Support/raw_ostream.h" |
Frederic Riss | 2929a7a | 2015-02-28 00:29:11 +0000 | [diff] [blame] | 86 | #include "llvm/Target/TargetMachine.h" |
| 87 | #include "llvm/Target/TargetOptions.h" |
Eugene Zelenko | 66f724e | 2017-11-01 21:16:06 +0000 | [diff] [blame] | 88 | #include <algorithm> |
| 89 | #include <cassert> |
| 90 | #include <cinttypes> |
| 91 | #include <climits> |
| 92 | #include <cstdint> |
| 93 | #include <cstdlib> |
| 94 | #include <cstring> |
| 95 | #include <limits> |
| 96 | #include <map> |
Greg Clayton | fc1fc8b | 2016-12-01 18:56:29 +0000 | [diff] [blame] | 97 | #include <memory> |
Frederic Riss | b616a18 | 2015-01-28 18:27:01 +0000 | [diff] [blame] | 98 | #include <string> |
Eugene Zelenko | 66f724e | 2017-11-01 21:16:06 +0000 | [diff] [blame] | 99 | #include <system_error> |
Frederic Riss | e83badb | 2015-03-13 18:35:57 +0000 | [diff] [blame] | 100 | #include <tuple> |
Eugene Zelenko | 66f724e | 2017-11-01 21:16:06 +0000 | [diff] [blame] | 101 | #include <utility> |
| 102 | #include <vector> |
Frederic Riss | 31e081e | 2014-12-12 17:31:24 +0000 | [diff] [blame] | 103 | |
| 104 | namespace llvm { |
| 105 | namespace dsymutil { |
| 106 | |
Adrian Prantl | d6d5ed0 | 2015-09-22 18:50:58 +0000 | [diff] [blame] | 107 | /// Similar to DWARFUnitSection::getUnitForOffset(), but returning our |
| 108 | /// CompileUnit object instead. |
Jonas Devlieghere | ea63d87 | 2018-06-28 15:01:42 +0000 | [diff] [blame] | 109 | static CompileUnit *getUnitForOffset(const UnitListTy &Units, unsigned Offset) { |
Jonas Devlieghere | 3ad0c5a | 2018-02-22 11:32:51 +0000 | [diff] [blame] | 110 | auto CU = std::upper_bound( |
| 111 | Units.begin(), Units.end(), Offset, |
| 112 | [](uint32_t LHS, const std::unique_ptr<CompileUnit> &RHS) { |
| 113 | return LHS < RHS->getOrigUnit().getNextUnitOffset(); |
| 114 | }); |
Greg Clayton | fc1fc8b | 2016-12-01 18:56:29 +0000 | [diff] [blame] | 115 | return CU != Units.end() ? CU->get() : nullptr; |
Frederic Riss | 5bdb2cd | 2015-02-13 23:18:29 +0000 | [diff] [blame] | 116 | } |
| 117 | |
Jonas Devlieghere | 3ad0c5a | 2018-02-22 11:32:51 +0000 | [diff] [blame] | 118 | /// Resolve the DIE attribute reference that has been extracted in \p RefValue. |
| 119 | /// The resulting DIE might be in another CompileUnit which is stored into \p |
| 120 | /// ReferencedCU. \returns null if resolving fails for any reason. |
Jonas Devlieghere | ea63d87 | 2018-06-28 15:01:42 +0000 | [diff] [blame] | 121 | static DWARFDie resolveDIEReference(const DwarfLinker &Linker, |
| 122 | const DebugMapObject &DMO, |
| 123 | const UnitListTy &Units, |
| 124 | const DWARFFormValue &RefValue, |
| 125 | const DWARFUnit &Unit, const DWARFDie &DIE, |
| 126 | CompileUnit *&RefCU) { |
Frederic Riss | 5bdb2cd | 2015-02-13 23:18:29 +0000 | [diff] [blame] | 127 | assert(RefValue.isFormClass(DWARFFormValue::FC_Reference)); |
Greg Clayton | 1a30f4b | 2016-10-31 16:46:02 +0000 | [diff] [blame] | 128 | uint64_t RefOffset = *RefValue.getAsReference(); |
Frederic Riss | 5bdb2cd | 2015-02-13 23:18:29 +0000 | [diff] [blame] | 129 | |
Adrian Prantl | d6d5ed0 | 2015-09-22 18:50:58 +0000 | [diff] [blame] | 130 | if ((RefCU = getUnitForOffset(Units, RefOffset))) |
Jonas Devlieghere | 28b2d0c | 2017-09-21 10:28:33 +0000 | [diff] [blame] | 131 | if (const auto RefDie = RefCU->getOrigUnit().getDIEForOffset(RefOffset)) { |
| 132 | // In a file with broken references, an attribute might point to a NULL |
| 133 | // DIE. |
Jonas Devlieghere | 3ad0c5a | 2018-02-22 11:32:51 +0000 | [diff] [blame] | 134 | if (!RefDie.isNULL()) |
Jonas Devlieghere | 28b2d0c | 2017-09-21 10:28:33 +0000 | [diff] [blame] | 135 | return RefDie; |
| 136 | } |
Frederic Riss | 5bdb2cd | 2015-02-13 23:18:29 +0000 | [diff] [blame] | 137 | |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 138 | Linker.reportWarning("could not find referenced DIE", DMO, &DIE); |
Greg Clayton | adb170f | 2016-12-13 18:25:19 +0000 | [diff] [blame] | 139 | return DWARFDie(); |
Frederic Riss | 5bdb2cd | 2015-02-13 23:18:29 +0000 | [diff] [blame] | 140 | } |
| 141 | |
Jonas Devlieghere | 3ad0c5a | 2018-02-22 11:32:51 +0000 | [diff] [blame] | 142 | /// \returns whether the passed \a Attr type might contain a DIE reference |
| 143 | /// suitable for ODR uniquing. |
Frederic Riss | 309fcf8 | 2015-07-21 22:41:43 +0000 | [diff] [blame] | 144 | static bool isODRAttribute(uint16_t Attr) { |
| 145 | switch (Attr) { |
| 146 | default: |
| 147 | return false; |
| 148 | case dwarf::DW_AT_type: |
| 149 | case dwarf::DW_AT_containing_type: |
| 150 | case dwarf::DW_AT_specification: |
| 151 | case dwarf::DW_AT_abstract_origin: |
| 152 | case dwarf::DW_AT_import: |
| 153 | return true; |
| 154 | } |
| 155 | llvm_unreachable("Improper attribute."); |
| 156 | } |
| 157 | |
Adrian Prantl | c6bf8fa | 2018-08-30 21:21:16 +0000 | [diff] [blame] | 158 | static bool isTypeTag(uint16_t Tag) { |
| 159 | switch (Tag) { |
| 160 | case dwarf::DW_TAG_array_type: |
| 161 | case dwarf::DW_TAG_class_type: |
| 162 | case dwarf::DW_TAG_enumeration_type: |
| 163 | case dwarf::DW_TAG_pointer_type: |
| 164 | case dwarf::DW_TAG_reference_type: |
| 165 | case dwarf::DW_TAG_string_type: |
| 166 | case dwarf::DW_TAG_structure_type: |
| 167 | case dwarf::DW_TAG_subroutine_type: |
| 168 | case dwarf::DW_TAG_typedef: |
| 169 | case dwarf::DW_TAG_union_type: |
| 170 | case dwarf::DW_TAG_ptr_to_member_type: |
| 171 | case dwarf::DW_TAG_set_type: |
| 172 | case dwarf::DW_TAG_subrange_type: |
| 173 | case dwarf::DW_TAG_base_type: |
| 174 | case dwarf::DW_TAG_const_type: |
| 175 | case dwarf::DW_TAG_constant: |
| 176 | case dwarf::DW_TAG_file_type: |
| 177 | case dwarf::DW_TAG_namelist: |
| 178 | case dwarf::DW_TAG_packed_type: |
| 179 | case dwarf::DW_TAG_volatile_type: |
| 180 | case dwarf::DW_TAG_restrict_type: |
| 181 | case dwarf::DW_TAG_atomic_type: |
| 182 | case dwarf::DW_TAG_interface_type: |
| 183 | case dwarf::DW_TAG_unspecified_type: |
| 184 | case dwarf::DW_TAG_shared_type: |
| 185 | return true; |
| 186 | default: |
| 187 | break; |
| 188 | } |
| 189 | return false; |
| 190 | } |
| 191 | |
Greg Clayton | adb170f | 2016-12-13 18:25:19 +0000 | [diff] [blame] | 192 | bool DwarfLinker::DIECloner::getDIENames(const DWARFDie &Die, |
Jonas Devlieghere | a9aab59 | 2018-01-29 14:52:50 +0000 | [diff] [blame] | 193 | AttributesInfo &Info, |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 194 | OffsetsStringPool &StringPool, |
Jonas Devlieghere | a9aab59 | 2018-01-29 14:52:50 +0000 | [diff] [blame] | 195 | bool StripTemplate) { |
| 196 | // This function will be called on DIEs having low_pcs and |
| 197 | // ranges. As getting the name might be more expansive, filter out |
| 198 | // blocks directly. |
| 199 | if (Die.getTag() == dwarf::DW_TAG_lexical_block) |
| 200 | return false; |
| 201 | |
Adrian Prantl | afca6b4 | 2015-09-14 16:46:10 +0000 | [diff] [blame] | 202 | // FIXME: a bit wasteful as the first getName might return the |
Frederic Riss | 991f3ea | 2015-03-16 02:05:10 +0000 | [diff] [blame] | 203 | // short name. |
Jonas Devlieghere | a9aab59 | 2018-01-29 14:52:50 +0000 | [diff] [blame] | 204 | if (!Info.MangledName) |
| 205 | if (const char *MangledName = Die.getName(DINameKind::LinkageName)) |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 206 | Info.MangledName = StringPool.getEntry(MangledName); |
Frederic Riss | 991f3ea | 2015-03-16 02:05:10 +0000 | [diff] [blame] | 207 | |
Jonas Devlieghere | a9aab59 | 2018-01-29 14:52:50 +0000 | [diff] [blame] | 208 | if (!Info.Name) |
| 209 | if (const char *Name = Die.getName(DINameKind::ShortName)) |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 210 | Info.Name = StringPool.getEntry(Name); |
Jonas Devlieghere | a9aab59 | 2018-01-29 14:52:50 +0000 | [diff] [blame] | 211 | |
| 212 | if (StripTemplate && Info.Name && Info.MangledName != Info.Name) { |
| 213 | // FIXME: dsymutil compatibility. This is wrong for operator< |
| 214 | auto Split = Info.Name.getString().split('<'); |
| 215 | if (!Split.second.empty()) |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 216 | Info.NameWithoutTemplate = StringPool.getEntry(Split.first); |
Jonas Devlieghere | a9aab59 | 2018-01-29 14:52:50 +0000 | [diff] [blame] | 217 | } |
Frederic Riss | 991f3ea | 2015-03-16 02:05:10 +0000 | [diff] [blame] | 218 | |
| 219 | return Info.Name || Info.MangledName; |
| 220 | } |
| 221 | |
Jonas Devlieghere | 3ad0c5a | 2018-02-22 11:32:51 +0000 | [diff] [blame] | 222 | /// Report a warning to the user, optionally including information about a |
| 223 | /// specific \p DIE related to the warning. |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 224 | void DwarfLinker::reportWarning(const Twine &Warning, const DebugMapObject &DMO, |
Greg Clayton | adb170f | 2016-12-13 18:25:19 +0000 | [diff] [blame] | 225 | const DWARFDie *DIE) const { |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 226 | StringRef Context = DMO.getObjectFilename(); |
Frederic Riss | a2cd6a5 | 2015-02-28 00:29:01 +0000 | [diff] [blame] | 227 | warn(Warning, Context); |
Frederic Riss | 5bdb2cd | 2015-02-13 23:18:29 +0000 | [diff] [blame] | 228 | |
Frederic Riss | d9a80bd | 2015-02-28 00:29:07 +0000 | [diff] [blame] | 229 | if (!Options.Verbose || !DIE) |
Frederic Riss | 5bdb2cd | 2015-02-13 23:18:29 +0000 | [diff] [blame] | 230 | return; |
| 231 | |
Jonas Devlieghere | d266307 | 2017-09-13 09:43:05 +0000 | [diff] [blame] | 232 | DIDumpOptions DumpOpts; |
Adrian Prantl | ae599aa | 2017-09-20 17:44:00 +0000 | [diff] [blame] | 233 | DumpOpts.RecurseDepth = 0; |
Jonas Devlieghere | d266307 | 2017-09-13 09:43:05 +0000 | [diff] [blame] | 234 | DumpOpts.Verbose = Options.Verbose; |
| 235 | |
Jonas Devlieghere | 5baab4c | 2018-04-14 21:36:42 +0000 | [diff] [blame] | 236 | WithColor::note() << " in DIE:\n"; |
Adrian Prantl | ae599aa | 2017-09-20 17:44:00 +0000 | [diff] [blame] | 237 | DIE->dump(errs(), 6 /* Indent */, DumpOpts); |
Frederic Riss | 5bdb2cd | 2015-02-13 23:18:29 +0000 | [diff] [blame] | 238 | } |
| 239 | |
Benjamin Kramer | 36538ff | 2016-06-08 19:09:22 +0000 | [diff] [blame] | 240 | bool DwarfLinker::createStreamer(const Triple &TheTriple, |
Rafael Espindola | 5feaa63 | 2017-11-15 20:55:53 +0000 | [diff] [blame] | 241 | raw_fd_ostream &OutFile) { |
Frederic Riss | 2929a7a | 2015-02-28 00:29:11 +0000 | [diff] [blame] | 242 | if (Options.NoOutput) |
| 243 | return true; |
| 244 | |
Jonas Devlieghere | a5d860c | 2018-07-09 16:58:48 +0000 | [diff] [blame] | 245 | Streamer = llvm::make_unique<DwarfStreamer>(OutFile, Options); |
Rafael Espindola | 5feaa63 | 2017-11-15 20:55:53 +0000 | [diff] [blame] | 246 | return Streamer->init(TheTriple); |
Frederic Riss | 2929a7a | 2015-02-28 00:29:11 +0000 | [diff] [blame] | 247 | } |
| 248 | |
Adrian Prantl | 43df582 | 2015-09-23 17:35:52 +0000 | [diff] [blame] | 249 | /// Recursive helper to build the global DeclContext information and |
| 250 | /// gather the child->parent relationships in the original compile unit. |
| 251 | /// |
| 252 | /// \return true when this DIE and all of its children are only |
| 253 | /// forward declarations to types defined in external clang modules |
| 254 | /// (i.e., forward declarations that are children of a DW_TAG_module). |
Jonas Devlieghere | 3ad0c5a | 2018-02-22 11:32:51 +0000 | [diff] [blame] | 255 | static bool analyzeContextInfo(const DWARFDie &DIE, unsigned ParentIdx, |
| 256 | CompileUnit &CU, DeclContext *CurrentDeclContext, |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 257 | UniquingStringPool &StringPool, |
Adrian Prantl | 43df582 | 2015-09-23 17:35:52 +0000 | [diff] [blame] | 258 | DeclContextTree &Contexts, |
Jonas Devlieghere | 60c6009 | 2018-09-07 10:29:22 +0000 | [diff] [blame] | 259 | uint64_t ModulesEndOffset, |
Adrian Prantl | 54a3f63 | 2015-09-23 20:44:37 +0000 | [diff] [blame] | 260 | bool InImportedModule = false) { |
Frederic Riss | 3ddec31 | 2015-01-28 22:15:14 +0000 | [diff] [blame] | 261 | unsigned MyIdx = CU.getOrigUnit().getDIEIndex(DIE); |
Frederic Riss | 309fcf8 | 2015-07-21 22:41:43 +0000 | [diff] [blame] | 262 | CompileUnit::DIEInfo &Info = CU.getInfo(MyIdx); |
| 263 | |
Adrian Prantl | 43df582 | 2015-09-23 17:35:52 +0000 | [diff] [blame] | 264 | // Clang imposes an ODR on modules(!) regardless of the language: |
| 265 | // "The module-id should consist of only a single identifier, |
| 266 | // which provides the name of the module being defined. Each |
| 267 | // module shall have a single definition." |
| 268 | // |
| 269 | // This does not extend to the types inside the modules: |
| 270 | // "[I]n C, this implies that if two structs are defined in |
| 271 | // different submodules with the same name, those two types are |
| 272 | // distinct types (but may be compatible types if their |
| 273 | // definitions match)." |
| 274 | // |
| 275 | // We treat non-C++ modules like namespaces for this reason. |
Greg Clayton | adb170f | 2016-12-13 18:25:19 +0000 | [diff] [blame] | 276 | if (DIE.getTag() == dwarf::DW_TAG_module && ParentIdx == 0 && |
Adrian Prantl | 7f359b2 | 2017-09-30 00:22:24 +0000 | [diff] [blame] | 277 | dwarf::toString(DIE.find(dwarf::DW_AT_name), "") != |
| 278 | CU.getClangModuleName()) { |
Adrian Prantl | 54a3f63 | 2015-09-23 20:44:37 +0000 | [diff] [blame] | 279 | InImportedModule = true; |
| 280 | } |
Adrian Prantl | 43df582 | 2015-09-23 17:35:52 +0000 | [diff] [blame] | 281 | |
Frederic Riss | 309fcf8 | 2015-07-21 22:41:43 +0000 | [diff] [blame] | 282 | Info.ParentIdx = ParentIdx; |
Adrian Prantl | bc01088 | 2015-10-02 00:27:08 +0000 | [diff] [blame] | 283 | bool InClangModule = CU.isClangModule() || InImportedModule; |
| 284 | if (CU.hasODR() || InClangModule) { |
Frederic Riss | 309fcf8 | 2015-07-21 22:41:43 +0000 | [diff] [blame] | 285 | if (CurrentDeclContext) { |
Adrian Prantl | bc01088 | 2015-10-02 00:27:08 +0000 | [diff] [blame] | 286 | auto PtrInvalidPair = Contexts.getChildDeclContext( |
| 287 | *CurrentDeclContext, DIE, CU, StringPool, InClangModule); |
Frederic Riss | 309fcf8 | 2015-07-21 22:41:43 +0000 | [diff] [blame] | 288 | CurrentDeclContext = PtrInvalidPair.getPointer(); |
| 289 | Info.Ctxt = |
| 290 | PtrInvalidPair.getInt() ? nullptr : PtrInvalidPair.getPointer(); |
Adrian Prantl | 64c7aa6 | 2017-07-21 02:07:33 +0000 | [diff] [blame] | 291 | if (Info.Ctxt) |
| 292 | Info.Ctxt->setDefinedInClangModule(InClangModule); |
Frederic Riss | 309fcf8 | 2015-07-21 22:41:43 +0000 | [diff] [blame] | 293 | } else |
| 294 | Info.Ctxt = CurrentDeclContext = nullptr; |
| 295 | } |
Frederic Riss | 3ddec31 | 2015-01-28 22:15:14 +0000 | [diff] [blame] | 296 | |
Adrian Prantl | 54a3f63 | 2015-09-23 20:44:37 +0000 | [diff] [blame] | 297 | Info.Prune = InImportedModule; |
Greg Clayton | adb170f | 2016-12-13 18:25:19 +0000 | [diff] [blame] | 298 | if (DIE.hasChildren()) |
Jonas Devlieghere | 3ad0c5a | 2018-02-22 11:32:51 +0000 | [diff] [blame] | 299 | for (auto Child : DIE.children()) |
Jonas Devlieghere | 60c6009 | 2018-09-07 10:29:22 +0000 | [diff] [blame] | 300 | Info.Prune &= |
| 301 | analyzeContextInfo(Child, MyIdx, CU, CurrentDeclContext, StringPool, |
| 302 | Contexts, ModulesEndOffset, InImportedModule); |
Adrian Prantl | 43df582 | 2015-09-23 17:35:52 +0000 | [diff] [blame] | 303 | |
| 304 | // Prune this DIE if it is either a forward declaration inside a |
| 305 | // DW_TAG_module or a DW_TAG_module that contains nothing but |
| 306 | // forward declarations. |
Jonas Devlieghere | 3ad0c5a | 2018-02-22 11:32:51 +0000 | [diff] [blame] | 307 | Info.Prune &= (DIE.getTag() == dwarf::DW_TAG_module) || |
Adrian Prantl | c6bf8fa | 2018-08-30 21:21:16 +0000 | [diff] [blame] | 308 | (isTypeTag(DIE.getTag()) && |
| 309 | dwarf::toUnsigned(DIE.find(dwarf::DW_AT_declaration), 0)); |
Adrian Prantl | 43df582 | 2015-09-23 17:35:52 +0000 | [diff] [blame] | 310 | |
Jonas Devlieghere | 60c6009 | 2018-09-07 10:29:22 +0000 | [diff] [blame] | 311 | // Only prune forward declarations inside a DW_TAG_module for which a |
| 312 | // definition exists elsewhere. |
| 313 | if (ModulesEndOffset == 0) |
| 314 | Info.Prune &= Info.Ctxt && Info.Ctxt->getCanonicalDIEOffset(); |
| 315 | else |
| 316 | Info.Prune &= Info.Ctxt && Info.Ctxt->getCanonicalDIEOffset() > 0 && |
| 317 | Info.Ctxt->getCanonicalDIEOffset() <= ModulesEndOffset; |
Adrian Prantl | fce2219 | 2015-10-05 23:11:20 +0000 | [diff] [blame] | 318 | |
Adrian Prantl | 43df582 | 2015-09-23 17:35:52 +0000 | [diff] [blame] | 319 | return Info.Prune; |
Jonas Devlieghere | 60c6009 | 2018-09-07 10:29:22 +0000 | [diff] [blame] | 320 | } // namespace dsymutil |
Frederic Riss | 3ddec31 | 2015-01-28 22:15:14 +0000 | [diff] [blame] | 321 | |
Frederic Riss | 2e2ed16 | 2015-02-13 23:18:34 +0000 | [diff] [blame] | 322 | static bool dieNeedsChildrenToBeMeaningful(uint32_t Tag) { |
| 323 | switch (Tag) { |
| 324 | default: |
| 325 | return false; |
| 326 | case dwarf::DW_TAG_subprogram: |
| 327 | case dwarf::DW_TAG_lexical_block: |
| 328 | case dwarf::DW_TAG_subroutine_type: |
| 329 | case dwarf::DW_TAG_structure_type: |
| 330 | case dwarf::DW_TAG_class_type: |
| 331 | case dwarf::DW_TAG_union_type: |
| 332 | return true; |
| 333 | } |
| 334 | llvm_unreachable("Invalid Tag"); |
| 335 | } |
| 336 | |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 337 | void DwarfLinker::startDebugObject(LinkContext &Context) { |
Frederic Riss | e6412a6 | 2015-03-15 20:45:43 +0000 | [diff] [blame] | 338 | // Iterate over the debug map entries and put all the ones that are |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 339 | // functions (because they have a size) into the Ranges map. This map is |
| 340 | // very similar to the FunctionRanges that are stored in each unit, with 2 |
| 341 | // notable differences: |
| 342 | // |
| 343 | // 1. Obviously this one is global, while the other ones are per-unit. |
| 344 | // |
| 345 | // 2. This one contains not only the functions described in the DIE |
| 346 | // tree, but also the ones that are only in the debug map. |
| 347 | // |
| 348 | // The latter information is required to reproduce dsymutil's logic while |
| 349 | // linking line tables. The cases where this information matters look like |
| 350 | // bugs that need to be investigated, but for now we need to reproduce |
| 351 | // dsymutil's behavior. |
Frederic Riss | e6412a6 | 2015-03-15 20:45:43 +0000 | [diff] [blame] | 352 | // FIXME: Once we understood exactly if that information is needed, |
| 353 | // maybe totally remove this (or try to use it to do a real |
| 354 | // -gline-tables-only on Darwin. |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 355 | for (const auto &Entry : Context.DMO.symbols()) { |
Frederic Riss | e6412a6 | 2015-03-15 20:45:43 +0000 | [diff] [blame] | 356 | const auto &Mapping = Entry.getValue(); |
Frederic Riss | c5413fc | 2016-01-31 04:29:22 +0000 | [diff] [blame] | 357 | if (Mapping.Size && Mapping.ObjectAddress) |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 358 | Context.Ranges[*Mapping.ObjectAddress] = DebugMapObjectRange( |
Frederic Riss | c5413fc | 2016-01-31 04:29:22 +0000 | [diff] [blame] | 359 | *Mapping.ObjectAddress + Mapping.Size, |
| 360 | int64_t(Mapping.BinaryAddress) - *Mapping.ObjectAddress); |
Frederic Riss | e6412a6 | 2015-03-15 20:45:43 +0000 | [diff] [blame] | 361 | } |
Frederic Riss | 3ddec31 | 2015-01-28 22:15:14 +0000 | [diff] [blame] | 362 | } |
| 363 | |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 364 | void DwarfLinker::endDebugObject(LinkContext &Context) { |
| 365 | Context.Clear(); |
Jonas Devlieghere | 7c767bd | 2018-07-25 23:01:38 +0000 | [diff] [blame] | 366 | |
Aaron Ballman | 9cd2a38 | 2015-06-26 14:51:22 +0000 | [diff] [blame] | 367 | for (auto I = DIEBlocks.begin(), E = DIEBlocks.end(); I != E; ++I) |
| 368 | (*I)->~DIEBlock(); |
| 369 | for (auto I = DIELocs.begin(), E = DIELocs.end(); I != E; ++I) |
| 370 | (*I)->~DIELoc(); |
Frederic Riss | d0d92e7 | 2015-03-04 22:07:44 +0000 | [diff] [blame] | 371 | |
| 372 | DIEBlocks.clear(); |
| 373 | DIELocs.clear(); |
| 374 | DIEAlloc.Reset(); |
Frederic Riss | 16acc91 | 2015-02-13 23:18:22 +0000 | [diff] [blame] | 375 | } |
| 376 | |
Frederic Riss | 870f3ff | 2016-02-01 04:43:14 +0000 | [diff] [blame] | 377 | static bool isMachOPairedReloc(uint64_t RelocType, uint64_t Arch) { |
| 378 | switch (Arch) { |
| 379 | case Triple::x86: |
| 380 | return RelocType == MachO::GENERIC_RELOC_SECTDIFF || |
| 381 | RelocType == MachO::GENERIC_RELOC_LOCAL_SECTDIFF; |
| 382 | case Triple::x86_64: |
| 383 | return RelocType == MachO::X86_64_RELOC_SUBTRACTOR; |
| 384 | case Triple::arm: |
| 385 | case Triple::thumb: |
| 386 | return RelocType == MachO::ARM_RELOC_SECTDIFF || |
| 387 | RelocType == MachO::ARM_RELOC_LOCAL_SECTDIFF || |
| 388 | RelocType == MachO::ARM_RELOC_HALF || |
| 389 | RelocType == MachO::ARM_RELOC_HALF_SECTDIFF; |
| 390 | case Triple::aarch64: |
| 391 | return RelocType == MachO::ARM64_RELOC_SUBTRACTOR; |
| 392 | default: |
| 393 | return false; |
| 394 | } |
| 395 | } |
| 396 | |
Adrian Prantl | 90d56f0 | 2017-07-21 16:51:17 +0000 | [diff] [blame] | 397 | /// Iterate over the relocations of the given \p Section and |
Frederic Riss | 16acc91 | 2015-02-13 23:18:22 +0000 | [diff] [blame] | 398 | /// store the ones that correspond to debug map entries into the |
| 399 | /// ValidRelocs array. |
Jonas Devlieghere | 3ad0c5a | 2018-02-22 11:32:51 +0000 | [diff] [blame] | 400 | void DwarfLinker::RelocationManager::findValidRelocsMachO( |
| 401 | const object::SectionRef &Section, const object::MachOObjectFile &Obj, |
| 402 | const DebugMapObject &DMO) { |
Frederic Riss | 16acc91 | 2015-02-13 23:18:22 +0000 | [diff] [blame] | 403 | StringRef Contents; |
| 404 | Section.getContents(Contents); |
| 405 | DataExtractor Data(Contents, Obj.isLittleEndian(), 0); |
Frederic Riss | 870f3ff | 2016-02-01 04:43:14 +0000 | [diff] [blame] | 406 | bool SkipNext = false; |
Frederic Riss | 16acc91 | 2015-02-13 23:18:22 +0000 | [diff] [blame] | 407 | |
| 408 | for (const object::RelocationRef &Reloc : Section.relocations()) { |
Frederic Riss | 870f3ff | 2016-02-01 04:43:14 +0000 | [diff] [blame] | 409 | if (SkipNext) { |
| 410 | SkipNext = false; |
| 411 | continue; |
| 412 | } |
| 413 | |
Frederic Riss | 16acc91 | 2015-02-13 23:18:22 +0000 | [diff] [blame] | 414 | object::DataRefImpl RelocDataRef = Reloc.getRawDataRefImpl(); |
| 415 | MachO::any_relocation_info MachOReloc = Obj.getRelocation(RelocDataRef); |
Frederic Riss | 870f3ff | 2016-02-01 04:43:14 +0000 | [diff] [blame] | 416 | |
| 417 | if (isMachOPairedReloc(Obj.getAnyRelocationType(MachOReloc), |
| 418 | Obj.getArch())) { |
| 419 | SkipNext = true; |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 420 | Linker.reportWarning("unsupported relocation in debug_info section.", |
| 421 | DMO); |
Frederic Riss | 870f3ff | 2016-02-01 04:43:14 +0000 | [diff] [blame] | 422 | continue; |
| 423 | } |
| 424 | |
Frederic Riss | 16acc91 | 2015-02-13 23:18:22 +0000 | [diff] [blame] | 425 | unsigned RelocSize = 1 << Obj.getAnyRelocationLength(MachOReloc); |
Rafael Espindola | ff67629 | 2015-06-29 23:29:12 +0000 | [diff] [blame] | 426 | uint64_t Offset64 = Reloc.getOffset(); |
| 427 | if ((RelocSize != 4 && RelocSize != 8)) { |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 428 | Linker.reportWarning("unsupported relocation in debug_info section.", |
| 429 | DMO); |
Frederic Riss | 16acc91 | 2015-02-13 23:18:22 +0000 | [diff] [blame] | 430 | continue; |
| 431 | } |
| 432 | uint32_t Offset = Offset64; |
| 433 | // Mach-o uses REL relocations, the addend is at the relocation offset. |
| 434 | uint64_t Addend = Data.getUnsigned(&Offset, RelocSize); |
Frederic Riss | f768b25 | 2016-02-01 03:44:22 +0000 | [diff] [blame] | 435 | uint64_t SymAddress; |
| 436 | int64_t SymOffset; |
| 437 | |
| 438 | if (Obj.isRelocationScattered(MachOReloc)) { |
| 439 | // The address of the base symbol for scattered relocations is |
| 440 | // stored in the reloc itself. The actual addend will store the |
| 441 | // base address plus the offset. |
| 442 | SymAddress = Obj.getScatteredRelocationValue(MachOReloc); |
| 443 | SymOffset = int64_t(Addend) - SymAddress; |
| 444 | } else { |
| 445 | SymAddress = Addend; |
| 446 | SymOffset = 0; |
| 447 | } |
Frederic Riss | 16acc91 | 2015-02-13 23:18:22 +0000 | [diff] [blame] | 448 | |
| 449 | auto Sym = Reloc.getSymbol(); |
| 450 | if (Sym != Obj.symbol_end()) { |
Kevin Enderby | 813e0cf | 2016-04-20 21:24:34 +0000 | [diff] [blame] | 451 | Expected<StringRef> SymbolName = Sym->getName(); |
Rafael Espindola | 8a80641 | 2015-07-02 20:55:21 +0000 | [diff] [blame] | 452 | if (!SymbolName) { |
Kevin Enderby | 813e0cf | 2016-04-20 21:24:34 +0000 | [diff] [blame] | 453 | consumeError(SymbolName.takeError()); |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 454 | Linker.reportWarning("error getting relocation symbol name.", DMO); |
Frederic Riss | 16acc91 | 2015-02-13 23:18:22 +0000 | [diff] [blame] | 455 | continue; |
| 456 | } |
Rafael Espindola | 8a80641 | 2015-07-02 20:55:21 +0000 | [diff] [blame] | 457 | if (const auto *Mapping = DMO.lookupSymbol(*SymbolName)) |
Frederic Riss | 16acc91 | 2015-02-13 23:18:22 +0000 | [diff] [blame] | 458 | ValidRelocs.emplace_back(Offset64, RelocSize, Addend, Mapping); |
Frederic Riss | f768b25 | 2016-02-01 03:44:22 +0000 | [diff] [blame] | 459 | } else if (const auto *Mapping = DMO.lookupObjectAddress(SymAddress)) { |
Jonas Devlieghere | 3ad0c5a | 2018-02-22 11:32:51 +0000 | [diff] [blame] | 460 | // Do not store the addend. The addend was the address of the symbol in |
| 461 | // the object file, the address in the binary that is stored in the debug |
| 462 | // map doesn't need to be offset. |
Frederic Riss | f768b25 | 2016-02-01 03:44:22 +0000 | [diff] [blame] | 463 | ValidRelocs.emplace_back(Offset64, RelocSize, SymOffset, Mapping); |
Frederic Riss | 16acc91 | 2015-02-13 23:18:22 +0000 | [diff] [blame] | 464 | } |
| 465 | } |
| 466 | } |
| 467 | |
Adrian Prantl | 90d56f0 | 2017-07-21 16:51:17 +0000 | [diff] [blame] | 468 | /// Dispatch the valid relocation finding logic to the |
Frederic Riss | 16acc91 | 2015-02-13 23:18:22 +0000 | [diff] [blame] | 469 | /// appropriate handler depending on the object file format. |
Adrian Prantl | 0a0a960 | 2015-09-11 23:45:30 +0000 | [diff] [blame] | 470 | bool DwarfLinker::RelocationManager::findValidRelocs( |
| 471 | const object::SectionRef &Section, const object::ObjectFile &Obj, |
| 472 | const DebugMapObject &DMO) { |
Frederic Riss | 16acc91 | 2015-02-13 23:18:22 +0000 | [diff] [blame] | 473 | // Dispatch to the right handler depending on the file type. |
| 474 | if (auto *MachOObj = dyn_cast<object::MachOObjectFile>(&Obj)) |
| 475 | findValidRelocsMachO(Section, *MachOObj, DMO); |
| 476 | else |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 477 | Linker.reportWarning( |
| 478 | Twine("unsupported object file type: ") + Obj.getFileName(), DMO); |
Frederic Riss | 16acc91 | 2015-02-13 23:18:22 +0000 | [diff] [blame] | 479 | |
| 480 | if (ValidRelocs.empty()) |
| 481 | return false; |
| 482 | |
| 483 | // Sort the relocations by offset. We will walk the DIEs linearly in |
| 484 | // the file, this allows us to just keep an index in the relocation |
| 485 | // array that we advance during our walk, rather than resorting to |
| 486 | // some associative container. See DwarfLinker::NextValidReloc. |
Fangrui Song | 3b35e17 | 2018-09-27 02:13:45 +0000 | [diff] [blame] | 487 | llvm::sort(ValidRelocs); |
Frederic Riss | 16acc91 | 2015-02-13 23:18:22 +0000 | [diff] [blame] | 488 | return true; |
| 489 | } |
| 490 | |
Adrian Prantl | 90d56f0 | 2017-07-21 16:51:17 +0000 | [diff] [blame] | 491 | /// Look for relocations in the debug_info section that match |
Frederic Riss | 16acc91 | 2015-02-13 23:18:22 +0000 | [diff] [blame] | 492 | /// entries in the debug map. These relocations will drive the Dwarf |
| 493 | /// link by indicating which DIEs refer to symbols present in the |
| 494 | /// linked binary. |
Jonas Devlieghere | 3ad0c5a | 2018-02-22 11:32:51 +0000 | [diff] [blame] | 495 | /// \returns whether there are any valid relocations in the debug info. |
| 496 | bool DwarfLinker::RelocationManager::findValidRelocsInDebugInfo( |
| 497 | const object::ObjectFile &Obj, const DebugMapObject &DMO) { |
Frederic Riss | 16acc91 | 2015-02-13 23:18:22 +0000 | [diff] [blame] | 498 | // Find the debug_info section. |
| 499 | for (const object::SectionRef &Section : Obj.sections()) { |
| 500 | StringRef SectionName; |
| 501 | Section.getName(SectionName); |
| 502 | SectionName = SectionName.substr(SectionName.find_first_not_of("._")); |
| 503 | if (SectionName != "debug_info") |
| 504 | continue; |
| 505 | return findValidRelocs(Section, Obj, DMO); |
| 506 | } |
| 507 | return false; |
| 508 | } |
Frederic Riss | 3ddec31 | 2015-01-28 22:15:14 +0000 | [diff] [blame] | 509 | |
Adrian Prantl | 90d56f0 | 2017-07-21 16:51:17 +0000 | [diff] [blame] | 510 | /// Checks that there is a relocation against an actual debug |
Frederic Riss | 2e2ed16 | 2015-02-13 23:18:34 +0000 | [diff] [blame] | 511 | /// map entry between \p StartOffset and \p NextOffset. |
| 512 | /// |
| 513 | /// This function must be called with offsets in strictly ascending |
| 514 | /// order because it never looks back at relocations it already 'went past'. |
| 515 | /// \returns true and sets Info.InDebugMap if it is the case. |
Jonas Devlieghere | 3ad0c5a | 2018-02-22 11:32:51 +0000 | [diff] [blame] | 516 | bool DwarfLinker::RelocationManager::hasValidRelocation( |
| 517 | uint32_t StartOffset, uint32_t EndOffset, CompileUnit::DIEInfo &Info) { |
Frederic Riss | 2e2ed16 | 2015-02-13 23:18:34 +0000 | [diff] [blame] | 518 | assert(NextValidReloc == 0 || |
| 519 | StartOffset > ValidRelocs[NextValidReloc - 1].Offset); |
| 520 | if (NextValidReloc >= ValidRelocs.size()) |
| 521 | return false; |
| 522 | |
| 523 | uint64_t RelocOffset = ValidRelocs[NextValidReloc].Offset; |
| 524 | |
| 525 | // We might need to skip some relocs that we didn't consider. For |
| 526 | // example the high_pc of a discarded DIE might contain a reloc that |
| 527 | // is in the list because it actually corresponds to the start of a |
| 528 | // function that is in the debug map. |
| 529 | while (RelocOffset < StartOffset && NextValidReloc < ValidRelocs.size() - 1) |
| 530 | RelocOffset = ValidRelocs[++NextValidReloc].Offset; |
| 531 | |
| 532 | if (RelocOffset < StartOffset || RelocOffset >= EndOffset) |
| 533 | return false; |
| 534 | |
| 535 | const auto &ValidReloc = ValidRelocs[NextValidReloc++]; |
Frederic Riss | 786b471 | 2015-06-01 21:12:45 +0000 | [diff] [blame] | 536 | const auto &Mapping = ValidReloc.Mapping->getValue(); |
Eugene Zelenko | 66f724e | 2017-11-01 21:16:06 +0000 | [diff] [blame] | 537 | uint64_t ObjectAddress = Mapping.ObjectAddress |
| 538 | ? uint64_t(*Mapping.ObjectAddress) |
| 539 | : std::numeric_limits<uint64_t>::max(); |
Adrian Prantl | 0a0a960 | 2015-09-11 23:45:30 +0000 | [diff] [blame] | 540 | if (Linker.Options.Verbose) |
Frederic Riss | 2e2ed16 | 2015-02-13 23:18:34 +0000 | [diff] [blame] | 541 | outs() << "Found valid debug map entry: " << ValidReloc.Mapping->getKey() |
Jonas Devlieghere | 3ad0c5a | 2018-02-22 11:32:51 +0000 | [diff] [blame] | 542 | << " " |
| 543 | << format("\t%016" PRIx64 " => %016" PRIx64, ObjectAddress, |
| 544 | uint64_t(Mapping.BinaryAddress)); |
Frederic Riss | 2e2ed16 | 2015-02-13 23:18:34 +0000 | [diff] [blame] | 545 | |
Frederic Riss | c5413fc | 2016-01-31 04:29:22 +0000 | [diff] [blame] | 546 | Info.AddrAdjust = int64_t(Mapping.BinaryAddress) + ValidReloc.Addend; |
| 547 | if (Mapping.ObjectAddress) |
| 548 | Info.AddrAdjust -= ObjectAddress; |
Frederic Riss | 2e2ed16 | 2015-02-13 23:18:34 +0000 | [diff] [blame] | 549 | Info.InDebugMap = true; |
| 550 | return true; |
| 551 | } |
| 552 | |
Adrian Prantl | 90d56f0 | 2017-07-21 16:51:17 +0000 | [diff] [blame] | 553 | /// Get the starting and ending (exclusive) offset for the |
Frederic Riss | 2e2ed16 | 2015-02-13 23:18:34 +0000 | [diff] [blame] | 554 | /// attribute with index \p Idx descibed by \p Abbrev. \p Offset is |
| 555 | /// supposed to point to the position of the first attribute described |
| 556 | /// by \p Abbrev. |
| 557 | /// \return [StartOffset, EndOffset) as a pair. |
| 558 | static std::pair<uint32_t, uint32_t> |
| 559 | getAttributeOffsets(const DWARFAbbreviationDeclaration *Abbrev, unsigned Idx, |
| 560 | unsigned Offset, const DWARFUnit &Unit) { |
| 561 | DataExtractor Data = Unit.getDebugInfoExtractor(); |
| 562 | |
| 563 | for (unsigned i = 0; i < Idx; ++i) |
Paul Robinson | fd770ea | 2017-06-26 18:43:01 +0000 | [diff] [blame] | 564 | DWARFFormValue::skipValue(Abbrev->getFormByIndex(i), Data, &Offset, |
| 565 | Unit.getFormParams()); |
Frederic Riss | 2e2ed16 | 2015-02-13 23:18:34 +0000 | [diff] [blame] | 566 | |
| 567 | uint32_t End = Offset; |
Paul Robinson | fd770ea | 2017-06-26 18:43:01 +0000 | [diff] [blame] | 568 | DWARFFormValue::skipValue(Abbrev->getFormByIndex(Idx), Data, &End, |
| 569 | Unit.getFormParams()); |
Frederic Riss | 2e2ed16 | 2015-02-13 23:18:34 +0000 | [diff] [blame] | 570 | |
| 571 | return std::make_pair(Offset, End); |
| 572 | } |
| 573 | |
Adrian Prantl | 90d56f0 | 2017-07-21 16:51:17 +0000 | [diff] [blame] | 574 | /// Check if a variable describing DIE should be kept. |
Frederic Riss | 2e2ed16 | 2015-02-13 23:18:34 +0000 | [diff] [blame] | 575 | /// \returns updated TraversalFlags. |
Adrian Prantl | 0a0a960 | 2015-09-11 23:45:30 +0000 | [diff] [blame] | 576 | unsigned DwarfLinker::shouldKeepVariableDIE(RelocationManager &RelocMgr, |
Greg Clayton | adb170f | 2016-12-13 18:25:19 +0000 | [diff] [blame] | 577 | const DWARFDie &DIE, |
Adrian Prantl | 0a0a960 | 2015-09-11 23:45:30 +0000 | [diff] [blame] | 578 | CompileUnit &Unit, |
| 579 | CompileUnit::DIEInfo &MyInfo, |
| 580 | unsigned Flags) { |
Frederic Riss | 2e2ed16 | 2015-02-13 23:18:34 +0000 | [diff] [blame] | 581 | const auto *Abbrev = DIE.getAbbreviationDeclarationPtr(); |
| 582 | |
| 583 | // Global variables with constant value can always be kept. |
| 584 | if (!(Flags & TF_InFunctionScope) && |
Greg Clayton | b07cdea | 2016-11-15 01:23:06 +0000 | [diff] [blame] | 585 | Abbrev->findAttributeIndex(dwarf::DW_AT_const_value)) { |
Frederic Riss | 2e2ed16 | 2015-02-13 23:18:34 +0000 | [diff] [blame] | 586 | MyInfo.InDebugMap = true; |
| 587 | return Flags | TF_Keep; |
| 588 | } |
| 589 | |
Greg Clayton | b07cdea | 2016-11-15 01:23:06 +0000 | [diff] [blame] | 590 | Optional<uint32_t> LocationIdx = |
| 591 | Abbrev->findAttributeIndex(dwarf::DW_AT_location); |
| 592 | if (!LocationIdx) |
Frederic Riss | 2e2ed16 | 2015-02-13 23:18:34 +0000 | [diff] [blame] | 593 | return Flags; |
| 594 | |
| 595 | uint32_t Offset = DIE.getOffset() + getULEB128Size(Abbrev->getCode()); |
| 596 | const DWARFUnit &OrigUnit = Unit.getOrigUnit(); |
| 597 | uint32_t LocationOffset, LocationEndOffset; |
| 598 | std::tie(LocationOffset, LocationEndOffset) = |
Greg Clayton | b07cdea | 2016-11-15 01:23:06 +0000 | [diff] [blame] | 599 | getAttributeOffsets(Abbrev, *LocationIdx, Offset, OrigUnit); |
Frederic Riss | 2e2ed16 | 2015-02-13 23:18:34 +0000 | [diff] [blame] | 600 | |
| 601 | // See if there is a relocation to a valid debug map entry inside |
| 602 | // this variable's location. The order is important here. We want to |
| 603 | // always check in the variable has a valid relocation, so that the |
| 604 | // DIEInfo is filled. However, we don't want a static variable in a |
| 605 | // function to force us to keep the enclosing function. |
Adrian Prantl | 0a0a960 | 2015-09-11 23:45:30 +0000 | [diff] [blame] | 606 | if (!RelocMgr.hasValidRelocation(LocationOffset, LocationEndOffset, MyInfo) || |
Frederic Riss | 2e2ed16 | 2015-02-13 23:18:34 +0000 | [diff] [blame] | 607 | (Flags & TF_InFunctionScope)) |
| 608 | return Flags; |
| 609 | |
Jonas Devlieghere | d266307 | 2017-09-13 09:43:05 +0000 | [diff] [blame] | 610 | if (Options.Verbose) { |
| 611 | DIDumpOptions DumpOpts; |
Adrian Prantl | ae599aa | 2017-09-20 17:44:00 +0000 | [diff] [blame] | 612 | DumpOpts.RecurseDepth = 0; |
Jonas Devlieghere | d266307 | 2017-09-13 09:43:05 +0000 | [diff] [blame] | 613 | DumpOpts.Verbose = Options.Verbose; |
Adrian Prantl | ae599aa | 2017-09-20 17:44:00 +0000 | [diff] [blame] | 614 | DIE.dump(outs(), 8 /* Indent */, DumpOpts); |
Jonas Devlieghere | d266307 | 2017-09-13 09:43:05 +0000 | [diff] [blame] | 615 | } |
Frederic Riss | 2e2ed16 | 2015-02-13 23:18:34 +0000 | [diff] [blame] | 616 | |
| 617 | return Flags | TF_Keep; |
| 618 | } |
| 619 | |
Adrian Prantl | 90d56f0 | 2017-07-21 16:51:17 +0000 | [diff] [blame] | 620 | /// Check if a function describing DIE should be kept. |
Frederic Riss | 2e2ed16 | 2015-02-13 23:18:34 +0000 | [diff] [blame] | 621 | /// \returns updated TraversalFlags. |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 622 | unsigned DwarfLinker::shouldKeepSubprogramDIE( |
| 623 | RelocationManager &RelocMgr, RangesTy &Ranges, const DWARFDie &DIE, |
| 624 | const DebugMapObject &DMO, CompileUnit &Unit, CompileUnit::DIEInfo &MyInfo, |
| 625 | unsigned Flags) { |
Frederic Riss | 2e2ed16 | 2015-02-13 23:18:34 +0000 | [diff] [blame] | 626 | const auto *Abbrev = DIE.getAbbreviationDeclarationPtr(); |
| 627 | |
| 628 | Flags |= TF_InFunctionScope; |
| 629 | |
Greg Clayton | b07cdea | 2016-11-15 01:23:06 +0000 | [diff] [blame] | 630 | Optional<uint32_t> LowPcIdx = Abbrev->findAttributeIndex(dwarf::DW_AT_low_pc); |
| 631 | if (!LowPcIdx) |
Frederic Riss | 2e2ed16 | 2015-02-13 23:18:34 +0000 | [diff] [blame] | 632 | return Flags; |
| 633 | |
| 634 | uint32_t Offset = DIE.getOffset() + getULEB128Size(Abbrev->getCode()); |
Jonas Devlieghere | 35c4cd1 | 2018-02-20 17:34:29 +0000 | [diff] [blame] | 635 | DWARFUnit &OrigUnit = Unit.getOrigUnit(); |
Frederic Riss | 2e2ed16 | 2015-02-13 23:18:34 +0000 | [diff] [blame] | 636 | uint32_t LowPcOffset, LowPcEndOffset; |
| 637 | std::tie(LowPcOffset, LowPcEndOffset) = |
Greg Clayton | b07cdea | 2016-11-15 01:23:06 +0000 | [diff] [blame] | 638 | getAttributeOffsets(Abbrev, *LowPcIdx, Offset, OrigUnit); |
Frederic Riss | 2e2ed16 | 2015-02-13 23:18:34 +0000 | [diff] [blame] | 639 | |
Greg Clayton | beabb63 | 2017-01-13 21:08:18 +0000 | [diff] [blame] | 640 | auto LowPc = dwarf::toAddress(DIE.find(dwarf::DW_AT_low_pc)); |
Greg Clayton | c64f919 | 2016-12-14 22:38:08 +0000 | [diff] [blame] | 641 | assert(LowPc.hasValue() && "low_pc attribute is not an address."); |
| 642 | if (!LowPc || |
Adrian Prantl | 0a0a960 | 2015-09-11 23:45:30 +0000 | [diff] [blame] | 643 | !RelocMgr.hasValidRelocation(LowPcOffset, LowPcEndOffset, MyInfo)) |
Frederic Riss | 2e2ed16 | 2015-02-13 23:18:34 +0000 | [diff] [blame] | 644 | return Flags; |
| 645 | |
Jonas Devlieghere | d266307 | 2017-09-13 09:43:05 +0000 | [diff] [blame] | 646 | if (Options.Verbose) { |
| 647 | DIDumpOptions DumpOpts; |
Adrian Prantl | ae599aa | 2017-09-20 17:44:00 +0000 | [diff] [blame] | 648 | DumpOpts.RecurseDepth = 0; |
Jonas Devlieghere | d266307 | 2017-09-13 09:43:05 +0000 | [diff] [blame] | 649 | DumpOpts.Verbose = Options.Verbose; |
Adrian Prantl | ae599aa | 2017-09-20 17:44:00 +0000 | [diff] [blame] | 650 | DIE.dump(outs(), 8 /* Indent */, DumpOpts); |
Jonas Devlieghere | d266307 | 2017-09-13 09:43:05 +0000 | [diff] [blame] | 651 | } |
Frederic Riss | 2e2ed16 | 2015-02-13 23:18:34 +0000 | [diff] [blame] | 652 | |
Jonas Devlieghere | 35c4cd1 | 2018-02-20 17:34:29 +0000 | [diff] [blame] | 653 | if (DIE.getTag() == dwarf::DW_TAG_label) { |
| 654 | if (Unit.hasLabelAt(*LowPc)) |
| 655 | return Flags; |
| 656 | // FIXME: dsymutil-classic compat. dsymutil-classic doesn't consider labels |
| 657 | // that don't fall into the CU's aranges. This is wrong IMO. Debug info |
| 658 | // generation bugs aside, this is really wrong in the case of labels, where |
| 659 | // a label marking the end of a function will have a PC == CU's high_pc. |
| 660 | if (dwarf::toAddress(OrigUnit.getUnitDIE().find(dwarf::DW_AT_high_pc)) |
Jonas Devlieghere | 3ad0c5a | 2018-02-22 11:32:51 +0000 | [diff] [blame] | 661 | .getValueOr(UINT64_MAX) <= LowPc) |
Jonas Devlieghere | 35c4cd1 | 2018-02-20 17:34:29 +0000 | [diff] [blame] | 662 | return Flags; |
| 663 | Unit.addLabelLowPc(*LowPc, MyInfo.AddrAdjust); |
| 664 | return Flags | TF_Keep; |
| 665 | } |
| 666 | |
Frederic Riss | 63a0e36 | 2015-03-12 18:45:10 +0000 | [diff] [blame] | 667 | Flags |= TF_Keep; |
| 668 | |
Greg Clayton | 655737a | 2016-12-19 20:36:41 +0000 | [diff] [blame] | 669 | Optional<uint64_t> HighPc = DIE.getHighPC(*LowPc); |
| 670 | if (!HighPc) { |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 671 | reportWarning("Function without high_pc. Range will be discarded.\n", DMO, |
| 672 | &DIE); |
Frederic Riss | 63a0e36 | 2015-03-12 18:45:10 +0000 | [diff] [blame] | 673 | return Flags; |
| 674 | } |
| 675 | |
Frederic Riss | e6412a6 | 2015-03-15 20:45:43 +0000 | [diff] [blame] | 676 | // Replace the debug map range with a more accurate one. |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 677 | Ranges[*LowPc] = DebugMapObjectRange(*HighPc, MyInfo.AddrAdjust); |
Greg Clayton | 655737a | 2016-12-19 20:36:41 +0000 | [diff] [blame] | 678 | Unit.addFunctionRange(*LowPc, *HighPc, MyInfo.AddrAdjust); |
Frederic Riss | 63a0e36 | 2015-03-12 18:45:10 +0000 | [diff] [blame] | 679 | return Flags; |
Frederic Riss | 2e2ed16 | 2015-02-13 23:18:34 +0000 | [diff] [blame] | 680 | } |
| 681 | |
Adrian Prantl | 90d56f0 | 2017-07-21 16:51:17 +0000 | [diff] [blame] | 682 | /// Check if a DIE should be kept. |
Frederic Riss | 2e2ed16 | 2015-02-13 23:18:34 +0000 | [diff] [blame] | 683 | /// \returns updated TraversalFlags. |
Adrian Prantl | 0a0a960 | 2015-09-11 23:45:30 +0000 | [diff] [blame] | 684 | unsigned DwarfLinker::shouldKeepDIE(RelocationManager &RelocMgr, |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 685 | RangesTy &Ranges, const DWARFDie &DIE, |
| 686 | const DebugMapObject &DMO, |
| 687 | CompileUnit &Unit, |
Frederic Riss | 2e2ed16 | 2015-02-13 23:18:34 +0000 | [diff] [blame] | 688 | CompileUnit::DIEInfo &MyInfo, |
| 689 | unsigned Flags) { |
| 690 | switch (DIE.getTag()) { |
| 691 | case dwarf::DW_TAG_constant: |
| 692 | case dwarf::DW_TAG_variable: |
Adrian Prantl | 0a0a960 | 2015-09-11 23:45:30 +0000 | [diff] [blame] | 693 | return shouldKeepVariableDIE(RelocMgr, DIE, Unit, MyInfo, Flags); |
Frederic Riss | 2e2ed16 | 2015-02-13 23:18:34 +0000 | [diff] [blame] | 694 | case dwarf::DW_TAG_subprogram: |
Jonas Devlieghere | 35c4cd1 | 2018-02-20 17:34:29 +0000 | [diff] [blame] | 695 | case dwarf::DW_TAG_label: |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 696 | return shouldKeepSubprogramDIE(RelocMgr, Ranges, DIE, DMO, Unit, MyInfo, |
| 697 | Flags); |
Frederic Riss | 2e2ed16 | 2015-02-13 23:18:34 +0000 | [diff] [blame] | 698 | case dwarf::DW_TAG_imported_module: |
| 699 | case dwarf::DW_TAG_imported_declaration: |
| 700 | case dwarf::DW_TAG_imported_unit: |
| 701 | // We always want to keep these. |
| 702 | return Flags | TF_Keep; |
Greg Clayton | fc1fc8b | 2016-12-01 18:56:29 +0000 | [diff] [blame] | 703 | default: |
| 704 | break; |
Frederic Riss | 2e2ed16 | 2015-02-13 23:18:34 +0000 | [diff] [blame] | 705 | } |
| 706 | |
| 707 | return Flags; |
| 708 | } |
| 709 | |
Adrian Prantl | 90d56f0 | 2017-07-21 16:51:17 +0000 | [diff] [blame] | 710 | /// Mark the passed DIE as well as all the ones it depends on |
Frederic Riss | 2e2ed16 | 2015-02-13 23:18:34 +0000 | [diff] [blame] | 711 | /// as kept. |
| 712 | /// |
| 713 | /// This function is called by lookForDIEsToKeep on DIEs that are |
| 714 | /// newly discovered to be needed in the link. It recursively calls |
| 715 | /// back to lookForDIEsToKeep while adding TF_DependencyWalk to the |
| 716 | /// TraversalFlags to inform it that it's not doing the primary DIE |
| 717 | /// tree walk. |
Jonas Devlieghere | ea63d87 | 2018-06-28 15:01:42 +0000 | [diff] [blame] | 718 | void DwarfLinker::keepDIEAndDependencies( |
| 719 | RelocationManager &RelocMgr, RangesTy &Ranges, const UnitListTy &Units, |
| 720 | const DWARFDie &Die, CompileUnit::DIEInfo &MyInfo, |
| 721 | const DebugMapObject &DMO, CompileUnit &CU, bool UseODR) { |
Greg Clayton | adb170f | 2016-12-13 18:25:19 +0000 | [diff] [blame] | 722 | DWARFUnit &Unit = CU.getOrigUnit(); |
Frederic Riss | 2e2ed16 | 2015-02-13 23:18:34 +0000 | [diff] [blame] | 723 | MyInfo.Keep = true; |
| 724 | |
Jonas Devlieghere | 75475a8 | 2017-08-31 20:22:31 +0000 | [diff] [blame] | 725 | // We're looking for incomplete types. |
| 726 | MyInfo.Incomplete = Die.getTag() != dwarf::DW_TAG_subprogram && |
| 727 | Die.getTag() != dwarf::DW_TAG_member && |
| 728 | dwarf::toUnsigned(Die.find(dwarf::DW_AT_declaration), 0); |
| 729 | |
Frederic Riss | 2e2ed16 | 2015-02-13 23:18:34 +0000 | [diff] [blame] | 730 | // First mark all the parent chain as kept. |
| 731 | unsigned AncestorIdx = MyInfo.ParentIdx; |
| 732 | while (!CU.getInfo(AncestorIdx).Keep) { |
Frederic Riss | 309fcf8 | 2015-07-21 22:41:43 +0000 | [diff] [blame] | 733 | unsigned ODRFlag = UseODR ? TF_ODR : 0; |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 734 | lookForDIEsToKeep(RelocMgr, Ranges, Units, Unit.getDIEAtIndex(AncestorIdx), |
| 735 | DMO, CU, |
Frederic Riss | 309fcf8 | 2015-07-21 22:41:43 +0000 | [diff] [blame] | 736 | TF_ParentWalk | TF_Keep | TF_DependencyWalk | ODRFlag); |
Frederic Riss | 2e2ed16 | 2015-02-13 23:18:34 +0000 | [diff] [blame] | 737 | AncestorIdx = CU.getInfo(AncestorIdx).ParentIdx; |
| 738 | } |
| 739 | |
| 740 | // Then we need to mark all the DIEs referenced by this DIE's |
| 741 | // attributes as kept. |
Paul Robinson | 502fd5d | 2017-06-29 16:52:08 +0000 | [diff] [blame] | 742 | DWARFDataExtractor Data = Unit.getDebugInfoExtractor(); |
Frederic Riss | 5571e77 | 2015-09-11 04:17:25 +0000 | [diff] [blame] | 743 | const auto *Abbrev = Die.getAbbreviationDeclarationPtr(); |
| 744 | uint32_t Offset = Die.getOffset() + getULEB128Size(Abbrev->getCode()); |
Frederic Riss | 2e2ed16 | 2015-02-13 23:18:34 +0000 | [diff] [blame] | 745 | |
Jonas Devlieghere | 75475a8 | 2017-08-31 20:22:31 +0000 | [diff] [blame] | 746 | // Mark all DIEs referenced through attributes as kept. |
Frederic Riss | 2e2ed16 | 2015-02-13 23:18:34 +0000 | [diff] [blame] | 747 | for (const auto &AttrSpec : Abbrev->attributes()) { |
| 748 | DWARFFormValue Val(AttrSpec.Form); |
| 749 | |
Jonas Devlieghere | f521abc | 2018-02-27 19:24:36 +0000 | [diff] [blame] | 750 | if (!Val.isFormClass(DWARFFormValue::FC_Reference) || |
| 751 | AttrSpec.Attr == dwarf::DW_AT_sibling) { |
Paul Robinson | fd770ea | 2017-06-26 18:43:01 +0000 | [diff] [blame] | 752 | DWARFFormValue::skipValue(AttrSpec.Form, Data, &Offset, |
| 753 | Unit.getFormParams()); |
Frederic Riss | 2e2ed16 | 2015-02-13 23:18:34 +0000 | [diff] [blame] | 754 | continue; |
| 755 | } |
| 756 | |
Paul Robinson | e9d757c | 2017-11-07 19:57:12 +0000 | [diff] [blame] | 757 | Val.extractValue(Data, &Offset, Unit.getFormParams(), &Unit); |
Frederic Riss | 2e2ed16 | 2015-02-13 23:18:34 +0000 | [diff] [blame] | 758 | CompileUnit *ReferencedCU; |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 759 | if (auto RefDie = resolveDIEReference(*this, DMO, Units, Val, Unit, Die, |
| 760 | ReferencedCU)) { |
Adrian Prantl | 80ce282 | 2017-07-21 16:51:09 +0000 | [diff] [blame] | 761 | uint32_t RefIdx = ReferencedCU->getOrigUnit().getDIEIndex(RefDie); |
Frederic Riss | 309fcf8 | 2015-07-21 22:41:43 +0000 | [diff] [blame] | 762 | CompileUnit::DIEInfo &Info = ReferencedCU->getInfo(RefIdx); |
Adrian Prantl | 64c7aa6 | 2017-07-21 02:07:33 +0000 | [diff] [blame] | 763 | bool IsModuleRef = Info.Ctxt && Info.Ctxt->getCanonicalDIEOffset() && |
| 764 | Info.Ctxt->isDefinedInClangModule(); |
Frederic Riss | 309fcf8 | 2015-07-21 22:41:43 +0000 | [diff] [blame] | 765 | // If the referenced DIE has a DeclContext that has already been |
| 766 | // emitted, then do not keep the one in this CU. We'll link to |
| 767 | // the canonical DIE in cloneDieReferenceAttribute. |
| 768 | // FIXME: compatibility with dsymutil-classic. UseODR shouldn't |
| 769 | // be necessary and could be advantageously replaced by |
| 770 | // ReferencedCU->hasODR() && CU.hasODR(). |
| 771 | // FIXME: compatibility with dsymutil-classic. There is no |
| 772 | // reason not to unique ref_addr references. |
Adrian Prantl | 64c7aa6 | 2017-07-21 02:07:33 +0000 | [diff] [blame] | 773 | if (AttrSpec.Form != dwarf::DW_FORM_ref_addr && (UseODR || IsModuleRef) && |
| 774 | Info.Ctxt && |
Frederic Riss | 309fcf8 | 2015-07-21 22:41:43 +0000 | [diff] [blame] | 775 | Info.Ctxt != ReferencedCU->getInfo(Info.ParentIdx).Ctxt && |
| 776 | Info.Ctxt->getCanonicalDIEOffset() && isODRAttribute(AttrSpec.Attr)) |
| 777 | continue; |
| 778 | |
Adrian Prantl | b29f9e5 | 2015-11-10 21:31:05 +0000 | [diff] [blame] | 779 | // Keep a module forward declaration if there is no definition. |
| 780 | if (!(isODRAttribute(AttrSpec.Attr) && Info.Ctxt && |
| 781 | Info.Ctxt->getCanonicalDIEOffset())) |
| 782 | Info.Prune = false; |
| 783 | |
Frederic Riss | 309fcf8 | 2015-07-21 22:41:43 +0000 | [diff] [blame] | 784 | unsigned ODRFlag = UseODR ? TF_ODR : 0; |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 785 | lookForDIEsToKeep(RelocMgr, Ranges, Units, RefDie, DMO, *ReferencedCU, |
Frederic Riss | 309fcf8 | 2015-07-21 22:41:43 +0000 | [diff] [blame] | 786 | TF_Keep | TF_DependencyWalk | ODRFlag); |
Jonas Devlieghere | 75475a8 | 2017-08-31 20:22:31 +0000 | [diff] [blame] | 787 | |
| 788 | // The incomplete property is propagated if the current DIE is complete |
| 789 | // but references an incomplete DIE. |
| 790 | if (Info.Incomplete && !MyInfo.Incomplete && |
| 791 | (Die.getTag() == dwarf::DW_TAG_typedef || |
| 792 | Die.getTag() == dwarf::DW_TAG_member || |
| 793 | Die.getTag() == dwarf::DW_TAG_reference_type || |
| 794 | Die.getTag() == dwarf::DW_TAG_ptr_to_member_type || |
| 795 | Die.getTag() == dwarf::DW_TAG_pointer_type)) |
| 796 | MyInfo.Incomplete = true; |
Frederic Riss | 309fcf8 | 2015-07-21 22:41:43 +0000 | [diff] [blame] | 797 | } |
Frederic Riss | 2e2ed16 | 2015-02-13 23:18:34 +0000 | [diff] [blame] | 798 | } |
| 799 | } |
| 800 | |
Jonas Devlieghere | 3289ee6 | 2018-08-01 13:24:39 +0000 | [diff] [blame] | 801 | namespace { |
| 802 | /// This class represents an item in the work list. In addition to it's obvious |
| 803 | /// purpose of representing the state associated with a particular run of the |
| 804 | /// work loop, it also serves as a marker to indicate that we should run the |
| 805 | /// "continuation" code. |
| 806 | /// |
| 807 | /// Originally, the latter was lambda which allowed arbitrary code to be run. |
| 808 | /// Because we always need to run the exact same code, it made more sense to |
| 809 | /// use a boolean and repurpose the already existing DIE field. |
| 810 | struct WorklistItem { |
| 811 | DWARFDie Die; |
| 812 | unsigned Flags; |
| 813 | bool IsContinuation; |
| 814 | CompileUnit::DIEInfo *ChildInfo = nullptr; |
| 815 | |
| 816 | /// Construct a classic worklist item. |
| 817 | WorklistItem(DWARFDie Die, unsigned Flags) |
| 818 | : Die(Die), Flags(Flags), IsContinuation(false){}; |
| 819 | |
| 820 | /// Creates a continuation marker. |
| 821 | WorklistItem(DWARFDie Die) : Die(Die), IsContinuation(true){}; |
| 822 | }; |
| 823 | } // namespace |
| 824 | |
| 825 | // Helper that updates the completeness of the current DIE. It depends on the |
| 826 | // fact that the incompletness of its children is already computed. |
| 827 | static void updateIncompleteness(const DWARFDie &Die, |
| 828 | CompileUnit::DIEInfo &ChildInfo, |
| 829 | CompileUnit &CU) { |
| 830 | // Only propagate incomplete members. |
| 831 | if (Die.getTag() != dwarf::DW_TAG_structure_type && |
| 832 | Die.getTag() != dwarf::DW_TAG_class_type) |
| 833 | return; |
| 834 | |
| 835 | unsigned Idx = CU.getOrigUnit().getDIEIndex(Die); |
| 836 | CompileUnit::DIEInfo &MyInfo = CU.getInfo(Idx); |
| 837 | |
| 838 | if (MyInfo.Incomplete) |
| 839 | return; |
| 840 | |
| 841 | if (ChildInfo.Incomplete || ChildInfo.Prune) |
| 842 | MyInfo.Incomplete = true; |
| 843 | } |
| 844 | |
Adrian Prantl | 90d56f0 | 2017-07-21 16:51:17 +0000 | [diff] [blame] | 845 | /// Recursively walk the \p DIE tree and look for DIEs to |
Frederic Riss | 2e2ed16 | 2015-02-13 23:18:34 +0000 | [diff] [blame] | 846 | /// keep. Store that information in \p CU's DIEInfo. |
| 847 | /// |
| 848 | /// This function is the entry point of the DIE selection |
| 849 | /// algorithm. It is expected to walk the DIE tree in file order and |
| 850 | /// (though the mediation of its helper) call hasValidRelocation() on |
| 851 | /// each DIE that might be a 'root DIE' (See DwarfLinker class |
| 852 | /// comment). |
| 853 | /// While walking the dependencies of root DIEs, this function is |
| 854 | /// also called, but during these dependency walks the file order is |
| 855 | /// not respected. The TF_DependencyWalk flag tells us which kind of |
| 856 | /// traversal we are currently doing. |
Jonas Devlieghere | 75475a8 | 2017-08-31 20:22:31 +0000 | [diff] [blame] | 857 | /// |
| 858 | /// The return value indicates whether the DIE is incomplete. |
Jonas Devlieghere | 3289ee6 | 2018-08-01 13:24:39 +0000 | [diff] [blame] | 859 | void DwarfLinker::lookForDIEsToKeep(RelocationManager &RelocMgr, |
Jonas Devlieghere | ea63d87 | 2018-06-28 15:01:42 +0000 | [diff] [blame] | 860 | RangesTy &Ranges, const UnitListTy &Units, |
Greg Clayton | adb170f | 2016-12-13 18:25:19 +0000 | [diff] [blame] | 861 | const DWARFDie &Die, |
Frederic Riss | 2e2ed16 | 2015-02-13 23:18:34 +0000 | [diff] [blame] | 862 | const DebugMapObject &DMO, CompileUnit &CU, |
| 863 | unsigned Flags) { |
Jonas Devlieghere | 3289ee6 | 2018-08-01 13:24:39 +0000 | [diff] [blame] | 864 | // LIFO work list. |
| 865 | SmallVector<WorklistItem, 4> Worklist; |
| 866 | Worklist.emplace_back(Die, Flags); |
Frederic Riss | 2e2ed16 | 2015-02-13 23:18:34 +0000 | [diff] [blame] | 867 | |
Jonas Devlieghere | 3289ee6 | 2018-08-01 13:24:39 +0000 | [diff] [blame] | 868 | while (!Worklist.empty()) { |
| 869 | WorklistItem Current = Worklist.back(); |
| 870 | Worklist.pop_back(); |
Frederic Riss | 2e2ed16 | 2015-02-13 23:18:34 +0000 | [diff] [blame] | 871 | |
Jonas Devlieghere | 3289ee6 | 2018-08-01 13:24:39 +0000 | [diff] [blame] | 872 | if (Current.IsContinuation) { |
| 873 | updateIncompleteness(Current.Die, *Current.ChildInfo, CU); |
| 874 | continue; |
| 875 | } |
Frederic Riss | 2e2ed16 | 2015-02-13 23:18:34 +0000 | [diff] [blame] | 876 | |
Jonas Devlieghere | 3289ee6 | 2018-08-01 13:24:39 +0000 | [diff] [blame] | 877 | unsigned Idx = CU.getOrigUnit().getDIEIndex(Current.Die); |
| 878 | CompileUnit::DIEInfo &MyInfo = CU.getInfo(Idx); |
| 879 | |
| 880 | // At this point we are guaranteed to have a continuation marker before us |
| 881 | // in the worklist, except for the last DIE. |
| 882 | if (!Worklist.empty()) |
| 883 | Worklist.back().ChildInfo = &MyInfo; |
| 884 | |
| 885 | if (MyInfo.Prune) |
| 886 | continue; |
| 887 | |
| 888 | // If the Keep flag is set, we are marking a required DIE's dependencies. |
| 889 | // If our target is already marked as kept, we're all set. |
| 890 | bool AlreadyKept = MyInfo.Keep; |
| 891 | if ((Current.Flags & TF_DependencyWalk) && AlreadyKept) |
| 892 | continue; |
| 893 | |
| 894 | // We must not call shouldKeepDIE while called from keepDIEAndDependencies, |
| 895 | // because it would screw up the relocation finding logic. |
| 896 | if (!(Current.Flags & TF_DependencyWalk)) |
| 897 | Current.Flags = shouldKeepDIE(RelocMgr, Ranges, Current.Die, DMO, CU, |
| 898 | MyInfo, Current.Flags); |
| 899 | |
| 900 | // If it is a newly kept DIE mark it as well as all its dependencies as |
| 901 | // kept. |
| 902 | if (!AlreadyKept && (Current.Flags & TF_Keep)) { |
| 903 | bool UseOdr = (Current.Flags & TF_DependencyWalk) |
| 904 | ? (Current.Flags & TF_ODR) |
| 905 | : CU.hasODR(); |
| 906 | keepDIEAndDependencies(RelocMgr, Ranges, Units, Current.Die, MyInfo, DMO, |
| 907 | CU, UseOdr); |
| 908 | } |
| 909 | |
| 910 | // The TF_ParentWalk flag tells us that we are currently walking up |
| 911 | // the parent chain of a required DIE, and we don't want to mark all |
| 912 | // the children of the parents as kept (consider for example a |
| 913 | // DW_TAG_namespace node in the parent chain). There are however a |
| 914 | // set of DIE types for which we want to ignore that directive and still |
| 915 | // walk their children. |
| 916 | if (dieNeedsChildrenToBeMeaningful(Current.Die.getTag())) |
| 917 | Current.Flags &= ~TF_ParentWalk; |
| 918 | |
| 919 | if (!Current.Die.hasChildren() || (Current.Flags & TF_ParentWalk)) |
| 920 | continue; |
| 921 | |
| 922 | // Add children in reverse order to the worklist to effectively process |
| 923 | // them in order. |
| 924 | for (auto Child : reverse(Current.Die.children())) { |
| 925 | // Add continuation marker before every child to calculate incompleteness |
| 926 | // after the last child is processed. We can't store this information in |
| 927 | // the same item because we might have to process other continuations |
| 928 | // first. |
| 929 | Worklist.emplace_back(Current.Die); |
| 930 | Worklist.emplace_back(Child, Current.Flags); |
| 931 | } |
Frederic Riss | 309fcf8 | 2015-07-21 22:41:43 +0000 | [diff] [blame] | 932 | } |
Frederic Riss | 2e2ed16 | 2015-02-13 23:18:34 +0000 | [diff] [blame] | 933 | } |
| 934 | |
Jonas Devlieghere | 3ad0c5a | 2018-02-22 11:32:51 +0000 | [diff] [blame] | 935 | /// Assign an abbreviation number to \p Abbrev. |
Frederic Riss | d0d92e7 | 2015-03-04 22:07:44 +0000 | [diff] [blame] | 936 | /// |
| 937 | /// Our DIEs get freed after every DebugMapObject has been processed, |
| 938 | /// thus the FoldingSet we use to unique DIEAbbrevs cannot refer to |
| 939 | /// the instances hold by the DIEs. When we encounter an abbreviation |
| 940 | /// that we don't know, we create a permanent copy of it. |
| 941 | void DwarfLinker::AssignAbbrev(DIEAbbrev &Abbrev) { |
| 942 | // Check the set for priors. |
| 943 | FoldingSetNodeID ID; |
| 944 | Abbrev.Profile(ID); |
| 945 | void *InsertToken; |
| 946 | DIEAbbrev *InSet = AbbreviationsSet.FindNodeOrInsertPos(ID, InsertToken); |
| 947 | |
| 948 | // If it's newly added. |
| 949 | if (InSet) { |
| 950 | // Assign existing abbreviation number. |
| 951 | Abbrev.setNumber(InSet->getNumber()); |
| 952 | } else { |
| 953 | // Add to abbreviation list. |
| 954 | Abbreviations.push_back( |
David Blaikie | be1cec0 | 2015-11-18 00:34:10 +0000 | [diff] [blame] | 955 | llvm::make_unique<DIEAbbrev>(Abbrev.getTag(), Abbrev.hasChildren())); |
Frederic Riss | d0d92e7 | 2015-03-04 22:07:44 +0000 | [diff] [blame] | 956 | for (const auto &Attr : Abbrev.getData()) |
| 957 | Abbreviations.back()->AddAttribute(Attr.getAttribute(), Attr.getForm()); |
David Blaikie | be1cec0 | 2015-11-18 00:34:10 +0000 | [diff] [blame] | 958 | AbbreviationsSet.InsertNode(Abbreviations.back().get(), InsertToken); |
Frederic Riss | d0d92e7 | 2015-03-04 22:07:44 +0000 | [diff] [blame] | 959 | // Assign the unique abbreviation number. |
| 960 | Abbrev.setNumber(Abbreviations.size()); |
| 961 | Abbreviations.back()->setNumber(Abbreviations.size()); |
| 962 | } |
| 963 | } |
| 964 | |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 965 | unsigned DwarfLinker::DIECloner::cloneStringAttribute( |
| 966 | DIE &Die, AttributeSpec AttrSpec, const DWARFFormValue &Val, |
| 967 | const DWARFUnit &U, OffsetsStringPool &StringPool, AttributesInfo &Info) { |
Frederic Riss | d0d92e7 | 2015-03-04 22:07:44 +0000 | [diff] [blame] | 968 | // Switch everything to out of line strings. |
Greg Clayton | 1a30f4b | 2016-10-31 16:46:02 +0000 | [diff] [blame] | 969 | const char *String = *Val.getAsCString(); |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 970 | auto StringEntry = StringPool.getEntry(String); |
| 971 | |
| 972 | // Update attributes info. |
Jonas Devlieghere | 6169346 | 2018-02-08 10:48:54 +0000 | [diff] [blame] | 973 | if (AttrSpec.Attr == dwarf::DW_AT_name) |
| 974 | Info.Name = StringEntry; |
| 975 | else if (AttrSpec.Attr == dwarf::DW_AT_MIPS_linkage_name || |
| 976 | AttrSpec.Attr == dwarf::DW_AT_linkage_name) |
| 977 | Info.MangledName = StringEntry; |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 978 | |
Duncan P. N. Exon Smith | 73e3fb6 | 2015-06-25 23:46:41 +0000 | [diff] [blame] | 979 | Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr), dwarf::DW_FORM_strp, |
Jonas Devlieghere | 6169346 | 2018-02-08 10:48:54 +0000 | [diff] [blame] | 980 | DIEInteger(StringEntry.getOffset())); |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 981 | |
Frederic Riss | d0d92e7 | 2015-03-04 22:07:44 +0000 | [diff] [blame] | 982 | return 4; |
| 983 | } |
| 984 | |
Adrian Prantl | afca6b4 | 2015-09-14 16:46:10 +0000 | [diff] [blame] | 985 | unsigned DwarfLinker::DIECloner::cloneDieReferenceAttribute( |
Jonas Devlieghere | 3ad0c5a | 2018-02-22 11:32:51 +0000 | [diff] [blame] | 986 | DIE &Die, const DWARFDie &InputDIE, AttributeSpec AttrSpec, |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 987 | unsigned AttrSize, const DWARFFormValue &Val, const DebugMapObject &DMO, |
| 988 | CompileUnit &Unit) { |
Frederic Riss | 309fcf8 | 2015-07-21 22:41:43 +0000 | [diff] [blame] | 989 | const DWARFUnit &U = Unit.getOrigUnit(); |
Greg Clayton | 1a30f4b | 2016-10-31 16:46:02 +0000 | [diff] [blame] | 990 | uint32_t Ref = *Val.getAsReference(); |
Frederic Riss | fe78287 | 2015-03-06 23:22:53 +0000 | [diff] [blame] | 991 | DIE *NewRefDie = nullptr; |
| 992 | CompileUnit *RefUnit = nullptr; |
Frederic Riss | 309fcf8 | 2015-07-21 22:41:43 +0000 | [diff] [blame] | 993 | DeclContext *Ctxt = nullptr; |
Frederic Riss | fe78287 | 2015-03-06 23:22:53 +0000 | [diff] [blame] | 994 | |
Jonas Devlieghere | 3ad0c5a | 2018-02-22 11:32:51 +0000 | [diff] [blame] | 995 | DWARFDie RefDie = |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 996 | resolveDIEReference(Linker, DMO, CompileUnits, Val, U, InputDIE, RefUnit); |
Frederic Riss | 309fcf8 | 2015-07-21 22:41:43 +0000 | [diff] [blame] | 997 | |
| 998 | // If the referenced DIE is not found, drop the attribute. |
Jonas Devlieghere | f521abc | 2018-02-27 19:24:36 +0000 | [diff] [blame] | 999 | if (!RefDie || AttrSpec.Attr == dwarf::DW_AT_sibling) |
Frederic Riss | fe78287 | 2015-03-06 23:22:53 +0000 | [diff] [blame] | 1000 | return 0; |
Frederic Riss | fe78287 | 2015-03-06 23:22:53 +0000 | [diff] [blame] | 1001 | |
| 1002 | unsigned Idx = RefUnit->getOrigUnit().getDIEIndex(RefDie); |
| 1003 | CompileUnit::DIEInfo &RefInfo = RefUnit->getInfo(Idx); |
Frederic Riss | 309fcf8 | 2015-07-21 22:41:43 +0000 | [diff] [blame] | 1004 | |
| 1005 | // If we already have emitted an equivalent DeclContext, just point |
| 1006 | // at it. |
| 1007 | if (isODRAttribute(AttrSpec.Attr)) { |
| 1008 | Ctxt = RefInfo.Ctxt; |
| 1009 | if (Ctxt && Ctxt->getCanonicalDIEOffset()) { |
| 1010 | DIEInteger Attr(Ctxt->getCanonicalDIEOffset()); |
| 1011 | Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr), |
| 1012 | dwarf::DW_FORM_ref_addr, Attr); |
Greg Clayton | 1a30f4b | 2016-10-31 16:46:02 +0000 | [diff] [blame] | 1013 | return U.getRefAddrByteSize(); |
Frederic Riss | 309fcf8 | 2015-07-21 22:41:43 +0000 | [diff] [blame] | 1014 | } |
| 1015 | } |
| 1016 | |
Frederic Riss | fe78287 | 2015-03-06 23:22:53 +0000 | [diff] [blame] | 1017 | if (!RefInfo.Clone) { |
| 1018 | assert(Ref > InputDIE.getOffset()); |
| 1019 | // We haven't cloned this DIE yet. Just create an empty one and |
| 1020 | // store it. It'll get really cloned when we process it. |
Greg Clayton | adb170f | 2016-12-13 18:25:19 +0000 | [diff] [blame] | 1021 | RefInfo.Clone = DIE::get(DIEAlloc, dwarf::Tag(RefDie.getTag())); |
Frederic Riss | fe78287 | 2015-03-06 23:22:53 +0000 | [diff] [blame] | 1022 | } |
| 1023 | NewRefDie = RefInfo.Clone; |
| 1024 | |
Frederic Riss | 309fcf8 | 2015-07-21 22:41:43 +0000 | [diff] [blame] | 1025 | if (AttrSpec.Form == dwarf::DW_FORM_ref_addr || |
| 1026 | (Unit.hasODR() && isODRAttribute(AttrSpec.Attr))) { |
Frederic Riss | fe78287 | 2015-03-06 23:22:53 +0000 | [diff] [blame] | 1027 | // We cannot currently rely on a DIEEntry to emit ref_addr |
| 1028 | // references, because the implementation calls back to DwarfDebug |
| 1029 | // to find the unit offset. (We don't have a DwarfDebug) |
| 1030 | // FIXME: we should be able to design DIEEntry reliance on |
| 1031 | // DwarfDebug away. |
Duncan P. N. Exon Smith | 09fe4bf | 2015-05-27 22:14:58 +0000 | [diff] [blame] | 1032 | uint64_t Attr; |
Frederic Riss | fe78287 | 2015-03-06 23:22:53 +0000 | [diff] [blame] | 1033 | if (Ref < InputDIE.getOffset()) { |
| 1034 | // We must have already cloned that DIE. |
| 1035 | uint32_t NewRefOffset = |
| 1036 | RefUnit->getStartOffset() + NewRefDie->getOffset(); |
Duncan P. N. Exon Smith | 09fe4bf | 2015-05-27 22:14:58 +0000 | [diff] [blame] | 1037 | Attr = NewRefOffset; |
Duncan P. N. Exon Smith | 73e3fb6 | 2015-06-25 23:46:41 +0000 | [diff] [blame] | 1038 | Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr), |
| 1039 | dwarf::DW_FORM_ref_addr, DIEInteger(Attr)); |
Frederic Riss | fe78287 | 2015-03-06 23:22:53 +0000 | [diff] [blame] | 1040 | } else { |
| 1041 | // A forward reference. Note and fixup later. |
Duncan P. N. Exon Smith | 09fe4bf | 2015-05-27 22:14:58 +0000 | [diff] [blame] | 1042 | Attr = 0xBADDEF; |
Duncan P. N. Exon Smith | 73e3fb6 | 2015-06-25 23:46:41 +0000 | [diff] [blame] | 1043 | Unit.noteForwardReference( |
Frederic Riss | 309fcf8 | 2015-07-21 22:41:43 +0000 | [diff] [blame] | 1044 | NewRefDie, RefUnit, Ctxt, |
Duncan P. N. Exon Smith | 73e3fb6 | 2015-06-25 23:46:41 +0000 | [diff] [blame] | 1045 | Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr), |
| 1046 | dwarf::DW_FORM_ref_addr, DIEInteger(Attr))); |
Frederic Riss | fe78287 | 2015-03-06 23:22:53 +0000 | [diff] [blame] | 1047 | } |
Greg Clayton | 1a30f4b | 2016-10-31 16:46:02 +0000 | [diff] [blame] | 1048 | return U.getRefAddrByteSize(); |
Frederic Riss | fe78287 | 2015-03-06 23:22:53 +0000 | [diff] [blame] | 1049 | } |
| 1050 | |
Duncan P. N. Exon Smith | 73e3fb6 | 2015-06-25 23:46:41 +0000 | [diff] [blame] | 1051 | Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr), |
| 1052 | dwarf::Form(AttrSpec.Form), DIEEntry(*NewRefDie)); |
Frederic Riss | d0d92e7 | 2015-03-04 22:07:44 +0000 | [diff] [blame] | 1053 | return AttrSize; |
| 1054 | } |
| 1055 | |
Adrian Prantl | afca6b4 | 2015-09-14 16:46:10 +0000 | [diff] [blame] | 1056 | unsigned DwarfLinker::DIECloner::cloneBlockAttribute(DIE &Die, |
| 1057 | AttributeSpec AttrSpec, |
| 1058 | const DWARFFormValue &Val, |
| 1059 | unsigned AttrSize) { |
Duncan P. N. Exon Smith | 401c02a | 2015-08-02 20:48:47 +0000 | [diff] [blame] | 1060 | DIEValueList *Attr; |
Duncan P. N. Exon Smith | 09fe4bf | 2015-05-27 22:14:58 +0000 | [diff] [blame] | 1061 | DIEValue Value; |
Frederic Riss | d0d92e7 | 2015-03-04 22:07:44 +0000 | [diff] [blame] | 1062 | DIELoc *Loc = nullptr; |
| 1063 | DIEBlock *Block = nullptr; |
| 1064 | // Just copy the block data over. |
Frederic Riss | 3a5c117 | 2015-03-13 18:35:39 +0000 | [diff] [blame] | 1065 | if (AttrSpec.Form == dwarf::DW_FORM_exprloc) { |
Duncan P. N. Exon Smith | 09fe4bf | 2015-05-27 22:14:58 +0000 | [diff] [blame] | 1066 | Loc = new (DIEAlloc) DIELoc; |
Adrian Prantl | afca6b4 | 2015-09-14 16:46:10 +0000 | [diff] [blame] | 1067 | Linker.DIELocs.push_back(Loc); |
Frederic Riss | d0d92e7 | 2015-03-04 22:07:44 +0000 | [diff] [blame] | 1068 | } else { |
Duncan P. N. Exon Smith | 09fe4bf | 2015-05-27 22:14:58 +0000 | [diff] [blame] | 1069 | Block = new (DIEAlloc) DIEBlock; |
Adrian Prantl | afca6b4 | 2015-09-14 16:46:10 +0000 | [diff] [blame] | 1070 | Linker.DIEBlocks.push_back(Block); |
Frederic Riss | d0d92e7 | 2015-03-04 22:07:44 +0000 | [diff] [blame] | 1071 | } |
Duncan P. N. Exon Smith | 401c02a | 2015-08-02 20:48:47 +0000 | [diff] [blame] | 1072 | Attr = Loc ? static_cast<DIEValueList *>(Loc) |
| 1073 | : static_cast<DIEValueList *>(Block); |
Duncan P. N. Exon Smith | 611a2f2 | 2015-05-27 22:31:41 +0000 | [diff] [blame] | 1074 | |
| 1075 | if (Loc) |
| 1076 | Value = DIEValue(dwarf::Attribute(AttrSpec.Attr), |
| 1077 | dwarf::Form(AttrSpec.Form), Loc); |
| 1078 | else |
| 1079 | Value = DIEValue(dwarf::Attribute(AttrSpec.Attr), |
| 1080 | dwarf::Form(AttrSpec.Form), Block); |
Frederic Riss | d0d92e7 | 2015-03-04 22:07:44 +0000 | [diff] [blame] | 1081 | ArrayRef<uint8_t> Bytes = *Val.getAsBlock(); |
| 1082 | for (auto Byte : Bytes) |
Duncan P. N. Exon Smith | 73e3fb6 | 2015-06-25 23:46:41 +0000 | [diff] [blame] | 1083 | Attr->addValue(DIEAlloc, static_cast<dwarf::Attribute>(0), |
| 1084 | dwarf::DW_FORM_data1, DIEInteger(Byte)); |
Frederic Riss | d0d92e7 | 2015-03-04 22:07:44 +0000 | [diff] [blame] | 1085 | // FIXME: If DIEBlock and DIELoc just reuses the Size field of |
| 1086 | // the DIE class, this if could be replaced by |
| 1087 | // Attr->setSize(Bytes.size()). |
Adrian Prantl | afca6b4 | 2015-09-14 16:46:10 +0000 | [diff] [blame] | 1088 | if (Linker.Streamer) { |
| 1089 | auto *AsmPrinter = &Linker.Streamer->getAsmPrinter(); |
Frederic Riss | d0d92e7 | 2015-03-04 22:07:44 +0000 | [diff] [blame] | 1090 | if (Loc) |
Adrian Prantl | afca6b4 | 2015-09-14 16:46:10 +0000 | [diff] [blame] | 1091 | Loc->ComputeSize(AsmPrinter); |
Frederic Riss | d0d92e7 | 2015-03-04 22:07:44 +0000 | [diff] [blame] | 1092 | else |
Adrian Prantl | afca6b4 | 2015-09-14 16:46:10 +0000 | [diff] [blame] | 1093 | Block->ComputeSize(AsmPrinter); |
Frederic Riss | d0d92e7 | 2015-03-04 22:07:44 +0000 | [diff] [blame] | 1094 | } |
Duncan P. N. Exon Smith | 73e3fb6 | 2015-06-25 23:46:41 +0000 | [diff] [blame] | 1095 | Die.addValue(DIEAlloc, Value); |
Frederic Riss | d0d92e7 | 2015-03-04 22:07:44 +0000 | [diff] [blame] | 1096 | return AttrSize; |
| 1097 | } |
| 1098 | |
Adrian Prantl | afca6b4 | 2015-09-14 16:46:10 +0000 | [diff] [blame] | 1099 | unsigned DwarfLinker::DIECloner::cloneAddressAttribute( |
| 1100 | DIE &Die, AttributeSpec AttrSpec, const DWARFFormValue &Val, |
| 1101 | const CompileUnit &Unit, AttributesInfo &Info) { |
Greg Clayton | 1a30f4b | 2016-10-31 16:46:02 +0000 | [diff] [blame] | 1102 | uint64_t Addr = *Val.getAsAddress(); |
Jonas Devlieghere | a9aab59 | 2018-01-29 14:52:50 +0000 | [diff] [blame] | 1103 | |
Jonas Devlieghere | 6169346 | 2018-02-08 10:48:54 +0000 | [diff] [blame] | 1104 | if (LLVM_UNLIKELY(Linker.Options.Update)) { |
| 1105 | if (AttrSpec.Attr == dwarf::DW_AT_low_pc) |
| 1106 | Info.HasLowPc = true; |
| 1107 | Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr), |
| 1108 | dwarf::Form(AttrSpec.Form), DIEInteger(Addr)); |
| 1109 | return Unit.getOrigUnit().getAddressByteSize(); |
| 1110 | } |
| 1111 | |
Frederic Riss | 89393bb | 2015-03-11 18:45:52 +0000 | [diff] [blame] | 1112 | if (AttrSpec.Attr == dwarf::DW_AT_low_pc) { |
| 1113 | if (Die.getTag() == dwarf::DW_TAG_inlined_subroutine || |
| 1114 | Die.getTag() == dwarf::DW_TAG_lexical_block) |
Frederic Riss | efe3016 | 2015-08-31 01:43:14 +0000 | [diff] [blame] | 1115 | // The low_pc of a block or inline subroutine might get |
| 1116 | // relocated because it happens to match the low_pc of the |
| 1117 | // enclosing subprogram. To prevent issues with that, always use |
| 1118 | // the low_pc from the input DIE if relocations have been applied. |
Eugene Zelenko | 66f724e | 2017-11-01 21:16:06 +0000 | [diff] [blame] | 1119 | Addr = (Info.OrigLowPc != std::numeric_limits<uint64_t>::max() |
| 1120 | ? Info.OrigLowPc |
| 1121 | : Addr) + |
Frederic Riss | efe3016 | 2015-08-31 01:43:14 +0000 | [diff] [blame] | 1122 | Info.PCOffset; |
Frederic Riss | 27db519 | 2015-03-13 18:35:54 +0000 | [diff] [blame] | 1123 | else if (Die.getTag() == dwarf::DW_TAG_compile_unit) { |
| 1124 | Addr = Unit.getLowPc(); |
Eugene Zelenko | 66f724e | 2017-11-01 21:16:06 +0000 | [diff] [blame] | 1125 | if (Addr == std::numeric_limits<uint64_t>::max()) |
Frederic Riss | 27db519 | 2015-03-13 18:35:54 +0000 | [diff] [blame] | 1126 | return 0; |
| 1127 | } |
Frederic Riss | 991f3ea | 2015-03-16 02:05:10 +0000 | [diff] [blame] | 1128 | Info.HasLowPc = true; |
Frederic Riss | 89393bb | 2015-03-11 18:45:52 +0000 | [diff] [blame] | 1129 | } else if (AttrSpec.Attr == dwarf::DW_AT_high_pc) { |
Frederic Riss | 27db519 | 2015-03-13 18:35:54 +0000 | [diff] [blame] | 1130 | if (Die.getTag() == dwarf::DW_TAG_compile_unit) { |
| 1131 | if (uint64_t HighPc = Unit.getHighPc()) |
| 1132 | Addr = HighPc; |
| 1133 | else |
| 1134 | return 0; |
| 1135 | } else |
| 1136 | // If we have a high_pc recorded for the input DIE, use |
| 1137 | // it. Otherwise (when no relocations where applied) just use the |
| 1138 | // one we just decoded. |
| 1139 | Addr = (Info.OrigHighPc ? Info.OrigHighPc : Addr) + Info.PCOffset; |
Frederic Riss | 89393bb | 2015-03-11 18:45:52 +0000 | [diff] [blame] | 1140 | } |
| 1141 | |
Duncan P. N. Exon Smith | 73e3fb6 | 2015-06-25 23:46:41 +0000 | [diff] [blame] | 1142 | Die.addValue(DIEAlloc, static_cast<dwarf::Attribute>(AttrSpec.Attr), |
Duncan P. N. Exon Smith | 09fe4bf | 2015-05-27 22:14:58 +0000 | [diff] [blame] | 1143 | static_cast<dwarf::Form>(AttrSpec.Form), DIEInteger(Addr)); |
Frederic Riss | 89393bb | 2015-03-11 18:45:52 +0000 | [diff] [blame] | 1144 | return Unit.getOrigUnit().getAddressByteSize(); |
| 1145 | } |
| 1146 | |
Adrian Prantl | afca6b4 | 2015-09-14 16:46:10 +0000 | [diff] [blame] | 1147 | unsigned DwarfLinker::DIECloner::cloneScalarAttribute( |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 1148 | DIE &Die, const DWARFDie &InputDIE, const DebugMapObject &DMO, |
| 1149 | CompileUnit &Unit, AttributeSpec AttrSpec, const DWARFFormValue &Val, |
| 1150 | unsigned AttrSize, AttributesInfo &Info) { |
Frederic Riss | d0d92e7 | 2015-03-04 22:07:44 +0000 | [diff] [blame] | 1151 | uint64_t Value; |
Jonas Devlieghere | 6169346 | 2018-02-08 10:48:54 +0000 | [diff] [blame] | 1152 | |
| 1153 | if (LLVM_UNLIKELY(Linker.Options.Update)) { |
| 1154 | if (auto OptionalValue = Val.getAsUnsignedConstant()) |
| 1155 | Value = *OptionalValue; |
| 1156 | else if (auto OptionalValue = Val.getAsSignedConstant()) |
| 1157 | Value = *OptionalValue; |
| 1158 | else if (auto OptionalValue = Val.getAsSectionOffset()) |
| 1159 | Value = *OptionalValue; |
| 1160 | else { |
| 1161 | Linker.reportWarning( |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 1162 | "Unsupported scalar attribute form. Dropping attribute.", DMO, |
| 1163 | &InputDIE); |
Jonas Devlieghere | 6169346 | 2018-02-08 10:48:54 +0000 | [diff] [blame] | 1164 | return 0; |
| 1165 | } |
| 1166 | if (AttrSpec.Attr == dwarf::DW_AT_declaration && Value) |
| 1167 | Info.IsDeclaration = true; |
| 1168 | Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr), |
| 1169 | dwarf::Form(AttrSpec.Form), DIEInteger(Value)); |
| 1170 | return AttrSize; |
| 1171 | } |
| 1172 | |
Frederic Riss | 27db519 | 2015-03-13 18:35:54 +0000 | [diff] [blame] | 1173 | if (AttrSpec.Attr == dwarf::DW_AT_high_pc && |
| 1174 | Die.getTag() == dwarf::DW_TAG_compile_unit) { |
| 1175 | if (Unit.getLowPc() == -1ULL) |
| 1176 | return 0; |
| 1177 | // Dwarf >= 4 high_pc is an size, not an address. |
| 1178 | Value = Unit.getHighPc() - Unit.getLowPc(); |
| 1179 | } else if (AttrSpec.Form == dwarf::DW_FORM_sec_offset) |
Frederic Riss | d0d92e7 | 2015-03-04 22:07:44 +0000 | [diff] [blame] | 1180 | Value = *Val.getAsSectionOffset(); |
| 1181 | else if (AttrSpec.Form == dwarf::DW_FORM_sdata) |
| 1182 | Value = *Val.getAsSignedConstant(); |
Frederic Riss | d0d92e7 | 2015-03-04 22:07:44 +0000 | [diff] [blame] | 1183 | else if (auto OptionalValue = Val.getAsUnsignedConstant()) |
| 1184 | Value = *OptionalValue; |
| 1185 | else { |
Adrian Prantl | afca6b4 | 2015-09-14 16:46:10 +0000 | [diff] [blame] | 1186 | Linker.reportWarning( |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 1187 | "Unsupported scalar attribute form. Dropping attribute.", DMO, |
| 1188 | &InputDIE); |
Frederic Riss | d0d92e7 | 2015-03-04 22:07:44 +0000 | [diff] [blame] | 1189 | return 0; |
| 1190 | } |
Duncan P. N. Exon Smith | 73e3fb6 | 2015-06-25 23:46:41 +0000 | [diff] [blame] | 1191 | PatchLocation Patch = |
| 1192 | Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr), |
| 1193 | dwarf::Form(AttrSpec.Form), DIEInteger(Value)); |
Jonas Devlieghere | a9aab59 | 2018-01-29 14:52:50 +0000 | [diff] [blame] | 1194 | if (AttrSpec.Attr == dwarf::DW_AT_ranges) { |
Duncan P. N. Exon Smith | 73e3fb6 | 2015-06-25 23:46:41 +0000 | [diff] [blame] | 1195 | Unit.noteRangeAttribute(Die, Patch); |
Jonas Devlieghere | a9aab59 | 2018-01-29 14:52:50 +0000 | [diff] [blame] | 1196 | Info.HasRanges = true; |
| 1197 | } |
Frederic Riss | 5f69f9f | 2015-09-11 04:17:30 +0000 | [diff] [blame] | 1198 | |
Frederic Riss | 5712ee1 | 2015-03-14 15:49:07 +0000 | [diff] [blame] | 1199 | // A more generic way to check for location attributes would be |
| 1200 | // nice, but it's very unlikely that any other attribute needs a |
| 1201 | // location list. |
| 1202 | else if (AttrSpec.Attr == dwarf::DW_AT_location || |
| 1203 | AttrSpec.Attr == dwarf::DW_AT_frame_base) |
Duncan P. N. Exon Smith | 73e3fb6 | 2015-06-25 23:46:41 +0000 | [diff] [blame] | 1204 | Unit.noteLocationAttribute(Patch, Info.PCOffset); |
Frederic Riss | 991f3ea | 2015-03-16 02:05:10 +0000 | [diff] [blame] | 1205 | else if (AttrSpec.Attr == dwarf::DW_AT_declaration && Value) |
| 1206 | Info.IsDeclaration = true; |
Frederic Riss | 5712ee1 | 2015-03-14 15:49:07 +0000 | [diff] [blame] | 1207 | |
Frederic Riss | d0d92e7 | 2015-03-04 22:07:44 +0000 | [diff] [blame] | 1208 | return AttrSize; |
| 1209 | } |
| 1210 | |
Adrian Prantl | 90d56f0 | 2017-07-21 16:51:17 +0000 | [diff] [blame] | 1211 | /// Clone \p InputDIE's attribute described by \p AttrSpec with |
Frederic Riss | d0d92e7 | 2015-03-04 22:07:44 +0000 | [diff] [blame] | 1212 | /// value \p Val, and add it to \p Die. |
| 1213 | /// \returns the size of the cloned attribute. |
Adrian Prantl | afca6b4 | 2015-09-14 16:46:10 +0000 | [diff] [blame] | 1214 | unsigned DwarfLinker::DIECloner::cloneAttribute( |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 1215 | DIE &Die, const DWARFDie &InputDIE, const DebugMapObject &DMO, |
| 1216 | CompileUnit &Unit, OffsetsStringPool &StringPool, const DWARFFormValue &Val, |
| 1217 | const AttributeSpec AttrSpec, unsigned AttrSize, AttributesInfo &Info) { |
Frederic Riss | d0d92e7 | 2015-03-04 22:07:44 +0000 | [diff] [blame] | 1218 | const DWARFUnit &U = Unit.getOrigUnit(); |
| 1219 | |
| 1220 | switch (AttrSpec.Form) { |
| 1221 | case dwarf::DW_FORM_strp: |
| 1222 | case dwarf::DW_FORM_string: |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 1223 | return cloneStringAttribute(Die, AttrSpec, Val, U, StringPool, Info); |
Frederic Riss | d0d92e7 | 2015-03-04 22:07:44 +0000 | [diff] [blame] | 1224 | case dwarf::DW_FORM_ref_addr: |
| 1225 | case dwarf::DW_FORM_ref1: |
| 1226 | case dwarf::DW_FORM_ref2: |
| 1227 | case dwarf::DW_FORM_ref4: |
| 1228 | case dwarf::DW_FORM_ref8: |
Frederic Riss | fe78287 | 2015-03-06 23:22:53 +0000 | [diff] [blame] | 1229 | return cloneDieReferenceAttribute(Die, InputDIE, AttrSpec, AttrSize, Val, |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 1230 | DMO, Unit); |
Frederic Riss | d0d92e7 | 2015-03-04 22:07:44 +0000 | [diff] [blame] | 1231 | case dwarf::DW_FORM_block: |
| 1232 | case dwarf::DW_FORM_block1: |
| 1233 | case dwarf::DW_FORM_block2: |
| 1234 | case dwarf::DW_FORM_block4: |
| 1235 | case dwarf::DW_FORM_exprloc: |
| 1236 | return cloneBlockAttribute(Die, AttrSpec, Val, AttrSize); |
| 1237 | case dwarf::DW_FORM_addr: |
Frederic Riss | 89393bb | 2015-03-11 18:45:52 +0000 | [diff] [blame] | 1238 | return cloneAddressAttribute(Die, AttrSpec, Val, Unit, Info); |
Frederic Riss | d0d92e7 | 2015-03-04 22:07:44 +0000 | [diff] [blame] | 1239 | case dwarf::DW_FORM_data1: |
| 1240 | case dwarf::DW_FORM_data2: |
| 1241 | case dwarf::DW_FORM_data4: |
| 1242 | case dwarf::DW_FORM_data8: |
| 1243 | case dwarf::DW_FORM_udata: |
| 1244 | case dwarf::DW_FORM_sdata: |
| 1245 | case dwarf::DW_FORM_sec_offset: |
| 1246 | case dwarf::DW_FORM_flag: |
| 1247 | case dwarf::DW_FORM_flag_present: |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 1248 | return cloneScalarAttribute(Die, InputDIE, DMO, Unit, AttrSpec, Val, |
| 1249 | AttrSize, Info); |
Frederic Riss | d0d92e7 | 2015-03-04 22:07:44 +0000 | [diff] [blame] | 1250 | default: |
Adrian Prantl | afca6b4 | 2015-09-14 16:46:10 +0000 | [diff] [blame] | 1251 | Linker.reportWarning( |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 1252 | "Unsupported attribute form in cloneAttribute. Dropping.", DMO, |
| 1253 | &InputDIE); |
Frederic Riss | d0d92e7 | 2015-03-04 22:07:44 +0000 | [diff] [blame] | 1254 | } |
| 1255 | |
| 1256 | return 0; |
| 1257 | } |
| 1258 | |
Adrian Prantl | 90d56f0 | 2017-07-21 16:51:17 +0000 | [diff] [blame] | 1259 | /// Apply the valid relocations found by findValidRelocs() to |
Frederic Riss | 3c8e619 | 2015-03-07 01:25:09 +0000 | [diff] [blame] | 1260 | /// the buffer \p Data, taking into account that Data is at \p BaseOffset |
| 1261 | /// in the debug_info section. |
| 1262 | /// |
| 1263 | /// Like for findValidRelocs(), this function must be called with |
| 1264 | /// monotonic \p BaseOffset values. |
| 1265 | /// |
Jonas Devlieghere | 3ad0c5a | 2018-02-22 11:32:51 +0000 | [diff] [blame] | 1266 | /// \returns whether any reloc has been applied. |
| 1267 | bool DwarfLinker::RelocationManager::applyValidRelocs( |
| 1268 | MutableArrayRef<char> Data, uint32_t BaseOffset, bool isLittleEndian) { |
Aaron Ballman | b365064 | 2015-03-07 15:16:27 +0000 | [diff] [blame] | 1269 | assert((NextValidReloc == 0 || |
Frederic Riss | 7944cd1 | 2015-03-11 18:45:57 +0000 | [diff] [blame] | 1270 | BaseOffset > ValidRelocs[NextValidReloc - 1].Offset) && |
| 1271 | "BaseOffset should only be increasing."); |
Frederic Riss | 3c8e619 | 2015-03-07 01:25:09 +0000 | [diff] [blame] | 1272 | if (NextValidReloc >= ValidRelocs.size()) |
| 1273 | return false; |
| 1274 | |
| 1275 | // Skip relocs that haven't been applied. |
| 1276 | while (NextValidReloc < ValidRelocs.size() && |
| 1277 | ValidRelocs[NextValidReloc].Offset < BaseOffset) |
| 1278 | ++NextValidReloc; |
| 1279 | |
| 1280 | bool Applied = false; |
| 1281 | uint64_t EndOffset = BaseOffset + Data.size(); |
| 1282 | while (NextValidReloc < ValidRelocs.size() && |
| 1283 | ValidRelocs[NextValidReloc].Offset >= BaseOffset && |
| 1284 | ValidRelocs[NextValidReloc].Offset < EndOffset) { |
| 1285 | const auto &ValidReloc = ValidRelocs[NextValidReloc++]; |
| 1286 | assert(ValidReloc.Offset - BaseOffset < Data.size()); |
| 1287 | assert(ValidReloc.Offset - BaseOffset + ValidReloc.Size <= Data.size()); |
| 1288 | char Buf[8]; |
| 1289 | uint64_t Value = ValidReloc.Mapping->getValue().BinaryAddress; |
| 1290 | Value += ValidReloc.Addend; |
| 1291 | for (unsigned i = 0; i != ValidReloc.Size; ++i) { |
| 1292 | unsigned Index = isLittleEndian ? i : (ValidReloc.Size - i - 1); |
| 1293 | Buf[i] = uint8_t(Value >> (Index * 8)); |
| 1294 | } |
| 1295 | assert(ValidReloc.Size <= sizeof(Buf)); |
| 1296 | memcpy(&Data[ValidReloc.Offset - BaseOffset], Buf, ValidReloc.Size); |
| 1297 | Applied = true; |
| 1298 | } |
| 1299 | |
| 1300 | return Applied; |
| 1301 | } |
| 1302 | |
Jonas Devlieghere | a9aab59 | 2018-01-29 14:52:50 +0000 | [diff] [blame] | 1303 | static bool isObjCSelector(StringRef Name) { |
| 1304 | return Name.size() > 2 && (Name[0] == '-' || Name[0] == '+') && |
| 1305 | (Name[1] == '['); |
| 1306 | } |
| 1307 | |
| 1308 | void DwarfLinker::DIECloner::addObjCAccelerator(CompileUnit &Unit, |
| 1309 | const DIE *Die, |
| 1310 | DwarfStringPoolEntryRef Name, |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 1311 | OffsetsStringPool &StringPool, |
Jonas Devlieghere | a9aab59 | 2018-01-29 14:52:50 +0000 | [diff] [blame] | 1312 | bool SkipPubSection) { |
| 1313 | assert(isObjCSelector(Name.getString()) && "not an objc selector"); |
| 1314 | // Objective C method or class function. |
| 1315 | // "- [Class(Category) selector :withArg ...]" |
| 1316 | StringRef ClassNameStart(Name.getString().drop_front(2)); |
| 1317 | size_t FirstSpace = ClassNameStart.find(' '); |
| 1318 | if (FirstSpace == StringRef::npos) |
| 1319 | return; |
| 1320 | |
| 1321 | StringRef SelectorStart(ClassNameStart.data() + FirstSpace + 1); |
| 1322 | if (!SelectorStart.size()) |
| 1323 | return; |
| 1324 | |
| 1325 | StringRef Selector(SelectorStart.data(), SelectorStart.size() - 1); |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 1326 | Unit.addNameAccelerator(Die, StringPool.getEntry(Selector), SkipPubSection); |
Jonas Devlieghere | a9aab59 | 2018-01-29 14:52:50 +0000 | [diff] [blame] | 1327 | |
| 1328 | // Add an entry for the class name that points to this |
| 1329 | // method/class function. |
| 1330 | StringRef ClassName(ClassNameStart.data(), FirstSpace); |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 1331 | Unit.addObjCAccelerator(Die, StringPool.getEntry(ClassName), SkipPubSection); |
Jonas Devlieghere | a9aab59 | 2018-01-29 14:52:50 +0000 | [diff] [blame] | 1332 | |
| 1333 | if (ClassName[ClassName.size() - 1] == ')') { |
| 1334 | size_t OpenParens = ClassName.find('('); |
| 1335 | if (OpenParens != StringRef::npos) { |
| 1336 | StringRef ClassNameNoCategory(ClassName.data(), OpenParens); |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 1337 | Unit.addObjCAccelerator(Die, StringPool.getEntry(ClassNameNoCategory), |
| 1338 | SkipPubSection); |
Jonas Devlieghere | a9aab59 | 2018-01-29 14:52:50 +0000 | [diff] [blame] | 1339 | |
| 1340 | std::string MethodNameNoCategory(Name.getString().data(), OpenParens + 2); |
| 1341 | // FIXME: The missing space here may be a bug, but |
| 1342 | // dsymutil-classic also does it this way. |
| 1343 | MethodNameNoCategory.append(SelectorStart); |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 1344 | Unit.addNameAccelerator(Die, StringPool.getEntry(MethodNameNoCategory), |
Jonas Devlieghere | a9aab59 | 2018-01-29 14:52:50 +0000 | [diff] [blame] | 1345 | SkipPubSection); |
| 1346 | } |
| 1347 | } |
| 1348 | } |
| 1349 | |
Frederic Riss | 5f69f9f | 2015-09-11 04:17:30 +0000 | [diff] [blame] | 1350 | static bool |
| 1351 | shouldSkipAttribute(DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, |
| 1352 | uint16_t Tag, bool InDebugMap, bool SkipPC, |
| 1353 | bool InFunctionScope) { |
| 1354 | switch (AttrSpec.Attr) { |
| 1355 | default: |
| 1356 | return false; |
| 1357 | case dwarf::DW_AT_low_pc: |
| 1358 | case dwarf::DW_AT_high_pc: |
| 1359 | case dwarf::DW_AT_ranges: |
| 1360 | return SkipPC; |
| 1361 | case dwarf::DW_AT_location: |
| 1362 | case dwarf::DW_AT_frame_base: |
Jonas Devlieghere | 3ad0c5a | 2018-02-22 11:32:51 +0000 | [diff] [blame] | 1363 | // FIXME: for some reason dsymutil-classic keeps the location attributes |
| 1364 | // when they are of block type (i.e. not location lists). This is totally |
| 1365 | // wrong for globals where we will keep a wrong address. It is mostly |
| 1366 | // harmless for locals, but there is no point in keeping these anyway when |
| 1367 | // the function wasn't linked. |
Frederic Riss | 5f69f9f | 2015-09-11 04:17:30 +0000 | [diff] [blame] | 1368 | return (SkipPC || (!InFunctionScope && Tag == dwarf::DW_TAG_variable && |
| 1369 | !InDebugMap)) && |
| 1370 | !DWARFFormValue(AttrSpec.Form).isFormClass(DWARFFormValue::FC_Block); |
| 1371 | } |
| 1372 | } |
| 1373 | |
Jonas Devlieghere | 3ad0c5a | 2018-02-22 11:32:51 +0000 | [diff] [blame] | 1374 | DIE *DwarfLinker::DIECloner::cloneDIE(const DWARFDie &InputDIE, |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 1375 | const DebugMapObject &DMO, |
| 1376 | CompileUnit &Unit, |
| 1377 | OffsetsStringPool &StringPool, |
| 1378 | int64_t PCOffset, uint32_t OutOffset, |
| 1379 | unsigned Flags, DIE *Die) { |
Frederic Riss | d0d92e7 | 2015-03-04 22:07:44 +0000 | [diff] [blame] | 1380 | DWARFUnit &U = Unit.getOrigUnit(); |
Greg Clayton | adb170f | 2016-12-13 18:25:19 +0000 | [diff] [blame] | 1381 | unsigned Idx = U.getDIEIndex(InputDIE); |
Frederic Riss | fe78287 | 2015-03-06 23:22:53 +0000 | [diff] [blame] | 1382 | CompileUnit::DIEInfo &Info = Unit.getInfo(Idx); |
Frederic Riss | d0d92e7 | 2015-03-04 22:07:44 +0000 | [diff] [blame] | 1383 | |
| 1384 | // Should the DIE appear in the output? |
| 1385 | if (!Unit.getInfo(Idx).Keep) |
| 1386 | return nullptr; |
| 1387 | |
| 1388 | uint32_t Offset = InputDIE.getOffset(); |
Greg Clayton | fc1fc8b | 2016-12-01 18:56:29 +0000 | [diff] [blame] | 1389 | assert(!(Die && Info.Clone) && "Can't supply a DIE and a cloned DIE"); |
| 1390 | if (!Die) { |
| 1391 | // The DIE might have been already created by a forward reference |
| 1392 | // (see cloneDieReferenceAttribute()). |
David Blaikie | 2af4e8b | 2016-12-01 22:04:16 +0000 | [diff] [blame] | 1393 | if (!Info.Clone) |
| 1394 | Info.Clone = DIE::get(DIEAlloc, dwarf::Tag(InputDIE.getTag())); |
| 1395 | Die = Info.Clone; |
Greg Clayton | fc1fc8b | 2016-12-01 18:56:29 +0000 | [diff] [blame] | 1396 | } |
| 1397 | |
Frederic Riss | fe78287 | 2015-03-06 23:22:53 +0000 | [diff] [blame] | 1398 | assert(Die->getTag() == InputDIE.getTag()); |
Frederic Riss | d0d92e7 | 2015-03-04 22:07:44 +0000 | [diff] [blame] | 1399 | Die->setOffset(OutOffset); |
Jonas Devlieghere | 75475a8 | 2017-08-31 20:22:31 +0000 | [diff] [blame] | 1400 | if ((Unit.hasODR() || Unit.isClangModule()) && !Info.Incomplete && |
Adrian Prantl | 43df582 | 2015-09-23 17:35:52 +0000 | [diff] [blame] | 1401 | Die->getTag() != dwarf::DW_TAG_namespace && Info.Ctxt && |
Frederic Riss | 309fcf8 | 2015-07-21 22:41:43 +0000 | [diff] [blame] | 1402 | Info.Ctxt != Unit.getInfo(Info.ParentIdx).Ctxt && |
| 1403 | !Info.Ctxt->getCanonicalDIEOffset()) { |
| 1404 | // We are about to emit a DIE that is the root of its own valid |
| 1405 | // DeclContext tree. Make the current offset the canonical offset |
| 1406 | // for this context. |
| 1407 | Info.Ctxt->setCanonicalDIEOffset(OutOffset + Unit.getStartOffset()); |
| 1408 | } |
Frederic Riss | d0d92e7 | 2015-03-04 22:07:44 +0000 | [diff] [blame] | 1409 | |
| 1410 | // Extract and clone every attribute. |
Paul Robinson | 502fd5d | 2017-06-29 16:52:08 +0000 | [diff] [blame] | 1411 | DWARFDataExtractor Data = U.getDebugInfoExtractor(); |
Adrian Prantl | d2136b3 | 2015-09-22 22:20:50 +0000 | [diff] [blame] | 1412 | // Point to the next DIE (generally there is always at least a NULL |
| 1413 | // entry after the current one). If this is a lone |
| 1414 | // DW_TAG_compile_unit without any children, point to the next unit. |
Jonas Devlieghere | 3ad0c5a | 2018-02-22 11:32:51 +0000 | [diff] [blame] | 1415 | uint32_t NextOffset = (Idx + 1 < U.getNumDIEs()) |
| 1416 | ? U.getDIEAtIndex(Idx + 1).getOffset() |
| 1417 | : U.getNextUnitOffset(); |
Frederic Riss | 89393bb | 2015-03-11 18:45:52 +0000 | [diff] [blame] | 1418 | AttributesInfo AttrInfo; |
Frederic Riss | 3c8e619 | 2015-03-07 01:25:09 +0000 | [diff] [blame] | 1419 | |
Jonas Devlieghere | 3ad0c5a | 2018-02-22 11:32:51 +0000 | [diff] [blame] | 1420 | // We could copy the data only if we need to apply a relocation to it. After |
| 1421 | // testing, it seems there is no performance downside to doing the copy |
| 1422 | // unconditionally, and it makes the code simpler. |
Frederic Riss | 3c8e619 | 2015-03-07 01:25:09 +0000 | [diff] [blame] | 1423 | SmallString<40> DIECopy(Data.getData().substr(Offset, NextOffset - Offset)); |
Paul Robinson | 502fd5d | 2017-06-29 16:52:08 +0000 | [diff] [blame] | 1424 | Data = |
| 1425 | DWARFDataExtractor(DIECopy, Data.isLittleEndian(), Data.getAddressSize()); |
Frederic Riss | 3c8e619 | 2015-03-07 01:25:09 +0000 | [diff] [blame] | 1426 | // Modify the copy with relocated addresses. |
Adrian Prantl | 0a0a960 | 2015-09-11 23:45:30 +0000 | [diff] [blame] | 1427 | if (RelocMgr.applyValidRelocs(DIECopy, Offset, Data.isLittleEndian())) { |
Frederic Riss | 89393bb | 2015-03-11 18:45:52 +0000 | [diff] [blame] | 1428 | // If we applied relocations, we store the value of high_pc that was |
| 1429 | // potentially stored in the input DIE. If high_pc is an address |
| 1430 | // (Dwarf version == 2), then it might have been relocated to a |
| 1431 | // totally unrelated value (because the end address in the object |
| 1432 | // file might be start address of another function which got moved |
Jonas Devlieghere | 3ad0c5a | 2018-02-22 11:32:51 +0000 | [diff] [blame] | 1433 | // independently by the linker). The computation of the actual |
Frederic Riss | 89393bb | 2015-03-11 18:45:52 +0000 | [diff] [blame] | 1434 | // high_pc value is done in cloneAddressAttribute(). |
Adrian Prantl | 7f359b2 | 2017-09-30 00:22:24 +0000 | [diff] [blame] | 1435 | AttrInfo.OrigHighPc = |
| 1436 | dwarf::toAddress(InputDIE.find(dwarf::DW_AT_high_pc), 0); |
Frederic Riss | efe3016 | 2015-08-31 01:43:14 +0000 | [diff] [blame] | 1437 | // Also store the low_pc. It might get relocated in an |
| 1438 | // inline_subprogram that happens at the beginning of its |
| 1439 | // inlining function. |
Eugene Zelenko | 66f724e | 2017-11-01 21:16:06 +0000 | [diff] [blame] | 1440 | AttrInfo.OrigLowPc = dwarf::toAddress(InputDIE.find(dwarf::DW_AT_low_pc), |
| 1441 | std::numeric_limits<uint64_t>::max()); |
Frederic Riss | 89393bb | 2015-03-11 18:45:52 +0000 | [diff] [blame] | 1442 | } |
Frederic Riss | 3c8e619 | 2015-03-07 01:25:09 +0000 | [diff] [blame] | 1443 | |
| 1444 | // Reset the Offset to 0 as we will be working on the local copy of |
| 1445 | // the data. |
| 1446 | Offset = 0; |
| 1447 | |
Frederic Riss | d0d92e7 | 2015-03-04 22:07:44 +0000 | [diff] [blame] | 1448 | const auto *Abbrev = InputDIE.getAbbreviationDeclarationPtr(); |
| 1449 | Offset += getULEB128Size(Abbrev->getCode()); |
| 1450 | |
Frederic Riss | 89393bb | 2015-03-11 18:45:52 +0000 | [diff] [blame] | 1451 | // We are entering a subprogram. Get and propagate the PCOffset. |
| 1452 | if (Die->getTag() == dwarf::DW_TAG_subprogram) |
| 1453 | PCOffset = Info.AddrAdjust; |
| 1454 | AttrInfo.PCOffset = PCOffset; |
| 1455 | |
Frederic Riss | 5f69f9f | 2015-09-11 04:17:30 +0000 | [diff] [blame] | 1456 | if (Abbrev->getTag() == dwarf::DW_TAG_subprogram) { |
| 1457 | Flags |= TF_InFunctionScope; |
Jonas Devlieghere | 6169346 | 2018-02-08 10:48:54 +0000 | [diff] [blame] | 1458 | if (!Info.InDebugMap && LLVM_LIKELY(!Options.Update)) |
Frederic Riss | 5f69f9f | 2015-09-11 04:17:30 +0000 | [diff] [blame] | 1459 | Flags |= TF_SkipPC; |
| 1460 | } |
| 1461 | |
| 1462 | bool Copied = false; |
Frederic Riss | d0d92e7 | 2015-03-04 22:07:44 +0000 | [diff] [blame] | 1463 | for (const auto &AttrSpec : Abbrev->attributes()) { |
Jonas Devlieghere | 6169346 | 2018-02-08 10:48:54 +0000 | [diff] [blame] | 1464 | if (LLVM_LIKELY(!Options.Update) && |
| 1465 | shouldSkipAttribute(AttrSpec, Die->getTag(), Info.InDebugMap, |
Frederic Riss | 5f69f9f | 2015-09-11 04:17:30 +0000 | [diff] [blame] | 1466 | Flags & TF_SkipPC, Flags & TF_InFunctionScope)) { |
Paul Robinson | fd770ea | 2017-06-26 18:43:01 +0000 | [diff] [blame] | 1467 | DWARFFormValue::skipValue(AttrSpec.Form, Data, &Offset, |
| 1468 | U.getFormParams()); |
Frederic Riss | 5f69f9f | 2015-09-11 04:17:30 +0000 | [diff] [blame] | 1469 | // FIXME: dsymutil-classic keeps the old abbreviation around |
| 1470 | // even if it's not used. We can remove this (and the copyAbbrev |
| 1471 | // helper) as soon as bit-for-bit compatibility is not a goal anymore. |
| 1472 | if (!Copied) { |
| 1473 | copyAbbrev(*InputDIE.getAbbreviationDeclarationPtr(), Unit.hasODR()); |
| 1474 | Copied = true; |
| 1475 | } |
| 1476 | continue; |
| 1477 | } |
| 1478 | |
Frederic Riss | d0d92e7 | 2015-03-04 22:07:44 +0000 | [diff] [blame] | 1479 | DWARFFormValue Val(AttrSpec.Form); |
| 1480 | uint32_t AttrSize = Offset; |
Paul Robinson | e9d757c | 2017-11-07 19:57:12 +0000 | [diff] [blame] | 1481 | Val.extractValue(Data, &Offset, U.getFormParams(), &U); |
Frederic Riss | d0d92e7 | 2015-03-04 22:07:44 +0000 | [diff] [blame] | 1482 | AttrSize = Offset - AttrSize; |
| 1483 | |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 1484 | OutOffset += cloneAttribute(*Die, InputDIE, DMO, Unit, StringPool, Val, |
| 1485 | AttrSpec, AttrSize, AttrInfo); |
Frederic Riss | d0d92e7 | 2015-03-04 22:07:44 +0000 | [diff] [blame] | 1486 | } |
| 1487 | |
Frederic Riss | 991f3ea | 2015-03-16 02:05:10 +0000 | [diff] [blame] | 1488 | // Look for accelerator entries. |
| 1489 | uint16_t Tag = InputDIE.getTag(); |
| 1490 | // FIXME: This is slightly wrong. An inline_subroutine without a |
| 1491 | // low_pc, but with AT_ranges might be interesting to get into the |
| 1492 | // accelerator tables too. For now stick with dsymutil's behavior. |
Jonas Devlieghere | a9aab59 | 2018-01-29 14:52:50 +0000 | [diff] [blame] | 1493 | if ((Info.InDebugMap || AttrInfo.HasLowPc || AttrInfo.HasRanges) && |
Frederic Riss | 991f3ea | 2015-03-16 02:05:10 +0000 | [diff] [blame] | 1494 | Tag != dwarf::DW_TAG_compile_unit && |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 1495 | getDIENames(InputDIE, AttrInfo, StringPool, |
Jonas Devlieghere | a9aab59 | 2018-01-29 14:52:50 +0000 | [diff] [blame] | 1496 | Tag != dwarf::DW_TAG_inlined_subroutine)) { |
Frederic Riss | 991f3ea | 2015-03-16 02:05:10 +0000 | [diff] [blame] | 1497 | if (AttrInfo.MangledName && AttrInfo.MangledName != AttrInfo.Name) |
| 1498 | Unit.addNameAccelerator(Die, AttrInfo.MangledName, |
Frederic Riss | 991f3ea | 2015-03-16 02:05:10 +0000 | [diff] [blame] | 1499 | Tag == dwarf::DW_TAG_inlined_subroutine); |
Jonas Devlieghere | a9aab59 | 2018-01-29 14:52:50 +0000 | [diff] [blame] | 1500 | if (AttrInfo.Name) { |
| 1501 | if (AttrInfo.NameWithoutTemplate) |
| 1502 | Unit.addNameAccelerator(Die, AttrInfo.NameWithoutTemplate, |
| 1503 | /* SkipPubSection */ true); |
| 1504 | Unit.addNameAccelerator(Die, AttrInfo.Name, |
Frederic Riss | 991f3ea | 2015-03-16 02:05:10 +0000 | [diff] [blame] | 1505 | Tag == dwarf::DW_TAG_inlined_subroutine); |
Jonas Devlieghere | a9aab59 | 2018-01-29 14:52:50 +0000 | [diff] [blame] | 1506 | } |
| 1507 | if (AttrInfo.Name && isObjCSelector(AttrInfo.Name.getString())) |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 1508 | addObjCAccelerator(Unit, Die, AttrInfo.Name, StringPool, |
| 1509 | /* SkipPubSection =*/true); |
Jonas Devlieghere | a9aab59 | 2018-01-29 14:52:50 +0000 | [diff] [blame] | 1510 | |
| 1511 | } else if (Tag == dwarf::DW_TAG_namespace) { |
| 1512 | if (!AttrInfo.Name) |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 1513 | AttrInfo.Name = StringPool.getEntry("(anonymous namespace)"); |
Jonas Devlieghere | a9aab59 | 2018-01-29 14:52:50 +0000 | [diff] [blame] | 1514 | Unit.addNamespaceAccelerator(Die, AttrInfo.Name); |
Frederic Riss | 991f3ea | 2015-03-16 02:05:10 +0000 | [diff] [blame] | 1515 | } else if (isTypeTag(Tag) && !AttrInfo.IsDeclaration && |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 1516 | getDIENames(InputDIE, AttrInfo, StringPool) && AttrInfo.Name && |
Jonas Devlieghere | a9aab59 | 2018-01-29 14:52:50 +0000 | [diff] [blame] | 1517 | AttrInfo.Name.getString()[0]) { |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 1518 | uint32_t Hash = hashFullyQualifiedName(InputDIE, Unit, DMO); |
Jonas Devlieghere | a9aab59 | 2018-01-29 14:52:50 +0000 | [diff] [blame] | 1519 | uint64_t RuntimeLang = |
| 1520 | dwarf::toUnsigned(InputDIE.find(dwarf::DW_AT_APPLE_runtime_class)) |
| 1521 | .getValueOr(0); |
| 1522 | bool ObjCClassIsImplementation = |
| 1523 | (RuntimeLang == dwarf::DW_LANG_ObjC || |
| 1524 | RuntimeLang == dwarf::DW_LANG_ObjC_plus_plus) && |
| 1525 | dwarf::toUnsigned(InputDIE.find(dwarf::DW_AT_APPLE_objc_complete_type)) |
| 1526 | .getValueOr(0); |
| 1527 | Unit.addTypeAccelerator(Die, AttrInfo.Name, ObjCClassIsImplementation, |
| 1528 | Hash); |
Frederic Riss | 991f3ea | 2015-03-16 02:05:10 +0000 | [diff] [blame] | 1529 | } |
| 1530 | |
Adrian Prantl | b29f9e5 | 2015-11-10 21:31:05 +0000 | [diff] [blame] | 1531 | // Determine whether there are any children that we want to keep. |
| 1532 | bool HasChildren = false; |
Jonas Devlieghere | a9aab59 | 2018-01-29 14:52:50 +0000 | [diff] [blame] | 1533 | for (auto Child : InputDIE.children()) { |
Adrian Prantl | b29f9e5 | 2015-11-10 21:31:05 +0000 | [diff] [blame] | 1534 | unsigned Idx = U.getDIEIndex(Child); |
| 1535 | if (Unit.getInfo(Idx).Keep) { |
| 1536 | HasChildren = true; |
| 1537 | break; |
| 1538 | } |
| 1539 | } |
| 1540 | |
Duncan P. N. Exon Smith | 611a2f2 | 2015-05-27 22:31:41 +0000 | [diff] [blame] | 1541 | DIEAbbrev NewAbbrev = Die->generateAbbrev(); |
Adrian Prantl | b29f9e5 | 2015-11-10 21:31:05 +0000 | [diff] [blame] | 1542 | if (HasChildren) |
Frederic Riss | d0d92e7 | 2015-03-04 22:07:44 +0000 | [diff] [blame] | 1543 | NewAbbrev.setChildrenFlag(dwarf::DW_CHILDREN_yes); |
| 1544 | // Assign a permanent abbrev number |
Adrian Prantl | afca6b4 | 2015-09-14 16:46:10 +0000 | [diff] [blame] | 1545 | Linker.AssignAbbrev(NewAbbrev); |
Duncan P. N. Exon Smith | 611a2f2 | 2015-05-27 22:31:41 +0000 | [diff] [blame] | 1546 | Die->setAbbrevNumber(NewAbbrev.getNumber()); |
Frederic Riss | d0d92e7 | 2015-03-04 22:07:44 +0000 | [diff] [blame] | 1547 | |
| 1548 | // Add the size of the abbreviation number to the output offset. |
| 1549 | OutOffset += getULEB128Size(Die->getAbbrevNumber()); |
| 1550 | |
Adrian Prantl | b29f9e5 | 2015-11-10 21:31:05 +0000 | [diff] [blame] | 1551 | if (!HasChildren) { |
Frederic Riss | d0d92e7 | 2015-03-04 22:07:44 +0000 | [diff] [blame] | 1552 | // Update our size. |
| 1553 | Die->setSize(OutOffset - Die->getOffset()); |
| 1554 | return Die; |
| 1555 | } |
| 1556 | |
| 1557 | // Recursively clone children. |
Jonas Devlieghere | 3ad0c5a | 2018-02-22 11:32:51 +0000 | [diff] [blame] | 1558 | for (auto Child : InputDIE.children()) { |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 1559 | if (DIE *Clone = cloneDIE(Child, DMO, Unit, StringPool, PCOffset, OutOffset, |
| 1560 | Flags)) { |
Duncan P. N. Exon Smith | 2da1484 | 2015-06-25 23:52:10 +0000 | [diff] [blame] | 1561 | Die->addChild(Clone); |
Frederic Riss | d0d92e7 | 2015-03-04 22:07:44 +0000 | [diff] [blame] | 1562 | OutOffset = Clone->getOffset() + Clone->getSize(); |
| 1563 | } |
| 1564 | } |
| 1565 | |
| 1566 | // Account for the end of children marker. |
| 1567 | OutOffset += sizeof(int8_t); |
| 1568 | // Update our size. |
| 1569 | Die->setSize(OutOffset - Die->getOffset()); |
| 1570 | return Die; |
| 1571 | } |
| 1572 | |
Adrian Prantl | 90d56f0 | 2017-07-21 16:51:17 +0000 | [diff] [blame] | 1573 | /// Patch the input object file relevant debug_ranges entries |
Frederic Riss | e031501 | 2015-03-13 23:30:31 +0000 | [diff] [blame] | 1574 | /// and emit them in the output file. Update the relevant attributes |
| 1575 | /// to point at the new entries. |
| 1576 | void DwarfLinker::patchRangesForUnit(const CompileUnit &Unit, |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 1577 | DWARFContext &OrigDwarf, |
| 1578 | const DebugMapObject &DMO) const { |
Wolfgang Pieb | daecf94 | 2018-10-31 01:12:58 +0000 | [diff] [blame] | 1579 | DWARFDebugRangeList RangeList; |
Frederic Riss | e031501 | 2015-03-13 23:30:31 +0000 | [diff] [blame] | 1580 | const auto &FunctionRanges = Unit.getFunctionRanges(); |
| 1581 | unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize(); |
Rafael Espindola | ee809ac | 2017-07-19 22:27:28 +0000 | [diff] [blame] | 1582 | DWARFDataExtractor RangeExtractor(OrigDwarf.getDWARFObj(), |
| 1583 | OrigDwarf.getDWARFObj().getRangeSection(), |
Paul Robinson | 502fd5d | 2017-06-29 16:52:08 +0000 | [diff] [blame] | 1584 | OrigDwarf.isLittleEndian(), AddressSize); |
Frederic Riss | e031501 | 2015-03-13 23:30:31 +0000 | [diff] [blame] | 1585 | auto InvalidRange = FunctionRanges.end(), CurrRange = InvalidRange; |
| 1586 | DWARFUnit &OrigUnit = Unit.getOrigUnit(); |
Greg Clayton | adb170f | 2016-12-13 18:25:19 +0000 | [diff] [blame] | 1587 | auto OrigUnitDie = OrigUnit.getUnitDIE(false); |
Adrian Prantl | 7f359b2 | 2017-09-30 00:22:24 +0000 | [diff] [blame] | 1588 | uint64_t OrigLowPc = |
| 1589 | dwarf::toAddress(OrigUnitDie.find(dwarf::DW_AT_low_pc), -1ULL); |
Frederic Riss | e031501 | 2015-03-13 23:30:31 +0000 | [diff] [blame] | 1590 | // Ranges addresses are based on the unit's low_pc. Compute the |
Sanjay Patel | 322ee9e | 2015-12-07 19:21:39 +0000 | [diff] [blame] | 1591 | // offset we need to apply to adapt to the new unit's low_pc. |
Frederic Riss | e031501 | 2015-03-13 23:30:31 +0000 | [diff] [blame] | 1592 | int64_t UnitPcOffset = 0; |
| 1593 | if (OrigLowPc != -1ULL) |
| 1594 | UnitPcOffset = int64_t(OrigLowPc) - Unit.getLowPc(); |
| 1595 | |
| 1596 | for (const auto &RangeAttribute : Unit.getRangesAttributes()) { |
Duncan P. N. Exon Smith | 09fe4bf | 2015-05-27 22:14:58 +0000 | [diff] [blame] | 1597 | uint32_t Offset = RangeAttribute.get(); |
| 1598 | RangeAttribute.set(Streamer->getRangesSectionSize()); |
Wolfgang Pieb | daecf94 | 2018-10-31 01:12:58 +0000 | [diff] [blame] | 1599 | if (Error E = RangeList.extract(RangeExtractor, &Offset)) { |
Wolfgang Pieb | 5a4174c | 2018-06-20 22:56:37 +0000 | [diff] [blame] | 1600 | llvm::consumeError(std::move(E)); |
| 1601 | reportWarning("invalid range list ignored.", DMO); |
| 1602 | RangeList.clear(); |
| 1603 | } |
Frederic Riss | e031501 | 2015-03-13 23:30:31 +0000 | [diff] [blame] | 1604 | const auto &Entries = RangeList.getEntries(); |
Wolfgang Pieb | daecf94 | 2018-10-31 01:12:58 +0000 | [diff] [blame] | 1605 | if (!Entries.empty()) { |
| 1606 | const DWARFDebugRangeList::RangeListEntry &First = Entries.front(); |
| 1607 | |
Frederic Riss | e031501 | 2015-03-13 23:30:31 +0000 | [diff] [blame] | 1608 | if (CurrRange == InvalidRange || |
Wolfgang Pieb | daecf94 | 2018-10-31 01:12:58 +0000 | [diff] [blame] | 1609 | First.StartAddress + OrigLowPc < CurrRange.start() || |
| 1610 | First.StartAddress + OrigLowPc >= CurrRange.stop()) { |
| 1611 | CurrRange = FunctionRanges.find(First.StartAddress + OrigLowPc); |
Frederic Riss | 9be5804 | 2015-08-31 05:09:32 +0000 | [diff] [blame] | 1612 | if (CurrRange == InvalidRange || |
Wolfgang Pieb | daecf94 | 2018-10-31 01:12:58 +0000 | [diff] [blame] | 1613 | CurrRange.start() > First.StartAddress + OrigLowPc) { |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 1614 | reportWarning("no mapping for range.", DMO); |
Frederic Riss | 9be5804 | 2015-08-31 05:09:32 +0000 | [diff] [blame] | 1615 | continue; |
| 1616 | } |
Frederic Riss | e031501 | 2015-03-13 23:30:31 +0000 | [diff] [blame] | 1617 | } |
| 1618 | } |
| 1619 | |
Wolfgang Pieb | daecf94 | 2018-10-31 01:12:58 +0000 | [diff] [blame] | 1620 | Streamer->emitRangesEntries(UnitPcOffset, OrigLowPc, CurrRange, Entries, |
Frederic Riss | e031501 | 2015-03-13 23:30:31 +0000 | [diff] [blame] | 1621 | AddressSize); |
| 1622 | } |
| 1623 | } |
| 1624 | |
Adrian Prantl | 90d56f0 | 2017-07-21 16:51:17 +0000 | [diff] [blame] | 1625 | /// Generate the debug_aranges entries for \p Unit and if the |
Frederic Riss | 9786d3d | 2015-03-14 03:46:51 +0000 | [diff] [blame] | 1626 | /// unit has a DW_AT_ranges attribute, also emit the debug_ranges |
| 1627 | /// contribution for this attribute. |
Frederic Riss | e031501 | 2015-03-13 23:30:31 +0000 | [diff] [blame] | 1628 | /// FIXME: this could actually be done right in patchRangesForUnit, |
| 1629 | /// but for the sake of initial bit-for-bit compatibility with legacy |
| 1630 | /// dsymutil, we have to do it in a delayed pass. |
| 1631 | void DwarfLinker::generateUnitRanges(CompileUnit &Unit) const { |
Duncan P. N. Exon Smith | 09fe4bf | 2015-05-27 22:14:58 +0000 | [diff] [blame] | 1632 | auto Attr = Unit.getUnitRangesAttribute(); |
Frederic Riss | 9786d3d | 2015-03-14 03:46:51 +0000 | [diff] [blame] | 1633 | if (Attr) |
Duncan P. N. Exon Smith | 09fe4bf | 2015-05-27 22:14:58 +0000 | [diff] [blame] | 1634 | Attr->set(Streamer->getRangesSectionSize()); |
| 1635 | Streamer->emitUnitRangesEntries(Unit, static_cast<bool>(Attr)); |
Frederic Riss | e031501 | 2015-03-13 23:30:31 +0000 | [diff] [blame] | 1636 | } |
| 1637 | |
Adrian Prantl | 90d56f0 | 2017-07-21 16:51:17 +0000 | [diff] [blame] | 1638 | /// Insert the new line info sequence \p Seq into the current |
Frederic Riss | e6412a6 | 2015-03-15 20:45:43 +0000 | [diff] [blame] | 1639 | /// set of already linked line info \p Rows. |
| 1640 | static void insertLineSequence(std::vector<DWARFDebugLine::Row> &Seq, |
| 1641 | std::vector<DWARFDebugLine::Row> &Rows) { |
| 1642 | if (Seq.empty()) |
| 1643 | return; |
| 1644 | |
| 1645 | if (!Rows.empty() && Rows.back().Address < Seq.front().Address) { |
| 1646 | Rows.insert(Rows.end(), Seq.begin(), Seq.end()); |
| 1647 | Seq.clear(); |
| 1648 | return; |
| 1649 | } |
| 1650 | |
| 1651 | auto InsertPoint = std::lower_bound( |
| 1652 | Rows.begin(), Rows.end(), Seq.front(), |
| 1653 | [](const DWARFDebugLine::Row &LHS, const DWARFDebugLine::Row &RHS) { |
| 1654 | return LHS.Address < RHS.Address; |
| 1655 | }); |
| 1656 | |
| 1657 | // FIXME: this only removes the unneeded end_sequence if the |
Jonas Devlieghere | 3ad0c5a | 2018-02-22 11:32:51 +0000 | [diff] [blame] | 1658 | // sequences have been inserted in order. Using a global sort like |
Frederic Riss | e6412a6 | 2015-03-15 20:45:43 +0000 | [diff] [blame] | 1659 | // described in patchLineTableForUnit() and delaying the end_sequene |
| 1660 | // elimination to emitLineTableForUnit() we can get rid of all of them. |
| 1661 | if (InsertPoint != Rows.end() && |
| 1662 | InsertPoint->Address == Seq.front().Address && InsertPoint->EndSequence) { |
| 1663 | *InsertPoint = Seq.front(); |
| 1664 | Rows.insert(InsertPoint + 1, Seq.begin() + 1, Seq.end()); |
| 1665 | } else { |
| 1666 | Rows.insert(InsertPoint, Seq.begin(), Seq.end()); |
| 1667 | } |
| 1668 | |
| 1669 | Seq.clear(); |
| 1670 | } |
| 1671 | |
Duncan P. N. Exon Smith | ee46b79 | 2015-06-25 21:42:46 +0000 | [diff] [blame] | 1672 | static void patchStmtList(DIE &Die, DIEInteger Offset) { |
| 1673 | for (auto &V : Die.values()) |
| 1674 | if (V.getAttribute() == dwarf::DW_AT_stmt_list) { |
Duncan P. N. Exon Smith | 73e3fb6 | 2015-06-25 23:46:41 +0000 | [diff] [blame] | 1675 | V = DIEValue(V.getAttribute(), V.getForm(), Offset); |
Duncan P. N. Exon Smith | ee46b79 | 2015-06-25 21:42:46 +0000 | [diff] [blame] | 1676 | return; |
| 1677 | } |
| 1678 | |
| 1679 | llvm_unreachable("Didn't find DW_AT_stmt_list in cloned DIE!"); |
| 1680 | } |
| 1681 | |
Adrian Prantl | 90d56f0 | 2017-07-21 16:51:17 +0000 | [diff] [blame] | 1682 | /// Extract the line table for \p Unit from \p OrigDwarf, and |
Frederic Riss | e6412a6 | 2015-03-15 20:45:43 +0000 | [diff] [blame] | 1683 | /// recreate a relocated version of these for the address ranges that |
| 1684 | /// are present in the binary. |
| 1685 | void DwarfLinker::patchLineTableForUnit(CompileUnit &Unit, |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 1686 | DWARFContext &OrigDwarf, |
| 1687 | RangesTy &Ranges, |
| 1688 | const DebugMapObject &DMO) { |
Greg Clayton | adb170f | 2016-12-13 18:25:19 +0000 | [diff] [blame] | 1689 | DWARFDie CUDie = Unit.getOrigUnit().getUnitDIE(); |
Greg Clayton | beabb63 | 2017-01-13 21:08:18 +0000 | [diff] [blame] | 1690 | auto StmtList = dwarf::toSectionOffset(CUDie.find(dwarf::DW_AT_stmt_list)); |
Greg Clayton | c64f919 | 2016-12-14 22:38:08 +0000 | [diff] [blame] | 1691 | if (!StmtList) |
Frederic Riss | e6412a6 | 2015-03-15 20:45:43 +0000 | [diff] [blame] | 1692 | return; |
| 1693 | |
| 1694 | // Update the cloned DW_AT_stmt_list with the correct debug_line offset. |
Duncan P. N. Exon Smith | ee46b79 | 2015-06-25 21:42:46 +0000 | [diff] [blame] | 1695 | if (auto *OutputDIE = Unit.getOutputUnitDIE()) |
| 1696 | patchStmtList(*OutputDIE, DIEInteger(Streamer->getLineSectionSize())); |
Frederic Riss | e6412a6 | 2015-03-15 20:45:43 +0000 | [diff] [blame] | 1697 | |
| 1698 | // Parse the original line info for the unit. |
| 1699 | DWARFDebugLine::LineTable LineTable; |
Greg Clayton | c64f919 | 2016-12-14 22:38:08 +0000 | [diff] [blame] | 1700 | uint32_t StmtOffset = *StmtList; |
Rafael Espindola | ee809ac | 2017-07-19 22:27:28 +0000 | [diff] [blame] | 1701 | DWARFDataExtractor LineExtractor( |
| 1702 | OrigDwarf.getDWARFObj(), OrigDwarf.getDWARFObj().getLineSection(), |
| 1703 | OrigDwarf.isLittleEndian(), Unit.getOrigUnit().getAddressByteSize()); |
Jonas Devlieghere | 20767d1 | 2019-01-07 23:27:25 +0000 | [diff] [blame] | 1704 | if (Options.Translator) |
| 1705 | return Streamer->translateLineTable(LineExtractor, StmtOffset, Options); |
James Henderson | b826631 | 2018-05-10 10:51:33 +0000 | [diff] [blame] | 1706 | |
| 1707 | Error Err = LineTable.parse(LineExtractor, &StmtOffset, OrigDwarf, |
Victor Leschuk | 271b93a | 2018-08-23 12:43:33 +0000 | [diff] [blame] | 1708 | &Unit.getOrigUnit(), DWARFContext::dumpWarning); |
| 1709 | DWARFContext::dumpWarning(std::move(Err)); |
Frederic Riss | e6412a6 | 2015-03-15 20:45:43 +0000 | [diff] [blame] | 1710 | |
| 1711 | // This vector is the output line table. |
| 1712 | std::vector<DWARFDebugLine::Row> NewRows; |
| 1713 | NewRows.reserve(LineTable.Rows.size()); |
| 1714 | |
| 1715 | // Current sequence of rows being extracted, before being inserted |
| 1716 | // in NewRows. |
| 1717 | std::vector<DWARFDebugLine::Row> Seq; |
| 1718 | const auto &FunctionRanges = Unit.getFunctionRanges(); |
| 1719 | auto InvalidRange = FunctionRanges.end(), CurrRange = InvalidRange; |
| 1720 | |
| 1721 | // FIXME: This logic is meant to generate exactly the same output as |
Jonas Devlieghere | 3ad0c5a | 2018-02-22 11:32:51 +0000 | [diff] [blame] | 1722 | // Darwin's classic dsymutil. There is a nicer way to implement this |
Frederic Riss | e6412a6 | 2015-03-15 20:45:43 +0000 | [diff] [blame] | 1723 | // by simply putting all the relocated line info in NewRows and simply |
| 1724 | // sorting NewRows before passing it to emitLineTableForUnit. This |
| 1725 | // should be correct as sequences for a function should stay |
| 1726 | // together in the sorted output. There are a few corner cases that |
| 1727 | // look suspicious though, and that required to implement the logic |
| 1728 | // this way. Revisit that once initial validation is finished. |
| 1729 | |
| 1730 | // Iterate over the object file line info and extract the sequences |
| 1731 | // that correspond to linked functions. |
| 1732 | for (auto &Row : LineTable.Rows) { |
Jonas Devlieghere | 3ad0c5a | 2018-02-22 11:32:51 +0000 | [diff] [blame] | 1733 | // Check whether we stepped out of the range. The range is |
Frederic Riss | e6412a6 | 2015-03-15 20:45:43 +0000 | [diff] [blame] | 1734 | // half-open, but consider accept the end address of the range if |
| 1735 | // it is marked as end_sequence in the input (because in that |
| 1736 | // case, the relocation offset is accurate and that entry won't |
| 1737 | // serve as the start of another function). |
| 1738 | if (CurrRange == InvalidRange || Row.Address < CurrRange.start() || |
| 1739 | Row.Address > CurrRange.stop() || |
| 1740 | (Row.Address == CurrRange.stop() && !Row.EndSequence)) { |
| 1741 | // We just stepped out of a known range. Insert a end_sequence |
| 1742 | // corresponding to the end of the range. |
| 1743 | uint64_t StopAddress = CurrRange != InvalidRange |
| 1744 | ? CurrRange.stop() + CurrRange.value() |
| 1745 | : -1ULL; |
| 1746 | CurrRange = FunctionRanges.find(Row.Address); |
| 1747 | bool CurrRangeValid = |
| 1748 | CurrRange != InvalidRange && CurrRange.start() <= Row.Address; |
| 1749 | if (!CurrRangeValid) { |
| 1750 | CurrRange = InvalidRange; |
| 1751 | if (StopAddress != -1ULL) { |
| 1752 | // Try harder by looking in the DebugMapObject function |
| 1753 | // ranges map. There are corner cases where this finds a |
| 1754 | // valid entry. It's unclear if this is right or wrong, but |
| 1755 | // for now do as dsymutil. |
| 1756 | // FIXME: Understand exactly what cases this addresses and |
| 1757 | // potentially remove it along with the Ranges map. |
| 1758 | auto Range = Ranges.lower_bound(Row.Address); |
| 1759 | if (Range != Ranges.begin() && Range != Ranges.end()) |
| 1760 | --Range; |
| 1761 | |
| 1762 | if (Range != Ranges.end() && Range->first <= Row.Address && |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 1763 | Range->second.HighPC >= Row.Address) { |
| 1764 | StopAddress = Row.Address + Range->second.Offset; |
Frederic Riss | e6412a6 | 2015-03-15 20:45:43 +0000 | [diff] [blame] | 1765 | } |
| 1766 | } |
| 1767 | } |
| 1768 | if (StopAddress != -1ULL && !Seq.empty()) { |
| 1769 | // Insert end sequence row with the computed end address, but |
| 1770 | // the same line as the previous one. |
Yaron Keren | ccc3705 | 2015-08-10 16:15:51 +0000 | [diff] [blame] | 1771 | auto NextLine = Seq.back(); |
Yaron Keren | 99b2ac6 | 2015-08-10 18:27:51 +0000 | [diff] [blame] | 1772 | NextLine.Address = StopAddress; |
| 1773 | NextLine.EndSequence = 1; |
| 1774 | NextLine.PrologueEnd = 0; |
| 1775 | NextLine.BasicBlock = 0; |
| 1776 | NextLine.EpilogueBegin = 0; |
Yaron Keren | af1c9b3 | 2015-08-10 18:03:35 +0000 | [diff] [blame] | 1777 | Seq.push_back(NextLine); |
Frederic Riss | e6412a6 | 2015-03-15 20:45:43 +0000 | [diff] [blame] | 1778 | insertLineSequence(Seq, NewRows); |
| 1779 | } |
| 1780 | |
| 1781 | if (!CurrRangeValid) |
| 1782 | continue; |
| 1783 | } |
| 1784 | |
| 1785 | // Ignore empty sequences. |
| 1786 | if (Row.EndSequence && Seq.empty()) |
| 1787 | continue; |
| 1788 | |
| 1789 | // Relocate row address and add it to the current sequence. |
| 1790 | Row.Address += CurrRange.value(); |
| 1791 | Seq.emplace_back(Row); |
| 1792 | |
| 1793 | if (Row.EndSequence) |
| 1794 | insertLineSequence(Seq, NewRows); |
| 1795 | } |
| 1796 | |
| 1797 | // Finished extracting, now emit the line tables. |
Jonas Devlieghere | 3ad0c5a | 2018-02-22 11:32:51 +0000 | [diff] [blame] | 1798 | // FIXME: LLVM hard-codes its prologue values. We just copy the |
Frederic Riss | e6412a6 | 2015-03-15 20:45:43 +0000 | [diff] [blame] | 1799 | // prologue over and that works because we act as both producer and |
| 1800 | // consumer. It would be nicer to have a real configurable line |
| 1801 | // table emitter. |
Jonas Devlieghere | e75cd38 | 2017-12-12 11:32:21 +0000 | [diff] [blame] | 1802 | if (LineTable.Prologue.getVersion() < 2 || |
| 1803 | LineTable.Prologue.getVersion() > 5 || |
Frederic Riss | e6412a6 | 2015-03-15 20:45:43 +0000 | [diff] [blame] | 1804 | LineTable.Prologue.DefaultIsStmt != DWARF2_LINE_DEFAULT_IS_STMT || |
Frederic Riss | 54c40cf | 2015-08-07 15:14:13 +0000 | [diff] [blame] | 1805 | LineTable.Prologue.OpcodeBase > 13) |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 1806 | reportWarning("line table parameters mismatch. Cannot emit.", DMO); |
Frederic Riss | 54c40cf | 2015-08-07 15:14:13 +0000 | [diff] [blame] | 1807 | else { |
Jonas Devlieghere | e75cd38 | 2017-12-12 11:32:21 +0000 | [diff] [blame] | 1808 | uint32_t PrologueEnd = *StmtList + 10 + LineTable.Prologue.PrologueLength; |
Jonas Devlieghere | 217ad73 | 2018-02-01 10:19:56 +0000 | [diff] [blame] | 1809 | // DWARF v5 has an extra 2 bytes of information before the header_length |
Jonas Devlieghere | e75cd38 | 2017-12-12 11:32:21 +0000 | [diff] [blame] | 1810 | // field. |
| 1811 | if (LineTable.Prologue.getVersion() == 5) |
| 1812 | PrologueEnd += 2; |
Rafael Espindola | ee809ac | 2017-07-19 22:27:28 +0000 | [diff] [blame] | 1813 | StringRef LineData = OrigDwarf.getDWARFObj().getLineSection().Data; |
Frederic Riss | 54c40cf | 2015-08-07 15:14:13 +0000 | [diff] [blame] | 1814 | MCDwarfLineTableParams Params; |
| 1815 | Params.DWARF2LineOpcodeBase = LineTable.Prologue.OpcodeBase; |
| 1816 | Params.DWARF2LineBase = LineTable.Prologue.LineBase; |
| 1817 | Params.DWARF2LineRange = LineTable.Prologue.LineRange; |
| 1818 | Streamer->emitLineTableForUnit(Params, |
Greg Clayton | c64f919 | 2016-12-14 22:38:08 +0000 | [diff] [blame] | 1819 | LineData.slice(*StmtList + 4, PrologueEnd), |
Frederic Riss | e6412a6 | 2015-03-15 20:45:43 +0000 | [diff] [blame] | 1820 | LineTable.Prologue.MinInstLength, NewRows, |
| 1821 | Unit.getOrigUnit().getAddressByteSize()); |
Frederic Riss | 54c40cf | 2015-08-07 15:14:13 +0000 | [diff] [blame] | 1822 | } |
Frederic Riss | e6412a6 | 2015-03-15 20:45:43 +0000 | [diff] [blame] | 1823 | } |
| 1824 | |
Frederic Riss | 991f3ea | 2015-03-16 02:05:10 +0000 | [diff] [blame] | 1825 | void DwarfLinker::emitAcceleratorEntriesForUnit(CompileUnit &Unit) { |
Jonas Devlieghere | 7c767bd | 2018-07-25 23:01:38 +0000 | [diff] [blame] | 1826 | switch (Options.TheAccelTableKind) { |
| 1827 | case AccelTableKind::Apple: |
| 1828 | emitAppleAcceleratorEntriesForUnit(Unit); |
| 1829 | break; |
| 1830 | case AccelTableKind::Dwarf: |
| 1831 | emitDwarfAcceleratorEntriesForUnit(Unit); |
| 1832 | break; |
| 1833 | case AccelTableKind::Default: |
| 1834 | llvm_unreachable("The default must be updated to a concrete value."); |
| 1835 | break; |
| 1836 | } |
| 1837 | } |
| 1838 | |
| 1839 | void DwarfLinker::emitAppleAcceleratorEntriesForUnit(CompileUnit &Unit) { |
Jonas Devlieghere | a9aab59 | 2018-01-29 14:52:50 +0000 | [diff] [blame] | 1840 | // Add namespaces. |
| 1841 | for (const auto &Namespace : Unit.getNamespaces()) |
| 1842 | AppleNamespaces.addName(Namespace.Name, |
| 1843 | Namespace.Die->getOffset() + Unit.getStartOffset()); |
| 1844 | |
| 1845 | /// Add names. |
| 1846 | if (!Options.Minimize) |
| 1847 | Streamer->emitPubNamesForUnit(Unit); |
| 1848 | for (const auto &Pubname : Unit.getPubnames()) |
| 1849 | AppleNames.addName(Pubname.Name, |
| 1850 | Pubname.Die->getOffset() + Unit.getStartOffset()); |
| 1851 | |
| 1852 | /// Add types. |
| 1853 | if (!Options.Minimize) |
| 1854 | Streamer->emitPubTypesForUnit(Unit); |
| 1855 | for (const auto &Pubtype : Unit.getPubtypes()) |
| 1856 | AppleTypes.addName( |
| 1857 | Pubtype.Name, Pubtype.Die->getOffset() + Unit.getStartOffset(), |
| 1858 | Pubtype.Die->getTag(), |
| 1859 | Pubtype.ObjcClassImplementation ? dwarf::DW_FLAG_type_implementation |
| 1860 | : 0, |
| 1861 | Pubtype.QualifiedNameHash); |
| 1862 | |
| 1863 | /// Add ObjC names. |
| 1864 | for (const auto &ObjC : Unit.getObjC()) |
| 1865 | AppleObjc.addName(ObjC.Name, ObjC.Die->getOffset() + Unit.getStartOffset()); |
Frederic Riss | 991f3ea | 2015-03-16 02:05:10 +0000 | [diff] [blame] | 1866 | } |
| 1867 | |
Jonas Devlieghere | 7c767bd | 2018-07-25 23:01:38 +0000 | [diff] [blame] | 1868 | void DwarfLinker::emitDwarfAcceleratorEntriesForUnit(CompileUnit &Unit) { |
| 1869 | for (const auto &Namespace : Unit.getNamespaces()) |
| 1870 | DebugNames.addName(Namespace.Name, Namespace.Die->getOffset(), |
| 1871 | Namespace.Die->getTag(), Unit.getUniqueID()); |
| 1872 | for (const auto &Pubname : Unit.getPubnames()) |
| 1873 | DebugNames.addName(Pubname.Name, Pubname.Die->getOffset(), |
| 1874 | Pubname.Die->getTag(), Unit.getUniqueID()); |
| 1875 | for (const auto &Pubtype : Unit.getPubtypes()) |
| 1876 | DebugNames.addName(Pubtype.Name, Pubtype.Die->getOffset(), |
| 1877 | Pubtype.Die->getTag(), Unit.getUniqueID()); |
| 1878 | } |
| 1879 | |
Adrian Prantl | 90d56f0 | 2017-07-21 16:51:17 +0000 | [diff] [blame] | 1880 | /// Read the frame info stored in the object, and emit the |
Frederic Riss | 9ccf07f | 2015-06-05 23:06:11 +0000 | [diff] [blame] | 1881 | /// patched frame descriptions for the linked binary. |
| 1882 | /// |
| 1883 | /// This is actually pretty easy as the data of the CIEs and FDEs can |
| 1884 | /// be considered as black boxes and moved as is. The only thing to do |
| 1885 | /// is to patch the addresses in the headers. |
| 1886 | void DwarfLinker::patchFrameInfoForObject(const DebugMapObject &DMO, |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 1887 | RangesTy &Ranges, |
Frederic Riss | 9ccf07f | 2015-06-05 23:06:11 +0000 | [diff] [blame] | 1888 | DWARFContext &OrigDwarf, |
| 1889 | unsigned AddrSize) { |
Rafael Espindola | ee809ac | 2017-07-19 22:27:28 +0000 | [diff] [blame] | 1890 | StringRef FrameData = OrigDwarf.getDWARFObj().getDebugFrameSection(); |
Frederic Riss | 9ccf07f | 2015-06-05 23:06:11 +0000 | [diff] [blame] | 1891 | if (FrameData.empty()) |
| 1892 | return; |
| 1893 | |
| 1894 | DataExtractor Data(FrameData, OrigDwarf.isLittleEndian(), 0); |
| 1895 | uint32_t InputOffset = 0; |
| 1896 | |
| 1897 | // Store the data of the CIEs defined in this object, keyed by their |
| 1898 | // offsets. |
| 1899 | DenseMap<uint32_t, StringRef> LocalCIES; |
| 1900 | |
| 1901 | while (Data.isValidOffset(InputOffset)) { |
| 1902 | uint32_t EntryOffset = InputOffset; |
| 1903 | uint32_t InitialLength = Data.getU32(&InputOffset); |
| 1904 | if (InitialLength == 0xFFFFFFFF) |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 1905 | return reportWarning("Dwarf64 bits no supported", DMO); |
Frederic Riss | 9ccf07f | 2015-06-05 23:06:11 +0000 | [diff] [blame] | 1906 | |
| 1907 | uint32_t CIEId = Data.getU32(&InputOffset); |
| 1908 | if (CIEId == 0xFFFFFFFF) { |
| 1909 | // This is a CIE, store it. |
| 1910 | StringRef CIEData = FrameData.substr(EntryOffset, InitialLength + 4); |
| 1911 | LocalCIES[EntryOffset] = CIEData; |
| 1912 | // The -4 is to account for the CIEId we just read. |
| 1913 | InputOffset += InitialLength - 4; |
| 1914 | continue; |
| 1915 | } |
| 1916 | |
| 1917 | uint32_t Loc = Data.getUnsigned(&InputOffset, AddrSize); |
| 1918 | |
| 1919 | // Some compilers seem to emit frame info that doesn't start at |
| 1920 | // the function entry point, thus we can't just lookup the address |
| 1921 | // in the debug map. Use the linker's range map to see if the FDE |
| 1922 | // describes something that we can relocate. |
| 1923 | auto Range = Ranges.upper_bound(Loc); |
| 1924 | if (Range != Ranges.begin()) |
| 1925 | --Range; |
| 1926 | if (Range == Ranges.end() || Range->first > Loc || |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 1927 | Range->second.HighPC <= Loc) { |
Frederic Riss | 9ccf07f | 2015-06-05 23:06:11 +0000 | [diff] [blame] | 1928 | // The +4 is to account for the size of the InitialLength field itself. |
| 1929 | InputOffset = EntryOffset + InitialLength + 4; |
| 1930 | continue; |
| 1931 | } |
| 1932 | |
| 1933 | // This is an FDE, and we have a mapping. |
| 1934 | // Have we already emitted a corresponding CIE? |
| 1935 | StringRef CIEData = LocalCIES[CIEId]; |
| 1936 | if (CIEData.empty()) |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 1937 | return reportWarning("Inconsistent debug_frame content. Dropping.", DMO); |
Frederic Riss | 9ccf07f | 2015-06-05 23:06:11 +0000 | [diff] [blame] | 1938 | |
| 1939 | // Look if we already emitted a CIE that corresponds to the |
| 1940 | // referenced one (the CIE data is the key of that lookup). |
| 1941 | auto IteratorInserted = EmittedCIEs.insert( |
| 1942 | std::make_pair(CIEData, Streamer->getFrameSectionSize())); |
| 1943 | // If there is no CIE yet for this ID, emit it. |
| 1944 | if (IteratorInserted.second || |
| 1945 | // FIXME: dsymutil-classic only caches the last used CIE for |
| 1946 | // reuse. Mimic that behavior for now. Just removing that |
| 1947 | // second half of the condition and the LastCIEOffset variable |
| 1948 | // makes the code DTRT. |
| 1949 | LastCIEOffset != IteratorInserted.first->getValue()) { |
| 1950 | LastCIEOffset = Streamer->getFrameSectionSize(); |
| 1951 | IteratorInserted.first->getValue() = LastCIEOffset; |
| 1952 | Streamer->emitCIE(CIEData); |
| 1953 | } |
| 1954 | |
| 1955 | // Emit the FDE with updated address and CIE pointer. |
| 1956 | // (4 + AddrSize) is the size of the CIEId + initial_location |
| 1957 | // fields that will get reconstructed by emitFDE(). |
| 1958 | unsigned FDERemainingBytes = InitialLength - (4 + AddrSize); |
| 1959 | Streamer->emitFDE(IteratorInserted.first->getValue(), AddrSize, |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 1960 | Loc + Range->second.Offset, |
Frederic Riss | 9ccf07f | 2015-06-05 23:06:11 +0000 | [diff] [blame] | 1961 | FrameData.substr(InputOffset, FDERemainingBytes)); |
| 1962 | InputOffset += FDERemainingBytes; |
| 1963 | } |
| 1964 | } |
| 1965 | |
Adrian Prantl | afca6b4 | 2015-09-14 16:46:10 +0000 | [diff] [blame] | 1966 | void DwarfLinker::DIECloner::copyAbbrev( |
| 1967 | const DWARFAbbreviationDeclaration &Abbrev, bool hasODR) { |
Frederic Riss | 5f69f9f | 2015-09-11 04:17:30 +0000 | [diff] [blame] | 1968 | DIEAbbrev Copy(dwarf::Tag(Abbrev.getTag()), |
| 1969 | dwarf::Form(Abbrev.hasChildren())); |
| 1970 | |
| 1971 | for (const auto &Attr : Abbrev.attributes()) { |
| 1972 | uint16_t Form = Attr.Form; |
| 1973 | if (hasODR && isODRAttribute(Attr.Attr)) |
| 1974 | Form = dwarf::DW_FORM_ref_addr; |
| 1975 | Copy.AddAttribute(dwarf::Attribute(Attr.Attr), dwarf::Form(Form)); |
| 1976 | } |
| 1977 | |
Adrian Prantl | afca6b4 | 2015-09-14 16:46:10 +0000 | [diff] [blame] | 1978 | Linker.AssignAbbrev(Copy); |
Frederic Riss | 5f69f9f | 2015-09-11 04:17:30 +0000 | [diff] [blame] | 1979 | } |
| 1980 | |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 1981 | uint32_t DwarfLinker::DIECloner::hashFullyQualifiedName( |
| 1982 | DWARFDie DIE, CompileUnit &U, const DebugMapObject &DMO, int RecurseDepth) { |
Jonas Devlieghere | a9aab59 | 2018-01-29 14:52:50 +0000 | [diff] [blame] | 1983 | const char *Name = nullptr; |
| 1984 | DWARFUnit *OrigUnit = &U.getOrigUnit(); |
| 1985 | CompileUnit *CU = &U; |
| 1986 | Optional<DWARFFormValue> Ref; |
| 1987 | |
| 1988 | while (1) { |
| 1989 | if (const char *CurrentName = DIE.getName(DINameKind::ShortName)) |
| 1990 | Name = CurrentName; |
| 1991 | |
| 1992 | if (!(Ref = DIE.find(dwarf::DW_AT_specification)) && |
| 1993 | !(Ref = DIE.find(dwarf::DW_AT_abstract_origin))) |
| 1994 | break; |
| 1995 | |
| 1996 | if (!Ref->isFormClass(DWARFFormValue::FC_Reference)) |
| 1997 | break; |
| 1998 | |
| 1999 | CompileUnit *RefCU; |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 2000 | if (auto RefDIE = resolveDIEReference(Linker, DMO, CompileUnits, *Ref, |
Jonas Devlieghere | a9aab59 | 2018-01-29 14:52:50 +0000 | [diff] [blame] | 2001 | U.getOrigUnit(), DIE, RefCU)) { |
| 2002 | CU = RefCU; |
| 2003 | OrigUnit = &RefCU->getOrigUnit(); |
| 2004 | DIE = RefDIE; |
| 2005 | } |
| 2006 | } |
| 2007 | |
| 2008 | unsigned Idx = OrigUnit->getDIEIndex(DIE); |
| 2009 | if (!Name && DIE.getTag() == dwarf::DW_TAG_namespace) |
| 2010 | Name = "(anonymous namespace)"; |
| 2011 | |
| 2012 | if (CU->getInfo(Idx).ParentIdx == 0 || |
| 2013 | // FIXME: dsymutil-classic compatibility. Ignore modules. |
| 2014 | CU->getOrigUnit().getDIEAtIndex(CU->getInfo(Idx).ParentIdx).getTag() == |
| 2015 | dwarf::DW_TAG_module) |
| 2016 | return djbHash(Name ? Name : "", djbHash(RecurseDepth ? "" : "::")); |
| 2017 | |
| 2018 | DWARFDie Die = OrigUnit->getDIEAtIndex(CU->getInfo(Idx).ParentIdx); |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 2019 | return djbHash( |
| 2020 | (Name ? Name : ""), |
| 2021 | djbHash((Name ? "::" : ""), |
| 2022 | hashFullyQualifiedName(Die, *CU, DMO, ++RecurseDepth))); |
Jonas Devlieghere | a9aab59 | 2018-01-29 14:52:50 +0000 | [diff] [blame] | 2023 | } |
| 2024 | |
Jonas Devlieghere | 3ad0c5a | 2018-02-22 11:32:51 +0000 | [diff] [blame] | 2025 | static uint64_t getDwoId(const DWARFDie &CUDie, const DWARFUnit &Unit) { |
| 2026 | auto DwoId = dwarf::toUnsigned( |
| 2027 | CUDie.find({dwarf::DW_AT_dwo_id, dwarf::DW_AT_GNU_dwo_id})); |
Greg Clayton | c64f919 | 2016-12-14 22:38:08 +0000 | [diff] [blame] | 2028 | if (DwoId) |
| 2029 | return *DwoId; |
| 2030 | return 0; |
Adrian Prantl | f4ad759 | 2015-09-23 17:11:10 +0000 | [diff] [blame] | 2031 | } |
| 2032 | |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 2033 | bool DwarfLinker::registerModuleReference( |
| 2034 | const DWARFDie &CUDie, const DWARFUnit &Unit, DebugMap &ModuleMap, |
| 2035 | const DebugMapObject &DMO, RangesTy &Ranges, OffsetsStringPool &StringPool, |
| 2036 | UniquingStringPool &UniquingStringPool, DeclContextTree &ODRContexts, |
Jonas Devlieghere | 60c6009 | 2018-09-07 10:29:22 +0000 | [diff] [blame] | 2037 | uint64_t ModulesEndOffset, unsigned &UnitID, unsigned Indent, bool Quiet) { |
Jonas Devlieghere | 3ad0c5a | 2018-02-22 11:32:51 +0000 | [diff] [blame] | 2038 | std::string PCMfile = dwarf::toString( |
| 2039 | CUDie.find({dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}), ""); |
Adrian Prantl | d2136b3 | 2015-09-22 22:20:50 +0000 | [diff] [blame] | 2040 | if (PCMfile.empty()) |
| 2041 | return false; |
| 2042 | |
| 2043 | // Clang module DWARF skeleton CUs abuse this for the path to the module. |
Greg Clayton | beabb63 | 2017-01-13 21:08:18 +0000 | [diff] [blame] | 2044 | std::string PCMpath = dwarf::toString(CUDie.find(dwarf::DW_AT_comp_dir), ""); |
Adrian Prantl | f4ad759 | 2015-09-23 17:11:10 +0000 | [diff] [blame] | 2045 | uint64_t DwoId = getDwoId(CUDie, Unit); |
Adrian Prantl | d2136b3 | 2015-09-22 22:20:50 +0000 | [diff] [blame] | 2046 | |
Greg Clayton | beabb63 | 2017-01-13 21:08:18 +0000 | [diff] [blame] | 2047 | std::string Name = dwarf::toString(CUDie.find(dwarf::DW_AT_name), ""); |
Adrian Prantl | 43df582 | 2015-09-23 17:35:52 +0000 | [diff] [blame] | 2048 | if (Name.empty()) { |
Adrian Prantl | 5309f16 | 2018-08-24 20:41:08 +0000 | [diff] [blame] | 2049 | if (!Quiet) |
| 2050 | reportWarning("Anonymous module skeleton CU for " + PCMfile, DMO); |
Adrian Prantl | 43df582 | 2015-09-23 17:35:52 +0000 | [diff] [blame] | 2051 | return true; |
| 2052 | } |
| 2053 | |
Adrian Prantl | 5309f16 | 2018-08-24 20:41:08 +0000 | [diff] [blame] | 2054 | if (!Quiet && Options.Verbose) { |
Adrian Prantl | d2136b3 | 2015-09-22 22:20:50 +0000 | [diff] [blame] | 2055 | outs().indent(Indent); |
| 2056 | outs() << "Found clang module reference " << PCMfile; |
| 2057 | } |
| 2058 | |
Adrian Prantl | f4ad759 | 2015-09-23 17:11:10 +0000 | [diff] [blame] | 2059 | auto Cached = ClangModules.find(PCMfile); |
| 2060 | if (Cached != ClangModules.end()) { |
Adrian Prantl | 07368be | 2016-05-13 00:17:58 +0000 | [diff] [blame] | 2061 | // FIXME: Until PR27449 (https://llvm.org/bugs/show_bug.cgi?id=27449) is |
| 2062 | // fixed in clang, only warn about DWO_id mismatches in verbose mode. |
| 2063 | // ASTFileSignatures will change randomly when a module is rebuilt. |
Adrian Prantl | 5309f16 | 2018-08-24 20:41:08 +0000 | [diff] [blame] | 2064 | if (!Quiet && Options.Verbose && (Cached->second != DwoId)) |
Adrian Prantl | f4ad759 | 2015-09-23 17:11:10 +0000 | [diff] [blame] | 2065 | reportWarning(Twine("hash mismatch: this object file was built against a " |
Jonas Devlieghere | 3ad0c5a | 2018-02-22 11:32:51 +0000 | [diff] [blame] | 2066 | "different version of the module ") + |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 2067 | PCMfile, |
| 2068 | DMO); |
Adrian Prantl | 5309f16 | 2018-08-24 20:41:08 +0000 | [diff] [blame] | 2069 | if (!Quiet && Options.Verbose) |
Adrian Prantl | d2136b3 | 2015-09-22 22:20:50 +0000 | [diff] [blame] | 2070 | outs() << " [cached].\n"; |
| 2071 | return true; |
| 2072 | } |
Adrian Prantl | 5309f16 | 2018-08-24 20:41:08 +0000 | [diff] [blame] | 2073 | if (!Quiet && Options.Verbose) |
Adrian Prantl | d2136b3 | 2015-09-22 22:20:50 +0000 | [diff] [blame] | 2074 | outs() << " ...\n"; |
| 2075 | |
| 2076 | // Cyclic dependencies are disallowed by Clang, but we still |
| 2077 | // shouldn't run into an infinite loop, so mark it as processed now. |
Adrian Prantl | f4ad759 | 2015-09-23 17:11:10 +0000 | [diff] [blame] | 2078 | ClangModules.insert({PCMfile, DwoId}); |
Jonas Devlieghere | 60c6009 | 2018-09-07 10:29:22 +0000 | [diff] [blame] | 2079 | if (Error E = |
| 2080 | loadClangModule(PCMfile, PCMpath, Name, DwoId, ModuleMap, DMO, Ranges, |
| 2081 | StringPool, UniquingStringPool, ODRContexts, |
| 2082 | ModulesEndOffset, UnitID, Indent + 2, Quiet)) { |
Rafael Espindola | 75fe73f | 2017-11-16 17:46:43 +0000 | [diff] [blame] | 2083 | consumeError(std::move(E)); |
| 2084 | return false; |
| 2085 | } |
Adrian Prantl | d2136b3 | 2015-09-22 22:20:50 +0000 | [diff] [blame] | 2086 | return true; |
| 2087 | } |
| 2088 | |
Frederic Riss | fa7f7bd | 2015-07-24 06:41:11 +0000 | [diff] [blame] | 2089 | ErrorOr<const object::ObjectFile &> |
Jonas Devlieghere | 4d3e6c1 | 2018-06-29 16:50:41 +0000 | [diff] [blame] | 2090 | DwarfLinker::loadObject(const DebugMapObject &Obj, const DebugMap &Map) { |
| 2091 | auto ObjectEntry = |
| 2092 | BinHolder.getObjectEntry(Obj.getObjectFilename(), Obj.getTimestamp()); |
| 2093 | if (!ObjectEntry) { |
| 2094 | auto Err = ObjectEntry.takeError(); |
| 2095 | reportWarning( |
| 2096 | Twine(Obj.getObjectFilename()) + ": " + toString(std::move(Err)), Obj); |
| 2097 | return errorToErrorCode(std::move(Err)); |
Frederic Riss | 42829a5 | 2015-08-31 05:16:35 +0000 | [diff] [blame] | 2098 | } |
Jonas Devlieghere | 4d3e6c1 | 2018-06-29 16:50:41 +0000 | [diff] [blame] | 2099 | |
| 2100 | auto Object = ObjectEntry->getObject(Map.getTriple()); |
| 2101 | if (!Object) { |
| 2102 | auto Err = Object.takeError(); |
| 2103 | reportWarning( |
| 2104 | Twine(Obj.getObjectFilename()) + ": " + toString(std::move(Err)), Obj); |
| 2105 | return errorToErrorCode(std::move(Err)); |
| 2106 | } |
| 2107 | |
| 2108 | return *Object; |
Frederic Riss | fa7f7bd | 2015-07-24 06:41:11 +0000 | [diff] [blame] | 2109 | } |
| 2110 | |
Adrian Prantl | 5309f16 | 2018-08-24 20:41:08 +0000 | [diff] [blame] | 2111 | Error DwarfLinker::loadClangModule( |
| 2112 | StringRef Filename, StringRef ModulePath, StringRef ModuleName, |
| 2113 | uint64_t DwoId, DebugMap &ModuleMap, const DebugMapObject &DMO, |
| 2114 | RangesTy &Ranges, OffsetsStringPool &StringPool, |
| 2115 | UniquingStringPool &UniquingStringPool, DeclContextTree &ODRContexts, |
Jonas Devlieghere | 60c6009 | 2018-09-07 10:29:22 +0000 | [diff] [blame] | 2116 | uint64_t ModulesEndOffset, unsigned &UnitID, unsigned Indent, bool Quiet) { |
Adrian Prantl | d2136b3 | 2015-09-22 22:20:50 +0000 | [diff] [blame] | 2117 | SmallString<80> Path(Options.PrependPath); |
| 2118 | if (sys::path::is_relative(Filename)) |
| 2119 | sys::path::append(Path, ModulePath, Filename); |
| 2120 | else |
| 2121 | sys::path::append(Path, Filename); |
Jonas Devlieghere | 4d3e6c1 | 2018-06-29 16:50:41 +0000 | [diff] [blame] | 2122 | // Don't use the cached binary holder because we have no thread-safety |
| 2123 | // guarantee and the lifetime is limited. |
Francis Ricci | 6f200df | 2017-10-06 14:49:20 +0000 | [diff] [blame] | 2124 | auto &Obj = ModuleMap.addDebugMapObject( |
| 2125 | Path, sys::TimePoint<std::chrono::seconds>(), MachO::N_OSO); |
Jonas Devlieghere | 4d3e6c1 | 2018-06-29 16:50:41 +0000 | [diff] [blame] | 2126 | auto ErrOrObj = loadObject(Obj, ModuleMap); |
Adrian Prantl | b363d33 | 2016-01-14 18:31:07 +0000 | [diff] [blame] | 2127 | if (!ErrOrObj) { |
| 2128 | // Try and emit more helpful warnings by applying some heuristics. |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 2129 | StringRef ObjFile = DMO.getObjectFilename(); |
Adrian Prantl | b363d33 | 2016-01-14 18:31:07 +0000 | [diff] [blame] | 2130 | bool isClangModule = sys::path::extension(Filename).equals(".pcm"); |
| 2131 | bool isArchive = ObjFile.endswith(")"); |
| 2132 | if (isClangModule) { |
Adrian Prantl | b363d33 | 2016-01-14 18:31:07 +0000 | [diff] [blame] | 2133 | StringRef ModuleCacheDir = sys::path::parent_path(Path); |
| 2134 | if (sys::fs::exists(ModuleCacheDir)) { |
| 2135 | // If the module's parent directory exists, we assume that the module |
| 2136 | // cache has expired and was pruned by clang. A more adventurous |
| 2137 | // dsymutil would invoke clang to rebuild the module now. |
| 2138 | if (!ModuleCacheHintDisplayed) { |
Jonas Devlieghere | 5baab4c | 2018-04-14 21:36:42 +0000 | [diff] [blame] | 2139 | WithColor::note() << "The clang module cache may have expired since " |
| 2140 | "this object file was built. Rebuilding the " |
| 2141 | "object file will rebuild the module cache.\n"; |
Adrian Prantl | b363d33 | 2016-01-14 18:31:07 +0000 | [diff] [blame] | 2142 | ModuleCacheHintDisplayed = true; |
| 2143 | } |
| 2144 | } else if (isArchive) { |
| 2145 | // If the module cache directory doesn't exist at all and the object |
| 2146 | // file is inside a static library, we assume that the static library |
| 2147 | // was built on a different machine. We don't want to discourage module |
| 2148 | // debugging for convenience libraries within a project though. |
| 2149 | if (!ArchiveHintDisplayed) { |
Jonas Devlieghere | 5baab4c | 2018-04-14 21:36:42 +0000 | [diff] [blame] | 2150 | WithColor::note() |
| 2151 | << "Linking a static library that was built with " |
| 2152 | "-gmodules, but the module cache was not found. " |
| 2153 | "Redistributable static libraries should never be " |
| 2154 | "built with module debugging enabled. The debug " |
| 2155 | "experience will be degraded due to incomplete " |
| 2156 | "debug information.\n"; |
Adrian Prantl | b363d33 | 2016-01-14 18:31:07 +0000 | [diff] [blame] | 2157 | ArchiveHintDisplayed = true; |
| 2158 | } |
| 2159 | } |
| 2160 | } |
Rafael Espindola | 75fe73f | 2017-11-16 17:46:43 +0000 | [diff] [blame] | 2161 | return Error::success(); |
Adrian Prantl | b363d33 | 2016-01-14 18:31:07 +0000 | [diff] [blame] | 2162 | } |
Adrian Prantl | d2136b3 | 2015-09-22 22:20:50 +0000 | [diff] [blame] | 2163 | |
Benjamin Kramer | 39a9cdb | 2015-09-23 10:38:59 +0000 | [diff] [blame] | 2164 | std::unique_ptr<CompileUnit> Unit; |
Adrian Prantl | d2136b3 | 2015-09-22 22:20:50 +0000 | [diff] [blame] | 2165 | |
| 2166 | // Setup access to the debug info. |
Rafael Espindola | ee809ac | 2017-07-19 22:27:28 +0000 | [diff] [blame] | 2167 | auto DwarfContext = DWARFContext::create(*ErrOrObj); |
Adrian Prantl | d2136b3 | 2015-09-22 22:20:50 +0000 | [diff] [blame] | 2168 | RelocationManager RelocMgr(*this); |
Adrian Prantl | f385590 | 2017-08-08 18:26:12 +0000 | [diff] [blame] | 2169 | |
Jonas Devlieghere | 7c767bd | 2018-07-25 23:01:38 +0000 | [diff] [blame] | 2170 | for (const auto &CU : DwarfContext->compile_units()) { |
| 2171 | updateDwarfVersion(CU->getVersion()); |
Adrian Prantl | d2136b3 | 2015-09-22 22:20:50 +0000 | [diff] [blame] | 2172 | // Recursively get all modules imported by this one. |
Adrian Prantl | f385590 | 2017-08-08 18:26:12 +0000 | [diff] [blame] | 2173 | auto CUDie = CU->getUnitDIE(false); |
Jonas Devlieghere | 760af16 | 2018-04-08 17:35:17 +0000 | [diff] [blame] | 2174 | if (!CUDie) |
| 2175 | continue; |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 2176 | if (!registerModuleReference(CUDie, *CU, ModuleMap, DMO, Ranges, StringPool, |
Jonas Devlieghere | 60c6009 | 2018-09-07 10:29:22 +0000 | [diff] [blame] | 2177 | UniquingStringPool, ODRContexts, |
| 2178 | ModulesEndOffset, UnitID, Indent, Quiet)) { |
Adrian Prantl | d2136b3 | 2015-09-22 22:20:50 +0000 | [diff] [blame] | 2179 | if (Unit) { |
Rafael Espindola | 75fe73f | 2017-11-16 17:46:43 +0000 | [diff] [blame] | 2180 | std::string Err = |
| 2181 | (Filename + |
| 2182 | ": Clang modules are expected to have exactly 1 compile unit.\n") |
| 2183 | .str(); |
Jonas Devlieghere | beee6ae | 2018-03-09 15:22:42 +0000 | [diff] [blame] | 2184 | error(Err); |
Rafael Espindola | 75fe73f | 2017-11-16 17:46:43 +0000 | [diff] [blame] | 2185 | return make_error<StringError>(Err, inconvertibleErrorCode()); |
Adrian Prantl | d2136b3 | 2015-09-22 22:20:50 +0000 | [diff] [blame] | 2186 | } |
Adrian Prantl | cbea336 | 2016-04-25 17:04:32 +0000 | [diff] [blame] | 2187 | // FIXME: Until PR27449 (https://llvm.org/bugs/show_bug.cgi?id=27449) is |
| 2188 | // fixed in clang, only warn about DWO_id mismatches in verbose mode. |
| 2189 | // ASTFileSignatures will change randomly when a module is rebuilt. |
Greg Clayton | adb170f | 2016-12-13 18:25:19 +0000 | [diff] [blame] | 2190 | uint64_t PCMDwoId = getDwoId(CUDie, *CU); |
Adrian Prantl | 07368be | 2016-05-13 00:17:58 +0000 | [diff] [blame] | 2191 | if (PCMDwoId != DwoId) { |
Adrian Prantl | 5309f16 | 2018-08-24 20:41:08 +0000 | [diff] [blame] | 2192 | if (!Quiet && Options.Verbose) |
Adrian Prantl | 07368be | 2016-05-13 00:17:58 +0000 | [diff] [blame] | 2193 | reportWarning( |
| 2194 | Twine("hash mismatch: this object file was built against a " |
Jonas Devlieghere | 3ad0c5a | 2018-02-22 11:32:51 +0000 | [diff] [blame] | 2195 | "different version of the module ") + |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 2196 | Filename, |
| 2197 | DMO); |
Adrian Prantl | 07368be | 2016-05-13 00:17:58 +0000 | [diff] [blame] | 2198 | // Update the cache entry with the DwoId of the module loaded from disk. |
| 2199 | ClangModules[Filename] = PCMDwoId; |
| 2200 | } |
Adrian Prantl | f4ad759 | 2015-09-23 17:11:10 +0000 | [diff] [blame] | 2201 | |
| 2202 | // Add this module. |
Adrian Prantl | 43df582 | 2015-09-23 17:35:52 +0000 | [diff] [blame] | 2203 | Unit = llvm::make_unique<CompileUnit>(*CU, UnitID++, !Options.NoODR, |
| 2204 | ModuleName); |
Adrian Prantl | d2136b3 | 2015-09-22 22:20:50 +0000 | [diff] [blame] | 2205 | Unit->setHasInterestingContent(); |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 2206 | analyzeContextInfo(CUDie, 0, *Unit, &ODRContexts.getRoot(), |
Jonas Devlieghere | 60c6009 | 2018-09-07 10:29:22 +0000 | [diff] [blame] | 2207 | UniquingStringPool, ODRContexts, ModulesEndOffset); |
Adrian Prantl | d2136b3 | 2015-09-22 22:20:50 +0000 | [diff] [blame] | 2208 | // Keep everything. |
| 2209 | Unit->markEverythingAsKept(); |
| 2210 | } |
| 2211 | } |
Adrian Prantl | 88b828e | 2017-08-22 01:10:48 +0000 | [diff] [blame] | 2212 | if (!Unit->getOrigUnit().getUnitDIE().hasChildren()) |
Rafael Espindola | 75fe73f | 2017-11-16 17:46:43 +0000 | [diff] [blame] | 2213 | return Error::success(); |
Adrian Prantl | 5309f16 | 2018-08-24 20:41:08 +0000 | [diff] [blame] | 2214 | if (!Quiet && Options.Verbose) { |
Adrian Prantl | d2136b3 | 2015-09-22 22:20:50 +0000 | [diff] [blame] | 2215 | outs().indent(Indent); |
| 2216 | outs() << "cloning .debug_info from " << Filename << "\n"; |
| 2217 | } |
| 2218 | |
Jonas Devlieghere | ea63d87 | 2018-06-28 15:01:42 +0000 | [diff] [blame] | 2219 | UnitListTy CompileUnits; |
Greg Clayton | fc1fc8b | 2016-12-01 18:56:29 +0000 | [diff] [blame] | 2220 | CompileUnits.push_back(std::move(Unit)); |
| 2221 | DIECloner(*this, RelocMgr, DIEAlloc, CompileUnits, Options) |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 2222 | .cloneAllCompileUnits(*DwarfContext, DMO, Ranges, StringPool); |
Rafael Espindola | 75fe73f | 2017-11-16 17:46:43 +0000 | [diff] [blame] | 2223 | return Error::success(); |
Adrian Prantl | d2136b3 | 2015-09-22 22:20:50 +0000 | [diff] [blame] | 2224 | } |
| 2225 | |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 2226 | void DwarfLinker::DIECloner::cloneAllCompileUnits( |
| 2227 | DWARFContext &DwarfContext, const DebugMapObject &DMO, RangesTy &Ranges, |
| 2228 | OffsetsStringPool &StringPool) { |
Adrian Prantl | afca6b4 | 2015-09-14 16:46:10 +0000 | [diff] [blame] | 2229 | if (!Linker.Streamer) |
Adrian Prantl | 0a0a960 | 2015-09-11 23:45:30 +0000 | [diff] [blame] | 2230 | return; |
| 2231 | |
| 2232 | for (auto &CurrentUnit : CompileUnits) { |
Greg Clayton | adb170f | 2016-12-13 18:25:19 +0000 | [diff] [blame] | 2233 | auto InputDIE = CurrentUnit->getOrigUnit().getUnitDIE(); |
Greg Clayton | fc1fc8b | 2016-12-01 18:56:29 +0000 | [diff] [blame] | 2234 | CurrentUnit->setStartOffset(Linker.OutputDebugInfoSize); |
Jonas Devlieghere | 760af16 | 2018-04-08 17:35:17 +0000 | [diff] [blame] | 2235 | if (!InputDIE) { |
| 2236 | Linker.OutputDebugInfoSize = CurrentUnit->computeNextUnitOffset(); |
| 2237 | continue; |
| 2238 | } |
Frederic Riss | 909a321 | 2017-02-09 19:41:55 +0000 | [diff] [blame] | 2239 | if (CurrentUnit->getInfo(0).Keep) { |
| 2240 | // Clone the InputDIE into your Unit DIE in our compile unit since it |
| 2241 | // already has a DIE inside of it. |
| 2242 | CurrentUnit->createOutputDIE(); |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 2243 | cloneDIE(InputDIE, DMO, *CurrentUnit, StringPool, 0 /* PC offset */, |
Frederic Riss | 909a321 | 2017-02-09 19:41:55 +0000 | [diff] [blame] | 2244 | 11 /* Unit Header size */, 0, CurrentUnit->getOutputUnitDIE()); |
| 2245 | } |
Greg Clayton | fc1fc8b | 2016-12-01 18:56:29 +0000 | [diff] [blame] | 2246 | Linker.OutputDebugInfoSize = CurrentUnit->computeNextUnitOffset(); |
Adrian Prantl | afca6b4 | 2015-09-14 16:46:10 +0000 | [diff] [blame] | 2247 | if (Linker.Options.NoOutput) |
Adrian Prantl | 0a0a960 | 2015-09-11 23:45:30 +0000 | [diff] [blame] | 2248 | continue; |
Jonas Devlieghere | 6169346 | 2018-02-08 10:48:54 +0000 | [diff] [blame] | 2249 | |
Jonas Devlieghere | 20767d1 | 2019-01-07 23:27:25 +0000 | [diff] [blame] | 2250 | // FIXME: for compatibility with the classic dsymutil, we emit |
| 2251 | // an empty line table for the unit, even if the unit doesn't |
| 2252 | // actually exist in the DIE tree. |
| 2253 | if (LLVM_LIKELY(!Linker.Options.Update) || Linker.Options.Translator) |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 2254 | Linker.patchLineTableForUnit(*CurrentUnit, DwarfContext, Ranges, DMO); |
Jonas Devlieghere | 20767d1 | 2019-01-07 23:27:25 +0000 | [diff] [blame] | 2255 | Linker.emitAcceleratorEntriesForUnit(*CurrentUnit); |
| 2256 | if (Linker.Options.Update) |
| 2257 | continue; |
| 2258 | Linker.patchRangesForUnit(*CurrentUnit, DwarfContext, DMO); |
| 2259 | Linker.Streamer->emitLocationsForUnit(*CurrentUnit, DwarfContext); |
Adrian Prantl | 0a0a960 | 2015-09-11 23:45:30 +0000 | [diff] [blame] | 2260 | } |
| 2261 | |
Adrian Prantl | afca6b4 | 2015-09-14 16:46:10 +0000 | [diff] [blame] | 2262 | if (Linker.Options.NoOutput) |
Adrian Prantl | 0a0a960 | 2015-09-11 23:45:30 +0000 | [diff] [blame] | 2263 | return; |
| 2264 | |
| 2265 | // Emit all the compile unit's debug information. |
| 2266 | for (auto &CurrentUnit : CompileUnits) { |
Jonas Devlieghere | 6169346 | 2018-02-08 10:48:54 +0000 | [diff] [blame] | 2267 | if (LLVM_LIKELY(!Linker.Options.Update)) |
| 2268 | Linker.generateUnitRanges(*CurrentUnit); |
Greg Clayton | fc1fc8b | 2016-12-01 18:56:29 +0000 | [diff] [blame] | 2269 | CurrentUnit->fixupForwardReferences(); |
| 2270 | Linker.Streamer->emitCompileUnitHeader(*CurrentUnit); |
| 2271 | if (!CurrentUnit->getOutputUnitDIE()) |
Adrian Prantl | 0a0a960 | 2015-09-11 23:45:30 +0000 | [diff] [blame] | 2272 | continue; |
Greg Clayton | fc1fc8b | 2016-12-01 18:56:29 +0000 | [diff] [blame] | 2273 | Linker.Streamer->emitDIE(*CurrentUnit->getOutputUnitDIE()); |
Adrian Prantl | 0a0a960 | 2015-09-11 23:45:30 +0000 | [diff] [blame] | 2274 | } |
| 2275 | } |
| 2276 | |
Jonas Devlieghere | 7c767bd | 2018-07-25 23:01:38 +0000 | [diff] [blame] | 2277 | void DwarfLinker::updateAccelKind(DWARFContext &Dwarf) { |
| 2278 | if (Options.TheAccelTableKind != AccelTableKind::Default) |
| 2279 | return; |
| 2280 | |
| 2281 | auto &DwarfObj = Dwarf.getDWARFObj(); |
| 2282 | |
| 2283 | if (!AtLeastOneDwarfAccelTable && |
| 2284 | (!DwarfObj.getAppleNamesSection().Data.empty() || |
| 2285 | !DwarfObj.getAppleTypesSection().Data.empty() || |
| 2286 | !DwarfObj.getAppleNamespacesSection().Data.empty() || |
| 2287 | !DwarfObj.getAppleObjCSection().Data.empty())) { |
| 2288 | AtLeastOneAppleAccelTable = true; |
| 2289 | } |
| 2290 | |
| 2291 | if (!AtLeastOneDwarfAccelTable && |
| 2292 | !DwarfObj.getDebugNamesSection().Data.empty()) { |
| 2293 | AtLeastOneDwarfAccelTable = true; |
| 2294 | } |
| 2295 | } |
| 2296 | |
Jonas Devlieghere | 67eb8fd | 2018-04-02 10:40:43 +0000 | [diff] [blame] | 2297 | bool DwarfLinker::emitPaperTrailWarnings(const DebugMapObject &DMO, |
| 2298 | const DebugMap &Map, |
| 2299 | OffsetsStringPool &StringPool) { |
| 2300 | if (DMO.getWarnings().empty() || !DMO.empty()) |
| 2301 | return false; |
| 2302 | |
| 2303 | Streamer->switchToDebugInfoSection(/* Version */ 2); |
| 2304 | DIE *CUDie = DIE::get(DIEAlloc, dwarf::DW_TAG_compile_unit); |
| 2305 | CUDie->setOffset(11); |
| 2306 | StringRef Producer = StringPool.internString("dsymutil"); |
| 2307 | StringRef File = StringPool.internString(DMO.getObjectFilename()); |
| 2308 | CUDie->addValue(DIEAlloc, dwarf::DW_AT_producer, dwarf::DW_FORM_strp, |
| 2309 | DIEInteger(StringPool.getStringOffset(Producer))); |
| 2310 | DIEBlock *String = new (DIEAlloc) DIEBlock(); |
| 2311 | DIEBlocks.push_back(String); |
| 2312 | for (auto &C : File) |
| 2313 | String->addValue(DIEAlloc, dwarf::Attribute(0), dwarf::DW_FORM_data1, |
| 2314 | DIEInteger(C)); |
| 2315 | String->addValue(DIEAlloc, dwarf::Attribute(0), dwarf::DW_FORM_data1, |
| 2316 | DIEInteger(0)); |
| 2317 | |
| 2318 | CUDie->addValue(DIEAlloc, dwarf::DW_AT_name, dwarf::DW_FORM_string, String); |
| 2319 | for (const auto &Warning : DMO.getWarnings()) { |
| 2320 | DIE &ConstDie = CUDie->addChild(DIE::get(DIEAlloc, dwarf::DW_TAG_constant)); |
| 2321 | ConstDie.addValue( |
| 2322 | DIEAlloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, |
| 2323 | DIEInteger(StringPool.getStringOffset("dsymutil_warning"))); |
| 2324 | ConstDie.addValue(DIEAlloc, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, |
| 2325 | DIEInteger(1)); |
| 2326 | ConstDie.addValue(DIEAlloc, dwarf::DW_AT_const_value, dwarf::DW_FORM_strp, |
| 2327 | DIEInteger(StringPool.getStringOffset(Warning))); |
| 2328 | } |
| 2329 | unsigned Size = 4 /* FORM_strp */ + File.size() + 1 + |
| 2330 | DMO.getWarnings().size() * (4 + 1 + 4) + |
| 2331 | 1 /* End of children */; |
| 2332 | DIEAbbrev Abbrev = CUDie->generateAbbrev(); |
| 2333 | AssignAbbrev(Abbrev); |
| 2334 | CUDie->setAbbrevNumber(Abbrev.getNumber()); |
| 2335 | Size += getULEB128Size(Abbrev.getNumber()); |
| 2336 | // Abbreviation ordering needed for classic compatibility. |
| 2337 | for (auto &Child : CUDie->children()) { |
| 2338 | Abbrev = Child.generateAbbrev(); |
| 2339 | AssignAbbrev(Abbrev); |
| 2340 | Child.setAbbrevNumber(Abbrev.getNumber()); |
| 2341 | Size += getULEB128Size(Abbrev.getNumber()); |
| 2342 | } |
| 2343 | CUDie->setSize(Size); |
| 2344 | auto &Asm = Streamer->getAsmPrinter(); |
| 2345 | Asm.emitInt32(11 + CUDie->getSize() - 4); |
| 2346 | Asm.emitInt16(2); |
| 2347 | Asm.emitInt32(0); |
| 2348 | Asm.emitInt8(Map.getTriple().isArch64Bit() ? 8 : 4); |
| 2349 | Streamer->emitDIE(*CUDie); |
| 2350 | OutputDebugInfoSize += 11 /* Header */ + Size; |
| 2351 | |
| 2352 | return true; |
| 2353 | } |
| 2354 | |
Frederic Riss | b616a18 | 2015-01-28 18:27:01 +0000 | [diff] [blame] | 2355 | bool DwarfLinker::link(const DebugMap &Map) { |
Rafael Espindola | 5feaa63 | 2017-11-15 20:55:53 +0000 | [diff] [blame] | 2356 | if (!createStreamer(Map.getTriple(), OutFile)) |
Frederic Riss | 2929a7a | 2015-02-28 00:29:11 +0000 | [diff] [blame] | 2357 | return false; |
| 2358 | |
Frederic Riss | d0d92e7 | 2015-03-04 22:07:44 +0000 | [diff] [blame] | 2359 | // Size of the DIEs (and headers) generated for the linked output. |
Adrian Prantl | 0a0a960 | 2015-09-11 23:45:30 +0000 | [diff] [blame] | 2360 | OutputDebugInfoSize = 0; |
Frederic Riss | 1d6cc76 | 2015-03-14 03:46:40 +0000 | [diff] [blame] | 2361 | // A unique ID that identifies each compile unit. |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 2362 | unsigned UnitID = 0; |
Adrian Prantl | d2136b3 | 2015-09-22 22:20:50 +0000 | [diff] [blame] | 2363 | DebugMap ModuleMap(Map.getTriple(), Map.getBinaryPath()); |
| 2364 | |
Jonas Devlieghere | b936520 | 2018-03-13 14:27:15 +0000 | [diff] [blame] | 2365 | // First populate the data structure we need for each iteration of the |
| 2366 | // parallel loop. |
| 2367 | unsigned NumObjects = Map.getNumberOfObjects(); |
| 2368 | std::vector<LinkContext> ObjectContexts; |
| 2369 | ObjectContexts.reserve(NumObjects); |
Jonas Devlieghere | 7c767bd | 2018-07-25 23:01:38 +0000 | [diff] [blame] | 2370 | for (const auto &Obj : Map.objects()) { |
Jonas Devlieghere | 4d3e6c1 | 2018-06-29 16:50:41 +0000 | [diff] [blame] | 2371 | ObjectContexts.emplace_back(Map, *this, *Obj.get()); |
Jonas Devlieghere | 7c767bd | 2018-07-25 23:01:38 +0000 | [diff] [blame] | 2372 | LinkContext &LC = ObjectContexts.back(); |
| 2373 | if (LC.ObjectFile) |
| 2374 | updateAccelKind(*LC.DwarfContext); |
| 2375 | } |
Jonas Devlieghere | b936520 | 2018-03-13 14:27:15 +0000 | [diff] [blame] | 2376 | |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 2377 | // This Dwarf string pool which is only used for uniquing. This one should |
| 2378 | // never be used for offsets as its not thread-safe or predictable. |
| 2379 | UniquingStringPool UniquingStringPool; |
| 2380 | |
| 2381 | // This Dwarf string pool which is used for emission. It must be used |
| 2382 | // serially as the order of calling getStringOffset matters for |
| 2383 | // reproducibility. |
Jonas Devlieghere | 20767d1 | 2019-01-07 23:27:25 +0000 | [diff] [blame] | 2384 | OffsetsStringPool OffsetsStringPool(Options.Translator); |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 2385 | |
| 2386 | // ODR Contexts for the link. |
| 2387 | DeclContextTree ODRContexts; |
| 2388 | |
Jonas Devlieghere | 7c767bd | 2018-07-25 23:01:38 +0000 | [diff] [blame] | 2389 | // If we haven't decided on an accelerator table kind yet, we base ourselves |
| 2390 | // on the DWARF we have seen so far. At this point we haven't pulled in debug |
| 2391 | // information from modules yet, so it is technically possible that they |
| 2392 | // would affect the decision. However, as they're built with the same |
| 2393 | // compiler and flags, it is safe to assume that they will follow the |
| 2394 | // decision made here. |
| 2395 | if (Options.TheAccelTableKind == AccelTableKind::Default) { |
| 2396 | if (AtLeastOneDwarfAccelTable && !AtLeastOneAppleAccelTable) |
| 2397 | Options.TheAccelTableKind = AccelTableKind::Dwarf; |
| 2398 | else |
| 2399 | Options.TheAccelTableKind = AccelTableKind::Apple; |
| 2400 | } |
| 2401 | |
Jonas Devlieghere | b936520 | 2018-03-13 14:27:15 +0000 | [diff] [blame] | 2402 | for (LinkContext &LinkContext : ObjectContexts) { |
Frederic Riss | d9a80bd | 2015-02-28 00:29:07 +0000 | [diff] [blame] | 2403 | if (Options.Verbose) |
Jonas Devlieghere | b936520 | 2018-03-13 14:27:15 +0000 | [diff] [blame] | 2404 | outs() << "DEBUG MAP OBJECT: " << LinkContext.DMO.getObjectFilename() |
| 2405 | << "\n"; |
Francis Ricci | 6f200df | 2017-10-06 14:49:20 +0000 | [diff] [blame] | 2406 | |
| 2407 | // N_AST objects (swiftmodule files) should get dumped directly into the |
| 2408 | // appropriate DWARF section. |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 2409 | if (LinkContext.DMO.getType() == MachO::N_AST) { |
| 2410 | StringRef File = LinkContext.DMO.getObjectFilename(); |
Jonas Devlieghere | f16734c | 2017-10-13 14:41:23 +0000 | [diff] [blame] | 2411 | auto ErrorOrMem = MemoryBuffer::getFile(File); |
| 2412 | if (!ErrorOrMem) { |
Jonas Devlieghere | cc46e39 | 2018-03-13 15:47:38 +0000 | [diff] [blame] | 2413 | warn("Could not open '" + File + "'\n"); |
Francis Ricci | 6f200df | 2017-10-06 14:49:20 +0000 | [diff] [blame] | 2414 | continue; |
Jonas Devlieghere | f16734c | 2017-10-13 14:41:23 +0000 | [diff] [blame] | 2415 | } |
| 2416 | sys::fs::file_status Stat; |
Jonas Devlieghere | beee6ae | 2018-03-09 15:22:42 +0000 | [diff] [blame] | 2417 | if (auto Err = sys::fs::status(File, Stat)) { |
| 2418 | warn(Err.message()); |
Jonas Devlieghere | f16734c | 2017-10-13 14:41:23 +0000 | [diff] [blame] | 2419 | continue; |
| 2420 | } |
Jonas Devlieghere | aefeecf | 2018-12-04 17:15:23 +0000 | [diff] [blame] | 2421 | if (!Options.NoTimestamp) { |
| 2422 | // The modification can have sub-second precision so we need to cast |
| 2423 | // away the extra precision that's not present in the debug map. |
| 2424 | auto ModificationTime = |
| 2425 | std::chrono::time_point_cast<std::chrono::seconds>( |
| 2426 | Stat.getLastModificationTime()); |
| 2427 | if (ModificationTime != LinkContext.DMO.getTimestamp()) { |
| 2428 | // Not using the helper here as we can easily stream TimePoint<>. |
| 2429 | WithColor::warning() |
| 2430 | << "Timestamp mismatch for " << File << ": " |
| 2431 | << Stat.getLastModificationTime() << " and " |
| 2432 | << sys::TimePoint<>(LinkContext.DMO.getTimestamp()) << "\n"; |
| 2433 | continue; |
| 2434 | } |
Jonas Devlieghere | f16734c | 2017-10-13 14:41:23 +0000 | [diff] [blame] | 2435 | } |
| 2436 | |
| 2437 | // Copy the module into the .swift_ast section. |
Francis Ricci | 6f200df | 2017-10-06 14:49:20 +0000 | [diff] [blame] | 2438 | if (!Options.NoOutput) |
Jonas Devlieghere | f16734c | 2017-10-13 14:41:23 +0000 | [diff] [blame] | 2439 | Streamer->emitSwiftAST((*ErrorOrMem)->getBuffer()); |
Francis Ricci | 6f200df | 2017-10-06 14:49:20 +0000 | [diff] [blame] | 2440 | continue; |
| 2441 | } |
| 2442 | |
Jonas Devlieghere | 67eb8fd | 2018-04-02 10:40:43 +0000 | [diff] [blame] | 2443 | if (emitPaperTrailWarnings(LinkContext.DMO, Map, OffsetsStringPool)) |
| 2444 | continue; |
Jonas Devlieghere | b936520 | 2018-03-13 14:27:15 +0000 | [diff] [blame] | 2445 | |
Jonas Devlieghere | 67eb8fd | 2018-04-02 10:40:43 +0000 | [diff] [blame] | 2446 | if (!LinkContext.ObjectFile) |
Frederic Riss | b616a18 | 2015-01-28 18:27:01 +0000 | [diff] [blame] | 2447 | continue; |
Frederic Riss | b616a18 | 2015-01-28 18:27:01 +0000 | [diff] [blame] | 2448 | |
Frederic Riss | 16acc91 | 2015-02-13 23:18:22 +0000 | [diff] [blame] | 2449 | // Look for relocations that correspond to debug map entries. |
Jonas Devlieghere | b936520 | 2018-03-13 14:27:15 +0000 | [diff] [blame] | 2450 | |
Jonas Devlieghere | 6169346 | 2018-02-08 10:48:54 +0000 | [diff] [blame] | 2451 | if (LLVM_LIKELY(!Options.Update) && |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 2452 | !LinkContext.RelocMgr.findValidRelocsInDebugInfo( |
| 2453 | *LinkContext.ObjectFile, LinkContext.DMO)) { |
Frederic Riss | d9a80bd | 2015-02-28 00:29:07 +0000 | [diff] [blame] | 2454 | if (Options.Verbose) |
Jonas Devlieghere | b936520 | 2018-03-13 14:27:15 +0000 | [diff] [blame] | 2455 | outs() << "No valid relocations found. Skipping.\n"; |
| 2456 | |
| 2457 | // Clear this ObjFile entry as a signal to other loops that we should not |
| 2458 | // process this iteration. |
| 2459 | LinkContext.ObjectFile = nullptr; |
Frederic Riss | 16acc91 | 2015-02-13 23:18:22 +0000 | [diff] [blame] | 2460 | continue; |
| 2461 | } |
| 2462 | |
Frederic Riss | 3ddec31 | 2015-01-28 22:15:14 +0000 | [diff] [blame] | 2463 | // Setup access to the debug info. |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 2464 | if (!LinkContext.DwarfContext) |
| 2465 | continue; |
Frederic Riss | b616a18 | 2015-01-28 18:27:01 +0000 | [diff] [blame] | 2466 | |
Jonas Devlieghere | b936520 | 2018-03-13 14:27:15 +0000 | [diff] [blame] | 2467 | startDebugObject(LinkContext); |
| 2468 | |
Adrian Prantl | fce2219 | 2015-10-05 23:11:20 +0000 | [diff] [blame] | 2469 | // In a first phase, just read in the debug info and load all clang modules. |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 2470 | LinkContext.CompileUnits.reserve( |
| 2471 | LinkContext.DwarfContext->getNumCompileUnits()); |
Jonas Devlieghere | 7c767bd | 2018-07-25 23:01:38 +0000 | [diff] [blame] | 2472 | |
Jonas Devlieghere | a4c60c4 | 2018-03-13 10:52:49 +0000 | [diff] [blame] | 2473 | for (const auto &CU : LinkContext.DwarfContext->compile_units()) { |
Jonas Devlieghere | 7c767bd | 2018-07-25 23:01:38 +0000 | [diff] [blame] | 2474 | updateDwarfVersion(CU->getVersion()); |
Greg Clayton | adb170f | 2016-12-13 18:25:19 +0000 | [diff] [blame] | 2475 | auto CUDie = CU->getUnitDIE(false); |
Frederic Riss | d9a80bd | 2015-02-28 00:29:07 +0000 | [diff] [blame] | 2476 | if (Options.Verbose) { |
Frederic Riss | b616a18 | 2015-01-28 18:27:01 +0000 | [diff] [blame] | 2477 | outs() << "Input compilation unit:"; |
Jonas Devlieghere | d266307 | 2017-09-13 09:43:05 +0000 | [diff] [blame] | 2478 | DIDumpOptions DumpOpts; |
Adrian Prantl | ae599aa | 2017-09-20 17:44:00 +0000 | [diff] [blame] | 2479 | DumpOpts.RecurseDepth = 0; |
Jonas Devlieghere | d266307 | 2017-09-13 09:43:05 +0000 | [diff] [blame] | 2480 | DumpOpts.Verbose = Options.Verbose; |
Adrian Prantl | ae599aa | 2017-09-20 17:44:00 +0000 | [diff] [blame] | 2481 | CUDie.dump(outs(), 0, DumpOpts); |
Frederic Riss | b616a18 | 2015-01-28 18:27:01 +0000 | [diff] [blame] | 2482 | } |
Adrian Prantl | 5309f16 | 2018-08-24 20:41:08 +0000 | [diff] [blame] | 2483 | if (CUDie && !LLVM_UNLIKELY(Options.Update)) |
| 2484 | registerModuleReference(CUDie, *CU, ModuleMap, LinkContext.DMO, |
| 2485 | LinkContext.Ranges, OffsetsStringPool, |
Jonas Devlieghere | 60c6009 | 2018-09-07 10:29:22 +0000 | [diff] [blame] | 2486 | UniquingStringPool, ODRContexts, 0, UnitID); |
Frederic Riss | b616a18 | 2015-01-28 18:27:01 +0000 | [diff] [blame] | 2487 | } |
Jonas Devlieghere | b936520 | 2018-03-13 14:27:15 +0000 | [diff] [blame] | 2488 | } |
Frederic Riss | 3ddec31 | 2015-01-28 22:15:14 +0000 | [diff] [blame] | 2489 | |
Jonas Devlieghere | 7c767bd | 2018-07-25 23:01:38 +0000 | [diff] [blame] | 2490 | // If we haven't seen any CUs, pick an arbitrary valid Dwarf version anyway. |
Jonas Devlieghere | 67eb8fd | 2018-04-02 10:40:43 +0000 | [diff] [blame] | 2491 | if (MaxDwarfVersion == 0) |
| 2492 | MaxDwarfVersion = 3; |
| 2493 | |
Jonas Devlieghere | 60c6009 | 2018-09-07 10:29:22 +0000 | [diff] [blame] | 2494 | // At this point we know how much data we have emitted. We use this value to |
| 2495 | // compare canonical DIE offsets in analyzeContextInfo to see if a definition |
| 2496 | // is already emitted, without being affected by canonical die offsets set |
| 2497 | // later. This prevents undeterminism when analyze and clone execute |
| 2498 | // concurrently, as clone set the canonical DIE offset and analyze reads it. |
| 2499 | const uint64_t ModulesEndOffset = OutputDebugInfoSize; |
| 2500 | |
Jonas Devlieghere | b936520 | 2018-03-13 14:27:15 +0000 | [diff] [blame] | 2501 | // These variables manage the list of processed object files. |
| 2502 | // The mutex and condition variable are to ensure that this is thread safe. |
| 2503 | std::mutex ProcessedFilesMutex; |
| 2504 | std::condition_variable ProcessedFilesConditionVariable; |
| 2505 | BitVector ProcessedFiles(NumObjects, false); |
| 2506 | |
Jonas Devlieghere | 9840d7c | 2018-09-06 17:31:59 +0000 | [diff] [blame] | 2507 | // Analyzing the context info is particularly expensive so it is executed in |
| 2508 | // parallel with emitting the previous compile unit. |
| 2509 | auto AnalyzeLambda = [&](size_t i) { |
| 2510 | auto &LinkContext = ObjectContexts[i]; |
Jonas Devlieghere | b936520 | 2018-03-13 14:27:15 +0000 | [diff] [blame] | 2511 | |
Jonas Devlieghere | 9840d7c | 2018-09-06 17:31:59 +0000 | [diff] [blame] | 2512 | if (!LinkContext.ObjectFile || !LinkContext.DwarfContext) |
| 2513 | return; |
| 2514 | |
| 2515 | for (const auto &CU : LinkContext.DwarfContext->compile_units()) { |
| 2516 | updateDwarfVersion(CU->getVersion()); |
| 2517 | // The !registerModuleReference() condition effectively skips |
| 2518 | // over fully resolved skeleton units. This second pass of |
| 2519 | // registerModuleReferences doesn't do any new work, but it |
| 2520 | // will collect top-level errors, which are suppressed. Module |
| 2521 | // warnings were already displayed in the first iteration. |
| 2522 | bool Quiet = true; |
| 2523 | auto CUDie = CU->getUnitDIE(false); |
| 2524 | if (!CUDie || LLVM_UNLIKELY(Options.Update) || |
| 2525 | !registerModuleReference(CUDie, *CU, ModuleMap, LinkContext.DMO, |
| 2526 | LinkContext.Ranges, OffsetsStringPool, |
Jonas Devlieghere | 60c6009 | 2018-09-07 10:29:22 +0000 | [diff] [blame] | 2527 | UniquingStringPool, ODRContexts, |
| 2528 | ModulesEndOffset, UnitID, Quiet)) { |
Jonas Devlieghere | 9840d7c | 2018-09-06 17:31:59 +0000 | [diff] [blame] | 2529 | LinkContext.CompileUnits.push_back(llvm::make_unique<CompileUnit>( |
| 2530 | *CU, UnitID++, !Options.NoODR && !Options.Update, "")); |
| 2531 | } |
| 2532 | } |
| 2533 | |
| 2534 | // Now build the DIE parent links that we will use during the next phase. |
| 2535 | for (auto &CurrentUnit : LinkContext.CompileUnits) { |
| 2536 | auto CUDie = CurrentUnit->getOrigUnit().getUnitDIE(); |
| 2537 | if (!CUDie) |
Jonas Devlieghere | b936520 | 2018-03-13 14:27:15 +0000 | [diff] [blame] | 2538 | continue; |
Jonas Devlieghere | 9840d7c | 2018-09-06 17:31:59 +0000 | [diff] [blame] | 2539 | analyzeContextInfo(CurrentUnit->getOrigUnit().getUnitDIE(), 0, |
| 2540 | *CurrentUnit, &ODRContexts.getRoot(), |
Jonas Devlieghere | 60c6009 | 2018-09-07 10:29:22 +0000 | [diff] [blame] | 2541 | UniquingStringPool, ODRContexts, ModulesEndOffset); |
Jonas Devlieghere | b936520 | 2018-03-13 14:27:15 +0000 | [diff] [blame] | 2542 | } |
Jonas Devlieghere | 2f039a0 | 2018-04-03 18:01:18 +0000 | [diff] [blame] | 2543 | }; |
Jonas Devlieghere | b936520 | 2018-03-13 14:27:15 +0000 | [diff] [blame] | 2544 | |
| 2545 | // And then the remaining work in serial again. |
| 2546 | // Note, although this loop runs in serial, it can run in parallel with |
| 2547 | // the analyzeContextInfo loop so long as we process files with indices >= |
| 2548 | // than those processed by analyzeContextInfo. |
Jonas Devlieghere | 9840d7c | 2018-09-06 17:31:59 +0000 | [diff] [blame] | 2549 | auto CloneLambda = [&](size_t i) { |
| 2550 | auto &LinkContext = ObjectContexts[i]; |
| 2551 | if (!LinkContext.ObjectFile) |
| 2552 | return; |
Jonas Devlieghere | b936520 | 2018-03-13 14:27:15 +0000 | [diff] [blame] | 2553 | |
Jonas Devlieghere | 9840d7c | 2018-09-06 17:31:59 +0000 | [diff] [blame] | 2554 | // Then mark all the DIEs that need to be present in the linked output |
| 2555 | // and collect some information about them. |
| 2556 | // Note that this loop can not be merged with the previous one because |
| 2557 | // cross-cu references require the ParentIdx to be setup for every CU in |
| 2558 | // the object file before calling this. |
| 2559 | if (LLVM_UNLIKELY(Options.Update)) { |
| 2560 | for (auto &CurrentUnit : LinkContext.CompileUnits) |
| 2561 | CurrentUnit->markEverythingAsKept(); |
| 2562 | Streamer->copyInvariantDebugSection(*LinkContext.ObjectFile); |
| 2563 | } else { |
| 2564 | for (auto &CurrentUnit : LinkContext.CompileUnits) |
| 2565 | lookForDIEsToKeep(LinkContext.RelocMgr, LinkContext.Ranges, |
| 2566 | LinkContext.CompileUnits, |
| 2567 | CurrentUnit->getOrigUnit().getUnitDIE(), |
| 2568 | LinkContext.DMO, *CurrentUnit, 0); |
Jonas Devlieghere | 6169346 | 2018-02-08 10:48:54 +0000 | [diff] [blame] | 2569 | } |
Frederic Riss | 2e2ed16 | 2015-02-13 23:18:34 +0000 | [diff] [blame] | 2570 | |
Jonas Devlieghere | 9840d7c | 2018-09-06 17:31:59 +0000 | [diff] [blame] | 2571 | // The calls to applyValidRelocs inside cloneDIE will walk the reloc |
| 2572 | // array again (in the same way findValidRelocsInDebugInfo() did). We |
| 2573 | // need to reset the NextValidReloc index to the beginning. |
| 2574 | LinkContext.RelocMgr.resetValidRelocs(); |
| 2575 | if (LinkContext.RelocMgr.hasValidRelocs() || LLVM_UNLIKELY(Options.Update)) |
| 2576 | DIECloner(*this, LinkContext.RelocMgr, DIEAlloc, LinkContext.CompileUnits, |
| 2577 | Options) |
| 2578 | .cloneAllCompileUnits(*LinkContext.DwarfContext, LinkContext.DMO, |
| 2579 | LinkContext.Ranges, OffsetsStringPool); |
| 2580 | if (!Options.NoOutput && !LinkContext.CompileUnits.empty() && |
| 2581 | LLVM_LIKELY(!Options.Update)) |
| 2582 | patchFrameInfoForObject( |
| 2583 | LinkContext.DMO, LinkContext.Ranges, *LinkContext.DwarfContext, |
| 2584 | LinkContext.CompileUnits[0]->getOrigUnit().getAddressByteSize()); |
| 2585 | |
| 2586 | // Clean-up before starting working on the next object. |
| 2587 | endDebugObject(LinkContext); |
| 2588 | }; |
| 2589 | |
| 2590 | auto EmitLambda = [&]() { |
Jonas Devlieghere | b936520 | 2018-03-13 14:27:15 +0000 | [diff] [blame] | 2591 | // Emit everything that's global. |
| 2592 | if (!Options.NoOutput) { |
| 2593 | Streamer->emitAbbrevs(Abbreviations, MaxDwarfVersion); |
| 2594 | Streamer->emitStrings(OffsetsStringPool); |
Jonas Devlieghere | 7c767bd | 2018-07-25 23:01:38 +0000 | [diff] [blame] | 2595 | switch (Options.TheAccelTableKind) { |
| 2596 | case AccelTableKind::Apple: |
| 2597 | Streamer->emitAppleNames(AppleNames); |
| 2598 | Streamer->emitAppleNamespaces(AppleNamespaces); |
| 2599 | Streamer->emitAppleTypes(AppleTypes); |
| 2600 | Streamer->emitAppleObjc(AppleObjc); |
| 2601 | break; |
| 2602 | case AccelTableKind::Dwarf: |
| 2603 | Streamer->emitDebugNames(DebugNames); |
| 2604 | break; |
| 2605 | case AccelTableKind::Default: |
| 2606 | llvm_unreachable("Default should have already been resolved."); |
| 2607 | break; |
| 2608 | } |
Jonas Devlieghere | b936520 | 2018-03-13 14:27:15 +0000 | [diff] [blame] | 2609 | } |
Jonas Devlieghere | 2f039a0 | 2018-04-03 18:01:18 +0000 | [diff] [blame] | 2610 | }; |
Frederic Riss | 9ccf07f | 2015-06-05 23:06:11 +0000 | [diff] [blame] | 2611 | |
Jonas Devlieghere | 9840d7c | 2018-09-06 17:31:59 +0000 | [diff] [blame] | 2612 | auto AnalyzeAll = [&]() { |
| 2613 | for (unsigned i = 0, e = NumObjects; i != e; ++i) { |
| 2614 | AnalyzeLambda(i); |
| 2615 | |
| 2616 | std::unique_lock<std::mutex> LockGuard(ProcessedFilesMutex); |
| 2617 | ProcessedFiles.set(i); |
| 2618 | ProcessedFilesConditionVariable.notify_one(); |
| 2619 | } |
| 2620 | }; |
| 2621 | |
| 2622 | auto CloneAll = [&]() { |
| 2623 | for (unsigned i = 0, e = NumObjects; i != e; ++i) { |
| 2624 | { |
| 2625 | std::unique_lock<std::mutex> LockGuard(ProcessedFilesMutex); |
| 2626 | if (!ProcessedFiles[i]) { |
| 2627 | ProcessedFilesConditionVariable.wait( |
| 2628 | LockGuard, [&]() { return ProcessedFiles[i]; }); |
| 2629 | } |
| 2630 | } |
| 2631 | |
| 2632 | CloneLambda(i); |
| 2633 | } |
| 2634 | EmitLambda(); |
| 2635 | }; |
| 2636 | |
| 2637 | // To limit memory usage in the single threaded case, analyze and clone are |
| 2638 | // run sequentially so the LinkContext is freed after processing each object |
| 2639 | // in endDebugObject. |
Jonas Devlieghere | 2f039a0 | 2018-04-03 18:01:18 +0000 | [diff] [blame] | 2640 | if (Options.Threads == 1) { |
Jonas Devlieghere | 9840d7c | 2018-09-06 17:31:59 +0000 | [diff] [blame] | 2641 | for (unsigned i = 0, e = NumObjects; i != e; ++i) { |
| 2642 | AnalyzeLambda(i); |
| 2643 | CloneLambda(i); |
| 2644 | } |
| 2645 | EmitLambda(); |
Jonas Devlieghere | 2f039a0 | 2018-04-03 18:01:18 +0000 | [diff] [blame] | 2646 | } else { |
| 2647 | ThreadPool pool(2); |
Jonas Devlieghere | 9840d7c | 2018-09-06 17:31:59 +0000 | [diff] [blame] | 2648 | pool.async(AnalyzeAll); |
| 2649 | pool.async(CloneAll); |
Jonas Devlieghere | 2f039a0 | 2018-04-03 18:01:18 +0000 | [diff] [blame] | 2650 | pool.wait(); |
| 2651 | } |
Frederic Riss | d0d92e7 | 2015-03-04 22:07:44 +0000 | [diff] [blame] | 2652 | |
Jonas Devlieghere | 20767d1 | 2019-01-07 23:27:25 +0000 | [diff] [blame] | 2653 | return Options.NoOutput ? true : Streamer->finish(Map, Options.Translator); |
Jonas Devlieghere | 7c767bd | 2018-07-25 23:01:38 +0000 | [diff] [blame] | 2654 | } // namespace dsymutil |
Frederic Riss | b616a18 | 2015-01-28 18:27:01 +0000 | [diff] [blame] | 2655 | |
Jonas Devlieghere | 9f33bbfe | 2018-06-29 16:51:52 +0000 | [diff] [blame] | 2656 | bool linkDwarf(raw_fd_ostream &OutFile, BinaryHolder &BinHolder, |
Jonas Devlieghere | 4d3e6c1 | 2018-06-29 16:50:41 +0000 | [diff] [blame] | 2657 | const DebugMap &DM, const LinkOptions &Options) { |
| 2658 | DwarfLinker Linker(OutFile, BinHolder, Options); |
Frederic Riss | b616a18 | 2015-01-28 18:27:01 +0000 | [diff] [blame] | 2659 | return Linker.link(DM); |
| 2660 | } |
Eugene Zelenko | 66f724e | 2017-11-01 21:16:06 +0000 | [diff] [blame] | 2661 | |
Jonas Devlieghere | cc46e39 | 2018-03-13 15:47:38 +0000 | [diff] [blame] | 2662 | } // namespace dsymutil |
| 2663 | } // namespace llvm |