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