1fcaf7f86SDimitry Andric //=== llvm-dwarfutil.cpp --------------------------------------------------===// 2fcaf7f86SDimitry Andric // 3fcaf7f86SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4fcaf7f86SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5fcaf7f86SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6fcaf7f86SDimitry Andric // 7fcaf7f86SDimitry Andric //===----------------------------------------------------------------------===// 8fcaf7f86SDimitry Andric 9fcaf7f86SDimitry Andric #include "DebugInfoLinker.h" 10fcaf7f86SDimitry Andric #include "Error.h" 11fcaf7f86SDimitry Andric #include "Options.h" 12fcaf7f86SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFContext.h" 13fcaf7f86SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFVerifier.h" 14fcaf7f86SDimitry Andric #include "llvm/MC/MCTargetOptionsCommandFlags.h" 15fcaf7f86SDimitry Andric #include "llvm/ObjCopy/CommonConfig.h" 16fcaf7f86SDimitry Andric #include "llvm/ObjCopy/ConfigManager.h" 17fcaf7f86SDimitry Andric #include "llvm/ObjCopy/ObjCopy.h" 18fcaf7f86SDimitry Andric #include "llvm/Option/Arg.h" 19fcaf7f86SDimitry Andric #include "llvm/Option/ArgList.h" 20fcaf7f86SDimitry Andric #include "llvm/Option/Option.h" 21fcaf7f86SDimitry Andric #include "llvm/Support/CRC.h" 22fcaf7f86SDimitry Andric #include "llvm/Support/CommandLine.h" 23fcaf7f86SDimitry Andric #include "llvm/Support/FileUtilities.h" 24fcaf7f86SDimitry Andric #include "llvm/Support/InitLLVM.h" 25fcaf7f86SDimitry Andric #include "llvm/Support/PrettyStackTrace.h" 26fcaf7f86SDimitry Andric #include "llvm/Support/Process.h" 27fcaf7f86SDimitry Andric #include "llvm/Support/Signals.h" 28fcaf7f86SDimitry Andric #include "llvm/Support/TargetSelect.h" 29fcaf7f86SDimitry Andric 30fcaf7f86SDimitry Andric using namespace llvm; 31fcaf7f86SDimitry Andric using namespace object; 32fcaf7f86SDimitry Andric 33fcaf7f86SDimitry Andric namespace { 34fcaf7f86SDimitry Andric enum ID { 35fcaf7f86SDimitry Andric OPT_INVALID = 0, // This is not an option ID. 36fcaf7f86SDimitry Andric #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ 37fcaf7f86SDimitry Andric HELPTEXT, METAVAR, VALUES) \ 38fcaf7f86SDimitry Andric OPT_##ID, 39fcaf7f86SDimitry Andric #include "Options.inc" 40fcaf7f86SDimitry Andric #undef OPTION 41fcaf7f86SDimitry Andric }; 42fcaf7f86SDimitry Andric 43bdd1243dSDimitry Andric #define PREFIX(NAME, VALUE) \ 44bdd1243dSDimitry Andric static constexpr StringLiteral NAME##_init[] = VALUE; \ 45bdd1243dSDimitry Andric static constexpr ArrayRef<StringLiteral> NAME(NAME##_init, \ 46bdd1243dSDimitry Andric std::size(NAME##_init) - 1); 47fcaf7f86SDimitry Andric #include "Options.inc" 48fcaf7f86SDimitry Andric #undef PREFIX 49fcaf7f86SDimitry Andric 50bdd1243dSDimitry Andric static constexpr opt::OptTable::Info InfoTable[] = { 51fcaf7f86SDimitry Andric #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ 52fcaf7f86SDimitry Andric HELPTEXT, METAVAR, VALUES) \ 53fcaf7f86SDimitry Andric { \ 54fcaf7f86SDimitry Andric PREFIX, NAME, HELPTEXT, \ 55fcaf7f86SDimitry Andric METAVAR, OPT_##ID, opt::Option::KIND##Class, \ 56fcaf7f86SDimitry Andric PARAM, FLAGS, OPT_##GROUP, \ 57fcaf7f86SDimitry Andric OPT_##ALIAS, ALIASARGS, VALUES}, 58fcaf7f86SDimitry Andric #include "Options.inc" 59fcaf7f86SDimitry Andric #undef OPTION 60fcaf7f86SDimitry Andric }; 61fcaf7f86SDimitry Andric 62bdd1243dSDimitry Andric class DwarfutilOptTable : public opt::GenericOptTable { 63fcaf7f86SDimitry Andric public: 64bdd1243dSDimitry Andric DwarfutilOptTable() : opt::GenericOptTable(InfoTable) {} 65fcaf7f86SDimitry Andric }; 66fcaf7f86SDimitry Andric } // namespace 67fcaf7f86SDimitry Andric 68fcaf7f86SDimitry Andric namespace llvm { 69fcaf7f86SDimitry Andric namespace dwarfutil { 70fcaf7f86SDimitry Andric 71fcaf7f86SDimitry Andric std::string ToolName; 72fcaf7f86SDimitry Andric 73fcaf7f86SDimitry Andric static mc::RegisterMCTargetOptionsFlags MOF; 74fcaf7f86SDimitry Andric 75fcaf7f86SDimitry Andric static Error validateAndSetOptions(opt::InputArgList &Args, Options &Options) { 76fcaf7f86SDimitry Andric auto UnknownArgs = Args.filtered(OPT_UNKNOWN); 77fcaf7f86SDimitry Andric if (!UnknownArgs.empty()) 78fcaf7f86SDimitry Andric return createStringError( 79fcaf7f86SDimitry Andric std::errc::invalid_argument, 80fcaf7f86SDimitry Andric formatv("unknown option: {0}", (*UnknownArgs.begin())->getSpelling()) 81fcaf7f86SDimitry Andric .str() 82fcaf7f86SDimitry Andric .c_str()); 83fcaf7f86SDimitry Andric 84fcaf7f86SDimitry Andric std::vector<std::string> InputFiles = Args.getAllArgValues(OPT_INPUT); 85fcaf7f86SDimitry Andric if (InputFiles.size() != 2) 86fcaf7f86SDimitry Andric return createStringError( 87fcaf7f86SDimitry Andric std::errc::invalid_argument, 88fcaf7f86SDimitry Andric formatv("exactly two positional arguments expected, {0} provided", 89fcaf7f86SDimitry Andric InputFiles.size()) 90fcaf7f86SDimitry Andric .str() 91fcaf7f86SDimitry Andric .c_str()); 92fcaf7f86SDimitry Andric 93fcaf7f86SDimitry Andric Options.InputFileName = InputFiles[0]; 94fcaf7f86SDimitry Andric Options.OutputFileName = InputFiles[1]; 95fcaf7f86SDimitry Andric 96fcaf7f86SDimitry Andric Options.BuildSeparateDebugFile = 97fcaf7f86SDimitry Andric Args.hasFlag(OPT_separate_debug_file, OPT_no_separate_debug_file, false); 98fcaf7f86SDimitry Andric Options.DoODRDeduplication = 99fcaf7f86SDimitry Andric Args.hasFlag(OPT_odr_deduplication, OPT_no_odr_deduplication, true); 100fcaf7f86SDimitry Andric Options.DoGarbageCollection = 101fcaf7f86SDimitry Andric Args.hasFlag(OPT_garbage_collection, OPT_no_garbage_collection, true); 102fcaf7f86SDimitry Andric Options.Verbose = Args.hasArg(OPT_verbose); 103fcaf7f86SDimitry Andric Options.Verify = Args.hasArg(OPT_verify); 104fcaf7f86SDimitry Andric 105fcaf7f86SDimitry Andric if (opt::Arg *NumThreads = Args.getLastArg(OPT_threads)) 106fcaf7f86SDimitry Andric Options.NumThreads = atoi(NumThreads->getValue()); 107fcaf7f86SDimitry Andric else 108fcaf7f86SDimitry Andric Options.NumThreads = 0; // Use all available hardware threads 109fcaf7f86SDimitry Andric 110fcaf7f86SDimitry Andric if (opt::Arg *Tombstone = Args.getLastArg(OPT_tombstone)) { 111fcaf7f86SDimitry Andric StringRef S = Tombstone->getValue(); 112fcaf7f86SDimitry Andric if (S == "bfd") 113fcaf7f86SDimitry Andric Options.Tombstone = TombstoneKind::BFD; 114fcaf7f86SDimitry Andric else if (S == "maxpc") 115fcaf7f86SDimitry Andric Options.Tombstone = TombstoneKind::MaxPC; 116fcaf7f86SDimitry Andric else if (S == "universal") 117fcaf7f86SDimitry Andric Options.Tombstone = TombstoneKind::Universal; 118fcaf7f86SDimitry Andric else if (S == "exec") 119fcaf7f86SDimitry Andric Options.Tombstone = TombstoneKind::Exec; 120fcaf7f86SDimitry Andric else 121fcaf7f86SDimitry Andric return createStringError( 122fcaf7f86SDimitry Andric std::errc::invalid_argument, 123fcaf7f86SDimitry Andric formatv("unknown tombstone value: '{0}'", S).str().c_str()); 124fcaf7f86SDimitry Andric } 125fcaf7f86SDimitry Andric 126*06c3fb27SDimitry Andric if (opt::Arg *LinkerKind = Args.getLastArg(OPT_linker)) { 127*06c3fb27SDimitry Andric StringRef S = LinkerKind->getValue(); 128*06c3fb27SDimitry Andric if (S == "apple") 129*06c3fb27SDimitry Andric Options.UseLLVMDWARFLinker = false; 130*06c3fb27SDimitry Andric else if (S == "llvm") 131*06c3fb27SDimitry Andric Options.UseLLVMDWARFLinker = true; 132*06c3fb27SDimitry Andric else 133*06c3fb27SDimitry Andric return createStringError( 134*06c3fb27SDimitry Andric std::errc::invalid_argument, 135*06c3fb27SDimitry Andric formatv("unknown linker kind value: '{0}'", S).str().c_str()); 136*06c3fb27SDimitry Andric } 137*06c3fb27SDimitry Andric 138bdd1243dSDimitry Andric if (opt::Arg *BuildAccelerator = Args.getLastArg(OPT_build_accelerator)) { 139bdd1243dSDimitry Andric StringRef S = BuildAccelerator->getValue(); 140bdd1243dSDimitry Andric 141bdd1243dSDimitry Andric if (S == "none") 142bdd1243dSDimitry Andric Options.AccelTableKind = DwarfUtilAccelKind::None; 143bdd1243dSDimitry Andric else if (S == "DWARF") 144bdd1243dSDimitry Andric Options.AccelTableKind = DwarfUtilAccelKind::DWARF; 145bdd1243dSDimitry Andric else 146bdd1243dSDimitry Andric return createStringError( 147bdd1243dSDimitry Andric std::errc::invalid_argument, 148bdd1243dSDimitry Andric formatv("unknown build-accelerator value: '{0}'", S).str().c_str()); 149bdd1243dSDimitry Andric } 150bdd1243dSDimitry Andric 151fcaf7f86SDimitry Andric if (Options.Verbose) { 152fcaf7f86SDimitry Andric if (Options.NumThreads != 1 && Args.hasArg(OPT_threads)) 153fcaf7f86SDimitry Andric warning("--num-threads set to 1 because verbose mode is specified"); 154fcaf7f86SDimitry Andric 155fcaf7f86SDimitry Andric Options.NumThreads = 1; 156fcaf7f86SDimitry Andric } 157fcaf7f86SDimitry Andric 158fcaf7f86SDimitry Andric if (Options.DoODRDeduplication && Args.hasArg(OPT_odr_deduplication) && 159fcaf7f86SDimitry Andric !Options.DoGarbageCollection) 160fcaf7f86SDimitry Andric return createStringError( 161fcaf7f86SDimitry Andric std::errc::invalid_argument, 162fcaf7f86SDimitry Andric "cannot use --odr-deduplication without --garbage-collection"); 163fcaf7f86SDimitry Andric 164fcaf7f86SDimitry Andric if (Options.BuildSeparateDebugFile && Options.OutputFileName == "-") 165fcaf7f86SDimitry Andric return createStringError( 166fcaf7f86SDimitry Andric std::errc::invalid_argument, 167fcaf7f86SDimitry Andric "unable to write to stdout when --separate-debug-file specified"); 168fcaf7f86SDimitry Andric 169fcaf7f86SDimitry Andric return Error::success(); 170fcaf7f86SDimitry Andric } 171fcaf7f86SDimitry Andric 172fcaf7f86SDimitry Andric static Error setConfigToAddNewDebugSections(objcopy::ConfigManager &Config, 173fcaf7f86SDimitry Andric ObjectFile &ObjFile) { 174fcaf7f86SDimitry Andric // Add new debug sections. 175fcaf7f86SDimitry Andric for (SectionRef Sec : ObjFile.sections()) { 176fcaf7f86SDimitry Andric Expected<StringRef> SecName = Sec.getName(); 177fcaf7f86SDimitry Andric if (!SecName) 178fcaf7f86SDimitry Andric return SecName.takeError(); 179fcaf7f86SDimitry Andric 180fcaf7f86SDimitry Andric if (isDebugSection(*SecName)) { 181fcaf7f86SDimitry Andric Expected<StringRef> SecData = Sec.getContents(); 182fcaf7f86SDimitry Andric if (!SecData) 183fcaf7f86SDimitry Andric return SecData.takeError(); 184fcaf7f86SDimitry Andric 185fcaf7f86SDimitry Andric Config.Common.AddSection.emplace_back(objcopy::NewSectionInfo( 186fcaf7f86SDimitry Andric *SecName, MemoryBuffer::getMemBuffer(*SecData, *SecName, false))); 187fcaf7f86SDimitry Andric } 188fcaf7f86SDimitry Andric } 189fcaf7f86SDimitry Andric 190fcaf7f86SDimitry Andric return Error::success(); 191fcaf7f86SDimitry Andric } 192fcaf7f86SDimitry Andric 193fcaf7f86SDimitry Andric static Error verifyOutput(const Options &Opts) { 194fcaf7f86SDimitry Andric if (Opts.OutputFileName == "-") { 195fcaf7f86SDimitry Andric warning("verification skipped because writing to stdout"); 196fcaf7f86SDimitry Andric return Error::success(); 197fcaf7f86SDimitry Andric } 198fcaf7f86SDimitry Andric 199fcaf7f86SDimitry Andric std::string FileName = Opts.BuildSeparateDebugFile 200fcaf7f86SDimitry Andric ? Opts.getSeparateDebugFileName() 201fcaf7f86SDimitry Andric : Opts.OutputFileName; 202fcaf7f86SDimitry Andric Expected<OwningBinary<Binary>> BinOrErr = createBinary(FileName); 203fcaf7f86SDimitry Andric if (!BinOrErr) 204fcaf7f86SDimitry Andric return createFileError(FileName, BinOrErr.takeError()); 205fcaf7f86SDimitry Andric 206fcaf7f86SDimitry Andric if (BinOrErr->getBinary()->isObject()) { 207fcaf7f86SDimitry Andric if (ObjectFile *Obj = static_cast<ObjectFile *>(BinOrErr->getBinary())) { 208fcaf7f86SDimitry Andric verbose("Verifying DWARF...", Opts.Verbose); 209fcaf7f86SDimitry Andric std::unique_ptr<DWARFContext> DICtx = DWARFContext::create(*Obj); 210fcaf7f86SDimitry Andric DIDumpOptions DumpOpts; 211fcaf7f86SDimitry Andric if (!DICtx->verify(Opts.Verbose ? outs() : nulls(), 212fcaf7f86SDimitry Andric DumpOpts.noImplicitRecursion())) 213fcaf7f86SDimitry Andric return createFileError(FileName, 214fcaf7f86SDimitry Andric createError("output verification failed")); 215fcaf7f86SDimitry Andric 216fcaf7f86SDimitry Andric return Error::success(); 217fcaf7f86SDimitry Andric } 218fcaf7f86SDimitry Andric } 219fcaf7f86SDimitry Andric 220fcaf7f86SDimitry Andric // The file "FileName" was created by this utility in the previous steps 221fcaf7f86SDimitry Andric // (i.e. it is already known that it should pass the isObject check). 222fcaf7f86SDimitry Andric // If the createBinary() function does not return an error, the isObject 223fcaf7f86SDimitry Andric // check should also be successful. 224fcaf7f86SDimitry Andric llvm_unreachable( 225fcaf7f86SDimitry Andric formatv("tool unexpectedly did not emit a supported object file: '{0}'", 226fcaf7f86SDimitry Andric FileName) 227fcaf7f86SDimitry Andric .str() 228fcaf7f86SDimitry Andric .c_str()); 229fcaf7f86SDimitry Andric } 230fcaf7f86SDimitry Andric 231fcaf7f86SDimitry Andric class raw_crc_ostream : public raw_ostream { 232fcaf7f86SDimitry Andric public: 233fcaf7f86SDimitry Andric explicit raw_crc_ostream(raw_ostream &O) : OS(O) { SetUnbuffered(); } 234fcaf7f86SDimitry Andric 235fcaf7f86SDimitry Andric void reserveExtraSpace(uint64_t ExtraSize) override { 236fcaf7f86SDimitry Andric OS.reserveExtraSpace(ExtraSize); 237fcaf7f86SDimitry Andric } 238fcaf7f86SDimitry Andric 239fcaf7f86SDimitry Andric uint32_t getCRC32() { return CRC32; } 240fcaf7f86SDimitry Andric 241fcaf7f86SDimitry Andric protected: 242fcaf7f86SDimitry Andric raw_ostream &OS; 243fcaf7f86SDimitry Andric uint32_t CRC32 = 0; 244fcaf7f86SDimitry Andric 245fcaf7f86SDimitry Andric /// See raw_ostream::write_impl. 246fcaf7f86SDimitry Andric void write_impl(const char *Ptr, size_t Size) override { 247fcaf7f86SDimitry Andric CRC32 = crc32( 248fcaf7f86SDimitry Andric CRC32, ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Ptr), Size)); 249fcaf7f86SDimitry Andric OS.write(Ptr, Size); 250fcaf7f86SDimitry Andric } 251fcaf7f86SDimitry Andric 252fcaf7f86SDimitry Andric /// Return the current position within the stream, not counting the bytes 253fcaf7f86SDimitry Andric /// currently in the buffer. 254fcaf7f86SDimitry Andric uint64_t current_pos() const override { return OS.tell(); } 255fcaf7f86SDimitry Andric }; 256fcaf7f86SDimitry Andric 257fcaf7f86SDimitry Andric static Expected<uint32_t> saveSeparateDebugInfo(const Options &Opts, 258fcaf7f86SDimitry Andric ObjectFile &InputFile) { 259fcaf7f86SDimitry Andric objcopy::ConfigManager Config; 260fcaf7f86SDimitry Andric std::string OutputFilename = Opts.getSeparateDebugFileName(); 261fcaf7f86SDimitry Andric Config.Common.InputFilename = Opts.InputFileName; 262fcaf7f86SDimitry Andric Config.Common.OutputFilename = OutputFilename; 263fcaf7f86SDimitry Andric Config.Common.OnlyKeepDebug = true; 264fcaf7f86SDimitry Andric uint32_t WrittenFileCRC32 = 0; 265fcaf7f86SDimitry Andric 266fcaf7f86SDimitry Andric if (Error Err = writeToOutput( 267fcaf7f86SDimitry Andric Config.Common.OutputFilename, [&](raw_ostream &OutFile) -> Error { 268fcaf7f86SDimitry Andric raw_crc_ostream CRCBuffer(OutFile); 269fcaf7f86SDimitry Andric if (Error Err = objcopy::executeObjcopyOnBinary(Config, InputFile, 270fcaf7f86SDimitry Andric CRCBuffer)) 271fcaf7f86SDimitry Andric return Err; 272fcaf7f86SDimitry Andric 273fcaf7f86SDimitry Andric WrittenFileCRC32 = CRCBuffer.getCRC32(); 274fcaf7f86SDimitry Andric return Error::success(); 275fcaf7f86SDimitry Andric })) 276fcaf7f86SDimitry Andric return std::move(Err); 277fcaf7f86SDimitry Andric 278fcaf7f86SDimitry Andric return WrittenFileCRC32; 279fcaf7f86SDimitry Andric } 280fcaf7f86SDimitry Andric 281fcaf7f86SDimitry Andric static Error saveNonDebugInfo(const Options &Opts, ObjectFile &InputFile, 282fcaf7f86SDimitry Andric uint32_t GnuDebugLinkCRC32) { 283fcaf7f86SDimitry Andric objcopy::ConfigManager Config; 284fcaf7f86SDimitry Andric Config.Common.InputFilename = Opts.InputFileName; 285fcaf7f86SDimitry Andric Config.Common.OutputFilename = Opts.OutputFileName; 286fcaf7f86SDimitry Andric Config.Common.StripDebug = true; 287fcaf7f86SDimitry Andric std::string SeparateDebugFileName = Opts.getSeparateDebugFileName(); 288fcaf7f86SDimitry Andric Config.Common.AddGnuDebugLink = sys::path::filename(SeparateDebugFileName); 289fcaf7f86SDimitry Andric Config.Common.GnuDebugLinkCRC32 = GnuDebugLinkCRC32; 290fcaf7f86SDimitry Andric 291fcaf7f86SDimitry Andric if (Error Err = writeToOutput( 292fcaf7f86SDimitry Andric Config.Common.OutputFilename, [&](raw_ostream &OutFile) -> Error { 293fcaf7f86SDimitry Andric if (Error Err = 294fcaf7f86SDimitry Andric objcopy::executeObjcopyOnBinary(Config, InputFile, OutFile)) 295fcaf7f86SDimitry Andric return Err; 296fcaf7f86SDimitry Andric 297fcaf7f86SDimitry Andric return Error::success(); 298fcaf7f86SDimitry Andric })) 299fcaf7f86SDimitry Andric return Err; 300fcaf7f86SDimitry Andric 301fcaf7f86SDimitry Andric return Error::success(); 302fcaf7f86SDimitry Andric } 303fcaf7f86SDimitry Andric 304fcaf7f86SDimitry Andric static Error splitDebugIntoSeparateFile(const Options &Opts, 305fcaf7f86SDimitry Andric ObjectFile &InputFile) { 306fcaf7f86SDimitry Andric Expected<uint32_t> SeparateDebugFileCRC32OrErr = 307fcaf7f86SDimitry Andric saveSeparateDebugInfo(Opts, InputFile); 308fcaf7f86SDimitry Andric if (!SeparateDebugFileCRC32OrErr) 309fcaf7f86SDimitry Andric return SeparateDebugFileCRC32OrErr.takeError(); 310fcaf7f86SDimitry Andric 311fcaf7f86SDimitry Andric if (Error Err = 312fcaf7f86SDimitry Andric saveNonDebugInfo(Opts, InputFile, *SeparateDebugFileCRC32OrErr)) 313fcaf7f86SDimitry Andric return Err; 314fcaf7f86SDimitry Andric 315fcaf7f86SDimitry Andric return Error::success(); 316fcaf7f86SDimitry Andric } 317fcaf7f86SDimitry Andric 318fcaf7f86SDimitry Andric using DebugInfoBits = SmallString<10000>; 319fcaf7f86SDimitry Andric 320fcaf7f86SDimitry Andric static Error addSectionsFromLinkedData(objcopy::ConfigManager &Config, 321fcaf7f86SDimitry Andric ObjectFile &InputFile, 322fcaf7f86SDimitry Andric DebugInfoBits &LinkedDebugInfoBits) { 323972a253aSDimitry Andric if (isa<ELFObjectFile<ELF32LE>>(&InputFile)) { 324fcaf7f86SDimitry Andric Expected<ELFObjectFile<ELF32LE>> MemFile = ELFObjectFile<ELF32LE>::create( 325fcaf7f86SDimitry Andric MemoryBufferRef(LinkedDebugInfoBits, "")); 326fcaf7f86SDimitry Andric if (!MemFile) 327fcaf7f86SDimitry Andric return MemFile.takeError(); 328fcaf7f86SDimitry Andric 329fcaf7f86SDimitry Andric if (Error Err = setConfigToAddNewDebugSections(Config, *MemFile)) 330fcaf7f86SDimitry Andric return Err; 331972a253aSDimitry Andric } else if (isa<ELFObjectFile<ELF64LE>>(&InputFile)) { 332fcaf7f86SDimitry Andric Expected<ELFObjectFile<ELF64LE>> MemFile = ELFObjectFile<ELF64LE>::create( 333fcaf7f86SDimitry Andric MemoryBufferRef(LinkedDebugInfoBits, "")); 334fcaf7f86SDimitry Andric if (!MemFile) 335fcaf7f86SDimitry Andric return MemFile.takeError(); 336fcaf7f86SDimitry Andric 337fcaf7f86SDimitry Andric if (Error Err = setConfigToAddNewDebugSections(Config, *MemFile)) 338fcaf7f86SDimitry Andric return Err; 339972a253aSDimitry Andric } else if (isa<ELFObjectFile<ELF32BE>>(&InputFile)) { 340fcaf7f86SDimitry Andric Expected<ELFObjectFile<ELF32BE>> MemFile = ELFObjectFile<ELF32BE>::create( 341fcaf7f86SDimitry Andric MemoryBufferRef(LinkedDebugInfoBits, "")); 342fcaf7f86SDimitry Andric if (!MemFile) 343fcaf7f86SDimitry Andric return MemFile.takeError(); 344fcaf7f86SDimitry Andric 345fcaf7f86SDimitry Andric if (Error Err = setConfigToAddNewDebugSections(Config, *MemFile)) 346fcaf7f86SDimitry Andric return Err; 347972a253aSDimitry Andric } else if (isa<ELFObjectFile<ELF64BE>>(&InputFile)) { 348fcaf7f86SDimitry Andric Expected<ELFObjectFile<ELF64BE>> MemFile = ELFObjectFile<ELF64BE>::create( 349fcaf7f86SDimitry Andric MemoryBufferRef(LinkedDebugInfoBits, "")); 350fcaf7f86SDimitry Andric if (!MemFile) 351fcaf7f86SDimitry Andric return MemFile.takeError(); 352fcaf7f86SDimitry Andric 353fcaf7f86SDimitry Andric if (Error Err = setConfigToAddNewDebugSections(Config, *MemFile)) 354fcaf7f86SDimitry Andric return Err; 355fcaf7f86SDimitry Andric } else 356fcaf7f86SDimitry Andric return createStringError(std::errc::invalid_argument, 357fcaf7f86SDimitry Andric "unsupported file format"); 358fcaf7f86SDimitry Andric 359fcaf7f86SDimitry Andric return Error::success(); 360fcaf7f86SDimitry Andric } 361fcaf7f86SDimitry Andric 362fcaf7f86SDimitry Andric static Expected<uint32_t> 363fcaf7f86SDimitry Andric saveSeparateLinkedDebugInfo(const Options &Opts, ObjectFile &InputFile, 364fcaf7f86SDimitry Andric DebugInfoBits LinkedDebugInfoBits) { 365fcaf7f86SDimitry Andric objcopy::ConfigManager Config; 366fcaf7f86SDimitry Andric std::string OutputFilename = Opts.getSeparateDebugFileName(); 367fcaf7f86SDimitry Andric Config.Common.InputFilename = Opts.InputFileName; 368fcaf7f86SDimitry Andric Config.Common.OutputFilename = OutputFilename; 369fcaf7f86SDimitry Andric Config.Common.StripDebug = true; 370fcaf7f86SDimitry Andric Config.Common.OnlyKeepDebug = true; 371fcaf7f86SDimitry Andric uint32_t WrittenFileCRC32 = 0; 372fcaf7f86SDimitry Andric 373fcaf7f86SDimitry Andric if (Error Err = 374fcaf7f86SDimitry Andric addSectionsFromLinkedData(Config, InputFile, LinkedDebugInfoBits)) 375fcaf7f86SDimitry Andric return std::move(Err); 376fcaf7f86SDimitry Andric 377fcaf7f86SDimitry Andric if (Error Err = writeToOutput( 378fcaf7f86SDimitry Andric Config.Common.OutputFilename, [&](raw_ostream &OutFile) -> Error { 379fcaf7f86SDimitry Andric raw_crc_ostream CRCBuffer(OutFile); 380fcaf7f86SDimitry Andric 381fcaf7f86SDimitry Andric if (Error Err = objcopy::executeObjcopyOnBinary(Config, InputFile, 382fcaf7f86SDimitry Andric CRCBuffer)) 383fcaf7f86SDimitry Andric return Err; 384fcaf7f86SDimitry Andric 385fcaf7f86SDimitry Andric WrittenFileCRC32 = CRCBuffer.getCRC32(); 386fcaf7f86SDimitry Andric return Error::success(); 387fcaf7f86SDimitry Andric })) 388fcaf7f86SDimitry Andric return std::move(Err); 389fcaf7f86SDimitry Andric 390fcaf7f86SDimitry Andric return WrittenFileCRC32; 391fcaf7f86SDimitry Andric } 392fcaf7f86SDimitry Andric 393fcaf7f86SDimitry Andric static Error saveSingleLinkedDebugInfo(const Options &Opts, 394fcaf7f86SDimitry Andric ObjectFile &InputFile, 395fcaf7f86SDimitry Andric DebugInfoBits LinkedDebugInfoBits) { 396fcaf7f86SDimitry Andric objcopy::ConfigManager Config; 397fcaf7f86SDimitry Andric 398fcaf7f86SDimitry Andric Config.Common.InputFilename = Opts.InputFileName; 399fcaf7f86SDimitry Andric Config.Common.OutputFilename = Opts.OutputFileName; 400fcaf7f86SDimitry Andric Config.Common.StripDebug = true; 401fcaf7f86SDimitry Andric if (Error Err = 402fcaf7f86SDimitry Andric addSectionsFromLinkedData(Config, InputFile, LinkedDebugInfoBits)) 403fcaf7f86SDimitry Andric return Err; 404fcaf7f86SDimitry Andric 405fcaf7f86SDimitry Andric if (Error Err = writeToOutput( 406fcaf7f86SDimitry Andric Config.Common.OutputFilename, [&](raw_ostream &OutFile) -> Error { 407fcaf7f86SDimitry Andric return objcopy::executeObjcopyOnBinary(Config, InputFile, OutFile); 408fcaf7f86SDimitry Andric })) 409fcaf7f86SDimitry Andric return Err; 410fcaf7f86SDimitry Andric 411fcaf7f86SDimitry Andric return Error::success(); 412fcaf7f86SDimitry Andric } 413fcaf7f86SDimitry Andric 414fcaf7f86SDimitry Andric static Error saveLinkedDebugInfo(const Options &Opts, ObjectFile &InputFile, 415fcaf7f86SDimitry Andric DebugInfoBits LinkedDebugInfoBits) { 416fcaf7f86SDimitry Andric if (Opts.BuildSeparateDebugFile) { 417fcaf7f86SDimitry Andric Expected<uint32_t> SeparateDebugFileCRC32OrErr = 418fcaf7f86SDimitry Andric saveSeparateLinkedDebugInfo(Opts, InputFile, 419fcaf7f86SDimitry Andric std::move(LinkedDebugInfoBits)); 420fcaf7f86SDimitry Andric if (!SeparateDebugFileCRC32OrErr) 421fcaf7f86SDimitry Andric return SeparateDebugFileCRC32OrErr.takeError(); 422fcaf7f86SDimitry Andric 423fcaf7f86SDimitry Andric if (Error Err = 424fcaf7f86SDimitry Andric saveNonDebugInfo(Opts, InputFile, *SeparateDebugFileCRC32OrErr)) 425fcaf7f86SDimitry Andric return Err; 426fcaf7f86SDimitry Andric } else { 427fcaf7f86SDimitry Andric if (Error Err = saveSingleLinkedDebugInfo(Opts, InputFile, 428fcaf7f86SDimitry Andric std::move(LinkedDebugInfoBits))) 429fcaf7f86SDimitry Andric return Err; 430fcaf7f86SDimitry Andric } 431fcaf7f86SDimitry Andric 432fcaf7f86SDimitry Andric return Error::success(); 433fcaf7f86SDimitry Andric } 434fcaf7f86SDimitry Andric 435fcaf7f86SDimitry Andric static Error saveCopyOfFile(const Options &Opts, ObjectFile &InputFile) { 436fcaf7f86SDimitry Andric objcopy::ConfigManager Config; 437fcaf7f86SDimitry Andric 438fcaf7f86SDimitry Andric Config.Common.InputFilename = Opts.InputFileName; 439fcaf7f86SDimitry Andric Config.Common.OutputFilename = Opts.OutputFileName; 440fcaf7f86SDimitry Andric 441fcaf7f86SDimitry Andric if (Error Err = writeToOutput( 442fcaf7f86SDimitry Andric Config.Common.OutputFilename, [&](raw_ostream &OutFile) -> Error { 443fcaf7f86SDimitry Andric return objcopy::executeObjcopyOnBinary(Config, InputFile, OutFile); 444fcaf7f86SDimitry Andric })) 445fcaf7f86SDimitry Andric return Err; 446fcaf7f86SDimitry Andric 447fcaf7f86SDimitry Andric return Error::success(); 448fcaf7f86SDimitry Andric } 449fcaf7f86SDimitry Andric 450fcaf7f86SDimitry Andric static Error applyCLOptions(const struct Options &Opts, ObjectFile &InputFile) { 451bdd1243dSDimitry Andric if (Opts.DoGarbageCollection || 452bdd1243dSDimitry Andric Opts.AccelTableKind != DwarfUtilAccelKind::None) { 453bdd1243dSDimitry Andric verbose("Do debug info linking...", Opts.Verbose); 454fcaf7f86SDimitry Andric 455fcaf7f86SDimitry Andric DebugInfoBits LinkedDebugInfo; 456fcaf7f86SDimitry Andric raw_svector_ostream OutStream(LinkedDebugInfo); 457fcaf7f86SDimitry Andric 458972a253aSDimitry Andric if (Error Err = linkDebugInfo(InputFile, Opts, OutStream)) 459972a253aSDimitry Andric return Err; 460972a253aSDimitry Andric 461fcaf7f86SDimitry Andric if (Error Err = 462fcaf7f86SDimitry Andric saveLinkedDebugInfo(Opts, InputFile, std::move(LinkedDebugInfo))) 463fcaf7f86SDimitry Andric return Err; 464fcaf7f86SDimitry Andric 465fcaf7f86SDimitry Andric return Error::success(); 466fcaf7f86SDimitry Andric } else if (Opts.BuildSeparateDebugFile) { 467fcaf7f86SDimitry Andric if (Error Err = splitDebugIntoSeparateFile(Opts, InputFile)) 468fcaf7f86SDimitry Andric return Err; 469fcaf7f86SDimitry Andric } else { 470fcaf7f86SDimitry Andric if (Error Err = saveCopyOfFile(Opts, InputFile)) 471fcaf7f86SDimitry Andric return Err; 472fcaf7f86SDimitry Andric } 473fcaf7f86SDimitry Andric 474fcaf7f86SDimitry Andric return Error::success(); 475fcaf7f86SDimitry Andric } 476fcaf7f86SDimitry Andric 477fcaf7f86SDimitry Andric } // end of namespace dwarfutil 478fcaf7f86SDimitry Andric } // end of namespace llvm 479fcaf7f86SDimitry Andric 480fcaf7f86SDimitry Andric int main(int Argc, char const *Argv[]) { 481fcaf7f86SDimitry Andric using namespace dwarfutil; 482fcaf7f86SDimitry Andric 483fcaf7f86SDimitry Andric InitLLVM X(Argc, Argv); 484fcaf7f86SDimitry Andric ToolName = Argv[0]; 485fcaf7f86SDimitry Andric 486fcaf7f86SDimitry Andric // Parse arguments. 487fcaf7f86SDimitry Andric DwarfutilOptTable T; 488fcaf7f86SDimitry Andric unsigned MAI; 489fcaf7f86SDimitry Andric unsigned MAC; 490bdd1243dSDimitry Andric ArrayRef<const char *> ArgsArr = ArrayRef(Argv + 1, Argc - 1); 491fcaf7f86SDimitry Andric opt::InputArgList Args = T.ParseArgs(ArgsArr, MAI, MAC); 492fcaf7f86SDimitry Andric 493fcaf7f86SDimitry Andric if (Args.hasArg(OPT_help) || Args.size() == 0) { 494fcaf7f86SDimitry Andric T.printHelp( 495fcaf7f86SDimitry Andric outs(), (ToolName + " [options] <input file> <output file>").c_str(), 496fcaf7f86SDimitry Andric "llvm-dwarfutil is a tool to copy and manipulate debug info", false); 497fcaf7f86SDimitry Andric return EXIT_SUCCESS; 498fcaf7f86SDimitry Andric } 499fcaf7f86SDimitry Andric 500fcaf7f86SDimitry Andric if (Args.hasArg(OPT_version)) { 501fcaf7f86SDimitry Andric cl::PrintVersionMessage(); 502fcaf7f86SDimitry Andric return EXIT_SUCCESS; 503fcaf7f86SDimitry Andric } 504fcaf7f86SDimitry Andric 505fcaf7f86SDimitry Andric Options Opts; 506fcaf7f86SDimitry Andric if (Error Err = validateAndSetOptions(Args, Opts)) 507fcaf7f86SDimitry Andric error(std::move(Err), dwarfutil::ToolName); 508fcaf7f86SDimitry Andric 509fcaf7f86SDimitry Andric InitializeAllTargets(); 510fcaf7f86SDimitry Andric InitializeAllTargetMCs(); 511fcaf7f86SDimitry Andric InitializeAllTargetInfos(); 512fcaf7f86SDimitry Andric InitializeAllAsmPrinters(); 513fcaf7f86SDimitry Andric 514fcaf7f86SDimitry Andric ErrorOr<std::unique_ptr<MemoryBuffer>> BuffOrErr = 515fcaf7f86SDimitry Andric MemoryBuffer::getFileOrSTDIN(Opts.InputFileName); 516fcaf7f86SDimitry Andric if (BuffOrErr.getError()) 517fcaf7f86SDimitry Andric error(createFileError(Opts.InputFileName, BuffOrErr.getError())); 518fcaf7f86SDimitry Andric 519fcaf7f86SDimitry Andric Expected<std::unique_ptr<Binary>> BinOrErr = 520fcaf7f86SDimitry Andric object::createBinary(**BuffOrErr); 521fcaf7f86SDimitry Andric if (!BinOrErr) 522fcaf7f86SDimitry Andric error(createFileError(Opts.InputFileName, BinOrErr.takeError())); 523fcaf7f86SDimitry Andric 524fcaf7f86SDimitry Andric Expected<FilePermissionsApplier> PermsApplierOrErr = 525fcaf7f86SDimitry Andric FilePermissionsApplier::create(Opts.InputFileName); 526fcaf7f86SDimitry Andric if (!PermsApplierOrErr) 527fcaf7f86SDimitry Andric error(createFileError(Opts.InputFileName, PermsApplierOrErr.takeError())); 528fcaf7f86SDimitry Andric 529fcaf7f86SDimitry Andric if (!(*BinOrErr)->isObject()) 530fcaf7f86SDimitry Andric error(createFileError(Opts.InputFileName, 531fcaf7f86SDimitry Andric createError("unsupported input file"))); 532fcaf7f86SDimitry Andric 533fcaf7f86SDimitry Andric if (Error Err = 534fcaf7f86SDimitry Andric applyCLOptions(Opts, *static_cast<ObjectFile *>((*BinOrErr).get()))) 535fcaf7f86SDimitry Andric error(createFileError(Opts.InputFileName, std::move(Err))); 536fcaf7f86SDimitry Andric 537fcaf7f86SDimitry Andric BinOrErr->reset(); 538fcaf7f86SDimitry Andric BuffOrErr->reset(); 539fcaf7f86SDimitry Andric 540fcaf7f86SDimitry Andric if (Error Err = PermsApplierOrErr->apply(Opts.OutputFileName)) 541fcaf7f86SDimitry Andric error(std::move(Err)); 542fcaf7f86SDimitry Andric 543fcaf7f86SDimitry Andric if (Opts.BuildSeparateDebugFile) 544fcaf7f86SDimitry Andric if (Error Err = PermsApplierOrErr->apply(Opts.getSeparateDebugFileName())) 545fcaf7f86SDimitry Andric error(std::move(Err)); 546fcaf7f86SDimitry Andric 547fcaf7f86SDimitry Andric if (Opts.Verify) { 548fcaf7f86SDimitry Andric if (Error Err = verifyOutput(Opts)) 549fcaf7f86SDimitry Andric error(std::move(Err)); 550fcaf7f86SDimitry Andric } 551fcaf7f86SDimitry Andric 552fcaf7f86SDimitry Andric return EXIT_SUCCESS; 553fcaf7f86SDimitry Andric } 554