xref: /llvm-project/llvm/tools/llvm-dwarfutil/llvm-dwarfutil.cpp (revision dd647e3e608ed0b2bac7c588d5859b80ef4a5976)
14539b441SAlexey Lapshin //=== llvm-dwarfutil.cpp --------------------------------------------------===//
24539b441SAlexey Lapshin //
34539b441SAlexey Lapshin // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44539b441SAlexey Lapshin // See https://llvm.org/LICENSE.txt for license information.
54539b441SAlexey Lapshin // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
64539b441SAlexey Lapshin //
74539b441SAlexey Lapshin //===----------------------------------------------------------------------===//
84539b441SAlexey Lapshin 
94539b441SAlexey Lapshin #include "DebugInfoLinker.h"
104539b441SAlexey Lapshin #include "Error.h"
114539b441SAlexey Lapshin #include "Options.h"
124539b441SAlexey Lapshin #include "llvm/DebugInfo/DWARF/DWARFContext.h"
134539b441SAlexey Lapshin #include "llvm/DebugInfo/DWARF/DWARFVerifier.h"
144539b441SAlexey Lapshin #include "llvm/MC/MCTargetOptionsCommandFlags.h"
154539b441SAlexey Lapshin #include "llvm/ObjCopy/CommonConfig.h"
164539b441SAlexey Lapshin #include "llvm/ObjCopy/ConfigManager.h"
174539b441SAlexey Lapshin #include "llvm/ObjCopy/ObjCopy.h"
184539b441SAlexey Lapshin #include "llvm/Option/Arg.h"
194539b441SAlexey Lapshin #include "llvm/Option/ArgList.h"
204539b441SAlexey Lapshin #include "llvm/Option/Option.h"
214539b441SAlexey Lapshin #include "llvm/Support/CRC.h"
224539b441SAlexey Lapshin #include "llvm/Support/CommandLine.h"
234539b441SAlexey Lapshin #include "llvm/Support/FileUtilities.h"
244539b441SAlexey Lapshin #include "llvm/Support/InitLLVM.h"
254539b441SAlexey Lapshin #include "llvm/Support/PrettyStackTrace.h"
264539b441SAlexey Lapshin #include "llvm/Support/Process.h"
274539b441SAlexey Lapshin #include "llvm/Support/Signals.h"
284539b441SAlexey Lapshin #include "llvm/Support/TargetSelect.h"
294539b441SAlexey Lapshin 
304539b441SAlexey Lapshin using namespace llvm;
314539b441SAlexey Lapshin using namespace object;
324539b441SAlexey Lapshin 
334539b441SAlexey Lapshin namespace {
344539b441SAlexey Lapshin enum ID {
354539b441SAlexey Lapshin   OPT_INVALID = 0, // This is not an option ID.
363f092f37SJan Svoboda #define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__),
374539b441SAlexey Lapshin #include "Options.inc"
384539b441SAlexey Lapshin #undef OPTION
394539b441SAlexey Lapshin };
404539b441SAlexey Lapshin 
41*dd647e3eSChandler Carruth #define OPTTABLE_STR_TABLE_CODE
424539b441SAlexey Lapshin #include "Options.inc"
43*dd647e3eSChandler Carruth #undef OPTTABLE_STR_TABLE_CODE
44*dd647e3eSChandler Carruth 
45*dd647e3eSChandler Carruth #define OPTTABLE_PREFIXES_TABLE_CODE
46*dd647e3eSChandler Carruth #include "Options.inc"
47*dd647e3eSChandler Carruth #undef OPTTABLE_PREFIXES_TABLE_CODE
484539b441SAlexey Lapshin 
49dcb6d212SJustin Bogner using namespace llvm::opt;
5007d9ab9aSserge-sans-paille static constexpr opt::OptTable::Info InfoTable[] = {
513f092f37SJan Svoboda #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
524539b441SAlexey Lapshin #include "Options.inc"
534539b441SAlexey Lapshin #undef OPTION
544539b441SAlexey Lapshin };
554539b441SAlexey Lapshin 
5607bb29d8Sserge-sans-paille class DwarfutilOptTable : public opt::GenericOptTable {
574539b441SAlexey Lapshin public:
58*dd647e3eSChandler Carruth   DwarfutilOptTable()
59*dd647e3eSChandler Carruth       : opt::GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) {}
604539b441SAlexey Lapshin };
614539b441SAlexey Lapshin } // namespace
624539b441SAlexey Lapshin 
634539b441SAlexey Lapshin namespace llvm {
644539b441SAlexey Lapshin namespace dwarfutil {
654539b441SAlexey Lapshin 
664539b441SAlexey Lapshin std::string ToolName;
674539b441SAlexey Lapshin 
684539b441SAlexey Lapshin static mc::RegisterMCTargetOptionsFlags MOF;
694539b441SAlexey Lapshin 
704539b441SAlexey Lapshin static Error validateAndSetOptions(opt::InputArgList &Args, Options &Options) {
714539b441SAlexey Lapshin   auto UnknownArgs = Args.filtered(OPT_UNKNOWN);
724539b441SAlexey Lapshin   if (!UnknownArgs.empty())
734539b441SAlexey Lapshin     return createStringError(
744539b441SAlexey Lapshin         std::errc::invalid_argument,
754539b441SAlexey Lapshin         formatv("unknown option: {0}", (*UnknownArgs.begin())->getSpelling())
764539b441SAlexey Lapshin             .str()
774539b441SAlexey Lapshin             .c_str());
784539b441SAlexey Lapshin 
794539b441SAlexey Lapshin   std::vector<std::string> InputFiles = Args.getAllArgValues(OPT_INPUT);
804539b441SAlexey Lapshin   if (InputFiles.size() != 2)
814539b441SAlexey Lapshin     return createStringError(
824539b441SAlexey Lapshin         std::errc::invalid_argument,
834539b441SAlexey Lapshin         formatv("exactly two positional arguments expected, {0} provided",
844539b441SAlexey Lapshin                 InputFiles.size())
854539b441SAlexey Lapshin             .str()
864539b441SAlexey Lapshin             .c_str());
874539b441SAlexey Lapshin 
884539b441SAlexey Lapshin   Options.InputFileName = InputFiles[0];
894539b441SAlexey Lapshin   Options.OutputFileName = InputFiles[1];
904539b441SAlexey Lapshin 
914539b441SAlexey Lapshin   Options.BuildSeparateDebugFile =
924539b441SAlexey Lapshin       Args.hasFlag(OPT_separate_debug_file, OPT_no_separate_debug_file, false);
934539b441SAlexey Lapshin   Options.DoODRDeduplication =
944539b441SAlexey Lapshin       Args.hasFlag(OPT_odr_deduplication, OPT_no_odr_deduplication, true);
954539b441SAlexey Lapshin   Options.DoGarbageCollection =
964539b441SAlexey Lapshin       Args.hasFlag(OPT_garbage_collection, OPT_no_garbage_collection, true);
974539b441SAlexey Lapshin   Options.Verbose = Args.hasArg(OPT_verbose);
984539b441SAlexey Lapshin   Options.Verify = Args.hasArg(OPT_verify);
994539b441SAlexey Lapshin 
1004539b441SAlexey Lapshin   if (opt::Arg *NumThreads = Args.getLastArg(OPT_threads))
1014539b441SAlexey Lapshin     Options.NumThreads = atoi(NumThreads->getValue());
1024539b441SAlexey Lapshin   else
1034539b441SAlexey Lapshin     Options.NumThreads = 0; // Use all available hardware threads
1044539b441SAlexey Lapshin 
1054539b441SAlexey Lapshin   if (opt::Arg *Tombstone = Args.getLastArg(OPT_tombstone)) {
1064539b441SAlexey Lapshin     StringRef S = Tombstone->getValue();
1074539b441SAlexey Lapshin     if (S == "bfd")
1084539b441SAlexey Lapshin       Options.Tombstone = TombstoneKind::BFD;
1094539b441SAlexey Lapshin     else if (S == "maxpc")
1104539b441SAlexey Lapshin       Options.Tombstone = TombstoneKind::MaxPC;
1114539b441SAlexey Lapshin     else if (S == "universal")
1124539b441SAlexey Lapshin       Options.Tombstone = TombstoneKind::Universal;
1134539b441SAlexey Lapshin     else if (S == "exec")
1144539b441SAlexey Lapshin       Options.Tombstone = TombstoneKind::Exec;
1154539b441SAlexey Lapshin     else
1164539b441SAlexey Lapshin       return createStringError(
1174539b441SAlexey Lapshin           std::errc::invalid_argument,
1184539b441SAlexey Lapshin           formatv("unknown tombstone value: '{0}'", S).str().c_str());
1194539b441SAlexey Lapshin   }
1204539b441SAlexey Lapshin 
12136f35109SAlexey Lapshin   if (opt::Arg *LinkerKind = Args.getLastArg(OPT_linker)) {
12236f35109SAlexey Lapshin     StringRef S = LinkerKind->getValue();
123f1fdfe68SAlexey Lapshin     if (S == "classic")
124f1fdfe68SAlexey Lapshin       Options.UseDWARFLinkerParallel = false;
125f1fdfe68SAlexey Lapshin     else if (S == "parallel")
126f1fdfe68SAlexey Lapshin       Options.UseDWARFLinkerParallel = true;
12736f35109SAlexey Lapshin     else
12836f35109SAlexey Lapshin       return createStringError(
12936f35109SAlexey Lapshin           std::errc::invalid_argument,
13036f35109SAlexey Lapshin           formatv("unknown linker kind value: '{0}'", S).str().c_str());
13136f35109SAlexey Lapshin   }
13236f35109SAlexey Lapshin 
1332216ee49SAlexey Lapshin   if (opt::Arg *BuildAccelerator = Args.getLastArg(OPT_build_accelerator)) {
1342216ee49SAlexey Lapshin     StringRef S = BuildAccelerator->getValue();
1352216ee49SAlexey Lapshin 
1362216ee49SAlexey Lapshin     if (S == "none")
1372216ee49SAlexey Lapshin       Options.AccelTableKind = DwarfUtilAccelKind::None;
1382216ee49SAlexey Lapshin     else if (S == "DWARF")
1392216ee49SAlexey Lapshin       Options.AccelTableKind = DwarfUtilAccelKind::DWARF;
1402216ee49SAlexey Lapshin     else
1412216ee49SAlexey Lapshin       return createStringError(
1422216ee49SAlexey Lapshin           std::errc::invalid_argument,
1432216ee49SAlexey Lapshin           formatv("unknown build-accelerator value: '{0}'", S).str().c_str());
1442216ee49SAlexey Lapshin   }
1452216ee49SAlexey Lapshin 
1464539b441SAlexey Lapshin   if (Options.Verbose) {
1474539b441SAlexey Lapshin     if (Options.NumThreads != 1 && Args.hasArg(OPT_threads))
1484539b441SAlexey Lapshin       warning("--num-threads set to 1 because verbose mode is specified");
1494539b441SAlexey Lapshin 
1504539b441SAlexey Lapshin     Options.NumThreads = 1;
1514539b441SAlexey Lapshin   }
1524539b441SAlexey Lapshin 
1534539b441SAlexey Lapshin   if (Options.DoODRDeduplication && Args.hasArg(OPT_odr_deduplication) &&
1544539b441SAlexey Lapshin       !Options.DoGarbageCollection)
1554539b441SAlexey Lapshin     return createStringError(
1564539b441SAlexey Lapshin         std::errc::invalid_argument,
1574539b441SAlexey Lapshin         "cannot use --odr-deduplication without --garbage-collection");
1584539b441SAlexey Lapshin 
1594539b441SAlexey Lapshin   if (Options.BuildSeparateDebugFile && Options.OutputFileName == "-")
1604539b441SAlexey Lapshin     return createStringError(
1614539b441SAlexey Lapshin         std::errc::invalid_argument,
1624539b441SAlexey Lapshin         "unable to write to stdout when --separate-debug-file specified");
1634539b441SAlexey Lapshin 
1644539b441SAlexey Lapshin   return Error::success();
1654539b441SAlexey Lapshin }
1664539b441SAlexey Lapshin 
1674539b441SAlexey Lapshin static Error setConfigToAddNewDebugSections(objcopy::ConfigManager &Config,
1684539b441SAlexey Lapshin                                             ObjectFile &ObjFile) {
1694539b441SAlexey Lapshin   // Add new debug sections.
1704539b441SAlexey Lapshin   for (SectionRef Sec : ObjFile.sections()) {
1714539b441SAlexey Lapshin     Expected<StringRef> SecName = Sec.getName();
1724539b441SAlexey Lapshin     if (!SecName)
1734539b441SAlexey Lapshin       return SecName.takeError();
1744539b441SAlexey Lapshin 
1754539b441SAlexey Lapshin     if (isDebugSection(*SecName)) {
1764539b441SAlexey Lapshin       Expected<StringRef> SecData = Sec.getContents();
1774539b441SAlexey Lapshin       if (!SecData)
1784539b441SAlexey Lapshin         return SecData.takeError();
1794539b441SAlexey Lapshin 
1804539b441SAlexey Lapshin       Config.Common.AddSection.emplace_back(objcopy::NewSectionInfo(
1814539b441SAlexey Lapshin           *SecName, MemoryBuffer::getMemBuffer(*SecData, *SecName, false)));
1824539b441SAlexey Lapshin     }
1834539b441SAlexey Lapshin   }
1844539b441SAlexey Lapshin 
1854539b441SAlexey Lapshin   return Error::success();
1864539b441SAlexey Lapshin }
1874539b441SAlexey Lapshin 
1884539b441SAlexey Lapshin static Error verifyOutput(const Options &Opts) {
1894539b441SAlexey Lapshin   if (Opts.OutputFileName == "-") {
1904539b441SAlexey Lapshin     warning("verification skipped because writing to stdout");
1914539b441SAlexey Lapshin     return Error::success();
1924539b441SAlexey Lapshin   }
1934539b441SAlexey Lapshin 
1944539b441SAlexey Lapshin   std::string FileName = Opts.BuildSeparateDebugFile
1954539b441SAlexey Lapshin                              ? Opts.getSeparateDebugFileName()
1964539b441SAlexey Lapshin                              : Opts.OutputFileName;
1974539b441SAlexey Lapshin   Expected<OwningBinary<Binary>> BinOrErr = createBinary(FileName);
1984539b441SAlexey Lapshin   if (!BinOrErr)
1994539b441SAlexey Lapshin     return createFileError(FileName, BinOrErr.takeError());
2004539b441SAlexey Lapshin 
2014539b441SAlexey Lapshin   if (BinOrErr->getBinary()->isObject()) {
2024539b441SAlexey Lapshin     if (ObjectFile *Obj = static_cast<ObjectFile *>(BinOrErr->getBinary())) {
2034539b441SAlexey Lapshin       verbose("Verifying DWARF...", Opts.Verbose);
2044539b441SAlexey Lapshin       std::unique_ptr<DWARFContext> DICtx = DWARFContext::create(*Obj);
2054539b441SAlexey Lapshin       DIDumpOptions DumpOpts;
2064539b441SAlexey Lapshin       if (!DICtx->verify(Opts.Verbose ? outs() : nulls(),
2074539b441SAlexey Lapshin                          DumpOpts.noImplicitRecursion()))
2084539b441SAlexey Lapshin         return createFileError(FileName,
2094539b441SAlexey Lapshin                                createError("output verification failed"));
2104539b441SAlexey Lapshin 
2114539b441SAlexey Lapshin       return Error::success();
2124539b441SAlexey Lapshin     }
2134539b441SAlexey Lapshin   }
2144539b441SAlexey Lapshin 
2154539b441SAlexey Lapshin   // The file "FileName" was created by this utility in the previous steps
2164539b441SAlexey Lapshin   // (i.e. it is already known that it should pass the isObject check).
2174539b441SAlexey Lapshin   // If the createBinary() function does not return an error, the isObject
2184539b441SAlexey Lapshin   // check should also be successful.
2194539b441SAlexey Lapshin   llvm_unreachable(
2204539b441SAlexey Lapshin       formatv("tool unexpectedly did not emit a supported object file: '{0}'",
2214539b441SAlexey Lapshin               FileName)
2224539b441SAlexey Lapshin           .str()
2234539b441SAlexey Lapshin           .c_str());
2244539b441SAlexey Lapshin }
2254539b441SAlexey Lapshin 
2264539b441SAlexey Lapshin class raw_crc_ostream : public raw_ostream {
2274539b441SAlexey Lapshin public:
2284539b441SAlexey Lapshin   explicit raw_crc_ostream(raw_ostream &O) : OS(O) { SetUnbuffered(); }
2294539b441SAlexey Lapshin 
2304539b441SAlexey Lapshin   void reserveExtraSpace(uint64_t ExtraSize) override {
2314539b441SAlexey Lapshin     OS.reserveExtraSpace(ExtraSize);
2324539b441SAlexey Lapshin   }
2334539b441SAlexey Lapshin 
2344539b441SAlexey Lapshin   uint32_t getCRC32() { return CRC32; }
2354539b441SAlexey Lapshin 
2364539b441SAlexey Lapshin protected:
2374539b441SAlexey Lapshin   raw_ostream &OS;
2384539b441SAlexey Lapshin   uint32_t CRC32 = 0;
2394539b441SAlexey Lapshin 
2404539b441SAlexey Lapshin   /// See raw_ostream::write_impl.
2414539b441SAlexey Lapshin   void write_impl(const char *Ptr, size_t Size) override {
2424539b441SAlexey Lapshin     CRC32 = crc32(
2434539b441SAlexey Lapshin         CRC32, ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Ptr), Size));
2444539b441SAlexey Lapshin     OS.write(Ptr, Size);
2454539b441SAlexey Lapshin   }
2464539b441SAlexey Lapshin 
2474539b441SAlexey Lapshin   /// Return the current position within the stream, not counting the bytes
2484539b441SAlexey Lapshin   /// currently in the buffer.
2494539b441SAlexey Lapshin   uint64_t current_pos() const override { return OS.tell(); }
2504539b441SAlexey Lapshin };
2514539b441SAlexey Lapshin 
2524539b441SAlexey Lapshin static Expected<uint32_t> saveSeparateDebugInfo(const Options &Opts,
2534539b441SAlexey Lapshin                                                 ObjectFile &InputFile) {
2544539b441SAlexey Lapshin   objcopy::ConfigManager Config;
2554539b441SAlexey Lapshin   std::string OutputFilename = Opts.getSeparateDebugFileName();
2564539b441SAlexey Lapshin   Config.Common.InputFilename = Opts.InputFileName;
2574539b441SAlexey Lapshin   Config.Common.OutputFilename = OutputFilename;
2584539b441SAlexey Lapshin   Config.Common.OnlyKeepDebug = true;
2594539b441SAlexey Lapshin   uint32_t WrittenFileCRC32 = 0;
2604539b441SAlexey Lapshin 
2614539b441SAlexey Lapshin   if (Error Err = writeToOutput(
2624539b441SAlexey Lapshin           Config.Common.OutputFilename, [&](raw_ostream &OutFile) -> Error {
2634539b441SAlexey Lapshin             raw_crc_ostream CRCBuffer(OutFile);
2644539b441SAlexey Lapshin             if (Error Err = objcopy::executeObjcopyOnBinary(Config, InputFile,
2654539b441SAlexey Lapshin                                                             CRCBuffer))
2664539b441SAlexey Lapshin               return Err;
2674539b441SAlexey Lapshin 
2684539b441SAlexey Lapshin             WrittenFileCRC32 = CRCBuffer.getCRC32();
2694539b441SAlexey Lapshin             return Error::success();
2704539b441SAlexey Lapshin           }))
2714539b441SAlexey Lapshin     return std::move(Err);
2724539b441SAlexey Lapshin 
2734539b441SAlexey Lapshin   return WrittenFileCRC32;
2744539b441SAlexey Lapshin }
2754539b441SAlexey Lapshin 
2764539b441SAlexey Lapshin static Error saveNonDebugInfo(const Options &Opts, ObjectFile &InputFile,
2774539b441SAlexey Lapshin                               uint32_t GnuDebugLinkCRC32) {
2784539b441SAlexey Lapshin   objcopy::ConfigManager Config;
2794539b441SAlexey Lapshin   Config.Common.InputFilename = Opts.InputFileName;
2804539b441SAlexey Lapshin   Config.Common.OutputFilename = Opts.OutputFileName;
2814539b441SAlexey Lapshin   Config.Common.StripDebug = true;
2824539b441SAlexey Lapshin   std::string SeparateDebugFileName = Opts.getSeparateDebugFileName();
2834539b441SAlexey Lapshin   Config.Common.AddGnuDebugLink = sys::path::filename(SeparateDebugFileName);
2844539b441SAlexey Lapshin   Config.Common.GnuDebugLinkCRC32 = GnuDebugLinkCRC32;
2854539b441SAlexey Lapshin 
2864539b441SAlexey Lapshin   if (Error Err = writeToOutput(
2874539b441SAlexey Lapshin           Config.Common.OutputFilename, [&](raw_ostream &OutFile) -> Error {
2884539b441SAlexey Lapshin             if (Error Err =
2894539b441SAlexey Lapshin                     objcopy::executeObjcopyOnBinary(Config, InputFile, OutFile))
2904539b441SAlexey Lapshin               return Err;
2914539b441SAlexey Lapshin 
2924539b441SAlexey Lapshin             return Error::success();
2934539b441SAlexey Lapshin           }))
2944539b441SAlexey Lapshin     return Err;
2954539b441SAlexey Lapshin 
2964539b441SAlexey Lapshin   return Error::success();
2974539b441SAlexey Lapshin }
2984539b441SAlexey Lapshin 
2994539b441SAlexey Lapshin static Error splitDebugIntoSeparateFile(const Options &Opts,
3004539b441SAlexey Lapshin                                         ObjectFile &InputFile) {
3014539b441SAlexey Lapshin   Expected<uint32_t> SeparateDebugFileCRC32OrErr =
3024539b441SAlexey Lapshin       saveSeparateDebugInfo(Opts, InputFile);
3034539b441SAlexey Lapshin   if (!SeparateDebugFileCRC32OrErr)
3044539b441SAlexey Lapshin     return SeparateDebugFileCRC32OrErr.takeError();
3054539b441SAlexey Lapshin 
3064539b441SAlexey Lapshin   if (Error Err =
3074539b441SAlexey Lapshin           saveNonDebugInfo(Opts, InputFile, *SeparateDebugFileCRC32OrErr))
3084539b441SAlexey Lapshin     return Err;
3094539b441SAlexey Lapshin 
3104539b441SAlexey Lapshin   return Error::success();
3114539b441SAlexey Lapshin }
3124539b441SAlexey Lapshin 
3134539b441SAlexey Lapshin using DebugInfoBits = SmallString<10000>;
3144539b441SAlexey Lapshin 
3154539b441SAlexey Lapshin static Error addSectionsFromLinkedData(objcopy::ConfigManager &Config,
3164539b441SAlexey Lapshin                                        ObjectFile &InputFile,
3174539b441SAlexey Lapshin                                        DebugInfoBits &LinkedDebugInfoBits) {
318ae002f8bSKazu Hirata   if (isa<ELFObjectFile<ELF32LE>>(&InputFile)) {
3194539b441SAlexey Lapshin     Expected<ELFObjectFile<ELF32LE>> MemFile = ELFObjectFile<ELF32LE>::create(
3204539b441SAlexey Lapshin         MemoryBufferRef(LinkedDebugInfoBits, ""));
3214539b441SAlexey Lapshin     if (!MemFile)
3224539b441SAlexey Lapshin       return MemFile.takeError();
3234539b441SAlexey Lapshin 
3244539b441SAlexey Lapshin     if (Error Err = setConfigToAddNewDebugSections(Config, *MemFile))
3254539b441SAlexey Lapshin       return Err;
326ae002f8bSKazu Hirata   } else if (isa<ELFObjectFile<ELF64LE>>(&InputFile)) {
3274539b441SAlexey Lapshin     Expected<ELFObjectFile<ELF64LE>> MemFile = ELFObjectFile<ELF64LE>::create(
3284539b441SAlexey Lapshin         MemoryBufferRef(LinkedDebugInfoBits, ""));
3294539b441SAlexey Lapshin     if (!MemFile)
3304539b441SAlexey Lapshin       return MemFile.takeError();
3314539b441SAlexey Lapshin 
3324539b441SAlexey Lapshin     if (Error Err = setConfigToAddNewDebugSections(Config, *MemFile))
3334539b441SAlexey Lapshin       return Err;
334ae002f8bSKazu Hirata   } else if (isa<ELFObjectFile<ELF32BE>>(&InputFile)) {
3354539b441SAlexey Lapshin     Expected<ELFObjectFile<ELF32BE>> MemFile = ELFObjectFile<ELF32BE>::create(
3364539b441SAlexey Lapshin         MemoryBufferRef(LinkedDebugInfoBits, ""));
3374539b441SAlexey Lapshin     if (!MemFile)
3384539b441SAlexey Lapshin       return MemFile.takeError();
3394539b441SAlexey Lapshin 
3404539b441SAlexey Lapshin     if (Error Err = setConfigToAddNewDebugSections(Config, *MemFile))
3414539b441SAlexey Lapshin       return Err;
342ae002f8bSKazu Hirata   } else if (isa<ELFObjectFile<ELF64BE>>(&InputFile)) {
3434539b441SAlexey Lapshin     Expected<ELFObjectFile<ELF64BE>> MemFile = ELFObjectFile<ELF64BE>::create(
3444539b441SAlexey Lapshin         MemoryBufferRef(LinkedDebugInfoBits, ""));
3454539b441SAlexey Lapshin     if (!MemFile)
3464539b441SAlexey Lapshin       return MemFile.takeError();
3474539b441SAlexey Lapshin 
3484539b441SAlexey Lapshin     if (Error Err = setConfigToAddNewDebugSections(Config, *MemFile))
3494539b441SAlexey Lapshin       return Err;
3504539b441SAlexey Lapshin   } else
3514539b441SAlexey Lapshin     return createStringError(std::errc::invalid_argument,
3524539b441SAlexey Lapshin                              "unsupported file format");
3534539b441SAlexey Lapshin 
3544539b441SAlexey Lapshin   return Error::success();
3554539b441SAlexey Lapshin }
3564539b441SAlexey Lapshin 
3574539b441SAlexey Lapshin static Expected<uint32_t>
3584539b441SAlexey Lapshin saveSeparateLinkedDebugInfo(const Options &Opts, ObjectFile &InputFile,
3594539b441SAlexey Lapshin                             DebugInfoBits LinkedDebugInfoBits) {
3604539b441SAlexey Lapshin   objcopy::ConfigManager Config;
3614539b441SAlexey Lapshin   std::string OutputFilename = Opts.getSeparateDebugFileName();
3624539b441SAlexey Lapshin   Config.Common.InputFilename = Opts.InputFileName;
3634539b441SAlexey Lapshin   Config.Common.OutputFilename = OutputFilename;
3644539b441SAlexey Lapshin   Config.Common.StripDebug = true;
3654539b441SAlexey Lapshin   Config.Common.OnlyKeepDebug = true;
3664539b441SAlexey Lapshin   uint32_t WrittenFileCRC32 = 0;
3674539b441SAlexey Lapshin 
3684539b441SAlexey Lapshin   if (Error Err =
3694539b441SAlexey Lapshin           addSectionsFromLinkedData(Config, InputFile, LinkedDebugInfoBits))
3704539b441SAlexey Lapshin     return std::move(Err);
3714539b441SAlexey Lapshin 
3724539b441SAlexey Lapshin   if (Error Err = writeToOutput(
3734539b441SAlexey Lapshin           Config.Common.OutputFilename, [&](raw_ostream &OutFile) -> Error {
3744539b441SAlexey Lapshin             raw_crc_ostream CRCBuffer(OutFile);
3754539b441SAlexey Lapshin 
3764539b441SAlexey Lapshin             if (Error Err = objcopy::executeObjcopyOnBinary(Config, InputFile,
3774539b441SAlexey Lapshin                                                             CRCBuffer))
3784539b441SAlexey Lapshin               return Err;
3794539b441SAlexey Lapshin 
3804539b441SAlexey Lapshin             WrittenFileCRC32 = CRCBuffer.getCRC32();
3814539b441SAlexey Lapshin             return Error::success();
3824539b441SAlexey Lapshin           }))
3834539b441SAlexey Lapshin     return std::move(Err);
3844539b441SAlexey Lapshin 
3854539b441SAlexey Lapshin   return WrittenFileCRC32;
3864539b441SAlexey Lapshin }
3874539b441SAlexey Lapshin 
3884539b441SAlexey Lapshin static Error saveSingleLinkedDebugInfo(const Options &Opts,
3894539b441SAlexey Lapshin                                        ObjectFile &InputFile,
3904539b441SAlexey Lapshin                                        DebugInfoBits LinkedDebugInfoBits) {
3914539b441SAlexey Lapshin   objcopy::ConfigManager Config;
3924539b441SAlexey Lapshin 
3934539b441SAlexey Lapshin   Config.Common.InputFilename = Opts.InputFileName;
3944539b441SAlexey Lapshin   Config.Common.OutputFilename = Opts.OutputFileName;
3954539b441SAlexey Lapshin   Config.Common.StripDebug = true;
3964539b441SAlexey Lapshin   if (Error Err =
3974539b441SAlexey Lapshin           addSectionsFromLinkedData(Config, InputFile, LinkedDebugInfoBits))
3984539b441SAlexey Lapshin     return Err;
3994539b441SAlexey Lapshin 
4004539b441SAlexey Lapshin   if (Error Err = writeToOutput(
4014539b441SAlexey Lapshin           Config.Common.OutputFilename, [&](raw_ostream &OutFile) -> Error {
4024539b441SAlexey Lapshin             return objcopy::executeObjcopyOnBinary(Config, InputFile, OutFile);
4034539b441SAlexey Lapshin           }))
4044539b441SAlexey Lapshin     return Err;
4054539b441SAlexey Lapshin 
4064539b441SAlexey Lapshin   return Error::success();
4074539b441SAlexey Lapshin }
4084539b441SAlexey Lapshin 
4094539b441SAlexey Lapshin static Error saveLinkedDebugInfo(const Options &Opts, ObjectFile &InputFile,
4104539b441SAlexey Lapshin                                  DebugInfoBits LinkedDebugInfoBits) {
4114539b441SAlexey Lapshin   if (Opts.BuildSeparateDebugFile) {
4124539b441SAlexey Lapshin     Expected<uint32_t> SeparateDebugFileCRC32OrErr =
4134539b441SAlexey Lapshin         saveSeparateLinkedDebugInfo(Opts, InputFile,
4144539b441SAlexey Lapshin                                     std::move(LinkedDebugInfoBits));
4154539b441SAlexey Lapshin     if (!SeparateDebugFileCRC32OrErr)
4164539b441SAlexey Lapshin       return SeparateDebugFileCRC32OrErr.takeError();
4174539b441SAlexey Lapshin 
4184539b441SAlexey Lapshin     if (Error Err =
4194539b441SAlexey Lapshin             saveNonDebugInfo(Opts, InputFile, *SeparateDebugFileCRC32OrErr))
4204539b441SAlexey Lapshin       return Err;
4214539b441SAlexey Lapshin   } else {
4224539b441SAlexey Lapshin     if (Error Err = saveSingleLinkedDebugInfo(Opts, InputFile,
4234539b441SAlexey Lapshin                                               std::move(LinkedDebugInfoBits)))
4244539b441SAlexey Lapshin       return Err;
4254539b441SAlexey Lapshin   }
4264539b441SAlexey Lapshin 
4274539b441SAlexey Lapshin   return Error::success();
4284539b441SAlexey Lapshin }
4294539b441SAlexey Lapshin 
4304539b441SAlexey Lapshin static Error saveCopyOfFile(const Options &Opts, ObjectFile &InputFile) {
4314539b441SAlexey Lapshin   objcopy::ConfigManager Config;
4324539b441SAlexey Lapshin 
4334539b441SAlexey Lapshin   Config.Common.InputFilename = Opts.InputFileName;
4344539b441SAlexey Lapshin   Config.Common.OutputFilename = Opts.OutputFileName;
4354539b441SAlexey Lapshin 
4364539b441SAlexey Lapshin   if (Error Err = writeToOutput(
4374539b441SAlexey Lapshin           Config.Common.OutputFilename, [&](raw_ostream &OutFile) -> Error {
4384539b441SAlexey Lapshin             return objcopy::executeObjcopyOnBinary(Config, InputFile, OutFile);
4394539b441SAlexey Lapshin           }))
4404539b441SAlexey Lapshin     return Err;
4414539b441SAlexey Lapshin 
4424539b441SAlexey Lapshin   return Error::success();
4434539b441SAlexey Lapshin }
4444539b441SAlexey Lapshin 
4454539b441SAlexey Lapshin static Error applyCLOptions(const struct Options &Opts, ObjectFile &InputFile) {
4462216ee49SAlexey Lapshin   if (Opts.DoGarbageCollection ||
4472216ee49SAlexey Lapshin       Opts.AccelTableKind != DwarfUtilAccelKind::None) {
4482216ee49SAlexey Lapshin     verbose("Do debug info linking...", Opts.Verbose);
4494539b441SAlexey Lapshin 
4504539b441SAlexey Lapshin     DebugInfoBits LinkedDebugInfo;
4514539b441SAlexey Lapshin     raw_svector_ostream OutStream(LinkedDebugInfo);
4524539b441SAlexey Lapshin 
453e74197bcSAlexey Lapshin     if (Error Err = linkDebugInfo(InputFile, Opts, OutStream))
454e74197bcSAlexey Lapshin       return Err;
455e74197bcSAlexey Lapshin 
4564539b441SAlexey Lapshin     if (Error Err =
4574539b441SAlexey Lapshin             saveLinkedDebugInfo(Opts, InputFile, std::move(LinkedDebugInfo)))
4584539b441SAlexey Lapshin       return Err;
4594539b441SAlexey Lapshin 
4604539b441SAlexey Lapshin     return Error::success();
4614539b441SAlexey Lapshin   } else if (Opts.BuildSeparateDebugFile) {
4624539b441SAlexey Lapshin     if (Error Err = splitDebugIntoSeparateFile(Opts, InputFile))
4634539b441SAlexey Lapshin       return Err;
4644539b441SAlexey Lapshin   } else {
4654539b441SAlexey Lapshin     if (Error Err = saveCopyOfFile(Opts, InputFile))
4664539b441SAlexey Lapshin       return Err;
4674539b441SAlexey Lapshin   }
4684539b441SAlexey Lapshin 
4694539b441SAlexey Lapshin   return Error::success();
4704539b441SAlexey Lapshin }
4714539b441SAlexey Lapshin 
4724539b441SAlexey Lapshin } // end of namespace dwarfutil
4734539b441SAlexey Lapshin } // end of namespace llvm
4744539b441SAlexey Lapshin 
4754539b441SAlexey Lapshin int main(int Argc, char const *Argv[]) {
4764539b441SAlexey Lapshin   using namespace dwarfutil;
4774539b441SAlexey Lapshin 
4784539b441SAlexey Lapshin   InitLLVM X(Argc, Argv);
4794539b441SAlexey Lapshin   ToolName = Argv[0];
4804539b441SAlexey Lapshin 
4814539b441SAlexey Lapshin   // Parse arguments.
4824539b441SAlexey Lapshin   DwarfutilOptTable T;
4834539b441SAlexey Lapshin   unsigned MAI;
4844539b441SAlexey Lapshin   unsigned MAC;
48538818b60Sserge-sans-paille   ArrayRef<const char *> ArgsArr = ArrayRef(Argv + 1, Argc - 1);
4864539b441SAlexey Lapshin   opt::InputArgList Args = T.ParseArgs(ArgsArr, MAI, MAC);
4874539b441SAlexey Lapshin 
4884539b441SAlexey Lapshin   if (Args.hasArg(OPT_help) || Args.size() == 0) {
4894539b441SAlexey Lapshin     T.printHelp(
4904539b441SAlexey Lapshin         outs(), (ToolName + " [options] <input file> <output file>").c_str(),
4914539b441SAlexey Lapshin         "llvm-dwarfutil is a tool to copy and manipulate debug info", false);
4924539b441SAlexey Lapshin     return EXIT_SUCCESS;
4934539b441SAlexey Lapshin   }
4944539b441SAlexey Lapshin 
4954539b441SAlexey Lapshin   if (Args.hasArg(OPT_version)) {
4964539b441SAlexey Lapshin     cl::PrintVersionMessage();
4974539b441SAlexey Lapshin     return EXIT_SUCCESS;
4984539b441SAlexey Lapshin   }
4994539b441SAlexey Lapshin 
5004539b441SAlexey Lapshin   Options Opts;
5014539b441SAlexey Lapshin   if (Error Err = validateAndSetOptions(Args, Opts))
5024539b441SAlexey Lapshin     error(std::move(Err), dwarfutil::ToolName);
5034539b441SAlexey Lapshin 
5044539b441SAlexey Lapshin   InitializeAllTargets();
5054539b441SAlexey Lapshin   InitializeAllTargetMCs();
5064539b441SAlexey Lapshin   InitializeAllTargetInfos();
5074539b441SAlexey Lapshin   InitializeAllAsmPrinters();
5084539b441SAlexey Lapshin 
5094539b441SAlexey Lapshin   ErrorOr<std::unique_ptr<MemoryBuffer>> BuffOrErr =
5104539b441SAlexey Lapshin       MemoryBuffer::getFileOrSTDIN(Opts.InputFileName);
5114539b441SAlexey Lapshin   if (BuffOrErr.getError())
5124539b441SAlexey Lapshin     error(createFileError(Opts.InputFileName, BuffOrErr.getError()));
5134539b441SAlexey Lapshin 
5144539b441SAlexey Lapshin   Expected<std::unique_ptr<Binary>> BinOrErr =
5154539b441SAlexey Lapshin       object::createBinary(**BuffOrErr);
5164539b441SAlexey Lapshin   if (!BinOrErr)
5174539b441SAlexey Lapshin     error(createFileError(Opts.InputFileName, BinOrErr.takeError()));
5184539b441SAlexey Lapshin 
5194539b441SAlexey Lapshin   Expected<FilePermissionsApplier> PermsApplierOrErr =
5204539b441SAlexey Lapshin       FilePermissionsApplier::create(Opts.InputFileName);
5214539b441SAlexey Lapshin   if (!PermsApplierOrErr)
5224539b441SAlexey Lapshin     error(createFileError(Opts.InputFileName, PermsApplierOrErr.takeError()));
5234539b441SAlexey Lapshin 
5244539b441SAlexey Lapshin   if (!(*BinOrErr)->isObject())
5254539b441SAlexey Lapshin     error(createFileError(Opts.InputFileName,
5264539b441SAlexey Lapshin                           createError("unsupported input file")));
5274539b441SAlexey Lapshin 
5284539b441SAlexey Lapshin   if (Error Err =
5294539b441SAlexey Lapshin           applyCLOptions(Opts, *static_cast<ObjectFile *>((*BinOrErr).get())))
5304539b441SAlexey Lapshin     error(createFileError(Opts.InputFileName, std::move(Err)));
5314539b441SAlexey Lapshin 
5324539b441SAlexey Lapshin   BinOrErr->reset();
5334539b441SAlexey Lapshin   BuffOrErr->reset();
5344539b441SAlexey Lapshin 
5354539b441SAlexey Lapshin   if (Error Err = PermsApplierOrErr->apply(Opts.OutputFileName))
5364539b441SAlexey Lapshin     error(std::move(Err));
5374539b441SAlexey Lapshin 
5384539b441SAlexey Lapshin   if (Opts.BuildSeparateDebugFile)
5394539b441SAlexey Lapshin     if (Error Err = PermsApplierOrErr->apply(Opts.getSeparateDebugFileName()))
5404539b441SAlexey Lapshin       error(std::move(Err));
5414539b441SAlexey Lapshin 
5424539b441SAlexey Lapshin   if (Opts.Verify) {
5434539b441SAlexey Lapshin     if (Error Err = verifyOutput(Opts))
5444539b441SAlexey Lapshin       error(std::move(Err));
5454539b441SAlexey Lapshin   }
5464539b441SAlexey Lapshin 
5474539b441SAlexey Lapshin   return EXIT_SUCCESS;
5484539b441SAlexey Lapshin }
549