1 //===-- llvm-dwp.cpp - Split DWARF merging tool for llvm ------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // A utility for merging DWARF 5 Split DWARF .dwo files into .dwp (DWARF 10 // package files). 11 // 12 //===----------------------------------------------------------------------===// 13 #include "llvm/DWP/DWP.h" 14 #include "llvm/DWP/DWPError.h" 15 #include "llvm/MC/MCContext.h" 16 #include "llvm/MC/MCObjectFileInfo.h" 17 #include "llvm/MC/MCTargetOptionsCommandFlags.h" 18 #include "llvm/Object/Decompressor.h" 19 #include "llvm/Support/MemoryBuffer.h" 20 21 using namespace llvm; 22 using namespace llvm::object; 23 24 static mc::RegisterMCTargetOptionsFlags MCTargetOptionsFlags; 25 26 // Returns the size of debug_str_offsets section headers in bytes. 27 static uint64_t debugStrOffsetsHeaderSize(DataExtractor StrOffsetsData, 28 uint16_t DwarfVersion) { 29 if (DwarfVersion <= 4) 30 return 0; // There is no header before dwarf 5. 31 uint64_t Offset = 0; 32 uint64_t Length = StrOffsetsData.getU32(&Offset); 33 if (Length == llvm::dwarf::DW_LENGTH_DWARF64) 34 return 16; // unit length: 12 bytes, version: 2 bytes, padding: 2 bytes. 35 return 8; // unit length: 4 bytes, version: 2 bytes, padding: 2 bytes. 36 } 37 38 static uint64_t getCUAbbrev(StringRef Abbrev, uint64_t AbbrCode) { 39 uint64_t Offset = 0; 40 DataExtractor AbbrevData(Abbrev, true, 0); 41 while (AbbrevData.getULEB128(&Offset) != AbbrCode) { 42 // Tag 43 AbbrevData.getULEB128(&Offset); 44 // DW_CHILDREN 45 AbbrevData.getU8(&Offset); 46 // Attributes 47 while (AbbrevData.getULEB128(&Offset) | AbbrevData.getULEB128(&Offset)) 48 ; 49 } 50 return Offset; 51 } 52 53 static Expected<const char *> 54 getIndexedString(dwarf::Form Form, DataExtractor InfoData, uint64_t &InfoOffset, 55 StringRef StrOffsets, StringRef Str, uint16_t Version) { 56 if (Form == dwarf::DW_FORM_string) 57 return InfoData.getCStr(&InfoOffset); 58 uint64_t StrIndex; 59 switch (Form) { 60 case dwarf::DW_FORM_strx1: 61 StrIndex = InfoData.getU8(&InfoOffset); 62 break; 63 case dwarf::DW_FORM_strx2: 64 StrIndex = InfoData.getU16(&InfoOffset); 65 break; 66 case dwarf::DW_FORM_strx3: 67 StrIndex = InfoData.getU24(&InfoOffset); 68 break; 69 case dwarf::DW_FORM_strx4: 70 StrIndex = InfoData.getU32(&InfoOffset); 71 break; 72 case dwarf::DW_FORM_strx: 73 case dwarf::DW_FORM_GNU_str_index: 74 StrIndex = InfoData.getULEB128(&InfoOffset); 75 break; 76 default: 77 return make_error<DWPError>( 78 "string field must be encoded with one of the following: " 79 "DW_FORM_string, DW_FORM_strx, DW_FORM_strx1, DW_FORM_strx2, " 80 "DW_FORM_strx3, DW_FORM_strx4, or DW_FORM_GNU_str_index."); 81 } 82 DataExtractor StrOffsetsData(StrOffsets, true, 0); 83 uint64_t StrOffsetsOffset = 4 * StrIndex; 84 StrOffsetsOffset += debugStrOffsetsHeaderSize(StrOffsetsData, Version); 85 86 uint64_t StrOffset = StrOffsetsData.getU32(&StrOffsetsOffset); 87 DataExtractor StrData(Str, true, 0); 88 return StrData.getCStr(&StrOffset); 89 } 90 91 static Expected<CompileUnitIdentifiers> 92 getCUIdentifiers(InfoSectionUnitHeader &Header, StringRef Abbrev, 93 StringRef Info, StringRef StrOffsets, StringRef Str) { 94 DataExtractor InfoData(Info, true, 0); 95 uint64_t Offset = Header.HeaderSize; 96 if (Header.Version >= 5 && Header.UnitType != dwarf::DW_UT_split_compile) 97 return make_error<DWPError>( 98 std::string("unit type DW_UT_split_compile type not found in " 99 "debug_info header. Unexpected unit type 0x" + 100 utostr(Header.UnitType) + " found")); 101 102 CompileUnitIdentifiers ID; 103 104 uint32_t AbbrCode = InfoData.getULEB128(&Offset); 105 DataExtractor AbbrevData(Abbrev, true, 0); 106 uint64_t AbbrevOffset = getCUAbbrev(Abbrev, AbbrCode); 107 auto Tag = static_cast<dwarf::Tag>(AbbrevData.getULEB128(&AbbrevOffset)); 108 if (Tag != dwarf::DW_TAG_compile_unit) 109 return make_error<DWPError>("top level DIE is not a compile unit"); 110 // DW_CHILDREN 111 AbbrevData.getU8(&AbbrevOffset); 112 uint32_t Name; 113 dwarf::Form Form; 114 while ((Name = AbbrevData.getULEB128(&AbbrevOffset)) | 115 (Form = static_cast<dwarf::Form>( 116 AbbrevData.getULEB128(&AbbrevOffset))) && 117 (Name != 0 || Form != 0)) { 118 switch (Name) { 119 case dwarf::DW_AT_name: { 120 Expected<const char *> EName = getIndexedString( 121 Form, InfoData, Offset, StrOffsets, Str, Header.Version); 122 if (!EName) 123 return EName.takeError(); 124 ID.Name = *EName; 125 break; 126 } 127 case dwarf::DW_AT_GNU_dwo_name: 128 case dwarf::DW_AT_dwo_name: { 129 Expected<const char *> EName = getIndexedString( 130 Form, InfoData, Offset, StrOffsets, Str, Header.Version); 131 if (!EName) 132 return EName.takeError(); 133 ID.DWOName = *EName; 134 break; 135 } 136 case dwarf::DW_AT_GNU_dwo_id: 137 Header.Signature = InfoData.getU64(&Offset); 138 break; 139 default: 140 DWARFFormValue::skipValue( 141 Form, InfoData, &Offset, 142 dwarf::FormParams({Header.Version, Header.AddrSize, Header.Format})); 143 } 144 } 145 if (!Header.Signature) 146 return make_error<DWPError>("compile unit missing dwo_id"); 147 ID.Signature = *Header.Signature; 148 return ID; 149 } 150 151 static bool isSupportedSectionKind(DWARFSectionKind Kind) { 152 return Kind != DW_SECT_EXT_unknown; 153 } 154 155 namespace llvm { 156 // Convert an internal section identifier into the index to use with 157 // UnitIndexEntry::Contributions. 158 unsigned getContributionIndex(DWARFSectionKind Kind, uint32_t IndexVersion) { 159 assert(serializeSectionKind(Kind, IndexVersion) >= DW_SECT_INFO); 160 return serializeSectionKind(Kind, IndexVersion) - DW_SECT_INFO; 161 } 162 } // namespace llvm 163 164 // Convert a UnitIndexEntry::Contributions index to the corresponding on-disk 165 // value of the section identifier. 166 static unsigned getOnDiskSectionId(unsigned Index) { 167 return Index + DW_SECT_INFO; 168 } 169 170 static StringRef getSubsection(StringRef Section, 171 const DWARFUnitIndex::Entry &Entry, 172 DWARFSectionKind Kind) { 173 const auto *Off = Entry.getContribution(Kind); 174 if (!Off) 175 return StringRef(); 176 return Section.substr(Off->Offset, Off->Length); 177 } 178 179 static void 180 addAllTypesFromDWP(MCStreamer &Out, 181 MapVector<uint64_t, UnitIndexEntry> &TypeIndexEntries, 182 const DWARFUnitIndex &TUIndex, MCSection *OutputTypes, 183 StringRef Types, const UnitIndexEntry &TUEntry, 184 uint32_t &TypesOffset, unsigned TypesContributionIndex) { 185 Out.switchSection(OutputTypes); 186 for (const DWARFUnitIndex::Entry &E : TUIndex.getRows()) { 187 auto *I = E.getContributions(); 188 if (!I) 189 continue; 190 auto P = TypeIndexEntries.insert(std::make_pair(E.getSignature(), TUEntry)); 191 if (!P.second) 192 continue; 193 auto &Entry = P.first->second; 194 // Zero out the debug_info contribution 195 Entry.Contributions[0] = {}; 196 for (auto Kind : TUIndex.getColumnKinds()) { 197 if (!isSupportedSectionKind(Kind)) 198 continue; 199 auto &C = 200 Entry.Contributions[getContributionIndex(Kind, TUIndex.getVersion())]; 201 C.Offset += I->Offset; 202 C.Length = I->Length; 203 ++I; 204 } 205 auto &C = Entry.Contributions[TypesContributionIndex]; 206 Out.emitBytes(Types.substr( 207 C.Offset - TUEntry.Contributions[TypesContributionIndex].Offset, 208 C.Length)); 209 C.Offset = TypesOffset; 210 TypesOffset += C.Length; 211 } 212 } 213 214 static void addAllTypesFromTypesSection( 215 MCStreamer &Out, MapVector<uint64_t, UnitIndexEntry> &TypeIndexEntries, 216 MCSection *OutputTypes, const std::vector<StringRef> &TypesSections, 217 const UnitIndexEntry &CUEntry, uint32_t &TypesOffset) { 218 for (StringRef Types : TypesSections) { 219 Out.switchSection(OutputTypes); 220 uint64_t Offset = 0; 221 DataExtractor Data(Types, true, 0); 222 while (Data.isValidOffset(Offset)) { 223 UnitIndexEntry Entry = CUEntry; 224 // Zero out the debug_info contribution 225 Entry.Contributions[0] = {}; 226 auto &C = Entry.Contributions[getContributionIndex(DW_SECT_EXT_TYPES, 2)]; 227 C.Offset = TypesOffset; 228 auto PrevOffset = Offset; 229 // Length of the unit, including the 4 byte length field. 230 C.Length = Data.getU32(&Offset) + 4; 231 232 Data.getU16(&Offset); // Version 233 Data.getU32(&Offset); // Abbrev offset 234 Data.getU8(&Offset); // Address size 235 auto Signature = Data.getU64(&Offset); 236 Offset = PrevOffset + C.Length; 237 238 auto P = TypeIndexEntries.insert(std::make_pair(Signature, Entry)); 239 if (!P.second) 240 continue; 241 242 Out.emitBytes(Types.substr(PrevOffset, C.Length)); 243 TypesOffset += C.Length; 244 } 245 } 246 } 247 248 static std::string buildDWODescription(StringRef Name, StringRef DWPName, 249 StringRef DWOName) { 250 std::string Text = "\'"; 251 Text += Name; 252 Text += '\''; 253 if (!DWPName.empty()) { 254 Text += " (from "; 255 if (!DWOName.empty()) { 256 Text += '\''; 257 Text += DWOName; 258 Text += "' in "; 259 } 260 Text += '\''; 261 Text += DWPName; 262 Text += "')"; 263 } 264 return Text; 265 } 266 267 static Error createError(StringRef Name, Error E) { 268 return make_error<DWPError>( 269 ("failure while decompressing compressed section: '" + Name + "', " + 270 llvm::toString(std::move(E))) 271 .str()); 272 } 273 274 static Error 275 handleCompressedSection(std::deque<SmallString<32>> &UncompressedSections, 276 StringRef &Name, StringRef &Contents) { 277 if (!Decompressor::isGnuStyle(Name)) 278 return Error::success(); 279 280 Expected<Decompressor> Dec = 281 Decompressor::create(Name, Contents, false /*IsLE*/, false /*Is64Bit*/); 282 if (!Dec) 283 return createError(Name, Dec.takeError()); 284 285 UncompressedSections.emplace_back(); 286 if (Error E = Dec->resizeAndDecompress(UncompressedSections.back())) 287 return createError(Name, std::move(E)); 288 289 Name = Name.substr(2); // Drop ".z" 290 Contents = UncompressedSections.back(); 291 return Error::success(); 292 } 293 294 namespace llvm { 295 // Parse and return the header of an info section compile/type unit. 296 Expected<InfoSectionUnitHeader> parseInfoSectionUnitHeader(StringRef Info) { 297 InfoSectionUnitHeader Header; 298 Error Err = Error::success(); 299 uint64_t Offset = 0; 300 DWARFDataExtractor InfoData(Info, true, 0); 301 std::tie(Header.Length, Header.Format) = 302 InfoData.getInitialLength(&Offset, &Err); 303 if (Err) 304 return make_error<DWPError>("cannot parse compile unit length: " + 305 llvm::toString(std::move(Err))); 306 307 if (!InfoData.isValidOffset(Offset + (Header.Length - 1))) { 308 return make_error<DWPError>( 309 "compile unit exceeds .debug_info section range: " + 310 utostr(Offset + Header.Length) + " >= " + utostr(InfoData.size())); 311 } 312 313 Header.Version = InfoData.getU16(&Offset, &Err); 314 if (Err) 315 return make_error<DWPError>("cannot parse compile unit version: " + 316 llvm::toString(std::move(Err))); 317 318 uint64_t MinHeaderLength; 319 if (Header.Version >= 5) { 320 // Size: Version (2), UnitType (1), AddrSize (1), DebugAbbrevOffset (4), 321 // Signature (8) 322 MinHeaderLength = 16; 323 } else { 324 // Size: Version (2), DebugAbbrevOffset (4), AddrSize (1) 325 MinHeaderLength = 7; 326 } 327 if (Header.Length < MinHeaderLength) { 328 return make_error<DWPError>("unit length is too small: expected at least " + 329 utostr(MinHeaderLength) + " got " + 330 utostr(Header.Length) + "."); 331 } 332 if (Header.Version >= 5) { 333 Header.UnitType = InfoData.getU8(&Offset); 334 Header.AddrSize = InfoData.getU8(&Offset); 335 Header.DebugAbbrevOffset = InfoData.getU32(&Offset); 336 Header.Signature = InfoData.getU64(&Offset); 337 if (Header.UnitType == dwarf::DW_UT_split_type) { 338 // Type offset. 339 MinHeaderLength += 4; 340 if (Header.Length < MinHeaderLength) 341 return make_error<DWPError>("type unit is missing type offset"); 342 InfoData.getU32(&Offset); 343 } 344 } else { 345 // Note that, address_size and debug_abbrev_offset fields have switched 346 // places between dwarf version 4 and 5. 347 Header.DebugAbbrevOffset = InfoData.getU32(&Offset); 348 Header.AddrSize = InfoData.getU8(&Offset); 349 } 350 351 Header.HeaderSize = Offset; 352 return Header; 353 } 354 355 void writeStringsAndOffsets(MCStreamer &Out, DWPStringPool &Strings, 356 MCSection *StrOffsetSection, 357 StringRef CurStrSection, 358 StringRef CurStrOffsetSection, uint16_t Version) { 359 // Could possibly produce an error or warning if one of these was non-null but 360 // the other was null. 361 if (CurStrSection.empty() || CurStrOffsetSection.empty()) 362 return; 363 364 DenseMap<uint64_t, uint32_t> OffsetRemapping; 365 366 DataExtractor Data(CurStrSection, true, 0); 367 uint64_t LocalOffset = 0; 368 uint64_t PrevOffset = 0; 369 while (const char *S = Data.getCStr(&LocalOffset)) { 370 OffsetRemapping[PrevOffset] = 371 Strings.getOffset(S, LocalOffset - PrevOffset); 372 PrevOffset = LocalOffset; 373 } 374 375 Data = DataExtractor(CurStrOffsetSection, true, 0); 376 377 Out.switchSection(StrOffsetSection); 378 379 uint64_t HeaderSize = debugStrOffsetsHeaderSize(Data, Version); 380 uint64_t Offset = 0; 381 uint64_t Size = CurStrOffsetSection.size(); 382 // FIXME: This can be caused by bad input and should be handled as such. 383 assert(HeaderSize <= Size && "StrOffsetSection size is less than its header"); 384 // Copy the header to the output. 385 Out.emitBytes(Data.getBytes(&Offset, HeaderSize)); 386 while (Offset < Size) { 387 auto OldOffset = Data.getU32(&Offset); 388 auto NewOffset = OffsetRemapping[OldOffset]; 389 Out.emitIntValue(NewOffset, 4); 390 } 391 } 392 393 void writeIndexTable( 394 MCStreamer &Out, ArrayRef<unsigned> ContributionOffsets, 395 const MapVector<uint64_t, UnitIndexEntry> &IndexEntries, 396 uint32_t DWARFUnitIndex::Entry::SectionContribution::*Field) { 397 for (const auto &E : IndexEntries) 398 for (size_t I = 0; I != array_lengthof(E.second.Contributions); ++I) 399 if (ContributionOffsets[I]) 400 Out.emitIntValue(E.second.Contributions[I].*Field, 4); 401 } 402 403 void writeIndex(MCStreamer &Out, MCSection *Section, 404 ArrayRef<unsigned> ContributionOffsets, 405 const MapVector<uint64_t, UnitIndexEntry> &IndexEntries, 406 uint32_t IndexVersion) { 407 if (IndexEntries.empty()) 408 return; 409 410 unsigned Columns = 0; 411 for (auto &C : ContributionOffsets) 412 if (C) 413 ++Columns; 414 415 std::vector<unsigned> Buckets(NextPowerOf2(3 * IndexEntries.size() / 2)); 416 uint64_t Mask = Buckets.size() - 1; 417 size_t I = 0; 418 for (const auto &P : IndexEntries) { 419 auto S = P.first; 420 auto H = S & Mask; 421 auto HP = ((S >> 32) & Mask) | 1; 422 while (Buckets[H]) { 423 assert(S != IndexEntries.begin()[Buckets[H] - 1].first && 424 "Duplicate unit"); 425 H = (H + HP) & Mask; 426 } 427 Buckets[H] = I + 1; 428 ++I; 429 } 430 431 Out.switchSection(Section); 432 Out.emitIntValue(IndexVersion, 4); // Version 433 Out.emitIntValue(Columns, 4); // Columns 434 Out.emitIntValue(IndexEntries.size(), 4); // Num Units 435 Out.emitIntValue(Buckets.size(), 4); // Num Buckets 436 437 // Write the signatures. 438 for (const auto &I : Buckets) 439 Out.emitIntValue(I ? IndexEntries.begin()[I - 1].first : 0, 8); 440 441 // Write the indexes. 442 for (const auto &I : Buckets) 443 Out.emitIntValue(I, 4); 444 445 // Write the column headers (which sections will appear in the table) 446 for (size_t I = 0; I != ContributionOffsets.size(); ++I) 447 if (ContributionOffsets[I]) 448 Out.emitIntValue(getOnDiskSectionId(I), 4); 449 450 // Write the offsets. 451 writeIndexTable(Out, ContributionOffsets, IndexEntries, 452 &DWARFUnitIndex::Entry::SectionContribution::Offset); 453 454 // Write the lengths. 455 writeIndexTable(Out, ContributionOffsets, IndexEntries, 456 &DWARFUnitIndex::Entry::SectionContribution::Length); 457 } 458 459 Error buildDuplicateError(const std::pair<uint64_t, UnitIndexEntry> &PrevE, 460 const CompileUnitIdentifiers &ID, StringRef DWPName) { 461 return make_error<DWPError>( 462 std::string("duplicate DWO ID (") + utohexstr(PrevE.first) + ") in " + 463 buildDWODescription(PrevE.second.Name, PrevE.second.DWPName, 464 PrevE.second.DWOName) + 465 " and " + buildDWODescription(ID.Name, DWPName, ID.DWOName)); 466 } 467 468 Error handleSection( 469 const StringMap<std::pair<MCSection *, DWARFSectionKind>> &KnownSections, 470 const MCSection *StrSection, const MCSection *StrOffsetSection, 471 const MCSection *TypesSection, const MCSection *CUIndexSection, 472 const MCSection *TUIndexSection, const MCSection *InfoSection, 473 const SectionRef &Section, MCStreamer &Out, 474 std::deque<SmallString<32>> &UncompressedSections, 475 uint32_t (&ContributionOffsets)[8], UnitIndexEntry &CurEntry, 476 StringRef &CurStrSection, StringRef &CurStrOffsetSection, 477 std::vector<StringRef> &CurTypesSection, 478 std::vector<StringRef> &CurInfoSection, StringRef &AbbrevSection, 479 StringRef &CurCUIndexSection, StringRef &CurTUIndexSection, 480 std::vector<std::pair<DWARFSectionKind, uint32_t>> &SectionLength) { 481 if (Section.isBSS()) 482 return Error::success(); 483 484 if (Section.isVirtual()) 485 return Error::success(); 486 487 Expected<StringRef> NameOrErr = Section.getName(); 488 if (!NameOrErr) 489 return NameOrErr.takeError(); 490 StringRef Name = *NameOrErr; 491 492 Expected<StringRef> ContentsOrErr = Section.getContents(); 493 if (!ContentsOrErr) 494 return ContentsOrErr.takeError(); 495 StringRef Contents = *ContentsOrErr; 496 497 if (auto Err = handleCompressedSection(UncompressedSections, Name, Contents)) 498 return Err; 499 500 Name = Name.substr(Name.find_first_not_of("._")); 501 502 auto SectionPair = KnownSections.find(Name); 503 if (SectionPair == KnownSections.end()) 504 return Error::success(); 505 506 if (DWARFSectionKind Kind = SectionPair->second.second) { 507 if (Kind != DW_SECT_EXT_TYPES && Kind != DW_SECT_INFO) { 508 SectionLength.push_back(std::make_pair(Kind, Contents.size())); 509 } 510 511 if (Kind == DW_SECT_ABBREV) { 512 AbbrevSection = Contents; 513 } 514 } 515 516 MCSection *OutSection = SectionPair->second.first; 517 if (OutSection == StrOffsetSection) 518 CurStrOffsetSection = Contents; 519 else if (OutSection == StrSection) 520 CurStrSection = Contents; 521 else if (OutSection == TypesSection) 522 CurTypesSection.push_back(Contents); 523 else if (OutSection == CUIndexSection) 524 CurCUIndexSection = Contents; 525 else if (OutSection == TUIndexSection) 526 CurTUIndexSection = Contents; 527 else if (OutSection == InfoSection) 528 CurInfoSection.push_back(Contents); 529 else { 530 Out.switchSection(OutSection); 531 Out.emitBytes(Contents); 532 } 533 return Error::success(); 534 } 535 536 Error write(MCStreamer &Out, ArrayRef<std::string> Inputs) { 537 const auto &MCOFI = *Out.getContext().getObjectFileInfo(); 538 MCSection *const StrSection = MCOFI.getDwarfStrDWOSection(); 539 MCSection *const StrOffsetSection = MCOFI.getDwarfStrOffDWOSection(); 540 MCSection *const TypesSection = MCOFI.getDwarfTypesDWOSection(); 541 MCSection *const CUIndexSection = MCOFI.getDwarfCUIndexSection(); 542 MCSection *const TUIndexSection = MCOFI.getDwarfTUIndexSection(); 543 MCSection *const InfoSection = MCOFI.getDwarfInfoDWOSection(); 544 const StringMap<std::pair<MCSection *, DWARFSectionKind>> KnownSections = { 545 {"debug_info.dwo", {InfoSection, DW_SECT_INFO}}, 546 {"debug_types.dwo", {MCOFI.getDwarfTypesDWOSection(), DW_SECT_EXT_TYPES}}, 547 {"debug_str_offsets.dwo", {StrOffsetSection, DW_SECT_STR_OFFSETS}}, 548 {"debug_str.dwo", {StrSection, static_cast<DWARFSectionKind>(0)}}, 549 {"debug_loc.dwo", {MCOFI.getDwarfLocDWOSection(), DW_SECT_EXT_LOC}}, 550 {"debug_line.dwo", {MCOFI.getDwarfLineDWOSection(), DW_SECT_LINE}}, 551 {"debug_macro.dwo", {MCOFI.getDwarfMacroDWOSection(), DW_SECT_MACRO}}, 552 {"debug_abbrev.dwo", {MCOFI.getDwarfAbbrevDWOSection(), DW_SECT_ABBREV}}, 553 {"debug_loclists.dwo", 554 {MCOFI.getDwarfLoclistsDWOSection(), DW_SECT_LOCLISTS}}, 555 {"debug_rnglists.dwo", 556 {MCOFI.getDwarfRnglistsDWOSection(), DW_SECT_RNGLISTS}}, 557 {"debug_cu_index", {CUIndexSection, static_cast<DWARFSectionKind>(0)}}, 558 {"debug_tu_index", {TUIndexSection, static_cast<DWARFSectionKind>(0)}}}; 559 560 MapVector<uint64_t, UnitIndexEntry> IndexEntries; 561 MapVector<uint64_t, UnitIndexEntry> TypeIndexEntries; 562 563 uint32_t ContributionOffsets[8] = {}; 564 uint16_t Version = 0; 565 uint32_t IndexVersion = 0; 566 567 DWPStringPool Strings(Out, StrSection); 568 569 SmallVector<OwningBinary<object::ObjectFile>, 128> Objects; 570 Objects.reserve(Inputs.size()); 571 572 std::deque<SmallString<32>> UncompressedSections; 573 574 for (const auto &Input : Inputs) { 575 auto ErrOrObj = object::ObjectFile::createObjectFile(Input); 576 if (!ErrOrObj) 577 return ErrOrObj.takeError(); 578 579 auto &Obj = *ErrOrObj->getBinary(); 580 Objects.push_back(std::move(*ErrOrObj)); 581 582 UnitIndexEntry CurEntry = {}; 583 584 StringRef CurStrSection; 585 StringRef CurStrOffsetSection; 586 std::vector<StringRef> CurTypesSection; 587 std::vector<StringRef> CurInfoSection; 588 StringRef AbbrevSection; 589 StringRef CurCUIndexSection; 590 StringRef CurTUIndexSection; 591 592 // This maps each section contained in this file to its length. 593 // This information is later on used to calculate the contributions, 594 // i.e. offset and length, of each compile/type unit to a section. 595 std::vector<std::pair<DWARFSectionKind, uint32_t>> SectionLength; 596 597 for (const auto &Section : Obj.sections()) 598 if (auto Err = handleSection( 599 KnownSections, StrSection, StrOffsetSection, TypesSection, 600 CUIndexSection, TUIndexSection, InfoSection, Section, Out, 601 UncompressedSections, ContributionOffsets, CurEntry, 602 CurStrSection, CurStrOffsetSection, CurTypesSection, 603 CurInfoSection, AbbrevSection, CurCUIndexSection, 604 CurTUIndexSection, SectionLength)) 605 return Err; 606 607 if (CurInfoSection.empty()) 608 continue; 609 610 Expected<InfoSectionUnitHeader> HeaderOrErr = 611 parseInfoSectionUnitHeader(CurInfoSection.front()); 612 if (!HeaderOrErr) 613 return HeaderOrErr.takeError(); 614 InfoSectionUnitHeader &Header = *HeaderOrErr; 615 616 if (Version == 0) { 617 Version = Header.Version; 618 IndexVersion = Version < 5 ? 2 : 5; 619 } else if (Version != Header.Version) { 620 return make_error<DWPError>("incompatible DWARF compile unit versions."); 621 } 622 623 writeStringsAndOffsets(Out, Strings, StrOffsetSection, CurStrSection, 624 CurStrOffsetSection, Header.Version); 625 626 for (auto Pair : SectionLength) { 627 auto Index = getContributionIndex(Pair.first, IndexVersion); 628 CurEntry.Contributions[Index].Offset = ContributionOffsets[Index]; 629 ContributionOffsets[Index] += 630 (CurEntry.Contributions[Index].Length = Pair.second); 631 } 632 633 uint32_t &InfoSectionOffset = 634 ContributionOffsets[getContributionIndex(DW_SECT_INFO, IndexVersion)]; 635 if (CurCUIndexSection.empty()) { 636 bool FoundCUUnit = false; 637 Out.switchSection(InfoSection); 638 for (StringRef Info : CurInfoSection) { 639 uint64_t UnitOffset = 0; 640 while (Info.size() > UnitOffset) { 641 Expected<InfoSectionUnitHeader> HeaderOrError = 642 parseInfoSectionUnitHeader(Info.substr(UnitOffset, Info.size())); 643 if (!HeaderOrError) 644 return HeaderOrError.takeError(); 645 InfoSectionUnitHeader &Header = *HeaderOrError; 646 647 UnitIndexEntry Entry = CurEntry; 648 auto &C = Entry.Contributions[getContributionIndex(DW_SECT_INFO, 649 IndexVersion)]; 650 C.Offset = InfoSectionOffset; 651 C.Length = Header.Length + 4; 652 UnitOffset += C.Length; 653 if (Header.Version < 5 || 654 Header.UnitType == dwarf::DW_UT_split_compile) { 655 Expected<CompileUnitIdentifiers> EID = 656 getCUIdentifiers(Header, AbbrevSection, 657 Info.substr(UnitOffset - C.Length, C.Length), 658 CurStrOffsetSection, CurStrSection); 659 660 if (!EID) 661 return createFileError(Input, EID.takeError()); 662 const auto &ID = *EID; 663 auto P = IndexEntries.insert(std::make_pair(ID.Signature, Entry)); 664 if (!P.second) 665 return buildDuplicateError(*P.first, ID, ""); 666 P.first->second.Name = ID.Name; 667 P.first->second.DWOName = ID.DWOName; 668 669 FoundCUUnit = true; 670 } else if (Header.UnitType == dwarf::DW_UT_split_type) { 671 auto P = TypeIndexEntries.insert( 672 std::make_pair(*Header.Signature, Entry)); 673 if (!P.second) 674 continue; 675 } 676 Out.emitBytes(Info.substr(UnitOffset - C.Length, C.Length)); 677 InfoSectionOffset += C.Length; 678 } 679 } 680 681 if (!FoundCUUnit) 682 return make_error<DWPError>("no compile unit found in file: " + Input); 683 684 if (IndexVersion == 2) { 685 // Add types from the .debug_types section from DWARF < 5. 686 addAllTypesFromTypesSection( 687 Out, TypeIndexEntries, TypesSection, CurTypesSection, CurEntry, 688 ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES, 2)]); 689 } 690 continue; 691 } 692 693 if (CurInfoSection.size() != 1) 694 return make_error<DWPError>("expected exactly one occurrence of a debug " 695 "info section in a .dwp file"); 696 StringRef DwpSingleInfoSection = CurInfoSection.front(); 697 698 DWARFUnitIndex CUIndex(DW_SECT_INFO); 699 DataExtractor CUIndexData(CurCUIndexSection, Obj.isLittleEndian(), 0); 700 if (!CUIndex.parse(CUIndexData)) 701 return make_error<DWPError>("failed to parse cu_index"); 702 if (CUIndex.getVersion() != IndexVersion) 703 return make_error<DWPError>("incompatible cu_index versions, found " + 704 utostr(CUIndex.getVersion()) + 705 " and expecting " + utostr(IndexVersion)); 706 707 Out.switchSection(InfoSection); 708 for (const DWARFUnitIndex::Entry &E : CUIndex.getRows()) { 709 auto *I = E.getContributions(); 710 if (!I) 711 continue; 712 auto P = IndexEntries.insert(std::make_pair(E.getSignature(), CurEntry)); 713 StringRef CUInfoSection = 714 getSubsection(DwpSingleInfoSection, E, DW_SECT_INFO); 715 Expected<InfoSectionUnitHeader> HeaderOrError = 716 parseInfoSectionUnitHeader(CUInfoSection); 717 if (!HeaderOrError) 718 return HeaderOrError.takeError(); 719 InfoSectionUnitHeader &Header = *HeaderOrError; 720 721 Expected<CompileUnitIdentifiers> EID = getCUIdentifiers( 722 Header, getSubsection(AbbrevSection, E, DW_SECT_ABBREV), 723 CUInfoSection, 724 getSubsection(CurStrOffsetSection, E, DW_SECT_STR_OFFSETS), 725 CurStrSection); 726 if (!EID) 727 return createFileError(Input, EID.takeError()); 728 const auto &ID = *EID; 729 if (!P.second) 730 return buildDuplicateError(*P.first, ID, Input); 731 auto &NewEntry = P.first->second; 732 NewEntry.Name = ID.Name; 733 NewEntry.DWOName = ID.DWOName; 734 NewEntry.DWPName = Input; 735 for (auto Kind : CUIndex.getColumnKinds()) { 736 if (!isSupportedSectionKind(Kind)) 737 continue; 738 auto &C = 739 NewEntry.Contributions[getContributionIndex(Kind, IndexVersion)]; 740 C.Offset += I->Offset; 741 C.Length = I->Length; 742 ++I; 743 } 744 unsigned Index = getContributionIndex(DW_SECT_INFO, IndexVersion); 745 auto &C = NewEntry.Contributions[Index]; 746 Out.emitBytes(CUInfoSection); 747 C.Offset = InfoSectionOffset; 748 InfoSectionOffset += C.Length; 749 } 750 751 if (!CurTUIndexSection.empty()) { 752 llvm::DWARFSectionKind TUSectionKind; 753 MCSection *OutSection; 754 StringRef TypeInputSection; 755 // Write type units into debug info section for DWARFv5. 756 if (Version >= 5) { 757 TUSectionKind = DW_SECT_INFO; 758 OutSection = InfoSection; 759 TypeInputSection = DwpSingleInfoSection; 760 } else { 761 // Write type units into debug types section for DWARF < 5. 762 if (CurTypesSection.size() != 1) 763 return make_error<DWPError>( 764 "multiple type unit sections in .dwp file"); 765 766 TUSectionKind = DW_SECT_EXT_TYPES; 767 OutSection = TypesSection; 768 TypeInputSection = CurTypesSection.front(); 769 } 770 771 DWARFUnitIndex TUIndex(TUSectionKind); 772 DataExtractor TUIndexData(CurTUIndexSection, Obj.isLittleEndian(), 0); 773 if (!TUIndex.parse(TUIndexData)) 774 return make_error<DWPError>("failed to parse tu_index"); 775 if (TUIndex.getVersion() != IndexVersion) 776 return make_error<DWPError>("incompatible tu_index versions, found " + 777 utostr(TUIndex.getVersion()) + 778 " and expecting " + utostr(IndexVersion)); 779 780 unsigned TypesContributionIndex = 781 getContributionIndex(TUSectionKind, IndexVersion); 782 addAllTypesFromDWP(Out, TypeIndexEntries, TUIndex, OutSection, 783 TypeInputSection, CurEntry, 784 ContributionOffsets[TypesContributionIndex], 785 TypesContributionIndex); 786 } 787 } 788 789 if (Version < 5) { 790 // Lie about there being no info contributions so the TU index only includes 791 // the type unit contribution for DWARF < 5. In DWARFv5 the TU index has a 792 // contribution to the info section, so we do not want to lie about it. 793 ContributionOffsets[0] = 0; 794 } 795 writeIndex(Out, MCOFI.getDwarfTUIndexSection(), ContributionOffsets, 796 TypeIndexEntries, IndexVersion); 797 798 if (Version < 5) { 799 // Lie about the type contribution for DWARF < 5. In DWARFv5 the type 800 // section does not exist, so no need to do anything about this. 801 ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES, 2)] = 0; 802 // Unlie about the info contribution 803 ContributionOffsets[0] = 1; 804 } 805 806 writeIndex(Out, MCOFI.getDwarfCUIndexSection(), ContributionOffsets, 807 IndexEntries, IndexVersion); 808 809 return Error::success(); 810 } 811 } // namespace llvm 812