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