Path: blob/main/contrib/llvm-project/llvm/tools/llvm-dwp/llvm-dwp.cpp
35231 views
//===-- llvm-dwp.cpp - Split DWARF merging tool for llvm ------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// A utility for merging DWARF 5 Split DWARF .dwo files into .dwp (DWARF9// package files).10//11//===----------------------------------------------------------------------===//12#include "llvm/DWP/DWP.h"13#include "llvm/DWP/DWPError.h"14#include "llvm/DWP/DWPStringPool.h"15#include "llvm/MC/MCAsmBackend.h"16#include "llvm/MC/MCAsmInfo.h"17#include "llvm/MC/MCCodeEmitter.h"18#include "llvm/MC/MCContext.h"19#include "llvm/MC/MCInstrInfo.h"20#include "llvm/MC/MCObjectWriter.h"21#include "llvm/MC/MCRegisterInfo.h"22#include "llvm/MC/MCSubtargetInfo.h"23#include "llvm/MC/MCTargetOptionsCommandFlags.h"24#include "llvm/MC/TargetRegistry.h"25#include "llvm/Option/ArgList.h"26#include "llvm/Option/Option.h"27#include "llvm/Support/CommandLine.h"28#include "llvm/Support/FileSystem.h"29#include "llvm/Support/LLVMDriver.h"30#include "llvm/Support/MemoryBuffer.h"31#include "llvm/Support/TargetSelect.h"32#include "llvm/Support/ToolOutputFile.h"33#include <optional>3435using namespace llvm;36using namespace llvm::object;3738static mc::RegisterMCTargetOptionsFlags MCTargetOptionsFlags;3940// Command-line option boilerplate.41namespace {42enum ID {43OPT_INVALID = 0, // This is not an option ID.44#define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__),45#include "Opts.inc"46#undef OPTION47};4849#define PREFIX(NAME, VALUE) \50static constexpr StringLiteral NAME##_init[] = VALUE; \51static constexpr ArrayRef<StringLiteral> NAME(NAME##_init, \52std::size(NAME##_init) - 1);53#include "Opts.inc"54#undef PREFIX5556using namespace llvm::opt;57static constexpr opt::OptTable::Info InfoTable[] = {58#define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),59#include "Opts.inc"60#undef OPTION61};6263class DwpOptTable : public opt::GenericOptTable {64public:65DwpOptTable() : GenericOptTable(InfoTable) {}66};67} // end anonymous namespace6869// Options70static std::vector<std::string> ExecFilenames;71static std::string OutputFilename;72static std::string ContinueOption;7374static Expected<SmallVector<std::string, 16>>75getDWOFilenames(StringRef ExecFilename) {76auto ErrOrObj = object::ObjectFile::createObjectFile(ExecFilename);77if (!ErrOrObj)78return ErrOrObj.takeError();7980const ObjectFile &Obj = *ErrOrObj.get().getBinary();81std::unique_ptr<DWARFContext> DWARFCtx = DWARFContext::create(Obj);8283SmallVector<std::string, 16> DWOPaths;84for (const auto &CU : DWARFCtx->compile_units()) {85const DWARFDie &Die = CU->getUnitDIE();86std::string DWOName = dwarf::toString(87Die.find({dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}), "");88if (DWOName.empty())89continue;90std::string DWOCompDir =91dwarf::toString(Die.find(dwarf::DW_AT_comp_dir), "");92if (!DWOCompDir.empty()) {93SmallString<16> DWOPath(DWOName);94sys::fs::make_absolute(DWOCompDir, DWOPath);95if (!sys::fs::exists(DWOPath) && sys::fs::exists(DWOName))96DWOPaths.push_back(std::move(DWOName));97else98DWOPaths.emplace_back(DWOPath.data(), DWOPath.size());99} else {100DWOPaths.push_back(std::move(DWOName));101}102}103return std::move(DWOPaths);104}105106static int error(const Twine &Error, const Twine &Context) {107errs() << Twine("while processing ") + Context + ":\n";108errs() << Twine("error: ") + Error + "\n";109return 1;110}111112static Expected<Triple> readTargetTriple(StringRef FileName) {113auto ErrOrObj = object::ObjectFile::createObjectFile(FileName);114if (!ErrOrObj)115return ErrOrObj.takeError();116117return ErrOrObj->getBinary()->makeTriple();118}119120int llvm_dwp_main(int argc, char **argv, const llvm::ToolContext &) {121DwpOptTable Tbl;122llvm::BumpPtrAllocator A;123llvm::StringSaver Saver{A};124OnCuIndexOverflow OverflowOptValue = OnCuIndexOverflow::HardStop;125opt::InputArgList Args =126Tbl.parseArgs(argc, argv, OPT_UNKNOWN, Saver, [&](StringRef Msg) {127llvm::errs() << Msg << '\n';128std::exit(1);129});130131if (Args.hasArg(OPT_help)) {132Tbl.printHelp(llvm::outs(), "llvm-dwp [options] <input files>",133"merge split dwarf (.dwo) files");134std::exit(0);135}136137if (Args.hasArg(OPT_version)) {138llvm::cl::PrintVersionMessage();139std::exit(0);140}141142OutputFilename = Args.getLastArgValue(OPT_outputFileName, "");143if (Arg *Arg = Args.getLastArg(OPT_continueOnCuIndexOverflow,144OPT_continueOnCuIndexOverflow_EQ)) {145if (Arg->getOption().matches(OPT_continueOnCuIndexOverflow)) {146OverflowOptValue = OnCuIndexOverflow::Continue;147} else {148ContinueOption = Arg->getValue();149if (ContinueOption == "soft-stop") {150OverflowOptValue = OnCuIndexOverflow::SoftStop;151} else if (ContinueOption == "continue") {152OverflowOptValue = OnCuIndexOverflow::Continue;153} else {154llvm::errs() << "invalid value for --continue-on-cu-index-overflow"155<< ContinueOption << '\n';156exit(1);157}158}159}160161for (const llvm::opt::Arg *A : Args.filtered(OPT_execFileNames))162ExecFilenames.emplace_back(A->getValue());163164std::vector<std::string> DWOFilenames;165for (const llvm::opt::Arg *A : Args.filtered(OPT_INPUT))166DWOFilenames.emplace_back(A->getValue());167168llvm::InitializeAllTargetInfos();169llvm::InitializeAllTargetMCs();170llvm::InitializeAllTargets();171llvm::InitializeAllAsmPrinters();172173for (const auto &ExecFilename : ExecFilenames) {174auto DWOs = getDWOFilenames(ExecFilename);175if (!DWOs) {176logAllUnhandledErrors(177handleErrors(DWOs.takeError(),178[&](std::unique_ptr<ECError> EC) -> Error {179return createFileError(ExecFilename,180Error(std::move(EC)));181}),182WithColor::error());183return 1;184}185DWOFilenames.insert(DWOFilenames.end(),186std::make_move_iterator(DWOs->begin()),187std::make_move_iterator(DWOs->end()));188}189190if (DWOFilenames.empty()) {191WithColor::defaultWarningHandler(make_error<DWPError>(192"executable file does not contain any references to dwo files"));193return 0;194}195196std::string ErrorStr;197StringRef Context = "dwarf streamer init";198199auto ErrOrTriple = readTargetTriple(DWOFilenames.front());200if (!ErrOrTriple) {201logAllUnhandledErrors(202handleErrors(ErrOrTriple.takeError(),203[&](std::unique_ptr<ECError> EC) -> Error {204return createFileError(DWOFilenames.front(),205Error(std::move(EC)));206}),207WithColor::error());208return 1;209}210211// Get the target.212const Target *TheTarget =213TargetRegistry::lookupTarget("", *ErrOrTriple, ErrorStr);214if (!TheTarget)215return error(ErrorStr, Context);216std::string TripleName = ErrOrTriple->getTriple();217218// Create all the MC Objects.219std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName));220if (!MRI)221return error(Twine("no register info for target ") + TripleName, Context);222223MCTargetOptions MCOptions = llvm::mc::InitMCTargetOptionsFromFlags();224std::unique_ptr<MCAsmInfo> MAI(225TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions));226if (!MAI)227return error("no asm info for target " + TripleName, Context);228229std::unique_ptr<MCSubtargetInfo> MSTI(230TheTarget->createMCSubtargetInfo(TripleName, "", ""));231if (!MSTI)232return error("no subtarget info for target " + TripleName, Context);233234MCContext MC(*ErrOrTriple, MAI.get(), MRI.get(), MSTI.get());235std::unique_ptr<MCObjectFileInfo> MOFI(236TheTarget->createMCObjectFileInfo(MC, /*PIC=*/false));237MC.setObjectFileInfo(MOFI.get());238239MCTargetOptions Options;240auto MAB = TheTarget->createMCAsmBackend(*MSTI, *MRI, Options);241if (!MAB)242return error("no asm backend for target " + TripleName, Context);243244std::unique_ptr<MCInstrInfo> MII(TheTarget->createMCInstrInfo());245if (!MII)246return error("no instr info info for target " + TripleName, Context);247248MCCodeEmitter *MCE = TheTarget->createMCCodeEmitter(*MII, MC);249if (!MCE)250return error("no code emitter for target " + TripleName, Context);251252// Create the output file.253std::error_code EC;254ToolOutputFile OutFile(OutputFilename, EC, sys::fs::OF_None);255std::optional<buffer_ostream> BOS;256raw_pwrite_stream *OS;257if (EC)258return error(Twine(OutputFilename) + ": " + EC.message(), Context);259if (OutFile.os().supportsSeeking()) {260OS = &OutFile.os();261} else {262BOS.emplace(OutFile.os());263OS = &*BOS;264}265266std::unique_ptr<MCStreamer> MS(TheTarget->createMCObjectStreamer(267*ErrOrTriple, MC, std::unique_ptr<MCAsmBackend>(MAB),268MAB->createObjectWriter(*OS), std::unique_ptr<MCCodeEmitter>(MCE),269*MSTI));270if (!MS)271return error("no object streamer for target " + TripleName, Context);272273if (auto Err = write(*MS, DWOFilenames, OverflowOptValue)) {274logAllUnhandledErrors(std::move(Err), WithColor::error());275return 1;276}277278MS->finish();279OutFile.keep();280return 0;281}282283284