162cfcf62SDimitry Andric //===-- llvm-dwp.cpp - Split DWARF merging tool for llvm ------------------===// 262cfcf62SDimitry Andric // 362cfcf62SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 462cfcf62SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 562cfcf62SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 662cfcf62SDimitry Andric // 762cfcf62SDimitry Andric //===----------------------------------------------------------------------===// 862cfcf62SDimitry Andric // 962cfcf62SDimitry Andric // A utility for merging DWARF 5 Split DWARF .dwo files into .dwp (DWARF 1062cfcf62SDimitry Andric // package files). 1162cfcf62SDimitry Andric // 1262cfcf62SDimitry Andric //===----------------------------------------------------------------------===// 1362cfcf62SDimitry Andric #include "DWPError.h" 1462cfcf62SDimitry Andric #include "DWPStringPool.h" 1562cfcf62SDimitry Andric #include "llvm/ADT/MapVector.h" 1662cfcf62SDimitry Andric #include "llvm/ADT/Optional.h" 1762cfcf62SDimitry Andric #include "llvm/ADT/STLExtras.h" 1862cfcf62SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFContext.h" 1962cfcf62SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" 2062cfcf62SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h" 2162cfcf62SDimitry Andric #include "llvm/MC/MCAsmBackend.h" 2262cfcf62SDimitry Andric #include "llvm/MC/MCAsmInfo.h" 2362cfcf62SDimitry Andric #include "llvm/MC/MCCodeEmitter.h" 2462cfcf62SDimitry Andric #include "llvm/MC/MCContext.h" 2562cfcf62SDimitry Andric #include "llvm/MC/MCInstrInfo.h" 2662cfcf62SDimitry Andric #include "llvm/MC/MCObjectFileInfo.h" 2762cfcf62SDimitry Andric #include "llvm/MC/MCObjectWriter.h" 2862cfcf62SDimitry Andric #include "llvm/MC/MCRegisterInfo.h" 2962cfcf62SDimitry Andric #include "llvm/MC/MCStreamer.h" 30*5ffd83dbSDimitry Andric #include "llvm/MC/MCTargetOptionsCommandFlags.h" 3162cfcf62SDimitry Andric #include "llvm/Object/Decompressor.h" 3262cfcf62SDimitry Andric #include "llvm/Object/ObjectFile.h" 33*5ffd83dbSDimitry Andric #include "llvm/Support/CommandLine.h" 3462cfcf62SDimitry Andric #include "llvm/Support/DataExtractor.h" 3562cfcf62SDimitry Andric #include "llvm/Support/Error.h" 3662cfcf62SDimitry Andric #include "llvm/Support/FileSystem.h" 3762cfcf62SDimitry Andric #include "llvm/Support/InitLLVM.h" 3862cfcf62SDimitry Andric #include "llvm/Support/MathExtras.h" 3962cfcf62SDimitry Andric #include "llvm/Support/MemoryBuffer.h" 4062cfcf62SDimitry Andric #include "llvm/Support/Path.h" 4162cfcf62SDimitry Andric #include "llvm/Support/TargetRegistry.h" 4262cfcf62SDimitry Andric #include "llvm/Support/TargetSelect.h" 4362cfcf62SDimitry Andric #include "llvm/Support/ToolOutputFile.h" 4462cfcf62SDimitry Andric #include "llvm/Support/WithColor.h" 4562cfcf62SDimitry Andric #include "llvm/Support/raw_ostream.h" 4662cfcf62SDimitry Andric 4762cfcf62SDimitry Andric using namespace llvm; 4862cfcf62SDimitry Andric using namespace llvm::object; 4962cfcf62SDimitry Andric 50*5ffd83dbSDimitry Andric static mc::RegisterMCTargetOptionsFlags MCTargetOptionsFlags; 51*5ffd83dbSDimitry Andric 5262cfcf62SDimitry Andric cl::OptionCategory DwpCategory("Specific Options"); 5362cfcf62SDimitry Andric static cl::list<std::string> InputFiles(cl::Positional, cl::ZeroOrMore, 5462cfcf62SDimitry Andric cl::desc("<input files>"), 5562cfcf62SDimitry Andric cl::cat(DwpCategory)); 5662cfcf62SDimitry Andric 5762cfcf62SDimitry Andric static cl::list<std::string> ExecFilenames( 5862cfcf62SDimitry Andric "e", cl::ZeroOrMore, 5962cfcf62SDimitry Andric cl::desc("Specify the executable/library files to get the list of *.dwo from"), 6062cfcf62SDimitry Andric cl::value_desc("filename"), cl::cat(DwpCategory)); 6162cfcf62SDimitry Andric 6262cfcf62SDimitry Andric static cl::opt<std::string> OutputFilename(cl::Required, "o", 6362cfcf62SDimitry Andric cl::desc("Specify the output file."), 6462cfcf62SDimitry Andric cl::value_desc("filename"), 6562cfcf62SDimitry Andric cl::cat(DwpCategory)); 6662cfcf62SDimitry Andric 6762cfcf62SDimitry Andric static void writeStringsAndOffsets(MCStreamer &Out, DWPStringPool &Strings, 6862cfcf62SDimitry Andric MCSection *StrOffsetSection, 6962cfcf62SDimitry Andric StringRef CurStrSection, 7062cfcf62SDimitry Andric StringRef CurStrOffsetSection) { 7162cfcf62SDimitry Andric // Could possibly produce an error or warning if one of these was non-null but 7262cfcf62SDimitry Andric // the other was null. 7362cfcf62SDimitry Andric if (CurStrSection.empty() || CurStrOffsetSection.empty()) 7462cfcf62SDimitry Andric return; 7562cfcf62SDimitry Andric 7662cfcf62SDimitry Andric DenseMap<uint64_t, uint32_t> OffsetRemapping; 7762cfcf62SDimitry Andric 7862cfcf62SDimitry Andric DataExtractor Data(CurStrSection, true, 0); 7962cfcf62SDimitry Andric uint64_t LocalOffset = 0; 8062cfcf62SDimitry Andric uint64_t PrevOffset = 0; 8162cfcf62SDimitry Andric while (const char *s = Data.getCStr(&LocalOffset)) { 8262cfcf62SDimitry Andric OffsetRemapping[PrevOffset] = 8362cfcf62SDimitry Andric Strings.getOffset(s, LocalOffset - PrevOffset); 8462cfcf62SDimitry Andric PrevOffset = LocalOffset; 8562cfcf62SDimitry Andric } 8662cfcf62SDimitry Andric 8762cfcf62SDimitry Andric Data = DataExtractor(CurStrOffsetSection, true, 0); 8862cfcf62SDimitry Andric 8962cfcf62SDimitry Andric Out.SwitchSection(StrOffsetSection); 9062cfcf62SDimitry Andric 9162cfcf62SDimitry Andric uint64_t Offset = 0; 9262cfcf62SDimitry Andric uint64_t Size = CurStrOffsetSection.size(); 9362cfcf62SDimitry Andric while (Offset < Size) { 9462cfcf62SDimitry Andric auto OldOffset = Data.getU32(&Offset); 9562cfcf62SDimitry Andric auto NewOffset = OffsetRemapping[OldOffset]; 96*5ffd83dbSDimitry Andric Out.emitIntValue(NewOffset, 4); 9762cfcf62SDimitry Andric } 9862cfcf62SDimitry Andric } 9962cfcf62SDimitry Andric 10062cfcf62SDimitry Andric static uint64_t getCUAbbrev(StringRef Abbrev, uint64_t AbbrCode) { 10162cfcf62SDimitry Andric uint64_t CurCode; 10262cfcf62SDimitry Andric uint64_t Offset = 0; 10362cfcf62SDimitry Andric DataExtractor AbbrevData(Abbrev, true, 0); 10462cfcf62SDimitry Andric while ((CurCode = AbbrevData.getULEB128(&Offset)) != AbbrCode) { 10562cfcf62SDimitry Andric // Tag 10662cfcf62SDimitry Andric AbbrevData.getULEB128(&Offset); 10762cfcf62SDimitry Andric // DW_CHILDREN 10862cfcf62SDimitry Andric AbbrevData.getU8(&Offset); 10962cfcf62SDimitry Andric // Attributes 11062cfcf62SDimitry Andric while (AbbrevData.getULEB128(&Offset) | AbbrevData.getULEB128(&Offset)) 11162cfcf62SDimitry Andric ; 11262cfcf62SDimitry Andric } 11362cfcf62SDimitry Andric return Offset; 11462cfcf62SDimitry Andric } 11562cfcf62SDimitry Andric 11662cfcf62SDimitry Andric struct CompileUnitIdentifiers { 11762cfcf62SDimitry Andric uint64_t Signature = 0; 11862cfcf62SDimitry Andric const char *Name = ""; 11962cfcf62SDimitry Andric const char *DWOName = ""; 12062cfcf62SDimitry Andric }; 12162cfcf62SDimitry Andric 12262cfcf62SDimitry Andric static Expected<const char *> 12362cfcf62SDimitry Andric getIndexedString(dwarf::Form Form, DataExtractor InfoData, 12462cfcf62SDimitry Andric uint64_t &InfoOffset, StringRef StrOffsets, StringRef Str) { 12562cfcf62SDimitry Andric if (Form == dwarf::DW_FORM_string) 12662cfcf62SDimitry Andric return InfoData.getCStr(&InfoOffset); 12762cfcf62SDimitry Andric if (Form != dwarf::DW_FORM_GNU_str_index) 12862cfcf62SDimitry Andric return make_error<DWPError>( 12962cfcf62SDimitry Andric "string field encoded without DW_FORM_string or DW_FORM_GNU_str_index"); 13062cfcf62SDimitry Andric auto StrIndex = InfoData.getULEB128(&InfoOffset); 13162cfcf62SDimitry Andric DataExtractor StrOffsetsData(StrOffsets, true, 0); 13262cfcf62SDimitry Andric uint64_t StrOffsetsOffset = 4 * StrIndex; 13362cfcf62SDimitry Andric uint64_t StrOffset = StrOffsetsData.getU32(&StrOffsetsOffset); 13462cfcf62SDimitry Andric DataExtractor StrData(Str, true, 0); 13562cfcf62SDimitry Andric return StrData.getCStr(&StrOffset); 13662cfcf62SDimitry Andric } 13762cfcf62SDimitry Andric 13862cfcf62SDimitry Andric static Expected<CompileUnitIdentifiers> getCUIdentifiers(StringRef Abbrev, 13962cfcf62SDimitry Andric StringRef Info, 14062cfcf62SDimitry Andric StringRef StrOffsets, 14162cfcf62SDimitry Andric StringRef Str) { 14262cfcf62SDimitry Andric uint64_t Offset = 0; 14362cfcf62SDimitry Andric DataExtractor InfoData(Info, true, 0); 14462cfcf62SDimitry Andric dwarf::DwarfFormat Format = dwarf::DwarfFormat::DWARF32; 14562cfcf62SDimitry Andric uint64_t Length = InfoData.getU32(&Offset); 146*5ffd83dbSDimitry Andric CompileUnitIdentifiers ID; 147*5ffd83dbSDimitry Andric Optional<uint64_t> Signature = None; 14862cfcf62SDimitry Andric // If the length is 0xffffffff, then this indictes that this is a DWARF 64 14962cfcf62SDimitry Andric // stream and the length is actually encoded into a 64 bit value that follows. 15062cfcf62SDimitry Andric if (Length == 0xffffffffU) { 15162cfcf62SDimitry Andric Format = dwarf::DwarfFormat::DWARF64; 15262cfcf62SDimitry Andric Length = InfoData.getU64(&Offset); 15362cfcf62SDimitry Andric } 15462cfcf62SDimitry Andric uint16_t Version = InfoData.getU16(&Offset); 155*5ffd83dbSDimitry Andric if (Version >= 5) { 156*5ffd83dbSDimitry Andric auto UnitType = InfoData.getU8(&Offset); 157*5ffd83dbSDimitry Andric if (UnitType != dwarf::DW_UT_split_compile) 158*5ffd83dbSDimitry Andric return make_error<DWPError>( 159*5ffd83dbSDimitry Andric std::string("unit type DW_UT_split_compile type not found in " 160*5ffd83dbSDimitry Andric "debug_info header. Unexpected unit type 0x" + 161*5ffd83dbSDimitry Andric utostr(UnitType) + " found")); 162*5ffd83dbSDimitry Andric } 16362cfcf62SDimitry Andric InfoData.getU32(&Offset); // Abbrev offset (should be zero) 16462cfcf62SDimitry Andric uint8_t AddrSize = InfoData.getU8(&Offset); 165*5ffd83dbSDimitry Andric if (Version >= 5) 166*5ffd83dbSDimitry Andric Signature = InfoData.getU64(&Offset); 16762cfcf62SDimitry Andric uint32_t AbbrCode = InfoData.getULEB128(&Offset); 16862cfcf62SDimitry Andric 16962cfcf62SDimitry Andric DataExtractor AbbrevData(Abbrev, true, 0); 17062cfcf62SDimitry Andric uint64_t AbbrevOffset = getCUAbbrev(Abbrev, AbbrCode); 17162cfcf62SDimitry Andric auto Tag = static_cast<dwarf::Tag>(AbbrevData.getULEB128(&AbbrevOffset)); 17262cfcf62SDimitry Andric if (Tag != dwarf::DW_TAG_compile_unit) 17362cfcf62SDimitry Andric return make_error<DWPError>("top level DIE is not a compile unit"); 17462cfcf62SDimitry Andric // DW_CHILDREN 17562cfcf62SDimitry Andric AbbrevData.getU8(&AbbrevOffset); 17662cfcf62SDimitry Andric uint32_t Name; 17762cfcf62SDimitry Andric dwarf::Form Form; 17862cfcf62SDimitry Andric while ((Name = AbbrevData.getULEB128(&AbbrevOffset)) | 17962cfcf62SDimitry Andric (Form = static_cast<dwarf::Form>(AbbrevData.getULEB128(&AbbrevOffset))) && 18062cfcf62SDimitry Andric (Name != 0 || Form != 0)) { 18162cfcf62SDimitry Andric switch (Name) { 18262cfcf62SDimitry Andric case dwarf::DW_AT_name: { 18362cfcf62SDimitry Andric Expected<const char *> EName = 18462cfcf62SDimitry Andric getIndexedString(Form, InfoData, Offset, StrOffsets, Str); 18562cfcf62SDimitry Andric if (!EName) 18662cfcf62SDimitry Andric return EName.takeError(); 18762cfcf62SDimitry Andric ID.Name = *EName; 18862cfcf62SDimitry Andric break; 18962cfcf62SDimitry Andric } 190*5ffd83dbSDimitry Andric case dwarf::DW_AT_GNU_dwo_name: 191*5ffd83dbSDimitry Andric case dwarf::DW_AT_dwo_name: { 19262cfcf62SDimitry Andric Expected<const char *> EName = 19362cfcf62SDimitry Andric getIndexedString(Form, InfoData, Offset, StrOffsets, Str); 19462cfcf62SDimitry Andric if (!EName) 19562cfcf62SDimitry Andric return EName.takeError(); 19662cfcf62SDimitry Andric ID.DWOName = *EName; 19762cfcf62SDimitry Andric break; 19862cfcf62SDimitry Andric } 19962cfcf62SDimitry Andric case dwarf::DW_AT_GNU_dwo_id: 20062cfcf62SDimitry Andric Signature = InfoData.getU64(&Offset); 20162cfcf62SDimitry Andric break; 20262cfcf62SDimitry Andric default: 20362cfcf62SDimitry Andric DWARFFormValue::skipValue(Form, InfoData, &Offset, 20462cfcf62SDimitry Andric dwarf::FormParams({Version, AddrSize, Format})); 20562cfcf62SDimitry Andric } 20662cfcf62SDimitry Andric } 20762cfcf62SDimitry Andric if (!Signature) 20862cfcf62SDimitry Andric return make_error<DWPError>("compile unit missing dwo_id"); 20962cfcf62SDimitry Andric ID.Signature = *Signature; 21062cfcf62SDimitry Andric return ID; 21162cfcf62SDimitry Andric } 21262cfcf62SDimitry Andric 21362cfcf62SDimitry Andric struct UnitIndexEntry { 21462cfcf62SDimitry Andric DWARFUnitIndex::Entry::SectionContribution Contributions[8]; 21562cfcf62SDimitry Andric std::string Name; 21662cfcf62SDimitry Andric std::string DWOName; 21762cfcf62SDimitry Andric StringRef DWPName; 21862cfcf62SDimitry Andric }; 21962cfcf62SDimitry Andric 220*5ffd83dbSDimitry Andric static bool isSupportedSectionKind(DWARFSectionKind Kind) { 221*5ffd83dbSDimitry Andric return Kind != DW_SECT_EXT_unknown; 222*5ffd83dbSDimitry Andric } 223*5ffd83dbSDimitry Andric 224*5ffd83dbSDimitry Andric // Convert an internal section identifier into the index to use with 225*5ffd83dbSDimitry Andric // UnitIndexEntry::Contributions. 226*5ffd83dbSDimitry Andric static unsigned getContributionIndex(DWARFSectionKind Kind) { 227*5ffd83dbSDimitry Andric // Assuming the pre-standard DWP format. 228*5ffd83dbSDimitry Andric assert(serializeSectionKind(Kind, 2) >= DW_SECT_INFO); 229*5ffd83dbSDimitry Andric return serializeSectionKind(Kind, 2) - DW_SECT_INFO; 230*5ffd83dbSDimitry Andric } 231*5ffd83dbSDimitry Andric 232*5ffd83dbSDimitry Andric // Convert a UnitIndexEntry::Contributions index to the corresponding on-disk 233*5ffd83dbSDimitry Andric // value of the section identifier. 234*5ffd83dbSDimitry Andric static unsigned getOnDiskSectionId(unsigned Index) { 235*5ffd83dbSDimitry Andric return Index + DW_SECT_INFO; 236*5ffd83dbSDimitry Andric } 237*5ffd83dbSDimitry Andric 23862cfcf62SDimitry Andric static StringRef getSubsection(StringRef Section, 23962cfcf62SDimitry Andric const DWARFUnitIndex::Entry &Entry, 24062cfcf62SDimitry Andric DWARFSectionKind Kind) { 241*5ffd83dbSDimitry Andric const auto *Off = Entry.getContribution(Kind); 24262cfcf62SDimitry Andric if (!Off) 24362cfcf62SDimitry Andric return StringRef(); 24462cfcf62SDimitry Andric return Section.substr(Off->Offset, Off->Length); 24562cfcf62SDimitry Andric } 24662cfcf62SDimitry Andric 24762cfcf62SDimitry Andric static void addAllTypesFromDWP( 24862cfcf62SDimitry Andric MCStreamer &Out, MapVector<uint64_t, UnitIndexEntry> &TypeIndexEntries, 24962cfcf62SDimitry Andric const DWARFUnitIndex &TUIndex, MCSection *OutputTypes, StringRef Types, 25062cfcf62SDimitry Andric const UnitIndexEntry &TUEntry, uint32_t &TypesOffset) { 25162cfcf62SDimitry Andric Out.SwitchSection(OutputTypes); 25262cfcf62SDimitry Andric for (const DWARFUnitIndex::Entry &E : TUIndex.getRows()) { 253*5ffd83dbSDimitry Andric auto *I = E.getContributions(); 25462cfcf62SDimitry Andric if (!I) 25562cfcf62SDimitry Andric continue; 25662cfcf62SDimitry Andric auto P = TypeIndexEntries.insert(std::make_pair(E.getSignature(), TUEntry)); 25762cfcf62SDimitry Andric if (!P.second) 25862cfcf62SDimitry Andric continue; 25962cfcf62SDimitry Andric auto &Entry = P.first->second; 26062cfcf62SDimitry Andric // Zero out the debug_info contribution 26162cfcf62SDimitry Andric Entry.Contributions[0] = {}; 26262cfcf62SDimitry Andric for (auto Kind : TUIndex.getColumnKinds()) { 263*5ffd83dbSDimitry Andric if (!isSupportedSectionKind(Kind)) 264*5ffd83dbSDimitry Andric continue; 265*5ffd83dbSDimitry Andric auto &C = Entry.Contributions[getContributionIndex(Kind)]; 26662cfcf62SDimitry Andric C.Offset += I->Offset; 26762cfcf62SDimitry Andric C.Length = I->Length; 26862cfcf62SDimitry Andric ++I; 26962cfcf62SDimitry Andric } 270*5ffd83dbSDimitry Andric unsigned TypesIndex = getContributionIndex(DW_SECT_EXT_TYPES); 271*5ffd83dbSDimitry Andric auto &C = Entry.Contributions[TypesIndex]; 272*5ffd83dbSDimitry Andric Out.emitBytes(Types.substr( 273*5ffd83dbSDimitry Andric C.Offset - TUEntry.Contributions[TypesIndex].Offset, C.Length)); 27462cfcf62SDimitry Andric C.Offset = TypesOffset; 27562cfcf62SDimitry Andric TypesOffset += C.Length; 27662cfcf62SDimitry Andric } 27762cfcf62SDimitry Andric } 27862cfcf62SDimitry Andric 27962cfcf62SDimitry Andric static void addAllTypes(MCStreamer &Out, 28062cfcf62SDimitry Andric MapVector<uint64_t, UnitIndexEntry> &TypeIndexEntries, 28162cfcf62SDimitry Andric MCSection *OutputTypes, 28262cfcf62SDimitry Andric const std::vector<StringRef> &TypesSections, 28362cfcf62SDimitry Andric const UnitIndexEntry &CUEntry, uint32_t &TypesOffset) { 28462cfcf62SDimitry Andric for (StringRef Types : TypesSections) { 28562cfcf62SDimitry Andric Out.SwitchSection(OutputTypes); 28662cfcf62SDimitry Andric uint64_t Offset = 0; 28762cfcf62SDimitry Andric DataExtractor Data(Types, true, 0); 28862cfcf62SDimitry Andric while (Data.isValidOffset(Offset)) { 28962cfcf62SDimitry Andric UnitIndexEntry Entry = CUEntry; 29062cfcf62SDimitry Andric // Zero out the debug_info contribution 29162cfcf62SDimitry Andric Entry.Contributions[0] = {}; 292*5ffd83dbSDimitry Andric auto &C = Entry.Contributions[getContributionIndex(DW_SECT_EXT_TYPES)]; 29362cfcf62SDimitry Andric C.Offset = TypesOffset; 29462cfcf62SDimitry Andric auto PrevOffset = Offset; 29562cfcf62SDimitry Andric // Length of the unit, including the 4 byte length field. 29662cfcf62SDimitry Andric C.Length = Data.getU32(&Offset) + 4; 29762cfcf62SDimitry Andric 29862cfcf62SDimitry Andric Data.getU16(&Offset); // Version 29962cfcf62SDimitry Andric Data.getU32(&Offset); // Abbrev offset 30062cfcf62SDimitry Andric Data.getU8(&Offset); // Address size 30162cfcf62SDimitry Andric auto Signature = Data.getU64(&Offset); 30262cfcf62SDimitry Andric Offset = PrevOffset + C.Length; 30362cfcf62SDimitry Andric 30462cfcf62SDimitry Andric auto P = TypeIndexEntries.insert(std::make_pair(Signature, Entry)); 30562cfcf62SDimitry Andric if (!P.second) 30662cfcf62SDimitry Andric continue; 30762cfcf62SDimitry Andric 308*5ffd83dbSDimitry Andric Out.emitBytes(Types.substr(PrevOffset, C.Length)); 30962cfcf62SDimitry Andric TypesOffset += C.Length; 31062cfcf62SDimitry Andric } 31162cfcf62SDimitry Andric } 31262cfcf62SDimitry Andric } 31362cfcf62SDimitry Andric 31462cfcf62SDimitry Andric static void 31562cfcf62SDimitry Andric writeIndexTable(MCStreamer &Out, ArrayRef<unsigned> ContributionOffsets, 31662cfcf62SDimitry Andric const MapVector<uint64_t, UnitIndexEntry> &IndexEntries, 31762cfcf62SDimitry Andric uint32_t DWARFUnitIndex::Entry::SectionContribution::*Field) { 31862cfcf62SDimitry Andric for (const auto &E : IndexEntries) 31962cfcf62SDimitry Andric for (size_t i = 0; i != array_lengthof(E.second.Contributions); ++i) 32062cfcf62SDimitry Andric if (ContributionOffsets[i]) 321*5ffd83dbSDimitry Andric Out.emitIntValue(E.second.Contributions[i].*Field, 4); 32262cfcf62SDimitry Andric } 32362cfcf62SDimitry Andric 32462cfcf62SDimitry Andric static void 32562cfcf62SDimitry Andric writeIndex(MCStreamer &Out, MCSection *Section, 32662cfcf62SDimitry Andric ArrayRef<unsigned> ContributionOffsets, 32762cfcf62SDimitry Andric const MapVector<uint64_t, UnitIndexEntry> &IndexEntries) { 32862cfcf62SDimitry Andric if (IndexEntries.empty()) 32962cfcf62SDimitry Andric return; 33062cfcf62SDimitry Andric 33162cfcf62SDimitry Andric unsigned Columns = 0; 33262cfcf62SDimitry Andric for (auto &C : ContributionOffsets) 33362cfcf62SDimitry Andric if (C) 33462cfcf62SDimitry Andric ++Columns; 33562cfcf62SDimitry Andric 33662cfcf62SDimitry Andric std::vector<unsigned> Buckets(NextPowerOf2(3 * IndexEntries.size() / 2)); 33762cfcf62SDimitry Andric uint64_t Mask = Buckets.size() - 1; 33862cfcf62SDimitry Andric size_t i = 0; 33962cfcf62SDimitry Andric for (const auto &P : IndexEntries) { 34062cfcf62SDimitry Andric auto S = P.first; 34162cfcf62SDimitry Andric auto H = S & Mask; 34262cfcf62SDimitry Andric auto HP = ((S >> 32) & Mask) | 1; 34362cfcf62SDimitry Andric while (Buckets[H]) { 34462cfcf62SDimitry Andric assert(S != IndexEntries.begin()[Buckets[H] - 1].first && 34562cfcf62SDimitry Andric "Duplicate unit"); 34662cfcf62SDimitry Andric H = (H + HP) & Mask; 34762cfcf62SDimitry Andric } 34862cfcf62SDimitry Andric Buckets[H] = i + 1; 34962cfcf62SDimitry Andric ++i; 35062cfcf62SDimitry Andric } 35162cfcf62SDimitry Andric 35262cfcf62SDimitry Andric Out.SwitchSection(Section); 353*5ffd83dbSDimitry Andric Out.emitIntValue(2, 4); // Version 354*5ffd83dbSDimitry Andric Out.emitIntValue(Columns, 4); // Columns 355*5ffd83dbSDimitry Andric Out.emitIntValue(IndexEntries.size(), 4); // Num Units 356*5ffd83dbSDimitry Andric Out.emitIntValue(Buckets.size(), 4); // Num Buckets 35762cfcf62SDimitry Andric 35862cfcf62SDimitry Andric // Write the signatures. 35962cfcf62SDimitry Andric for (const auto &I : Buckets) 360*5ffd83dbSDimitry Andric Out.emitIntValue(I ? IndexEntries.begin()[I - 1].first : 0, 8); 36162cfcf62SDimitry Andric 36262cfcf62SDimitry Andric // Write the indexes. 36362cfcf62SDimitry Andric for (const auto &I : Buckets) 364*5ffd83dbSDimitry Andric Out.emitIntValue(I, 4); 36562cfcf62SDimitry Andric 36662cfcf62SDimitry Andric // Write the column headers (which sections will appear in the table) 36762cfcf62SDimitry Andric for (size_t i = 0; i != ContributionOffsets.size(); ++i) 36862cfcf62SDimitry Andric if (ContributionOffsets[i]) 369*5ffd83dbSDimitry Andric Out.emitIntValue(getOnDiskSectionId(i), 4); 37062cfcf62SDimitry Andric 37162cfcf62SDimitry Andric // Write the offsets. 37262cfcf62SDimitry Andric writeIndexTable(Out, ContributionOffsets, IndexEntries, 37362cfcf62SDimitry Andric &DWARFUnitIndex::Entry::SectionContribution::Offset); 37462cfcf62SDimitry Andric 37562cfcf62SDimitry Andric // Write the lengths. 37662cfcf62SDimitry Andric writeIndexTable(Out, ContributionOffsets, IndexEntries, 37762cfcf62SDimitry Andric &DWARFUnitIndex::Entry::SectionContribution::Length); 37862cfcf62SDimitry Andric } 37962cfcf62SDimitry Andric 38062cfcf62SDimitry Andric std::string buildDWODescription(StringRef Name, StringRef DWPName, StringRef DWOName) { 38162cfcf62SDimitry Andric std::string Text = "\'"; 38262cfcf62SDimitry Andric Text += Name; 38362cfcf62SDimitry Andric Text += '\''; 38462cfcf62SDimitry Andric if (!DWPName.empty()) { 38562cfcf62SDimitry Andric Text += " (from "; 38662cfcf62SDimitry Andric if (!DWOName.empty()) { 38762cfcf62SDimitry Andric Text += '\''; 38862cfcf62SDimitry Andric Text += DWOName; 38962cfcf62SDimitry Andric Text += "' in "; 39062cfcf62SDimitry Andric } 39162cfcf62SDimitry Andric Text += '\''; 39262cfcf62SDimitry Andric Text += DWPName; 39362cfcf62SDimitry Andric Text += "')"; 39462cfcf62SDimitry Andric } 39562cfcf62SDimitry Andric return Text; 39662cfcf62SDimitry Andric } 39762cfcf62SDimitry Andric 39862cfcf62SDimitry Andric static Error createError(StringRef Name, Error E) { 39962cfcf62SDimitry Andric return make_error<DWPError>( 40062cfcf62SDimitry Andric ("failure while decompressing compressed section: '" + Name + "', " + 40162cfcf62SDimitry Andric llvm::toString(std::move(E))) 40262cfcf62SDimitry Andric .str()); 40362cfcf62SDimitry Andric } 40462cfcf62SDimitry Andric 40562cfcf62SDimitry Andric static Error 40662cfcf62SDimitry Andric handleCompressedSection(std::deque<SmallString<32>> &UncompressedSections, 40762cfcf62SDimitry Andric StringRef &Name, StringRef &Contents) { 40862cfcf62SDimitry Andric if (!Decompressor::isGnuStyle(Name)) 40962cfcf62SDimitry Andric return Error::success(); 41062cfcf62SDimitry Andric 41162cfcf62SDimitry Andric Expected<Decompressor> Dec = 41262cfcf62SDimitry Andric Decompressor::create(Name, Contents, false /*IsLE*/, false /*Is64Bit*/); 41362cfcf62SDimitry Andric if (!Dec) 41462cfcf62SDimitry Andric return createError(Name, Dec.takeError()); 41562cfcf62SDimitry Andric 41662cfcf62SDimitry Andric UncompressedSections.emplace_back(); 41762cfcf62SDimitry Andric if (Error E = Dec->resizeAndDecompress(UncompressedSections.back())) 41862cfcf62SDimitry Andric return createError(Name, std::move(E)); 41962cfcf62SDimitry Andric 42062cfcf62SDimitry Andric Name = Name.substr(2); // Drop ".z" 42162cfcf62SDimitry Andric Contents = UncompressedSections.back(); 42262cfcf62SDimitry Andric return Error::success(); 42362cfcf62SDimitry Andric } 42462cfcf62SDimitry Andric 42562cfcf62SDimitry Andric static Error handleSection( 42662cfcf62SDimitry Andric const StringMap<std::pair<MCSection *, DWARFSectionKind>> &KnownSections, 42762cfcf62SDimitry Andric const MCSection *StrSection, const MCSection *StrOffsetSection, 42862cfcf62SDimitry Andric const MCSection *TypesSection, const MCSection *CUIndexSection, 42962cfcf62SDimitry Andric const MCSection *TUIndexSection, const SectionRef &Section, MCStreamer &Out, 43062cfcf62SDimitry Andric std::deque<SmallString<32>> &UncompressedSections, 43162cfcf62SDimitry Andric uint32_t (&ContributionOffsets)[8], UnitIndexEntry &CurEntry, 43262cfcf62SDimitry Andric StringRef &CurStrSection, StringRef &CurStrOffsetSection, 43362cfcf62SDimitry Andric std::vector<StringRef> &CurTypesSection, StringRef &InfoSection, 43462cfcf62SDimitry Andric StringRef &AbbrevSection, StringRef &CurCUIndexSection, 43562cfcf62SDimitry Andric StringRef &CurTUIndexSection) { 43662cfcf62SDimitry Andric if (Section.isBSS()) 43762cfcf62SDimitry Andric return Error::success(); 43862cfcf62SDimitry Andric 43962cfcf62SDimitry Andric if (Section.isVirtual()) 44062cfcf62SDimitry Andric return Error::success(); 44162cfcf62SDimitry Andric 44262cfcf62SDimitry Andric Expected<StringRef> NameOrErr = Section.getName(); 44362cfcf62SDimitry Andric if (!NameOrErr) 44462cfcf62SDimitry Andric return NameOrErr.takeError(); 44562cfcf62SDimitry Andric StringRef Name = *NameOrErr; 44662cfcf62SDimitry Andric 44762cfcf62SDimitry Andric Expected<StringRef> ContentsOrErr = Section.getContents(); 44862cfcf62SDimitry Andric if (!ContentsOrErr) 44962cfcf62SDimitry Andric return ContentsOrErr.takeError(); 45062cfcf62SDimitry Andric StringRef Contents = *ContentsOrErr; 45162cfcf62SDimitry Andric 45262cfcf62SDimitry Andric if (auto Err = handleCompressedSection(UncompressedSections, Name, Contents)) 45362cfcf62SDimitry Andric return Err; 45462cfcf62SDimitry Andric 45562cfcf62SDimitry Andric Name = Name.substr(Name.find_first_not_of("._")); 45662cfcf62SDimitry Andric 45762cfcf62SDimitry Andric auto SectionPair = KnownSections.find(Name); 45862cfcf62SDimitry Andric if (SectionPair == KnownSections.end()) 45962cfcf62SDimitry Andric return Error::success(); 46062cfcf62SDimitry Andric 46162cfcf62SDimitry Andric if (DWARFSectionKind Kind = SectionPair->second.second) { 462*5ffd83dbSDimitry Andric auto Index = getContributionIndex(Kind); 463*5ffd83dbSDimitry Andric if (Kind != DW_SECT_EXT_TYPES) { 46462cfcf62SDimitry Andric CurEntry.Contributions[Index].Offset = ContributionOffsets[Index]; 46562cfcf62SDimitry Andric ContributionOffsets[Index] += 46662cfcf62SDimitry Andric (CurEntry.Contributions[Index].Length = Contents.size()); 46762cfcf62SDimitry Andric } 46862cfcf62SDimitry Andric 46962cfcf62SDimitry Andric switch (Kind) { 47062cfcf62SDimitry Andric case DW_SECT_INFO: 47162cfcf62SDimitry Andric InfoSection = Contents; 47262cfcf62SDimitry Andric break; 47362cfcf62SDimitry Andric case DW_SECT_ABBREV: 47462cfcf62SDimitry Andric AbbrevSection = Contents; 47562cfcf62SDimitry Andric break; 47662cfcf62SDimitry Andric default: 47762cfcf62SDimitry Andric break; 47862cfcf62SDimitry Andric } 47962cfcf62SDimitry Andric } 48062cfcf62SDimitry Andric 48162cfcf62SDimitry Andric MCSection *OutSection = SectionPair->second.first; 48262cfcf62SDimitry Andric if (OutSection == StrOffsetSection) 48362cfcf62SDimitry Andric CurStrOffsetSection = Contents; 48462cfcf62SDimitry Andric else if (OutSection == StrSection) 48562cfcf62SDimitry Andric CurStrSection = Contents; 48662cfcf62SDimitry Andric else if (OutSection == TypesSection) 48762cfcf62SDimitry Andric CurTypesSection.push_back(Contents); 48862cfcf62SDimitry Andric else if (OutSection == CUIndexSection) 48962cfcf62SDimitry Andric CurCUIndexSection = Contents; 49062cfcf62SDimitry Andric else if (OutSection == TUIndexSection) 49162cfcf62SDimitry Andric CurTUIndexSection = Contents; 49262cfcf62SDimitry Andric else { 49362cfcf62SDimitry Andric Out.SwitchSection(OutSection); 494*5ffd83dbSDimitry Andric Out.emitBytes(Contents); 49562cfcf62SDimitry Andric } 49662cfcf62SDimitry Andric return Error::success(); 49762cfcf62SDimitry Andric } 49862cfcf62SDimitry Andric 49962cfcf62SDimitry Andric static Error 50062cfcf62SDimitry Andric buildDuplicateError(const std::pair<uint64_t, UnitIndexEntry> &PrevE, 50162cfcf62SDimitry Andric const CompileUnitIdentifiers &ID, StringRef DWPName) { 50262cfcf62SDimitry Andric return make_error<DWPError>( 503*5ffd83dbSDimitry Andric std::string("duplicate DWO ID (") + utohexstr(PrevE.first) + ") in " + 50462cfcf62SDimitry Andric buildDWODescription(PrevE.second.Name, PrevE.second.DWPName, 50562cfcf62SDimitry Andric PrevE.second.DWOName) + 50662cfcf62SDimitry Andric " and " + buildDWODescription(ID.Name, DWPName, ID.DWOName)); 50762cfcf62SDimitry Andric } 50862cfcf62SDimitry Andric 50962cfcf62SDimitry Andric static Expected<SmallVector<std::string, 16>> 51062cfcf62SDimitry Andric getDWOFilenames(StringRef ExecFilename) { 51162cfcf62SDimitry Andric auto ErrOrObj = object::ObjectFile::createObjectFile(ExecFilename); 51262cfcf62SDimitry Andric if (!ErrOrObj) 51362cfcf62SDimitry Andric return ErrOrObj.takeError(); 51462cfcf62SDimitry Andric 51562cfcf62SDimitry Andric const ObjectFile &Obj = *ErrOrObj.get().getBinary(); 51662cfcf62SDimitry Andric std::unique_ptr<DWARFContext> DWARFCtx = DWARFContext::create(Obj); 51762cfcf62SDimitry Andric 51862cfcf62SDimitry Andric SmallVector<std::string, 16> DWOPaths; 51962cfcf62SDimitry Andric for (const auto &CU : DWARFCtx->compile_units()) { 52062cfcf62SDimitry Andric const DWARFDie &Die = CU->getUnitDIE(); 52162cfcf62SDimitry Andric std::string DWOName = dwarf::toString( 52262cfcf62SDimitry Andric Die.find({dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}), ""); 52362cfcf62SDimitry Andric if (DWOName.empty()) 52462cfcf62SDimitry Andric continue; 52562cfcf62SDimitry Andric std::string DWOCompDir = 52662cfcf62SDimitry Andric dwarf::toString(Die.find(dwarf::DW_AT_comp_dir), ""); 52762cfcf62SDimitry Andric if (!DWOCompDir.empty()) { 52862cfcf62SDimitry Andric SmallString<16> DWOPath; 52962cfcf62SDimitry Andric sys::path::append(DWOPath, DWOCompDir, DWOName); 53062cfcf62SDimitry Andric DWOPaths.emplace_back(DWOPath.data(), DWOPath.size()); 53162cfcf62SDimitry Andric } else { 53262cfcf62SDimitry Andric DWOPaths.push_back(std::move(DWOName)); 53362cfcf62SDimitry Andric } 53462cfcf62SDimitry Andric } 53562cfcf62SDimitry Andric return std::move(DWOPaths); 53662cfcf62SDimitry Andric } 53762cfcf62SDimitry Andric 53862cfcf62SDimitry Andric static Error write(MCStreamer &Out, ArrayRef<std::string> Inputs) { 53962cfcf62SDimitry Andric const auto &MCOFI = *Out.getContext().getObjectFileInfo(); 54062cfcf62SDimitry Andric MCSection *const StrSection = MCOFI.getDwarfStrDWOSection(); 54162cfcf62SDimitry Andric MCSection *const StrOffsetSection = MCOFI.getDwarfStrOffDWOSection(); 54262cfcf62SDimitry Andric MCSection *const TypesSection = MCOFI.getDwarfTypesDWOSection(); 54362cfcf62SDimitry Andric MCSection *const CUIndexSection = MCOFI.getDwarfCUIndexSection(); 54462cfcf62SDimitry Andric MCSection *const TUIndexSection = MCOFI.getDwarfTUIndexSection(); 54562cfcf62SDimitry Andric const StringMap<std::pair<MCSection *, DWARFSectionKind>> KnownSections = { 54662cfcf62SDimitry Andric {"debug_info.dwo", {MCOFI.getDwarfInfoDWOSection(), DW_SECT_INFO}}, 547*5ffd83dbSDimitry Andric {"debug_types.dwo", {MCOFI.getDwarfTypesDWOSection(), DW_SECT_EXT_TYPES}}, 54862cfcf62SDimitry Andric {"debug_str_offsets.dwo", {StrOffsetSection, DW_SECT_STR_OFFSETS}}, 54962cfcf62SDimitry Andric {"debug_str.dwo", {StrSection, static_cast<DWARFSectionKind>(0)}}, 550*5ffd83dbSDimitry Andric {"debug_loc.dwo", {MCOFI.getDwarfLocDWOSection(), DW_SECT_EXT_LOC}}, 55162cfcf62SDimitry Andric {"debug_line.dwo", {MCOFI.getDwarfLineDWOSection(), DW_SECT_LINE}}, 55262cfcf62SDimitry Andric {"debug_abbrev.dwo", {MCOFI.getDwarfAbbrevDWOSection(), DW_SECT_ABBREV}}, 55362cfcf62SDimitry Andric {"debug_cu_index", {CUIndexSection, static_cast<DWARFSectionKind>(0)}}, 55462cfcf62SDimitry Andric {"debug_tu_index", {TUIndexSection, static_cast<DWARFSectionKind>(0)}}}; 55562cfcf62SDimitry Andric 55662cfcf62SDimitry Andric MapVector<uint64_t, UnitIndexEntry> IndexEntries; 55762cfcf62SDimitry Andric MapVector<uint64_t, UnitIndexEntry> TypeIndexEntries; 55862cfcf62SDimitry Andric 55962cfcf62SDimitry Andric uint32_t ContributionOffsets[8] = {}; 56062cfcf62SDimitry Andric 56162cfcf62SDimitry Andric DWPStringPool Strings(Out, StrSection); 56262cfcf62SDimitry Andric 56362cfcf62SDimitry Andric SmallVector<OwningBinary<object::ObjectFile>, 128> Objects; 56462cfcf62SDimitry Andric Objects.reserve(Inputs.size()); 56562cfcf62SDimitry Andric 56662cfcf62SDimitry Andric std::deque<SmallString<32>> UncompressedSections; 56762cfcf62SDimitry Andric 56862cfcf62SDimitry Andric for (const auto &Input : Inputs) { 56962cfcf62SDimitry Andric auto ErrOrObj = object::ObjectFile::createObjectFile(Input); 57062cfcf62SDimitry Andric if (!ErrOrObj) 57162cfcf62SDimitry Andric return ErrOrObj.takeError(); 57262cfcf62SDimitry Andric 57362cfcf62SDimitry Andric auto &Obj = *ErrOrObj->getBinary(); 57462cfcf62SDimitry Andric Objects.push_back(std::move(*ErrOrObj)); 57562cfcf62SDimitry Andric 57662cfcf62SDimitry Andric UnitIndexEntry CurEntry = {}; 57762cfcf62SDimitry Andric 57862cfcf62SDimitry Andric StringRef CurStrSection; 57962cfcf62SDimitry Andric StringRef CurStrOffsetSection; 58062cfcf62SDimitry Andric std::vector<StringRef> CurTypesSection; 58162cfcf62SDimitry Andric StringRef InfoSection; 58262cfcf62SDimitry Andric StringRef AbbrevSection; 58362cfcf62SDimitry Andric StringRef CurCUIndexSection; 58462cfcf62SDimitry Andric StringRef CurTUIndexSection; 58562cfcf62SDimitry Andric 58662cfcf62SDimitry Andric for (const auto &Section : Obj.sections()) 58762cfcf62SDimitry Andric if (auto Err = handleSection( 58862cfcf62SDimitry Andric KnownSections, StrSection, StrOffsetSection, TypesSection, 58962cfcf62SDimitry Andric CUIndexSection, TUIndexSection, Section, Out, 59062cfcf62SDimitry Andric UncompressedSections, ContributionOffsets, CurEntry, 59162cfcf62SDimitry Andric CurStrSection, CurStrOffsetSection, CurTypesSection, InfoSection, 59262cfcf62SDimitry Andric AbbrevSection, CurCUIndexSection, CurTUIndexSection)) 59362cfcf62SDimitry Andric return Err; 59462cfcf62SDimitry Andric 59562cfcf62SDimitry Andric if (InfoSection.empty()) 59662cfcf62SDimitry Andric continue; 59762cfcf62SDimitry Andric 59862cfcf62SDimitry Andric writeStringsAndOffsets(Out, Strings, StrOffsetSection, CurStrSection, 59962cfcf62SDimitry Andric CurStrOffsetSection); 60062cfcf62SDimitry Andric 60162cfcf62SDimitry Andric if (CurCUIndexSection.empty()) { 60262cfcf62SDimitry Andric Expected<CompileUnitIdentifiers> EID = getCUIdentifiers( 60362cfcf62SDimitry Andric AbbrevSection, InfoSection, CurStrOffsetSection, CurStrSection); 60462cfcf62SDimitry Andric if (!EID) 60562cfcf62SDimitry Andric return createFileError(Input, EID.takeError()); 60662cfcf62SDimitry Andric const auto &ID = *EID; 60762cfcf62SDimitry Andric auto P = IndexEntries.insert(std::make_pair(ID.Signature, CurEntry)); 60862cfcf62SDimitry Andric if (!P.second) 60962cfcf62SDimitry Andric return buildDuplicateError(*P.first, ID, ""); 61062cfcf62SDimitry Andric P.first->second.Name = ID.Name; 61162cfcf62SDimitry Andric P.first->second.DWOName = ID.DWOName; 61262cfcf62SDimitry Andric addAllTypes(Out, TypeIndexEntries, TypesSection, CurTypesSection, 613*5ffd83dbSDimitry Andric CurEntry, 614*5ffd83dbSDimitry Andric ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES)]); 61562cfcf62SDimitry Andric continue; 61662cfcf62SDimitry Andric } 61762cfcf62SDimitry Andric 61862cfcf62SDimitry Andric DWARFUnitIndex CUIndex(DW_SECT_INFO); 61962cfcf62SDimitry Andric DataExtractor CUIndexData(CurCUIndexSection, Obj.isLittleEndian(), 0); 62062cfcf62SDimitry Andric if (!CUIndex.parse(CUIndexData)) 621*5ffd83dbSDimitry Andric return make_error<DWPError>("failed to parse cu_index"); 622*5ffd83dbSDimitry Andric if (CUIndex.getVersion() != 2) 623*5ffd83dbSDimitry Andric return make_error<DWPError>( 624*5ffd83dbSDimitry Andric "unsupported cu_index version: " + utostr(CUIndex.getVersion()) + 625*5ffd83dbSDimitry Andric " (only version 2 is supported)"); 62662cfcf62SDimitry Andric 62762cfcf62SDimitry Andric for (const DWARFUnitIndex::Entry &E : CUIndex.getRows()) { 628*5ffd83dbSDimitry Andric auto *I = E.getContributions(); 62962cfcf62SDimitry Andric if (!I) 63062cfcf62SDimitry Andric continue; 63162cfcf62SDimitry Andric auto P = IndexEntries.insert(std::make_pair(E.getSignature(), CurEntry)); 63262cfcf62SDimitry Andric Expected<CompileUnitIdentifiers> EID = getCUIdentifiers( 63362cfcf62SDimitry Andric getSubsection(AbbrevSection, E, DW_SECT_ABBREV), 63462cfcf62SDimitry Andric getSubsection(InfoSection, E, DW_SECT_INFO), 63562cfcf62SDimitry Andric getSubsection(CurStrOffsetSection, E, DW_SECT_STR_OFFSETS), 63662cfcf62SDimitry Andric CurStrSection); 63762cfcf62SDimitry Andric if (!EID) 63862cfcf62SDimitry Andric return createFileError(Input, EID.takeError()); 63962cfcf62SDimitry Andric const auto &ID = *EID; 64062cfcf62SDimitry Andric if (!P.second) 64162cfcf62SDimitry Andric return buildDuplicateError(*P.first, ID, Input); 64262cfcf62SDimitry Andric auto &NewEntry = P.first->second; 64362cfcf62SDimitry Andric NewEntry.Name = ID.Name; 64462cfcf62SDimitry Andric NewEntry.DWOName = ID.DWOName; 64562cfcf62SDimitry Andric NewEntry.DWPName = Input; 64662cfcf62SDimitry Andric for (auto Kind : CUIndex.getColumnKinds()) { 647*5ffd83dbSDimitry Andric if (!isSupportedSectionKind(Kind)) 648*5ffd83dbSDimitry Andric continue; 649*5ffd83dbSDimitry Andric auto &C = NewEntry.Contributions[getContributionIndex(Kind)]; 65062cfcf62SDimitry Andric C.Offset += I->Offset; 65162cfcf62SDimitry Andric C.Length = I->Length; 65262cfcf62SDimitry Andric ++I; 65362cfcf62SDimitry Andric } 65462cfcf62SDimitry Andric } 65562cfcf62SDimitry Andric 65662cfcf62SDimitry Andric if (!CurTypesSection.empty()) { 65762cfcf62SDimitry Andric if (CurTypesSection.size() != 1) 65862cfcf62SDimitry Andric return make_error<DWPError>("multiple type unit sections in .dwp file"); 659*5ffd83dbSDimitry Andric DWARFUnitIndex TUIndex(DW_SECT_EXT_TYPES); 66062cfcf62SDimitry Andric DataExtractor TUIndexData(CurTUIndexSection, Obj.isLittleEndian(), 0); 66162cfcf62SDimitry Andric if (!TUIndex.parse(TUIndexData)) 662*5ffd83dbSDimitry Andric return make_error<DWPError>("failed to parse tu_index"); 663*5ffd83dbSDimitry Andric if (TUIndex.getVersion() != 2) 664*5ffd83dbSDimitry Andric return make_error<DWPError>( 665*5ffd83dbSDimitry Andric "unsupported tu_index version: " + utostr(TUIndex.getVersion()) + 666*5ffd83dbSDimitry Andric " (only version 2 is supported)"); 667*5ffd83dbSDimitry Andric 668*5ffd83dbSDimitry Andric addAllTypesFromDWP( 669*5ffd83dbSDimitry Andric Out, TypeIndexEntries, TUIndex, TypesSection, CurTypesSection.front(), 670*5ffd83dbSDimitry Andric CurEntry, 671*5ffd83dbSDimitry Andric ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES)]); 67262cfcf62SDimitry Andric } 67362cfcf62SDimitry Andric } 67462cfcf62SDimitry Andric 67562cfcf62SDimitry Andric // Lie about there being no info contributions so the TU index only includes 67662cfcf62SDimitry Andric // the type unit contribution 67762cfcf62SDimitry Andric ContributionOffsets[0] = 0; 67862cfcf62SDimitry Andric writeIndex(Out, MCOFI.getDwarfTUIndexSection(), ContributionOffsets, 67962cfcf62SDimitry Andric TypeIndexEntries); 68062cfcf62SDimitry Andric 68162cfcf62SDimitry Andric // Lie about the type contribution 682*5ffd83dbSDimitry Andric ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES)] = 0; 68362cfcf62SDimitry Andric // Unlie about the info contribution 68462cfcf62SDimitry Andric ContributionOffsets[0] = 1; 68562cfcf62SDimitry Andric 68662cfcf62SDimitry Andric writeIndex(Out, MCOFI.getDwarfCUIndexSection(), ContributionOffsets, 68762cfcf62SDimitry Andric IndexEntries); 68862cfcf62SDimitry Andric 68962cfcf62SDimitry Andric return Error::success(); 69062cfcf62SDimitry Andric } 69162cfcf62SDimitry Andric 69262cfcf62SDimitry Andric static int error(const Twine &Error, const Twine &Context) { 69362cfcf62SDimitry Andric errs() << Twine("while processing ") + Context + ":\n"; 69462cfcf62SDimitry Andric errs() << Twine("error: ") + Error + "\n"; 69562cfcf62SDimitry Andric return 1; 69662cfcf62SDimitry Andric } 69762cfcf62SDimitry Andric 69862cfcf62SDimitry Andric int main(int argc, char **argv) { 69962cfcf62SDimitry Andric InitLLVM X(argc, argv); 70062cfcf62SDimitry Andric 70162cfcf62SDimitry Andric cl::ParseCommandLineOptions(argc, argv, "merge split dwarf (.dwo) files\n"); 70262cfcf62SDimitry Andric 70362cfcf62SDimitry Andric llvm::InitializeAllTargetInfos(); 70462cfcf62SDimitry Andric llvm::InitializeAllTargetMCs(); 70562cfcf62SDimitry Andric llvm::InitializeAllTargets(); 70662cfcf62SDimitry Andric llvm::InitializeAllAsmPrinters(); 70762cfcf62SDimitry Andric 70862cfcf62SDimitry Andric std::string ErrorStr; 70962cfcf62SDimitry Andric StringRef Context = "dwarf streamer init"; 71062cfcf62SDimitry Andric 71162cfcf62SDimitry Andric Triple TheTriple("x86_64-linux-gnu"); 71262cfcf62SDimitry Andric 71362cfcf62SDimitry Andric // Get the target. 71462cfcf62SDimitry Andric const Target *TheTarget = 71562cfcf62SDimitry Andric TargetRegistry::lookupTarget("", TheTriple, ErrorStr); 71662cfcf62SDimitry Andric if (!TheTarget) 71762cfcf62SDimitry Andric return error(ErrorStr, Context); 71862cfcf62SDimitry Andric std::string TripleName = TheTriple.getTriple(); 71962cfcf62SDimitry Andric 72062cfcf62SDimitry Andric // Create all the MC Objects. 72162cfcf62SDimitry Andric std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName)); 72262cfcf62SDimitry Andric if (!MRI) 72362cfcf62SDimitry Andric return error(Twine("no register info for target ") + TripleName, Context); 72462cfcf62SDimitry Andric 725*5ffd83dbSDimitry Andric MCTargetOptions MCOptions = llvm::mc::InitMCTargetOptionsFromFlags(); 72662cfcf62SDimitry Andric std::unique_ptr<MCAsmInfo> MAI( 72762cfcf62SDimitry Andric TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions)); 72862cfcf62SDimitry Andric if (!MAI) 72962cfcf62SDimitry Andric return error("no asm info for target " + TripleName, Context); 73062cfcf62SDimitry Andric 73162cfcf62SDimitry Andric MCObjectFileInfo MOFI; 73262cfcf62SDimitry Andric MCContext MC(MAI.get(), MRI.get(), &MOFI); 73362cfcf62SDimitry Andric MOFI.InitMCObjectFileInfo(TheTriple, /*PIC*/ false, MC); 73462cfcf62SDimitry Andric 73562cfcf62SDimitry Andric std::unique_ptr<MCSubtargetInfo> MSTI( 73662cfcf62SDimitry Andric TheTarget->createMCSubtargetInfo(TripleName, "", "")); 73762cfcf62SDimitry Andric if (!MSTI) 73862cfcf62SDimitry Andric return error("no subtarget info for target " + TripleName, Context); 73962cfcf62SDimitry Andric 74062cfcf62SDimitry Andric MCTargetOptions Options; 74162cfcf62SDimitry Andric auto MAB = TheTarget->createMCAsmBackend(*MSTI, *MRI, Options); 74262cfcf62SDimitry Andric if (!MAB) 74362cfcf62SDimitry Andric return error("no asm backend for target " + TripleName, Context); 74462cfcf62SDimitry Andric 74562cfcf62SDimitry Andric std::unique_ptr<MCInstrInfo> MII(TheTarget->createMCInstrInfo()); 74662cfcf62SDimitry Andric if (!MII) 74762cfcf62SDimitry Andric return error("no instr info info for target " + TripleName, Context); 74862cfcf62SDimitry Andric 74962cfcf62SDimitry Andric MCCodeEmitter *MCE = TheTarget->createMCCodeEmitter(*MII, *MRI, MC); 75062cfcf62SDimitry Andric if (!MCE) 75162cfcf62SDimitry Andric return error("no code emitter for target " + TripleName, Context); 75262cfcf62SDimitry Andric 75362cfcf62SDimitry Andric // Create the output file. 75462cfcf62SDimitry Andric std::error_code EC; 75562cfcf62SDimitry Andric ToolOutputFile OutFile(OutputFilename, EC, sys::fs::OF_None); 75662cfcf62SDimitry Andric Optional<buffer_ostream> BOS; 75762cfcf62SDimitry Andric raw_pwrite_stream *OS; 75862cfcf62SDimitry Andric if (EC) 75962cfcf62SDimitry Andric return error(Twine(OutputFilename) + ": " + EC.message(), Context); 76062cfcf62SDimitry Andric if (OutFile.os().supportsSeeking()) { 76162cfcf62SDimitry Andric OS = &OutFile.os(); 76262cfcf62SDimitry Andric } else { 76362cfcf62SDimitry Andric BOS.emplace(OutFile.os()); 76462cfcf62SDimitry Andric OS = BOS.getPointer(); 76562cfcf62SDimitry Andric } 76662cfcf62SDimitry Andric 76762cfcf62SDimitry Andric std::unique_ptr<MCStreamer> MS(TheTarget->createMCObjectStreamer( 76862cfcf62SDimitry Andric TheTriple, MC, std::unique_ptr<MCAsmBackend>(MAB), 76962cfcf62SDimitry Andric MAB->createObjectWriter(*OS), std::unique_ptr<MCCodeEmitter>(MCE), *MSTI, 77062cfcf62SDimitry Andric MCOptions.MCRelaxAll, MCOptions.MCIncrementalLinkerCompatible, 77162cfcf62SDimitry Andric /*DWARFMustBeAtTheEnd*/ false)); 77262cfcf62SDimitry Andric if (!MS) 77362cfcf62SDimitry Andric return error("no object streamer for target " + TripleName, Context); 77462cfcf62SDimitry Andric 77562cfcf62SDimitry Andric std::vector<std::string> DWOFilenames = InputFiles; 77662cfcf62SDimitry Andric for (const auto &ExecFilename : ExecFilenames) { 77762cfcf62SDimitry Andric auto DWOs = getDWOFilenames(ExecFilename); 77862cfcf62SDimitry Andric if (!DWOs) { 77962cfcf62SDimitry Andric logAllUnhandledErrors(DWOs.takeError(), WithColor::error()); 78062cfcf62SDimitry Andric return 1; 78162cfcf62SDimitry Andric } 78262cfcf62SDimitry Andric DWOFilenames.insert(DWOFilenames.end(), 78362cfcf62SDimitry Andric std::make_move_iterator(DWOs->begin()), 78462cfcf62SDimitry Andric std::make_move_iterator(DWOs->end())); 78562cfcf62SDimitry Andric } 78662cfcf62SDimitry Andric 78762cfcf62SDimitry Andric if (auto Err = write(*MS, DWOFilenames)) { 78862cfcf62SDimitry Andric logAllUnhandledErrors(std::move(Err), WithColor::error()); 78962cfcf62SDimitry Andric return 1; 79062cfcf62SDimitry Andric } 79162cfcf62SDimitry Andric 79262cfcf62SDimitry Andric MS->Finish(); 79362cfcf62SDimitry Andric OutFile.keep(); 79462cfcf62SDimitry Andric return 0; 79562cfcf62SDimitry Andric } 796