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