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