xref: /aosp_15_r20/external/llvm/tools/dsymutil/dsymutil.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===-- dsymutil.cpp - Debug info dumping utility for llvm ----------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This program is a utility that aims to be a dropin replacement for
11*9880d681SAndroid Build Coastguard Worker // Darwin's dsymutil.
12*9880d681SAndroid Build Coastguard Worker //
13*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
14*9880d681SAndroid Build Coastguard Worker 
15*9880d681SAndroid Build Coastguard Worker #include "DebugMap.h"
16*9880d681SAndroid Build Coastguard Worker #include "MachOUtils.h"
17*9880d681SAndroid Build Coastguard Worker #include "dsymutil.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/Object/MachO.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/FileSystem.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/FileUtilities.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ManagedStatic.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Options.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/PrettyStackTrace.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Signals.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/TargetSelect.h"
27*9880d681SAndroid Build Coastguard Worker #include <cstdint>
28*9880d681SAndroid Build Coastguard Worker #include <string>
29*9880d681SAndroid Build Coastguard Worker 
30*9880d681SAndroid Build Coastguard Worker using namespace llvm::dsymutil;
31*9880d681SAndroid Build Coastguard Worker 
32*9880d681SAndroid Build Coastguard Worker namespace {
33*9880d681SAndroid Build Coastguard Worker using namespace llvm::cl;
34*9880d681SAndroid Build Coastguard Worker 
35*9880d681SAndroid Build Coastguard Worker OptionCategory DsymCategory("Specific Options");
36*9880d681SAndroid Build Coastguard Worker static opt<bool> Help("h", desc("Alias for -help"), Hidden);
37*9880d681SAndroid Build Coastguard Worker static opt<bool> Version("v", desc("Alias for -version"), Hidden);
38*9880d681SAndroid Build Coastguard Worker 
39*9880d681SAndroid Build Coastguard Worker static list<std::string> InputFiles(Positional, OneOrMore,
40*9880d681SAndroid Build Coastguard Worker                                     desc("<input files>"), cat(DsymCategory));
41*9880d681SAndroid Build Coastguard Worker 
42*9880d681SAndroid Build Coastguard Worker static opt<std::string>
43*9880d681SAndroid Build Coastguard Worker     OutputFileOpt("o",
44*9880d681SAndroid Build Coastguard Worker                   desc("Specify the output file. default: <input file>.dwarf"),
45*9880d681SAndroid Build Coastguard Worker                   value_desc("filename"), cat(DsymCategory));
46*9880d681SAndroid Build Coastguard Worker 
47*9880d681SAndroid Build Coastguard Worker static opt<std::string> OsoPrependPath(
48*9880d681SAndroid Build Coastguard Worker     "oso-prepend-path",
49*9880d681SAndroid Build Coastguard Worker     desc("Specify a directory to prepend to the paths of object files."),
50*9880d681SAndroid Build Coastguard Worker     value_desc("path"), cat(DsymCategory));
51*9880d681SAndroid Build Coastguard Worker 
52*9880d681SAndroid Build Coastguard Worker static opt<bool> DumpStab(
53*9880d681SAndroid Build Coastguard Worker     "symtab",
54*9880d681SAndroid Build Coastguard Worker     desc("Dumps the symbol table found in executable or object file(s) and\n"
55*9880d681SAndroid Build Coastguard Worker          "exits."),
56*9880d681SAndroid Build Coastguard Worker     init(false), cat(DsymCategory));
57*9880d681SAndroid Build Coastguard Worker static alias DumpStabA("s", desc("Alias for --symtab"), aliasopt(DumpStab));
58*9880d681SAndroid Build Coastguard Worker 
59*9880d681SAndroid Build Coastguard Worker static opt<bool> FlatOut("flat",
60*9880d681SAndroid Build Coastguard Worker                          desc("Produce a flat dSYM file (not a bundle)."),
61*9880d681SAndroid Build Coastguard Worker                          init(false), cat(DsymCategory));
62*9880d681SAndroid Build Coastguard Worker static alias FlatOutA("f", desc("Alias for --flat"), aliasopt(FlatOut));
63*9880d681SAndroid Build Coastguard Worker 
64*9880d681SAndroid Build Coastguard Worker static opt<bool> Verbose("verbose", desc("Verbosity level"), init(false),
65*9880d681SAndroid Build Coastguard Worker                          cat(DsymCategory));
66*9880d681SAndroid Build Coastguard Worker 
67*9880d681SAndroid Build Coastguard Worker static opt<bool>
68*9880d681SAndroid Build Coastguard Worker     NoOutput("no-output",
69*9880d681SAndroid Build Coastguard Worker              desc("Do the link in memory, but do not emit the result file."),
70*9880d681SAndroid Build Coastguard Worker              init(false), cat(DsymCategory));
71*9880d681SAndroid Build Coastguard Worker 
72*9880d681SAndroid Build Coastguard Worker static list<std::string> ArchFlags(
73*9880d681SAndroid Build Coastguard Worker     "arch",
74*9880d681SAndroid Build Coastguard Worker     desc("Link DWARF debug information only for specified CPU architecture\n"
75*9880d681SAndroid Build Coastguard Worker          "types. This option can be specified multiple times, once for each\n"
76*9880d681SAndroid Build Coastguard Worker          "desired architecture.  All cpu architectures will be linked by\n"
77*9880d681SAndroid Build Coastguard Worker          "default."),
78*9880d681SAndroid Build Coastguard Worker     ZeroOrMore, cat(DsymCategory));
79*9880d681SAndroid Build Coastguard Worker 
80*9880d681SAndroid Build Coastguard Worker static opt<bool>
81*9880d681SAndroid Build Coastguard Worker     NoODR("no-odr",
82*9880d681SAndroid Build Coastguard Worker           desc("Do not use ODR (One Definition Rule) for type uniquing."),
83*9880d681SAndroid Build Coastguard Worker           init(false), cat(DsymCategory));
84*9880d681SAndroid Build Coastguard Worker 
85*9880d681SAndroid Build Coastguard Worker static opt<bool> DumpDebugMap(
86*9880d681SAndroid Build Coastguard Worker     "dump-debug-map",
87*9880d681SAndroid Build Coastguard Worker     desc("Parse and dump the debug map to standard output. Not DWARF link "
88*9880d681SAndroid Build Coastguard Worker          "will take place."),
89*9880d681SAndroid Build Coastguard Worker     init(false), cat(DsymCategory));
90*9880d681SAndroid Build Coastguard Worker 
91*9880d681SAndroid Build Coastguard Worker static opt<bool> InputIsYAMLDebugMap(
92*9880d681SAndroid Build Coastguard Worker     "y", desc("Treat the input file is a YAML debug map rather than a binary."),
93*9880d681SAndroid Build Coastguard Worker     init(false), cat(DsymCategory));
94*9880d681SAndroid Build Coastguard Worker }
95*9880d681SAndroid Build Coastguard Worker 
createPlistFile(llvm::StringRef BundleRoot)96*9880d681SAndroid Build Coastguard Worker static bool createPlistFile(llvm::StringRef BundleRoot) {
97*9880d681SAndroid Build Coastguard Worker   if (NoOutput)
98*9880d681SAndroid Build Coastguard Worker     return true;
99*9880d681SAndroid Build Coastguard Worker 
100*9880d681SAndroid Build Coastguard Worker   // Create plist file to write to.
101*9880d681SAndroid Build Coastguard Worker   llvm::SmallString<128> InfoPlist(BundleRoot);
102*9880d681SAndroid Build Coastguard Worker   llvm::sys::path::append(InfoPlist, "Contents/Info.plist");
103*9880d681SAndroid Build Coastguard Worker   std::error_code EC;
104*9880d681SAndroid Build Coastguard Worker   llvm::raw_fd_ostream PL(InfoPlist, EC, llvm::sys::fs::F_Text);
105*9880d681SAndroid Build Coastguard Worker   if (EC) {
106*9880d681SAndroid Build Coastguard Worker     llvm::errs() << "error: cannot create plist file " << InfoPlist << ": "
107*9880d681SAndroid Build Coastguard Worker                  << EC.message() << '\n';
108*9880d681SAndroid Build Coastguard Worker     return false;
109*9880d681SAndroid Build Coastguard Worker   }
110*9880d681SAndroid Build Coastguard Worker 
111*9880d681SAndroid Build Coastguard Worker   // FIXME: Use CoreFoundation to get executable bundle info. Use
112*9880d681SAndroid Build Coastguard Worker   // dummy values for now.
113*9880d681SAndroid Build Coastguard Worker   std::string bundleVersionStr = "1", bundleShortVersionStr = "1.0",
114*9880d681SAndroid Build Coastguard Worker               bundleIDStr;
115*9880d681SAndroid Build Coastguard Worker 
116*9880d681SAndroid Build Coastguard Worker   llvm::StringRef BundleID = *llvm::sys::path::rbegin(BundleRoot);
117*9880d681SAndroid Build Coastguard Worker   if (llvm::sys::path::extension(BundleRoot) == ".dSYM")
118*9880d681SAndroid Build Coastguard Worker     bundleIDStr = llvm::sys::path::stem(BundleID);
119*9880d681SAndroid Build Coastguard Worker   else
120*9880d681SAndroid Build Coastguard Worker     bundleIDStr = BundleID;
121*9880d681SAndroid Build Coastguard Worker 
122*9880d681SAndroid Build Coastguard Worker   // Print out information to the plist file.
123*9880d681SAndroid Build Coastguard Worker   PL << "<?xml version=\"1.0\" encoding=\"UTF-8\"\?>\n"
124*9880d681SAndroid Build Coastguard Worker      << "<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" "
125*9880d681SAndroid Build Coastguard Worker      << "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
126*9880d681SAndroid Build Coastguard Worker      << "<plist version=\"1.0\">\n"
127*9880d681SAndroid Build Coastguard Worker      << "\t<dict>\n"
128*9880d681SAndroid Build Coastguard Worker      << "\t\t<key>CFBundleDevelopmentRegion</key>\n"
129*9880d681SAndroid Build Coastguard Worker      << "\t\t<string>English</string>\n"
130*9880d681SAndroid Build Coastguard Worker      << "\t\t<key>CFBundleIdentifier</key>\n"
131*9880d681SAndroid Build Coastguard Worker      << "\t\t<string>com.apple.xcode.dsym." << bundleIDStr << "</string>\n"
132*9880d681SAndroid Build Coastguard Worker      << "\t\t<key>CFBundleInfoDictionaryVersion</key>\n"
133*9880d681SAndroid Build Coastguard Worker      << "\t\t<string>6.0</string>\n"
134*9880d681SAndroid Build Coastguard Worker      << "\t\t<key>CFBundlePackageType</key>\n"
135*9880d681SAndroid Build Coastguard Worker      << "\t\t<string>dSYM</string>\n"
136*9880d681SAndroid Build Coastguard Worker      << "\t\t<key>CFBundleSignature</key>\n"
137*9880d681SAndroid Build Coastguard Worker      << "\t\t<string>\?\?\?\?</string>\n"
138*9880d681SAndroid Build Coastguard Worker      << "\t\t<key>CFBundleShortVersionString</key>\n"
139*9880d681SAndroid Build Coastguard Worker      << "\t\t<string>" << bundleShortVersionStr << "</string>\n"
140*9880d681SAndroid Build Coastguard Worker      << "\t\t<key>CFBundleVersion</key>\n"
141*9880d681SAndroid Build Coastguard Worker      << "\t\t<string>" << bundleVersionStr << "</string>\n"
142*9880d681SAndroid Build Coastguard Worker      << "\t</dict>\n"
143*9880d681SAndroid Build Coastguard Worker      << "</plist>\n";
144*9880d681SAndroid Build Coastguard Worker 
145*9880d681SAndroid Build Coastguard Worker   PL.close();
146*9880d681SAndroid Build Coastguard Worker   return true;
147*9880d681SAndroid Build Coastguard Worker }
148*9880d681SAndroid Build Coastguard Worker 
createBundleDir(llvm::StringRef BundleBase)149*9880d681SAndroid Build Coastguard Worker static bool createBundleDir(llvm::StringRef BundleBase) {
150*9880d681SAndroid Build Coastguard Worker   if (NoOutput)
151*9880d681SAndroid Build Coastguard Worker     return true;
152*9880d681SAndroid Build Coastguard Worker 
153*9880d681SAndroid Build Coastguard Worker   llvm::SmallString<128> Bundle(BundleBase);
154*9880d681SAndroid Build Coastguard Worker   llvm::sys::path::append(Bundle, "Contents", "Resources", "DWARF");
155*9880d681SAndroid Build Coastguard Worker   if (std::error_code EC = create_directories(Bundle.str(), true,
156*9880d681SAndroid Build Coastguard Worker                                               llvm::sys::fs::perms::all_all)) {
157*9880d681SAndroid Build Coastguard Worker     llvm::errs() << "error: cannot create directory " << Bundle << ": "
158*9880d681SAndroid Build Coastguard Worker                  << EC.message() << "\n";
159*9880d681SAndroid Build Coastguard Worker     return false;
160*9880d681SAndroid Build Coastguard Worker   }
161*9880d681SAndroid Build Coastguard Worker   return true;
162*9880d681SAndroid Build Coastguard Worker }
163*9880d681SAndroid Build Coastguard Worker 
getUniqueFile(const llvm::Twine & Model,int & ResultFD,llvm::SmallVectorImpl<char> & ResultPath)164*9880d681SAndroid Build Coastguard Worker static std::error_code getUniqueFile(const llvm::Twine &Model, int &ResultFD,
165*9880d681SAndroid Build Coastguard Worker                                      llvm::SmallVectorImpl<char> &ResultPath) {
166*9880d681SAndroid Build Coastguard Worker   // If in NoOutput mode, use the createUniqueFile variant that
167*9880d681SAndroid Build Coastguard Worker   // doesn't open the file but still generates a somewhat unique
168*9880d681SAndroid Build Coastguard Worker   // name. In the real usage scenario, we'll want to ensure that the
169*9880d681SAndroid Build Coastguard Worker   // file is trully unique, and creating it is the only way to achieve
170*9880d681SAndroid Build Coastguard Worker   // that.
171*9880d681SAndroid Build Coastguard Worker   if (NoOutput)
172*9880d681SAndroid Build Coastguard Worker     return llvm::sys::fs::createUniqueFile(Model, ResultPath);
173*9880d681SAndroid Build Coastguard Worker   return llvm::sys::fs::createUniqueFile(Model, ResultFD, ResultPath);
174*9880d681SAndroid Build Coastguard Worker }
175*9880d681SAndroid Build Coastguard Worker 
getOutputFileName(llvm::StringRef InputFile,bool TempFile=false)176*9880d681SAndroid Build Coastguard Worker static std::string getOutputFileName(llvm::StringRef InputFile,
177*9880d681SAndroid Build Coastguard Worker                                      bool TempFile = false) {
178*9880d681SAndroid Build Coastguard Worker   if (TempFile) {
179*9880d681SAndroid Build Coastguard Worker     llvm::SmallString<128> TmpFile;
180*9880d681SAndroid Build Coastguard Worker     llvm::sys::path::system_temp_directory(true, TmpFile);
181*9880d681SAndroid Build Coastguard Worker     llvm::StringRef Basename =
182*9880d681SAndroid Build Coastguard Worker         OutputFileOpt.empty() ? InputFile : llvm::StringRef(OutputFileOpt);
183*9880d681SAndroid Build Coastguard Worker     llvm::sys::path::append(TmpFile, llvm::sys::path::filename(Basename));
184*9880d681SAndroid Build Coastguard Worker 
185*9880d681SAndroid Build Coastguard Worker     int FD;
186*9880d681SAndroid Build Coastguard Worker     llvm::SmallString<128> UniqueFile;
187*9880d681SAndroid Build Coastguard Worker     if (auto EC = getUniqueFile(TmpFile + ".tmp%%%%%.dwarf", FD, UniqueFile)) {
188*9880d681SAndroid Build Coastguard Worker       llvm::errs() << "error: failed to create temporary outfile '"
189*9880d681SAndroid Build Coastguard Worker                    << TmpFile << "': " << EC.message() << '\n';
190*9880d681SAndroid Build Coastguard Worker       return "";
191*9880d681SAndroid Build Coastguard Worker     }
192*9880d681SAndroid Build Coastguard Worker     llvm::sys::RemoveFileOnSignal(UniqueFile);
193*9880d681SAndroid Build Coastguard Worker     if (!NoOutput) {
194*9880d681SAndroid Build Coastguard Worker       // Close the file immediately. We know it is unique. It will be
195*9880d681SAndroid Build Coastguard Worker       // reopened and written to later.
196*9880d681SAndroid Build Coastguard Worker       llvm::raw_fd_ostream CloseImmediately(FD, true /* shouldClose */, true);
197*9880d681SAndroid Build Coastguard Worker     }
198*9880d681SAndroid Build Coastguard Worker     return UniqueFile.str();
199*9880d681SAndroid Build Coastguard Worker   }
200*9880d681SAndroid Build Coastguard Worker 
201*9880d681SAndroid Build Coastguard Worker   if (FlatOut) {
202*9880d681SAndroid Build Coastguard Worker     // If a flat dSYM has been requested, things are pretty simple.
203*9880d681SAndroid Build Coastguard Worker     if (OutputFileOpt.empty()) {
204*9880d681SAndroid Build Coastguard Worker       if (InputFile == "-")
205*9880d681SAndroid Build Coastguard Worker         return "a.out.dwarf";
206*9880d681SAndroid Build Coastguard Worker       return (InputFile + ".dwarf").str();
207*9880d681SAndroid Build Coastguard Worker     }
208*9880d681SAndroid Build Coastguard Worker 
209*9880d681SAndroid Build Coastguard Worker     return OutputFileOpt;
210*9880d681SAndroid Build Coastguard Worker   }
211*9880d681SAndroid Build Coastguard Worker 
212*9880d681SAndroid Build Coastguard Worker   // We need to create/update a dSYM bundle.
213*9880d681SAndroid Build Coastguard Worker   // A bundle hierarchy looks like this:
214*9880d681SAndroid Build Coastguard Worker   //   <bundle name>.dSYM/
215*9880d681SAndroid Build Coastguard Worker   //       Contents/
216*9880d681SAndroid Build Coastguard Worker   //          Info.plist
217*9880d681SAndroid Build Coastguard Worker   //          Resources/
218*9880d681SAndroid Build Coastguard Worker   //             DWARF/
219*9880d681SAndroid Build Coastguard Worker   //                <DWARF file(s)>
220*9880d681SAndroid Build Coastguard Worker   std::string DwarfFile =
221*9880d681SAndroid Build Coastguard Worker       InputFile == "-" ? llvm::StringRef("a.out") : InputFile;
222*9880d681SAndroid Build Coastguard Worker   llvm::SmallString<128> BundleDir(OutputFileOpt);
223*9880d681SAndroid Build Coastguard Worker   if (BundleDir.empty())
224*9880d681SAndroid Build Coastguard Worker     BundleDir = DwarfFile + ".dSYM";
225*9880d681SAndroid Build Coastguard Worker   if (!createBundleDir(BundleDir) || !createPlistFile(BundleDir))
226*9880d681SAndroid Build Coastguard Worker     return "";
227*9880d681SAndroid Build Coastguard Worker 
228*9880d681SAndroid Build Coastguard Worker   llvm::sys::path::append(BundleDir, "Contents", "Resources", "DWARF",
229*9880d681SAndroid Build Coastguard Worker                           llvm::sys::path::filename(DwarfFile));
230*9880d681SAndroid Build Coastguard Worker   return BundleDir.str();
231*9880d681SAndroid Build Coastguard Worker }
232*9880d681SAndroid Build Coastguard Worker 
exitDsymutil(int ExitStatus)233*9880d681SAndroid Build Coastguard Worker void llvm::dsymutil::exitDsymutil(int ExitStatus) {
234*9880d681SAndroid Build Coastguard Worker   // Cleanup temporary files.
235*9880d681SAndroid Build Coastguard Worker   llvm::sys::RunInterruptHandlers();
236*9880d681SAndroid Build Coastguard Worker   exit(ExitStatus);
237*9880d681SAndroid Build Coastguard Worker }
238*9880d681SAndroid Build Coastguard Worker 
main(int argc,char ** argv)239*9880d681SAndroid Build Coastguard Worker int main(int argc, char **argv) {
240*9880d681SAndroid Build Coastguard Worker   llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
241*9880d681SAndroid Build Coastguard Worker   llvm::PrettyStackTraceProgram StackPrinter(argc, argv);
242*9880d681SAndroid Build Coastguard Worker   llvm::llvm_shutdown_obj Shutdown;
243*9880d681SAndroid Build Coastguard Worker   LinkOptions Options;
244*9880d681SAndroid Build Coastguard Worker   void *MainAddr = (void *)(intptr_t)&exitDsymutil;
245*9880d681SAndroid Build Coastguard Worker   std::string SDKPath = llvm::sys::fs::getMainExecutable(argv[0], MainAddr);
246*9880d681SAndroid Build Coastguard Worker   SDKPath = llvm::sys::path::parent_path(SDKPath);
247*9880d681SAndroid Build Coastguard Worker 
248*9880d681SAndroid Build Coastguard Worker   HideUnrelatedOptions(DsymCategory);
249*9880d681SAndroid Build Coastguard Worker   llvm::cl::ParseCommandLineOptions(
250*9880d681SAndroid Build Coastguard Worker       argc, argv,
251*9880d681SAndroid Build Coastguard Worker       "manipulate archived DWARF debug symbol files.\n\n"
252*9880d681SAndroid Build Coastguard Worker       "dsymutil links the DWARF debug information found in the object files\n"
253*9880d681SAndroid Build Coastguard Worker       "for the executable <input file> by using debug symbols information\n"
254*9880d681SAndroid Build Coastguard Worker       "contained in its symbol table.\n");
255*9880d681SAndroid Build Coastguard Worker 
256*9880d681SAndroid Build Coastguard Worker   if (Help)
257*9880d681SAndroid Build Coastguard Worker     PrintHelpMessage();
258*9880d681SAndroid Build Coastguard Worker 
259*9880d681SAndroid Build Coastguard Worker   if (Version) {
260*9880d681SAndroid Build Coastguard Worker     llvm::cl::PrintVersionMessage();
261*9880d681SAndroid Build Coastguard Worker     return 0;
262*9880d681SAndroid Build Coastguard Worker   }
263*9880d681SAndroid Build Coastguard Worker 
264*9880d681SAndroid Build Coastguard Worker   Options.Verbose = Verbose;
265*9880d681SAndroid Build Coastguard Worker   Options.NoOutput = NoOutput;
266*9880d681SAndroid Build Coastguard Worker   Options.NoODR = NoODR;
267*9880d681SAndroid Build Coastguard Worker   Options.PrependPath = OsoPrependPath;
268*9880d681SAndroid Build Coastguard Worker 
269*9880d681SAndroid Build Coastguard Worker   llvm::InitializeAllTargetInfos();
270*9880d681SAndroid Build Coastguard Worker   llvm::InitializeAllTargetMCs();
271*9880d681SAndroid Build Coastguard Worker   llvm::InitializeAllTargets();
272*9880d681SAndroid Build Coastguard Worker   llvm::InitializeAllAsmPrinters();
273*9880d681SAndroid Build Coastguard Worker 
274*9880d681SAndroid Build Coastguard Worker   if (!FlatOut && OutputFileOpt == "-") {
275*9880d681SAndroid Build Coastguard Worker     llvm::errs() << "error: cannot emit to standard output without --flat\n";
276*9880d681SAndroid Build Coastguard Worker     return 1;
277*9880d681SAndroid Build Coastguard Worker   }
278*9880d681SAndroid Build Coastguard Worker 
279*9880d681SAndroid Build Coastguard Worker   if (InputFiles.size() > 1 && FlatOut && !OutputFileOpt.empty()) {
280*9880d681SAndroid Build Coastguard Worker     llvm::errs() << "error: cannot use -o with multiple inputs in flat mode\n";
281*9880d681SAndroid Build Coastguard Worker     return 1;
282*9880d681SAndroid Build Coastguard Worker   }
283*9880d681SAndroid Build Coastguard Worker 
284*9880d681SAndroid Build Coastguard Worker   for (const auto &Arch : ArchFlags)
285*9880d681SAndroid Build Coastguard Worker     if (Arch != "*" && Arch != "all" &&
286*9880d681SAndroid Build Coastguard Worker         !llvm::object::MachOObjectFile::isValidArch(Arch)) {
287*9880d681SAndroid Build Coastguard Worker       llvm::errs() << "error: Unsupported cpu architecture: '" << Arch << "'\n";
288*9880d681SAndroid Build Coastguard Worker       exitDsymutil(1);
289*9880d681SAndroid Build Coastguard Worker     }
290*9880d681SAndroid Build Coastguard Worker 
291*9880d681SAndroid Build Coastguard Worker   for (auto &InputFile : InputFiles) {
292*9880d681SAndroid Build Coastguard Worker     // Dump the symbol table for each input file and requested arch
293*9880d681SAndroid Build Coastguard Worker     if (DumpStab) {
294*9880d681SAndroid Build Coastguard Worker       if (!dumpStab(InputFile, ArchFlags, OsoPrependPath))
295*9880d681SAndroid Build Coastguard Worker         exitDsymutil(1);
296*9880d681SAndroid Build Coastguard Worker       continue;
297*9880d681SAndroid Build Coastguard Worker     }
298*9880d681SAndroid Build Coastguard Worker 
299*9880d681SAndroid Build Coastguard Worker     auto DebugMapPtrsOrErr = parseDebugMap(InputFile, ArchFlags, OsoPrependPath,
300*9880d681SAndroid Build Coastguard Worker                                            Verbose, InputIsYAMLDebugMap);
301*9880d681SAndroid Build Coastguard Worker 
302*9880d681SAndroid Build Coastguard Worker     if (auto EC = DebugMapPtrsOrErr.getError()) {
303*9880d681SAndroid Build Coastguard Worker       llvm::errs() << "error: cannot parse the debug map for \"" << InputFile
304*9880d681SAndroid Build Coastguard Worker                    << "\": " << EC.message() << '\n';
305*9880d681SAndroid Build Coastguard Worker       exitDsymutil(1);
306*9880d681SAndroid Build Coastguard Worker     }
307*9880d681SAndroid Build Coastguard Worker 
308*9880d681SAndroid Build Coastguard Worker     if (DebugMapPtrsOrErr->empty()) {
309*9880d681SAndroid Build Coastguard Worker       llvm::errs() << "error: no architecture to link\n";
310*9880d681SAndroid Build Coastguard Worker       exitDsymutil(1);
311*9880d681SAndroid Build Coastguard Worker     }
312*9880d681SAndroid Build Coastguard Worker 
313*9880d681SAndroid Build Coastguard Worker     // If there is more than one link to execute, we need to generate
314*9880d681SAndroid Build Coastguard Worker     // temporary files.
315*9880d681SAndroid Build Coastguard Worker     bool NeedsTempFiles = !DumpDebugMap && (*DebugMapPtrsOrErr).size() != 1;
316*9880d681SAndroid Build Coastguard Worker     llvm::SmallVector<MachOUtils::ArchAndFilename, 4> TempFiles;
317*9880d681SAndroid Build Coastguard Worker     for (auto &Map : *DebugMapPtrsOrErr) {
318*9880d681SAndroid Build Coastguard Worker       if (Verbose || DumpDebugMap)
319*9880d681SAndroid Build Coastguard Worker         Map->print(llvm::outs());
320*9880d681SAndroid Build Coastguard Worker 
321*9880d681SAndroid Build Coastguard Worker       if (DumpDebugMap)
322*9880d681SAndroid Build Coastguard Worker         continue;
323*9880d681SAndroid Build Coastguard Worker 
324*9880d681SAndroid Build Coastguard Worker       if (Map->begin() == Map->end())
325*9880d681SAndroid Build Coastguard Worker         llvm::errs() << "warning: no debug symbols in executable (-arch "
326*9880d681SAndroid Build Coastguard Worker                      << MachOUtils::getArchName(Map->getTriple().getArchName())
327*9880d681SAndroid Build Coastguard Worker                      << ")\n";
328*9880d681SAndroid Build Coastguard Worker 
329*9880d681SAndroid Build Coastguard Worker       std::string OutputFile = getOutputFileName(InputFile, NeedsTempFiles);
330*9880d681SAndroid Build Coastguard Worker       if (OutputFile.empty() || !linkDwarf(OutputFile, *Map, Options))
331*9880d681SAndroid Build Coastguard Worker         exitDsymutil(1);
332*9880d681SAndroid Build Coastguard Worker 
333*9880d681SAndroid Build Coastguard Worker       if (NeedsTempFiles)
334*9880d681SAndroid Build Coastguard Worker         TempFiles.emplace_back(Map->getTriple().getArchName().str(),
335*9880d681SAndroid Build Coastguard Worker                                OutputFile);
336*9880d681SAndroid Build Coastguard Worker     }
337*9880d681SAndroid Build Coastguard Worker 
338*9880d681SAndroid Build Coastguard Worker     if (NeedsTempFiles &&
339*9880d681SAndroid Build Coastguard Worker         !MachOUtils::generateUniversalBinary(
340*9880d681SAndroid Build Coastguard Worker             TempFiles, getOutputFileName(InputFile), Options, SDKPath))
341*9880d681SAndroid Build Coastguard Worker       exitDsymutil(1);
342*9880d681SAndroid Build Coastguard Worker   }
343*9880d681SAndroid Build Coastguard Worker 
344*9880d681SAndroid Build Coastguard Worker   exitDsymutil(0);
345*9880d681SAndroid Build Coastguard Worker }
346