1006 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8//9// A utility for merging DWARF 5 Split DWARF .dwo files into .dwp (DWARF10// package files).11//12//===----------------------------------------------------------------------===//13#include "llvm/DWP/DWP.h"14#include "llvm/ADT/Twine.h"15#include "llvm/DWP/DWPError.h"16#include "llvm/MC/MCContext.h"17#include "llvm/MC/MCObjectFileInfo.h"18#include "llvm/MC/MCTargetOptionsCommandFlags.h"19#include "llvm/Object/Decompressor.h"20#include "llvm/Object/ELFObjectFile.h"21#include <limits>22 23using namespace llvm;24using namespace llvm::object;25 26static mc::RegisterMCTargetOptionsFlags MCTargetOptionsFlags;27 28// Returns the size of debug_str_offsets section headers in bytes.29static uint64_t debugStrOffsetsHeaderSize(DataExtractor StrOffsetsData,30 uint16_t DwarfVersion) {31 if (DwarfVersion <= 4)32 return 0; // There is no header before dwarf 5.33 uint64_t Offset = 0;34 uint64_t Length = StrOffsetsData.getU32(&Offset);35 if (Length == llvm::dwarf::DW_LENGTH_DWARF64)36 return 16; // unit length: 12 bytes, version: 2 bytes, padding: 2 bytes.37 return 8; // unit length: 4 bytes, version: 2 bytes, padding: 2 bytes.38}39 40static uint64_t getCUAbbrev(StringRef Abbrev, uint64_t AbbrCode) {41 uint64_t Offset = 0;42 DataExtractor AbbrevData(Abbrev, true, 0);43 while (AbbrevData.getULEB128(&Offset) != AbbrCode) {44 // Tag45 AbbrevData.getULEB128(&Offset);46 // DW_CHILDREN47 AbbrevData.getU8(&Offset);48 // Attributes49 while (AbbrevData.getULEB128(&Offset) | AbbrevData.getULEB128(&Offset))50 ;51 }52 return Offset;53}54 55static Expected<const char *>56getIndexedString(dwarf::Form Form, DataExtractor InfoData, uint64_t &InfoOffset,57 StringRef StrOffsets, StringRef Str, uint16_t Version) {58 if (Form == dwarf::DW_FORM_string)59 return InfoData.getCStr(&InfoOffset);60 uint64_t StrIndex;61 switch (Form) {62 case dwarf::DW_FORM_strx1:63 StrIndex = InfoData.getU8(&InfoOffset);64 break;65 case dwarf::DW_FORM_strx2:66 StrIndex = InfoData.getU16(&InfoOffset);67 break;68 case dwarf::DW_FORM_strx3:69 StrIndex = InfoData.getU24(&InfoOffset);70 break;71 case dwarf::DW_FORM_strx4:72 StrIndex = InfoData.getU32(&InfoOffset);73 break;74 case dwarf::DW_FORM_strx:75 case dwarf::DW_FORM_GNU_str_index:76 StrIndex = InfoData.getULEB128(&InfoOffset);77 break;78 default:79 return make_error<DWPError>(80 "string field must be encoded with one of the following: "81 "DW_FORM_string, DW_FORM_strx, DW_FORM_strx1, DW_FORM_strx2, "82 "DW_FORM_strx3, DW_FORM_strx4, or DW_FORM_GNU_str_index.");83 }84 DataExtractor StrOffsetsData(StrOffsets, true, 0);85 uint64_t StrOffsetsOffset = 4 * StrIndex;86 StrOffsetsOffset += debugStrOffsetsHeaderSize(StrOffsetsData, Version);87 88 uint64_t StrOffset = StrOffsetsData.getU32(&StrOffsetsOffset);89 DataExtractor StrData(Str, true, 0);90 return StrData.getCStr(&StrOffset);91}92 93static Expected<CompileUnitIdentifiers>94getCUIdentifiers(InfoSectionUnitHeader &Header, StringRef Abbrev,95 StringRef Info, StringRef StrOffsets, StringRef Str) {96 DataExtractor InfoData(Info, true, 0);97 uint64_t Offset = Header.HeaderSize;98 if (Header.Version >= 5 && Header.UnitType != dwarf::DW_UT_split_compile)99 return make_error<DWPError>(100 std::string("unit type DW_UT_split_compile type not found in "101 "debug_info header. Unexpected unit type 0x" +102 utostr(Header.UnitType) + " found"));103 104 CompileUnitIdentifiers ID;105 106 uint32_t AbbrCode = InfoData.getULEB128(&Offset);107 DataExtractor AbbrevData(Abbrev, true, 0);108 uint64_t AbbrevOffset = getCUAbbrev(Abbrev, AbbrCode);109 auto Tag = static_cast<dwarf::Tag>(AbbrevData.getULEB128(&AbbrevOffset));110 if (Tag != dwarf::DW_TAG_compile_unit)111 return make_error<DWPError>("top level DIE is not a compile unit");112 // DW_CHILDREN113 AbbrevData.getU8(&AbbrevOffset);114 uint32_t Name;115 dwarf::Form Form;116 while ((Name = AbbrevData.getULEB128(&AbbrevOffset)) |117 (Form = static_cast<dwarf::Form>(118 AbbrevData.getULEB128(&AbbrevOffset))) &&119 (Name != 0 || Form != 0)) {120 switch (Name) {121 case dwarf::DW_AT_name: {122 Expected<const char *> EName = getIndexedString(123 Form, InfoData, Offset, StrOffsets, Str, Header.Version);124 if (!EName)125 return EName.takeError();126 ID.Name = *EName;127 break;128 }129 case dwarf::DW_AT_GNU_dwo_name:130 case dwarf::DW_AT_dwo_name: {131 Expected<const char *> EName = getIndexedString(132 Form, InfoData, Offset, StrOffsets, Str, Header.Version);133 if (!EName)134 return EName.takeError();135 ID.DWOName = *EName;136 break;137 }138 case dwarf::DW_AT_GNU_dwo_id:139 Header.Signature = InfoData.getU64(&Offset);140 break;141 default:142 DWARFFormValue::skipValue(143 Form, InfoData, &Offset,144 dwarf::FormParams({Header.Version, Header.AddrSize, Header.Format}));145 }146 }147 if (!Header.Signature)148 return make_error<DWPError>("compile unit missing dwo_id");149 ID.Signature = *Header.Signature;150 return ID;151}152 153static bool isSupportedSectionKind(DWARFSectionKind Kind) {154 return Kind != DW_SECT_EXT_unknown;155}156 157// Convert an internal section identifier into the index to use with158// UnitIndexEntry::Contributions.159static unsigned getContributionIndex(DWARFSectionKind Kind,160 uint32_t IndexVersion) {161 assert(serializeSectionKind(Kind, IndexVersion) >= DW_SECT_INFO);162 return serializeSectionKind(Kind, IndexVersion) - DW_SECT_INFO;163}164 165// Convert a UnitIndexEntry::Contributions index to the corresponding on-disk166// value of the section identifier.167static unsigned getOnDiskSectionId(unsigned Index) {168 return Index + DW_SECT_INFO;169}170 171static StringRef getSubsection(StringRef Section,172 const DWARFUnitIndex::Entry &Entry,173 DWARFSectionKind Kind) {174 const auto *Off = Entry.getContribution(Kind);175 if (!Off)176 return StringRef();177 return Section.substr(Off->getOffset(), Off->getLength());178}179 180static Error sectionOverflowErrorOrWarning(uint32_t PrevOffset,181 uint32_t OverflowedOffset,182 StringRef SectionName,183 OnCuIndexOverflow OverflowOptValue,184 bool &AnySectionOverflow) {185 std::string Msg =186 (SectionName +187 Twine(" Section Contribution Offset overflow 4G. Previous Offset ") +188 Twine(PrevOffset) + Twine(", After overflow offset ") +189 Twine(OverflowedOffset) + Twine("."))190 .str();191 if (OverflowOptValue == OnCuIndexOverflow::Continue) {192 WithColor::defaultWarningHandler(make_error<DWPError>(Msg));193 return Error::success();194 } else if (OverflowOptValue == OnCuIndexOverflow::SoftStop) {195 AnySectionOverflow = true;196 WithColor::defaultWarningHandler(make_error<DWPError>(Msg));197 return Error::success();198 }199 return make_error<DWPError>(Msg);200}201 202static Error addAllTypesFromDWP(203 MCStreamer &Out, MapVector<uint64_t, UnitIndexEntry> &TypeIndexEntries,204 const DWARFUnitIndex &TUIndex, MCSection *OutputTypes, StringRef Types,205 const UnitIndexEntry &TUEntry, uint32_t &TypesOffset,206 unsigned TypesContributionIndex, OnCuIndexOverflow OverflowOptValue,207 bool &AnySectionOverflow) {208 Out.switchSection(OutputTypes);209 for (const DWARFUnitIndex::Entry &E : TUIndex.getRows()) {210 auto *I = E.getContributions();211 if (!I)212 continue;213 auto P = TypeIndexEntries.insert(std::make_pair(E.getSignature(), TUEntry));214 if (!P.second)215 continue;216 auto &Entry = P.first->second;217 // Zero out the debug_info contribution218 Entry.Contributions[0] = {};219 for (auto Kind : TUIndex.getColumnKinds()) {220 if (!isSupportedSectionKind(Kind))221 continue;222 auto &C =223 Entry.Contributions[getContributionIndex(Kind, TUIndex.getVersion())];224 C.setOffset(C.getOffset() + I->getOffset());225 C.setLength(I->getLength());226 ++I;227 }228 auto &C = Entry.Contributions[TypesContributionIndex];229 Out.emitBytes(Types.substr(230 C.getOffset() -231 TUEntry.Contributions[TypesContributionIndex].getOffset(),232 C.getLength()));233 C.setOffset(TypesOffset);234 uint32_t OldOffset = TypesOffset;235 static_assert(sizeof(OldOffset) == sizeof(TypesOffset));236 TypesOffset += C.getLength();237 if (OldOffset > TypesOffset) {238 if (Error Err = sectionOverflowErrorOrWarning(OldOffset, TypesOffset,239 "Types", OverflowOptValue,240 AnySectionOverflow))241 return Err;242 if (AnySectionOverflow) {243 TypesOffset = OldOffset;244 return Error::success();245 }246 }247 }248 return Error::success();249}250 251static Error addAllTypesFromTypesSection(252 MCStreamer &Out, MapVector<uint64_t, UnitIndexEntry> &TypeIndexEntries,253 MCSection *OutputTypes, const std::vector<StringRef> &TypesSections,254 const UnitIndexEntry &CUEntry, uint32_t &TypesOffset,255 OnCuIndexOverflow OverflowOptValue, bool &AnySectionOverflow) {256 for (StringRef Types : TypesSections) {257 Out.switchSection(OutputTypes);258 uint64_t Offset = 0;259 DataExtractor Data(Types, true, 0);260 while (Data.isValidOffset(Offset)) {261 UnitIndexEntry Entry = CUEntry;262 // Zero out the debug_info contribution263 Entry.Contributions[0] = {};264 auto &C = Entry.Contributions[getContributionIndex(DW_SECT_EXT_TYPES, 2)];265 C.setOffset(TypesOffset);266 auto PrevOffset = Offset;267 // Length of the unit, including the 4 byte length field.268 C.setLength(Data.getU32(&Offset) + 4);269 270 Data.getU16(&Offset); // Version271 Data.getU32(&Offset); // Abbrev offset272 Data.getU8(&Offset); // Address size273 auto Signature = Data.getU64(&Offset);274 Offset = PrevOffset + C.getLength32();275 276 auto P = TypeIndexEntries.insert(std::make_pair(Signature, Entry));277 if (!P.second)278 continue;279 280 Out.emitBytes(Types.substr(PrevOffset, C.getLength32()));281 uint32_t OldOffset = TypesOffset;282 TypesOffset += C.getLength32();283 if (OldOffset > TypesOffset) {284 if (Error Err = sectionOverflowErrorOrWarning(OldOffset, TypesOffset,285 "Types", OverflowOptValue,286 AnySectionOverflow))287 return Err;288 if (AnySectionOverflow) {289 TypesOffset = OldOffset;290 return Error::success();291 }292 }293 }294 }295 return Error::success();296}297 298static std::string buildDWODescription(StringRef Name, StringRef DWPName,299 StringRef DWOName) {300 std::string Text = "\'";301 Text += Name;302 Text += '\'';303 bool HasDWO = !DWOName.empty();304 bool HasDWP = !DWPName.empty();305 if (HasDWO || HasDWP) {306 Text += " (from ";307 if (HasDWO) {308 Text += '\'';309 Text += DWOName;310 Text += '\'';311 }312 if (HasDWO && HasDWP)313 Text += " in ";314 if (!DWPName.empty()) {315 Text += '\'';316 Text += DWPName;317 Text += '\'';318 }319 Text += ")";320 }321 return Text;322}323 324static Error createError(StringRef Name, Error E) {325 return make_error<DWPError>(326 ("failure while decompressing compressed section: '" + Name + "', " +327 llvm::toString(std::move(E)))328 .str());329}330 331static Error332handleCompressedSection(std::deque<SmallString<32>> &UncompressedSections,333 SectionRef Sec, StringRef Name, StringRef &Contents) {334 auto *Obj = dyn_cast<ELFObjectFileBase>(Sec.getObject());335 if (!Obj ||336 !(static_cast<ELFSectionRef>(Sec).getFlags() & ELF::SHF_COMPRESSED))337 return Error::success();338 bool IsLE = isa<object::ELF32LEObjectFile>(Obj) ||339 isa<object::ELF64LEObjectFile>(Obj);340 bool Is64 = isa<object::ELF64LEObjectFile>(Obj) ||341 isa<object::ELF64BEObjectFile>(Obj);342 Expected<Decompressor> Dec = Decompressor::create(Name, Contents, IsLE, Is64);343 if (!Dec)344 return createError(Name, Dec.takeError());345 346 UncompressedSections.emplace_back();347 if (Error E = Dec->resizeAndDecompress(UncompressedSections.back()))348 return createError(Name, std::move(E));349 350 Contents = UncompressedSections.back();351 return Error::success();352}353 354namespace llvm {355// Parse and return the header of an info section compile/type unit.356Expected<InfoSectionUnitHeader> parseInfoSectionUnitHeader(StringRef Info) {357 InfoSectionUnitHeader Header;358 Error Err = Error::success();359 uint64_t Offset = 0;360 DWARFDataExtractor InfoData(Info, true, 0);361 std::tie(Header.Length, Header.Format) =362 InfoData.getInitialLength(&Offset, &Err);363 if (Err)364 return make_error<DWPError>("cannot parse compile unit length: " +365 llvm::toString(std::move(Err)));366 367 if (!InfoData.isValidOffset(Offset + (Header.Length - 1))) {368 return make_error<DWPError>(369 "compile unit exceeds .debug_info section range: " +370 utostr(Offset + Header.Length) + " >= " + utostr(InfoData.size()));371 }372 373 Header.Version = InfoData.getU16(&Offset, &Err);374 if (Err)375 return make_error<DWPError>("cannot parse compile unit version: " +376 llvm::toString(std::move(Err)));377 378 uint64_t MinHeaderLength;379 if (Header.Version >= 5) {380 // Size: Version (2), UnitType (1), AddrSize (1), DebugAbbrevOffset (4),381 // Signature (8)382 MinHeaderLength = 16;383 } else {384 // Size: Version (2), DebugAbbrevOffset (4), AddrSize (1)385 MinHeaderLength = 7;386 }387 if (Header.Length < MinHeaderLength) {388 return make_error<DWPError>("unit length is too small: expected at least " +389 utostr(MinHeaderLength) + " got " +390 utostr(Header.Length) + ".");391 }392 if (Header.Version >= 5) {393 Header.UnitType = InfoData.getU8(&Offset);394 Header.AddrSize = InfoData.getU8(&Offset);395 Header.DebugAbbrevOffset = InfoData.getU32(&Offset);396 Header.Signature = InfoData.getU64(&Offset);397 if (Header.UnitType == dwarf::DW_UT_split_type) {398 // Type offset.399 MinHeaderLength += 4;400 if (Header.Length < MinHeaderLength)401 return make_error<DWPError>("type unit is missing type offset");402 InfoData.getU32(&Offset);403 }404 } else {405 // Note that, address_size and debug_abbrev_offset fields have switched406 // places between dwarf version 4 and 5.407 Header.DebugAbbrevOffset = InfoData.getU32(&Offset);408 Header.AddrSize = InfoData.getU8(&Offset);409 }410 411 Header.HeaderSize = Offset;412 return Header;413}414 415static void writeNewOffsetsTo(MCStreamer &Out, DataExtractor &Data,416 DenseMap<uint64_t, uint64_t> &OffsetRemapping,417 uint64_t &Offset, const uint64_t Size,418 uint32_t OldOffsetSize, uint32_t NewOffsetSize) {419 // Create a mask so we don't trigger a emitIntValue() assert below if the420 // NewOffset is over 4GB.421 const uint64_t NewOffsetMask = NewOffsetSize == 8 ? UINT64_MAX : UINT32_MAX;422 while (Offset < Size) {423 const uint64_t OldOffset = Data.getUnsigned(&Offset, OldOffsetSize);424 const uint64_t NewOffset = OffsetRemapping[OldOffset];425 // Truncate the string offset like the old llvm-dwp would have if we aren't426 // promoting the .debug_str_offsets to DWARF64.427 Out.emitIntValue(NewOffset & NewOffsetMask, NewOffsetSize);428 }429}430 431void writeStringsAndOffsets(432 MCStreamer &Out, DWPStringPool &Strings, MCSection *StrOffsetSection,433 StringRef CurStrSection, StringRef CurStrOffsetSection, uint16_t Version,434 SectionLengths &SectionLength,435 const Dwarf64StrOffsetsPromotion StrOffsetsOptValue) {436 // Could possibly produce an error or warning if one of these was non-null but437 // the other was null.438 if (CurStrSection.empty() || CurStrOffsetSection.empty())439 return;440 441 DenseMap<uint64_t, uint64_t> OffsetRemapping;442 443 DataExtractor Data(CurStrSection, true, 0);444 uint64_t LocalOffset = 0;445 uint64_t PrevOffset = 0;446 447 // Keep track if any new string offsets exceed UINT32_MAX. If any do, we can448 // emit a DWARF64 .debug_str_offsets table for this compile unit. If the449 // \a StrOffsetsOptValue argument is Dwarf64StrOffsetsPromotion::Always, then450 // force the emission of DWARF64 .debug_str_offsets for testing.451 uint32_t OldOffsetSize = 4;452 uint32_t NewOffsetSize =453 StrOffsetsOptValue == Dwarf64StrOffsetsPromotion::Always ? 8 : 4;454 while (const char *S = Data.getCStr(&LocalOffset)) {455 uint64_t NewOffset = Strings.getOffset(S, LocalOffset - PrevOffset);456 OffsetRemapping[PrevOffset] = NewOffset;457 // Only promote the .debug_str_offsets to DWARF64 if our setting allows it.458 if (StrOffsetsOptValue != Dwarf64StrOffsetsPromotion::Disabled &&459 NewOffset > UINT32_MAX) {460 NewOffsetSize = 8;461 }462 PrevOffset = LocalOffset;463 }464 465 Data = DataExtractor(CurStrOffsetSection, true, 0);466 467 Out.switchSection(StrOffsetSection);468 469 uint64_t Offset = 0;470 uint64_t Size = CurStrOffsetSection.size();471 if (Version > 4) {472 while (Offset < Size) {473 const uint64_t HeaderSize = debugStrOffsetsHeaderSize(Data, Version);474 assert(HeaderSize <= Size - Offset &&475 "StrOffsetSection size is less than its header");476 477 uint64_t ContributionEnd = 0;478 uint64_t ContributionSize = 0;479 uint64_t HeaderLengthOffset = Offset;480 if (HeaderSize == 8) {481 ContributionSize = Data.getU32(&HeaderLengthOffset);482 } else if (HeaderSize == 16) {483 OldOffsetSize = 8;484 HeaderLengthOffset += 4; // skip the dwarf64 marker485 ContributionSize = Data.getU64(&HeaderLengthOffset);486 }487 ContributionEnd = ContributionSize + HeaderLengthOffset;488 489 StringRef HeaderBytes = Data.getBytes(&Offset, HeaderSize);490 if (OldOffsetSize == 4 && NewOffsetSize == 8) {491 // We had a DWARF32 .debug_str_offsets header, but we need to emit492 // some string offsets that require 64 bit offsets on the .debug_str493 // section. Emit the .debug_str_offsets header in DWARF64 format so we494 // can emit string offsets that exceed UINT32_MAX without truncating495 // the string offset.496 497 // 2 bytes for DWARF version, 2 bytes pad.498 const uint64_t VersionPadSize = 4;499 const uint64_t NewLength =500 (ContributionSize - VersionPadSize) * 2 + VersionPadSize;501 // Emit the DWARF64 length that starts with a 4 byte DW_LENGTH_DWARF64502 // value followed by the 8 byte updated length.503 Out.emitIntValue(llvm::dwarf::DW_LENGTH_DWARF64, 4);504 Out.emitIntValue(NewLength, 8);505 // Emit DWARF version as a 2 byte integer.506 Out.emitIntValue(Version, 2);507 // Emit 2 bytes of padding.508 Out.emitIntValue(0, 2);509 // Update the .debug_str_offsets section length contribution for the510 // this .dwo file.511 for (auto &Pair : SectionLength) {512 if (Pair.first == DW_SECT_STR_OFFSETS) {513 Pair.second = NewLength + 12;514 break;515 }516 }517 } else {518 // Just emit the same .debug_str_offsets header.519 Out.emitBytes(HeaderBytes);520 }521 writeNewOffsetsTo(Out, Data, OffsetRemapping, Offset, ContributionEnd,522 OldOffsetSize, NewOffsetSize);523 }524 525 } else {526 assert(OldOffsetSize == NewOffsetSize);527 writeNewOffsetsTo(Out, Data, OffsetRemapping, Offset, Size, OldOffsetSize,528 NewOffsetSize);529 }530}531 532enum AccessField { Offset, Length };533void writeIndexTable(MCStreamer &Out, ArrayRef<unsigned> ContributionOffsets,534 const MapVector<uint64_t, UnitIndexEntry> &IndexEntries,535 const AccessField &Field) {536 for (const auto &E : IndexEntries)537 for (size_t I = 0; I != std::size(E.second.Contributions); ++I)538 if (ContributionOffsets[I])539 Out.emitIntValue((Field == AccessField::Offset540 ? E.second.Contributions[I].getOffset32()541 : E.second.Contributions[I].getLength32()),542 4);543}544 545void writeIndex(MCStreamer &Out, MCSection *Section,546 ArrayRef<unsigned> ContributionOffsets,547 const MapVector<uint64_t, UnitIndexEntry> &IndexEntries,548 uint32_t IndexVersion) {549 if (IndexEntries.empty())550 return;551 552 unsigned Columns = 0;553 for (auto &C : ContributionOffsets)554 if (C)555 ++Columns;556 557 std::vector<unsigned> Buckets(NextPowerOf2(3 * IndexEntries.size() / 2));558 uint64_t Mask = Buckets.size() - 1;559 size_t I = 0;560 for (const auto &P : IndexEntries) {561 auto S = P.first;562 auto H = S & Mask;563 auto HP = ((S >> 32) & Mask) | 1;564 while (Buckets[H]) {565 assert(S != IndexEntries.begin()[Buckets[H] - 1].first &&566 "Duplicate unit");567 H = (H + HP) & Mask;568 }569 Buckets[H] = I + 1;570 ++I;571 }572 573 Out.switchSection(Section);574 Out.emitIntValue(IndexVersion, 4); // Version575 Out.emitIntValue(Columns, 4); // Columns576 Out.emitIntValue(IndexEntries.size(), 4); // Num Units577 Out.emitIntValue(Buckets.size(), 4); // Num Buckets578 579 // Write the signatures.580 for (const auto &I : Buckets)581 Out.emitIntValue(I ? IndexEntries.begin()[I - 1].first : 0, 8);582 583 // Write the indexes.584 for (const auto &I : Buckets)585 Out.emitIntValue(I, 4);586 587 // Write the column headers (which sections will appear in the table)588 for (size_t I = 0; I != ContributionOffsets.size(); ++I)589 if (ContributionOffsets[I])590 Out.emitIntValue(getOnDiskSectionId(I), 4);591 592 // Write the offsets.593 writeIndexTable(Out, ContributionOffsets, IndexEntries, AccessField::Offset);594 595 // Write the lengths.596 writeIndexTable(Out, ContributionOffsets, IndexEntries, AccessField::Length);597}598 599Error buildDuplicateError(const std::pair<uint64_t, UnitIndexEntry> &PrevE,600 const CompileUnitIdentifiers &ID, StringRef DWPName) {601 return make_error<DWPError>(602 std::string("duplicate DWO ID (") + utohexstr(PrevE.first) + ") in " +603 buildDWODescription(PrevE.second.Name, PrevE.second.DWPName,604 PrevE.second.DWOName) +605 " and " + buildDWODescription(ID.Name, DWPName, ID.DWOName));606}607 608Error handleSection(609 const StringMap<std::pair<MCSection *, DWARFSectionKind>> &KnownSections,610 const MCSection *StrSection, const MCSection *StrOffsetSection,611 const MCSection *TypesSection, const MCSection *CUIndexSection,612 const MCSection *TUIndexSection, const MCSection *InfoSection,613 const SectionRef &Section, MCStreamer &Out,614 std::deque<SmallString<32>> &UncompressedSections,615 uint32_t (&ContributionOffsets)[8], UnitIndexEntry &CurEntry,616 StringRef &CurStrSection, StringRef &CurStrOffsetSection,617 std::vector<StringRef> &CurTypesSection,618 std::vector<StringRef> &CurInfoSection, StringRef &AbbrevSection,619 StringRef &CurCUIndexSection, StringRef &CurTUIndexSection,620 SectionLengths &SectionLength) {621 if (Section.isBSS())622 return Error::success();623 624 if (Section.isVirtual())625 return Error::success();626 627 Expected<StringRef> NameOrErr = Section.getName();628 if (!NameOrErr)629 return NameOrErr.takeError();630 StringRef Name = *NameOrErr;631 632 Expected<StringRef> ContentsOrErr = Section.getContents();633 if (!ContentsOrErr)634 return ContentsOrErr.takeError();635 StringRef Contents = *ContentsOrErr;636 637 if (auto Err = handleCompressedSection(UncompressedSections, Section, Name,638 Contents))639 return Err;640 641 Name = Name.substr(Name.find_first_not_of("._"));642 643 auto SectionPair = KnownSections.find(Name);644 if (SectionPair == KnownSections.end())645 return Error::success();646 647 if (DWARFSectionKind Kind = SectionPair->second.second) {648 if (Kind != DW_SECT_EXT_TYPES && Kind != DW_SECT_INFO) {649 SectionLength.push_back(std::make_pair(Kind, Contents.size()));650 }651 652 if (Kind == DW_SECT_ABBREV) {653 AbbrevSection = Contents;654 }655 }656 657 MCSection *OutSection = SectionPair->second.first;658 if (OutSection == StrOffsetSection)659 CurStrOffsetSection = Contents;660 else if (OutSection == StrSection)661 CurStrSection = Contents;662 else if (OutSection == TypesSection)663 CurTypesSection.push_back(Contents);664 else if (OutSection == CUIndexSection)665 CurCUIndexSection = Contents;666 else if (OutSection == TUIndexSection)667 CurTUIndexSection = Contents;668 else if (OutSection == InfoSection)669 CurInfoSection.push_back(Contents);670 else {671 Out.switchSection(OutSection);672 Out.emitBytes(Contents);673 }674 return Error::success();675}676 677Error write(MCStreamer &Out, ArrayRef<std::string> Inputs,678 OnCuIndexOverflow OverflowOptValue,679 Dwarf64StrOffsetsPromotion StrOffsetsOptValue) {680 const auto &MCOFI = *Out.getContext().getObjectFileInfo();681 MCSection *const StrSection = MCOFI.getDwarfStrDWOSection();682 MCSection *const StrOffsetSection = MCOFI.getDwarfStrOffDWOSection();683 MCSection *const TypesSection = MCOFI.getDwarfTypesDWOSection();684 MCSection *const CUIndexSection = MCOFI.getDwarfCUIndexSection();685 MCSection *const TUIndexSection = MCOFI.getDwarfTUIndexSection();686 MCSection *const InfoSection = MCOFI.getDwarfInfoDWOSection();687 const StringMap<std::pair<MCSection *, DWARFSectionKind>> KnownSections = {688 {"debug_info.dwo", {InfoSection, DW_SECT_INFO}},689 {"debug_types.dwo", {MCOFI.getDwarfTypesDWOSection(), DW_SECT_EXT_TYPES}},690 {"debug_str_offsets.dwo", {StrOffsetSection, DW_SECT_STR_OFFSETS}},691 {"debug_str.dwo", {StrSection, static_cast<DWARFSectionKind>(0)}},692 {"debug_loc.dwo", {MCOFI.getDwarfLocDWOSection(), DW_SECT_EXT_LOC}},693 {"debug_line.dwo", {MCOFI.getDwarfLineDWOSection(), DW_SECT_LINE}},694 {"debug_macro.dwo", {MCOFI.getDwarfMacroDWOSection(), DW_SECT_MACRO}},695 {"debug_abbrev.dwo", {MCOFI.getDwarfAbbrevDWOSection(), DW_SECT_ABBREV}},696 {"debug_loclists.dwo",697 {MCOFI.getDwarfLoclistsDWOSection(), DW_SECT_LOCLISTS}},698 {"debug_rnglists.dwo",699 {MCOFI.getDwarfRnglistsDWOSection(), DW_SECT_RNGLISTS}},700 {"debug_cu_index", {CUIndexSection, static_cast<DWARFSectionKind>(0)}},701 {"debug_tu_index", {TUIndexSection, static_cast<DWARFSectionKind>(0)}}};702 703 MapVector<uint64_t, UnitIndexEntry> IndexEntries;704 MapVector<uint64_t, UnitIndexEntry> TypeIndexEntries;705 706 uint32_t ContributionOffsets[8] = {};707 uint16_t Version = 0;708 uint32_t IndexVersion = 0;709 StringRef FirstInput;710 bool AnySectionOverflow = false;711 712 DWPStringPool Strings(Out, StrSection);713 714 SmallVector<OwningBinary<object::ObjectFile>, 128> Objects;715 Objects.reserve(Inputs.size());716 717 std::deque<SmallString<32>> UncompressedSections;718 719 for (const auto &Input : Inputs) {720 auto ErrOrObj = object::ObjectFile::createObjectFile(Input);721 if (!ErrOrObj) {722 return handleErrors(ErrOrObj.takeError(),723 [&](std::unique_ptr<ECError> EC) -> Error {724 return createFileError(Input, Error(std::move(EC)));725 });726 }727 728 auto &Obj = *ErrOrObj->getBinary();729 Objects.push_back(std::move(*ErrOrObj));730 731 UnitIndexEntry CurEntry = {};732 733 StringRef CurStrSection;734 StringRef CurStrOffsetSection;735 std::vector<StringRef> CurTypesSection;736 std::vector<StringRef> CurInfoSection;737 StringRef AbbrevSection;738 StringRef CurCUIndexSection;739 StringRef CurTUIndexSection;740 741 // This maps each section contained in this file to its length.742 // This information is later on used to calculate the contributions,743 // i.e. offset and length, of each compile/type unit to a section.744 SectionLengths SectionLength;745 746 for (const auto &Section : Obj.sections())747 if (auto Err = handleSection(748 KnownSections, StrSection, StrOffsetSection, TypesSection,749 CUIndexSection, TUIndexSection, InfoSection, Section, Out,750 UncompressedSections, ContributionOffsets, CurEntry,751 CurStrSection, CurStrOffsetSection, CurTypesSection,752 CurInfoSection, AbbrevSection, CurCUIndexSection,753 CurTUIndexSection, SectionLength))754 return Err;755 756 if (CurInfoSection.empty())757 continue;758 759 Expected<InfoSectionUnitHeader> HeaderOrErr =760 parseInfoSectionUnitHeader(CurInfoSection.front());761 if (!HeaderOrErr)762 return HeaderOrErr.takeError();763 InfoSectionUnitHeader &Header = *HeaderOrErr;764 765 if (Version == 0) {766 Version = Header.Version;767 IndexVersion = Version < 5 ? 2 : 5;768 FirstInput = Input;769 } else if (Version != Header.Version) {770 return make_error<DWPError>(771 "incompatible DWARF compile unit version: " + Input + " (version " +772 utostr(Header.Version) + ") and " + FirstInput.str() + " (version " +773 utostr(Version) + ")");774 }775 776 writeStringsAndOffsets(Out, Strings, StrOffsetSection, CurStrSection,777 CurStrOffsetSection, Header.Version, SectionLength,778 StrOffsetsOptValue);779 780 for (auto Pair : SectionLength) {781 auto Index = getContributionIndex(Pair.first, IndexVersion);782 CurEntry.Contributions[Index].setOffset(ContributionOffsets[Index]);783 CurEntry.Contributions[Index].setLength(Pair.second);784 uint32_t OldOffset = ContributionOffsets[Index];785 ContributionOffsets[Index] += CurEntry.Contributions[Index].getLength32();786 if (OldOffset > ContributionOffsets[Index]) {787 uint32_t SectionIndex = 0;788 for (auto &Section : Obj.sections()) {789 if (SectionIndex == Index) {790 if (Error Err = sectionOverflowErrorOrWarning(791 OldOffset, ContributionOffsets[Index], *Section.getName(),792 OverflowOptValue, AnySectionOverflow))793 return Err;794 }795 ++SectionIndex;796 }797 if (AnySectionOverflow)798 break;799 }800 }801 802 uint32_t &InfoSectionOffset =803 ContributionOffsets[getContributionIndex(DW_SECT_INFO, IndexVersion)];804 if (CurCUIndexSection.empty()) {805 bool FoundCUUnit = false;806 Out.switchSection(InfoSection);807 for (StringRef Info : CurInfoSection) {808 uint64_t UnitOffset = 0;809 while (Info.size() > UnitOffset) {810 Expected<InfoSectionUnitHeader> HeaderOrError =811 parseInfoSectionUnitHeader(Info.substr(UnitOffset, Info.size()));812 if (!HeaderOrError)813 return HeaderOrError.takeError();814 InfoSectionUnitHeader &Header = *HeaderOrError;815 816 UnitIndexEntry Entry = CurEntry;817 auto &C = Entry.Contributions[getContributionIndex(DW_SECT_INFO,818 IndexVersion)];819 C.setOffset(InfoSectionOffset);820 C.setLength(Header.Length + 4);821 822 if (std::numeric_limits<uint32_t>::max() - InfoSectionOffset <823 C.getLength32()) {824 if (Error Err = sectionOverflowErrorOrWarning(825 InfoSectionOffset, InfoSectionOffset + C.getLength32(),826 "debug_info", OverflowOptValue, AnySectionOverflow))827 return Err;828 if (AnySectionOverflow) {829 if (Header.Version < 5 ||830 Header.UnitType == dwarf::DW_UT_split_compile)831 FoundCUUnit = true;832 break;833 }834 }835 836 UnitOffset += C.getLength32();837 if (Header.Version < 5 ||838 Header.UnitType == dwarf::DW_UT_split_compile) {839 Expected<CompileUnitIdentifiers> EID = getCUIdentifiers(840 Header, AbbrevSection,841 Info.substr(UnitOffset - C.getLength32(), C.getLength32()),842 CurStrOffsetSection, CurStrSection);843 844 if (!EID)845 return createFileError(Input, EID.takeError());846 const auto &ID = *EID;847 auto P = IndexEntries.insert(std::make_pair(ID.Signature, Entry));848 if (!P.second)849 return buildDuplicateError(*P.first, ID, "");850 P.first->second.Name = ID.Name;851 P.first->second.DWOName = ID.DWOName;852 853 FoundCUUnit = true;854 } else if (Header.UnitType == dwarf::DW_UT_split_type) {855 auto P = TypeIndexEntries.insert(856 std::make_pair(*Header.Signature, Entry));857 if (!P.second)858 continue;859 }860 Out.emitBytes(861 Info.substr(UnitOffset - C.getLength32(), C.getLength32()));862 InfoSectionOffset += C.getLength32();863 }864 if (AnySectionOverflow)865 break;866 }867 868 if (!FoundCUUnit)869 return make_error<DWPError>("no compile unit found in file: " + Input);870 871 if (IndexVersion == 2) {872 // Add types from the .debug_types section from DWARF < 5.873 if (Error Err = addAllTypesFromTypesSection(874 Out, TypeIndexEntries, TypesSection, CurTypesSection, CurEntry,875 ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES, 2)],876 OverflowOptValue, AnySectionOverflow))877 return Err;878 }879 if (AnySectionOverflow)880 break;881 continue;882 }883 884 if (CurInfoSection.size() != 1)885 return make_error<DWPError>("expected exactly one occurrence of a debug "886 "info section in a .dwp file");887 StringRef DwpSingleInfoSection = CurInfoSection.front();888 889 DWARFUnitIndex CUIndex(DW_SECT_INFO);890 DataExtractor CUIndexData(CurCUIndexSection, Obj.isLittleEndian(), 0);891 if (!CUIndex.parse(CUIndexData))892 return make_error<DWPError>("failed to parse cu_index");893 if (CUIndex.getVersion() != IndexVersion)894 return make_error<DWPError>("incompatible cu_index versions, found " +895 utostr(CUIndex.getVersion()) +896 " and expecting " + utostr(IndexVersion));897 898 Out.switchSection(InfoSection);899 for (const DWARFUnitIndex::Entry &E : CUIndex.getRows()) {900 auto *I = E.getContributions();901 if (!I)902 continue;903 auto P = IndexEntries.insert(std::make_pair(E.getSignature(), CurEntry));904 StringRef CUInfoSection =905 getSubsection(DwpSingleInfoSection, E, DW_SECT_INFO);906 Expected<InfoSectionUnitHeader> HeaderOrError =907 parseInfoSectionUnitHeader(CUInfoSection);908 if (!HeaderOrError)909 return HeaderOrError.takeError();910 InfoSectionUnitHeader &Header = *HeaderOrError;911 912 Expected<CompileUnitIdentifiers> EID = getCUIdentifiers(913 Header, getSubsection(AbbrevSection, E, DW_SECT_ABBREV),914 CUInfoSection,915 getSubsection(CurStrOffsetSection, E, DW_SECT_STR_OFFSETS),916 CurStrSection);917 if (!EID)918 return createFileError(Input, EID.takeError());919 const auto &ID = *EID;920 if (!P.second)921 return buildDuplicateError(*P.first, ID, Input);922 auto &NewEntry = P.first->second;923 NewEntry.Name = ID.Name;924 NewEntry.DWOName = ID.DWOName;925 NewEntry.DWPName = Input;926 for (auto Kind : CUIndex.getColumnKinds()) {927 if (!isSupportedSectionKind(Kind))928 continue;929 auto &C =930 NewEntry.Contributions[getContributionIndex(Kind, IndexVersion)];931 C.setOffset(C.getOffset() + I->getOffset());932 C.setLength(I->getLength());933 ++I;934 }935 unsigned Index = getContributionIndex(DW_SECT_INFO, IndexVersion);936 auto &C = NewEntry.Contributions[Index];937 Out.emitBytes(CUInfoSection);938 C.setOffset(InfoSectionOffset);939 InfoSectionOffset += C.getLength32();940 }941 942 if (!CurTUIndexSection.empty()) {943 llvm::DWARFSectionKind TUSectionKind;944 MCSection *OutSection;945 StringRef TypeInputSection;946 // Write type units into debug info section for DWARFv5.947 if (Version >= 5) {948 TUSectionKind = DW_SECT_INFO;949 OutSection = InfoSection;950 TypeInputSection = DwpSingleInfoSection;951 } else {952 // Write type units into debug types section for DWARF < 5.953 if (CurTypesSection.size() != 1)954 return make_error<DWPError>(955 "multiple type unit sections in .dwp file");956 957 TUSectionKind = DW_SECT_EXT_TYPES;958 OutSection = TypesSection;959 TypeInputSection = CurTypesSection.front();960 }961 962 DWARFUnitIndex TUIndex(TUSectionKind);963 DataExtractor TUIndexData(CurTUIndexSection, Obj.isLittleEndian(), 0);964 if (!TUIndex.parse(TUIndexData))965 return make_error<DWPError>("failed to parse tu_index");966 if (TUIndex.getVersion() != IndexVersion)967 return make_error<DWPError>("incompatible tu_index versions, found " +968 utostr(TUIndex.getVersion()) +969 " and expecting " + utostr(IndexVersion));970 971 unsigned TypesContributionIndex =972 getContributionIndex(TUSectionKind, IndexVersion);973 if (Error Err = addAllTypesFromDWP(974 Out, TypeIndexEntries, TUIndex, OutSection, TypeInputSection,975 CurEntry, ContributionOffsets[TypesContributionIndex],976 TypesContributionIndex, OverflowOptValue, AnySectionOverflow))977 return Err;978 }979 if (AnySectionOverflow)980 break;981 }982 983 if (Version < 5) {984 // Lie about there being no info contributions so the TU index only includes985 // the type unit contribution for DWARF < 5. In DWARFv5 the TU index has a986 // contribution to the info section, so we do not want to lie about it.987 ContributionOffsets[0] = 0;988 }989 writeIndex(Out, MCOFI.getDwarfTUIndexSection(), ContributionOffsets,990 TypeIndexEntries, IndexVersion);991 992 if (Version < 5) {993 // Lie about the type contribution for DWARF < 5. In DWARFv5 the type994 // section does not exist, so no need to do anything about this.995 ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES, 2)] = 0;996 // Unlie about the info contribution997 ContributionOffsets[0] = 1;998 }999 1000 writeIndex(Out, MCOFI.getDwarfCUIndexSection(), ContributionOffsets,1001 IndexEntries, IndexVersion);1002 1003 return Error::success();1004}1005} // namespace llvm1006