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