Jonas Devlieghere | 928fea2 | 2018-06-27 16:13:40 +0000 | [diff] [blame] | 1 | //===- tools/dsymutil/DwarfStreamer.cpp - Dwarf Streamer ------------------===// |
| 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file is distributed under the University of Illinois Open Source |
| 6 | // License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | |
| 10 | #include "DwarfStreamer.h" |
Jonas Devlieghere | 7c767bd | 2018-07-25 23:01:38 +0000 | [diff] [blame] | 11 | #include "CompileUnit.h" |
Jonas Devlieghere | 928fea2 | 2018-06-27 16:13:40 +0000 | [diff] [blame] | 12 | #include "LinkUtils.h" |
| 13 | #include "MachOUtils.h" |
| 14 | #include "llvm/ADT/Triple.h" |
| 15 | #include "llvm/DebugInfo/DWARF/DWARFContext.h" |
| 16 | #include "llvm/MC/MCTargetOptions.h" |
| 17 | #include "llvm/MC/MCTargetOptionsCommandFlags.inc" |
| 18 | #include "llvm/Support/LEB128.h" |
| 19 | #include "llvm/Support/TargetRegistry.h" |
| 20 | #include "llvm/Target/TargetMachine.h" |
| 21 | #include "llvm/Target/TargetOptions.h" |
| 22 | |
| 23 | namespace llvm { |
| 24 | namespace dsymutil { |
| 25 | |
| 26 | /// Retrieve the section named \a SecName in \a Obj. |
| 27 | /// |
| 28 | /// To accommodate for platform discrepancies, the name passed should be |
| 29 | /// (for example) 'debug_info' to match either '__debug_info' or '.debug_info'. |
| 30 | /// This function will strip the initial platform-specific characters. |
| 31 | static Optional<object::SectionRef> |
| 32 | getSectionByName(const object::ObjectFile &Obj, StringRef SecName) { |
| 33 | for (const object::SectionRef &Section : Obj.sections()) { |
| 34 | StringRef SectionName; |
| 35 | Section.getName(SectionName); |
| 36 | SectionName = SectionName.substr(SectionName.find_first_not_of("._")); |
| 37 | if (SectionName != SecName) |
| 38 | continue; |
| 39 | return Section; |
| 40 | } |
| 41 | return None; |
| 42 | } |
| 43 | |
| 44 | bool DwarfStreamer::init(Triple TheTriple) { |
| 45 | std::string ErrorStr; |
| 46 | std::string TripleName; |
| 47 | StringRef Context = "dwarf streamer init"; |
| 48 | |
| 49 | // Get the target. |
| 50 | const Target *TheTarget = |
| 51 | TargetRegistry::lookupTarget(TripleName, TheTriple, ErrorStr); |
| 52 | if (!TheTarget) |
| 53 | return error(ErrorStr, Context); |
| 54 | TripleName = TheTriple.getTriple(); |
| 55 | |
| 56 | // Create all the MC Objects. |
| 57 | MRI.reset(TheTarget->createMCRegInfo(TripleName)); |
| 58 | if (!MRI) |
| 59 | return error(Twine("no register info for target ") + TripleName, Context); |
| 60 | |
| 61 | MAI.reset(TheTarget->createMCAsmInfo(*MRI, TripleName)); |
| 62 | if (!MAI) |
| 63 | return error("no asm info for target " + TripleName, Context); |
| 64 | |
| 65 | MOFI.reset(new MCObjectFileInfo); |
| 66 | MC.reset(new MCContext(MAI.get(), MRI.get(), MOFI.get())); |
| 67 | MOFI->InitMCObjectFileInfo(TheTriple, /*PIC*/ false, *MC); |
| 68 | |
| 69 | MSTI.reset(TheTarget->createMCSubtargetInfo(TripleName, "", "")); |
| 70 | if (!MSTI) |
| 71 | return error("no subtarget info for target " + TripleName, Context); |
| 72 | |
Jonas Devlieghere | a5d860c | 2018-07-09 16:58:48 +0000 | [diff] [blame] | 73 | MCTargetOptions MCOptions = InitMCTargetOptionsFromFlags(); |
| 74 | MAB = TheTarget->createMCAsmBackend(*MSTI, *MRI, MCOptions); |
Jonas Devlieghere | 928fea2 | 2018-06-27 16:13:40 +0000 | [diff] [blame] | 75 | if (!MAB) |
| 76 | return error("no asm backend for target " + TripleName, Context); |
| 77 | |
| 78 | MII.reset(TheTarget->createMCInstrInfo()); |
| 79 | if (!MII) |
| 80 | return error("no instr info info for target " + TripleName, Context); |
| 81 | |
| 82 | MCE = TheTarget->createMCCodeEmitter(*MII, *MRI, *MC); |
| 83 | if (!MCE) |
| 84 | return error("no code emitter for target " + TripleName, Context); |
| 85 | |
Jonas Devlieghere | a5d860c | 2018-07-09 16:58:48 +0000 | [diff] [blame] | 86 | switch (Options.FileType) { |
| 87 | case OutputFileType::Assembly: { |
| 88 | MIP = TheTarget->createMCInstPrinter(TheTriple, MAI->getAssemblerDialect(), |
| 89 | *MAI, *MII, *MRI); |
| 90 | MS = TheTarget->createAsmStreamer( |
| 91 | *MC, llvm::make_unique<formatted_raw_ostream>(OutFile), true, true, MIP, |
| 92 | std::unique_ptr<MCCodeEmitter>(MCE), std::unique_ptr<MCAsmBackend>(MAB), |
| 93 | true); |
| 94 | break; |
| 95 | } |
| 96 | case OutputFileType::Object: { |
| 97 | MS = TheTarget->createMCObjectStreamer( |
| 98 | TheTriple, *MC, std::unique_ptr<MCAsmBackend>(MAB), |
| 99 | MAB->createObjectWriter(OutFile), std::unique_ptr<MCCodeEmitter>(MCE), |
| 100 | *MSTI, MCOptions.MCRelaxAll, MCOptions.MCIncrementalLinkerCompatible, |
| 101 | /*DWARFMustBeAtTheEnd*/ false); |
| 102 | break; |
| 103 | } |
| 104 | } |
| 105 | |
Jonas Devlieghere | 928fea2 | 2018-06-27 16:13:40 +0000 | [diff] [blame] | 106 | if (!MS) |
| 107 | return error("no object streamer for target " + TripleName, Context); |
| 108 | |
| 109 | // Finally create the AsmPrinter we'll use to emit the DIEs. |
| 110 | TM.reset(TheTarget->createTargetMachine(TripleName, "", "", TargetOptions(), |
| 111 | None)); |
| 112 | if (!TM) |
| 113 | return error("no target machine for target " + TripleName, Context); |
| 114 | |
| 115 | Asm.reset(TheTarget->createAsmPrinter(*TM, std::unique_ptr<MCStreamer>(MS))); |
| 116 | if (!Asm) |
| 117 | return error("no asm printer for target " + TripleName, Context); |
| 118 | |
| 119 | RangesSectionSize = 0; |
| 120 | LocSectionSize = 0; |
| 121 | LineSectionSize = 0; |
| 122 | FrameSectionSize = 0; |
| 123 | |
| 124 | return true; |
| 125 | } |
| 126 | |
Jonas Devlieghere | 20767d1 | 2019-01-07 23:27:25 +0000 | [diff] [blame] | 127 | bool DwarfStreamer::finish(const DebugMap &DM, SymbolMapTranslator &T) { |
Jonas Devlieghere | 928fea2 | 2018-06-27 16:13:40 +0000 | [diff] [blame] | 128 | bool Result = true; |
Jonas Devlieghere | a5d860c | 2018-07-09 16:58:48 +0000 | [diff] [blame] | 129 | if (DM.getTriple().isOSDarwin() && !DM.getBinaryPath().empty() && |
| 130 | Options.FileType == OutputFileType::Object) |
Jonas Devlieghere | 20767d1 | 2019-01-07 23:27:25 +0000 | [diff] [blame] | 131 | Result = MachOUtils::generateDsymCompanion(DM, T, *MS, OutFile); |
Jonas Devlieghere | 928fea2 | 2018-06-27 16:13:40 +0000 | [diff] [blame] | 132 | else |
| 133 | MS->Finish(); |
| 134 | return Result; |
| 135 | } |
| 136 | |
| 137 | void DwarfStreamer::switchToDebugInfoSection(unsigned DwarfVersion) { |
| 138 | MS->SwitchSection(MOFI->getDwarfInfoSection()); |
| 139 | MC->setDwarfVersion(DwarfVersion); |
| 140 | } |
| 141 | |
| 142 | /// Emit the compilation unit header for \p Unit in the debug_info section. |
| 143 | /// |
| 144 | /// A Dwarf section header is encoded as: |
| 145 | /// uint32_t Unit length (omitting this field) |
| 146 | /// uint16_t Version |
| 147 | /// uint32_t Abbreviation table offset |
| 148 | /// uint8_t Address size |
| 149 | /// |
| 150 | /// Leading to a total of 11 bytes. |
| 151 | void DwarfStreamer::emitCompileUnitHeader(CompileUnit &Unit) { |
| 152 | unsigned Version = Unit.getOrigUnit().getVersion(); |
| 153 | switchToDebugInfoSection(Version); |
| 154 | |
Jonas Devlieghere | 55b2eb0 | 2018-07-06 12:49:54 +0000 | [diff] [blame] | 155 | /// The start of the unit within its section. |
| 156 | Unit.setLabelBegin(Asm->createTempSymbol("cu_begin")); |
| 157 | Asm->OutStreamer->EmitLabel(Unit.getLabelBegin()); |
| 158 | |
Jonas Devlieghere | 928fea2 | 2018-06-27 16:13:40 +0000 | [diff] [blame] | 159 | // Emit size of content not including length itself. The size has already |
| 160 | // been computed in CompileUnit::computeOffsets(). Subtract 4 to that size to |
| 161 | // account for the length field. |
| 162 | Asm->emitInt32(Unit.getNextUnitOffset() - Unit.getStartOffset() - 4); |
| 163 | Asm->emitInt16(Version); |
Jonas Devlieghere | 55b2eb0 | 2018-07-06 12:49:54 +0000 | [diff] [blame] | 164 | |
Jonas Devlieghere | 928fea2 | 2018-06-27 16:13:40 +0000 | [diff] [blame] | 165 | // We share one abbreviations table across all units so it's always at the |
| 166 | // start of the section. |
| 167 | Asm->emitInt32(0); |
| 168 | Asm->emitInt8(Unit.getOrigUnit().getAddressByteSize()); |
Jonas Devlieghere | 7c767bd | 2018-07-25 23:01:38 +0000 | [diff] [blame] | 169 | |
| 170 | // Remember this CU. |
| 171 | EmittedUnits.push_back({Unit.getUniqueID(), Unit.getLabelBegin()}); |
Jonas Devlieghere | 928fea2 | 2018-06-27 16:13:40 +0000 | [diff] [blame] | 172 | } |
| 173 | |
| 174 | /// Emit the \p Abbrevs array as the shared abbreviation table |
| 175 | /// for the linked Dwarf file. |
| 176 | void DwarfStreamer::emitAbbrevs( |
| 177 | const std::vector<std::unique_ptr<DIEAbbrev>> &Abbrevs, |
| 178 | unsigned DwarfVersion) { |
| 179 | MS->SwitchSection(MOFI->getDwarfAbbrevSection()); |
| 180 | MC->setDwarfVersion(DwarfVersion); |
| 181 | Asm->emitDwarfAbbrevs(Abbrevs); |
| 182 | } |
| 183 | |
| 184 | /// Recursively emit the DIE tree rooted at \p Die. |
| 185 | void DwarfStreamer::emitDIE(DIE &Die) { |
| 186 | MS->SwitchSection(MOFI->getDwarfInfoSection()); |
| 187 | Asm->emitDwarfDIE(Die); |
| 188 | } |
| 189 | |
| 190 | /// Emit the debug_str section stored in \p Pool. |
| 191 | void DwarfStreamer::emitStrings(const NonRelocatableStringpool &Pool) { |
| 192 | Asm->OutStreamer->SwitchSection(MOFI->getDwarfStrSection()); |
Pavel Labath | 23332c5 | 2018-08-07 09:54:52 +0000 | [diff] [blame] | 193 | std::vector<DwarfStringPoolEntryRef> Entries = Pool.getEntriesForEmission(); |
Jonas Devlieghere | 928fea2 | 2018-06-27 16:13:40 +0000 | [diff] [blame] | 194 | for (auto Entry : Entries) { |
Jonas Devlieghere | 928fea2 | 2018-06-27 16:13:40 +0000 | [diff] [blame] | 195 | // Emit the string itself. |
| 196 | Asm->OutStreamer->EmitBytes(Entry.getString()); |
| 197 | // Emit a null terminator. |
| 198 | Asm->emitInt8(0); |
| 199 | } |
| 200 | } |
| 201 | |
Jonas Devlieghere | 7c767bd | 2018-07-25 23:01:38 +0000 | [diff] [blame] | 202 | void DwarfStreamer::emitDebugNames( |
| 203 | AccelTable<DWARF5AccelTableStaticData> &Table) { |
| 204 | if (EmittedUnits.empty()) |
| 205 | return; |
| 206 | |
| 207 | // Build up data structures needed to emit this section. |
| 208 | std::vector<MCSymbol *> CompUnits; |
| 209 | DenseMap<unsigned, size_t> UniqueIdToCuMap; |
| 210 | unsigned Id = 0; |
| 211 | for (auto &CU : EmittedUnits) { |
| 212 | CompUnits.push_back(CU.LabelBegin); |
| 213 | // We might be omitting CUs, so we need to remap them. |
| 214 | UniqueIdToCuMap[CU.ID] = Id++; |
| 215 | } |
| 216 | |
| 217 | Asm->OutStreamer->SwitchSection(MOFI->getDwarfDebugNamesSection()); |
| 218 | emitDWARF5AccelTable( |
| 219 | Asm.get(), Table, CompUnits, |
| 220 | [&UniqueIdToCuMap](const DWARF5AccelTableStaticData &Entry) { |
| 221 | return UniqueIdToCuMap[Entry.getCUIndex()]; |
| 222 | }); |
| 223 | } |
| 224 | |
Jonas Devlieghere | 928fea2 | 2018-06-27 16:13:40 +0000 | [diff] [blame] | 225 | void DwarfStreamer::emitAppleNamespaces( |
| 226 | AccelTable<AppleAccelTableStaticOffsetData> &Table) { |
| 227 | Asm->OutStreamer->SwitchSection(MOFI->getDwarfAccelNamespaceSection()); |
| 228 | auto *SectionBegin = Asm->createTempSymbol("namespac_begin"); |
| 229 | Asm->OutStreamer->EmitLabel(SectionBegin); |
| 230 | emitAppleAccelTable(Asm.get(), Table, "namespac", SectionBegin); |
| 231 | } |
| 232 | |
| 233 | void DwarfStreamer::emitAppleNames( |
| 234 | AccelTable<AppleAccelTableStaticOffsetData> &Table) { |
| 235 | Asm->OutStreamer->SwitchSection(MOFI->getDwarfAccelNamesSection()); |
| 236 | auto *SectionBegin = Asm->createTempSymbol("names_begin"); |
| 237 | Asm->OutStreamer->EmitLabel(SectionBegin); |
| 238 | emitAppleAccelTable(Asm.get(), Table, "names", SectionBegin); |
| 239 | } |
| 240 | |
| 241 | void DwarfStreamer::emitAppleObjc( |
| 242 | AccelTable<AppleAccelTableStaticOffsetData> &Table) { |
| 243 | Asm->OutStreamer->SwitchSection(MOFI->getDwarfAccelObjCSection()); |
| 244 | auto *SectionBegin = Asm->createTempSymbol("objc_begin"); |
| 245 | Asm->OutStreamer->EmitLabel(SectionBegin); |
| 246 | emitAppleAccelTable(Asm.get(), Table, "objc", SectionBegin); |
| 247 | } |
| 248 | |
| 249 | void DwarfStreamer::emitAppleTypes( |
| 250 | AccelTable<AppleAccelTableStaticTypeData> &Table) { |
| 251 | Asm->OutStreamer->SwitchSection(MOFI->getDwarfAccelTypesSection()); |
| 252 | auto *SectionBegin = Asm->createTempSymbol("types_begin"); |
| 253 | Asm->OutStreamer->EmitLabel(SectionBegin); |
| 254 | emitAppleAccelTable(Asm.get(), Table, "types", SectionBegin); |
| 255 | } |
| 256 | |
| 257 | /// Emit the swift_ast section stored in \p Buffers. |
| 258 | void DwarfStreamer::emitSwiftAST(StringRef Buffer) { |
| 259 | MCSection *SwiftASTSection = MOFI->getDwarfSwiftASTSection(); |
| 260 | SwiftASTSection->setAlignment(1 << 5); |
| 261 | MS->SwitchSection(SwiftASTSection); |
| 262 | MS->EmitBytes(Buffer); |
| 263 | } |
| 264 | |
| 265 | /// Emit the debug_range section contents for \p FuncRange by |
| 266 | /// translating the original \p Entries. The debug_range section |
| 267 | /// format is totally trivial, consisting just of pairs of address |
| 268 | /// sized addresses describing the ranges. |
| 269 | void DwarfStreamer::emitRangesEntries( |
| 270 | int64_t UnitPcOffset, uint64_t OrigLowPc, |
| 271 | const FunctionIntervals::const_iterator &FuncRange, |
Wolfgang Pieb | daecf94 | 2018-10-31 01:12:58 +0000 | [diff] [blame] | 272 | const std::vector<DWARFDebugRangeList::RangeListEntry> &Entries, |
| 273 | unsigned AddressSize) { |
Jonas Devlieghere | 928fea2 | 2018-06-27 16:13:40 +0000 | [diff] [blame] | 274 | MS->SwitchSection(MC->getObjectFileInfo()->getDwarfRangesSection()); |
| 275 | |
| 276 | // Offset each range by the right amount. |
Wolfgang Pieb | daecf94 | 2018-10-31 01:12:58 +0000 | [diff] [blame] | 277 | int64_t PcOffset = Entries.empty() ? 0 : FuncRange.value() + UnitPcOffset; |
| 278 | for (const auto &Range : Entries) { |
| 279 | if (Range.isBaseAddressSelectionEntry(AddressSize)) { |
Jonas Devlieghere | 928fea2 | 2018-06-27 16:13:40 +0000 | [diff] [blame] | 280 | warn("unsupported base address selection operation", |
| 281 | "emitting debug_ranges"); |
| 282 | break; |
| 283 | } |
| 284 | // Do not emit empty ranges. |
Wolfgang Pieb | daecf94 | 2018-10-31 01:12:58 +0000 | [diff] [blame] | 285 | if (Range.StartAddress == Range.EndAddress) |
Jonas Devlieghere | 928fea2 | 2018-06-27 16:13:40 +0000 | [diff] [blame] | 286 | continue; |
| 287 | |
| 288 | // All range entries should lie in the function range. |
Wolfgang Pieb | daecf94 | 2018-10-31 01:12:58 +0000 | [diff] [blame] | 289 | if (!(Range.StartAddress + OrigLowPc >= FuncRange.start() && |
| 290 | Range.EndAddress + OrigLowPc <= FuncRange.stop())) |
Jonas Devlieghere | 928fea2 | 2018-06-27 16:13:40 +0000 | [diff] [blame] | 291 | warn("inconsistent range data.", "emitting debug_ranges"); |
Wolfgang Pieb | daecf94 | 2018-10-31 01:12:58 +0000 | [diff] [blame] | 292 | MS->EmitIntValue(Range.StartAddress + PcOffset, AddressSize); |
| 293 | MS->EmitIntValue(Range.EndAddress + PcOffset, AddressSize); |
Jonas Devlieghere | 928fea2 | 2018-06-27 16:13:40 +0000 | [diff] [blame] | 294 | RangesSectionSize += 2 * AddressSize; |
| 295 | } |
| 296 | |
| 297 | // Add the terminator entry. |
| 298 | MS->EmitIntValue(0, AddressSize); |
| 299 | MS->EmitIntValue(0, AddressSize); |
| 300 | RangesSectionSize += 2 * AddressSize; |
| 301 | } |
| 302 | |
| 303 | /// Emit the debug_aranges contribution of a unit and |
| 304 | /// if \p DoDebugRanges is true the debug_range contents for a |
| 305 | /// compile_unit level DW_AT_ranges attribute (Which are basically the |
| 306 | /// same thing with a different base address). |
| 307 | /// Just aggregate all the ranges gathered inside that unit. |
| 308 | void DwarfStreamer::emitUnitRangesEntries(CompileUnit &Unit, |
| 309 | bool DoDebugRanges) { |
| 310 | unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize(); |
| 311 | // Gather the ranges in a vector, so that we can simplify them. The |
| 312 | // IntervalMap will have coalesced the non-linked ranges, but here |
| 313 | // we want to coalesce the linked addresses. |
| 314 | std::vector<std::pair<uint64_t, uint64_t>> Ranges; |
| 315 | const auto &FunctionRanges = Unit.getFunctionRanges(); |
| 316 | for (auto Range = FunctionRanges.begin(), End = FunctionRanges.end(); |
| 317 | Range != End; ++Range) |
| 318 | Ranges.push_back(std::make_pair(Range.start() + Range.value(), |
| 319 | Range.stop() + Range.value())); |
| 320 | |
| 321 | // The object addresses where sorted, but again, the linked |
| 322 | // addresses might end up in a different order. |
Fangrui Song | 3b35e17 | 2018-09-27 02:13:45 +0000 | [diff] [blame] | 323 | llvm::sort(Ranges); |
Jonas Devlieghere | 928fea2 | 2018-06-27 16:13:40 +0000 | [diff] [blame] | 324 | |
| 325 | if (!Ranges.empty()) { |
| 326 | MS->SwitchSection(MC->getObjectFileInfo()->getDwarfARangesSection()); |
| 327 | |
| 328 | MCSymbol *BeginLabel = Asm->createTempSymbol("Barange"); |
| 329 | MCSymbol *EndLabel = Asm->createTempSymbol("Earange"); |
| 330 | |
| 331 | unsigned HeaderSize = |
| 332 | sizeof(int32_t) + // Size of contents (w/o this field |
| 333 | sizeof(int16_t) + // DWARF ARange version number |
| 334 | sizeof(int32_t) + // Offset of CU in the .debug_info section |
| 335 | sizeof(int8_t) + // Pointer Size (in bytes) |
| 336 | sizeof(int8_t); // Segment Size (in bytes) |
| 337 | |
| 338 | unsigned TupleSize = AddressSize * 2; |
| 339 | unsigned Padding = OffsetToAlignment(HeaderSize, TupleSize); |
| 340 | |
| 341 | Asm->EmitLabelDifference(EndLabel, BeginLabel, 4); // Arange length |
| 342 | Asm->OutStreamer->EmitLabel(BeginLabel); |
| 343 | Asm->emitInt16(dwarf::DW_ARANGES_VERSION); // Version number |
| 344 | Asm->emitInt32(Unit.getStartOffset()); // Corresponding unit's offset |
| 345 | Asm->emitInt8(AddressSize); // Address size |
| 346 | Asm->emitInt8(0); // Segment size |
| 347 | |
| 348 | Asm->OutStreamer->emitFill(Padding, 0x0); |
| 349 | |
| 350 | for (auto Range = Ranges.begin(), End = Ranges.end(); Range != End; |
| 351 | ++Range) { |
| 352 | uint64_t RangeStart = Range->first; |
| 353 | MS->EmitIntValue(RangeStart, AddressSize); |
| 354 | while ((Range + 1) != End && Range->second == (Range + 1)->first) |
| 355 | ++Range; |
| 356 | MS->EmitIntValue(Range->second - RangeStart, AddressSize); |
| 357 | } |
| 358 | |
| 359 | // Emit terminator |
| 360 | Asm->OutStreamer->EmitIntValue(0, AddressSize); |
| 361 | Asm->OutStreamer->EmitIntValue(0, AddressSize); |
| 362 | Asm->OutStreamer->EmitLabel(EndLabel); |
| 363 | } |
| 364 | |
| 365 | if (!DoDebugRanges) |
| 366 | return; |
| 367 | |
| 368 | MS->SwitchSection(MC->getObjectFileInfo()->getDwarfRangesSection()); |
| 369 | // Offset each range by the right amount. |
| 370 | int64_t PcOffset = -Unit.getLowPc(); |
| 371 | // Emit coalesced ranges. |
| 372 | for (auto Range = Ranges.begin(), End = Ranges.end(); Range != End; ++Range) { |
| 373 | MS->EmitIntValue(Range->first + PcOffset, AddressSize); |
| 374 | while (Range + 1 != End && Range->second == (Range + 1)->first) |
| 375 | ++Range; |
| 376 | MS->EmitIntValue(Range->second + PcOffset, AddressSize); |
| 377 | RangesSectionSize += 2 * AddressSize; |
| 378 | } |
| 379 | |
| 380 | // Add the terminator entry. |
| 381 | MS->EmitIntValue(0, AddressSize); |
| 382 | MS->EmitIntValue(0, AddressSize); |
| 383 | RangesSectionSize += 2 * AddressSize; |
| 384 | } |
| 385 | |
| 386 | /// Emit location lists for \p Unit and update attributes to point to the new |
| 387 | /// entries. |
| 388 | void DwarfStreamer::emitLocationsForUnit(const CompileUnit &Unit, |
| 389 | DWARFContext &Dwarf) { |
| 390 | const auto &Attributes = Unit.getLocationAttributes(); |
| 391 | |
| 392 | if (Attributes.empty()) |
| 393 | return; |
| 394 | |
| 395 | MS->SwitchSection(MC->getObjectFileInfo()->getDwarfLocSection()); |
| 396 | |
| 397 | unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize(); |
| 398 | const DWARFSection &InputSec = Dwarf.getDWARFObj().getLocSection(); |
| 399 | DataExtractor Data(InputSec.Data, Dwarf.isLittleEndian(), AddressSize); |
| 400 | DWARFUnit &OrigUnit = Unit.getOrigUnit(); |
| 401 | auto OrigUnitDie = OrigUnit.getUnitDIE(false); |
| 402 | int64_t UnitPcOffset = 0; |
| 403 | if (auto OrigLowPc = dwarf::toAddress(OrigUnitDie.find(dwarf::DW_AT_low_pc))) |
| 404 | UnitPcOffset = int64_t(*OrigLowPc) - Unit.getLowPc(); |
| 405 | |
| 406 | for (const auto &Attr : Attributes) { |
| 407 | uint32_t Offset = Attr.first.get(); |
| 408 | Attr.first.set(LocSectionSize); |
| 409 | // This is the quantity to add to the old location address to get |
| 410 | // the correct address for the new one. |
| 411 | int64_t LocPcOffset = Attr.second + UnitPcOffset; |
| 412 | while (Data.isValidOffset(Offset)) { |
| 413 | uint64_t Low = Data.getUnsigned(&Offset, AddressSize); |
| 414 | uint64_t High = Data.getUnsigned(&Offset, AddressSize); |
| 415 | LocSectionSize += 2 * AddressSize; |
| 416 | if (Low == 0 && High == 0) { |
| 417 | Asm->OutStreamer->EmitIntValue(0, AddressSize); |
| 418 | Asm->OutStreamer->EmitIntValue(0, AddressSize); |
| 419 | break; |
| 420 | } |
| 421 | Asm->OutStreamer->EmitIntValue(Low + LocPcOffset, AddressSize); |
| 422 | Asm->OutStreamer->EmitIntValue(High + LocPcOffset, AddressSize); |
| 423 | uint64_t Length = Data.getU16(&Offset); |
| 424 | Asm->OutStreamer->EmitIntValue(Length, 2); |
| 425 | // Just copy the bytes over. |
| 426 | Asm->OutStreamer->EmitBytes( |
| 427 | StringRef(InputSec.Data.substr(Offset, Length))); |
| 428 | Offset += Length; |
| 429 | LocSectionSize += Length + 2; |
| 430 | } |
| 431 | } |
| 432 | } |
| 433 | |
| 434 | void DwarfStreamer::emitLineTableForUnit(MCDwarfLineTableParams Params, |
| 435 | StringRef PrologueBytes, |
| 436 | unsigned MinInstLength, |
| 437 | std::vector<DWARFDebugLine::Row> &Rows, |
| 438 | unsigned PointerSize) { |
| 439 | // Switch to the section where the table will be emitted into. |
| 440 | MS->SwitchSection(MC->getObjectFileInfo()->getDwarfLineSection()); |
| 441 | MCSymbol *LineStartSym = MC->createTempSymbol(); |
| 442 | MCSymbol *LineEndSym = MC->createTempSymbol(); |
| 443 | |
| 444 | // The first 4 bytes is the total length of the information for this |
| 445 | // compilation unit (not including these 4 bytes for the length). |
| 446 | Asm->EmitLabelDifference(LineEndSym, LineStartSym, 4); |
| 447 | Asm->OutStreamer->EmitLabel(LineStartSym); |
| 448 | // Copy Prologue. |
| 449 | MS->EmitBytes(PrologueBytes); |
| 450 | LineSectionSize += PrologueBytes.size() + 4; |
| 451 | |
| 452 | SmallString<128> EncodingBuffer; |
| 453 | raw_svector_ostream EncodingOS(EncodingBuffer); |
| 454 | |
| 455 | if (Rows.empty()) { |
| 456 | // We only have the dummy entry, dsymutil emits an entry with a 0 |
| 457 | // address in that case. |
| 458 | MCDwarfLineAddr::Encode(*MC, Params, std::numeric_limits<int64_t>::max(), 0, |
| 459 | EncodingOS); |
| 460 | MS->EmitBytes(EncodingOS.str()); |
| 461 | LineSectionSize += EncodingBuffer.size(); |
| 462 | MS->EmitLabel(LineEndSym); |
| 463 | return; |
| 464 | } |
| 465 | |
| 466 | // Line table state machine fields |
| 467 | unsigned FileNum = 1; |
| 468 | unsigned LastLine = 1; |
| 469 | unsigned Column = 0; |
| 470 | unsigned IsStatement = 1; |
| 471 | unsigned Isa = 0; |
| 472 | uint64_t Address = -1ULL; |
| 473 | |
| 474 | unsigned RowsSinceLastSequence = 0; |
| 475 | |
| 476 | for (unsigned Idx = 0; Idx < Rows.size(); ++Idx) { |
| 477 | auto &Row = Rows[Idx]; |
| 478 | |
| 479 | int64_t AddressDelta; |
| 480 | if (Address == -1ULL) { |
| 481 | MS->EmitIntValue(dwarf::DW_LNS_extended_op, 1); |
| 482 | MS->EmitULEB128IntValue(PointerSize + 1); |
| 483 | MS->EmitIntValue(dwarf::DW_LNE_set_address, 1); |
| 484 | MS->EmitIntValue(Row.Address, PointerSize); |
| 485 | LineSectionSize += 2 + PointerSize + getULEB128Size(PointerSize + 1); |
| 486 | AddressDelta = 0; |
| 487 | } else { |
| 488 | AddressDelta = (Row.Address - Address) / MinInstLength; |
| 489 | } |
| 490 | |
| 491 | // FIXME: code copied and transformed from MCDwarf.cpp::EmitDwarfLineTable. |
| 492 | // We should find a way to share this code, but the current compatibility |
| 493 | // requirement with classic dsymutil makes it hard. Revisit that once this |
| 494 | // requirement is dropped. |
| 495 | |
| 496 | if (FileNum != Row.File) { |
| 497 | FileNum = Row.File; |
| 498 | MS->EmitIntValue(dwarf::DW_LNS_set_file, 1); |
| 499 | MS->EmitULEB128IntValue(FileNum); |
| 500 | LineSectionSize += 1 + getULEB128Size(FileNum); |
| 501 | } |
| 502 | if (Column != Row.Column) { |
| 503 | Column = Row.Column; |
| 504 | MS->EmitIntValue(dwarf::DW_LNS_set_column, 1); |
| 505 | MS->EmitULEB128IntValue(Column); |
| 506 | LineSectionSize += 1 + getULEB128Size(Column); |
| 507 | } |
| 508 | |
| 509 | // FIXME: We should handle the discriminator here, but dsymutil doesn't |
| 510 | // consider it, thus ignore it for now. |
| 511 | |
| 512 | if (Isa != Row.Isa) { |
| 513 | Isa = Row.Isa; |
| 514 | MS->EmitIntValue(dwarf::DW_LNS_set_isa, 1); |
| 515 | MS->EmitULEB128IntValue(Isa); |
| 516 | LineSectionSize += 1 + getULEB128Size(Isa); |
| 517 | } |
| 518 | if (IsStatement != Row.IsStmt) { |
| 519 | IsStatement = Row.IsStmt; |
| 520 | MS->EmitIntValue(dwarf::DW_LNS_negate_stmt, 1); |
| 521 | LineSectionSize += 1; |
| 522 | } |
| 523 | if (Row.BasicBlock) { |
| 524 | MS->EmitIntValue(dwarf::DW_LNS_set_basic_block, 1); |
| 525 | LineSectionSize += 1; |
| 526 | } |
| 527 | |
| 528 | if (Row.PrologueEnd) { |
| 529 | MS->EmitIntValue(dwarf::DW_LNS_set_prologue_end, 1); |
| 530 | LineSectionSize += 1; |
| 531 | } |
| 532 | |
| 533 | if (Row.EpilogueBegin) { |
| 534 | MS->EmitIntValue(dwarf::DW_LNS_set_epilogue_begin, 1); |
| 535 | LineSectionSize += 1; |
| 536 | } |
| 537 | |
| 538 | int64_t LineDelta = int64_t(Row.Line) - LastLine; |
| 539 | if (!Row.EndSequence) { |
| 540 | MCDwarfLineAddr::Encode(*MC, Params, LineDelta, AddressDelta, EncodingOS); |
| 541 | MS->EmitBytes(EncodingOS.str()); |
| 542 | LineSectionSize += EncodingBuffer.size(); |
| 543 | EncodingBuffer.resize(0); |
| 544 | Address = Row.Address; |
| 545 | LastLine = Row.Line; |
| 546 | RowsSinceLastSequence++; |
| 547 | } else { |
| 548 | if (LineDelta) { |
| 549 | MS->EmitIntValue(dwarf::DW_LNS_advance_line, 1); |
| 550 | MS->EmitSLEB128IntValue(LineDelta); |
| 551 | LineSectionSize += 1 + getSLEB128Size(LineDelta); |
| 552 | } |
| 553 | if (AddressDelta) { |
| 554 | MS->EmitIntValue(dwarf::DW_LNS_advance_pc, 1); |
| 555 | MS->EmitULEB128IntValue(AddressDelta); |
| 556 | LineSectionSize += 1 + getULEB128Size(AddressDelta); |
| 557 | } |
| 558 | MCDwarfLineAddr::Encode(*MC, Params, std::numeric_limits<int64_t>::max(), |
| 559 | 0, EncodingOS); |
| 560 | MS->EmitBytes(EncodingOS.str()); |
| 561 | LineSectionSize += EncodingBuffer.size(); |
| 562 | EncodingBuffer.resize(0); |
| 563 | Address = -1ULL; |
| 564 | LastLine = FileNum = IsStatement = 1; |
| 565 | RowsSinceLastSequence = Column = Isa = 0; |
| 566 | } |
| 567 | } |
| 568 | |
| 569 | if (RowsSinceLastSequence) { |
| 570 | MCDwarfLineAddr::Encode(*MC, Params, std::numeric_limits<int64_t>::max(), 0, |
| 571 | EncodingOS); |
| 572 | MS->EmitBytes(EncodingOS.str()); |
| 573 | LineSectionSize += EncodingBuffer.size(); |
| 574 | EncodingBuffer.resize(0); |
| 575 | } |
| 576 | |
| 577 | MS->EmitLabel(LineEndSym); |
| 578 | } |
| 579 | |
Jonas Devlieghere | 20767d1 | 2019-01-07 23:27:25 +0000 | [diff] [blame] | 580 | /// Copy the debug_line over to the updated binary while unobfuscating the file |
| 581 | /// names and directories. |
| 582 | void DwarfStreamer::translateLineTable(DataExtractor Data, uint32_t Offset, |
| 583 | LinkOptions &Options) { |
| 584 | MS->SwitchSection(MC->getObjectFileInfo()->getDwarfLineSection()); |
| 585 | StringRef Contents = Data.getData(); |
| 586 | |
| 587 | // We have to deconstruct the line table header, because it contains to |
| 588 | // length fields that will need to be updated when we change the length of |
| 589 | // the files and directories in there. |
| 590 | unsigned UnitLength = Data.getU32(&Offset); |
| 591 | unsigned UnitEnd = Offset + UnitLength; |
| 592 | MCSymbol *BeginLabel = MC->createTempSymbol(); |
| 593 | MCSymbol *EndLabel = MC->createTempSymbol(); |
| 594 | unsigned Version = Data.getU16(&Offset); |
| 595 | |
| 596 | if (Version > 5) { |
| 597 | warn("Unsupported line table version: dropping contents and not " |
| 598 | "unobfsucating line table."); |
| 599 | return; |
| 600 | } |
| 601 | |
| 602 | Asm->EmitLabelDifference(EndLabel, BeginLabel, 4); |
| 603 | Asm->OutStreamer->EmitLabel(BeginLabel); |
| 604 | Asm->emitInt16(Version); |
| 605 | LineSectionSize += 6; |
| 606 | |
| 607 | MCSymbol *HeaderBeginLabel = MC->createTempSymbol(); |
| 608 | MCSymbol *HeaderEndLabel = MC->createTempSymbol(); |
| 609 | Asm->EmitLabelDifference(HeaderEndLabel, HeaderBeginLabel, 4); |
| 610 | Asm->OutStreamer->EmitLabel(HeaderBeginLabel); |
| 611 | Offset += 4; |
| 612 | LineSectionSize += 4; |
| 613 | |
| 614 | uint32_t AfterHeaderLengthOffset = Offset; |
| 615 | // Skip to the directories. |
| 616 | Offset += (Version >= 4) ? 5 : 4; |
| 617 | unsigned OpcodeBase = Data.getU8(&Offset); |
| 618 | Offset += OpcodeBase - 1; |
| 619 | Asm->OutStreamer->EmitBytes(Contents.slice(AfterHeaderLengthOffset, Offset)); |
| 620 | LineSectionSize += Offset - AfterHeaderLengthOffset; |
| 621 | |
| 622 | // Offset points to the first directory. |
| 623 | while (const char *Dir = Data.getCStr(&Offset)) { |
| 624 | if (Dir[0] == 0) |
| 625 | break; |
| 626 | |
| 627 | StringRef Translated = Options.Translator(Dir); |
| 628 | Asm->OutStreamer->EmitBytes(Translated); |
| 629 | Asm->emitInt8(0); |
| 630 | LineSectionSize += Translated.size() + 1; |
| 631 | } |
| 632 | Asm->emitInt8(0); |
| 633 | LineSectionSize += 1; |
| 634 | |
| 635 | while (const char *File = Data.getCStr(&Offset)) { |
| 636 | if (File[0] == 0) |
| 637 | break; |
| 638 | |
| 639 | StringRef Translated = Options.Translator(File); |
| 640 | Asm->OutStreamer->EmitBytes(Translated); |
| 641 | Asm->emitInt8(0); |
| 642 | LineSectionSize += Translated.size() + 1; |
| 643 | |
| 644 | uint32_t OffsetBeforeLEBs = Offset; |
| 645 | Asm->EmitULEB128(Data.getULEB128(&Offset)); |
| 646 | Asm->EmitULEB128(Data.getULEB128(&Offset)); |
| 647 | Asm->EmitULEB128(Data.getULEB128(&Offset)); |
| 648 | LineSectionSize += Offset - OffsetBeforeLEBs; |
| 649 | } |
| 650 | Asm->emitInt8(0); |
| 651 | LineSectionSize += 1; |
| 652 | |
| 653 | Asm->OutStreamer->EmitLabel(HeaderEndLabel); |
| 654 | |
| 655 | // Copy the actual line table program over. |
| 656 | Asm->OutStreamer->EmitBytes(Contents.slice(Offset, UnitEnd)); |
| 657 | LineSectionSize += UnitEnd - Offset; |
| 658 | |
| 659 | Asm->OutStreamer->EmitLabel(EndLabel); |
| 660 | Offset = UnitEnd; |
| 661 | } |
| 662 | |
Jonas Devlieghere | 928fea2 | 2018-06-27 16:13:40 +0000 | [diff] [blame] | 663 | static void emitSectionContents(const object::ObjectFile &Obj, |
| 664 | StringRef SecName, MCStreamer *MS) { |
| 665 | StringRef Contents; |
| 666 | if (auto Sec = getSectionByName(Obj, SecName)) |
| 667 | if (!Sec->getContents(Contents)) |
| 668 | MS->EmitBytes(Contents); |
| 669 | } |
| 670 | |
Jonas Devlieghere | a5d860c | 2018-07-09 16:58:48 +0000 | [diff] [blame] | 671 | void DwarfStreamer::copyInvariantDebugSection(const object::ObjectFile &Obj) { |
Jonas Devlieghere | 20767d1 | 2019-01-07 23:27:25 +0000 | [diff] [blame] | 672 | if (!Options.Translator) { |
| 673 | MS->SwitchSection(MC->getObjectFileInfo()->getDwarfLineSection()); |
| 674 | emitSectionContents(Obj, "debug_line", MS); |
| 675 | } |
Jonas Devlieghere | 928fea2 | 2018-06-27 16:13:40 +0000 | [diff] [blame] | 676 | |
| 677 | MS->SwitchSection(MC->getObjectFileInfo()->getDwarfLocSection()); |
| 678 | emitSectionContents(Obj, "debug_loc", MS); |
| 679 | |
| 680 | MS->SwitchSection(MC->getObjectFileInfo()->getDwarfRangesSection()); |
| 681 | emitSectionContents(Obj, "debug_ranges", MS); |
| 682 | |
| 683 | MS->SwitchSection(MC->getObjectFileInfo()->getDwarfFrameSection()); |
| 684 | emitSectionContents(Obj, "debug_frame", MS); |
| 685 | |
| 686 | MS->SwitchSection(MC->getObjectFileInfo()->getDwarfARangesSection()); |
| 687 | emitSectionContents(Obj, "debug_aranges", MS); |
| 688 | } |
| 689 | |
| 690 | /// Emit the pubnames or pubtypes section contribution for \p |
| 691 | /// Unit into \p Sec. The data is provided in \p Names. |
| 692 | void DwarfStreamer::emitPubSectionForUnit( |
| 693 | MCSection *Sec, StringRef SecName, const CompileUnit &Unit, |
| 694 | const std::vector<CompileUnit::AccelInfo> &Names) { |
| 695 | if (Names.empty()) |
| 696 | return; |
| 697 | |
| 698 | // Start the dwarf pubnames section. |
| 699 | Asm->OutStreamer->SwitchSection(Sec); |
| 700 | MCSymbol *BeginLabel = Asm->createTempSymbol("pub" + SecName + "_begin"); |
| 701 | MCSymbol *EndLabel = Asm->createTempSymbol("pub" + SecName + "_end"); |
| 702 | |
| 703 | bool HeaderEmitted = false; |
| 704 | // Emit the pubnames for this compilation unit. |
| 705 | for (const auto &Name : Names) { |
| 706 | if (Name.SkipPubSection) |
| 707 | continue; |
| 708 | |
| 709 | if (!HeaderEmitted) { |
| 710 | // Emit the header. |
| 711 | Asm->EmitLabelDifference(EndLabel, BeginLabel, 4); // Length |
| 712 | Asm->OutStreamer->EmitLabel(BeginLabel); |
| 713 | Asm->emitInt16(dwarf::DW_PUBNAMES_VERSION); // Version |
| 714 | Asm->emitInt32(Unit.getStartOffset()); // Unit offset |
| 715 | Asm->emitInt32(Unit.getNextUnitOffset() - Unit.getStartOffset()); // Size |
| 716 | HeaderEmitted = true; |
| 717 | } |
| 718 | Asm->emitInt32(Name.Die->getOffset()); |
| 719 | |
| 720 | // Emit the string itself. |
| 721 | Asm->OutStreamer->EmitBytes(Name.Name.getString()); |
| 722 | // Emit a null terminator. |
| 723 | Asm->emitInt8(0); |
| 724 | } |
| 725 | |
| 726 | if (!HeaderEmitted) |
| 727 | return; |
| 728 | Asm->emitInt32(0); // End marker. |
| 729 | Asm->OutStreamer->EmitLabel(EndLabel); |
| 730 | } |
| 731 | |
| 732 | /// Emit .debug_pubnames for \p Unit. |
| 733 | void DwarfStreamer::emitPubNamesForUnit(const CompileUnit &Unit) { |
| 734 | emitPubSectionForUnit(MC->getObjectFileInfo()->getDwarfPubNamesSection(), |
| 735 | "names", Unit, Unit.getPubnames()); |
| 736 | } |
| 737 | |
| 738 | /// Emit .debug_pubtypes for \p Unit. |
| 739 | void DwarfStreamer::emitPubTypesForUnit(const CompileUnit &Unit) { |
| 740 | emitPubSectionForUnit(MC->getObjectFileInfo()->getDwarfPubTypesSection(), |
| 741 | "types", Unit, Unit.getPubtypes()); |
| 742 | } |
| 743 | |
| 744 | /// Emit a CIE into the debug_frame section. |
| 745 | void DwarfStreamer::emitCIE(StringRef CIEBytes) { |
| 746 | MS->SwitchSection(MC->getObjectFileInfo()->getDwarfFrameSection()); |
| 747 | |
| 748 | MS->EmitBytes(CIEBytes); |
| 749 | FrameSectionSize += CIEBytes.size(); |
| 750 | } |
| 751 | |
| 752 | /// Emit a FDE into the debug_frame section. \p FDEBytes |
| 753 | /// contains the FDE data without the length, CIE offset and address |
| 754 | /// which will be replaced with the parameter values. |
| 755 | void DwarfStreamer::emitFDE(uint32_t CIEOffset, uint32_t AddrSize, |
| 756 | uint32_t Address, StringRef FDEBytes) { |
| 757 | MS->SwitchSection(MC->getObjectFileInfo()->getDwarfFrameSection()); |
| 758 | |
| 759 | MS->EmitIntValue(FDEBytes.size() + 4 + AddrSize, 4); |
| 760 | MS->EmitIntValue(CIEOffset, 4); |
| 761 | MS->EmitIntValue(Address, AddrSize); |
| 762 | MS->EmitBytes(FDEBytes); |
| 763 | FrameSectionSize += FDEBytes.size() + 8 + AddrSize; |
| 764 | } |
| 765 | |
| 766 | } // namespace dsymutil |
| 767 | } // namespace llvm |