File: | include/llvm/Support/Error.h |
Warning: | line 201, column 5 Potential leak of memory pointed to by 'Payload._M_t._M_head_impl' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===-- llvm-nm.cpp - Symbol table dumping utility for llvm ---------------===// | |||
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 | // | |||
10 | // This program is a utility that works like traditional Unix "nm", that is, it | |||
11 | // prints out the names of symbols in a bitcode or object file, along with some | |||
12 | // information about each symbol. | |||
13 | // | |||
14 | // This "nm" supports many of the features of GNU "nm", including its different | |||
15 | // output formats. | |||
16 | // | |||
17 | //===----------------------------------------------------------------------===// | |||
18 | ||||
19 | #include "llvm/ADT/StringSwitch.h" | |||
20 | #include "llvm/BinaryFormat/COFF.h" | |||
21 | #include "llvm/Demangle/Demangle.h" | |||
22 | #include "llvm/IR/Function.h" | |||
23 | #include "llvm/IR/LLVMContext.h" | |||
24 | #include "llvm/Object/Archive.h" | |||
25 | #include "llvm/Object/COFF.h" | |||
26 | #include "llvm/Object/COFFImportFile.h" | |||
27 | #include "llvm/Object/ELFObjectFile.h" | |||
28 | #include "llvm/Object/IRObjectFile.h" | |||
29 | #include "llvm/Object/MachO.h" | |||
30 | #include "llvm/Object/MachOUniversal.h" | |||
31 | #include "llvm/Object/ObjectFile.h" | |||
32 | #include "llvm/Object/Wasm.h" | |||
33 | #include "llvm/Support/CommandLine.h" | |||
34 | #include "llvm/Support/FileSystem.h" | |||
35 | #include "llvm/Support/Format.h" | |||
36 | #include "llvm/Support/InitLLVM.h" | |||
37 | #include "llvm/Support/MemoryBuffer.h" | |||
38 | #include "llvm/Support/Program.h" | |||
39 | #include "llvm/Support/Signals.h" | |||
40 | #include "llvm/Support/TargetSelect.h" | |||
41 | #include "llvm/Support/raw_ostream.h" | |||
42 | #include <vector> | |||
43 | ||||
44 | using namespace llvm; | |||
45 | using namespace object; | |||
46 | ||||
47 | namespace { | |||
48 | enum OutputFormatTy { bsd, sysv, posix, darwin }; | |||
49 | cl::opt<OutputFormatTy> OutputFormat( | |||
50 | "format", cl::desc("Specify output format"), | |||
51 | cl::values(clEnumVal(bsd, "BSD format")llvm::cl::OptionEnumValue { "bsd", int(bsd), "BSD format" }, clEnumVal(sysv, "System V format")llvm::cl::OptionEnumValue { "sysv", int(sysv), "System V format" }, | |||
52 | clEnumVal(posix, "POSIX.2 format")llvm::cl::OptionEnumValue { "posix", int(posix), "POSIX.2 format" }, | |||
53 | clEnumVal(darwin, "Darwin -m format")llvm::cl::OptionEnumValue { "darwin", int(darwin), "Darwin -m format" }), | |||
54 | cl::init(bsd)); | |||
55 | cl::alias OutputFormat2("f", cl::desc("Alias for --format"), | |||
56 | cl::aliasopt(OutputFormat)); | |||
57 | ||||
58 | cl::list<std::string> InputFilenames(cl::Positional, cl::desc("<input files>"), | |||
59 | cl::ZeroOrMore); | |||
60 | ||||
61 | cl::opt<bool> UndefinedOnly("undefined-only", | |||
62 | cl::desc("Show only undefined symbols")); | |||
63 | cl::alias UndefinedOnly2("u", cl::desc("Alias for --undefined-only"), | |||
64 | cl::aliasopt(UndefinedOnly), cl::Grouping); | |||
65 | ||||
66 | cl::opt<bool> DynamicSyms("dynamic", | |||
67 | cl::desc("Display the dynamic symbols instead " | |||
68 | "of normal symbols.")); | |||
69 | cl::alias DynamicSyms2("D", cl::desc("Alias for --dynamic"), | |||
70 | cl::aliasopt(DynamicSyms), cl::Grouping); | |||
71 | ||||
72 | cl::opt<bool> DefinedOnly("defined-only", | |||
73 | cl::desc("Show only defined symbols")); | |||
74 | cl::alias DefinedOnly2("U", cl::desc("Alias for --defined-only"), | |||
75 | cl::aliasopt(DefinedOnly), cl::Grouping); | |||
76 | ||||
77 | cl::opt<bool> ExternalOnly("extern-only", | |||
78 | cl::desc("Show only external symbols"), | |||
79 | cl::ZeroOrMore); | |||
80 | cl::alias ExternalOnly2("g", cl::desc("Alias for --extern-only"), | |||
81 | cl::aliasopt(ExternalOnly), cl::Grouping, | |||
82 | cl::ZeroOrMore); | |||
83 | ||||
84 | cl::opt<bool> NoWeakSymbols("no-weak", | |||
85 | cl::desc("Show only non-weak symbols")); | |||
86 | cl::alias NoWeakSymbols2("W", cl::desc("Alias for --no-weak"), | |||
87 | cl::aliasopt(NoWeakSymbols), cl::Grouping); | |||
88 | ||||
89 | cl::opt<bool> BSDFormat("B", cl::desc("Alias for --format=bsd"), | |||
90 | cl::Grouping); | |||
91 | cl::opt<bool> POSIXFormat("P", cl::desc("Alias for --format=posix"), | |||
92 | cl::Grouping); | |||
93 | cl::opt<bool> DarwinFormat("m", cl::desc("Alias for --format=darwin"), | |||
94 | cl::Grouping); | |||
95 | ||||
96 | static cl::list<std::string> | |||
97 | ArchFlags("arch", cl::desc("architecture(s) from a Mach-O file to dump"), | |||
98 | cl::ZeroOrMore); | |||
99 | bool ArchAll = false; | |||
100 | ||||
101 | cl::opt<bool> PrintFileName( | |||
102 | "print-file-name", | |||
103 | cl::desc("Precede each symbol with the object file it came from")); | |||
104 | ||||
105 | cl::alias PrintFileNameA("A", cl::desc("Alias for --print-file-name"), | |||
106 | cl::aliasopt(PrintFileName), cl::Grouping); | |||
107 | cl::alias PrintFileNameo("o", cl::desc("Alias for --print-file-name"), | |||
108 | cl::aliasopt(PrintFileName), cl::Grouping); | |||
109 | ||||
110 | cl::opt<bool> DebugSyms("debug-syms", | |||
111 | cl::desc("Show all symbols, even debugger only")); | |||
112 | cl::alias DebugSymsa("a", cl::desc("Alias for --debug-syms"), | |||
113 | cl::aliasopt(DebugSyms), cl::Grouping); | |||
114 | ||||
115 | cl::opt<bool> NumericSort("numeric-sort", cl::desc("Sort symbols by address")); | |||
116 | cl::alias NumericSortn("n", cl::desc("Alias for --numeric-sort"), | |||
117 | cl::aliasopt(NumericSort), cl::Grouping); | |||
118 | cl::alias NumericSortv("v", cl::desc("Alias for --numeric-sort"), | |||
119 | cl::aliasopt(NumericSort), cl::Grouping); | |||
120 | ||||
121 | cl::opt<bool> NoSort("no-sort", cl::desc("Show symbols in order encountered")); | |||
122 | cl::alias NoSortp("p", cl::desc("Alias for --no-sort"), cl::aliasopt(NoSort), | |||
123 | cl::Grouping); | |||
124 | ||||
125 | cl::opt<bool> Demangle("demangle", cl::desc("Demangle C++ symbol names")); | |||
126 | cl::alias DemangleC("C", cl::desc("Alias for --demangle"), cl::aliasopt(Demangle), | |||
127 | cl::Grouping); | |||
128 | ||||
129 | cl::opt<bool> ReverseSort("reverse-sort", cl::desc("Sort in reverse order")); | |||
130 | cl::alias ReverseSortr("r", cl::desc("Alias for --reverse-sort"), | |||
131 | cl::aliasopt(ReverseSort), cl::Grouping); | |||
132 | ||||
133 | cl::opt<bool> PrintSize("print-size", | |||
134 | cl::desc("Show symbol size instead of address")); | |||
135 | cl::alias PrintSizeS("S", cl::desc("Alias for --print-size"), | |||
136 | cl::aliasopt(PrintSize), cl::Grouping); | |||
137 | bool MachOPrintSizeWarning = false; | |||
138 | ||||
139 | cl::opt<bool> SizeSort("size-sort", cl::desc("Sort symbols by size")); | |||
140 | ||||
141 | cl::opt<bool> WithoutAliases("without-aliases", cl::Hidden, | |||
142 | cl::desc("Exclude aliases from output")); | |||
143 | ||||
144 | cl::opt<bool> ArchiveMap("print-armap", cl::desc("Print the archive map")); | |||
145 | cl::alias ArchiveMaps("M", cl::desc("Alias for --print-armap"), | |||
146 | cl::aliasopt(ArchiveMap), cl::Grouping); | |||
147 | ||||
148 | enum Radix { d, o, x }; | |||
149 | cl::opt<Radix> | |||
150 | AddressRadix("radix", cl::desc("Radix (o/d/x) for printing symbol Values"), | |||
151 | cl::values(clEnumVal(d, "decimal")llvm::cl::OptionEnumValue { "d", int(d), "decimal" }, clEnumVal(o, "octal")llvm::cl::OptionEnumValue { "o", int(o), "octal" }, | |||
152 | clEnumVal(x, "hexadecimal")llvm::cl::OptionEnumValue { "x", int(x), "hexadecimal" }), | |||
153 | cl::init(x)); | |||
154 | cl::alias RadixAlias("t", cl::desc("Alias for --radix"), | |||
155 | cl::aliasopt(AddressRadix)); | |||
156 | ||||
157 | cl::opt<bool> JustSymbolName("just-symbol-name", | |||
158 | cl::desc("Print just the symbol's name")); | |||
159 | cl::alias JustSymbolNames("j", cl::desc("Alias for --just-symbol-name"), | |||
160 | cl::aliasopt(JustSymbolName), cl::Grouping); | |||
161 | ||||
162 | // FIXME: This option takes exactly two strings and should be allowed anywhere | |||
163 | // on the command line. Such that "llvm-nm -s __TEXT __text foo.o" would work. | |||
164 | // But that does not as the CommandLine Library does not have a way to make | |||
165 | // this work. For now the "-s __TEXT __text" has to be last on the command | |||
166 | // line. | |||
167 | cl::list<std::string> SegSect("s", cl::Positional, cl::ZeroOrMore, | |||
168 | cl::desc("Dump only symbols from this segment " | |||
169 | "and section name, Mach-O only")); | |||
170 | ||||
171 | cl::opt<bool> FormatMachOasHex("x", cl::desc("Print symbol entry in hex, " | |||
172 | "Mach-O only"), cl::Grouping); | |||
173 | cl::opt<bool> AddDyldInfo("add-dyldinfo", | |||
174 | cl::desc("Add symbols from the dyldinfo not already " | |||
175 | "in the symbol table, Mach-O only")); | |||
176 | cl::opt<bool> NoDyldInfo("no-dyldinfo", | |||
177 | cl::desc("Don't add any symbols from the dyldinfo, " | |||
178 | "Mach-O only")); | |||
179 | cl::opt<bool> DyldInfoOnly("dyldinfo-only", | |||
180 | cl::desc("Show only symbols from the dyldinfo, " | |||
181 | "Mach-O only")); | |||
182 | ||||
183 | cl::opt<bool> NoLLVMBitcode("no-llvm-bc", | |||
184 | cl::desc("Disable LLVM bitcode reader")); | |||
185 | ||||
186 | cl::extrahelp HelpResponse("\nPass @FILE as argument to read options from FILE.\n"); | |||
187 | ||||
188 | bool PrintAddress = true; | |||
189 | ||||
190 | bool MultipleFiles = false; | |||
191 | ||||
192 | bool HadError = false; | |||
193 | ||||
194 | std::string ToolName; | |||
195 | } // anonymous namespace | |||
196 | ||||
197 | static void error(Twine Message, Twine Path = Twine()) { | |||
198 | HadError = true; | |||
199 | errs() << ToolName << ": " << Path << ": " << Message << ".\n"; | |||
200 | } | |||
201 | ||||
202 | static bool error(std::error_code EC, Twine Path = Twine()) { | |||
203 | if (EC) { | |||
204 | error(EC.message(), Path); | |||
205 | return true; | |||
206 | } | |||
207 | return false; | |||
208 | } | |||
209 | ||||
210 | // This version of error() prints the archive name and member name, for example: | |||
211 | // "libx.a(foo.o)" after the ToolName before the error message. It sets | |||
212 | // HadError but returns allowing the code to move on to other archive members. | |||
213 | static void error(llvm::Error E, StringRef FileName, const Archive::Child &C, | |||
214 | StringRef ArchitectureName = StringRef()) { | |||
215 | HadError = true; | |||
216 | errs() << ToolName << ": " << FileName; | |||
217 | ||||
218 | Expected<StringRef> NameOrErr = C.getName(); | |||
219 | // TODO: if we have a error getting the name then it would be nice to print | |||
220 | // the index of which archive member this is and or its offset in the | |||
221 | // archive instead of "???" as the name. | |||
222 | if (!NameOrErr) { | |||
223 | consumeError(NameOrErr.takeError()); | |||
224 | errs() << "(" << "???" << ")"; | |||
225 | } else | |||
226 | errs() << "(" << NameOrErr.get() << ")"; | |||
227 | ||||
228 | if (!ArchitectureName.empty()) | |||
229 | errs() << " (for architecture " << ArchitectureName << ") "; | |||
230 | ||||
231 | std::string Buf; | |||
232 | raw_string_ostream OS(Buf); | |||
233 | logAllUnhandledErrors(std::move(E), OS, ""); | |||
234 | OS.flush(); | |||
235 | errs() << " " << Buf << "\n"; | |||
236 | } | |||
237 | ||||
238 | // This version of error() prints the file name and which architecture slice it | |||
239 | // is from, for example: "foo.o (for architecture i386)" after the ToolName | |||
240 | // before the error message. It sets HadError but returns allowing the code to | |||
241 | // move on to other architecture slices. | |||
242 | static void error(llvm::Error E, StringRef FileName, | |||
243 | StringRef ArchitectureName = StringRef()) { | |||
244 | HadError = true; | |||
245 | errs() << ToolName << ": " << FileName; | |||
246 | ||||
247 | if (!ArchitectureName.empty()) | |||
248 | errs() << " (for architecture " << ArchitectureName << ") "; | |||
249 | ||||
250 | std::string Buf; | |||
251 | raw_string_ostream OS(Buf); | |||
252 | logAllUnhandledErrors(std::move(E), OS, ""); | |||
253 | OS.flush(); | |||
254 | errs() << " " << Buf << "\n"; | |||
255 | } | |||
256 | ||||
257 | namespace { | |||
258 | struct NMSymbol { | |||
259 | uint64_t Address; | |||
260 | uint64_t Size; | |||
261 | char TypeChar; | |||
262 | StringRef Name; | |||
263 | BasicSymbolRef Sym; | |||
264 | // The Sym field above points to the native symbol in the object file, | |||
265 | // for Mach-O when we are creating symbols from the dyld info the above | |||
266 | // pointer is null as there is no native symbol. In these cases the fields | |||
267 | // below are filled in to represent what would have been a Mach-O nlist | |||
268 | // native symbol. | |||
269 | uint32_t SymFlags; | |||
270 | SectionRef Section; | |||
271 | uint8_t NType; | |||
272 | uint8_t NSect; | |||
273 | uint16_t NDesc; | |||
274 | StringRef IndirectName; | |||
275 | }; | |||
276 | } // anonymous namespace | |||
277 | ||||
278 | static bool compareSymbolAddress(const NMSymbol &A, const NMSymbol &B) { | |||
279 | bool ADefined; | |||
280 | if (A.Sym.getRawDataRefImpl().p) | |||
281 | ADefined = !(A.Sym.getFlags() & SymbolRef::SF_Undefined); | |||
282 | else | |||
283 | ADefined = A.TypeChar != 'U'; | |||
284 | bool BDefined; | |||
285 | if (B.Sym.getRawDataRefImpl().p) | |||
286 | BDefined = !(B.Sym.getFlags() & SymbolRef::SF_Undefined); | |||
287 | else | |||
288 | BDefined = B.TypeChar != 'U'; | |||
289 | return std::make_tuple(ADefined, A.Address, A.Name, A.Size) < | |||
290 | std::make_tuple(BDefined, B.Address, B.Name, B.Size); | |||
291 | } | |||
292 | ||||
293 | static bool compareSymbolSize(const NMSymbol &A, const NMSymbol &B) { | |||
294 | return std::make_tuple(A.Size, A.Name, A.Address) < | |||
295 | std::make_tuple(B.Size, B.Name, B.Address); | |||
296 | } | |||
297 | ||||
298 | static bool compareSymbolName(const NMSymbol &A, const NMSymbol &B) { | |||
299 | return std::make_tuple(A.Name, A.Size, A.Address) < | |||
300 | std::make_tuple(B.Name, B.Size, B.Address); | |||
301 | } | |||
302 | ||||
303 | static char isSymbolList64Bit(SymbolicFile &Obj) { | |||
304 | if (auto *IRObj = dyn_cast<IRObjectFile>(&Obj)) | |||
305 | return Triple(IRObj->getTargetTriple()).isArch64Bit(); | |||
306 | if (isa<COFFObjectFile>(Obj) || isa<COFFImportFile>(Obj)) | |||
307 | return false; | |||
308 | if (isa<WasmObjectFile>(Obj)) | |||
309 | return false; | |||
310 | if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj)) | |||
311 | return MachO->is64Bit(); | |||
312 | return cast<ELFObjectFileBase>(Obj).getBytesInAddress() == 8; | |||
313 | } | |||
314 | ||||
315 | static StringRef CurrentFilename; | |||
316 | typedef std::vector<NMSymbol> SymbolListT; | |||
317 | static SymbolListT SymbolList; | |||
318 | ||||
319 | static char getSymbolNMTypeChar(IRObjectFile &Obj, basic_symbol_iterator I); | |||
320 | ||||
321 | // darwinPrintSymbol() is used to print a symbol from a Mach-O file when the | |||
322 | // the OutputFormat is darwin or we are printing Mach-O symbols in hex. For | |||
323 | // the darwin format it produces the same output as darwin's nm(1) -m output | |||
324 | // and when printing Mach-O symbols in hex it produces the same output as | |||
325 | // darwin's nm(1) -x format. | |||
326 | static void darwinPrintSymbol(SymbolicFile &Obj, SymbolListT::iterator I, | |||
327 | char *SymbolAddrStr, const char *printBlanks, | |||
328 | const char *printDashes, const char *printFormat) { | |||
329 | MachO::mach_header H; | |||
330 | MachO::mach_header_64 H_64; | |||
331 | uint32_t Filetype = MachO::MH_OBJECT; | |||
332 | uint32_t Flags = 0; | |||
333 | uint8_t NType = 0; | |||
334 | uint8_t NSect = 0; | |||
335 | uint16_t NDesc = 0; | |||
336 | uint32_t NStrx = 0; | |||
337 | uint64_t NValue = 0; | |||
338 | MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj); | |||
339 | if (Obj.isIR()) { | |||
340 | uint32_t SymFlags = I->Sym.getFlags(); | |||
341 | if (SymFlags & SymbolRef::SF_Global) | |||
342 | NType |= MachO::N_EXT; | |||
343 | if (SymFlags & SymbolRef::SF_Hidden) | |||
344 | NType |= MachO::N_PEXT; | |||
345 | if (SymFlags & SymbolRef::SF_Undefined) | |||
346 | NType |= MachO::N_EXT | MachO::N_UNDF; | |||
347 | else { | |||
348 | // Here we have a symbol definition. So to fake out a section name we | |||
349 | // use 1, 2 and 3 for section numbers. See below where they are used to | |||
350 | // print out fake section names. | |||
351 | NType |= MachO::N_SECT; | |||
352 | if (SymFlags & SymbolRef::SF_Const) | |||
353 | NSect = 3; | |||
354 | else if (SymFlags & SymbolRef::SF_Executable) | |||
355 | NSect = 1; | |||
356 | else | |||
357 | NSect = 2; | |||
358 | } | |||
359 | if (SymFlags & SymbolRef::SF_Weak) | |||
360 | NDesc |= MachO::N_WEAK_DEF; | |||
361 | } else { | |||
362 | DataRefImpl SymDRI = I->Sym.getRawDataRefImpl(); | |||
363 | if (MachO->is64Bit()) { | |||
364 | H_64 = MachO->MachOObjectFile::getHeader64(); | |||
365 | Filetype = H_64.filetype; | |||
366 | Flags = H_64.flags; | |||
367 | if (SymDRI.p){ | |||
368 | MachO::nlist_64 STE_64 = MachO->getSymbol64TableEntry(SymDRI); | |||
369 | NType = STE_64.n_type; | |||
370 | NSect = STE_64.n_sect; | |||
371 | NDesc = STE_64.n_desc; | |||
372 | NStrx = STE_64.n_strx; | |||
373 | NValue = STE_64.n_value; | |||
374 | } else { | |||
375 | NType = I->NType; | |||
376 | NSect = I->NSect; | |||
377 | NDesc = I->NDesc; | |||
378 | NStrx = 0; | |||
379 | NValue = I->Address; | |||
380 | } | |||
381 | } else { | |||
382 | H = MachO->MachOObjectFile::getHeader(); | |||
383 | Filetype = H.filetype; | |||
384 | Flags = H.flags; | |||
385 | if (SymDRI.p){ | |||
386 | MachO::nlist STE = MachO->getSymbolTableEntry(SymDRI); | |||
387 | NType = STE.n_type; | |||
388 | NSect = STE.n_sect; | |||
389 | NDesc = STE.n_desc; | |||
390 | NStrx = STE.n_strx; | |||
391 | NValue = STE.n_value; | |||
392 | } else { | |||
393 | NType = I->NType; | |||
394 | NSect = I->NSect; | |||
395 | NDesc = I->NDesc; | |||
396 | NStrx = 0; | |||
397 | NValue = I->Address; | |||
398 | } | |||
399 | } | |||
400 | } | |||
401 | ||||
402 | // If we are printing Mach-O symbols in hex do that and return. | |||
403 | if (FormatMachOasHex) { | |||
404 | char Str[18] = ""; | |||
405 | format(printFormat, NValue).print(Str, sizeof(Str)); | |||
406 | outs() << Str << ' '; | |||
407 | format("%02x", NType).print(Str, sizeof(Str)); | |||
408 | outs() << Str << ' '; | |||
409 | format("%02x", NSect).print(Str, sizeof(Str)); | |||
410 | outs() << Str << ' '; | |||
411 | format("%04x", NDesc).print(Str, sizeof(Str)); | |||
412 | outs() << Str << ' '; | |||
413 | format("%08x", NStrx).print(Str, sizeof(Str)); | |||
414 | outs() << Str << ' '; | |||
415 | outs() << I->Name; | |||
416 | if ((NType & MachO::N_TYPE) == MachO::N_INDR) { | |||
417 | outs() << " (indirect for "; | |||
418 | format(printFormat, NValue).print(Str, sizeof(Str)); | |||
419 | outs() << Str << ' '; | |||
420 | StringRef IndirectName; | |||
421 | if (I->Sym.getRawDataRefImpl().p) { | |||
422 | if (MachO->getIndirectName(I->Sym.getRawDataRefImpl(), IndirectName)) | |||
423 | outs() << "?)"; | |||
424 | else | |||
425 | outs() << IndirectName << ")"; | |||
426 | } | |||
427 | else | |||
428 | outs() << I->IndirectName << ")"; | |||
429 | } | |||
430 | outs() << "\n"; | |||
431 | return; | |||
432 | } | |||
433 | ||||
434 | if (PrintAddress) { | |||
435 | if ((NType & MachO::N_TYPE) == MachO::N_INDR) | |||
436 | strcpy(SymbolAddrStr, printBlanks); | |||
437 | if (Obj.isIR() && (NType & MachO::N_TYPE) == MachO::N_TYPE) | |||
438 | strcpy(SymbolAddrStr, printDashes); | |||
439 | outs() << SymbolAddrStr << ' '; | |||
440 | } | |||
441 | ||||
442 | switch (NType & MachO::N_TYPE) { | |||
443 | case MachO::N_UNDF: | |||
444 | if (NValue != 0) { | |||
445 | outs() << "(common) "; | |||
446 | if (MachO::GET_COMM_ALIGN(NDesc) != 0) | |||
447 | outs() << "(alignment 2^" << (int)MachO::GET_COMM_ALIGN(NDesc) << ") "; | |||
448 | } else { | |||
449 | if ((NType & MachO::N_TYPE) == MachO::N_PBUD) | |||
450 | outs() << "(prebound "; | |||
451 | else | |||
452 | outs() << "("; | |||
453 | if ((NDesc & MachO::REFERENCE_TYPE) == | |||
454 | MachO::REFERENCE_FLAG_UNDEFINED_LAZY) | |||
455 | outs() << "undefined [lazy bound]) "; | |||
456 | else if ((NDesc & MachO::REFERENCE_TYPE) == | |||
457 | MachO::REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY) | |||
458 | outs() << "undefined [private lazy bound]) "; | |||
459 | else if ((NDesc & MachO::REFERENCE_TYPE) == | |||
460 | MachO::REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY) | |||
461 | outs() << "undefined [private]) "; | |||
462 | else | |||
463 | outs() << "undefined) "; | |||
464 | } | |||
465 | break; | |||
466 | case MachO::N_ABS: | |||
467 | outs() << "(absolute) "; | |||
468 | break; | |||
469 | case MachO::N_INDR: | |||
470 | outs() << "(indirect) "; | |||
471 | break; | |||
472 | case MachO::N_SECT: { | |||
473 | if (Obj.isIR()) { | |||
474 | // For llvm bitcode files print out a fake section name using the values | |||
475 | // use 1, 2 and 3 for section numbers as set above. | |||
476 | if (NSect == 1) | |||
477 | outs() << "(LTO,CODE) "; | |||
478 | else if (NSect == 2) | |||
479 | outs() << "(LTO,DATA) "; | |||
480 | else if (NSect == 3) | |||
481 | outs() << "(LTO,RODATA) "; | |||
482 | else | |||
483 | outs() << "(?,?) "; | |||
484 | break; | |||
485 | } | |||
486 | section_iterator Sec = SectionRef(); | |||
487 | if (I->Sym.getRawDataRefImpl().p) { | |||
488 | Expected<section_iterator> SecOrErr = | |||
489 | MachO->getSymbolSection(I->Sym.getRawDataRefImpl()); | |||
490 | if (!SecOrErr) { | |||
491 | consumeError(SecOrErr.takeError()); | |||
492 | outs() << "(?,?) "; | |||
493 | break; | |||
494 | } | |||
495 | Sec = *SecOrErr; | |||
496 | if (Sec == MachO->section_end()) { | |||
497 | outs() << "(?,?) "; | |||
498 | break; | |||
499 | } | |||
500 | } else { | |||
501 | Sec = I->Section; | |||
502 | } | |||
503 | DataRefImpl Ref = Sec->getRawDataRefImpl(); | |||
504 | StringRef SectionName; | |||
505 | MachO->getSectionName(Ref, SectionName); | |||
506 | StringRef SegmentName = MachO->getSectionFinalSegmentName(Ref); | |||
507 | outs() << "(" << SegmentName << "," << SectionName << ") "; | |||
508 | break; | |||
509 | } | |||
510 | default: | |||
511 | outs() << "(?) "; | |||
512 | break; | |||
513 | } | |||
514 | ||||
515 | if (NType & MachO::N_EXT) { | |||
516 | if (NDesc & MachO::REFERENCED_DYNAMICALLY) | |||
517 | outs() << "[referenced dynamically] "; | |||
518 | if (NType & MachO::N_PEXT) { | |||
519 | if ((NDesc & MachO::N_WEAK_DEF) == MachO::N_WEAK_DEF) | |||
520 | outs() << "weak private external "; | |||
521 | else | |||
522 | outs() << "private external "; | |||
523 | } else { | |||
524 | if ((NDesc & MachO::N_WEAK_REF) == MachO::N_WEAK_REF || | |||
525 | (NDesc & MachO::N_WEAK_DEF) == MachO::N_WEAK_DEF) { | |||
526 | if ((NDesc & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF)) == | |||
527 | (MachO::N_WEAK_REF | MachO::N_WEAK_DEF)) | |||
528 | outs() << "weak external automatically hidden "; | |||
529 | else | |||
530 | outs() << "weak external "; | |||
531 | } else | |||
532 | outs() << "external "; | |||
533 | } | |||
534 | } else { | |||
535 | if (NType & MachO::N_PEXT) | |||
536 | outs() << "non-external (was a private external) "; | |||
537 | else | |||
538 | outs() << "non-external "; | |||
539 | } | |||
540 | ||||
541 | if (Filetype == MachO::MH_OBJECT && | |||
542 | (NDesc & MachO::N_NO_DEAD_STRIP) == MachO::N_NO_DEAD_STRIP) | |||
543 | outs() << "[no dead strip] "; | |||
544 | ||||
545 | if (Filetype == MachO::MH_OBJECT && | |||
546 | ((NType & MachO::N_TYPE) != MachO::N_UNDF) && | |||
547 | (NDesc & MachO::N_SYMBOL_RESOLVER) == MachO::N_SYMBOL_RESOLVER) | |||
548 | outs() << "[symbol resolver] "; | |||
549 | ||||
550 | if (Filetype == MachO::MH_OBJECT && | |||
551 | ((NType & MachO::N_TYPE) != MachO::N_UNDF) && | |||
552 | (NDesc & MachO::N_ALT_ENTRY) == MachO::N_ALT_ENTRY) | |||
553 | outs() << "[alt entry] "; | |||
554 | ||||
555 | if ((NDesc & MachO::N_ARM_THUMB_DEF) == MachO::N_ARM_THUMB_DEF) | |||
556 | outs() << "[Thumb] "; | |||
557 | ||||
558 | if ((NType & MachO::N_TYPE) == MachO::N_INDR) { | |||
559 | outs() << I->Name << " (for "; | |||
560 | StringRef IndirectName; | |||
561 | if (MachO) { | |||
562 | if (I->Sym.getRawDataRefImpl().p) { | |||
563 | if (MachO->getIndirectName(I->Sym.getRawDataRefImpl(), IndirectName)) | |||
564 | outs() << "?)"; | |||
565 | else | |||
566 | outs() << IndirectName << ")"; | |||
567 | } | |||
568 | else | |||
569 | outs() << I->IndirectName << ")"; | |||
570 | } else | |||
571 | outs() << "?)"; | |||
572 | } else | |||
573 | outs() << I->Name; | |||
574 | ||||
575 | if ((Flags & MachO::MH_TWOLEVEL) == MachO::MH_TWOLEVEL && | |||
576 | (((NType & MachO::N_TYPE) == MachO::N_UNDF && NValue == 0) || | |||
577 | (NType & MachO::N_TYPE) == MachO::N_PBUD)) { | |||
578 | uint32_t LibraryOrdinal = MachO::GET_LIBRARY_ORDINAL(NDesc); | |||
579 | if (LibraryOrdinal != 0) { | |||
580 | if (LibraryOrdinal == MachO::EXECUTABLE_ORDINAL) | |||
581 | outs() << " (from executable)"; | |||
582 | else if (LibraryOrdinal == MachO::DYNAMIC_LOOKUP_ORDINAL) | |||
583 | outs() << " (dynamically looked up)"; | |||
584 | else { | |||
585 | StringRef LibraryName; | |||
586 | if (!MachO || | |||
587 | MachO->getLibraryShortNameByIndex(LibraryOrdinal - 1, LibraryName)) | |||
588 | outs() << " (from bad library ordinal " << LibraryOrdinal << ")"; | |||
589 | else | |||
590 | outs() << " (from " << LibraryName << ")"; | |||
591 | } | |||
592 | } | |||
593 | } | |||
594 | ||||
595 | outs() << "\n"; | |||
596 | } | |||
597 | ||||
598 | // Table that maps Darwin's Mach-O stab constants to strings to allow printing. | |||
599 | struct DarwinStabName { | |||
600 | uint8_t NType; | |||
601 | const char *Name; | |||
602 | }; | |||
603 | static const struct DarwinStabName DarwinStabNames[] = { | |||
604 | {MachO::N_GSYM, "GSYM"}, | |||
605 | {MachO::N_FNAME, "FNAME"}, | |||
606 | {MachO::N_FUN, "FUN"}, | |||
607 | {MachO::N_STSYM, "STSYM"}, | |||
608 | {MachO::N_LCSYM, "LCSYM"}, | |||
609 | {MachO::N_BNSYM, "BNSYM"}, | |||
610 | {MachO::N_PC, "PC"}, | |||
611 | {MachO::N_AST, "AST"}, | |||
612 | {MachO::N_OPT, "OPT"}, | |||
613 | {MachO::N_RSYM, "RSYM"}, | |||
614 | {MachO::N_SLINE, "SLINE"}, | |||
615 | {MachO::N_ENSYM, "ENSYM"}, | |||
616 | {MachO::N_SSYM, "SSYM"}, | |||
617 | {MachO::N_SO, "SO"}, | |||
618 | {MachO::N_OSO, "OSO"}, | |||
619 | {MachO::N_LSYM, "LSYM"}, | |||
620 | {MachO::N_BINCL, "BINCL"}, | |||
621 | {MachO::N_SOL, "SOL"}, | |||
622 | {MachO::N_PARAMS, "PARAM"}, | |||
623 | {MachO::N_VERSION, "VERS"}, | |||
624 | {MachO::N_OLEVEL, "OLEV"}, | |||
625 | {MachO::N_PSYM, "PSYM"}, | |||
626 | {MachO::N_EINCL, "EINCL"}, | |||
627 | {MachO::N_ENTRY, "ENTRY"}, | |||
628 | {MachO::N_LBRAC, "LBRAC"}, | |||
629 | {MachO::N_EXCL, "EXCL"}, | |||
630 | {MachO::N_RBRAC, "RBRAC"}, | |||
631 | {MachO::N_BCOMM, "BCOMM"}, | |||
632 | {MachO::N_ECOMM, "ECOMM"}, | |||
633 | {MachO::N_ECOML, "ECOML"}, | |||
634 | {MachO::N_LENG, "LENG"}, | |||
635 | {0, nullptr}}; | |||
636 | ||||
637 | static const char *getDarwinStabString(uint8_t NType) { | |||
638 | for (unsigned i = 0; DarwinStabNames[i].Name; i++) { | |||
639 | if (DarwinStabNames[i].NType == NType) | |||
640 | return DarwinStabNames[i].Name; | |||
641 | } | |||
642 | return nullptr; | |||
643 | } | |||
644 | ||||
645 | // darwinPrintStab() prints the n_sect, n_desc along with a symbolic name of | |||
646 | // a stab n_type value in a Mach-O file. | |||
647 | static void darwinPrintStab(MachOObjectFile *MachO, SymbolListT::iterator I) { | |||
648 | MachO::nlist_64 STE_64; | |||
649 | MachO::nlist STE; | |||
650 | uint8_t NType; | |||
651 | uint8_t NSect; | |||
652 | uint16_t NDesc; | |||
653 | DataRefImpl SymDRI = I->Sym.getRawDataRefImpl(); | |||
654 | if (MachO->is64Bit()) { | |||
655 | STE_64 = MachO->getSymbol64TableEntry(SymDRI); | |||
656 | NType = STE_64.n_type; | |||
657 | NSect = STE_64.n_sect; | |||
658 | NDesc = STE_64.n_desc; | |||
659 | } else { | |||
660 | STE = MachO->getSymbolTableEntry(SymDRI); | |||
661 | NType = STE.n_type; | |||
662 | NSect = STE.n_sect; | |||
663 | NDesc = STE.n_desc; | |||
664 | } | |||
665 | ||||
666 | char Str[18] = ""; | |||
667 | format("%02x", NSect).print(Str, sizeof(Str)); | |||
668 | outs() << ' ' << Str << ' '; | |||
669 | format("%04x", NDesc).print(Str, sizeof(Str)); | |||
670 | outs() << Str << ' '; | |||
671 | if (const char *stabString = getDarwinStabString(NType)) | |||
672 | format("%5.5s", stabString).print(Str, sizeof(Str)); | |||
673 | else | |||
674 | format(" %02x", NType).print(Str, sizeof(Str)); | |||
675 | outs() << Str; | |||
676 | } | |||
677 | ||||
678 | static Optional<std::string> demangle(StringRef Name, bool StripUnderscore) { | |||
679 | if (StripUnderscore && Name.size() > 0 && Name[0] == '_') | |||
680 | Name = Name.substr(1); | |||
681 | ||||
682 | if (!Name.startswith("_Z")) | |||
683 | return None; | |||
684 | ||||
685 | int Status; | |||
686 | char *Undecorated = | |||
687 | itaniumDemangle(Name.str().c_str(), nullptr, nullptr, &Status); | |||
688 | if (Status != 0) | |||
689 | return None; | |||
690 | ||||
691 | std::string S(Undecorated); | |||
692 | free(Undecorated); | |||
693 | return S; | |||
694 | } | |||
695 | ||||
696 | static bool symbolIsDefined(const NMSymbol &Sym) { | |||
697 | return Sym.TypeChar != 'U' && Sym.TypeChar != 'w' && Sym.TypeChar != 'v'; | |||
698 | } | |||
699 | ||||
700 | static void sortAndPrintSymbolList(SymbolicFile &Obj, bool printName, | |||
701 | const std::string &ArchiveName, | |||
702 | const std::string &ArchitectureName) { | |||
703 | if (!NoSort) { | |||
704 | std::function<bool(const NMSymbol &, const NMSymbol &)> Cmp; | |||
705 | if (NumericSort) | |||
706 | Cmp = compareSymbolAddress; | |||
707 | else if (SizeSort) | |||
708 | Cmp = compareSymbolSize; | |||
709 | else | |||
710 | Cmp = compareSymbolName; | |||
711 | ||||
712 | if (ReverseSort) | |||
713 | Cmp = [=](const NMSymbol &A, const NMSymbol &B) { return Cmp(B, A); }; | |||
714 | llvm::sort(SymbolList, Cmp); | |||
715 | } | |||
716 | ||||
717 | if (!PrintFileName) { | |||
718 | if (OutputFormat == posix && MultipleFiles && printName) { | |||
719 | outs() << '\n' << CurrentFilename << ":\n"; | |||
720 | } else if (OutputFormat == bsd && MultipleFiles && printName) { | |||
721 | outs() << "\n" << CurrentFilename << ":\n"; | |||
722 | } else if (OutputFormat == sysv) { | |||
723 | outs() << "\n\nSymbols from " << CurrentFilename << ":\n\n"; | |||
724 | if (isSymbolList64Bit(Obj)) | |||
725 | outs() << "Name Value Class Type" | |||
726 | << " Size Line Section\n"; | |||
727 | else | |||
728 | outs() << "Name Value Class Type" | |||
729 | << " Size Line Section\n"; | |||
730 | } | |||
731 | } | |||
732 | ||||
733 | const char *printBlanks, *printDashes, *printFormat; | |||
734 | if (isSymbolList64Bit(Obj)) { | |||
735 | printBlanks = " "; | |||
736 | printDashes = "----------------"; | |||
737 | switch (AddressRadix) { | |||
738 | case Radix::o: | |||
739 | printFormat = OutputFormat == posix ? "%" PRIo64"l" "o" : "%016" PRIo64"l" "o"; | |||
740 | break; | |||
741 | case Radix::x: | |||
742 | printFormat = OutputFormat == posix ? "%" PRIx64"l" "x" : "%016" PRIx64"l" "x"; | |||
743 | break; | |||
744 | default: | |||
745 | printFormat = OutputFormat == posix ? "%" PRId64"l" "d" : "%016" PRId64"l" "d"; | |||
746 | } | |||
747 | } else { | |||
748 | printBlanks = " "; | |||
749 | printDashes = "--------"; | |||
750 | switch (AddressRadix) { | |||
751 | case Radix::o: | |||
752 | printFormat = OutputFormat == posix ? "%" PRIo64"l" "o" : "%08" PRIo64"l" "o"; | |||
753 | break; | |||
754 | case Radix::x: | |||
755 | printFormat = OutputFormat == posix ? "%" PRIx64"l" "x" : "%08" PRIx64"l" "x"; | |||
756 | break; | |||
757 | default: | |||
758 | printFormat = OutputFormat == posix ? "%" PRId64"l" "d" : "%08" PRId64"l" "d"; | |||
759 | } | |||
760 | } | |||
761 | ||||
762 | auto writeFileName = [&](raw_ostream &S) { | |||
763 | if (!ArchitectureName.empty()) | |||
764 | S << "(for architecture " << ArchitectureName << "):"; | |||
765 | if (OutputFormat == posix && !ArchiveName.empty()) | |||
766 | S << ArchiveName << "[" << CurrentFilename << "]: "; | |||
767 | else { | |||
768 | if (!ArchiveName.empty()) | |||
769 | S << ArchiveName << ":"; | |||
770 | S << CurrentFilename << ": "; | |||
771 | } | |||
772 | }; | |||
773 | ||||
774 | if (SymbolList.empty()) { | |||
775 | if (PrintFileName) | |||
776 | writeFileName(errs()); | |||
777 | errs() << "no symbols\n"; | |||
778 | } | |||
779 | ||||
780 | for (SymbolListT::iterator I = SymbolList.begin(), E = SymbolList.end(); | |||
781 | I != E; ++I) { | |||
782 | uint32_t SymFlags; | |||
783 | std::string Name = I->Name.str(); | |||
784 | MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj); | |||
785 | if (Demangle) { | |||
786 | if (Optional<std::string> Opt = demangle(I->Name, MachO)) | |||
787 | Name = *Opt; | |||
788 | } | |||
789 | if (I->Sym.getRawDataRefImpl().p) | |||
790 | SymFlags = I->Sym.getFlags(); | |||
791 | else | |||
792 | SymFlags = I->SymFlags; | |||
793 | ||||
794 | bool Undefined = SymFlags & SymbolRef::SF_Undefined; | |||
795 | bool Global = SymFlags & SymbolRef::SF_Global; | |||
796 | bool Weak = SymFlags & SymbolRef::SF_Weak; | |||
797 | if ((!Undefined && UndefinedOnly) || (Undefined && DefinedOnly) || | |||
798 | (!Global && ExternalOnly) || (SizeSort && !PrintAddress) || | |||
799 | (Weak && NoWeakSymbols)) | |||
800 | continue; | |||
801 | if (PrintFileName) | |||
802 | writeFileName(outs()); | |||
803 | if ((JustSymbolName || | |||
804 | (UndefinedOnly && MachO && OutputFormat != darwin)) && | |||
805 | OutputFormat != posix) { | |||
806 | outs() << Name << "\n"; | |||
807 | continue; | |||
808 | } | |||
809 | ||||
810 | char SymbolAddrStr[18] = ""; | |||
811 | char SymbolSizeStr[18] = ""; | |||
812 | ||||
813 | // If the format is SysV or the symbol isn't defined, then print spaces. | |||
814 | if (OutputFormat == sysv || !symbolIsDefined(*I)) { | |||
815 | if (OutputFormat == posix) { | |||
816 | format(printFormat, I->Address) | |||
817 | .print(SymbolAddrStr, sizeof(SymbolAddrStr)); | |||
818 | format(printFormat, I->Size) | |||
819 | .print(SymbolSizeStr, sizeof(SymbolSizeStr)); | |||
820 | } else { | |||
821 | strcpy(SymbolAddrStr, printBlanks); | |||
822 | strcpy(SymbolSizeStr, printBlanks); | |||
823 | } | |||
824 | } | |||
825 | ||||
826 | // Otherwise, print the symbol address and size. | |||
827 | if (symbolIsDefined(*I)) { | |||
828 | if (Obj.isIR()) | |||
829 | strcpy(SymbolAddrStr, printDashes); | |||
830 | else if(MachO && I->TypeChar == 'I') | |||
831 | strcpy(SymbolAddrStr, printBlanks); | |||
832 | else | |||
833 | format(printFormat, I->Address) | |||
834 | .print(SymbolAddrStr, sizeof(SymbolAddrStr)); | |||
835 | format(printFormat, I->Size).print(SymbolSizeStr, sizeof(SymbolSizeStr)); | |||
836 | } | |||
837 | ||||
838 | // If OutputFormat is darwin or we are printing Mach-O symbols in hex and | |||
839 | // we have a MachOObjectFile, call darwinPrintSymbol to print as darwin's | |||
840 | // nm(1) -m output or hex, else if OutputFormat is darwin or we are | |||
841 | // printing Mach-O symbols in hex and not a Mach-O object fall back to | |||
842 | // OutputFormat bsd (see below). | |||
843 | if ((OutputFormat == darwin || FormatMachOasHex) && (MachO || Obj.isIR())) { | |||
844 | darwinPrintSymbol(Obj, I, SymbolAddrStr, printBlanks, printDashes, | |||
845 | printFormat); | |||
846 | } else if (OutputFormat == posix) { | |||
847 | outs() << Name << " " << I->TypeChar << " "; | |||
848 | if (MachO) | |||
849 | outs() << SymbolAddrStr << " " << "0" /* SymbolSizeStr */ << "\n"; | |||
850 | else | |||
851 | outs() << SymbolAddrStr << " " << SymbolSizeStr << "\n"; | |||
852 | } else if (OutputFormat == bsd || (OutputFormat == darwin && !MachO)) { | |||
853 | if (PrintAddress) | |||
854 | outs() << SymbolAddrStr << ' '; | |||
855 | if (PrintSize) { | |||
856 | outs() << SymbolSizeStr; | |||
857 | outs() << ' '; | |||
858 | } | |||
859 | outs() << I->TypeChar; | |||
860 | if (I->TypeChar == '-' && MachO) | |||
861 | darwinPrintStab(MachO, I); | |||
862 | outs() << " " << Name; | |||
863 | if (I->TypeChar == 'I' && MachO) { | |||
864 | outs() << " (indirect for "; | |||
865 | if (I->Sym.getRawDataRefImpl().p) { | |||
866 | StringRef IndirectName; | |||
867 | if (MachO->getIndirectName(I->Sym.getRawDataRefImpl(), IndirectName)) | |||
868 | outs() << "?)"; | |||
869 | else | |||
870 | outs() << IndirectName << ")"; | |||
871 | } else | |||
872 | outs() << I->IndirectName << ")"; | |||
873 | } | |||
874 | outs() << "\n"; | |||
875 | } else if (OutputFormat == sysv) { | |||
876 | std::string PaddedName(Name); | |||
877 | while (PaddedName.length() < 20) | |||
878 | PaddedName += " "; | |||
879 | outs() << PaddedName << "|" << SymbolAddrStr << "| " << I->TypeChar | |||
880 | << " | |" << SymbolSizeStr << "| |\n"; | |||
881 | } | |||
882 | } | |||
883 | ||||
884 | SymbolList.clear(); | |||
885 | } | |||
886 | ||||
887 | static char getSymbolNMTypeChar(ELFObjectFileBase &Obj, | |||
888 | basic_symbol_iterator I) { | |||
889 | // OK, this is ELF | |||
890 | elf_symbol_iterator SymI(I); | |||
891 | ||||
892 | Expected<elf_section_iterator> SecIOrErr = SymI->getSection(); | |||
893 | if (!SecIOrErr) { | |||
894 | consumeError(SecIOrErr.takeError()); | |||
895 | return '?'; | |||
896 | } | |||
897 | ||||
898 | elf_section_iterator SecI = *SecIOrErr; | |||
899 | if (SecI != Obj.section_end()) { | |||
900 | switch (SecI->getType()) { | |||
901 | case ELF::SHT_PROGBITS: | |||
902 | case ELF::SHT_DYNAMIC: | |||
903 | switch (SecI->getFlags()) { | |||
904 | case (ELF::SHF_ALLOC | ELF::SHF_EXECINSTR): | |||
905 | return 't'; | |||
906 | case (ELF::SHF_TLS | ELF::SHF_ALLOC | ELF::SHF_WRITE): | |||
907 | case (ELF::SHF_ALLOC | ELF::SHF_WRITE): | |||
908 | return 'd'; | |||
909 | case ELF::SHF_ALLOC: | |||
910 | case (ELF::SHF_ALLOC | ELF::SHF_MERGE): | |||
911 | case (ELF::SHF_ALLOC | ELF::SHF_MERGE | ELF::SHF_STRINGS): | |||
912 | return 'r'; | |||
913 | } | |||
914 | break; | |||
915 | case ELF::SHT_NOBITS: | |||
916 | return 'b'; | |||
917 | case ELF::SHT_INIT_ARRAY: | |||
918 | case ELF::SHT_FINI_ARRAY: | |||
919 | return 't'; | |||
920 | } | |||
921 | } | |||
922 | ||||
923 | if (SymI->getELFType() == ELF::STT_SECTION) { | |||
924 | Expected<StringRef> Name = SymI->getName(); | |||
925 | if (!Name) { | |||
926 | consumeError(Name.takeError()); | |||
927 | return '?'; | |||
928 | } | |||
929 | return StringSwitch<char>(*Name) | |||
930 | .StartsWith(".debug", 'N') | |||
931 | .StartsWith(".note", 'n') | |||
932 | .Default('?'); | |||
933 | } | |||
934 | ||||
935 | return 'n'; | |||
936 | } | |||
937 | ||||
938 | static char getSymbolNMTypeChar(COFFObjectFile &Obj, symbol_iterator I) { | |||
939 | COFFSymbolRef Symb = Obj.getCOFFSymbol(*I); | |||
940 | // OK, this is COFF. | |||
941 | symbol_iterator SymI(I); | |||
942 | ||||
943 | Expected<StringRef> Name = SymI->getName(); | |||
944 | if (!Name) { | |||
945 | consumeError(Name.takeError()); | |||
946 | return '?'; | |||
947 | } | |||
948 | ||||
949 | char Ret = StringSwitch<char>(*Name) | |||
950 | .StartsWith(".debug", 'N') | |||
951 | .StartsWith(".sxdata", 'N') | |||
952 | .Default('?'); | |||
953 | ||||
954 | if (Ret != '?') | |||
955 | return Ret; | |||
956 | ||||
957 | uint32_t Characteristics = 0; | |||
958 | if (!COFF::isReservedSectionNumber(Symb.getSectionNumber())) { | |||
959 | Expected<section_iterator> SecIOrErr = SymI->getSection(); | |||
960 | if (!SecIOrErr) { | |||
961 | consumeError(SecIOrErr.takeError()); | |||
962 | return '?'; | |||
963 | } | |||
964 | section_iterator SecI = *SecIOrErr; | |||
965 | const coff_section *Section = Obj.getCOFFSection(*SecI); | |||
966 | Characteristics = Section->Characteristics; | |||
967 | StringRef SectionName; | |||
968 | Obj.getSectionName(Section, SectionName); | |||
969 | if (SectionName.startswith(".idata")) | |||
970 | return 'i'; | |||
971 | } | |||
972 | ||||
973 | switch (Symb.getSectionNumber()) { | |||
974 | case COFF::IMAGE_SYM_DEBUG: | |||
975 | return 'n'; | |||
976 | default: | |||
977 | // Check section type. | |||
978 | if (Characteristics & COFF::IMAGE_SCN_CNT_CODE) | |||
979 | return 't'; | |||
980 | if (Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA) | |||
981 | return Characteristics & COFF::IMAGE_SCN_MEM_WRITE ? 'd' : 'r'; | |||
982 | if (Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) | |||
983 | return 'b'; | |||
984 | if (Characteristics & COFF::IMAGE_SCN_LNK_INFO) | |||
985 | return 'i'; | |||
986 | // Check for section symbol. | |||
987 | if (Symb.isSectionDefinition()) | |||
988 | return 's'; | |||
989 | } | |||
990 | ||||
991 | return '?'; | |||
992 | } | |||
993 | ||||
994 | static char getSymbolNMTypeChar(COFFImportFile &Obj) { | |||
995 | switch (Obj.getCOFFImportHeader()->getType()) { | |||
996 | case COFF::IMPORT_CODE: | |||
997 | return 't'; | |||
998 | case COFF::IMPORT_DATA: | |||
999 | return 'd'; | |||
1000 | case COFF::IMPORT_CONST: | |||
1001 | return 'r'; | |||
1002 | } | |||
1003 | return '?'; | |||
1004 | } | |||
1005 | ||||
1006 | static char getSymbolNMTypeChar(MachOObjectFile &Obj, basic_symbol_iterator I) { | |||
1007 | DataRefImpl Symb = I->getRawDataRefImpl(); | |||
1008 | uint8_t NType = Obj.is64Bit() ? Obj.getSymbol64TableEntry(Symb).n_type | |||
1009 | : Obj.getSymbolTableEntry(Symb).n_type; | |||
1010 | ||||
1011 | if (NType & MachO::N_STAB) | |||
1012 | return '-'; | |||
1013 | ||||
1014 | switch (NType & MachO::N_TYPE) { | |||
1015 | case MachO::N_ABS: | |||
1016 | return 's'; | |||
1017 | case MachO::N_INDR: | |||
1018 | return 'i'; | |||
1019 | case MachO::N_SECT: { | |||
1020 | Expected<section_iterator> SecOrErr = Obj.getSymbolSection(Symb); | |||
1021 | if (!SecOrErr) { | |||
1022 | consumeError(SecOrErr.takeError()); | |||
1023 | return 's'; | |||
1024 | } | |||
1025 | section_iterator Sec = *SecOrErr; | |||
1026 | if (Sec == Obj.section_end()) | |||
1027 | return 's'; | |||
1028 | DataRefImpl Ref = Sec->getRawDataRefImpl(); | |||
1029 | StringRef SectionName; | |||
1030 | Obj.getSectionName(Ref, SectionName); | |||
1031 | StringRef SegmentName = Obj.getSectionFinalSegmentName(Ref); | |||
1032 | if (Obj.is64Bit() && | |||
1033 | Obj.getHeader64().filetype == MachO::MH_KEXT_BUNDLE && | |||
1034 | SegmentName == "__TEXT_EXEC" && SectionName == "__text") | |||
1035 | return 't'; | |||
1036 | if (SegmentName == "__TEXT" && SectionName == "__text") | |||
1037 | return 't'; | |||
1038 | if (SegmentName == "__DATA" && SectionName == "__data") | |||
1039 | return 'd'; | |||
1040 | if (SegmentName == "__DATA" && SectionName == "__bss") | |||
1041 | return 'b'; | |||
1042 | return 's'; | |||
1043 | } | |||
1044 | } | |||
1045 | ||||
1046 | return '?'; | |||
1047 | } | |||
1048 | ||||
1049 | static char getSymbolNMTypeChar(WasmObjectFile &Obj, basic_symbol_iterator I) { | |||
1050 | uint32_t Flags = I->getFlags(); | |||
1051 | if (Flags & SymbolRef::SF_Executable) | |||
1052 | return 't'; | |||
1053 | return 'd'; | |||
1054 | } | |||
1055 | ||||
1056 | static char getSymbolNMTypeChar(IRObjectFile &Obj, basic_symbol_iterator I) { | |||
1057 | uint32_t Flags = I->getFlags(); | |||
1058 | // FIXME: should we print 'b'? At the IR level we cannot be sure if this | |||
1059 | // will be in bss or not, but we could approximate. | |||
1060 | if (Flags & SymbolRef::SF_Executable) | |||
1061 | return 't'; | |||
1062 | else if (Triple(Obj.getTargetTriple()).isOSDarwin() && | |||
1063 | (Flags & SymbolRef::SF_Const)) | |||
1064 | return 's'; | |||
1065 | else | |||
1066 | return 'd'; | |||
1067 | } | |||
1068 | ||||
1069 | static bool isObject(SymbolicFile &Obj, basic_symbol_iterator I) { | |||
1070 | return !dyn_cast<ELFObjectFileBase>(&Obj) | |||
1071 | ? false | |||
1072 | : elf_symbol_iterator(I)->getELFType() == ELF::STT_OBJECT; | |||
1073 | } | |||
1074 | ||||
1075 | static char getNMTypeChar(SymbolicFile &Obj, basic_symbol_iterator I) { | |||
1076 | uint32_t Symflags = I->getFlags(); | |||
1077 | if ((Symflags & object::SymbolRef::SF_Weak) && !isa<MachOObjectFile>(Obj)) { | |||
1078 | char Ret = isObject(Obj, I) ? 'v' : 'w'; | |||
1079 | return (!(Symflags & object::SymbolRef::SF_Undefined)) ? toupper(Ret) : Ret; | |||
1080 | } | |||
1081 | ||||
1082 | if (Symflags & object::SymbolRef::SF_Undefined) | |||
1083 | return 'U'; | |||
1084 | ||||
1085 | if (Symflags & object::SymbolRef::SF_Common) | |||
1086 | return 'C'; | |||
1087 | ||||
1088 | char Ret = '?'; | |||
1089 | if (Symflags & object::SymbolRef::SF_Absolute) | |||
1090 | Ret = 'a'; | |||
1091 | else if (IRObjectFile *IR = dyn_cast<IRObjectFile>(&Obj)) | |||
1092 | Ret = getSymbolNMTypeChar(*IR, I); | |||
1093 | else if (COFFObjectFile *COFF = dyn_cast<COFFObjectFile>(&Obj)) | |||
1094 | Ret = getSymbolNMTypeChar(*COFF, I); | |||
1095 | else if (COFFImportFile *COFFImport = dyn_cast<COFFImportFile>(&Obj)) | |||
1096 | Ret = getSymbolNMTypeChar(*COFFImport); | |||
1097 | else if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj)) | |||
1098 | Ret = getSymbolNMTypeChar(*MachO, I); | |||
1099 | else if (WasmObjectFile *Wasm = dyn_cast<WasmObjectFile>(&Obj)) | |||
1100 | Ret = getSymbolNMTypeChar(*Wasm, I); | |||
1101 | else | |||
1102 | Ret = getSymbolNMTypeChar(cast<ELFObjectFileBase>(Obj), I); | |||
1103 | ||||
1104 | if (Symflags & object::SymbolRef::SF_Global) | |||
1105 | Ret = toupper(Ret); | |||
1106 | ||||
1107 | return Ret; | |||
1108 | } | |||
1109 | ||||
1110 | // getNsectForSegSect() is used to implement the Mach-O "-s segname sectname" | |||
1111 | // option to dump only those symbols from that section in a Mach-O file. | |||
1112 | // It is called once for each Mach-O file from dumpSymbolNamesFromObject() | |||
1113 | // to get the section number for that named section from the command line | |||
1114 | // arguments. It returns the section number for that section in the Mach-O | |||
1115 | // file or zero it is not present. | |||
1116 | static unsigned getNsectForSegSect(MachOObjectFile *Obj) { | |||
1117 | unsigned Nsect = 1; | |||
1118 | for (auto &S : Obj->sections()) { | |||
1119 | DataRefImpl Ref = S.getRawDataRefImpl(); | |||
1120 | StringRef SectionName; | |||
1121 | Obj->getSectionName(Ref, SectionName); | |||
1122 | StringRef SegmentName = Obj->getSectionFinalSegmentName(Ref); | |||
1123 | if (SegmentName == SegSect[0] && SectionName == SegSect[1]) | |||
1124 | return Nsect; | |||
1125 | Nsect++; | |||
1126 | } | |||
1127 | return 0; | |||
1128 | } | |||
1129 | ||||
1130 | // getNsectInMachO() is used to implement the Mach-O "-s segname sectname" | |||
1131 | // option to dump only those symbols from that section in a Mach-O file. | |||
1132 | // It is called once for each symbol in a Mach-O file from | |||
1133 | // dumpSymbolNamesFromObject() and returns the section number for that symbol | |||
1134 | // if it is in a section, else it returns 0. | |||
1135 | static unsigned getNsectInMachO(MachOObjectFile &Obj, BasicSymbolRef Sym) { | |||
1136 | DataRefImpl Symb = Sym.getRawDataRefImpl(); | |||
1137 | if (Obj.is64Bit()) { | |||
1138 | MachO::nlist_64 STE = Obj.getSymbol64TableEntry(Symb); | |||
1139 | return (STE.n_type & MachO::N_TYPE) == MachO::N_SECT ? STE.n_sect : 0; | |||
1140 | } | |||
1141 | MachO::nlist STE = Obj.getSymbolTableEntry(Symb); | |||
1142 | return (STE.n_type & MachO::N_TYPE) == MachO::N_SECT ? STE.n_sect : 0; | |||
1143 | } | |||
1144 | ||||
1145 | static void | |||
1146 | dumpSymbolNamesFromObject(SymbolicFile &Obj, bool printName, | |||
1147 | const std::string &ArchiveName = std::string(), | |||
1148 | const std::string &ArchitectureName = std::string()) { | |||
1149 | auto Symbols = Obj.symbols(); | |||
1150 | if (DynamicSyms) { | |||
| ||||
1151 | const auto *E = dyn_cast<ELFObjectFileBase>(&Obj); | |||
1152 | if (!E) { | |||
1153 | error("File format has no dynamic symbol table", Obj.getFileName()); | |||
1154 | return; | |||
1155 | } | |||
1156 | auto DynSymbols = E->getDynamicSymbolIterators(); | |||
1157 | Symbols = | |||
1158 | make_range<basic_symbol_iterator>(DynSymbols.begin(), DynSymbols.end()); | |||
1159 | } | |||
1160 | std::string NameBuffer; | |||
1161 | raw_string_ostream OS(NameBuffer); | |||
1162 | // If a "-s segname sectname" option was specified and this is a Mach-O | |||
1163 | // file get the section number for that section in this object file. | |||
1164 | unsigned int Nsect = 0; | |||
1165 | MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj); | |||
1166 | if (SegSect.size() != 0 && MachO) { | |||
1167 | Nsect = getNsectForSegSect(MachO); | |||
1168 | // If this section is not in the object file no symbols are printed. | |||
1169 | if (Nsect == 0) | |||
1170 | return; | |||
1171 | } | |||
1172 | if (!MachO || !DyldInfoOnly) { | |||
1173 | for (BasicSymbolRef Sym : Symbols) { | |||
1174 | uint32_t SymFlags = Sym.getFlags(); | |||
1175 | if (!DebugSyms && (SymFlags & SymbolRef::SF_FormatSpecific)) | |||
1176 | continue; | |||
1177 | if (WithoutAliases && (SymFlags & SymbolRef::SF_Indirect)) | |||
1178 | continue; | |||
1179 | // If a "-s segname sectname" option was specified and this is a Mach-O | |||
1180 | // file and this section appears in this file, Nsect will be non-zero then | |||
1181 | // see if this symbol is a symbol from that section and if not skip it. | |||
1182 | if (Nsect && Nsect != getNsectInMachO(*MachO, Sym)) | |||
1183 | continue; | |||
1184 | NMSymbol S = {}; | |||
1185 | S.Size = 0; | |||
1186 | S.Address = 0; | |||
1187 | if (PrintSize) { | |||
1188 | if (isa<ELFObjectFileBase>(&Obj)) | |||
1189 | S.Size = ELFSymbolRef(Sym).getSize(); | |||
1190 | } | |||
1191 | if (PrintAddress && isa<ObjectFile>(Obj)) { | |||
1192 | SymbolRef SymRef(Sym); | |||
1193 | Expected<uint64_t> AddressOrErr = SymRef.getAddress(); | |||
1194 | if (!AddressOrErr) { | |||
1195 | consumeError(AddressOrErr.takeError()); | |||
1196 | break; | |||
1197 | } | |||
1198 | S.Address = *AddressOrErr; | |||
1199 | } | |||
1200 | S.TypeChar = getNMTypeChar(Obj, Sym); | |||
1201 | std::error_code EC = Sym.printName(OS); | |||
1202 | if (EC && MachO) | |||
1203 | OS << "bad string index"; | |||
1204 | else | |||
1205 | error(EC); | |||
1206 | OS << '\0'; | |||
1207 | S.Sym = Sym; | |||
1208 | SymbolList.push_back(S); | |||
1209 | } | |||
1210 | } | |||
1211 | ||||
1212 | OS.flush(); | |||
1213 | const char *P = NameBuffer.c_str(); | |||
1214 | unsigned I; | |||
1215 | for (I = 0; I < SymbolList.size(); ++I) { | |||
1216 | SymbolList[I].Name = P; | |||
1217 | P += strlen(P) + 1; | |||
1218 | } | |||
1219 | ||||
1220 | // If this is a Mach-O file where the nlist symbol table is out of sync | |||
1221 | // with the dyld export trie then look through exports and fake up symbols | |||
1222 | // for the ones that are missing (also done with the -add-dyldinfo flag). | |||
1223 | // This is needed if strip(1) -T is run on a binary containing swift | |||
1224 | // language symbols for example. The option -only-dyldinfo will fake up | |||
1225 | // all symbols from the dyld export trie as well as the bind info. | |||
1226 | std::string ExportsNameBuffer; | |||
1227 | raw_string_ostream EOS(ExportsNameBuffer); | |||
1228 | std::string BindsNameBuffer; | |||
1229 | raw_string_ostream BOS(BindsNameBuffer); | |||
1230 | std::string LazysNameBuffer; | |||
1231 | raw_string_ostream LOS(LazysNameBuffer); | |||
1232 | std::string WeaksNameBuffer; | |||
1233 | raw_string_ostream WOS(WeaksNameBuffer); | |||
1234 | std::string FunctionStartsNameBuffer; | |||
1235 | raw_string_ostream FOS(FunctionStartsNameBuffer); | |||
1236 | if (MachO && !NoDyldInfo) { | |||
1237 | MachO::mach_header H; | |||
1238 | MachO::mach_header_64 H_64; | |||
1239 | uint32_t HFlags = 0; | |||
1240 | if (MachO->is64Bit()) { | |||
1241 | H_64 = MachO->MachOObjectFile::getHeader64(); | |||
1242 | HFlags = H_64.flags; | |||
1243 | } else { | |||
1244 | H = MachO->MachOObjectFile::getHeader(); | |||
1245 | HFlags = H.flags; | |||
1246 | } | |||
1247 | uint64_t BaseSegmentAddress = 0; | |||
1248 | for (const auto &Command : MachO->load_commands()) { | |||
1249 | if (Command.C.cmd == MachO::LC_SEGMENT) { | |||
1250 | MachO::segment_command Seg = MachO->getSegmentLoadCommand(Command); | |||
1251 | if (Seg.fileoff == 0 && Seg.filesize != 0) { | |||
1252 | BaseSegmentAddress = Seg.vmaddr; | |||
1253 | break; | |||
1254 | } | |||
1255 | } else if (Command.C.cmd == MachO::LC_SEGMENT_64) { | |||
1256 | MachO::segment_command_64 Seg = MachO->getSegment64LoadCommand(Command); | |||
1257 | if (Seg.fileoff == 0 && Seg.filesize != 0) { | |||
1258 | BaseSegmentAddress = Seg.vmaddr; | |||
1259 | break; | |||
1260 | } | |||
1261 | } | |||
1262 | } | |||
1263 | if (DyldInfoOnly || AddDyldInfo || | |||
1264 | HFlags & MachO::MH_NLIST_OUTOFSYNC_WITH_DYLDINFO) { | |||
1265 | unsigned ExportsAdded = 0; | |||
1266 | Error Err = Error::success(); | |||
1267 | for (const llvm::object::ExportEntry &Entry : MachO->exports(Err)) { | |||
1268 | bool found = false; | |||
1269 | bool ReExport = false; | |||
1270 | if (!DyldInfoOnly) { | |||
1271 | for (unsigned J = 0; J < SymbolList.size() && !found; ++J) { | |||
1272 | if (SymbolList[J].Address == Entry.address() + BaseSegmentAddress && | |||
1273 | SymbolList[J].Name == Entry.name()) | |||
1274 | found = true; | |||
1275 | } | |||
1276 | } | |||
1277 | if (!found) { | |||
1278 | NMSymbol S = {}; | |||
1279 | S.Address = Entry.address() + BaseSegmentAddress; | |||
1280 | S.Size = 0; | |||
1281 | S.TypeChar = '\0'; | |||
1282 | S.Name = Entry.name(); | |||
1283 | // There is no symbol in the nlist symbol table for this so we set | |||
1284 | // Sym effectivly to null and the rest of code in here must test for | |||
1285 | // it and not do things like Sym.getFlags() for it. | |||
1286 | S.Sym = BasicSymbolRef(); | |||
1287 | S.SymFlags = SymbolRef::SF_Global; | |||
1288 | S.Section = SectionRef(); | |||
1289 | S.NType = 0; | |||
1290 | S.NSect = 0; | |||
1291 | S.NDesc = 0; | |||
1292 | S.IndirectName = StringRef(); | |||
1293 | ||||
1294 | uint64_t EFlags = Entry.flags(); | |||
1295 | bool Abs = ((EFlags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) == | |||
1296 | MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE); | |||
1297 | bool Resolver = (EFlags & | |||
1298 | MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER); | |||
1299 | ReExport = (EFlags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT); | |||
1300 | bool WeakDef = (EFlags & MachO::EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION); | |||
1301 | if (WeakDef) | |||
1302 | S.NDesc |= MachO::N_WEAK_DEF; | |||
1303 | if (Abs) { | |||
1304 | S.NType = MachO::N_EXT | MachO::N_ABS; | |||
1305 | S.TypeChar = 'A'; | |||
1306 | } else if (ReExport) { | |||
1307 | S.NType = MachO::N_EXT | MachO::N_INDR; | |||
1308 | S.TypeChar = 'I'; | |||
1309 | } else { | |||
1310 | S.NType = MachO::N_EXT | MachO::N_SECT; | |||
1311 | if (Resolver) { | |||
1312 | S.Address = Entry.other() + BaseSegmentAddress; | |||
1313 | if ((S.Address & 1) != 0 && | |||
1314 | !MachO->is64Bit() && H.cputype == MachO::CPU_TYPE_ARM){ | |||
1315 | S.Address &= ~1LL; | |||
1316 | S.NDesc |= MachO::N_ARM_THUMB_DEF; | |||
1317 | } | |||
1318 | } else { | |||
1319 | S.Address = Entry.address() + BaseSegmentAddress; | |||
1320 | } | |||
1321 | StringRef SegmentName = StringRef(); | |||
1322 | StringRef SectionName = StringRef(); | |||
1323 | for (const SectionRef &Section : MachO->sections()) { | |||
1324 | S.NSect++; | |||
1325 | Section.getName(SectionName); | |||
1326 | SegmentName = MachO->getSectionFinalSegmentName( | |||
1327 | Section.getRawDataRefImpl()); | |||
1328 | if (S.Address >= Section.getAddress() && | |||
1329 | S.Address < Section.getAddress() + Section.getSize()) { | |||
1330 | S.Section = Section; | |||
1331 | break; | |||
1332 | } else if (Entry.name() == "__mh_execute_header" && | |||
1333 | SegmentName == "__TEXT" && SectionName == "__text") { | |||
1334 | S.Section = Section; | |||
1335 | S.NDesc |= MachO::REFERENCED_DYNAMICALLY; | |||
1336 | break; | |||
1337 | } | |||
1338 | } | |||
1339 | if (SegmentName == "__TEXT" && SectionName == "__text") | |||
1340 | S.TypeChar = 'T'; | |||
1341 | else if (SegmentName == "__DATA" && SectionName == "__data") | |||
1342 | S.TypeChar = 'D'; | |||
1343 | else if (SegmentName == "__DATA" && SectionName == "__bss") | |||
1344 | S.TypeChar = 'B'; | |||
1345 | else | |||
1346 | S.TypeChar = 'S'; | |||
1347 | } | |||
1348 | SymbolList.push_back(S); | |||
1349 | ||||
1350 | EOS << Entry.name(); | |||
1351 | EOS << '\0'; | |||
1352 | ExportsAdded++; | |||
1353 | ||||
1354 | // For ReExports there are a two more things to do, first add the | |||
1355 | // indirect name and second create the undefined symbol using the | |||
1356 | // referened dynamic library. | |||
1357 | if (ReExport) { | |||
1358 | ||||
1359 | // Add the indirect name. | |||
1360 | if (Entry.otherName().empty()) | |||
1361 | EOS << Entry.name(); | |||
1362 | else | |||
1363 | EOS << Entry.otherName(); | |||
1364 | EOS << '\0'; | |||
1365 | ||||
1366 | // Now create the undefined symbol using the referened dynamic | |||
1367 | // library. | |||
1368 | NMSymbol U = {}; | |||
1369 | U.Address = 0; | |||
1370 | U.Size = 0; | |||
1371 | U.TypeChar = 'U'; | |||
1372 | if (Entry.otherName().empty()) | |||
1373 | U.Name = Entry.name(); | |||
1374 | else | |||
1375 | U.Name = Entry.otherName(); | |||
1376 | // Again there is no symbol in the nlist symbol table for this so | |||
1377 | // we set Sym effectivly to null and the rest of code in here must | |||
1378 | // test for it and not do things like Sym.getFlags() for it. | |||
1379 | U.Sym = BasicSymbolRef(); | |||
1380 | U.SymFlags = SymbolRef::SF_Global | SymbolRef::SF_Undefined; | |||
1381 | U.Section = SectionRef(); | |||
1382 | U.NType = MachO::N_EXT | MachO::N_UNDF; | |||
1383 | U.NSect = 0; | |||
1384 | U.NDesc = 0; | |||
1385 | // The library ordinal for this undefined symbol is in the export | |||
1386 | // trie Entry.other(). | |||
1387 | MachO::SET_LIBRARY_ORDINAL(U.NDesc, Entry.other()); | |||
1388 | U.IndirectName = StringRef(); | |||
1389 | SymbolList.push_back(U); | |||
1390 | ||||
1391 | // Finally add the undefined symbol's name. | |||
1392 | if (Entry.otherName().empty()) | |||
1393 | EOS << Entry.name(); | |||
1394 | else | |||
1395 | EOS << Entry.otherName(); | |||
1396 | EOS << '\0'; | |||
1397 | ExportsAdded++; | |||
1398 | } | |||
1399 | } | |||
1400 | } | |||
1401 | if (Err) | |||
1402 | error(std::move(Err), MachO->getFileName()); | |||
1403 | // Set the symbol names and indirect names for the added symbols. | |||
1404 | if (ExportsAdded) { | |||
1405 | EOS.flush(); | |||
1406 | const char *Q = ExportsNameBuffer.c_str(); | |||
1407 | for (unsigned K = 0; K < ExportsAdded; K++) { | |||
1408 | SymbolList[I].Name = Q; | |||
1409 | Q += strlen(Q) + 1; | |||
1410 | if (SymbolList[I].TypeChar == 'I') { | |||
1411 | SymbolList[I].IndirectName = Q; | |||
1412 | Q += strlen(Q) + 1; | |||
1413 | } | |||
1414 | I++; | |||
1415 | } | |||
1416 | } | |||
1417 | ||||
1418 | // Add the undefined symbols from the bind entries. | |||
1419 | unsigned BindsAdded = 0; | |||
1420 | Error BErr = Error::success(); | |||
1421 | StringRef LastSymbolName = StringRef(); | |||
1422 | for (const llvm::object::MachOBindEntry &Entry : MachO->bindTable(BErr)) { | |||
1423 | bool found = false; | |||
1424 | if (LastSymbolName == Entry.symbolName()) | |||
1425 | found = true; | |||
1426 | else if(!DyldInfoOnly) { | |||
1427 | for (unsigned J = 0; J < SymbolList.size() && !found; ++J) { | |||
1428 | if (SymbolList[J].Name == Entry.symbolName()) | |||
1429 | found = true; | |||
1430 | } | |||
1431 | } | |||
1432 | if (!found) { | |||
1433 | LastSymbolName = Entry.symbolName(); | |||
1434 | NMSymbol B = {}; | |||
1435 | B.Address = 0; | |||
1436 | B.Size = 0; | |||
1437 | B.TypeChar = 'U'; | |||
1438 | // There is no symbol in the nlist symbol table for this so we set | |||
1439 | // Sym effectivly to null and the rest of code in here must test for | |||
1440 | // it and not do things like Sym.getFlags() for it. | |||
1441 | B.Sym = BasicSymbolRef(); | |||
1442 | B.SymFlags = SymbolRef::SF_Global | SymbolRef::SF_Undefined; | |||
1443 | B.NType = MachO::N_EXT | MachO::N_UNDF; | |||
1444 | B.NSect = 0; | |||
1445 | B.NDesc = 0; | |||
1446 | B.NDesc = 0; | |||
1447 | MachO::SET_LIBRARY_ORDINAL(B.NDesc, Entry.ordinal()); | |||
1448 | B.IndirectName = StringRef(); | |||
1449 | B.Name = Entry.symbolName(); | |||
1450 | SymbolList.push_back(B); | |||
1451 | BOS << Entry.symbolName(); | |||
1452 | BOS << '\0'; | |||
1453 | BindsAdded++; | |||
1454 | } | |||
1455 | } | |||
1456 | if (BErr) | |||
1457 | error(std::move(BErr), MachO->getFileName()); | |||
1458 | // Set the symbol names and indirect names for the added symbols. | |||
1459 | if (BindsAdded) { | |||
1460 | BOS.flush(); | |||
1461 | const char *Q = BindsNameBuffer.c_str(); | |||
1462 | for (unsigned K = 0; K < BindsAdded; K++) { | |||
1463 | SymbolList[I].Name = Q; | |||
1464 | Q += strlen(Q) + 1; | |||
1465 | if (SymbolList[I].TypeChar == 'I') { | |||
1466 | SymbolList[I].IndirectName = Q; | |||
1467 | Q += strlen(Q) + 1; | |||
1468 | } | |||
1469 | I++; | |||
1470 | } | |||
1471 | } | |||
1472 | ||||
1473 | // Add the undefined symbols from the lazy bind entries. | |||
1474 | unsigned LazysAdded = 0; | |||
1475 | Error LErr = Error::success(); | |||
1476 | LastSymbolName = StringRef(); | |||
1477 | for (const llvm::object::MachOBindEntry &Entry : | |||
1478 | MachO->lazyBindTable(LErr)) { | |||
1479 | bool found = false; | |||
1480 | if (LastSymbolName == Entry.symbolName()) | |||
1481 | found = true; | |||
1482 | else { | |||
1483 | // Here we must check to see it this symbol is already in the | |||
1484 | // SymbolList as it might have already have been added above via a | |||
1485 | // non-lazy (bind) entry. | |||
1486 | for (unsigned J = 0; J < SymbolList.size() && !found; ++J) { | |||
1487 | if (SymbolList[J].Name == Entry.symbolName()) | |||
1488 | found = true; | |||
1489 | } | |||
1490 | } | |||
1491 | if (!found) { | |||
1492 | LastSymbolName = Entry.symbolName(); | |||
1493 | NMSymbol L = {}; | |||
1494 | L.Name = Entry.symbolName(); | |||
1495 | L.Address = 0; | |||
1496 | L.Size = 0; | |||
1497 | L.TypeChar = 'U'; | |||
1498 | // There is no symbol in the nlist symbol table for this so we set | |||
1499 | // Sym effectivly to null and the rest of code in here must test for | |||
1500 | // it and not do things like Sym.getFlags() for it. | |||
1501 | L.Sym = BasicSymbolRef(); | |||
1502 | L.SymFlags = SymbolRef::SF_Global | SymbolRef::SF_Undefined; | |||
1503 | L.NType = MachO::N_EXT | MachO::N_UNDF; | |||
1504 | L.NSect = 0; | |||
1505 | // The REFERENCE_FLAG_UNDEFINED_LAZY is no longer used but here it | |||
1506 | // makes sence since we are creating this from a lazy bind entry. | |||
1507 | L.NDesc = MachO::REFERENCE_FLAG_UNDEFINED_LAZY; | |||
1508 | MachO::SET_LIBRARY_ORDINAL(L.NDesc, Entry.ordinal()); | |||
1509 | L.IndirectName = StringRef(); | |||
1510 | SymbolList.push_back(L); | |||
1511 | LOS << Entry.symbolName(); | |||
1512 | LOS << '\0'; | |||
1513 | LazysAdded++; | |||
1514 | } | |||
1515 | } | |||
1516 | if (LErr) | |||
1517 | error(std::move(LErr), MachO->getFileName()); | |||
1518 | // Set the symbol names and indirect names for the added symbols. | |||
1519 | if (LazysAdded) { | |||
1520 | LOS.flush(); | |||
1521 | const char *Q = LazysNameBuffer.c_str(); | |||
1522 | for (unsigned K = 0; K < LazysAdded; K++) { | |||
1523 | SymbolList[I].Name = Q; | |||
1524 | Q += strlen(Q) + 1; | |||
1525 | if (SymbolList[I].TypeChar == 'I') { | |||
1526 | SymbolList[I].IndirectName = Q; | |||
1527 | Q += strlen(Q) + 1; | |||
1528 | } | |||
1529 | I++; | |||
1530 | } | |||
1531 | } | |||
1532 | ||||
1533 | // Add the undefineds symbol from the weak bind entries which are not | |||
1534 | // strong symbols. | |||
1535 | unsigned WeaksAdded = 0; | |||
1536 | Error WErr = Error::success(); | |||
1537 | LastSymbolName = StringRef(); | |||
1538 | for (const llvm::object::MachOBindEntry &Entry : | |||
1539 | MachO->weakBindTable(WErr)) { | |||
1540 | bool found = false; | |||
1541 | unsigned J = 0; | |||
1542 | if (LastSymbolName == Entry.symbolName() || | |||
1543 | Entry.flags() & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) { | |||
1544 | found = true; | |||
1545 | } else { | |||
1546 | for (J = 0; J < SymbolList.size() && !found; ++J) { | |||
1547 | if (SymbolList[J].Name == Entry.symbolName()) { | |||
1548 | found = true; | |||
1549 | break; | |||
1550 | } | |||
1551 | } | |||
1552 | } | |||
1553 | if (!found) { | |||
1554 | LastSymbolName = Entry.symbolName(); | |||
1555 | NMSymbol W; | |||
1556 | memset(&W, '\0', sizeof(NMSymbol)); | |||
1557 | W.Name = Entry.symbolName(); | |||
1558 | W.Address = 0; | |||
1559 | W.Size = 0; | |||
1560 | W.TypeChar = 'U'; | |||
1561 | // There is no symbol in the nlist symbol table for this so we set | |||
1562 | // Sym effectivly to null and the rest of code in here must test for | |||
1563 | // it and not do things like Sym.getFlags() for it. | |||
1564 | W.Sym = BasicSymbolRef(); | |||
1565 | W.SymFlags = SymbolRef::SF_Global | SymbolRef::SF_Undefined; | |||
1566 | W.NType = MachO::N_EXT | MachO::N_UNDF; | |||
1567 | W.NSect = 0; | |||
1568 | // Odd that we are using N_WEAK_DEF on an undefined symbol but that is | |||
1569 | // what is created in this case by the linker when there are real | |||
1570 | // symbols in the nlist structs. | |||
1571 | W.NDesc = MachO::N_WEAK_DEF; | |||
1572 | W.IndirectName = StringRef(); | |||
1573 | SymbolList.push_back(W); | |||
1574 | WOS << Entry.symbolName(); | |||
1575 | WOS << '\0'; | |||
1576 | WeaksAdded++; | |||
1577 | } else { | |||
1578 | // This is the case the symbol was previously been found and it could | |||
1579 | // have been added from a bind or lazy bind symbol. If so and not | |||
1580 | // a definition also mark it as weak. | |||
1581 | if (SymbolList[J].TypeChar == 'U') | |||
1582 | // See comment above about N_WEAK_DEF. | |||
1583 | SymbolList[J].NDesc |= MachO::N_WEAK_DEF; | |||
1584 | } | |||
1585 | } | |||
1586 | if (WErr) | |||
1587 | error(std::move(WErr), MachO->getFileName()); | |||
1588 | // Set the symbol names and indirect names for the added symbols. | |||
1589 | if (WeaksAdded) { | |||
1590 | WOS.flush(); | |||
1591 | const char *Q = WeaksNameBuffer.c_str(); | |||
1592 | for (unsigned K = 0; K < WeaksAdded; K++) { | |||
1593 | SymbolList[I].Name = Q; | |||
1594 | Q += strlen(Q) + 1; | |||
1595 | if (SymbolList[I].TypeChar == 'I') { | |||
1596 | SymbolList[I].IndirectName = Q; | |||
1597 | Q += strlen(Q) + 1; | |||
1598 | } | |||
1599 | I++; | |||
1600 | } | |||
1601 | } | |||
1602 | ||||
1603 | // Trying adding symbol from the function starts table and LC_MAIN entry | |||
1604 | // point. | |||
1605 | SmallVector<uint64_t, 8> FoundFns; | |||
1606 | uint64_t lc_main_offset = UINT64_MAX(18446744073709551615UL); | |||
1607 | for (const auto &Command : MachO->load_commands()) { | |||
1608 | if (Command.C.cmd == MachO::LC_FUNCTION_STARTS) { | |||
1609 | // We found a function starts segment, parse the addresses for | |||
1610 | // consumption. | |||
1611 | MachO::linkedit_data_command LLC = | |||
1612 | MachO->getLinkeditDataLoadCommand(Command); | |||
1613 | ||||
1614 | MachO->ReadULEB128s(LLC.dataoff, FoundFns); | |||
1615 | } else if (Command.C.cmd == MachO::LC_MAIN) { | |||
1616 | MachO::entry_point_command LCmain = | |||
1617 | MachO->getEntryPointCommand(Command); | |||
1618 | lc_main_offset = LCmain.entryoff; | |||
1619 | } | |||
1620 | } | |||
1621 | // See if these addresses are already in the symbol table. | |||
1622 | unsigned FunctionStartsAdded = 0; | |||
1623 | for (uint64_t f = 0; f < FoundFns.size(); f++) { | |||
1624 | bool found = false; | |||
1625 | for (unsigned J = 0; J < SymbolList.size() && !found; ++J) { | |||
1626 | if (SymbolList[J].Address == FoundFns[f] + BaseSegmentAddress) | |||
1627 | found = true; | |||
1628 | } | |||
1629 | // See this address is not already in the symbol table fake up an | |||
1630 | // nlist for it. | |||
1631 | if (!found) { | |||
1632 | NMSymbol F = {}; | |||
1633 | F.Name = "<redacted function X>"; | |||
1634 | F.Address = FoundFns[f] + BaseSegmentAddress; | |||
1635 | F.Size = 0; | |||
1636 | // There is no symbol in the nlist symbol table for this so we set | |||
1637 | // Sym effectivly to null and the rest of code in here must test for | |||
1638 | // it and not do things like Sym.getFlags() for it. | |||
1639 | F.Sym = BasicSymbolRef(); | |||
1640 | F.SymFlags = 0; | |||
1641 | F.NType = MachO::N_SECT; | |||
1642 | F.NSect = 0; | |||
1643 | StringRef SegmentName = StringRef(); | |||
1644 | StringRef SectionName = StringRef(); | |||
1645 | for (const SectionRef &Section : MachO->sections()) { | |||
1646 | Section.getName(SectionName); | |||
1647 | SegmentName = MachO->getSectionFinalSegmentName( | |||
1648 | Section.getRawDataRefImpl()); | |||
1649 | F.NSect++; | |||
1650 | if (F.Address >= Section.getAddress() && | |||
1651 | F.Address < Section.getAddress() + Section.getSize()) { | |||
1652 | F.Section = Section; | |||
1653 | break; | |||
1654 | } | |||
1655 | } | |||
1656 | if (SegmentName == "__TEXT" && SectionName == "__text") | |||
1657 | F.TypeChar = 't'; | |||
1658 | else if (SegmentName == "__DATA" && SectionName == "__data") | |||
1659 | F.TypeChar = 'd'; | |||
1660 | else if (SegmentName == "__DATA" && SectionName == "__bss") | |||
1661 | F.TypeChar = 'b'; | |||
1662 | else | |||
1663 | F.TypeChar = 's'; | |||
1664 | F.NDesc = 0; | |||
1665 | F.IndirectName = StringRef(); | |||
1666 | SymbolList.push_back(F); | |||
1667 | if (FoundFns[f] == lc_main_offset) | |||
1668 | FOS << "<redacted LC_MAIN>"; | |||
1669 | else | |||
1670 | FOS << "<redacted function " << f << ">"; | |||
1671 | FOS << '\0'; | |||
1672 | FunctionStartsAdded++; | |||
1673 | } | |||
1674 | } | |||
1675 | if (FunctionStartsAdded) { | |||
1676 | FOS.flush(); | |||
1677 | const char *Q = FunctionStartsNameBuffer.c_str(); | |||
1678 | for (unsigned K = 0; K < FunctionStartsAdded; K++) { | |||
1679 | SymbolList[I].Name = Q; | |||
1680 | Q += strlen(Q) + 1; | |||
1681 | if (SymbolList[I].TypeChar == 'I') { | |||
1682 | SymbolList[I].IndirectName = Q; | |||
1683 | Q += strlen(Q) + 1; | |||
1684 | } | |||
1685 | I++; | |||
1686 | } | |||
1687 | } | |||
1688 | } | |||
1689 | } | |||
1690 | ||||
1691 | CurrentFilename = Obj.getFileName(); | |||
1692 | sortAndPrintSymbolList(Obj, printName, ArchiveName, ArchitectureName); | |||
1693 | } | |||
1694 | ||||
1695 | // checkMachOAndArchFlags() checks to see if the SymbolicFile is a Mach-O file | |||
1696 | // and if it is and there is a list of architecture flags is specified then | |||
1697 | // check to make sure this Mach-O file is one of those architectures or all | |||
1698 | // architectures was specificed. If not then an error is generated and this | |||
1699 | // routine returns false. Else it returns true. | |||
1700 | static bool checkMachOAndArchFlags(SymbolicFile *O, std::string &Filename) { | |||
1701 | auto *MachO = dyn_cast<MachOObjectFile>(O); | |||
1702 | ||||
1703 | if (!MachO || ArchAll || ArchFlags.empty()) | |||
1704 | return true; | |||
1705 | ||||
1706 | MachO::mach_header H; | |||
1707 | MachO::mach_header_64 H_64; | |||
1708 | Triple T; | |||
1709 | const char *McpuDefault, *ArchFlag; | |||
1710 | if (MachO->is64Bit()) { | |||
1711 | H_64 = MachO->MachOObjectFile::getHeader64(); | |||
1712 | T = MachOObjectFile::getArchTriple(H_64.cputype, H_64.cpusubtype, | |||
1713 | &McpuDefault, &ArchFlag); | |||
1714 | } else { | |||
1715 | H = MachO->MachOObjectFile::getHeader(); | |||
1716 | T = MachOObjectFile::getArchTriple(H.cputype, H.cpusubtype, | |||
1717 | &McpuDefault, &ArchFlag); | |||
1718 | } | |||
1719 | const std::string ArchFlagName(ArchFlag); | |||
1720 | if (none_of(ArchFlags, [&](const std::string &Name) { | |||
1721 | return Name == ArchFlagName; | |||
1722 | })) { | |||
1723 | error("No architecture specified", Filename); | |||
1724 | return false; | |||
1725 | } | |||
1726 | return true; | |||
1727 | } | |||
1728 | ||||
1729 | static void dumpSymbolNamesFromFile(std::string &Filename) { | |||
1730 | ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr = | |||
1731 | MemoryBuffer::getFileOrSTDIN(Filename); | |||
1732 | if (error(BufferOrErr.getError(), Filename)) | |||
1733 | return; | |||
1734 | ||||
1735 | LLVMContext Context; | |||
1736 | Expected<std::unique_ptr<Binary>> BinaryOrErr = createBinary( | |||
1737 | BufferOrErr.get()->getMemBufferRef(), NoLLVMBitcode ? nullptr : &Context); | |||
1738 | if (!BinaryOrErr) { | |||
1739 | error(BinaryOrErr.takeError(), Filename); | |||
1740 | return; | |||
1741 | } | |||
1742 | Binary &Bin = *BinaryOrErr.get(); | |||
1743 | ||||
1744 | if (Archive *A = dyn_cast<Archive>(&Bin)) { | |||
1745 | if (ArchiveMap) { | |||
1746 | Archive::symbol_iterator I = A->symbol_begin(); | |||
1747 | Archive::symbol_iterator E = A->symbol_end(); | |||
1748 | if (I != E) { | |||
1749 | outs() << "Archive map\n"; | |||
1750 | for (; I != E; ++I) { | |||
1751 | Expected<Archive::Child> C = I->getMember(); | |||
1752 | if (!C) { | |||
1753 | error(C.takeError(), Filename); | |||
1754 | break; | |||
1755 | } | |||
1756 | Expected<StringRef> FileNameOrErr = C->getName(); | |||
1757 | if (!FileNameOrErr) { | |||
1758 | error(FileNameOrErr.takeError(), Filename); | |||
1759 | break; | |||
1760 | } | |||
1761 | StringRef SymName = I->getName(); | |||
1762 | outs() << SymName << " in " << FileNameOrErr.get() << "\n"; | |||
1763 | } | |||
1764 | outs() << "\n"; | |||
1765 | } | |||
1766 | } | |||
1767 | ||||
1768 | { | |||
1769 | Error Err = Error::success(); | |||
1770 | for (auto &C : A->children(Err)) { | |||
1771 | Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(&Context); | |||
1772 | if (!ChildOrErr) { | |||
1773 | if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) | |||
1774 | error(std::move(E), Filename, C); | |||
1775 | continue; | |||
1776 | } | |||
1777 | if (SymbolicFile *O = dyn_cast<SymbolicFile>(&*ChildOrErr.get())) { | |||
1778 | if (!MachOPrintSizeWarning && PrintSize && isa<MachOObjectFile>(O)) { | |||
1779 | errs() << ToolName << ": warning sizes with -print-size for Mach-O " | |||
1780 | "files are always zero.\n"; | |||
1781 | MachOPrintSizeWarning = true; | |||
1782 | } | |||
1783 | if (!checkMachOAndArchFlags(O, Filename)) | |||
1784 | return; | |||
1785 | if (!PrintFileName) { | |||
1786 | outs() << "\n"; | |||
1787 | if (isa<MachOObjectFile>(O)) { | |||
1788 | outs() << Filename << "(" << O->getFileName() << ")"; | |||
1789 | } else | |||
1790 | outs() << O->getFileName(); | |||
1791 | outs() << ":\n"; | |||
1792 | } | |||
1793 | dumpSymbolNamesFromObject(*O, false, Filename); | |||
1794 | } | |||
1795 | } | |||
1796 | if (Err) | |||
1797 | error(std::move(Err), A->getFileName()); | |||
1798 | } | |||
1799 | return; | |||
1800 | } | |||
1801 | if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(&Bin)) { | |||
1802 | // If we have a list of architecture flags specified dump only those. | |||
1803 | if (!ArchAll && ArchFlags.size() != 0) { | |||
1804 | // Look for a slice in the universal binary that matches each ArchFlag. | |||
1805 | bool ArchFound; | |||
1806 | for (unsigned i = 0; i < ArchFlags.size(); ++i) { | |||
1807 | ArchFound = false; | |||
1808 | for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), | |||
1809 | E = UB->end_objects(); | |||
1810 | I != E; ++I) { | |||
1811 | if (ArchFlags[i] == I->getArchFlagName()) { | |||
1812 | ArchFound = true; | |||
1813 | Expected<std::unique_ptr<ObjectFile>> ObjOrErr = | |||
1814 | I->getAsObjectFile(); | |||
1815 | std::string ArchiveName; | |||
1816 | std::string ArchitectureName; | |||
1817 | ArchiveName.clear(); | |||
1818 | ArchitectureName.clear(); | |||
1819 | if (ObjOrErr) { | |||
1820 | ObjectFile &Obj = *ObjOrErr.get(); | |||
1821 | if (ArchFlags.size() > 1) { | |||
1822 | if (PrintFileName) | |||
1823 | ArchitectureName = I->getArchFlagName(); | |||
1824 | else | |||
1825 | outs() << "\n" << Obj.getFileName() << " (for architecture " | |||
1826 | << I->getArchFlagName() << ")" | |||
1827 | << ":\n"; | |||
1828 | } | |||
1829 | dumpSymbolNamesFromObject(Obj, false, ArchiveName, | |||
1830 | ArchitectureName); | |||
1831 | } else if (auto E = isNotObjectErrorInvalidFileType( | |||
1832 | ObjOrErr.takeError())) { | |||
1833 | error(std::move(E), Filename, ArchFlags.size() > 1 ? | |||
1834 | StringRef(I->getArchFlagName()) : StringRef()); | |||
1835 | continue; | |||
1836 | } else if (Expected<std::unique_ptr<Archive>> AOrErr = | |||
1837 | I->getAsArchive()) { | |||
1838 | std::unique_ptr<Archive> &A = *AOrErr; | |||
1839 | Error Err = Error::success(); | |||
1840 | for (auto &C : A->children(Err)) { | |||
1841 | Expected<std::unique_ptr<Binary>> ChildOrErr = | |||
1842 | C.getAsBinary(&Context); | |||
1843 | if (!ChildOrErr) { | |||
1844 | if (auto E = isNotObjectErrorInvalidFileType( | |||
1845 | ChildOrErr.takeError())) { | |||
1846 | error(std::move(E), Filename, C, ArchFlags.size() > 1 ? | |||
1847 | StringRef(I->getArchFlagName()) : StringRef()); | |||
1848 | } | |||
1849 | continue; | |||
1850 | } | |||
1851 | if (SymbolicFile *O = | |||
1852 | dyn_cast<SymbolicFile>(&*ChildOrErr.get())) { | |||
1853 | if (PrintFileName) { | |||
1854 | ArchiveName = A->getFileName(); | |||
1855 | if (ArchFlags.size() > 1) | |||
1856 | ArchitectureName = I->getArchFlagName(); | |||
1857 | } else { | |||
1858 | outs() << "\n" << A->getFileName(); | |||
1859 | outs() << "(" << O->getFileName() << ")"; | |||
1860 | if (ArchFlags.size() > 1) { | |||
1861 | outs() << " (for architecture " << I->getArchFlagName() | |||
1862 | << ")"; | |||
1863 | } | |||
1864 | outs() << ":\n"; | |||
1865 | } | |||
1866 | dumpSymbolNamesFromObject(*O, false, ArchiveName, | |||
1867 | ArchitectureName); | |||
1868 | } | |||
1869 | } | |||
1870 | if (Err) | |||
1871 | error(std::move(Err), A->getFileName()); | |||
1872 | } else { | |||
1873 | consumeError(AOrErr.takeError()); | |||
1874 | error(Filename + " for architecture " + | |||
1875 | StringRef(I->getArchFlagName()) + | |||
1876 | " is not a Mach-O file or an archive file", | |||
1877 | "Mach-O universal file"); | |||
1878 | } | |||
1879 | } | |||
1880 | } | |||
1881 | if (!ArchFound) { | |||
1882 | error(ArchFlags[i], | |||
1883 | "file: " + Filename + " does not contain architecture"); | |||
1884 | return; | |||
1885 | } | |||
1886 | } | |||
1887 | return; | |||
1888 | } | |||
1889 | // No architecture flags were specified so if this contains a slice that | |||
1890 | // matches the host architecture dump only that. | |||
1891 | if (!ArchAll) { | |||
1892 | StringRef HostArchName = MachOObjectFile::getHostArch().getArchName(); | |||
1893 | for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), | |||
1894 | E = UB->end_objects(); | |||
1895 | I != E; ++I) { | |||
1896 | if (HostArchName == I->getArchFlagName()) { | |||
1897 | Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile(); | |||
1898 | std::string ArchiveName; | |||
1899 | if (ObjOrErr) { | |||
1900 | ObjectFile &Obj = *ObjOrErr.get(); | |||
1901 | dumpSymbolNamesFromObject(Obj, false); | |||
1902 | } else if (auto E = isNotObjectErrorInvalidFileType( | |||
1903 | ObjOrErr.takeError())) { | |||
1904 | error(std::move(E), Filename); | |||
1905 | return; | |||
1906 | } else if (Expected<std::unique_ptr<Archive>> AOrErr = | |||
1907 | I->getAsArchive()) { | |||
1908 | std::unique_ptr<Archive> &A = *AOrErr; | |||
1909 | Error Err = Error::success(); | |||
1910 | for (auto &C : A->children(Err)) { | |||
1911 | Expected<std::unique_ptr<Binary>> ChildOrErr = | |||
1912 | C.getAsBinary(&Context); | |||
1913 | if (!ChildOrErr) { | |||
1914 | if (auto E = isNotObjectErrorInvalidFileType( | |||
1915 | ChildOrErr.takeError())) | |||
1916 | error(std::move(E), Filename, C); | |||
1917 | continue; | |||
1918 | } | |||
1919 | if (SymbolicFile *O = | |||
1920 | dyn_cast<SymbolicFile>(&*ChildOrErr.get())) { | |||
1921 | if (PrintFileName) | |||
1922 | ArchiveName = A->getFileName(); | |||
1923 | else | |||
1924 | outs() << "\n" << A->getFileName() << "(" << O->getFileName() | |||
1925 | << ")" | |||
1926 | << ":\n"; | |||
1927 | dumpSymbolNamesFromObject(*O, false, ArchiveName); | |||
1928 | } | |||
1929 | } | |||
1930 | if (Err) | |||
1931 | error(std::move(Err), A->getFileName()); | |||
1932 | } else { | |||
1933 | consumeError(AOrErr.takeError()); | |||
1934 | error(Filename + " for architecture " + | |||
1935 | StringRef(I->getArchFlagName()) + | |||
1936 | " is not a Mach-O file or an archive file", | |||
1937 | "Mach-O universal file"); | |||
1938 | } | |||
1939 | return; | |||
1940 | } | |||
1941 | } | |||
1942 | } | |||
1943 | // Either all architectures have been specified or none have been specified | |||
1944 | // and this does not contain the host architecture so dump all the slices. | |||
1945 | bool moreThanOneArch = UB->getNumberOfObjects() > 1; | |||
1946 | for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), | |||
1947 | E = UB->end_objects(); | |||
1948 | I != E; ++I) { | |||
1949 | Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile(); | |||
1950 | std::string ArchiveName; | |||
1951 | std::string ArchitectureName; | |||
1952 | ArchiveName.clear(); | |||
1953 | ArchitectureName.clear(); | |||
1954 | if (ObjOrErr) { | |||
1955 | ObjectFile &Obj = *ObjOrErr.get(); | |||
1956 | if (PrintFileName) { | |||
1957 | if (isa<MachOObjectFile>(Obj) && moreThanOneArch) | |||
1958 | ArchitectureName = I->getArchFlagName(); | |||
1959 | } else { | |||
1960 | if (moreThanOneArch) | |||
1961 | outs() << "\n"; | |||
1962 | outs() << Obj.getFileName(); | |||
1963 | if (isa<MachOObjectFile>(Obj) && moreThanOneArch) | |||
1964 | outs() << " (for architecture " << I->getArchFlagName() << ")"; | |||
1965 | outs() << ":\n"; | |||
1966 | } | |||
1967 | dumpSymbolNamesFromObject(Obj, false, ArchiveName, ArchitectureName); | |||
1968 | } else if (auto E = isNotObjectErrorInvalidFileType( | |||
1969 | ObjOrErr.takeError())) { | |||
1970 | error(std::move(E), Filename, moreThanOneArch ? | |||
1971 | StringRef(I->getArchFlagName()) : StringRef()); | |||
1972 | continue; | |||
1973 | } else if (Expected<std::unique_ptr<Archive>> AOrErr = | |||
1974 | I->getAsArchive()) { | |||
1975 | std::unique_ptr<Archive> &A = *AOrErr; | |||
1976 | Error Err = Error::success(); | |||
1977 | for (auto &C : A->children(Err)) { | |||
1978 | Expected<std::unique_ptr<Binary>> ChildOrErr = | |||
1979 | C.getAsBinary(&Context); | |||
1980 | if (!ChildOrErr) { | |||
1981 | if (auto E = isNotObjectErrorInvalidFileType( | |||
1982 | ChildOrErr.takeError())) | |||
1983 | error(std::move(E), Filename, C, moreThanOneArch ? | |||
1984 | StringRef(ArchitectureName) : StringRef()); | |||
1985 | continue; | |||
1986 | } | |||
1987 | if (SymbolicFile *O = dyn_cast<SymbolicFile>(&*ChildOrErr.get())) { | |||
1988 | if (PrintFileName) { | |||
1989 | ArchiveName = A->getFileName(); | |||
1990 | if (isa<MachOObjectFile>(O) && moreThanOneArch) | |||
1991 | ArchitectureName = I->getArchFlagName(); | |||
1992 | } else { | |||
1993 | outs() << "\n" << A->getFileName(); | |||
1994 | if (isa<MachOObjectFile>(O)) { | |||
1995 | outs() << "(" << O->getFileName() << ")"; | |||
1996 | if (moreThanOneArch) | |||
1997 | outs() << " (for architecture " << I->getArchFlagName() | |||
1998 | << ")"; | |||
1999 | } else | |||
2000 | outs() << ":" << O->getFileName(); | |||
2001 | outs() << ":\n"; | |||
2002 | } | |||
2003 | dumpSymbolNamesFromObject(*O, false, ArchiveName, ArchitectureName); | |||
2004 | } | |||
2005 | } | |||
2006 | if (Err) | |||
2007 | error(std::move(Err), A->getFileName()); | |||
2008 | } else { | |||
2009 | consumeError(AOrErr.takeError()); | |||
2010 | error(Filename + " for architecture " + | |||
2011 | StringRef(I->getArchFlagName()) + | |||
2012 | " is not a Mach-O file or an archive file", | |||
2013 | "Mach-O universal file"); | |||
2014 | } | |||
2015 | } | |||
2016 | return; | |||
2017 | } | |||
2018 | if (SymbolicFile *O = dyn_cast<SymbolicFile>(&Bin)) { | |||
2019 | if (!MachOPrintSizeWarning && PrintSize && isa<MachOObjectFile>(O)) { | |||
2020 | errs() << ToolName << ": warning sizes with -print-size for Mach-O files " | |||
2021 | "are always zero.\n"; | |||
2022 | MachOPrintSizeWarning = true; | |||
2023 | } | |||
2024 | if (!checkMachOAndArchFlags(O, Filename)) | |||
2025 | return; | |||
2026 | dumpSymbolNamesFromObject(*O, true); | |||
2027 | } | |||
2028 | } | |||
2029 | ||||
2030 | int main(int argc, char **argv) { | |||
2031 | InitLLVM X(argc, argv); | |||
2032 | cl::ParseCommandLineOptions(argc, argv, "llvm symbol table dumper\n"); | |||
2033 | ||||
2034 | // llvm-nm only reads binary files. | |||
2035 | if (error(sys::ChangeStdinToBinary())) | |||
2036 | return 1; | |||
2037 | ||||
2038 | // These calls are needed so that we can read bitcode correctly. | |||
2039 | llvm::InitializeAllTargetInfos(); | |||
2040 | llvm::InitializeAllTargetMCs(); | |||
2041 | llvm::InitializeAllAsmParsers(); | |||
2042 | ||||
2043 | ToolName = argv[0]; | |||
2044 | if (BSDFormat) | |||
2045 | OutputFormat = bsd; | |||
2046 | if (POSIXFormat) | |||
2047 | OutputFormat = posix; | |||
2048 | if (DarwinFormat) | |||
2049 | OutputFormat = darwin; | |||
2050 | ||||
2051 | // The relative order of these is important. If you pass --size-sort it should | |||
2052 | // only print out the size. However, if you pass -S --size-sort, it should | |||
2053 | // print out both the size and address. | |||
2054 | if (SizeSort && !PrintSize) | |||
2055 | PrintAddress = false; | |||
2056 | if (OutputFormat == sysv || SizeSort) | |||
2057 | PrintSize = true; | |||
2058 | if (InputFilenames.empty()) | |||
2059 | InputFilenames.push_back("a.out"); | |||
2060 | if (InputFilenames.size() > 1) | |||
2061 | MultipleFiles = true; | |||
2062 | ||||
2063 | for (unsigned i = 0; i < ArchFlags.size(); ++i) { | |||
2064 | if (ArchFlags[i] == "all") { | |||
2065 | ArchAll = true; | |||
2066 | } else { | |||
2067 | if (!MachOObjectFile::isValidArch(ArchFlags[i])) | |||
2068 | error("Unknown architecture named '" + ArchFlags[i] + "'", | |||
2069 | "for the -arch option"); | |||
2070 | } | |||
2071 | } | |||
2072 | ||||
2073 | if (SegSect.size() != 0 && SegSect.size() != 2) | |||
2074 | error("bad number of arguments (must be two arguments)", | |||
2075 | "for the -s option"); | |||
2076 | ||||
2077 | if (NoDyldInfo && (AddDyldInfo || DyldInfoOnly)) | |||
2078 | error("-no-dyldinfo can't be used with -add-dyldinfo or -dyldinfo-only"); | |||
2079 | ||||
2080 | llvm::for_each(InputFilenames, dumpSymbolNamesFromFile); | |||
2081 | ||||
2082 | if (HadError) | |||
2083 | return 1; | |||
2084 | } |
1 | //===- llvm/Support/Error.h - Recoverable error handling --------*- C++ -*-===// | |||
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 | // | |||
10 | // This file defines an API used to report recoverable errors. | |||
11 | // | |||
12 | //===----------------------------------------------------------------------===// | |||
13 | ||||
14 | #ifndef LLVM_SUPPORT_ERROR_H | |||
15 | #define LLVM_SUPPORT_ERROR_H | |||
16 | ||||
17 | #include "llvm-c/Error.h" | |||
18 | #include "llvm/ADT/STLExtras.h" | |||
19 | #include "llvm/ADT/SmallVector.h" | |||
20 | #include "llvm/ADT/StringExtras.h" | |||
21 | #include "llvm/ADT/Twine.h" | |||
22 | #include "llvm/Config/abi-breaking.h" | |||
23 | #include "llvm/Support/AlignOf.h" | |||
24 | #include "llvm/Support/Compiler.h" | |||
25 | #include "llvm/Support/Debug.h" | |||
26 | #include "llvm/Support/ErrorHandling.h" | |||
27 | #include "llvm/Support/ErrorOr.h" | |||
28 | #include "llvm/Support/Format.h" | |||
29 | #include "llvm/Support/raw_ostream.h" | |||
30 | #include <algorithm> | |||
31 | #include <cassert> | |||
32 | #include <cstdint> | |||
33 | #include <cstdlib> | |||
34 | #include <functional> | |||
35 | #include <memory> | |||
36 | #include <new> | |||
37 | #include <string> | |||
38 | #include <system_error> | |||
39 | #include <type_traits> | |||
40 | #include <utility> | |||
41 | #include <vector> | |||
42 | ||||
43 | namespace llvm { | |||
44 | ||||
45 | class ErrorSuccess; | |||
46 | ||||
47 | /// Base class for error info classes. Do not extend this directly: Extend | |||
48 | /// the ErrorInfo template subclass instead. | |||
49 | class ErrorInfoBase { | |||
50 | public: | |||
51 | virtual ~ErrorInfoBase() = default; | |||
52 | ||||
53 | /// Print an error message to an output stream. | |||
54 | virtual void log(raw_ostream &OS) const = 0; | |||
55 | ||||
56 | /// Return the error message as a string. | |||
57 | virtual std::string message() const { | |||
58 | std::string Msg; | |||
59 | raw_string_ostream OS(Msg); | |||
60 | log(OS); | |||
61 | return OS.str(); | |||
62 | } | |||
63 | ||||
64 | /// Convert this error to a std::error_code. | |||
65 | /// | |||
66 | /// This is a temporary crutch to enable interaction with code still | |||
67 | /// using std::error_code. It will be removed in the future. | |||
68 | virtual std::error_code convertToErrorCode() const = 0; | |||
69 | ||||
70 | // Returns the class ID for this type. | |||
71 | static const void *classID() { return &ID; } | |||
72 | ||||
73 | // Returns the class ID for the dynamic type of this ErrorInfoBase instance. | |||
74 | virtual const void *dynamicClassID() const = 0; | |||
75 | ||||
76 | // Check whether this instance is a subclass of the class identified by | |||
77 | // ClassID. | |||
78 | virtual bool isA(const void *const ClassID) const { | |||
79 | return ClassID == classID(); | |||
80 | } | |||
81 | ||||
82 | // Check whether this instance is a subclass of ErrorInfoT. | |||
83 | template <typename ErrorInfoT> bool isA() const { | |||
84 | return isA(ErrorInfoT::classID()); | |||
85 | } | |||
86 | ||||
87 | private: | |||
88 | virtual void anchor(); | |||
89 | ||||
90 | static char ID; | |||
91 | }; | |||
92 | ||||
93 | /// Lightweight error class with error context and mandatory checking. | |||
94 | /// | |||
95 | /// Instances of this class wrap a ErrorInfoBase pointer. Failure states | |||
96 | /// are represented by setting the pointer to a ErrorInfoBase subclass | |||
97 | /// instance containing information describing the failure. Success is | |||
98 | /// represented by a null pointer value. | |||
99 | /// | |||
100 | /// Instances of Error also contains a 'Checked' flag, which must be set | |||
101 | /// before the destructor is called, otherwise the destructor will trigger a | |||
102 | /// runtime error. This enforces at runtime the requirement that all Error | |||
103 | /// instances be checked or returned to the caller. | |||
104 | /// | |||
105 | /// There are two ways to set the checked flag, depending on what state the | |||
106 | /// Error instance is in. For Error instances indicating success, it | |||
107 | /// is sufficient to invoke the boolean conversion operator. E.g.: | |||
108 | /// | |||
109 | /// @code{.cpp} | |||
110 | /// Error foo(<...>); | |||
111 | /// | |||
112 | /// if (auto E = foo(<...>)) | |||
113 | /// return E; // <- Return E if it is in the error state. | |||
114 | /// // We have verified that E was in the success state. It can now be safely | |||
115 | /// // destroyed. | |||
116 | /// @endcode | |||
117 | /// | |||
118 | /// A success value *can not* be dropped. For example, just calling 'foo(<...>)' | |||
119 | /// without testing the return value will raise a runtime error, even if foo | |||
120 | /// returns success. | |||
121 | /// | |||
122 | /// For Error instances representing failure, you must use either the | |||
123 | /// handleErrors or handleAllErrors function with a typed handler. E.g.: | |||
124 | /// | |||
125 | /// @code{.cpp} | |||
126 | /// class MyErrorInfo : public ErrorInfo<MyErrorInfo> { | |||
127 | /// // Custom error info. | |||
128 | /// }; | |||
129 | /// | |||
130 | /// Error foo(<...>) { return make_error<MyErrorInfo>(...); } | |||
131 | /// | |||
132 | /// auto E = foo(<...>); // <- foo returns failure with MyErrorInfo. | |||
133 | /// auto NewE = | |||
134 | /// handleErrors(E, | |||
135 | /// [](const MyErrorInfo &M) { | |||
136 | /// // Deal with the error. | |||
137 | /// }, | |||
138 | /// [](std::unique_ptr<OtherError> M) -> Error { | |||
139 | /// if (canHandle(*M)) { | |||
140 | /// // handle error. | |||
141 | /// return Error::success(); | |||
142 | /// } | |||
143 | /// // Couldn't handle this error instance. Pass it up the stack. | |||
144 | /// return Error(std::move(M)); | |||
145 | /// ); | |||
146 | /// // Note - we must check or return NewE in case any of the handlers | |||
147 | /// // returned a new error. | |||
148 | /// @endcode | |||
149 | /// | |||
150 | /// The handleAllErrors function is identical to handleErrors, except | |||
151 | /// that it has a void return type, and requires all errors to be handled and | |||
152 | /// no new errors be returned. It prevents errors (assuming they can all be | |||
153 | /// handled) from having to be bubbled all the way to the top-level. | |||
154 | /// | |||
155 | /// *All* Error instances must be checked before destruction, even if | |||
156 | /// they're moved-assigned or constructed from Success values that have already | |||
157 | /// been checked. This enforces checking through all levels of the call stack. | |||
158 | class LLVM_NODISCARD[[clang::warn_unused_result]] Error { | |||
159 | // Both ErrorList and FileError need to be able to yank ErrorInfoBase | |||
160 | // pointers out of this class to add to the error list. | |||
161 | friend class ErrorList; | |||
162 | friend class FileError; | |||
163 | ||||
164 | // handleErrors needs to be able to set the Checked flag. | |||
165 | template <typename... HandlerTs> | |||
166 | friend Error handleErrors(Error E, HandlerTs &&... Handlers); | |||
167 | ||||
168 | // Expected<T> needs to be able to steal the payload when constructed from an | |||
169 | // error. | |||
170 | template <typename T> friend class Expected; | |||
171 | ||||
172 | // wrap needs to be able to steal the payload. | |||
173 | friend LLVMErrorRef wrap(Error); | |||
174 | ||||
175 | protected: | |||
176 | /// Create a success value. Prefer using 'Error::success()' for readability | |||
177 | Error() { | |||
178 | setPtr(nullptr); | |||
179 | setChecked(false); | |||
180 | } | |||
181 | ||||
182 | public: | |||
183 | /// Create a success value. | |||
184 | static ErrorSuccess success(); | |||
185 | ||||
186 | // Errors are not copy-constructable. | |||
187 | Error(const Error &Other) = delete; | |||
188 | ||||
189 | /// Move-construct an error value. The newly constructed error is considered | |||
190 | /// unchecked, even if the source error had been checked. The original error | |||
191 | /// becomes a checked Success value, regardless of its original state. | |||
192 | Error(Error &&Other) { | |||
193 | setChecked(true); | |||
194 | *this = std::move(Other); | |||
195 | } | |||
196 | ||||
197 | /// Create an error value. Prefer using the 'make_error' function, but | |||
198 | /// this constructor can be useful when "re-throwing" errors from handlers. | |||
199 | Error(std::unique_ptr<ErrorInfoBase> Payload) { | |||
200 | setPtr(Payload.release()); | |||
201 | setChecked(false); | |||
| ||||
202 | } | |||
203 | ||||
204 | // Errors are not copy-assignable. | |||
205 | Error &operator=(const Error &Other) = delete; | |||
206 | ||||
207 | /// Move-assign an error value. The current error must represent success, you | |||
208 | /// you cannot overwrite an unhandled error. The current error is then | |||
209 | /// considered unchecked. The source error becomes a checked success value, | |||
210 | /// regardless of its original state. | |||
211 | Error &operator=(Error &&Other) { | |||
212 | // Don't allow overwriting of unchecked values. | |||
213 | assertIsChecked(); | |||
214 | setPtr(Other.getPtr()); | |||
215 | ||||
216 | // This Error is unchecked, even if the source error was checked. | |||
217 | setChecked(false); | |||
218 | ||||
219 | // Null out Other's payload and set its checked bit. | |||
220 | Other.setPtr(nullptr); | |||
221 | Other.setChecked(true); | |||
222 | ||||
223 | return *this; | |||
224 | } | |||
225 | ||||
226 | /// Destroy a Error. Fails with a call to abort() if the error is | |||
227 | /// unchecked. | |||
228 | ~Error() { | |||
229 | assertIsChecked(); | |||
230 | delete getPtr(); | |||
231 | } | |||
232 | ||||
233 | /// Bool conversion. Returns true if this Error is in a failure state, | |||
234 | /// and false if it is in an accept state. If the error is in a Success state | |||
235 | /// it will be considered checked. | |||
236 | explicit operator bool() { | |||
237 | setChecked(getPtr() == nullptr); | |||
238 | return getPtr() != nullptr; | |||
239 | } | |||
240 | ||||
241 | /// Check whether one error is a subclass of another. | |||
242 | template <typename ErrT> bool isA() const { | |||
243 | return getPtr() && getPtr()->isA(ErrT::classID()); | |||
244 | } | |||
245 | ||||
246 | /// Returns the dynamic class id of this error, or null if this is a success | |||
247 | /// value. | |||
248 | const void* dynamicClassID() const { | |||
249 | if (!getPtr()) | |||
250 | return nullptr; | |||
251 | return getPtr()->dynamicClassID(); | |||
252 | } | |||
253 | ||||
254 | private: | |||
255 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 | |||
256 | // assertIsChecked() happens very frequently, but under normal circumstances | |||
257 | // is supposed to be a no-op. So we want it to be inlined, but having a bunch | |||
258 | // of debug prints can cause the function to be too large for inlining. So | |||
259 | // it's important that we define this function out of line so that it can't be | |||
260 | // inlined. | |||
261 | LLVM_ATTRIBUTE_NORETURN__attribute__((noreturn)) | |||
262 | void fatalUncheckedError() const; | |||
263 | #endif | |||
264 | ||||
265 | void assertIsChecked() { | |||
266 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 | |||
267 | if (LLVM_UNLIKELY(!getChecked() || getPtr())__builtin_expect((bool)(!getChecked() || getPtr()), false)) | |||
268 | fatalUncheckedError(); | |||
269 | #endif | |||
270 | } | |||
271 | ||||
272 | ErrorInfoBase *getPtr() const { | |||
273 | return reinterpret_cast<ErrorInfoBase*>( | |||
274 | reinterpret_cast<uintptr_t>(Payload) & | |||
275 | ~static_cast<uintptr_t>(0x1)); | |||
276 | } | |||
277 | ||||
278 | void setPtr(ErrorInfoBase *EI) { | |||
279 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 | |||
280 | Payload = reinterpret_cast<ErrorInfoBase*>( | |||
281 | (reinterpret_cast<uintptr_t>(EI) & | |||
282 | ~static_cast<uintptr_t>(0x1)) | | |||
283 | (reinterpret_cast<uintptr_t>(Payload) & 0x1)); | |||
284 | #else | |||
285 | Payload = EI; | |||
286 | #endif | |||
287 | } | |||
288 | ||||
289 | bool getChecked() const { | |||
290 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 | |||
291 | return (reinterpret_cast<uintptr_t>(Payload) & 0x1) == 0; | |||
292 | #else | |||
293 | return true; | |||
294 | #endif | |||
295 | } | |||
296 | ||||
297 | void setChecked(bool V) { | |||
298 | Payload = reinterpret_cast<ErrorInfoBase*>( | |||
299 | (reinterpret_cast<uintptr_t>(Payload) & | |||
300 | ~static_cast<uintptr_t>(0x1)) | | |||
301 | (V ? 0 : 1)); | |||
302 | } | |||
303 | ||||
304 | std::unique_ptr<ErrorInfoBase> takePayload() { | |||
305 | std::unique_ptr<ErrorInfoBase> Tmp(getPtr()); | |||
306 | setPtr(nullptr); | |||
307 | setChecked(true); | |||
308 | return Tmp; | |||
309 | } | |||
310 | ||||
311 | friend raw_ostream &operator<<(raw_ostream &OS, const Error &E) { | |||
312 | if (auto P = E.getPtr()) | |||
313 | P->log(OS); | |||
314 | else | |||
315 | OS << "success"; | |||
316 | return OS; | |||
317 | } | |||
318 | ||||
319 | ErrorInfoBase *Payload = nullptr; | |||
320 | }; | |||
321 | ||||
322 | /// Subclass of Error for the sole purpose of identifying the success path in | |||
323 | /// the type system. This allows to catch invalid conversion to Expected<T> at | |||
324 | /// compile time. | |||
325 | class ErrorSuccess final : public Error {}; | |||
326 | ||||
327 | inline ErrorSuccess Error::success() { return ErrorSuccess(); } | |||
328 | ||||
329 | /// Make a Error instance representing failure using the given error info | |||
330 | /// type. | |||
331 | template <typename ErrT, typename... ArgTs> Error make_error(ArgTs &&... Args) { | |||
332 | return Error(llvm::make_unique<ErrT>(std::forward<ArgTs>(Args)...)); | |||
333 | } | |||
334 | ||||
335 | /// Base class for user error types. Users should declare their error types | |||
336 | /// like: | |||
337 | /// | |||
338 | /// class MyError : public ErrorInfo<MyError> { | |||
339 | /// .... | |||
340 | /// }; | |||
341 | /// | |||
342 | /// This class provides an implementation of the ErrorInfoBase::kind | |||
343 | /// method, which is used by the Error RTTI system. | |||
344 | template <typename ThisErrT, typename ParentErrT = ErrorInfoBase> | |||
345 | class ErrorInfo : public ParentErrT { | |||
346 | public: | |||
347 | using ParentErrT::ParentErrT; // inherit constructors | |||
348 | ||||
349 | static const void *classID() { return &ThisErrT::ID; } | |||
350 | ||||
351 | const void *dynamicClassID() const override { return &ThisErrT::ID; } | |||
352 | ||||
353 | bool isA(const void *const ClassID) const override { | |||
354 | return ClassID == classID() || ParentErrT::isA(ClassID); | |||
355 | } | |||
356 | }; | |||
357 | ||||
358 | /// Special ErrorInfo subclass representing a list of ErrorInfos. | |||
359 | /// Instances of this class are constructed by joinError. | |||
360 | class ErrorList final : public ErrorInfo<ErrorList> { | |||
361 | // handleErrors needs to be able to iterate the payload list of an | |||
362 | // ErrorList. | |||
363 | template <typename... HandlerTs> | |||
364 | friend Error handleErrors(Error E, HandlerTs &&... Handlers); | |||
365 | ||||
366 | // joinErrors is implemented in terms of join. | |||
367 | friend Error joinErrors(Error, Error); | |||
368 | ||||
369 | public: | |||
370 | void log(raw_ostream &OS) const override { | |||
371 | OS << "Multiple errors:\n"; | |||
372 | for (auto &ErrPayload : Payloads) { | |||
373 | ErrPayload->log(OS); | |||
374 | OS << "\n"; | |||
375 | } | |||
376 | } | |||
377 | ||||
378 | std::error_code convertToErrorCode() const override; | |||
379 | ||||
380 | // Used by ErrorInfo::classID. | |||
381 | static char ID; | |||
382 | ||||
383 | private: | |||
384 | ErrorList(std::unique_ptr<ErrorInfoBase> Payload1, | |||
385 | std::unique_ptr<ErrorInfoBase> Payload2) { | |||
386 | assert(!Payload1->isA<ErrorList>() && !Payload2->isA<ErrorList>() &&((!Payload1->isA<ErrorList>() && !Payload2-> isA<ErrorList>() && "ErrorList constructor payloads should be singleton errors" ) ? static_cast<void> (0) : __assert_fail ("!Payload1->isA<ErrorList>() && !Payload2->isA<ErrorList>() && \"ErrorList constructor payloads should be singleton errors\"" , "/build/llvm-toolchain-snapshot-8~svn345461/include/llvm/Support/Error.h" , 387, __PRETTY_FUNCTION__)) | |||
387 | "ErrorList constructor payloads should be singleton errors")((!Payload1->isA<ErrorList>() && !Payload2-> isA<ErrorList>() && "ErrorList constructor payloads should be singleton errors" ) ? static_cast<void> (0) : __assert_fail ("!Payload1->isA<ErrorList>() && !Payload2->isA<ErrorList>() && \"ErrorList constructor payloads should be singleton errors\"" , "/build/llvm-toolchain-snapshot-8~svn345461/include/llvm/Support/Error.h" , 387, __PRETTY_FUNCTION__)); | |||
388 | Payloads.push_back(std::move(Payload1)); | |||
389 | Payloads.push_back(std::move(Payload2)); | |||
390 | } | |||
391 | ||||
392 | static Error join(Error E1, Error E2) { | |||
393 | if (!E1) | |||
394 | return E2; | |||
395 | if (!E2) | |||
396 | return E1; | |||
397 | if (E1.isA<ErrorList>()) { | |||
398 | auto &E1List = static_cast<ErrorList &>(*E1.getPtr()); | |||
399 | if (E2.isA<ErrorList>()) { | |||
400 | auto E2Payload = E2.takePayload(); | |||
401 | auto &E2List = static_cast<ErrorList &>(*E2Payload); | |||
402 | for (auto &Payload : E2List.Payloads) | |||
403 | E1List.Payloads.push_back(std::move(Payload)); | |||
404 | } else | |||
405 | E1List.Payloads.push_back(E2.takePayload()); | |||
406 | ||||
407 | return E1; | |||
408 | } | |||
409 | if (E2.isA<ErrorList>()) { | |||
410 | auto &E2List = static_cast<ErrorList &>(*E2.getPtr()); | |||
411 | E2List.Payloads.insert(E2List.Payloads.begin(), E1.takePayload()); | |||
412 | return E2; | |||
413 | } | |||
414 | return Error(std::unique_ptr<ErrorList>( | |||
415 | new ErrorList(E1.takePayload(), E2.takePayload()))); | |||
416 | } | |||
417 | ||||
418 | std::vector<std::unique_ptr<ErrorInfoBase>> Payloads; | |||
419 | }; | |||
420 | ||||
421 | /// Concatenate errors. The resulting Error is unchecked, and contains the | |||
422 | /// ErrorInfo(s), if any, contained in E1, followed by the | |||
423 | /// ErrorInfo(s), if any, contained in E2. | |||
424 | inline Error joinErrors(Error E1, Error E2) { | |||
425 | return ErrorList::join(std::move(E1), std::move(E2)); | |||
426 | } | |||
427 | ||||
428 | /// Tagged union holding either a T or a Error. | |||
429 | /// | |||
430 | /// This class parallels ErrorOr, but replaces error_code with Error. Since | |||
431 | /// Error cannot be copied, this class replaces getError() with | |||
432 | /// takeError(). It also adds an bool errorIsA<ErrT>() method for testing the | |||
433 | /// error class type. | |||
434 | template <class T> class LLVM_NODISCARD[[clang::warn_unused_result]] Expected { | |||
435 | template <class T1> friend class ExpectedAsOutParameter; | |||
436 | template <class OtherT> friend class Expected; | |||
437 | ||||
438 | static const bool isRef = std::is_reference<T>::value; | |||
439 | ||||
440 | using wrap = std::reference_wrapper<typename std::remove_reference<T>::type>; | |||
441 | ||||
442 | using error_type = std::unique_ptr<ErrorInfoBase>; | |||
443 | ||||
444 | public: | |||
445 | using storage_type = typename std::conditional<isRef, wrap, T>::type; | |||
446 | using value_type = T; | |||
447 | ||||
448 | private: | |||
449 | using reference = typename std::remove_reference<T>::type &; | |||
450 | using const_reference = const typename std::remove_reference<T>::type &; | |||
451 | using pointer = typename std::remove_reference<T>::type *; | |||
452 | using const_pointer = const typename std::remove_reference<T>::type *; | |||
453 | ||||
454 | public: | |||
455 | /// Create an Expected<T> error value from the given Error. | |||
456 | Expected(Error Err) | |||
457 | : HasError(true) | |||
458 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 | |||
459 | // Expected is unchecked upon construction in Debug builds. | |||
460 | , Unchecked(true) | |||
461 | #endif | |||
462 | { | |||
463 | assert(Err && "Cannot create Expected<T> from Error success value.")((Err && "Cannot create Expected<T> from Error success value." ) ? static_cast<void> (0) : __assert_fail ("Err && \"Cannot create Expected<T> from Error success value.\"" , "/build/llvm-toolchain-snapshot-8~svn345461/include/llvm/Support/Error.h" , 463, __PRETTY_FUNCTION__)); | |||
464 | new (getErrorStorage()) error_type(Err.takePayload()); | |||
465 | } | |||
466 | ||||
467 | /// Forbid to convert from Error::success() implicitly, this avoids having | |||
468 | /// Expected<T> foo() { return Error::success(); } which compiles otherwise | |||
469 | /// but triggers the assertion above. | |||
470 | Expected(ErrorSuccess) = delete; | |||
471 | ||||
472 | /// Create an Expected<T> success value from the given OtherT value, which | |||
473 | /// must be convertible to T. | |||
474 | template <typename OtherT> | |||
475 | Expected(OtherT &&Val, | |||
476 | typename std::enable_if<std::is_convertible<OtherT, T>::value>::type | |||
477 | * = nullptr) | |||
478 | : HasError(false) | |||
479 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 | |||
480 | // Expected is unchecked upon construction in Debug builds. | |||
481 | , Unchecked(true) | |||
482 | #endif | |||
483 | { | |||
484 | new (getStorage()) storage_type(std::forward<OtherT>(Val)); | |||
485 | } | |||
486 | ||||
487 | /// Move construct an Expected<T> value. | |||
488 | Expected(Expected &&Other) { moveConstruct(std::move(Other)); } | |||
489 | ||||
490 | /// Move construct an Expected<T> value from an Expected<OtherT>, where OtherT | |||
491 | /// must be convertible to T. | |||
492 | template <class OtherT> | |||
493 | Expected(Expected<OtherT> &&Other, | |||
494 | typename std::enable_if<std::is_convertible<OtherT, T>::value>::type | |||
495 | * = nullptr) { | |||
496 | moveConstruct(std::move(Other)); | |||
497 | } | |||
498 | ||||
499 | /// Move construct an Expected<T> value from an Expected<OtherT>, where OtherT | |||
500 | /// isn't convertible to T. | |||
501 | template <class OtherT> | |||
502 | explicit Expected( | |||
503 | Expected<OtherT> &&Other, | |||
504 | typename std::enable_if<!std::is_convertible<OtherT, T>::value>::type * = | |||
505 | nullptr) { | |||
506 | moveConstruct(std::move(Other)); | |||
507 | } | |||
508 | ||||
509 | /// Move-assign from another Expected<T>. | |||
510 | Expected &operator=(Expected &&Other) { | |||
511 | moveAssign(std::move(Other)); | |||
512 | return *this; | |||
513 | } | |||
514 | ||||
515 | /// Destroy an Expected<T>. | |||
516 | ~Expected() { | |||
517 | assertIsChecked(); | |||
518 | if (!HasError) | |||
519 | getStorage()->~storage_type(); | |||
520 | else | |||
521 | getErrorStorage()->~error_type(); | |||
522 | } | |||
523 | ||||
524 | /// Return false if there is an error. | |||
525 | explicit operator bool() { | |||
526 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 | |||
527 | Unchecked = HasError; | |||
528 | #endif | |||
529 | return !HasError; | |||
530 | } | |||
531 | ||||
532 | /// Returns a reference to the stored T value. | |||
533 | reference get() { | |||
534 | assertIsChecked(); | |||
535 | return *getStorage(); | |||
536 | } | |||
537 | ||||
538 | /// Returns a const reference to the stored T value. | |||
539 | const_reference get() const { | |||
540 | assertIsChecked(); | |||
541 | return const_cast<Expected<T> *>(this)->get(); | |||
542 | } | |||
543 | ||||
544 | /// Check that this Expected<T> is an error of type ErrT. | |||
545 | template <typename ErrT> bool errorIsA() const { | |||
546 | return HasError && (*getErrorStorage())->template isA<ErrT>(); | |||
547 | } | |||
548 | ||||
549 | /// Take ownership of the stored error. | |||
550 | /// After calling this the Expected<T> is in an indeterminate state that can | |||
551 | /// only be safely destructed. No further calls (beside the destructor) should | |||
552 | /// be made on the Expected<T> vaule. | |||
553 | Error takeError() { | |||
554 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 | |||
555 | Unchecked = false; | |||
556 | #endif | |||
557 | return HasError ? Error(std::move(*getErrorStorage())) : Error::success(); | |||
558 | } | |||
559 | ||||
560 | /// Returns a pointer to the stored T value. | |||
561 | pointer operator->() { | |||
562 | assertIsChecked(); | |||
563 | return toPointer(getStorage()); | |||
564 | } | |||
565 | ||||
566 | /// Returns a const pointer to the stored T value. | |||
567 | const_pointer operator->() const { | |||
568 | assertIsChecked(); | |||
569 | return toPointer(getStorage()); | |||
570 | } | |||
571 | ||||
572 | /// Returns a reference to the stored T value. | |||
573 | reference operator*() { | |||
574 | assertIsChecked(); | |||
575 | return *getStorage(); | |||
576 | } | |||
577 | ||||
578 | /// Returns a const reference to the stored T value. | |||
579 | const_reference operator*() const { | |||
580 | assertIsChecked(); | |||
581 | return *getStorage(); | |||
582 | } | |||
583 | ||||
584 | private: | |||
585 | template <class T1> | |||
586 | static bool compareThisIfSameType(const T1 &a, const T1 &b) { | |||
587 | return &a == &b; | |||
588 | } | |||
589 | ||||
590 | template <class T1, class T2> | |||
591 | static bool compareThisIfSameType(const T1 &a, const T2 &b) { | |||
592 | return false; | |||
593 | } | |||
594 | ||||
595 | template <class OtherT> void moveConstruct(Expected<OtherT> &&Other) { | |||
596 | HasError = Other.HasError; | |||
597 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 | |||
598 | Unchecked = true; | |||
599 | Other.Unchecked = false; | |||
600 | #endif | |||
601 | ||||
602 | if (!HasError) | |||
603 | new (getStorage()) storage_type(std::move(*Other.getStorage())); | |||
604 | else | |||
605 | new (getErrorStorage()) error_type(std::move(*Other.getErrorStorage())); | |||
606 | } | |||
607 | ||||
608 | template <class OtherT> void moveAssign(Expected<OtherT> &&Other) { | |||
609 | assertIsChecked(); | |||
610 | ||||
611 | if (compareThisIfSameType(*this, Other)) | |||
612 | return; | |||
613 | ||||
614 | this->~Expected(); | |||
615 | new (this) Expected(std::move(Other)); | |||
616 | } | |||
617 | ||||
618 | pointer toPointer(pointer Val) { return Val; } | |||
619 | ||||
620 | const_pointer toPointer(const_pointer Val) const { return Val; } | |||
621 | ||||
622 | pointer toPointer(wrap *Val) { return &Val->get(); } | |||
623 | ||||
624 | const_pointer toPointer(const wrap *Val) const { return &Val->get(); } | |||
625 | ||||
626 | storage_type *getStorage() { | |||
627 | assert(!HasError && "Cannot get value when an error exists!")((!HasError && "Cannot get value when an error exists!" ) ? static_cast<void> (0) : __assert_fail ("!HasError && \"Cannot get value when an error exists!\"" , "/build/llvm-toolchain-snapshot-8~svn345461/include/llvm/Support/Error.h" , 627, __PRETTY_FUNCTION__)); | |||
628 | return reinterpret_cast<storage_type *>(TStorage.buffer); | |||
629 | } | |||
630 | ||||
631 | const storage_type *getStorage() const { | |||
632 | assert(!HasError && "Cannot get value when an error exists!")((!HasError && "Cannot get value when an error exists!" ) ? static_cast<void> (0) : __assert_fail ("!HasError && \"Cannot get value when an error exists!\"" , "/build/llvm-toolchain-snapshot-8~svn345461/include/llvm/Support/Error.h" , 632, __PRETTY_FUNCTION__)); | |||
633 | return reinterpret_cast<const storage_type *>(TStorage.buffer); | |||
634 | } | |||
635 | ||||
636 | error_type *getErrorStorage() { | |||
637 | assert(HasError && "Cannot get error when a value exists!")((HasError && "Cannot get error when a value exists!" ) ? static_cast<void> (0) : __assert_fail ("HasError && \"Cannot get error when a value exists!\"" , "/build/llvm-toolchain-snapshot-8~svn345461/include/llvm/Support/Error.h" , 637, __PRETTY_FUNCTION__)); | |||
638 | return reinterpret_cast<error_type *>(ErrorStorage.buffer); | |||
639 | } | |||
640 | ||||
641 | const error_type *getErrorStorage() const { | |||
642 | assert(HasError && "Cannot get error when a value exists!")((HasError && "Cannot get error when a value exists!" ) ? static_cast<void> (0) : __assert_fail ("HasError && \"Cannot get error when a value exists!\"" , "/build/llvm-toolchain-snapshot-8~svn345461/include/llvm/Support/Error.h" , 642, __PRETTY_FUNCTION__)); | |||
643 | return reinterpret_cast<const error_type *>(ErrorStorage.buffer); | |||
644 | } | |||
645 | ||||
646 | // Used by ExpectedAsOutParameter to reset the checked flag. | |||
647 | void setUnchecked() { | |||
648 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 | |||
649 | Unchecked = true; | |||
650 | #endif | |||
651 | } | |||
652 | ||||
653 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 | |||
654 | LLVM_ATTRIBUTE_NORETURN__attribute__((noreturn)) | |||
655 | LLVM_ATTRIBUTE_NOINLINE__attribute__((noinline)) | |||
656 | void fatalUncheckedExpected() const { | |||
657 | dbgs() << "Expected<T> must be checked before access or destruction.\n"; | |||
658 | if (HasError) { | |||
659 | dbgs() << "Unchecked Expected<T> contained error:\n"; | |||
660 | (*getErrorStorage())->log(dbgs()); | |||
661 | } else | |||
662 | dbgs() << "Expected<T> value was in success state. (Note: Expected<T> " | |||
663 | "values in success mode must still be checked prior to being " | |||
664 | "destroyed).\n"; | |||
665 | abort(); | |||
666 | } | |||
667 | #endif | |||
668 | ||||
669 | void assertIsChecked() { | |||
670 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 | |||
671 | if (LLVM_UNLIKELY(Unchecked)__builtin_expect((bool)(Unchecked), false)) | |||
672 | fatalUncheckedExpected(); | |||
673 | #endif | |||
674 | } | |||
675 | ||||
676 | union { | |||
677 | AlignedCharArrayUnion<storage_type> TStorage; | |||
678 | AlignedCharArrayUnion<error_type> ErrorStorage; | |||
679 | }; | |||
680 | bool HasError : 1; | |||
681 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 | |||
682 | bool Unchecked : 1; | |||
683 | #endif | |||
684 | }; | |||
685 | ||||
686 | /// Report a serious error, calling any installed error handler. See | |||
687 | /// ErrorHandling.h. | |||
688 | LLVM_ATTRIBUTE_NORETURN__attribute__((noreturn)) void report_fatal_error(Error Err, | |||
689 | bool gen_crash_diag = true); | |||
690 | ||||
691 | /// Report a fatal error if Err is a failure value. | |||
692 | /// | |||
693 | /// This function can be used to wrap calls to fallible functions ONLY when it | |||
694 | /// is known that the Error will always be a success value. E.g. | |||
695 | /// | |||
696 | /// @code{.cpp} | |||
697 | /// // foo only attempts the fallible operation if DoFallibleOperation is | |||
698 | /// // true. If DoFallibleOperation is false then foo always returns | |||
699 | /// // Error::success(). | |||
700 | /// Error foo(bool DoFallibleOperation); | |||
701 | /// | |||
702 | /// cantFail(foo(false)); | |||
703 | /// @endcode | |||
704 | inline void cantFail(Error Err, const char *Msg = nullptr) { | |||
705 | if (Err) { | |||
706 | if (!Msg) | |||
707 | Msg = "Failure value returned from cantFail wrapped call"; | |||
708 | llvm_unreachable(Msg)::llvm::llvm_unreachable_internal(Msg, "/build/llvm-toolchain-snapshot-8~svn345461/include/llvm/Support/Error.h" , 708); | |||
709 | } | |||
710 | } | |||
711 | ||||
712 | /// Report a fatal error if ValOrErr is a failure value, otherwise unwraps and | |||
713 | /// returns the contained value. | |||
714 | /// | |||
715 | /// This function can be used to wrap calls to fallible functions ONLY when it | |||
716 | /// is known that the Error will always be a success value. E.g. | |||
717 | /// | |||
718 | /// @code{.cpp} | |||
719 | /// // foo only attempts the fallible operation if DoFallibleOperation is | |||
720 | /// // true. If DoFallibleOperation is false then foo always returns an int. | |||
721 | /// Expected<int> foo(bool DoFallibleOperation); | |||
722 | /// | |||
723 | /// int X = cantFail(foo(false)); | |||
724 | /// @endcode | |||
725 | template <typename T> | |||
726 | T cantFail(Expected<T> ValOrErr, const char *Msg = nullptr) { | |||
727 | if (ValOrErr) | |||
728 | return std::move(*ValOrErr); | |||
729 | else { | |||
730 | if (!Msg) | |||
731 | Msg = "Failure value returned from cantFail wrapped call"; | |||
732 | llvm_unreachable(Msg)::llvm::llvm_unreachable_internal(Msg, "/build/llvm-toolchain-snapshot-8~svn345461/include/llvm/Support/Error.h" , 732); | |||
733 | } | |||
734 | } | |||
735 | ||||
736 | /// Report a fatal error if ValOrErr is a failure value, otherwise unwraps and | |||
737 | /// returns the contained reference. | |||
738 | /// | |||
739 | /// This function can be used to wrap calls to fallible functions ONLY when it | |||
740 | /// is known that the Error will always be a success value. E.g. | |||
741 | /// | |||
742 | /// @code{.cpp} | |||
743 | /// // foo only attempts the fallible operation if DoFallibleOperation is | |||
744 | /// // true. If DoFallibleOperation is false then foo always returns a Bar&. | |||
745 | /// Expected<Bar&> foo(bool DoFallibleOperation); | |||
746 | /// | |||
747 | /// Bar &X = cantFail(foo(false)); | |||
748 | /// @endcode | |||
749 | template <typename T> | |||
750 | T& cantFail(Expected<T&> ValOrErr, const char *Msg = nullptr) { | |||
751 | if (ValOrErr) | |||
752 | return *ValOrErr; | |||
753 | else { | |||
754 | if (!Msg) | |||
755 | Msg = "Failure value returned from cantFail wrapped call"; | |||
756 | llvm_unreachable(Msg)::llvm::llvm_unreachable_internal(Msg, "/build/llvm-toolchain-snapshot-8~svn345461/include/llvm/Support/Error.h" , 756); | |||
757 | } | |||
758 | } | |||
759 | ||||
760 | /// Helper for testing applicability of, and applying, handlers for | |||
761 | /// ErrorInfo types. | |||
762 | template <typename HandlerT> | |||
763 | class ErrorHandlerTraits | |||
764 | : public ErrorHandlerTraits<decltype( | |||
765 | &std::remove_reference<HandlerT>::type::operator())> {}; | |||
766 | ||||
767 | // Specialization functions of the form 'Error (const ErrT&)'. | |||
768 | template <typename ErrT> class ErrorHandlerTraits<Error (&)(ErrT &)> { | |||
769 | public: | |||
770 | static bool appliesTo(const ErrorInfoBase &E) { | |||
771 | return E.template isA<ErrT>(); | |||
772 | } | |||
773 | ||||
774 | template <typename HandlerT> | |||
775 | static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) { | |||
776 | assert(appliesTo(*E) && "Applying incorrect handler")((appliesTo(*E) && "Applying incorrect handler") ? static_cast <void> (0) : __assert_fail ("appliesTo(*E) && \"Applying incorrect handler\"" , "/build/llvm-toolchain-snapshot-8~svn345461/include/llvm/Support/Error.h" , 776, __PRETTY_FUNCTION__)); | |||
777 | return H(static_cast<ErrT &>(*E)); | |||
778 | } | |||
779 | }; | |||
780 | ||||
781 | // Specialization functions of the form 'void (const ErrT&)'. | |||
782 | template <typename ErrT> class ErrorHandlerTraits<void (&)(ErrT &)> { | |||
783 | public: | |||
784 | static bool appliesTo(const ErrorInfoBase &E) { | |||
785 | return E.template isA<ErrT>(); | |||
786 | } | |||
787 | ||||
788 | template <typename HandlerT> | |||
789 | static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) { | |||
790 | assert(appliesTo(*E) && "Applying incorrect handler")((appliesTo(*E) && "Applying incorrect handler") ? static_cast <void> (0) : __assert_fail ("appliesTo(*E) && \"Applying incorrect handler\"" , "/build/llvm-toolchain-snapshot-8~svn345461/include/llvm/Support/Error.h" , 790, __PRETTY_FUNCTION__)); | |||
791 | H(static_cast<ErrT &>(*E)); | |||
792 | return Error::success(); | |||
793 | } | |||
794 | }; | |||
795 | ||||
796 | /// Specialization for functions of the form 'Error (std::unique_ptr<ErrT>)'. | |||
797 | template <typename ErrT> | |||
798 | class ErrorHandlerTraits<Error (&)(std::unique_ptr<ErrT>)> { | |||
799 | public: | |||
800 | static bool appliesTo(const ErrorInfoBase &E) { | |||
801 | return E.template isA<ErrT>(); | |||
802 | } | |||
803 | ||||
804 | template <typename HandlerT> | |||
805 | static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) { | |||
806 | assert(appliesTo(*E) && "Applying incorrect handler")((appliesTo(*E) && "Applying incorrect handler") ? static_cast <void> (0) : __assert_fail ("appliesTo(*E) && \"Applying incorrect handler\"" , "/build/llvm-toolchain-snapshot-8~svn345461/include/llvm/Support/Error.h" , 806, __PRETTY_FUNCTION__)); | |||
807 | std::unique_ptr<ErrT> SubE(static_cast<ErrT *>(E.release())); | |||
808 | return H(std::move(SubE)); | |||
809 | } | |||
810 | }; | |||
811 | ||||
812 | /// Specialization for functions of the form 'void (std::unique_ptr<ErrT>)'. | |||
813 | template <typename ErrT> | |||
814 | class ErrorHandlerTraits<void (&)(std::unique_ptr<ErrT>)> { | |||
815 | public: | |||
816 | static bool appliesTo(const ErrorInfoBase &E) { | |||
817 | return E.template isA<ErrT>(); | |||
818 | } | |||
819 | ||||
820 | template <typename HandlerT> | |||
821 | static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) { | |||
822 | assert(appliesTo(*E) && "Applying incorrect handler")((appliesTo(*E) && "Applying incorrect handler") ? static_cast <void> (0) : __assert_fail ("appliesTo(*E) && \"Applying incorrect handler\"" , "/build/llvm-toolchain-snapshot-8~svn345461/include/llvm/Support/Error.h" , 822, __PRETTY_FUNCTION__)); | |||
823 | std::unique_ptr<ErrT> SubE(static_cast<ErrT *>(E.release())); | |||
824 | H(std::move(SubE)); | |||
825 | return Error::success(); | |||
826 | } | |||
827 | }; | |||
828 | ||||
829 | // Specialization for member functions of the form 'RetT (const ErrT&)'. | |||
830 | template <typename C, typename RetT, typename ErrT> | |||
831 | class ErrorHandlerTraits<RetT (C::*)(ErrT &)> | |||
832 | : public ErrorHandlerTraits<RetT (&)(ErrT &)> {}; | |||
833 | ||||
834 | // Specialization for member functions of the form 'RetT (const ErrT&) const'. | |||
835 | template <typename C, typename RetT, typename ErrT> | |||
836 | class ErrorHandlerTraits<RetT (C::*)(ErrT &) const> | |||
837 | : public ErrorHandlerTraits<RetT (&)(ErrT &)> {}; | |||
838 | ||||
839 | // Specialization for member functions of the form 'RetT (const ErrT&)'. | |||
840 | template <typename C, typename RetT, typename ErrT> | |||
841 | class ErrorHandlerTraits<RetT (C::*)(const ErrT &)> | |||
842 | : public ErrorHandlerTraits<RetT (&)(ErrT &)> {}; | |||
843 | ||||
844 | // Specialization for member functions of the form 'RetT (const ErrT&) const'. | |||
845 | template <typename C, typename RetT, typename ErrT> | |||
846 | class ErrorHandlerTraits<RetT (C::*)(const ErrT &) const> | |||
847 | : public ErrorHandlerTraits<RetT (&)(ErrT &)> {}; | |||
848 | ||||
849 | /// Specialization for member functions of the form | |||
850 | /// 'RetT (std::unique_ptr<ErrT>)'. | |||
851 | template <typename C, typename RetT, typename ErrT> | |||
852 | class ErrorHandlerTraits<RetT (C::*)(std::unique_ptr<ErrT>)> | |||
853 | : public ErrorHandlerTraits<RetT (&)(std::unique_ptr<ErrT>)> {}; | |||
854 | ||||
855 | /// Specialization for member functions of the form | |||
856 | /// 'RetT (std::unique_ptr<ErrT>) const'. | |||
857 | template <typename C, typename RetT, typename ErrT> | |||
858 | class ErrorHandlerTraits<RetT (C::*)(std::unique_ptr<ErrT>) const> | |||
859 | : public ErrorHandlerTraits<RetT (&)(std::unique_ptr<ErrT>)> {}; | |||
860 | ||||
861 | inline Error handleErrorImpl(std::unique_ptr<ErrorInfoBase> Payload) { | |||
862 | return Error(std::move(Payload)); | |||
863 | } | |||
864 | ||||
865 | template <typename HandlerT, typename... HandlerTs> | |||
866 | Error handleErrorImpl(std::unique_ptr<ErrorInfoBase> Payload, | |||
867 | HandlerT &&Handler, HandlerTs &&... Handlers) { | |||
868 | if (ErrorHandlerTraits<HandlerT>::appliesTo(*Payload)) | |||
869 | return ErrorHandlerTraits<HandlerT>::apply(std::forward<HandlerT>(Handler), | |||
870 | std::move(Payload)); | |||
871 | return handleErrorImpl(std::move(Payload), | |||
872 | std::forward<HandlerTs>(Handlers)...); | |||
873 | } | |||
874 | ||||
875 | /// Pass the ErrorInfo(s) contained in E to their respective handlers. Any | |||
876 | /// unhandled errors (or Errors returned by handlers) are re-concatenated and | |||
877 | /// returned. | |||
878 | /// Because this function returns an error, its result must also be checked | |||
879 | /// or returned. If you intend to handle all errors use handleAllErrors | |||
880 | /// (which returns void, and will abort() on unhandled errors) instead. | |||
881 | template <typename... HandlerTs> | |||
882 | Error handleErrors(Error E, HandlerTs &&... Hs) { | |||
883 | if (!E) | |||
884 | return Error::success(); | |||
885 | ||||
886 | std::unique_ptr<ErrorInfoBase> Payload = E.takePayload(); | |||
887 | ||||
888 | if (Payload->isA<ErrorList>()) { | |||
889 | ErrorList &List = static_cast<ErrorList &>(*Payload); | |||
890 | Error R; | |||
891 | for (auto &P : List.Payloads) | |||
892 | R = ErrorList::join( | |||
893 | std::move(R), | |||
894 | handleErrorImpl(std::move(P), std::forward<HandlerTs>(Hs)...)); | |||
895 | return R; | |||
896 | } | |||
897 | ||||
898 | return handleErrorImpl(std::move(Payload), std::forward<HandlerTs>(Hs)...); | |||
899 | } | |||
900 | ||||
901 | /// Behaves the same as handleErrors, except that by contract all errors | |||
902 | /// *must* be handled by the given handlers (i.e. there must be no remaining | |||
903 | /// errors after running the handlers, or llvm_unreachable is called). | |||
904 | template <typename... HandlerTs> | |||
905 | void handleAllErrors(Error E, HandlerTs &&... Handlers) { | |||
906 | cantFail(handleErrors(std::move(E), std::forward<HandlerTs>(Handlers)...)); | |||
907 | } | |||
908 | ||||
909 | /// Check that E is a non-error, then drop it. | |||
910 | /// If E is an error, llvm_unreachable will be called. | |||
911 | inline void handleAllErrors(Error E) { | |||
912 | cantFail(std::move(E)); | |||
913 | } | |||
914 | ||||
915 | /// Handle any errors (if present) in an Expected<T>, then try a recovery path. | |||
916 | /// | |||
917 | /// If the incoming value is a success value it is returned unmodified. If it | |||
918 | /// is a failure value then it the contained error is passed to handleErrors. | |||
919 | /// If handleErrors is able to handle the error then the RecoveryPath functor | |||
920 | /// is called to supply the final result. If handleErrors is not able to | |||
921 | /// handle all errors then the unhandled errors are returned. | |||
922 | /// | |||
923 | /// This utility enables the follow pattern: | |||
924 | /// | |||
925 | /// @code{.cpp} | |||
926 | /// enum FooStrategy { Aggressive, Conservative }; | |||
927 | /// Expected<Foo> foo(FooStrategy S); | |||
928 | /// | |||
929 | /// auto ResultOrErr = | |||
930 | /// handleExpected( | |||
931 | /// foo(Aggressive), | |||
932 | /// []() { return foo(Conservative); }, | |||
933 | /// [](AggressiveStrategyError&) { | |||
934 | /// // Implicitly conusme this - we'll recover by using a conservative | |||
935 | /// // strategy. | |||
936 | /// }); | |||
937 | /// | |||
938 | /// @endcode | |||
939 | template <typename T, typename RecoveryFtor, typename... HandlerTs> | |||
940 | Expected<T> handleExpected(Expected<T> ValOrErr, RecoveryFtor &&RecoveryPath, | |||
941 | HandlerTs &&... Handlers) { | |||
942 | if (ValOrErr) | |||
943 | return ValOrErr; | |||
944 | ||||
945 | if (auto Err = handleErrors(ValOrErr.takeError(), | |||
946 | std::forward<HandlerTs>(Handlers)...)) | |||
947 | return std::move(Err); | |||
948 | ||||
949 | return RecoveryPath(); | |||
950 | } | |||
951 | ||||
952 | /// Log all errors (if any) in E to OS. If there are any errors, ErrorBanner | |||
953 | /// will be printed before the first one is logged. A newline will be printed | |||
954 | /// after each error. | |||
955 | /// | |||
956 | /// This is useful in the base level of your program to allow clean termination | |||
957 | /// (allowing clean deallocation of resources, etc.), while reporting error | |||
958 | /// information to the user. | |||
959 | void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner); | |||
960 | ||||
961 | /// Write all error messages (if any) in E to a string. The newline character | |||
962 | /// is used to separate error messages. | |||
963 | inline std::string toString(Error E) { | |||
964 | SmallVector<std::string, 2> Errors; | |||
965 | handleAllErrors(std::move(E), [&Errors](const ErrorInfoBase &EI) { | |||
966 | Errors.push_back(EI.message()); | |||
967 | }); | |||
968 | return join(Errors.begin(), Errors.end(), "\n"); | |||
969 | } | |||
970 | ||||
971 | /// Consume a Error without doing anything. This method should be used | |||
972 | /// only where an error can be considered a reasonable and expected return | |||
973 | /// value. | |||
974 | /// | |||
975 | /// Uses of this method are potentially indicative of design problems: If it's | |||
976 | /// legitimate to do nothing while processing an "error", the error-producer | |||
977 | /// might be more clearly refactored to return an Optional<T>. | |||
978 | inline void consumeError(Error Err) { | |||
979 | handleAllErrors(std::move(Err), [](const ErrorInfoBase &) {}); | |||
980 | } | |||
981 | ||||
982 | /// Helper for converting an Error to a bool. | |||
983 | /// | |||
984 | /// This method returns true if Err is in an error state, or false if it is | |||
985 | /// in a success state. Puts Err in a checked state in both cases (unlike | |||
986 | /// Error::operator bool(), which only does this for success states). | |||
987 | inline bool errorToBool(Error Err) { | |||
988 | bool IsError = static_cast<bool>(Err); | |||
989 | if (IsError) | |||
990 | consumeError(std::move(Err)); | |||
991 | return IsError; | |||
992 | } | |||
993 | ||||
994 | /// Helper for Errors used as out-parameters. | |||
995 | /// | |||
996 | /// This helper is for use with the Error-as-out-parameter idiom, where an error | |||
997 | /// is passed to a function or method by reference, rather than being returned. | |||
998 | /// In such cases it is helpful to set the checked bit on entry to the function | |||
999 | /// so that the error can be written to (unchecked Errors abort on assignment) | |||
1000 | /// and clear the checked bit on exit so that clients cannot accidentally forget | |||
1001 | /// to check the result. This helper performs these actions automatically using | |||
1002 | /// RAII: | |||
1003 | /// | |||
1004 | /// @code{.cpp} | |||
1005 | /// Result foo(Error &Err) { | |||
1006 | /// ErrorAsOutParameter ErrAsOutParam(&Err); // 'Checked' flag set | |||
1007 | /// // <body of foo> | |||
1008 | /// // <- 'Checked' flag auto-cleared when ErrAsOutParam is destructed. | |||
1009 | /// } | |||
1010 | /// @endcode | |||
1011 | /// | |||
1012 | /// ErrorAsOutParameter takes an Error* rather than Error& so that it can be | |||
1013 | /// used with optional Errors (Error pointers that are allowed to be null). If | |||
1014 | /// ErrorAsOutParameter took an Error reference, an instance would have to be | |||
1015 | /// created inside every condition that verified that Error was non-null. By | |||
1016 | /// taking an Error pointer we can just create one instance at the top of the | |||
1017 | /// function. | |||
1018 | class ErrorAsOutParameter { | |||
1019 | public: | |||
1020 | ErrorAsOutParameter(Error *Err) : Err(Err) { | |||
1021 | // Raise the checked bit if Err is success. | |||
1022 | if (Err) | |||
1023 | (void)!!*Err; | |||
1024 | } | |||
1025 | ||||
1026 | ~ErrorAsOutParameter() { | |||
1027 | // Clear the checked bit. | |||
1028 | if (Err && !*Err) | |||
1029 | *Err = Error::success(); | |||
1030 | } | |||
1031 | ||||
1032 | private: | |||
1033 | Error *Err; | |||
1034 | }; | |||
1035 | ||||
1036 | /// Helper for Expected<T>s used as out-parameters. | |||
1037 | /// | |||
1038 | /// See ErrorAsOutParameter. | |||
1039 | template <typename T> | |||
1040 | class ExpectedAsOutParameter { | |||
1041 | public: | |||
1042 | ExpectedAsOutParameter(Expected<T> *ValOrErr) | |||
1043 | : ValOrErr(ValOrErr) { | |||
1044 | if (ValOrErr) | |||
1045 | (void)!!*ValOrErr; | |||
1046 | } | |||
1047 | ||||
1048 | ~ExpectedAsOutParameter() { | |||
1049 | if (ValOrErr) | |||
1050 | ValOrErr->setUnchecked(); | |||
1051 | } | |||
1052 | ||||
1053 | private: | |||
1054 | Expected<T> *ValOrErr; | |||
1055 | }; | |||
1056 | ||||
1057 | /// This class wraps a std::error_code in a Error. | |||
1058 | /// | |||
1059 | /// This is useful if you're writing an interface that returns a Error | |||
1060 | /// (or Expected) and you want to call code that still returns | |||
1061 | /// std::error_codes. | |||
1062 | class ECError : public ErrorInfo<ECError> { | |||
1063 | friend Error errorCodeToError(std::error_code); | |||
1064 | ||||
1065 | public: | |||
1066 | void setErrorCode(std::error_code EC) { this->EC = EC; } | |||
1067 | std::error_code convertToErrorCode() const override { return EC; } | |||
1068 | void log(raw_ostream &OS) const override { OS << EC.message(); } | |||
1069 | ||||
1070 | // Used by ErrorInfo::classID. | |||
1071 | static char ID; | |||
1072 | ||||
1073 | protected: | |||
1074 | ECError() = default; | |||
1075 | ECError(std::error_code EC) : EC(EC) {} | |||
1076 | ||||
1077 | std::error_code EC; | |||
1078 | }; | |||
1079 | ||||
1080 | /// The value returned by this function can be returned from convertToErrorCode | |||
1081 | /// for Error values where no sensible translation to std::error_code exists. | |||
1082 | /// It should only be used in this situation, and should never be used where a | |||
1083 | /// sensible conversion to std::error_code is available, as attempts to convert | |||
1084 | /// to/from this error will result in a fatal error. (i.e. it is a programmatic | |||
1085 | ///error to try to convert such a value). | |||
1086 | std::error_code inconvertibleErrorCode(); | |||
1087 | ||||
1088 | /// Helper for converting an std::error_code to a Error. | |||
1089 | Error errorCodeToError(std::error_code EC); | |||
1090 | ||||
1091 | /// Helper for converting an ECError to a std::error_code. | |||
1092 | /// | |||
1093 | /// This method requires that Err be Error() or an ECError, otherwise it | |||
1094 | /// will trigger a call to abort(). | |||
1095 | std::error_code errorToErrorCode(Error Err); | |||
1096 | ||||
1097 | /// Convert an ErrorOr<T> to an Expected<T>. | |||
1098 | template <typename T> Expected<T> errorOrToExpected(ErrorOr<T> &&EO) { | |||
1099 | if (auto EC = EO.getError()) | |||
1100 | return errorCodeToError(EC); | |||
1101 | return std::move(*EO); | |||
1102 | } | |||
1103 | ||||
1104 | /// Convert an Expected<T> to an ErrorOr<T>. | |||
1105 | template <typename T> ErrorOr<T> expectedToErrorOr(Expected<T> &&E) { | |||
1106 | if (auto Err = E.takeError()) | |||
1107 | return errorToErrorCode(std::move(Err)); | |||
1108 | return std::move(*E); | |||
1109 | } | |||
1110 | ||||
1111 | /// This class wraps a string in an Error. | |||
1112 | /// | |||
1113 | /// StringError is useful in cases where the client is not expected to be able | |||
1114 | /// to consume the specific error message programmatically (for example, if the | |||
1115 | /// error message is to be presented to the user). | |||
1116 | /// | |||
1117 | /// StringError can also be used when additional information is to be printed | |||
1118 | /// along with a error_code message. Depending on the constructor called, this | |||
1119 | /// class can either display: | |||
1120 | /// 1. the error_code message (ECError behavior) | |||
1121 | /// 2. a string | |||
1122 | /// 3. the error_code message and a string | |||
1123 | /// | |||
1124 | /// These behaviors are useful when subtyping is required; for example, when a | |||
1125 | /// specific library needs an explicit error type. In the example below, | |||
1126 | /// PDBError is derived from StringError: | |||
1127 | /// | |||
1128 | /// @code{.cpp} | |||
1129 | /// Expected<int> foo() { | |||
1130 | /// return llvm::make_error<PDBError>(pdb_error_code::dia_failed_loading, | |||
1131 | /// "Additional information"); | |||
1132 | /// } | |||
1133 | /// @endcode | |||
1134 | /// | |||
1135 | class StringError : public ErrorInfo<StringError> { | |||
1136 | public: | |||
1137 | static char ID; | |||
1138 | ||||
1139 | // Prints EC + S and converts to EC | |||
1140 | StringError(std::error_code EC, const Twine &S = Twine()); | |||
1141 | ||||
1142 | // Prints S and converts to EC | |||
1143 | StringError(const Twine &S, std::error_code EC); | |||
1144 | ||||
1145 | void log(raw_ostream &OS) const override; | |||
1146 | std::error_code convertToErrorCode() const override; | |||
1147 | ||||
1148 | const std::string &getMessage() const { return Msg; } | |||
1149 | ||||
1150 | private: | |||
1151 | std::string Msg; | |||
1152 | std::error_code EC; | |||
1153 | const bool PrintMsgOnly = false; | |||
1154 | }; | |||
1155 | ||||
1156 | /// Create formatted StringError object. | |||
1157 | template <typename... Ts> | |||
1158 | Error createStringError(std::error_code EC, char const *Fmt, | |||
1159 | const Ts &... Vals) { | |||
1160 | std::string Buffer; | |||
1161 | raw_string_ostream Stream(Buffer); | |||
1162 | Stream << format(Fmt, Vals...); | |||
1163 | return make_error<StringError>(Stream.str(), EC); | |||
1164 | } | |||
1165 | ||||
1166 | Error createStringError(std::error_code EC, char const *Msg); | |||
1167 | ||||
1168 | /// This class wraps a filename and another Error. | |||
1169 | /// | |||
1170 | /// In some cases, an error needs to live along a 'source' name, in order to | |||
1171 | /// show more detailed information to the user. | |||
1172 | class FileError final : public ErrorInfo<FileError> { | |||
1173 | ||||
1174 | friend Error createFileError(std::string, Error); | |||
1175 | ||||
1176 | public: | |||
1177 | void log(raw_ostream &OS) const override { | |||
1178 | assert(Err && !FileName.empty() && "Trying to log after takeError().")((Err && !FileName.empty() && "Trying to log after takeError()." ) ? static_cast<void> (0) : __assert_fail ("Err && !FileName.empty() && \"Trying to log after takeError().\"" , "/build/llvm-toolchain-snapshot-8~svn345461/include/llvm/Support/Error.h" , 1178, __PRETTY_FUNCTION__)); | |||
1179 | OS << "'" << FileName << "': "; | |||
1180 | Err->log(OS); | |||
1181 | } | |||
1182 | ||||
1183 | Error takeError() { return Error(std::move(Err)); } | |||
1184 | ||||
1185 | std::error_code convertToErrorCode() const override; | |||
1186 | ||||
1187 | // Used by ErrorInfo::classID. | |||
1188 | static char ID; | |||
1189 | ||||
1190 | private: | |||
1191 | FileError(std::string F, std::unique_ptr<ErrorInfoBase> E) { | |||
1192 | assert(E && "Cannot create FileError from Error success value.")((E && "Cannot create FileError from Error success value." ) ? static_cast<void> (0) : __assert_fail ("E && \"Cannot create FileError from Error success value.\"" , "/build/llvm-toolchain-snapshot-8~svn345461/include/llvm/Support/Error.h" , 1192, __PRETTY_FUNCTION__)); | |||
1193 | assert(!F.empty() &&((!F.empty() && "The file name provided to FileError must not be empty." ) ? static_cast<void> (0) : __assert_fail ("!F.empty() && \"The file name provided to FileError must not be empty.\"" , "/build/llvm-toolchain-snapshot-8~svn345461/include/llvm/Support/Error.h" , 1194, __PRETTY_FUNCTION__)) | |||
1194 | "The file name provided to FileError must not be empty.")((!F.empty() && "The file name provided to FileError must not be empty." ) ? static_cast<void> (0) : __assert_fail ("!F.empty() && \"The file name provided to FileError must not be empty.\"" , "/build/llvm-toolchain-snapshot-8~svn345461/include/llvm/Support/Error.h" , 1194, __PRETTY_FUNCTION__)); | |||
1195 | FileName = F; | |||
1196 | Err = std::move(E); | |||
1197 | } | |||
1198 | ||||
1199 | static Error build(std::string F, Error E) { | |||
1200 | return Error(std::unique_ptr<FileError>(new FileError(F, E.takePayload()))); | |||
1201 | } | |||
1202 | ||||
1203 | std::string FileName; | |||
1204 | std::unique_ptr<ErrorInfoBase> Err; | |||
1205 | }; | |||
1206 | ||||
1207 | /// Concatenate a source file path and/or name with an Error. The resulting | |||
1208 | /// Error is unchecked. | |||
1209 | inline Error createFileError(std::string F, Error E) { | |||
1210 | return FileError::build(F, std::move(E)); | |||
1211 | } | |||
1212 | ||||
1213 | Error createFileError(std::string F, ErrorSuccess) = delete; | |||
1214 | ||||
1215 | /// Helper for check-and-exit error handling. | |||
1216 | /// | |||
1217 | /// For tool use only. NOT FOR USE IN LIBRARY CODE. | |||
1218 | /// | |||
1219 | class ExitOnError { | |||
1220 | public: | |||
1221 | /// Create an error on exit helper. | |||
1222 | ExitOnError(std::string Banner = "", int DefaultErrorExitCode = 1) | |||
1223 | : Banner(std::move(Banner)), | |||
1224 | GetExitCode([=](const Error &) { return DefaultErrorExitCode; }) {} | |||
1225 | ||||
1226 | /// Set the banner string for any errors caught by operator(). | |||
1227 | void setBanner(std::string Banner) { this->Banner = std::move(Banner); } | |||
1228 | ||||
1229 | /// Set the exit-code mapper function. | |||
1230 | void setExitCodeMapper(std::function<int(const Error &)> GetExitCode) { | |||
1231 | this->GetExitCode = std::move(GetExitCode); | |||
1232 | } | |||
1233 | ||||
1234 | /// Check Err. If it's in a failure state log the error(s) and exit. | |||
1235 | void operator()(Error Err) const { checkError(std::move(Err)); } | |||
1236 | ||||
1237 | /// Check E. If it's in a success state then return the contained value. If | |||
1238 | /// it's in a failure state log the error(s) and exit. | |||
1239 | template <typename T> T operator()(Expected<T> &&E) const { | |||
1240 | checkError(E.takeError()); | |||
1241 | return std::move(*E); | |||
1242 | } | |||
1243 | ||||
1244 | /// Check E. If it's in a success state then return the contained reference. If | |||
1245 | /// it's in a failure state log the error(s) and exit. | |||
1246 | template <typename T> T& operator()(Expected<T&> &&E) const { | |||
1247 | checkError(E.takeError()); | |||
1248 | return *E; | |||
1249 | } | |||
1250 | ||||
1251 | private: | |||
1252 | void checkError(Error Err) const { | |||
1253 | if (Err) { | |||
1254 | int ExitCode = GetExitCode(Err); | |||
1255 | logAllUnhandledErrors(std::move(Err), errs(), Banner); | |||
1256 | exit(ExitCode); | |||
1257 | } | |||
1258 | } | |||
1259 | ||||
1260 | std::string Banner; | |||
1261 | std::function<int(const Error &)> GetExitCode; | |||
1262 | }; | |||
1263 | ||||
1264 | /// Conversion from Error to LLVMErrorRef for C error bindings. | |||
1265 | inline LLVMErrorRef wrap(Error Err) { | |||
1266 | return reinterpret_cast<LLVMErrorRef>(Err.takePayload().release()); | |||
1267 | } | |||
1268 | ||||
1269 | /// Conversion from LLVMErrorRef to Error for C error bindings. | |||
1270 | inline Error unwrap(LLVMErrorRef ErrRef) { | |||
1271 | return Error(std::unique_ptr<ErrorInfoBase>( | |||
1272 | reinterpret_cast<ErrorInfoBase *>(ErrRef))); | |||
1273 | } | |||
1274 | ||||
1275 | } // end namespace llvm | |||
1276 | ||||
1277 | #endif // LLVM_SUPPORT_ERROR_H |