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