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