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