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" 305ffd83dbSDimitry Andric #include "llvm/MC/MCTargetOptionsCommandFlags.h" 3162cfcf62SDimitry Andric #include "llvm/Object/Decompressor.h" 3262cfcf62SDimitry Andric #include "llvm/Object/ObjectFile.h" 335ffd83dbSDimitry 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 505ffd83dbSDimitry Andric static mc::RegisterMCTargetOptionsFlags MCTargetOptionsFlags; 515ffd83dbSDimitry 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]; 965ffd83dbSDimitry 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); 1465ffd83dbSDimitry Andric CompileUnitIdentifiers ID; 1475ffd83dbSDimitry 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); 1555ffd83dbSDimitry Andric if (Version >= 5) { 1565ffd83dbSDimitry Andric auto UnitType = InfoData.getU8(&Offset); 1575ffd83dbSDimitry Andric if (UnitType != dwarf::DW_UT_split_compile) 1585ffd83dbSDimitry Andric return make_error<DWPError>( 1595ffd83dbSDimitry Andric std::string("unit type DW_UT_split_compile type not found in " 1605ffd83dbSDimitry Andric "debug_info header. Unexpected unit type 0x" + 1615ffd83dbSDimitry Andric utostr(UnitType) + " found")); 1625ffd83dbSDimitry Andric } 16362cfcf62SDimitry Andric InfoData.getU32(&Offset); // Abbrev offset (should be zero) 16462cfcf62SDimitry Andric uint8_t AddrSize = InfoData.getU8(&Offset); 1655ffd83dbSDimitry Andric if (Version >= 5) 1665ffd83dbSDimitry 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 } 1905ffd83dbSDimitry Andric case dwarf::DW_AT_GNU_dwo_name: 1915ffd83dbSDimitry 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 2205ffd83dbSDimitry Andric static bool isSupportedSectionKind(DWARFSectionKind Kind) { 2215ffd83dbSDimitry Andric return Kind != DW_SECT_EXT_unknown; 2225ffd83dbSDimitry Andric } 2235ffd83dbSDimitry Andric 2245ffd83dbSDimitry Andric // Convert an internal section identifier into the index to use with 2255ffd83dbSDimitry Andric // UnitIndexEntry::Contributions. 2265ffd83dbSDimitry Andric static unsigned getContributionIndex(DWARFSectionKind Kind) { 2275ffd83dbSDimitry Andric // Assuming the pre-standard DWP format. 2285ffd83dbSDimitry Andric assert(serializeSectionKind(Kind, 2) >= DW_SECT_INFO); 2295ffd83dbSDimitry Andric return serializeSectionKind(Kind, 2) - DW_SECT_INFO; 2305ffd83dbSDimitry Andric } 2315ffd83dbSDimitry Andric 2325ffd83dbSDimitry Andric // Convert a UnitIndexEntry::Contributions index to the corresponding on-disk 2335ffd83dbSDimitry Andric // value of the section identifier. 2345ffd83dbSDimitry Andric static unsigned getOnDiskSectionId(unsigned Index) { 2355ffd83dbSDimitry Andric return Index + DW_SECT_INFO; 2365ffd83dbSDimitry Andric } 2375ffd83dbSDimitry Andric 23862cfcf62SDimitry Andric static StringRef getSubsection(StringRef Section, 23962cfcf62SDimitry Andric const DWARFUnitIndex::Entry &Entry, 24062cfcf62SDimitry Andric DWARFSectionKind Kind) { 2415ffd83dbSDimitry 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()) { 2535ffd83dbSDimitry 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()) { 2635ffd83dbSDimitry Andric if (!isSupportedSectionKind(Kind)) 2645ffd83dbSDimitry Andric continue; 2655ffd83dbSDimitry Andric auto &C = Entry.Contributions[getContributionIndex(Kind)]; 26662cfcf62SDimitry Andric C.Offset += I->Offset; 26762cfcf62SDimitry Andric C.Length = I->Length; 26862cfcf62SDimitry Andric ++I; 26962cfcf62SDimitry Andric } 2705ffd83dbSDimitry Andric unsigned TypesIndex = getContributionIndex(DW_SECT_EXT_TYPES); 2715ffd83dbSDimitry Andric auto &C = Entry.Contributions[TypesIndex]; 2725ffd83dbSDimitry Andric Out.emitBytes(Types.substr( 2735ffd83dbSDimitry 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] = {}; 2925ffd83dbSDimitry 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 3085ffd83dbSDimitry 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]) 3215ffd83dbSDimitry 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); 3535ffd83dbSDimitry Andric Out.emitIntValue(2, 4); // Version 3545ffd83dbSDimitry Andric Out.emitIntValue(Columns, 4); // Columns 3555ffd83dbSDimitry Andric Out.emitIntValue(IndexEntries.size(), 4); // Num Units 3565ffd83dbSDimitry Andric Out.emitIntValue(Buckets.size(), 4); // Num Buckets 35762cfcf62SDimitry Andric 35862cfcf62SDimitry Andric // Write the signatures. 35962cfcf62SDimitry Andric for (const auto &I : Buckets) 3605ffd83dbSDimitry 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) 3645ffd83dbSDimitry 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]) 3695ffd83dbSDimitry 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 380e8d8bef9SDimitry Andric static std::string buildDWODescription(StringRef Name, StringRef DWPName, 381e8d8bef9SDimitry Andric StringRef DWOName) { 38262cfcf62SDimitry Andric std::string Text = "\'"; 38362cfcf62SDimitry Andric Text += Name; 38462cfcf62SDimitry Andric Text += '\''; 38562cfcf62SDimitry Andric if (!DWPName.empty()) { 38662cfcf62SDimitry Andric Text += " (from "; 38762cfcf62SDimitry Andric if (!DWOName.empty()) { 38862cfcf62SDimitry Andric Text += '\''; 38962cfcf62SDimitry Andric Text += DWOName; 39062cfcf62SDimitry Andric Text += "' in "; 39162cfcf62SDimitry Andric } 39262cfcf62SDimitry Andric Text += '\''; 39362cfcf62SDimitry Andric Text += DWPName; 39462cfcf62SDimitry Andric Text += "')"; 39562cfcf62SDimitry Andric } 39662cfcf62SDimitry Andric return Text; 39762cfcf62SDimitry Andric } 39862cfcf62SDimitry Andric 39962cfcf62SDimitry Andric static Error createError(StringRef Name, Error E) { 40062cfcf62SDimitry Andric return make_error<DWPError>( 40162cfcf62SDimitry Andric ("failure while decompressing compressed section: '" + Name + "', " + 40262cfcf62SDimitry Andric llvm::toString(std::move(E))) 40362cfcf62SDimitry Andric .str()); 40462cfcf62SDimitry Andric } 40562cfcf62SDimitry Andric 40662cfcf62SDimitry Andric static Error 40762cfcf62SDimitry Andric handleCompressedSection(std::deque<SmallString<32>> &UncompressedSections, 40862cfcf62SDimitry Andric StringRef &Name, StringRef &Contents) { 40962cfcf62SDimitry Andric if (!Decompressor::isGnuStyle(Name)) 41062cfcf62SDimitry Andric return Error::success(); 41162cfcf62SDimitry Andric 41262cfcf62SDimitry Andric Expected<Decompressor> Dec = 41362cfcf62SDimitry Andric Decompressor::create(Name, Contents, false /*IsLE*/, false /*Is64Bit*/); 41462cfcf62SDimitry Andric if (!Dec) 41562cfcf62SDimitry Andric return createError(Name, Dec.takeError()); 41662cfcf62SDimitry Andric 41762cfcf62SDimitry Andric UncompressedSections.emplace_back(); 41862cfcf62SDimitry Andric if (Error E = Dec->resizeAndDecompress(UncompressedSections.back())) 41962cfcf62SDimitry Andric return createError(Name, std::move(E)); 42062cfcf62SDimitry Andric 42162cfcf62SDimitry Andric Name = Name.substr(2); // Drop ".z" 42262cfcf62SDimitry Andric Contents = UncompressedSections.back(); 42362cfcf62SDimitry Andric return Error::success(); 42462cfcf62SDimitry Andric } 42562cfcf62SDimitry Andric 42662cfcf62SDimitry Andric static Error handleSection( 42762cfcf62SDimitry Andric const StringMap<std::pair<MCSection *, DWARFSectionKind>> &KnownSections, 42862cfcf62SDimitry Andric const MCSection *StrSection, const MCSection *StrOffsetSection, 42962cfcf62SDimitry Andric const MCSection *TypesSection, const MCSection *CUIndexSection, 43062cfcf62SDimitry Andric const MCSection *TUIndexSection, const SectionRef &Section, MCStreamer &Out, 43162cfcf62SDimitry Andric std::deque<SmallString<32>> &UncompressedSections, 43262cfcf62SDimitry Andric uint32_t (&ContributionOffsets)[8], UnitIndexEntry &CurEntry, 43362cfcf62SDimitry Andric StringRef &CurStrSection, StringRef &CurStrOffsetSection, 43462cfcf62SDimitry Andric std::vector<StringRef> &CurTypesSection, StringRef &InfoSection, 43562cfcf62SDimitry Andric StringRef &AbbrevSection, StringRef &CurCUIndexSection, 43662cfcf62SDimitry Andric StringRef &CurTUIndexSection) { 43762cfcf62SDimitry Andric if (Section.isBSS()) 43862cfcf62SDimitry Andric return Error::success(); 43962cfcf62SDimitry Andric 44062cfcf62SDimitry Andric if (Section.isVirtual()) 44162cfcf62SDimitry Andric return Error::success(); 44262cfcf62SDimitry Andric 44362cfcf62SDimitry Andric Expected<StringRef> NameOrErr = Section.getName(); 44462cfcf62SDimitry Andric if (!NameOrErr) 44562cfcf62SDimitry Andric return NameOrErr.takeError(); 44662cfcf62SDimitry Andric StringRef Name = *NameOrErr; 44762cfcf62SDimitry Andric 44862cfcf62SDimitry Andric Expected<StringRef> ContentsOrErr = Section.getContents(); 44962cfcf62SDimitry Andric if (!ContentsOrErr) 45062cfcf62SDimitry Andric return ContentsOrErr.takeError(); 45162cfcf62SDimitry Andric StringRef Contents = *ContentsOrErr; 45262cfcf62SDimitry Andric 45362cfcf62SDimitry Andric if (auto Err = handleCompressedSection(UncompressedSections, Name, Contents)) 45462cfcf62SDimitry Andric return Err; 45562cfcf62SDimitry Andric 45662cfcf62SDimitry Andric Name = Name.substr(Name.find_first_not_of("._")); 45762cfcf62SDimitry Andric 45862cfcf62SDimitry Andric auto SectionPair = KnownSections.find(Name); 45962cfcf62SDimitry Andric if (SectionPair == KnownSections.end()) 46062cfcf62SDimitry Andric return Error::success(); 46162cfcf62SDimitry Andric 46262cfcf62SDimitry Andric if (DWARFSectionKind Kind = SectionPair->second.second) { 4635ffd83dbSDimitry Andric auto Index = getContributionIndex(Kind); 4645ffd83dbSDimitry Andric if (Kind != DW_SECT_EXT_TYPES) { 46562cfcf62SDimitry Andric CurEntry.Contributions[Index].Offset = ContributionOffsets[Index]; 46662cfcf62SDimitry Andric ContributionOffsets[Index] += 46762cfcf62SDimitry Andric (CurEntry.Contributions[Index].Length = Contents.size()); 46862cfcf62SDimitry Andric } 46962cfcf62SDimitry Andric 47062cfcf62SDimitry Andric switch (Kind) { 47162cfcf62SDimitry Andric case DW_SECT_INFO: 47262cfcf62SDimitry Andric InfoSection = Contents; 47362cfcf62SDimitry Andric break; 47462cfcf62SDimitry Andric case DW_SECT_ABBREV: 47562cfcf62SDimitry Andric AbbrevSection = Contents; 47662cfcf62SDimitry Andric break; 47762cfcf62SDimitry Andric default: 47862cfcf62SDimitry Andric break; 47962cfcf62SDimitry Andric } 48062cfcf62SDimitry Andric } 48162cfcf62SDimitry Andric 48262cfcf62SDimitry Andric MCSection *OutSection = SectionPair->second.first; 48362cfcf62SDimitry Andric if (OutSection == StrOffsetSection) 48462cfcf62SDimitry Andric CurStrOffsetSection = Contents; 48562cfcf62SDimitry Andric else if (OutSection == StrSection) 48662cfcf62SDimitry Andric CurStrSection = Contents; 48762cfcf62SDimitry Andric else if (OutSection == TypesSection) 48862cfcf62SDimitry Andric CurTypesSection.push_back(Contents); 48962cfcf62SDimitry Andric else if (OutSection == CUIndexSection) 49062cfcf62SDimitry Andric CurCUIndexSection = Contents; 49162cfcf62SDimitry Andric else if (OutSection == TUIndexSection) 49262cfcf62SDimitry Andric CurTUIndexSection = Contents; 49362cfcf62SDimitry Andric else { 49462cfcf62SDimitry Andric Out.SwitchSection(OutSection); 4955ffd83dbSDimitry Andric Out.emitBytes(Contents); 49662cfcf62SDimitry Andric } 49762cfcf62SDimitry Andric return Error::success(); 49862cfcf62SDimitry Andric } 49962cfcf62SDimitry Andric 50062cfcf62SDimitry Andric static Error 50162cfcf62SDimitry Andric buildDuplicateError(const std::pair<uint64_t, UnitIndexEntry> &PrevE, 50262cfcf62SDimitry Andric const CompileUnitIdentifiers &ID, StringRef DWPName) { 50362cfcf62SDimitry Andric return make_error<DWPError>( 5045ffd83dbSDimitry Andric std::string("duplicate DWO ID (") + utohexstr(PrevE.first) + ") in " + 50562cfcf62SDimitry Andric buildDWODescription(PrevE.second.Name, PrevE.second.DWPName, 50662cfcf62SDimitry Andric PrevE.second.DWOName) + 50762cfcf62SDimitry Andric " and " + buildDWODescription(ID.Name, DWPName, ID.DWOName)); 50862cfcf62SDimitry Andric } 50962cfcf62SDimitry Andric 51062cfcf62SDimitry Andric static Expected<SmallVector<std::string, 16>> 51162cfcf62SDimitry Andric getDWOFilenames(StringRef ExecFilename) { 51262cfcf62SDimitry Andric auto ErrOrObj = object::ObjectFile::createObjectFile(ExecFilename); 51362cfcf62SDimitry Andric if (!ErrOrObj) 51462cfcf62SDimitry Andric return ErrOrObj.takeError(); 51562cfcf62SDimitry Andric 51662cfcf62SDimitry Andric const ObjectFile &Obj = *ErrOrObj.get().getBinary(); 51762cfcf62SDimitry Andric std::unique_ptr<DWARFContext> DWARFCtx = DWARFContext::create(Obj); 51862cfcf62SDimitry Andric 51962cfcf62SDimitry Andric SmallVector<std::string, 16> DWOPaths; 52062cfcf62SDimitry Andric for (const auto &CU : DWARFCtx->compile_units()) { 52162cfcf62SDimitry Andric const DWARFDie &Die = CU->getUnitDIE(); 52262cfcf62SDimitry Andric std::string DWOName = dwarf::toString( 52362cfcf62SDimitry Andric Die.find({dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}), ""); 52462cfcf62SDimitry Andric if (DWOName.empty()) 52562cfcf62SDimitry Andric continue; 52662cfcf62SDimitry Andric std::string DWOCompDir = 52762cfcf62SDimitry Andric dwarf::toString(Die.find(dwarf::DW_AT_comp_dir), ""); 52862cfcf62SDimitry Andric if (!DWOCompDir.empty()) { 529*d409305fSDimitry Andric SmallString<16> DWOPath(std::move(DWOName)); 530*d409305fSDimitry Andric sys::fs::make_absolute(DWOCompDir, DWOPath); 53162cfcf62SDimitry Andric DWOPaths.emplace_back(DWOPath.data(), DWOPath.size()); 53262cfcf62SDimitry Andric } else { 53362cfcf62SDimitry Andric DWOPaths.push_back(std::move(DWOName)); 53462cfcf62SDimitry Andric } 53562cfcf62SDimitry Andric } 53662cfcf62SDimitry Andric return std::move(DWOPaths); 53762cfcf62SDimitry Andric } 53862cfcf62SDimitry Andric 53962cfcf62SDimitry Andric static Error write(MCStreamer &Out, ArrayRef<std::string> Inputs) { 54062cfcf62SDimitry Andric const auto &MCOFI = *Out.getContext().getObjectFileInfo(); 54162cfcf62SDimitry Andric MCSection *const StrSection = MCOFI.getDwarfStrDWOSection(); 54262cfcf62SDimitry Andric MCSection *const StrOffsetSection = MCOFI.getDwarfStrOffDWOSection(); 54362cfcf62SDimitry Andric MCSection *const TypesSection = MCOFI.getDwarfTypesDWOSection(); 54462cfcf62SDimitry Andric MCSection *const CUIndexSection = MCOFI.getDwarfCUIndexSection(); 54562cfcf62SDimitry Andric MCSection *const TUIndexSection = MCOFI.getDwarfTUIndexSection(); 54662cfcf62SDimitry Andric const StringMap<std::pair<MCSection *, DWARFSectionKind>> KnownSections = { 54762cfcf62SDimitry Andric {"debug_info.dwo", {MCOFI.getDwarfInfoDWOSection(), DW_SECT_INFO}}, 5485ffd83dbSDimitry Andric {"debug_types.dwo", {MCOFI.getDwarfTypesDWOSection(), DW_SECT_EXT_TYPES}}, 54962cfcf62SDimitry Andric {"debug_str_offsets.dwo", {StrOffsetSection, DW_SECT_STR_OFFSETS}}, 55062cfcf62SDimitry Andric {"debug_str.dwo", {StrSection, static_cast<DWARFSectionKind>(0)}}, 5515ffd83dbSDimitry Andric {"debug_loc.dwo", {MCOFI.getDwarfLocDWOSection(), DW_SECT_EXT_LOC}}, 55262cfcf62SDimitry Andric {"debug_line.dwo", {MCOFI.getDwarfLineDWOSection(), DW_SECT_LINE}}, 55362cfcf62SDimitry Andric {"debug_abbrev.dwo", {MCOFI.getDwarfAbbrevDWOSection(), DW_SECT_ABBREV}}, 55462cfcf62SDimitry Andric {"debug_cu_index", {CUIndexSection, static_cast<DWARFSectionKind>(0)}}, 55562cfcf62SDimitry Andric {"debug_tu_index", {TUIndexSection, static_cast<DWARFSectionKind>(0)}}}; 55662cfcf62SDimitry Andric 55762cfcf62SDimitry Andric MapVector<uint64_t, UnitIndexEntry> IndexEntries; 55862cfcf62SDimitry Andric MapVector<uint64_t, UnitIndexEntry> TypeIndexEntries; 55962cfcf62SDimitry Andric 56062cfcf62SDimitry Andric uint32_t ContributionOffsets[8] = {}; 56162cfcf62SDimitry Andric 56262cfcf62SDimitry Andric DWPStringPool Strings(Out, StrSection); 56362cfcf62SDimitry Andric 56462cfcf62SDimitry Andric SmallVector<OwningBinary<object::ObjectFile>, 128> Objects; 56562cfcf62SDimitry Andric Objects.reserve(Inputs.size()); 56662cfcf62SDimitry Andric 56762cfcf62SDimitry Andric std::deque<SmallString<32>> UncompressedSections; 56862cfcf62SDimitry Andric 56962cfcf62SDimitry Andric for (const auto &Input : Inputs) { 57062cfcf62SDimitry Andric auto ErrOrObj = object::ObjectFile::createObjectFile(Input); 57162cfcf62SDimitry Andric if (!ErrOrObj) 57262cfcf62SDimitry Andric return ErrOrObj.takeError(); 57362cfcf62SDimitry Andric 57462cfcf62SDimitry Andric auto &Obj = *ErrOrObj->getBinary(); 57562cfcf62SDimitry Andric Objects.push_back(std::move(*ErrOrObj)); 57662cfcf62SDimitry Andric 57762cfcf62SDimitry Andric UnitIndexEntry CurEntry = {}; 57862cfcf62SDimitry Andric 57962cfcf62SDimitry Andric StringRef CurStrSection; 58062cfcf62SDimitry Andric StringRef CurStrOffsetSection; 58162cfcf62SDimitry Andric std::vector<StringRef> CurTypesSection; 58262cfcf62SDimitry Andric StringRef InfoSection; 58362cfcf62SDimitry Andric StringRef AbbrevSection; 58462cfcf62SDimitry Andric StringRef CurCUIndexSection; 58562cfcf62SDimitry Andric StringRef CurTUIndexSection; 58662cfcf62SDimitry Andric 58762cfcf62SDimitry Andric for (const auto &Section : Obj.sections()) 58862cfcf62SDimitry Andric if (auto Err = handleSection( 58962cfcf62SDimitry Andric KnownSections, StrSection, StrOffsetSection, TypesSection, 59062cfcf62SDimitry Andric CUIndexSection, TUIndexSection, Section, Out, 59162cfcf62SDimitry Andric UncompressedSections, ContributionOffsets, CurEntry, 59262cfcf62SDimitry Andric CurStrSection, CurStrOffsetSection, CurTypesSection, InfoSection, 59362cfcf62SDimitry Andric AbbrevSection, CurCUIndexSection, CurTUIndexSection)) 59462cfcf62SDimitry Andric return Err; 59562cfcf62SDimitry Andric 59662cfcf62SDimitry Andric if (InfoSection.empty()) 59762cfcf62SDimitry Andric continue; 59862cfcf62SDimitry Andric 59962cfcf62SDimitry Andric writeStringsAndOffsets(Out, Strings, StrOffsetSection, CurStrSection, 60062cfcf62SDimitry Andric CurStrOffsetSection); 60162cfcf62SDimitry Andric 60262cfcf62SDimitry Andric if (CurCUIndexSection.empty()) { 60362cfcf62SDimitry Andric Expected<CompileUnitIdentifiers> EID = getCUIdentifiers( 60462cfcf62SDimitry Andric AbbrevSection, InfoSection, CurStrOffsetSection, CurStrSection); 60562cfcf62SDimitry Andric if (!EID) 60662cfcf62SDimitry Andric return createFileError(Input, EID.takeError()); 60762cfcf62SDimitry Andric const auto &ID = *EID; 60862cfcf62SDimitry Andric auto P = IndexEntries.insert(std::make_pair(ID.Signature, CurEntry)); 60962cfcf62SDimitry Andric if (!P.second) 61062cfcf62SDimitry Andric return buildDuplicateError(*P.first, ID, ""); 61162cfcf62SDimitry Andric P.first->second.Name = ID.Name; 61262cfcf62SDimitry Andric P.first->second.DWOName = ID.DWOName; 61362cfcf62SDimitry Andric addAllTypes(Out, TypeIndexEntries, TypesSection, CurTypesSection, 6145ffd83dbSDimitry Andric CurEntry, 6155ffd83dbSDimitry Andric ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES)]); 61662cfcf62SDimitry Andric continue; 61762cfcf62SDimitry Andric } 61862cfcf62SDimitry Andric 61962cfcf62SDimitry Andric DWARFUnitIndex CUIndex(DW_SECT_INFO); 62062cfcf62SDimitry Andric DataExtractor CUIndexData(CurCUIndexSection, Obj.isLittleEndian(), 0); 62162cfcf62SDimitry Andric if (!CUIndex.parse(CUIndexData)) 6225ffd83dbSDimitry Andric return make_error<DWPError>("failed to parse cu_index"); 6235ffd83dbSDimitry Andric if (CUIndex.getVersion() != 2) 6245ffd83dbSDimitry Andric return make_error<DWPError>( 6255ffd83dbSDimitry Andric "unsupported cu_index version: " + utostr(CUIndex.getVersion()) + 6265ffd83dbSDimitry Andric " (only version 2 is supported)"); 62762cfcf62SDimitry Andric 62862cfcf62SDimitry Andric for (const DWARFUnitIndex::Entry &E : CUIndex.getRows()) { 6295ffd83dbSDimitry Andric auto *I = E.getContributions(); 63062cfcf62SDimitry Andric if (!I) 63162cfcf62SDimitry Andric continue; 63262cfcf62SDimitry Andric auto P = IndexEntries.insert(std::make_pair(E.getSignature(), CurEntry)); 63362cfcf62SDimitry Andric Expected<CompileUnitIdentifiers> EID = getCUIdentifiers( 63462cfcf62SDimitry Andric getSubsection(AbbrevSection, E, DW_SECT_ABBREV), 63562cfcf62SDimitry Andric getSubsection(InfoSection, E, DW_SECT_INFO), 63662cfcf62SDimitry Andric getSubsection(CurStrOffsetSection, E, DW_SECT_STR_OFFSETS), 63762cfcf62SDimitry Andric CurStrSection); 63862cfcf62SDimitry Andric if (!EID) 63962cfcf62SDimitry Andric return createFileError(Input, EID.takeError()); 64062cfcf62SDimitry Andric const auto &ID = *EID; 64162cfcf62SDimitry Andric if (!P.second) 64262cfcf62SDimitry Andric return buildDuplicateError(*P.first, ID, Input); 64362cfcf62SDimitry Andric auto &NewEntry = P.first->second; 64462cfcf62SDimitry Andric NewEntry.Name = ID.Name; 64562cfcf62SDimitry Andric NewEntry.DWOName = ID.DWOName; 64662cfcf62SDimitry Andric NewEntry.DWPName = Input; 64762cfcf62SDimitry Andric for (auto Kind : CUIndex.getColumnKinds()) { 6485ffd83dbSDimitry Andric if (!isSupportedSectionKind(Kind)) 6495ffd83dbSDimitry Andric continue; 6505ffd83dbSDimitry Andric auto &C = NewEntry.Contributions[getContributionIndex(Kind)]; 65162cfcf62SDimitry Andric C.Offset += I->Offset; 65262cfcf62SDimitry Andric C.Length = I->Length; 65362cfcf62SDimitry Andric ++I; 65462cfcf62SDimitry Andric } 65562cfcf62SDimitry Andric } 65662cfcf62SDimitry Andric 65762cfcf62SDimitry Andric if (!CurTypesSection.empty()) { 65862cfcf62SDimitry Andric if (CurTypesSection.size() != 1) 65962cfcf62SDimitry Andric return make_error<DWPError>("multiple type unit sections in .dwp file"); 6605ffd83dbSDimitry Andric DWARFUnitIndex TUIndex(DW_SECT_EXT_TYPES); 66162cfcf62SDimitry Andric DataExtractor TUIndexData(CurTUIndexSection, Obj.isLittleEndian(), 0); 66262cfcf62SDimitry Andric if (!TUIndex.parse(TUIndexData)) 6635ffd83dbSDimitry Andric return make_error<DWPError>("failed to parse tu_index"); 6645ffd83dbSDimitry Andric if (TUIndex.getVersion() != 2) 6655ffd83dbSDimitry Andric return make_error<DWPError>( 6665ffd83dbSDimitry Andric "unsupported tu_index version: " + utostr(TUIndex.getVersion()) + 6675ffd83dbSDimitry Andric " (only version 2 is supported)"); 6685ffd83dbSDimitry Andric 6695ffd83dbSDimitry Andric addAllTypesFromDWP( 6705ffd83dbSDimitry Andric Out, TypeIndexEntries, TUIndex, TypesSection, CurTypesSection.front(), 6715ffd83dbSDimitry Andric CurEntry, 6725ffd83dbSDimitry Andric ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES)]); 67362cfcf62SDimitry Andric } 67462cfcf62SDimitry Andric } 67562cfcf62SDimitry Andric 67662cfcf62SDimitry Andric // Lie about there being no info contributions so the TU index only includes 67762cfcf62SDimitry Andric // the type unit contribution 67862cfcf62SDimitry Andric ContributionOffsets[0] = 0; 67962cfcf62SDimitry Andric writeIndex(Out, MCOFI.getDwarfTUIndexSection(), ContributionOffsets, 68062cfcf62SDimitry Andric TypeIndexEntries); 68162cfcf62SDimitry Andric 68262cfcf62SDimitry Andric // Lie about the type contribution 6835ffd83dbSDimitry Andric ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES)] = 0; 68462cfcf62SDimitry Andric // Unlie about the info contribution 68562cfcf62SDimitry Andric ContributionOffsets[0] = 1; 68662cfcf62SDimitry Andric 68762cfcf62SDimitry Andric writeIndex(Out, MCOFI.getDwarfCUIndexSection(), ContributionOffsets, 68862cfcf62SDimitry Andric IndexEntries); 68962cfcf62SDimitry Andric 69062cfcf62SDimitry Andric return Error::success(); 69162cfcf62SDimitry Andric } 69262cfcf62SDimitry Andric 69362cfcf62SDimitry Andric static int error(const Twine &Error, const Twine &Context) { 69462cfcf62SDimitry Andric errs() << Twine("while processing ") + Context + ":\n"; 69562cfcf62SDimitry Andric errs() << Twine("error: ") + Error + "\n"; 69662cfcf62SDimitry Andric return 1; 69762cfcf62SDimitry Andric } 69862cfcf62SDimitry Andric 699e8d8bef9SDimitry Andric static Expected<Triple> readTargetTriple(StringRef FileName) { 700e8d8bef9SDimitry Andric auto ErrOrObj = object::ObjectFile::createObjectFile(FileName); 701e8d8bef9SDimitry Andric if (!ErrOrObj) 702e8d8bef9SDimitry Andric return ErrOrObj.takeError(); 703e8d8bef9SDimitry Andric 704e8d8bef9SDimitry Andric return ErrOrObj->getBinary()->makeTriple(); 705e8d8bef9SDimitry Andric } 706e8d8bef9SDimitry Andric 70762cfcf62SDimitry Andric int main(int argc, char **argv) { 70862cfcf62SDimitry Andric InitLLVM X(argc, argv); 70962cfcf62SDimitry Andric 71062cfcf62SDimitry Andric cl::ParseCommandLineOptions(argc, argv, "merge split dwarf (.dwo) files\n"); 71162cfcf62SDimitry Andric 71262cfcf62SDimitry Andric llvm::InitializeAllTargetInfos(); 71362cfcf62SDimitry Andric llvm::InitializeAllTargetMCs(); 71462cfcf62SDimitry Andric llvm::InitializeAllTargets(); 71562cfcf62SDimitry Andric llvm::InitializeAllAsmPrinters(); 71662cfcf62SDimitry Andric 717e8d8bef9SDimitry Andric std::vector<std::string> DWOFilenames = InputFiles; 718e8d8bef9SDimitry Andric for (const auto &ExecFilename : ExecFilenames) { 719e8d8bef9SDimitry Andric auto DWOs = getDWOFilenames(ExecFilename); 720e8d8bef9SDimitry Andric if (!DWOs) { 721e8d8bef9SDimitry Andric logAllUnhandledErrors(DWOs.takeError(), WithColor::error()); 722e8d8bef9SDimitry Andric return 1; 723e8d8bef9SDimitry Andric } 724e8d8bef9SDimitry Andric DWOFilenames.insert(DWOFilenames.end(), 725e8d8bef9SDimitry Andric std::make_move_iterator(DWOs->begin()), 726e8d8bef9SDimitry Andric std::make_move_iterator(DWOs->end())); 727e8d8bef9SDimitry Andric } 728e8d8bef9SDimitry Andric 729e8d8bef9SDimitry Andric if (DWOFilenames.empty()) 730e8d8bef9SDimitry Andric return 0; 731e8d8bef9SDimitry Andric 73262cfcf62SDimitry Andric std::string ErrorStr; 73362cfcf62SDimitry Andric StringRef Context = "dwarf streamer init"; 73462cfcf62SDimitry Andric 735e8d8bef9SDimitry Andric auto ErrOrTriple = readTargetTriple(DWOFilenames.front()); 736e8d8bef9SDimitry Andric if (!ErrOrTriple) { 737e8d8bef9SDimitry Andric logAllUnhandledErrors(ErrOrTriple.takeError(), WithColor::error()); 738e8d8bef9SDimitry Andric return 1; 739e8d8bef9SDimitry Andric } 74062cfcf62SDimitry Andric 74162cfcf62SDimitry Andric // Get the target. 74262cfcf62SDimitry Andric const Target *TheTarget = 743e8d8bef9SDimitry Andric TargetRegistry::lookupTarget("", *ErrOrTriple, ErrorStr); 74462cfcf62SDimitry Andric if (!TheTarget) 74562cfcf62SDimitry Andric return error(ErrorStr, Context); 746e8d8bef9SDimitry Andric std::string TripleName = ErrOrTriple->getTriple(); 74762cfcf62SDimitry Andric 74862cfcf62SDimitry Andric // Create all the MC Objects. 74962cfcf62SDimitry Andric std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName)); 75062cfcf62SDimitry Andric if (!MRI) 75162cfcf62SDimitry Andric return error(Twine("no register info for target ") + TripleName, Context); 75262cfcf62SDimitry Andric 7535ffd83dbSDimitry Andric MCTargetOptions MCOptions = llvm::mc::InitMCTargetOptionsFromFlags(); 75462cfcf62SDimitry Andric std::unique_ptr<MCAsmInfo> MAI( 75562cfcf62SDimitry Andric TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions)); 75662cfcf62SDimitry Andric if (!MAI) 75762cfcf62SDimitry Andric return error("no asm info for target " + TripleName, Context); 75862cfcf62SDimitry Andric 75962cfcf62SDimitry Andric MCObjectFileInfo MOFI; 76062cfcf62SDimitry Andric MCContext MC(MAI.get(), MRI.get(), &MOFI); 761e8d8bef9SDimitry Andric MOFI.InitMCObjectFileInfo(*ErrOrTriple, /*PIC*/ false, MC); 76262cfcf62SDimitry Andric 76362cfcf62SDimitry Andric std::unique_ptr<MCSubtargetInfo> MSTI( 76462cfcf62SDimitry Andric TheTarget->createMCSubtargetInfo(TripleName, "", "")); 76562cfcf62SDimitry Andric if (!MSTI) 76662cfcf62SDimitry Andric return error("no subtarget info for target " + TripleName, Context); 76762cfcf62SDimitry Andric 76862cfcf62SDimitry Andric MCTargetOptions Options; 76962cfcf62SDimitry Andric auto MAB = TheTarget->createMCAsmBackend(*MSTI, *MRI, Options); 77062cfcf62SDimitry Andric if (!MAB) 77162cfcf62SDimitry Andric return error("no asm backend for target " + TripleName, Context); 77262cfcf62SDimitry Andric 77362cfcf62SDimitry Andric std::unique_ptr<MCInstrInfo> MII(TheTarget->createMCInstrInfo()); 77462cfcf62SDimitry Andric if (!MII) 77562cfcf62SDimitry Andric return error("no instr info info for target " + TripleName, Context); 77662cfcf62SDimitry Andric 77762cfcf62SDimitry Andric MCCodeEmitter *MCE = TheTarget->createMCCodeEmitter(*MII, *MRI, MC); 77862cfcf62SDimitry Andric if (!MCE) 77962cfcf62SDimitry Andric return error("no code emitter for target " + TripleName, Context); 78062cfcf62SDimitry Andric 78162cfcf62SDimitry Andric // Create the output file. 78262cfcf62SDimitry Andric std::error_code EC; 78362cfcf62SDimitry Andric ToolOutputFile OutFile(OutputFilename, EC, sys::fs::OF_None); 78462cfcf62SDimitry Andric Optional<buffer_ostream> BOS; 78562cfcf62SDimitry Andric raw_pwrite_stream *OS; 78662cfcf62SDimitry Andric if (EC) 78762cfcf62SDimitry Andric return error(Twine(OutputFilename) + ": " + EC.message(), Context); 78862cfcf62SDimitry Andric if (OutFile.os().supportsSeeking()) { 78962cfcf62SDimitry Andric OS = &OutFile.os(); 79062cfcf62SDimitry Andric } else { 79162cfcf62SDimitry Andric BOS.emplace(OutFile.os()); 79262cfcf62SDimitry Andric OS = BOS.getPointer(); 79362cfcf62SDimitry Andric } 79462cfcf62SDimitry Andric 79562cfcf62SDimitry Andric std::unique_ptr<MCStreamer> MS(TheTarget->createMCObjectStreamer( 796e8d8bef9SDimitry Andric *ErrOrTriple, MC, std::unique_ptr<MCAsmBackend>(MAB), 79762cfcf62SDimitry Andric MAB->createObjectWriter(*OS), std::unique_ptr<MCCodeEmitter>(MCE), *MSTI, 79862cfcf62SDimitry Andric MCOptions.MCRelaxAll, MCOptions.MCIncrementalLinkerCompatible, 79962cfcf62SDimitry Andric /*DWARFMustBeAtTheEnd*/ false)); 80062cfcf62SDimitry Andric if (!MS) 80162cfcf62SDimitry Andric return error("no object streamer for target " + TripleName, Context); 80262cfcf62SDimitry Andric 80362cfcf62SDimitry Andric if (auto Err = write(*MS, DWOFilenames)) { 80462cfcf62SDimitry Andric logAllUnhandledErrors(std::move(Err), WithColor::error()); 80562cfcf62SDimitry Andric return 1; 80662cfcf62SDimitry Andric } 80762cfcf62SDimitry Andric 80862cfcf62SDimitry Andric MS->Finish(); 80962cfcf62SDimitry Andric OutFile.keep(); 81062cfcf62SDimitry Andric return 0; 81162cfcf62SDimitry Andric } 812