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