Eugene Zelenko | 66f724e | 2017-11-01 21:16:06 +0000 | [diff] [blame] | 1 | //===- dsymutil.cpp - Debug info dumping utility for llvm -----------------===// |
Frederic Riss | 31e081e | 2014-12-12 17:31:24 +0000 | [diff] [blame] | 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file is distributed under the University of Illinois Open Source |
| 6 | // License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | // |
Jonas Devlieghere | 956dada | 2018-10-23 00:32:22 +0000 | [diff] [blame] | 10 | // This program is a utility that aims to be a dropin replacement for Darwin's |
| 11 | // dsymutil. |
Frederic Riss | 31e081e | 2014-12-12 17:31:24 +0000 | [diff] [blame] | 12 | //===----------------------------------------------------------------------===// |
| 13 | |
Jonas Devlieghere | ac330ef | 2017-10-31 13:54:15 +0000 | [diff] [blame] | 14 | #include "dsymutil.h" |
Jonas Devlieghere | 4d3e6c1 | 2018-06-29 16:50:41 +0000 | [diff] [blame] | 15 | #include "BinaryHolder.h" |
Jonas Devlieghere | bdc984c | 2017-11-30 10:25:28 +0000 | [diff] [blame] | 16 | #include "CFBundle.h" |
Frederic Riss | 31e081e | 2014-12-12 17:31:24 +0000 | [diff] [blame] | 17 | #include "DebugMap.h" |
Jonas Devlieghere | 928fea2 | 2018-06-27 16:13:40 +0000 | [diff] [blame] | 18 | #include "LinkUtils.h" |
Frederic Riss | 7a42578 | 2015-08-05 18:27:44 +0000 | [diff] [blame] | 19 | #include "MachOUtils.h" |
Eugene Zelenko | 66f724e | 2017-11-01 21:16:06 +0000 | [diff] [blame] | 20 | #include "llvm/ADT/SmallString.h" |
| 21 | #include "llvm/ADT/SmallVector.h" |
Jonas Devlieghere | e22dca5 | 2018-05-30 17:47:11 +0000 | [diff] [blame] | 22 | #include "llvm/ADT/StringExtras.h" |
Eugene Zelenko | 66f724e | 2017-11-01 21:16:06 +0000 | [diff] [blame] | 23 | #include "llvm/ADT/StringRef.h" |
| 24 | #include "llvm/ADT/Triple.h" |
Jonas Devlieghere | 5eb1a17 | 2017-12-07 11:17:19 +0000 | [diff] [blame] | 25 | #include "llvm/DebugInfo/DIContext.h" |
| 26 | #include "llvm/DebugInfo/DWARF/DWARFContext.h" |
| 27 | #include "llvm/DebugInfo/DWARF/DWARFVerifier.h" |
| 28 | #include "llvm/Object/Binary.h" |
Frederic Riss | 1b709aa | 2015-08-05 22:33:28 +0000 | [diff] [blame] | 29 | #include "llvm/Object/MachO.h" |
Eugene Zelenko | 66f724e | 2017-11-01 21:16:06 +0000 | [diff] [blame] | 30 | #include "llvm/Support/CommandLine.h" |
Frederic Riss | af511be | 2015-08-06 21:05:06 +0000 | [diff] [blame] | 31 | #include "llvm/Support/FileSystem.h" |
Rui Ueyama | 0b9d56a | 2018-04-13 18:26:06 +0000 | [diff] [blame] | 32 | #include "llvm/Support/InitLLVM.h" |
Frederic Riss | 31e081e | 2014-12-12 17:31:24 +0000 | [diff] [blame] | 33 | #include "llvm/Support/ManagedStatic.h" |
Eugene Zelenko | 66f724e | 2017-11-01 21:16:06 +0000 | [diff] [blame] | 34 | #include "llvm/Support/Path.h" |
Frederic Riss | 2929a7a | 2015-02-28 00:29:11 +0000 | [diff] [blame] | 35 | #include "llvm/Support/TargetSelect.h" |
Jonas Devlieghere | ac330ef | 2017-10-31 13:54:15 +0000 | [diff] [blame] | 36 | #include "llvm/Support/ThreadPool.h" |
Jonas Devlieghere | 5baab4c | 2018-04-14 21:36:42 +0000 | [diff] [blame] | 37 | #include "llvm/Support/WithColor.h" |
Jonas Devlieghere | ac330ef | 2017-10-31 13:54:15 +0000 | [diff] [blame] | 38 | #include "llvm/Support/raw_ostream.h" |
Eugene Zelenko | 66f724e | 2017-11-01 21:16:06 +0000 | [diff] [blame] | 39 | #include "llvm/Support/thread.h" |
| 40 | #include <algorithm> |
Frederic Riss | 0dbce2b | 2015-10-09 15:04:05 +0000 | [diff] [blame] | 41 | #include <cstdint> |
Eugene Zelenko | 66f724e | 2017-11-01 21:16:06 +0000 | [diff] [blame] | 42 | #include <cstdlib> |
Frederic Riss | 31e081e | 2014-12-12 17:31:24 +0000 | [diff] [blame] | 43 | #include <string> |
Eugene Zelenko | 66f724e | 2017-11-01 21:16:06 +0000 | [diff] [blame] | 44 | #include <system_error> |
Frederic Riss | 31e081e | 2014-12-12 17:31:24 +0000 | [diff] [blame] | 45 | |
Rafael Espindola | 5feaa63 | 2017-11-15 20:55:53 +0000 | [diff] [blame] | 46 | using namespace llvm; |
Eugene Zelenko | 66f724e | 2017-11-01 21:16:06 +0000 | [diff] [blame] | 47 | using namespace llvm::cl; |
Frederic Riss | 31e081e | 2014-12-12 17:31:24 +0000 | [diff] [blame] | 48 | using namespace llvm::dsymutil; |
Jonas Devlieghere | 5eb1a17 | 2017-12-07 11:17:19 +0000 | [diff] [blame] | 49 | using namespace object; |
Frederic Riss | 31e081e | 2014-12-12 17:31:24 +0000 | [diff] [blame] | 50 | |
Eugene Zelenko | 66f724e | 2017-11-01 21:16:06 +0000 | [diff] [blame] | 51 | static OptionCategory DsymCategory("Specific Options"); |
Frederic Riss | ba72b70 | 2015-07-29 22:29:46 +0000 | [diff] [blame] | 52 | static opt<bool> Help("h", desc("Alias for -help"), Hidden); |
Frederic Riss | 3134ceb | 2015-07-29 22:29:50 +0000 | [diff] [blame] | 53 | static opt<bool> Version("v", desc("Alias for -version"), Hidden); |
Frederic Riss | ba72b70 | 2015-07-29 22:29:46 +0000 | [diff] [blame] | 54 | |
Frederic Riss | d353c91 | 2015-07-31 20:22:20 +0000 | [diff] [blame] | 55 | static list<std::string> InputFiles(Positional, OneOrMore, |
| 56 | desc("<input files>"), cat(DsymCategory)); |
Frederic Riss | 31e081e | 2014-12-12 17:31:24 +0000 | [diff] [blame] | 57 | |
Frederic Riss | 7953382 | 2015-06-03 16:57:07 +0000 | [diff] [blame] | 58 | static opt<std::string> |
| 59 | OutputFileOpt("o", |
| 60 | desc("Specify the output file. default: <input file>.dwarf"), |
Frederic Riss | ba72b70 | 2015-07-29 22:29:46 +0000 | [diff] [blame] | 61 | value_desc("filename"), cat(DsymCategory)); |
Jonas Devlieghere | 20767d1 | 2019-01-07 23:27:25 +0000 | [diff] [blame] | 62 | static alias OutputFileOptA("out", desc("Alias for -o"), |
| 63 | aliasopt(OutputFileOpt)); |
Frederic Riss | 77f4ca1 | 2015-02-28 00:29:03 +0000 | [diff] [blame] | 64 | |
Frederic Riss | 7953382 | 2015-06-03 16:57:07 +0000 | [diff] [blame] | 65 | static opt<std::string> OsoPrependPath( |
| 66 | "oso-prepend-path", |
| 67 | desc("Specify a directory to prepend to the paths of object files."), |
Frederic Riss | ba72b70 | 2015-07-29 22:29:46 +0000 | [diff] [blame] | 68 | value_desc("path"), cat(DsymCategory)); |
Frederic Riss | 31e081e | 2014-12-12 17:31:24 +0000 | [diff] [blame] | 69 | |
Jonas Devlieghere | a5d860c | 2018-07-09 16:58:48 +0000 | [diff] [blame] | 70 | static opt<bool> Assembly( |
| 71 | "S", |
| 72 | desc("Output textual assembly instead of a binary dSYM companion file."), |
| 73 | init(false), cat(DsymCategory), cl::Hidden); |
| 74 | |
Frederic Riss | a8a34c5 | 2015-08-31 00:29:09 +0000 | [diff] [blame] | 75 | static opt<bool> DumpStab( |
| 76 | "symtab", |
| 77 | desc("Dumps the symbol table found in executable or object file(s) and\n" |
| 78 | "exits."), |
| 79 | init(false), cat(DsymCategory)); |
| 80 | static alias DumpStabA("s", desc("Alias for --symtab"), aliasopt(DumpStab)); |
| 81 | |
Frederic Riss | e88f2f3 | 2015-08-06 21:05:01 +0000 | [diff] [blame] | 82 | static opt<bool> FlatOut("flat", |
| 83 | desc("Produce a flat dSYM file (not a bundle)."), |
| 84 | init(false), cat(DsymCategory)); |
| 85 | static alias FlatOutA("f", desc("Alias for --flat"), aliasopt(FlatOut)); |
| 86 | |
Jonas Devlieghere | 2fa8e76 | 2018-01-30 19:54:16 +0000 | [diff] [blame] | 87 | static opt<bool> Minimize( |
| 88 | "minimize", |
Jonas Devlieghere | 7c767bd | 2018-07-25 23:01:38 +0000 | [diff] [blame] | 89 | desc("When used when creating a dSYM file with Apple accelerator tables,\n" |
| 90 | "this option will suppress the emission of the .debug_inlines, \n" |
| 91 | ".debug_pubnames, and .debug_pubtypes sections since dsymutil \n" |
| 92 | "has better equivalents: .apple_names and .apple_types. When used in\n" |
Jonas Devlieghere | 6169346 | 2018-02-08 10:48:54 +0000 | [diff] [blame] | 93 | "conjunction with --update option, this option will cause redundant\n" |
| 94 | "accelerator tables to be removed."), |
Jonas Devlieghere | 2fa8e76 | 2018-01-30 19:54:16 +0000 | [diff] [blame] | 95 | init(false), cat(DsymCategory)); |
| 96 | static alias MinimizeA("z", desc("Alias for --minimize"), aliasopt(Minimize)); |
| 97 | |
Jonas Devlieghere | 6169346 | 2018-02-08 10:48:54 +0000 | [diff] [blame] | 98 | static opt<bool> Update( |
| 99 | "update", |
| 100 | desc("Updates existing dSYM files to contain the latest accelerator\n" |
Jonas Devlieghere | 7c767bd | 2018-07-25 23:01:38 +0000 | [diff] [blame] | 101 | "tables and other DWARF optimizations."), |
Jonas Devlieghere | 6169346 | 2018-02-08 10:48:54 +0000 | [diff] [blame] | 102 | init(false), cat(DsymCategory)); |
| 103 | static alias UpdateA("u", desc("Alias for --update"), aliasopt(Update)); |
| 104 | |
Jonas Devlieghere | 20767d1 | 2019-01-07 23:27:25 +0000 | [diff] [blame] | 105 | static opt<std::string> SymbolMap( |
| 106 | "symbol-map", |
| 107 | desc("Updates the existing dSYMs inplace using symbol map specified."), |
| 108 | value_desc("bcsymbolmap"), cat(DsymCategory)); |
| 109 | |
Jonas Devlieghere | 7c767bd | 2018-07-25 23:01:38 +0000 | [diff] [blame] | 110 | static cl::opt<AccelTableKind> AcceleratorTable( |
| 111 | "accelerator", cl::desc("Output accelerator tables."), |
| 112 | cl::values(clEnumValN(AccelTableKind::Default, "Default", |
| 113 | "Default for input."), |
| 114 | clEnumValN(AccelTableKind::Apple, "Apple", "Apple"), |
| 115 | clEnumValN(AccelTableKind::Dwarf, "Dwarf", "DWARF")), |
| 116 | cl::init(AccelTableKind::Default), cat(DsymCategory)); |
| 117 | |
Jonas Devlieghere | ef7a206 | 2017-11-01 17:15:29 +0000 | [diff] [blame] | 118 | static opt<unsigned> NumThreads( |
| 119 | "num-threads", |
Jonas Devlieghere | ac330ef | 2017-10-31 13:54:15 +0000 | [diff] [blame] | 120 | desc("Specifies the maximum number (n) of simultaneous threads to use\n" |
| 121 | "when linking multiple architectures."), |
| 122 | value_desc("n"), init(0), cat(DsymCategory)); |
Jonas Devlieghere | ef7a206 | 2017-11-01 17:15:29 +0000 | [diff] [blame] | 123 | static alias NumThreadsA("j", desc("Alias for --num-threads"), |
| 124 | aliasopt(NumThreads)); |
Jonas Devlieghere | ac330ef | 2017-10-31 13:54:15 +0000 | [diff] [blame] | 125 | |
Frederic Riss | ba72b70 | 2015-07-29 22:29:46 +0000 | [diff] [blame] | 126 | static opt<bool> Verbose("verbose", desc("Verbosity level"), init(false), |
| 127 | cat(DsymCategory)); |
Frederic Riss | 31e081e | 2014-12-12 17:31:24 +0000 | [diff] [blame] | 128 | |
Frederic Riss | 7953382 | 2015-06-03 16:57:07 +0000 | [diff] [blame] | 129 | static opt<bool> |
| 130 | NoOutput("no-output", |
| 131 | desc("Do the link in memory, but do not emit the result file."), |
Frederic Riss | ba72b70 | 2015-07-29 22:29:46 +0000 | [diff] [blame] | 132 | init(false), cat(DsymCategory)); |
Eugene Zelenko | 66f724e | 2017-11-01 21:16:06 +0000 | [diff] [blame] | 133 | |
Jonas Devlieghere | f16734c | 2017-10-13 14:41:23 +0000 | [diff] [blame] | 134 | static opt<bool> |
| 135 | NoTimestamp("no-swiftmodule-timestamp", |
| 136 | desc("Don't check timestamp for swiftmodule files."), |
| 137 | init(false), cat(DsymCategory)); |
Eugene Zelenko | 66f724e | 2017-11-01 21:16:06 +0000 | [diff] [blame] | 138 | |
Frederic Riss | 1b709aa | 2015-08-05 22:33:28 +0000 | [diff] [blame] | 139 | static list<std::string> ArchFlags( |
| 140 | "arch", |
| 141 | desc("Link DWARF debug information only for specified CPU architecture\n" |
| 142 | "types. This option can be specified multiple times, once for each\n" |
Jonas Devlieghere | 2f759d4 | 2017-11-02 18:44:54 +0000 | [diff] [blame] | 143 | "desired architecture. All CPU architectures will be linked by\n" |
Jonas Devlieghere | 4cac1c4 | 2017-12-13 18:03:04 +0000 | [diff] [blame] | 144 | "default."), |
| 145 | value_desc("arch"), ZeroOrMore, cat(DsymCategory)); |
Frederic Riss | 1b709aa | 2015-08-05 22:33:28 +0000 | [diff] [blame] | 146 | |
Frederic Riss | 309fcf8 | 2015-07-21 22:41:43 +0000 | [diff] [blame] | 147 | static opt<bool> |
| 148 | NoODR("no-odr", |
| 149 | desc("Do not use ODR (One Definition Rule) for type uniquing."), |
Frederic Riss | ba72b70 | 2015-07-29 22:29:46 +0000 | [diff] [blame] | 150 | init(false), cat(DsymCategory)); |
Frederic Riss | 309fcf8 | 2015-07-21 22:41:43 +0000 | [diff] [blame] | 151 | |
Frederic Riss | 7745dac | 2015-06-03 16:57:12 +0000 | [diff] [blame] | 152 | static opt<bool> DumpDebugMap( |
| 153 | "dump-debug-map", |
| 154 | desc("Parse and dump the debug map to standard output. Not DWARF link " |
| 155 | "will take place."), |
Frederic Riss | ba72b70 | 2015-07-29 22:29:46 +0000 | [diff] [blame] | 156 | init(false), cat(DsymCategory)); |
Frederic Riss | 696c93c | 2015-06-03 20:29:24 +0000 | [diff] [blame] | 157 | |
| 158 | static opt<bool> InputIsYAMLDebugMap( |
| 159 | "y", desc("Treat the input file is a YAML debug map rather than a binary."), |
Frederic Riss | ba72b70 | 2015-07-29 22:29:46 +0000 | [diff] [blame] | 160 | init(false), cat(DsymCategory)); |
Frederic Riss | 31e081e | 2014-12-12 17:31:24 +0000 | [diff] [blame] | 161 | |
Jonas Devlieghere | 5eb1a17 | 2017-12-07 11:17:19 +0000 | [diff] [blame] | 162 | static opt<bool> Verify("verify", desc("Verify the linked DWARF debug info."), |
| 163 | cat(DsymCategory)); |
| 164 | |
Jonas Devlieghere | e5edcce | 2018-03-08 10:39:12 +0000 | [diff] [blame] | 165 | static opt<std::string> |
| 166 | Toolchain("toolchain", desc("Embed toolchain information in dSYM bundle."), |
| 167 | cat(DsymCategory)); |
| 168 | |
Jonas Devlieghere | 67eb8fd | 2018-04-02 10:40:43 +0000 | [diff] [blame] | 169 | static opt<bool> |
| 170 | PaperTrailWarnings("papertrail", |
| 171 | desc("Embed warnings in the linked DWARF debug info."), |
| 172 | cat(DsymCategory)); |
| 173 | |
Jonas Devlieghere | 956dada | 2018-10-23 00:32:22 +0000 | [diff] [blame] | 174 | static Error createPlistFile(llvm::StringRef Bin, llvm::StringRef BundleRoot) { |
Frederic Riss | af511be | 2015-08-06 21:05:06 +0000 | [diff] [blame] | 175 | if (NoOutput) |
Jonas Devlieghere | 956dada | 2018-10-23 00:32:22 +0000 | [diff] [blame] | 176 | return Error::success(); |
Frederic Riss | af511be | 2015-08-06 21:05:06 +0000 | [diff] [blame] | 177 | |
| 178 | // Create plist file to write to. |
| 179 | llvm::SmallString<128> InfoPlist(BundleRoot); |
| 180 | llvm::sys::path::append(InfoPlist, "Contents/Info.plist"); |
| 181 | std::error_code EC; |
| 182 | llvm::raw_fd_ostream PL(InfoPlist, EC, llvm::sys::fs::F_Text); |
Jonas Devlieghere | 956dada | 2018-10-23 00:32:22 +0000 | [diff] [blame] | 183 | if (EC) |
| 184 | return make_error<StringError>( |
| 185 | "cannot create Plist: " + toString(errorCodeToError(EC)), EC); |
Frederic Riss | af511be | 2015-08-06 21:05:06 +0000 | [diff] [blame] | 186 | |
Jonas Devlieghere | bdc984c | 2017-11-30 10:25:28 +0000 | [diff] [blame] | 187 | CFBundleInfo BI = getBundleInfo(Bin); |
Frederic Riss | af511be | 2015-08-06 21:05:06 +0000 | [diff] [blame] | 188 | |
Jonas Devlieghere | bdc984c | 2017-11-30 10:25:28 +0000 | [diff] [blame] | 189 | if (BI.IDStr.empty()) { |
| 190 | llvm::StringRef BundleID = *llvm::sys::path::rbegin(BundleRoot); |
| 191 | if (llvm::sys::path::extension(BundleRoot) == ".dSYM") |
| 192 | BI.IDStr = llvm::sys::path::stem(BundleID); |
| 193 | else |
| 194 | BI.IDStr = BundleID; |
| 195 | } |
Frederic Riss | af511be | 2015-08-06 21:05:06 +0000 | [diff] [blame] | 196 | |
| 197 | // Print out information to the plist file. |
| 198 | PL << "<?xml version=\"1.0\" encoding=\"UTF-8\"\?>\n" |
| 199 | << "<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" " |
| 200 | << "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n" |
| 201 | << "<plist version=\"1.0\">\n" |
| 202 | << "\t<dict>\n" |
| 203 | << "\t\t<key>CFBundleDevelopmentRegion</key>\n" |
| 204 | << "\t\t<string>English</string>\n" |
| 205 | << "\t\t<key>CFBundleIdentifier</key>\n" |
Jonas Devlieghere | bdc984c | 2017-11-30 10:25:28 +0000 | [diff] [blame] | 206 | << "\t\t<string>com.apple.xcode.dsym." << BI.IDStr << "</string>\n" |
Frederic Riss | af511be | 2015-08-06 21:05:06 +0000 | [diff] [blame] | 207 | << "\t\t<key>CFBundleInfoDictionaryVersion</key>\n" |
| 208 | << "\t\t<string>6.0</string>\n" |
| 209 | << "\t\t<key>CFBundlePackageType</key>\n" |
| 210 | << "\t\t<string>dSYM</string>\n" |
| 211 | << "\t\t<key>CFBundleSignature</key>\n" |
Jonas Devlieghere | bdc984c | 2017-11-30 10:25:28 +0000 | [diff] [blame] | 212 | << "\t\t<string>\?\?\?\?</string>\n"; |
| 213 | |
Jonas Devlieghere | e22dca5 | 2018-05-30 17:47:11 +0000 | [diff] [blame] | 214 | if (!BI.OmitShortVersion()) { |
| 215 | PL << "\t\t<key>CFBundleShortVersionString</key>\n"; |
| 216 | PL << "\t\t<string>"; |
Jonas Devlieghere | 7eeba25 | 2018-05-31 17:01:42 +0000 | [diff] [blame] | 217 | printHTMLEscaped(BI.ShortVersionStr, PL); |
Jonas Devlieghere | e22dca5 | 2018-05-30 17:47:11 +0000 | [diff] [blame] | 218 | PL << "</string>\n"; |
| 219 | } |
Jonas Devlieghere | bdc984c | 2017-11-30 10:25:28 +0000 | [diff] [blame] | 220 | |
Jonas Devlieghere | e22dca5 | 2018-05-30 17:47:11 +0000 | [diff] [blame] | 221 | PL << "\t\t<key>CFBundleVersion</key>\n"; |
| 222 | PL << "\t\t<string>"; |
Jonas Devlieghere | 7eeba25 | 2018-05-31 17:01:42 +0000 | [diff] [blame] | 223 | printHTMLEscaped(BI.VersionStr, PL); |
Jonas Devlieghere | e22dca5 | 2018-05-30 17:47:11 +0000 | [diff] [blame] | 224 | PL << "</string>\n"; |
Jonas Devlieghere | e5edcce | 2018-03-08 10:39:12 +0000 | [diff] [blame] | 225 | |
Jonas Devlieghere | e22dca5 | 2018-05-30 17:47:11 +0000 | [diff] [blame] | 226 | if (!Toolchain.empty()) { |
| 227 | PL << "\t\t<key>Toolchain</key>\n"; |
| 228 | PL << "\t\t<string>"; |
Jonas Devlieghere | 7eeba25 | 2018-05-31 17:01:42 +0000 | [diff] [blame] | 229 | printHTMLEscaped(Toolchain, PL); |
Jonas Devlieghere | e22dca5 | 2018-05-30 17:47:11 +0000 | [diff] [blame] | 230 | PL << "</string>\n"; |
| 231 | } |
Jonas Devlieghere | e5edcce | 2018-03-08 10:39:12 +0000 | [diff] [blame] | 232 | |
| 233 | PL << "\t</dict>\n" |
Frederic Riss | af511be | 2015-08-06 21:05:06 +0000 | [diff] [blame] | 234 | << "</plist>\n"; |
| 235 | |
| 236 | PL.close(); |
Jonas Devlieghere | 956dada | 2018-10-23 00:32:22 +0000 | [diff] [blame] | 237 | return Error::success(); |
Frederic Riss | af511be | 2015-08-06 21:05:06 +0000 | [diff] [blame] | 238 | } |
| 239 | |
Jonas Devlieghere | 956dada | 2018-10-23 00:32:22 +0000 | [diff] [blame] | 240 | static Error createBundleDir(llvm::StringRef BundleBase) { |
Frederic Riss | af511be | 2015-08-06 21:05:06 +0000 | [diff] [blame] | 241 | if (NoOutput) |
Jonas Devlieghere | 956dada | 2018-10-23 00:32:22 +0000 | [diff] [blame] | 242 | return Error::success(); |
Frederic Riss | af511be | 2015-08-06 21:05:06 +0000 | [diff] [blame] | 243 | |
| 244 | llvm::SmallString<128> Bundle(BundleBase); |
| 245 | llvm::sys::path::append(Bundle, "Contents", "Resources", "DWARF"); |
Jonas Devlieghere | 956dada | 2018-10-23 00:32:22 +0000 | [diff] [blame] | 246 | if (std::error_code EC = |
| 247 | create_directories(Bundle.str(), true, llvm::sys::fs::perms::all_all)) |
| 248 | return make_error<StringError>( |
| 249 | "cannot create bundle: " + toString(errorCodeToError(EC)), EC); |
| 250 | |
| 251 | return Error::success(); |
Frederic Riss | af511be | 2015-08-06 21:05:06 +0000 | [diff] [blame] | 252 | } |
| 253 | |
Jonas Devlieghere | 5eb1a17 | 2017-12-07 11:17:19 +0000 | [diff] [blame] | 254 | static bool verify(llvm::StringRef OutputFile, llvm::StringRef Arch) { |
| 255 | if (OutputFile == "-") { |
Jonas Devlieghere | 5baab4c | 2018-04-14 21:36:42 +0000 | [diff] [blame] | 256 | WithColor::warning() << "verification skipped for " << Arch |
| 257 | << "because writing to stdout.\n"; |
Jonas Devlieghere | 5eb1a17 | 2017-12-07 11:17:19 +0000 | [diff] [blame] | 258 | return true; |
| 259 | } |
| 260 | |
| 261 | Expected<OwningBinary<Binary>> BinOrErr = createBinary(OutputFile); |
| 262 | if (!BinOrErr) { |
Jonas Devlieghere | 956dada | 2018-10-23 00:32:22 +0000 | [diff] [blame] | 263 | WithColor::error() << OutputFile << ": " << toString(BinOrErr.takeError()); |
Jonas Devlieghere | 5eb1a17 | 2017-12-07 11:17:19 +0000 | [diff] [blame] | 264 | return false; |
| 265 | } |
| 266 | |
| 267 | Binary &Binary = *BinOrErr.get().getBinary(); |
| 268 | if (auto *Obj = dyn_cast<MachOObjectFile>(&Binary)) { |
| 269 | raw_ostream &os = Verbose ? errs() : nulls(); |
| 270 | os << "Verifying DWARF for architecture: " << Arch << "\n"; |
| 271 | std::unique_ptr<DWARFContext> DICtx = DWARFContext::create(*Obj); |
| 272 | DIDumpOptions DumpOpts; |
| 273 | bool success = DICtx->verify(os, DumpOpts.noImplicitRecursion()); |
| 274 | if (!success) |
Jonas Devlieghere | 5baab4c | 2018-04-14 21:36:42 +0000 | [diff] [blame] | 275 | WithColor::error() << "verification failed for " << Arch << '\n'; |
Jonas Devlieghere | 5eb1a17 | 2017-12-07 11:17:19 +0000 | [diff] [blame] | 276 | return success; |
| 277 | } |
| 278 | |
| 279 | return false; |
| 280 | } |
| 281 | |
Jonas Devlieghere | 956dada | 2018-10-23 00:32:22 +0000 | [diff] [blame] | 282 | static Expected<std::string> getOutputFileName(llvm::StringRef InputFile) { |
Jonas Devlieghere | 20767d1 | 2019-01-07 23:27:25 +0000 | [diff] [blame] | 283 | if (OutputFileOpt == "-") |
| 284 | return OutputFileOpt; |
| 285 | |
Jonas Devlieghere | 6169346 | 2018-02-08 10:48:54 +0000 | [diff] [blame] | 286 | // When updating, do in place replacement. |
Jonas Devlieghere | 20767d1 | 2019-01-07 23:27:25 +0000 | [diff] [blame] | 287 | if (OutputFileOpt.empty() && (Update || !SymbolMap.empty())) |
Jonas Devlieghere | 6169346 | 2018-02-08 10:48:54 +0000 | [diff] [blame] | 288 | return InputFile; |
| 289 | |
| 290 | // If a flat dSYM has been requested, things are pretty simple. |
Frederic Riss | af511be | 2015-08-06 21:05:06 +0000 | [diff] [blame] | 291 | if (FlatOut) { |
Frederic Riss | af511be | 2015-08-06 21:05:06 +0000 | [diff] [blame] | 292 | if (OutputFileOpt.empty()) { |
| 293 | if (InputFile == "-") |
| 294 | return "a.out.dwarf"; |
| 295 | return (InputFile + ".dwarf").str(); |
| 296 | } |
| 297 | |
| 298 | return OutputFileOpt; |
Frederic Riss | cca89d3 | 2015-08-05 18:27:34 +0000 | [diff] [blame] | 299 | } |
Frederic Riss | af511be | 2015-08-06 21:05:06 +0000 | [diff] [blame] | 300 | |
| 301 | // We need to create/update a dSYM bundle. |
| 302 | // A bundle hierarchy looks like this: |
| 303 | // <bundle name>.dSYM/ |
| 304 | // Contents/ |
| 305 | // Info.plist |
| 306 | // Resources/ |
| 307 | // DWARF/ |
| 308 | // <DWARF file(s)> |
| 309 | std::string DwarfFile = |
| 310 | InputFile == "-" ? llvm::StringRef("a.out") : InputFile; |
| 311 | llvm::SmallString<128> BundleDir(OutputFileOpt); |
| 312 | if (BundleDir.empty()) |
| 313 | BundleDir = DwarfFile + ".dSYM"; |
Jonas Devlieghere | 956dada | 2018-10-23 00:32:22 +0000 | [diff] [blame] | 314 | if (auto E = createBundleDir(BundleDir)) |
| 315 | return std::move(E); |
| 316 | if (auto E = createPlistFile(DwarfFile, BundleDir)) |
| 317 | return std::move(E); |
Frederic Riss | af511be | 2015-08-06 21:05:06 +0000 | [diff] [blame] | 318 | |
| 319 | llvm::sys::path::append(BundleDir, "Contents", "Resources", "DWARF", |
| 320 | llvm::sys::path::filename(DwarfFile)); |
| 321 | return BundleDir.str(); |
Frederic Riss | cca89d3 | 2015-08-05 18:27:34 +0000 | [diff] [blame] | 322 | } |
| 323 | |
Jonas Devlieghere | 6169346 | 2018-02-08 10:48:54 +0000 | [diff] [blame] | 324 | /// Parses the command line options into the LinkOptions struct and performs |
| 325 | /// some sanity checking. Returns an error in case the latter fails. |
| 326 | static Expected<LinkOptions> getOptions() { |
| 327 | LinkOptions Options; |
| 328 | |
| 329 | Options.Verbose = Verbose; |
| 330 | Options.NoOutput = NoOutput; |
| 331 | Options.NoODR = NoODR; |
| 332 | Options.Minimize = Minimize; |
| 333 | Options.Update = Update; |
| 334 | Options.NoTimestamp = NoTimestamp; |
| 335 | Options.PrependPath = OsoPrependPath; |
Jonas Devlieghere | 7c767bd | 2018-07-25 23:01:38 +0000 | [diff] [blame] | 336 | Options.TheAccelTableKind = AcceleratorTable; |
Jonas Devlieghere | 6169346 | 2018-02-08 10:48:54 +0000 | [diff] [blame] | 337 | |
Jonas Devlieghere | 20767d1 | 2019-01-07 23:27:25 +0000 | [diff] [blame] | 338 | if (!SymbolMap.empty()) |
| 339 | Options.Update = true; |
| 340 | |
Jonas Devlieghere | a5d860c | 2018-07-09 16:58:48 +0000 | [diff] [blame] | 341 | if (Assembly) |
| 342 | Options.FileType = OutputFileType::Assembly; |
| 343 | |
Jonas Devlieghere | 6169346 | 2018-02-08 10:48:54 +0000 | [diff] [blame] | 344 | if (Options.Update && std::find(InputFiles.begin(), InputFiles.end(), "-") != |
| 345 | InputFiles.end()) { |
| 346 | // FIXME: We cannot use stdin for an update because stdin will be |
| 347 | // consumed by the BinaryHolder during the debugmap parsing, and |
| 348 | // then we will want to consume it again in DwarfLinker. If we |
| 349 | // used a unique BinaryHolder object that could cache multiple |
| 350 | // binaries this restriction would go away. |
| 351 | return make_error<StringError>( |
Jonas Devlieghere | cc46e39 | 2018-03-13 15:47:38 +0000 | [diff] [blame] | 352 | "standard input cannot be used as input for a dSYM update.", |
Jonas Devlieghere | 6169346 | 2018-02-08 10:48:54 +0000 | [diff] [blame] | 353 | inconvertibleErrorCode()); |
| 354 | } |
| 355 | |
Jonas Devlieghere | 2f039a0 | 2018-04-03 18:01:18 +0000 | [diff] [blame] | 356 | if (NumThreads == 0) |
| 357 | Options.Threads = llvm::thread::hardware_concurrency(); |
| 358 | if (DumpDebugMap || Verbose) |
| 359 | Options.Threads = 1; |
| 360 | |
Jonas Devlieghere | 6169346 | 2018-02-08 10:48:54 +0000 | [diff] [blame] | 361 | return Options; |
| 362 | } |
| 363 | |
| 364 | /// Return a list of input files. This function has logic for dealing with the |
| 365 | /// special case where we might have dSYM bundles as input. The function |
| 366 | /// returns an error when the directory structure doesn't match that of a dSYM |
| 367 | /// bundle. |
| 368 | static Expected<std::vector<std::string>> getInputs(bool DsymAsInput) { |
| 369 | if (!DsymAsInput) |
| 370 | return InputFiles; |
| 371 | |
| 372 | // If we are updating, we might get dSYM bundles as input. |
| 373 | std::vector<std::string> Inputs; |
| 374 | for (const auto &Input : InputFiles) { |
| 375 | if (!llvm::sys::fs::is_directory(Input)) { |
| 376 | Inputs.push_back(Input); |
| 377 | continue; |
| 378 | } |
| 379 | |
| 380 | // Make sure that we're dealing with a dSYM bundle. |
Jonas Devlieghere | 0648dd9 | 2018-02-08 16:31:42 +0000 | [diff] [blame] | 381 | SmallString<256> BundlePath(Input); |
| 382 | sys::path::append(BundlePath, "Contents", "Resources", "DWARF"); |
| 383 | if (!llvm::sys::fs::is_directory(BundlePath)) |
Jonas Devlieghere | 6169346 | 2018-02-08 10:48:54 +0000 | [diff] [blame] | 384 | return make_error<StringError>( |
| 385 | Input + " is a directory, but doesn't look like a dSYM bundle.", |
| 386 | inconvertibleErrorCode()); |
| 387 | |
| 388 | // Create a directory iterator to iterate over all the entries in the |
| 389 | // bundle. |
| 390 | std::error_code EC; |
Jonas Devlieghere | 0648dd9 | 2018-02-08 16:31:42 +0000 | [diff] [blame] | 391 | llvm::sys::fs::directory_iterator DirIt(BundlePath, EC); |
Jonas Devlieghere | 6169346 | 2018-02-08 10:48:54 +0000 | [diff] [blame] | 392 | llvm::sys::fs::directory_iterator DirEnd; |
| 393 | if (EC) |
| 394 | return errorCodeToError(EC); |
| 395 | |
| 396 | // Add each entry to the list of inputs. |
| 397 | while (DirIt != DirEnd) { |
| 398 | Inputs.push_back(DirIt->path()); |
| 399 | DirIt.increment(EC); |
| 400 | if (EC) |
| 401 | return errorCodeToError(EC); |
| 402 | } |
| 403 | } |
| 404 | return Inputs; |
| 405 | } |
| 406 | |
Frederic Riss | 31e081e | 2014-12-12 17:31:24 +0000 | [diff] [blame] | 407 | int main(int argc, char **argv) { |
Rui Ueyama | 0b9d56a | 2018-04-13 18:26:06 +0000 | [diff] [blame] | 408 | InitLLVM X(argc, argv); |
| 409 | |
Rafael Espindola | ebc0ffe | 2017-11-17 17:33:09 +0000 | [diff] [blame] | 410 | void *P = (void *)(intptr_t)getOutputFileName; |
| 411 | std::string SDKPath = llvm::sys::fs::getMainExecutable(argv[0], P); |
Frederic Riss | a642d2c | 2015-10-08 22:35:53 +0000 | [diff] [blame] | 412 | SDKPath = llvm::sys::path::parent_path(SDKPath); |
Frederic Riss | 31e081e | 2014-12-12 17:31:24 +0000 | [diff] [blame] | 413 | |
Jonas Devlieghere | 2071b7a | 2018-05-24 11:36:57 +0000 | [diff] [blame] | 414 | HideUnrelatedOptions({&DsymCategory, &ColorCategory}); |
Frederic Riss | ba72b70 | 2015-07-29 22:29:46 +0000 | [diff] [blame] | 415 | llvm::cl::ParseCommandLineOptions( |
| 416 | argc, argv, |
| 417 | "manipulate archived DWARF debug symbol files.\n\n" |
| 418 | "dsymutil links the DWARF debug information found in the object files\n" |
| 419 | "for the executable <input file> by using debug symbols information\n" |
| 420 | "contained in its symbol table.\n"); |
| 421 | |
Rafael Espindola | 14fde14 | 2017-09-07 23:30:48 +0000 | [diff] [blame] | 422 | if (Help) { |
Frederic Riss | ba72b70 | 2015-07-29 22:29:46 +0000 | [diff] [blame] | 423 | PrintHelpMessage(); |
Rafael Espindola | 14fde14 | 2017-09-07 23:30:48 +0000 | [diff] [blame] | 424 | return 0; |
| 425 | } |
Frederic Riss | 696c93c | 2015-06-03 20:29:24 +0000 | [diff] [blame] | 426 | |
Frederic Riss | 3134ceb | 2015-07-29 22:29:50 +0000 | [diff] [blame] | 427 | if (Version) { |
| 428 | llvm::cl::PrintVersionMessage(); |
| 429 | return 0; |
| 430 | } |
| 431 | |
Jonas Devlieghere | 6169346 | 2018-02-08 10:48:54 +0000 | [diff] [blame] | 432 | auto OptionsOrErr = getOptions(); |
| 433 | if (!OptionsOrErr) { |
Jonas Devlieghere | 5baab4c | 2018-04-14 21:36:42 +0000 | [diff] [blame] | 434 | WithColor::error() << toString(OptionsOrErr.takeError()); |
Jonas Devlieghere | 6169346 | 2018-02-08 10:48:54 +0000 | [diff] [blame] | 435 | return 1; |
| 436 | } |
Frederic Riss | 2929a7a | 2015-02-28 00:29:11 +0000 | [diff] [blame] | 437 | |
| 438 | llvm::InitializeAllTargetInfos(); |
| 439 | llvm::InitializeAllTargetMCs(); |
| 440 | llvm::InitializeAllTargets(); |
| 441 | llvm::InitializeAllAsmPrinters(); |
Frederic Riss | d9a80bd | 2015-02-28 00:29:07 +0000 | [diff] [blame] | 442 | |
Jonas Devlieghere | 6169346 | 2018-02-08 10:48:54 +0000 | [diff] [blame] | 443 | auto InputsOrErr = getInputs(OptionsOrErr->Update); |
| 444 | if (!InputsOrErr) { |
Jonas Devlieghere | 5baab4c | 2018-04-14 21:36:42 +0000 | [diff] [blame] | 445 | WithColor::error() << toString(InputsOrErr.takeError()) << '\n'; |
Jonas Devlieghere | 6169346 | 2018-02-08 10:48:54 +0000 | [diff] [blame] | 446 | return 1; |
| 447 | } |
| 448 | |
Frederic Riss | e88f2f3 | 2015-08-06 21:05:01 +0000 | [diff] [blame] | 449 | if (!FlatOut && OutputFileOpt == "-") { |
Jonas Devlieghere | 5baab4c | 2018-04-14 21:36:42 +0000 | [diff] [blame] | 450 | WithColor::error() << "cannot emit to standard output without --flat\n"; |
Frederic Riss | e88f2f3 | 2015-08-06 21:05:01 +0000 | [diff] [blame] | 451 | return 1; |
| 452 | } |
| 453 | |
Jonas Devlieghere | 6169346 | 2018-02-08 10:48:54 +0000 | [diff] [blame] | 454 | if (InputsOrErr->size() > 1 && FlatOut && !OutputFileOpt.empty()) { |
Jonas Devlieghere | 5baab4c | 2018-04-14 21:36:42 +0000 | [diff] [blame] | 455 | WithColor::error() << "cannot use -o with multiple inputs in flat mode\n"; |
Frederic Riss | 31e081e | 2014-12-12 17:31:24 +0000 | [diff] [blame] | 456 | return 1; |
| 457 | } |
| 458 | |
Jonas Devlieghere | 20767d1 | 2019-01-07 23:27:25 +0000 | [diff] [blame] | 459 | if (InputFiles.size() > 1 && !SymbolMap.empty() && |
| 460 | !llvm::sys::fs::is_directory(SymbolMap)) { |
| 461 | WithColor::error() << "when unobfuscating multiple files, --symbol-map " |
| 462 | << "needs to point to a directory.\n"; |
| 463 | return 1; |
| 464 | } |
| 465 | |
Jonas Devlieghere | 67eb8fd | 2018-04-02 10:40:43 +0000 | [diff] [blame] | 466 | if (getenv("RC_DEBUG_OPTIONS")) |
| 467 | PaperTrailWarnings = true; |
| 468 | |
| 469 | if (PaperTrailWarnings && InputIsYAMLDebugMap) |
Jonas Devlieghere | 5baab4c | 2018-04-14 21:36:42 +0000 | [diff] [blame] | 470 | WithColor::warning() |
| 471 | << "Paper trail warnings are not supported for YAML input"; |
Jonas Devlieghere | 67eb8fd | 2018-04-02 10:40:43 +0000 | [diff] [blame] | 472 | |
Frederic Riss | 1b709aa | 2015-08-05 22:33:28 +0000 | [diff] [blame] | 473 | for (const auto &Arch : ArchFlags) |
| 474 | if (Arch != "*" && Arch != "all" && |
| 475 | !llvm::object::MachOObjectFile::isValidArch(Arch)) { |
Jonas Devlieghere | 5baab4c | 2018-04-14 21:36:42 +0000 | [diff] [blame] | 476 | WithColor::error() << "unsupported cpu architecture: '" << Arch << "'\n"; |
Rafael Espindola | ebc0ffe | 2017-11-17 17:33:09 +0000 | [diff] [blame] | 477 | return 1; |
Frederic Riss | 1b709aa | 2015-08-05 22:33:28 +0000 | [diff] [blame] | 478 | } |
| 479 | |
Jonas Devlieghere | 20767d1 | 2019-01-07 23:27:25 +0000 | [diff] [blame] | 480 | SymbolMapLoader SymMapLoader(SymbolMap); |
| 481 | |
Jonas Devlieghere | 6169346 | 2018-02-08 10:48:54 +0000 | [diff] [blame] | 482 | for (auto &InputFile : *InputsOrErr) { |
Frederic Riss | a8a34c5 | 2015-08-31 00:29:09 +0000 | [diff] [blame] | 483 | // Dump the symbol table for each input file and requested arch |
| 484 | if (DumpStab) { |
| 485 | if (!dumpStab(InputFile, ArchFlags, OsoPrependPath)) |
Rafael Espindola | ebc0ffe | 2017-11-17 17:33:09 +0000 | [diff] [blame] | 486 | return 1; |
Frederic Riss | a8a34c5 | 2015-08-31 00:29:09 +0000 | [diff] [blame] | 487 | continue; |
| 488 | } |
| 489 | |
Jonas Devlieghere | 67eb8fd | 2018-04-02 10:40:43 +0000 | [diff] [blame] | 490 | auto DebugMapPtrsOrErr = |
| 491 | parseDebugMap(InputFile, ArchFlags, OsoPrependPath, PaperTrailWarnings, |
| 492 | Verbose, InputIsYAMLDebugMap); |
Frederic Riss | 31e081e | 2014-12-12 17:31:24 +0000 | [diff] [blame] | 493 | |
Frederic Riss | 7a42578 | 2015-08-05 18:27:44 +0000 | [diff] [blame] | 494 | if (auto EC = DebugMapPtrsOrErr.getError()) { |
Jonas Devlieghere | 5baab4c | 2018-04-14 21:36:42 +0000 | [diff] [blame] | 495 | WithColor::error() << "cannot parse the debug map for '" << InputFile |
| 496 | << "': " << EC.message() << '\n'; |
Rafael Espindola | ebc0ffe | 2017-11-17 17:33:09 +0000 | [diff] [blame] | 497 | return 1; |
Frederic Riss | d353c91 | 2015-07-31 20:22:20 +0000 | [diff] [blame] | 498 | } |
Frederic Riss | 31e081e | 2014-12-12 17:31:24 +0000 | [diff] [blame] | 499 | |
Jonas Devlieghere | 6169346 | 2018-02-08 10:48:54 +0000 | [diff] [blame] | 500 | if (OptionsOrErr->Update) { |
| 501 | // The debug map should be empty. Add one object file corresponding to |
| 502 | // the input file. |
| 503 | for (auto &Map : *DebugMapPtrsOrErr) |
| 504 | Map->addDebugMapObject(InputFile, |
| 505 | llvm::sys::TimePoint<std::chrono::seconds>()); |
| 506 | } |
| 507 | |
| 508 | // Ensure that the debug map is not empty (anymore). |
Frederic Riss | 1b709aa | 2015-08-05 22:33:28 +0000 | [diff] [blame] | 509 | if (DebugMapPtrsOrErr->empty()) { |
Jonas Devlieghere | 5baab4c | 2018-04-14 21:36:42 +0000 | [diff] [blame] | 510 | WithColor::error() << "no architecture to link\n"; |
Rafael Espindola | ebc0ffe | 2017-11-17 17:33:09 +0000 | [diff] [blame] | 511 | return 1; |
Frederic Riss | 1b709aa | 2015-08-05 22:33:28 +0000 | [diff] [blame] | 512 | } |
| 513 | |
Jonas Devlieghere | 4d3e6c1 | 2018-06-29 16:50:41 +0000 | [diff] [blame] | 514 | // Shared a single binary holder for all the link steps. |
Jonas Devlieghere | 9f33bbfe | 2018-06-29 16:51:52 +0000 | [diff] [blame] | 515 | BinaryHolder BinHolder; |
Jonas Devlieghere | 4d3e6c1 | 2018-06-29 16:50:41 +0000 | [diff] [blame] | 516 | |
Jonas Devlieghere | 2f039a0 | 2018-04-03 18:01:18 +0000 | [diff] [blame] | 517 | NumThreads = |
| 518 | std::min<unsigned>(OptionsOrErr->Threads, DebugMapPtrsOrErr->size()); |
Jonas Devlieghere | 4cac1c4 | 2017-12-13 18:03:04 +0000 | [diff] [blame] | 519 | llvm::ThreadPool Threads(NumThreads); |
Jonas Devlieghere | ac330ef | 2017-10-31 13:54:15 +0000 | [diff] [blame] | 520 | |
Frederic Riss | 7a42578 | 2015-08-05 18:27:44 +0000 | [diff] [blame] | 521 | // If there is more than one link to execute, we need to generate |
| 522 | // temporary files. |
Jonas Devlieghere | 6169346 | 2018-02-08 10:48:54 +0000 | [diff] [blame] | 523 | bool NeedsTempFiles = |
| 524 | !DumpDebugMap && (OutputFileOpt != "-") && |
| 525 | (DebugMapPtrsOrErr->size() != 1 || OptionsOrErr->Update); |
| 526 | |
Jonas Devlieghere | 58d4a39 | 2018-07-29 14:56:15 +0000 | [diff] [blame] | 527 | llvm::SmallVector<MachOUtils::ArchAndFile, 4> TempFiles; |
Jonas Devlieghere | 4cac1c4 | 2017-12-13 18:03:04 +0000 | [diff] [blame] | 528 | std::atomic_char AllOK(1); |
Frederic Riss | 7a42578 | 2015-08-05 18:27:44 +0000 | [diff] [blame] | 529 | for (auto &Map : *DebugMapPtrsOrErr) { |
| 530 | if (Verbose || DumpDebugMap) |
| 531 | Map->print(llvm::outs()); |
Frederic Riss | d353c91 | 2015-07-31 20:22:20 +0000 | [diff] [blame] | 532 | |
Frederic Riss | 7a42578 | 2015-08-05 18:27:44 +0000 | [diff] [blame] | 533 | if (DumpDebugMap) |
| 534 | continue; |
Frederic Riss | d353c91 | 2015-07-31 20:22:20 +0000 | [diff] [blame] | 535 | |
Jonas Devlieghere | 20767d1 | 2019-01-07 23:27:25 +0000 | [diff] [blame] | 536 | if (!SymbolMap.empty()) |
| 537 | OptionsOrErr->Translator = SymMapLoader.Load(InputFile, *Map); |
| 538 | |
Frederic Riss | 909125a | 2015-08-25 18:19:43 +0000 | [diff] [blame] | 539 | if (Map->begin() == Map->end()) |
Jonas Devlieghere | 5baab4c | 2018-04-14 21:36:42 +0000 | [diff] [blame] | 540 | WithColor::warning() |
| 541 | << "no debug symbols in executable (-arch " |
| 542 | << MachOUtils::getArchName(Map->getTriple().getArchName()) << ")\n"; |
Frederic Riss | 909125a | 2015-08-25 18:19:43 +0000 | [diff] [blame] | 543 | |
Jonas Devlieghere | 4cac1c4 | 2017-12-13 18:03:04 +0000 | [diff] [blame] | 544 | // Using a std::shared_ptr rather than std::unique_ptr because move-only |
| 545 | // types don't work with std::bind in the ThreadPool implementation. |
| 546 | std::shared_ptr<raw_fd_ostream> OS; |
Jonas Devlieghere | 956dada | 2018-10-23 00:32:22 +0000 | [diff] [blame] | 547 | |
| 548 | Expected<std::string> OutputFileOrErr = getOutputFileName(InputFile); |
| 549 | if (!OutputFileOrErr) { |
| 550 | WithColor::error() << toString(OutputFileOrErr.takeError()); |
| 551 | return 1; |
| 552 | } |
| 553 | |
| 554 | std::string OutputFile = *OutputFileOrErr; |
Rafael Espindola | ebc0ffe | 2017-11-17 17:33:09 +0000 | [diff] [blame] | 555 | if (NeedsTempFiles) { |
Jonas Devlieghere | 58d4a39 | 2018-07-29 14:56:15 +0000 | [diff] [blame] | 556 | TempFiles.emplace_back(Map->getTriple().getArchName().str()); |
| 557 | |
| 558 | auto E = TempFiles.back().createTempFile(); |
| 559 | if (E) { |
Jonas Devlieghere | 956dada | 2018-10-23 00:32:22 +0000 | [diff] [blame] | 560 | WithColor::error() << toString(std::move(E)); |
Rafael Espindola | ebc0ffe | 2017-11-17 17:33:09 +0000 | [diff] [blame] | 561 | return 1; |
| 562 | } |
Jonas Devlieghere | 58d4a39 | 2018-07-29 14:56:15 +0000 | [diff] [blame] | 563 | |
| 564 | auto &TempFile = *(TempFiles.back().File); |
| 565 | OS = std::make_shared<raw_fd_ostream>(TempFile.FD, |
| 566 | /*shouldClose*/ false); |
| 567 | OutputFile = TempFile.TmpName; |
Rafael Espindola | ebc0ffe | 2017-11-17 17:33:09 +0000 | [diff] [blame] | 568 | } else { |
Rafael Espindola | 5feaa63 | 2017-11-15 20:55:53 +0000 | [diff] [blame] | 569 | std::error_code EC; |
Jonas Devlieghere | 4cac1c4 | 2017-12-13 18:03:04 +0000 | [diff] [blame] | 570 | OS = std::make_shared<raw_fd_ostream>(NoOutput ? "-" : OutputFile, EC, |
| 571 | sys::fs::F_None); |
Rafael Espindola | 5feaa63 | 2017-11-15 20:55:53 +0000 | [diff] [blame] | 572 | if (EC) { |
Jonas Devlieghere | 956dada | 2018-10-23 00:32:22 +0000 | [diff] [blame] | 573 | WithColor::error() << OutputFile << ": " << EC.message(); |
Rafael Espindola | ebc0ffe | 2017-11-17 17:33:09 +0000 | [diff] [blame] | 574 | return 1; |
Rafael Espindola | 5feaa63 | 2017-11-15 20:55:53 +0000 | [diff] [blame] | 575 | } |
Rafael Espindola | ebc0ffe | 2017-11-17 17:33:09 +0000 | [diff] [blame] | 576 | } |
| 577 | |
Jonas Devlieghere | 4cac1c4 | 2017-12-13 18:03:04 +0000 | [diff] [blame] | 578 | auto LinkLambda = [&, |
| 579 | OutputFile](std::shared_ptr<raw_fd_ostream> Stream) { |
Jonas Devlieghere | 4d3e6c1 | 2018-06-29 16:50:41 +0000 | [diff] [blame] | 580 | AllOK.fetch_and(linkDwarf(*Stream, BinHolder, *Map, *OptionsOrErr)); |
Jonas Devlieghere | 4cac1c4 | 2017-12-13 18:03:04 +0000 | [diff] [blame] | 581 | Stream->flush(); |
| 582 | if (Verify && !NoOutput) |
| 583 | AllOK.fetch_and(verify(OutputFile, Map->getTriple().getArchName())); |
Jonas Devlieghere | ac330ef | 2017-10-31 13:54:15 +0000 | [diff] [blame] | 584 | }; |
| 585 | |
| 586 | // FIXME: The DwarfLinker can have some very deep recursion that can max |
| 587 | // out the (significantly smaller) stack when using threads. We don't |
| 588 | // want this limitation when we only have a single thread. |
Jonas Devlieghere | 4cac1c4 | 2017-12-13 18:03:04 +0000 | [diff] [blame] | 589 | if (NumThreads == 1) |
| 590 | LinkLambda(OS); |
| 591 | else |
| 592 | Threads.async(LinkLambda, OS); |
Frederic Riss | 7a42578 | 2015-08-05 18:27:44 +0000 | [diff] [blame] | 593 | } |
| 594 | |
Jonas Devlieghere | 4cac1c4 | 2017-12-13 18:03:04 +0000 | [diff] [blame] | 595 | Threads.wait(); |
| 596 | |
| 597 | if (!AllOK) |
| 598 | return 1; |
Jonas Devlieghere | ac330ef | 2017-10-31 13:54:15 +0000 | [diff] [blame] | 599 | |
Jonas Devlieghere | 956dada | 2018-10-23 00:32:22 +0000 | [diff] [blame] | 600 | if (NeedsTempFiles) { |
| 601 | Expected<std::string> OutputFileOrErr = getOutputFileName(InputFile); |
| 602 | if (!OutputFileOrErr) { |
| 603 | WithColor::error() << toString(OutputFileOrErr.takeError()); |
| 604 | return 1; |
| 605 | } |
| 606 | if (!MachOUtils::generateUniversalBinary(TempFiles, *OutputFileOrErr, |
| 607 | *OptionsOrErr, SDKPath)) |
| 608 | return 1; |
| 609 | } |
Frederic Riss | 77f4ca1 | 2015-02-28 00:29:03 +0000 | [diff] [blame] | 610 | } |
Frederic Riss | 31e081e | 2014-12-12 17:31:24 +0000 | [diff] [blame] | 611 | |
Rafael Espindola | ebc0ffe | 2017-11-17 17:33:09 +0000 | [diff] [blame] | 612 | return 0; |
Frederic Riss | 31e081e | 2014-12-12 17:31:24 +0000 | [diff] [blame] | 613 | } |