Bug Summary

File:tools/llvm-objdump/COFFDump.cpp
Warning:line 685, column 58
Called C++ object pointer is uninitialized

Annotated Source Code

[?] Use j/k keys for keyboard navigation

/build/llvm-toolchain-snapshot-6.0~svn321639/tools/llvm-objdump/COFFDump.cpp

1//===-- COFFDump.cpp - COFF-specific dumper ---------------------*- 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/// \file
11/// \brief This file implements the COFF-specific dumper for llvm-objdump.
12/// It outputs the Win64 EH data structures as plain text.
13/// The encoding of the unwind codes is described in MSDN:
14/// http://msdn.microsoft.com/en-us/library/ck9asaa9.aspx
15///
16//===----------------------------------------------------------------------===//
17
18#include "llvm-objdump.h"
19#include "llvm/Object/COFF.h"
20#include "llvm/Object/COFFImportFile.h"
21#include "llvm/Object/ObjectFile.h"
22#include "llvm/Support/Format.h"
23#include "llvm/Support/Win64EH.h"
24#include "llvm/Support/raw_ostream.h"
25
26using namespace llvm;
27using namespace object;
28using namespace llvm::Win64EH;
29
30// Returns the name of the unwind code.
31static StringRef getUnwindCodeTypeName(uint8_t Code) {
32 switch(Code) {
33 default: llvm_unreachable("Invalid unwind code")::llvm::llvm_unreachable_internal("Invalid unwind code", "/build/llvm-toolchain-snapshot-6.0~svn321639/tools/llvm-objdump/COFFDump.cpp"
, 33)
;
34 case UOP_PushNonVol: return "UOP_PushNonVol";
35 case UOP_AllocLarge: return "UOP_AllocLarge";
36 case UOP_AllocSmall: return "UOP_AllocSmall";
37 case UOP_SetFPReg: return "UOP_SetFPReg";
38 case UOP_SaveNonVol: return "UOP_SaveNonVol";
39 case UOP_SaveNonVolBig: return "UOP_SaveNonVolBig";
40 case UOP_SaveXMM128: return "UOP_SaveXMM128";
41 case UOP_SaveXMM128Big: return "UOP_SaveXMM128Big";
42 case UOP_PushMachFrame: return "UOP_PushMachFrame";
43 }
44}
45
46// Returns the name of a referenced register.
47static StringRef getUnwindRegisterName(uint8_t Reg) {
48 switch(Reg) {
49 default: llvm_unreachable("Invalid register")::llvm::llvm_unreachable_internal("Invalid register", "/build/llvm-toolchain-snapshot-6.0~svn321639/tools/llvm-objdump/COFFDump.cpp"
, 49)
;
50 case 0: return "RAX";
51 case 1: return "RCX";
52 case 2: return "RDX";
53 case 3: return "RBX";
54 case 4: return "RSP";
55 case 5: return "RBP";
56 case 6: return "RSI";
57 case 7: return "RDI";
58 case 8: return "R8";
59 case 9: return "R9";
60 case 10: return "R10";
61 case 11: return "R11";
62 case 12: return "R12";
63 case 13: return "R13";
64 case 14: return "R14";
65 case 15: return "R15";
66 }
67}
68
69// Calculates the number of array slots required for the unwind code.
70static unsigned getNumUsedSlots(const UnwindCode &UnwindCode) {
71 switch (UnwindCode.getUnwindOp()) {
72 default: llvm_unreachable("Invalid unwind code")::llvm::llvm_unreachable_internal("Invalid unwind code", "/build/llvm-toolchain-snapshot-6.0~svn321639/tools/llvm-objdump/COFFDump.cpp"
, 72)
;
73 case UOP_PushNonVol:
74 case UOP_AllocSmall:
75 case UOP_SetFPReg:
76 case UOP_PushMachFrame:
77 return 1;
78 case UOP_SaveNonVol:
79 case UOP_SaveXMM128:
80 return 2;
81 case UOP_SaveNonVolBig:
82 case UOP_SaveXMM128Big:
83 return 3;
84 case UOP_AllocLarge:
85 return (UnwindCode.getOpInfo() == 0) ? 2 : 3;
86 }
87}
88
89// Prints one unwind code. Because an unwind code can occupy up to 3 slots in
90// the unwind codes array, this function requires that the correct number of
91// slots is provided.
92static void printUnwindCode(ArrayRef<UnwindCode> UCs) {
93 assert(UCs.size() >= getNumUsedSlots(UCs[0]))(static_cast <bool> (UCs.size() >= getNumUsedSlots(UCs
[0])) ? void (0) : __assert_fail ("UCs.size() >= getNumUsedSlots(UCs[0])"
, "/build/llvm-toolchain-snapshot-6.0~svn321639/tools/llvm-objdump/COFFDump.cpp"
, 93, __extension__ __PRETTY_FUNCTION__))
;
94 outs() << format(" 0x%02x: ", unsigned(UCs[0].u.CodeOffset))
95 << getUnwindCodeTypeName(UCs[0].getUnwindOp());
96 switch (UCs[0].getUnwindOp()) {
97 case UOP_PushNonVol:
98 outs() << " " << getUnwindRegisterName(UCs[0].getOpInfo());
99 break;
100 case UOP_AllocLarge:
101 if (UCs[0].getOpInfo() == 0) {
102 outs() << " " << UCs[1].FrameOffset;
103 } else {
104 outs() << " " << UCs[1].FrameOffset
105 + (static_cast<uint32_t>(UCs[2].FrameOffset) << 16);
106 }
107 break;
108 case UOP_AllocSmall:
109 outs() << " " << ((UCs[0].getOpInfo() + 1) * 8);
110 break;
111 case UOP_SetFPReg:
112 outs() << " ";
113 break;
114 case UOP_SaveNonVol:
115 outs() << " " << getUnwindRegisterName(UCs[0].getOpInfo())
116 << format(" [0x%04x]", 8 * UCs[1].FrameOffset);
117 break;
118 case UOP_SaveNonVolBig:
119 outs() << " " << getUnwindRegisterName(UCs[0].getOpInfo())
120 << format(" [0x%08x]", UCs[1].FrameOffset
121 + (static_cast<uint32_t>(UCs[2].FrameOffset) << 16));
122 break;
123 case UOP_SaveXMM128:
124 outs() << " XMM" << static_cast<uint32_t>(UCs[0].getOpInfo())
125 << format(" [0x%04x]", 16 * UCs[1].FrameOffset);
126 break;
127 case UOP_SaveXMM128Big:
128 outs() << " XMM" << UCs[0].getOpInfo()
129 << format(" [0x%08x]", UCs[1].FrameOffset
130 + (static_cast<uint32_t>(UCs[2].FrameOffset) << 16));
131 break;
132 case UOP_PushMachFrame:
133 outs() << " " << (UCs[0].getOpInfo() ? "w/o" : "w")
134 << " error code";
135 break;
136 }
137 outs() << "\n";
138}
139
140static void printAllUnwindCodes(ArrayRef<UnwindCode> UCs) {
141 for (const UnwindCode *I = UCs.begin(), *E = UCs.end(); I < E; ) {
142 unsigned UsedSlots = getNumUsedSlots(*I);
143 if (UsedSlots > UCs.size()) {
144 outs() << "Unwind data corrupted: Encountered unwind op "
145 << getUnwindCodeTypeName((*I).getUnwindOp())
146 << " which requires " << UsedSlots
147 << " slots, but only " << UCs.size()
148 << " remaining in buffer";
149 return ;
150 }
151 printUnwindCode(makeArrayRef(I, E));
152 I += UsedSlots;
153 }
154}
155
156// Given a symbol sym this functions returns the address and section of it.
157static std::error_code
158resolveSectionAndAddress(const COFFObjectFile *Obj, const SymbolRef &Sym,
159 const coff_section *&ResolvedSection,
160 uint64_t &ResolvedAddr) {
161 Expected<uint64_t> ResolvedAddrOrErr = Sym.getAddress();
162 if (!ResolvedAddrOrErr)
163 return errorToErrorCode(ResolvedAddrOrErr.takeError());
164 ResolvedAddr = *ResolvedAddrOrErr;
165 Expected<section_iterator> Iter = Sym.getSection();
166 if (!Iter)
167 return errorToErrorCode(Iter.takeError());
168 ResolvedSection = Obj->getCOFFSection(**Iter);
169 return std::error_code();
170}
171
172// Given a vector of relocations for a section and an offset into this section
173// the function returns the symbol used for the relocation at the offset.
174static std::error_code resolveSymbol(const std::vector<RelocationRef> &Rels,
175 uint64_t Offset, SymbolRef &Sym) {
176 for (auto &R : Rels) {
177 uint64_t Ofs = R.getOffset();
178 if (Ofs == Offset) {
179 Sym = *R.getSymbol();
180 return std::error_code();
181 }
182 }
183 return object_error::parse_failed;
184}
185
186// Given a vector of relocations for a section and an offset into this section
187// the function resolves the symbol used for the relocation at the offset and
188// returns the section content and the address inside the content pointed to
189// by the symbol.
190static std::error_code
191getSectionContents(const COFFObjectFile *Obj,
192 const std::vector<RelocationRef> &Rels, uint64_t Offset,
193 ArrayRef<uint8_t> &Contents, uint64_t &Addr) {
194 SymbolRef Sym;
195 if (std::error_code EC = resolveSymbol(Rels, Offset, Sym))
196 return EC;
197 const coff_section *Section;
198 if (std::error_code EC = resolveSectionAndAddress(Obj, Sym, Section, Addr))
199 return EC;
200 if (std::error_code EC = Obj->getSectionContents(Section, Contents))
201 return EC;
202 return std::error_code();
203}
204
205// Given a vector of relocations for a section and an offset into this section
206// the function returns the name of the symbol used for the relocation at the
207// offset.
208static std::error_code resolveSymbolName(const std::vector<RelocationRef> &Rels,
209 uint64_t Offset, StringRef &Name) {
210 SymbolRef Sym;
211 if (std::error_code EC = resolveSymbol(Rels, Offset, Sym))
212 return EC;
213 Expected<StringRef> NameOrErr = Sym.getName();
214 if (!NameOrErr)
215 return errorToErrorCode(NameOrErr.takeError());
216 Name = *NameOrErr;
217 return std::error_code();
218}
219
220static void printCOFFSymbolAddress(llvm::raw_ostream &Out,
221 const std::vector<RelocationRef> &Rels,
222 uint64_t Offset, uint32_t Disp) {
223 StringRef Sym;
224 if (!resolveSymbolName(Rels, Offset, Sym)) {
225 Out << Sym;
226 if (Disp > 0)
227 Out << format(" + 0x%04x", Disp);
228 } else {
229 Out << format("0x%04x", Disp);
230 }
231}
232
233static void
234printSEHTable(const COFFObjectFile *Obj, uint32_t TableVA, int Count) {
235 if (Count == 0)
236 return;
237
238 const pe32_header *PE32Header;
239 error(Obj->getPE32Header(PE32Header));
240 uint32_t ImageBase = PE32Header->ImageBase;
241 uintptr_t IntPtr = 0;
242 error(Obj->getVaPtr(TableVA, IntPtr));
243 const support::ulittle32_t *P = (const support::ulittle32_t *)IntPtr;
244 outs() << "SEH Table:";
245 for (int I = 0; I < Count; ++I)
246 outs() << format(" 0x%x", P[I] + ImageBase);
247 outs() << "\n\n";
248}
249
250template <typename T>
251static void printTLSDirectoryT(const coff_tls_directory<T> *TLSDir) {
252 size_t FormatWidth = sizeof(T) * 2;
253 outs() << "TLS directory:"
254 << "\n StartAddressOfRawData: "
255 << format_hex(TLSDir->StartAddressOfRawData, FormatWidth)
256 << "\n EndAddressOfRawData: "
257 << format_hex(TLSDir->EndAddressOfRawData, FormatWidth)
258 << "\n AddressOfIndex: "
259 << format_hex(TLSDir->AddressOfIndex, FormatWidth)
260 << "\n AddressOfCallBacks: "
261 << format_hex(TLSDir->AddressOfCallBacks, FormatWidth)
262 << "\n SizeOfZeroFill: "
263 << TLSDir->SizeOfZeroFill
264 << "\n Characteristics: "
265 << TLSDir->Characteristics
266 << "\n Alignment: "
267 << TLSDir->getAlignment()
268 << "\n\n";
269}
270
271static void printTLSDirectory(const COFFObjectFile *Obj) {
272 const pe32_header *PE32Header;
273 error(Obj->getPE32Header(PE32Header));
274
275 const pe32plus_header *PE32PlusHeader;
276 error(Obj->getPE32PlusHeader(PE32PlusHeader));
277
278 // Skip if it's not executable.
279 if (!PE32Header && !PE32PlusHeader)
280 return;
281
282 const data_directory *DataDir;
283 error(Obj->getDataDirectory(COFF::TLS_TABLE, DataDir));
284 uintptr_t IntPtr = 0;
285 if (DataDir->RelativeVirtualAddress == 0)
286 return;
287 error(Obj->getRvaPtr(DataDir->RelativeVirtualAddress, IntPtr));
288
289 if (PE32Header) {
290 auto *TLSDir = reinterpret_cast<const coff_tls_directory32 *>(IntPtr);
291 printTLSDirectoryT(TLSDir);
292 } else {
293 auto *TLSDir = reinterpret_cast<const coff_tls_directory64 *>(IntPtr);
294 printTLSDirectoryT(TLSDir);
295 }
296
297 outs() << "\n";
298}
299
300static void printLoadConfiguration(const COFFObjectFile *Obj) {
301 // Skip if it's not executable.
302 const pe32_header *PE32Header;
303 error(Obj->getPE32Header(PE32Header));
304 if (!PE32Header)
305 return;
306
307 // Currently only x86 is supported
308 if (Obj->getMachine() != COFF::IMAGE_FILE_MACHINE_I386)
309 return;
310
311 const data_directory *DataDir;
312 error(Obj->getDataDirectory(COFF::LOAD_CONFIG_TABLE, DataDir));
313 uintptr_t IntPtr = 0;
314 if (DataDir->RelativeVirtualAddress == 0)
315 return;
316 error(Obj->getRvaPtr(DataDir->RelativeVirtualAddress, IntPtr));
317
318 auto *LoadConf = reinterpret_cast<const coff_load_configuration32 *>(IntPtr);
319 outs() << "Load configuration:"
320 << "\n Timestamp: " << LoadConf->TimeDateStamp
321 << "\n Major Version: " << LoadConf->MajorVersion
322 << "\n Minor Version: " << LoadConf->MinorVersion
323 << "\n GlobalFlags Clear: " << LoadConf->GlobalFlagsClear
324 << "\n GlobalFlags Set: " << LoadConf->GlobalFlagsSet
325 << "\n Critical Section Default Timeout: " << LoadConf->CriticalSectionDefaultTimeout
326 << "\n Decommit Free Block Threshold: " << LoadConf->DeCommitFreeBlockThreshold
327 << "\n Decommit Total Free Threshold: " << LoadConf->DeCommitTotalFreeThreshold
328 << "\n Lock Prefix Table: " << LoadConf->LockPrefixTable
329 << "\n Maximum Allocation Size: " << LoadConf->MaximumAllocationSize
330 << "\n Virtual Memory Threshold: " << LoadConf->VirtualMemoryThreshold
331 << "\n Process Affinity Mask: " << LoadConf->ProcessAffinityMask
332 << "\n Process Heap Flags: " << LoadConf->ProcessHeapFlags
333 << "\n CSD Version: " << LoadConf->CSDVersion
334 << "\n Security Cookie: " << LoadConf->SecurityCookie
335 << "\n SEH Table: " << LoadConf->SEHandlerTable
336 << "\n SEH Count: " << LoadConf->SEHandlerCount
337 << "\n\n";
338 printSEHTable(Obj, LoadConf->SEHandlerTable, LoadConf->SEHandlerCount);
339 outs() << "\n";
340}
341
342// Prints import tables. The import table is a table containing the list of
343// DLL name and symbol names which will be linked by the loader.
344static void printImportTables(const COFFObjectFile *Obj) {
345 import_directory_iterator I = Obj->import_directory_begin();
346 import_directory_iterator E = Obj->import_directory_end();
347 if (I == E)
348 return;
349 outs() << "The Import Tables:\n";
350 for (const ImportDirectoryEntryRef &DirRef : Obj->import_directories()) {
351 const coff_import_directory_table_entry *Dir;
352 StringRef Name;
353 if (DirRef.getImportTableEntry(Dir)) return;
354 if (DirRef.getName(Name)) return;
355
356 outs() << format(" lookup %08x time %08x fwd %08x name %08x addr %08x\n\n",
357 static_cast<uint32_t>(Dir->ImportLookupTableRVA),
358 static_cast<uint32_t>(Dir->TimeDateStamp),
359 static_cast<uint32_t>(Dir->ForwarderChain),
360 static_cast<uint32_t>(Dir->NameRVA),
361 static_cast<uint32_t>(Dir->ImportAddressTableRVA));
362 outs() << " DLL Name: " << Name << "\n";
363 outs() << " Hint/Ord Name\n";
364 for (const ImportedSymbolRef &Entry : DirRef.imported_symbols()) {
365 bool IsOrdinal;
366 if (Entry.isOrdinal(IsOrdinal))
367 return;
368 if (IsOrdinal) {
369 uint16_t Ordinal;
370 if (Entry.getOrdinal(Ordinal))
371 return;
372 outs() << format(" % 6d\n", Ordinal);
373 continue;
374 }
375 uint32_t HintNameRVA;
376 if (Entry.getHintNameRVA(HintNameRVA))
377 return;
378 uint16_t Hint;
379 StringRef Name;
380 if (Obj->getHintName(HintNameRVA, Hint, Name))
381 return;
382 outs() << format(" % 6d ", Hint) << Name << "\n";
383 }
384 outs() << "\n";
385 }
386}
387
388// Prints export tables. The export table is a table containing the list of
389// exported symbol from the DLL.
390static void printExportTable(const COFFObjectFile *Obj) {
391 outs() << "Export Table:\n";
392 export_directory_iterator I = Obj->export_directory_begin();
393 export_directory_iterator E = Obj->export_directory_end();
394 if (I == E)
395 return;
396 StringRef DllName;
397 uint32_t OrdinalBase;
398 if (I->getDllName(DllName))
399 return;
400 if (I->getOrdinalBase(OrdinalBase))
401 return;
402 outs() << " DLL name: " << DllName << "\n";
403 outs() << " Ordinal base: " << OrdinalBase << "\n";
404 outs() << " Ordinal RVA Name\n";
405 for (; I != E; I = ++I) {
406 uint32_t Ordinal;
407 if (I->getOrdinal(Ordinal))
408 return;
409 uint32_t RVA;
410 if (I->getExportRVA(RVA))
411 return;
412 bool IsForwarder;
413 if (I->isForwarder(IsForwarder))
414 return;
415
416 if (IsForwarder) {
417 // Export table entries can be used to re-export symbols that
418 // this COFF file is imported from some DLLs. This is rare.
419 // In most cases IsForwarder is false.
420 outs() << format(" % 4d ", Ordinal);
421 } else {
422 outs() << format(" % 4d %# 8x", Ordinal, RVA);
423 }
424
425 StringRef Name;
426 if (I->getSymbolName(Name))
427 continue;
428 if (!Name.empty())
429 outs() << " " << Name;
430 if (IsForwarder) {
431 StringRef S;
432 if (I->getForwardTo(S))
433 return;
434 outs() << " (forwarded to " << S << ")";
435 }
436 outs() << "\n";
437 }
438}
439
440// Given the COFF object file, this function returns the relocations for .pdata
441// and the pointer to "runtime function" structs.
442static bool getPDataSection(const COFFObjectFile *Obj,
443 std::vector<RelocationRef> &Rels,
444 const RuntimeFunction *&RFStart, int &NumRFs) {
445 for (const SectionRef &Section : Obj->sections()) {
446 StringRef Name;
447 error(Section.getName(Name));
448 if (Name != ".pdata")
449 continue;
450
451 const coff_section *Pdata = Obj->getCOFFSection(Section);
452 for (const RelocationRef &Reloc : Section.relocations())
453 Rels.push_back(Reloc);
454
455 // Sort relocations by address.
456 std::sort(Rels.begin(), Rels.end(), RelocAddressLess);
457
458 ArrayRef<uint8_t> Contents;
459 error(Obj->getSectionContents(Pdata, Contents));
460 if (Contents.empty())
461 continue;
462
463 RFStart = reinterpret_cast<const RuntimeFunction *>(Contents.data());
464 NumRFs = Contents.size() / sizeof(RuntimeFunction);
465 return true;
466 }
467 return false;
468}
469
470static void printWin64EHUnwindInfo(const Win64EH::UnwindInfo *UI) {
471 // The casts to int are required in order to output the value as number.
472 // Without the casts the value would be interpreted as char data (which
473 // results in garbage output).
474 outs() << " Version: " << static_cast<int>(UI->getVersion()) << "\n";
475 outs() << " Flags: " << static_cast<int>(UI->getFlags());
476 if (UI->getFlags()) {
477 if (UI->getFlags() & UNW_ExceptionHandler)
478 outs() << " UNW_ExceptionHandler";
479 if (UI->getFlags() & UNW_TerminateHandler)
480 outs() << " UNW_TerminateHandler";
481 if (UI->getFlags() & UNW_ChainInfo)
482 outs() << " UNW_ChainInfo";
483 }
484 outs() << "\n";
485 outs() << " Size of prolog: " << static_cast<int>(UI->PrologSize) << "\n";
486 outs() << " Number of Codes: " << static_cast<int>(UI->NumCodes) << "\n";
487 // Maybe this should move to output of UOP_SetFPReg?
488 if (UI->getFrameRegister()) {
489 outs() << " Frame register: "
490 << getUnwindRegisterName(UI->getFrameRegister()) << "\n";
491 outs() << " Frame offset: " << 16 * UI->getFrameOffset() << "\n";
492 } else {
493 outs() << " No frame pointer used\n";
494 }
495 if (UI->getFlags() & (UNW_ExceptionHandler | UNW_TerminateHandler)) {
496 // FIXME: Output exception handler data
497 } else if (UI->getFlags() & UNW_ChainInfo) {
498 // FIXME: Output chained unwind info
499 }
500
501 if (UI->NumCodes)
502 outs() << " Unwind Codes:\n";
503
504 printAllUnwindCodes(makeArrayRef(&UI->UnwindCodes[0], UI->NumCodes));
505
506 outs() << "\n";
507 outs().flush();
508}
509
510/// Prints out the given RuntimeFunction struct for x64, assuming that Obj is
511/// pointing to an executable file.
512static void printRuntimeFunction(const COFFObjectFile *Obj,
513 const RuntimeFunction &RF) {
514 if (!RF.StartAddress)
515 return;
516 outs() << "Function Table:\n"
517 << format(" Start Address: 0x%04x\n",
518 static_cast<uint32_t>(RF.StartAddress))
519 << format(" End Address: 0x%04x\n",
520 static_cast<uint32_t>(RF.EndAddress))
521 << format(" Unwind Info Address: 0x%04x\n",
522 static_cast<uint32_t>(RF.UnwindInfoOffset));
523 uintptr_t addr;
524 if (Obj->getRvaPtr(RF.UnwindInfoOffset, addr))
525 return;
526 printWin64EHUnwindInfo(reinterpret_cast<const Win64EH::UnwindInfo *>(addr));
527}
528
529/// Prints out the given RuntimeFunction struct for x64, assuming that Obj is
530/// pointing to an object file. Unlike executable, fields in RuntimeFunction
531/// struct are filled with zeros, but instead there are relocations pointing to
532/// them so that the linker will fill targets' RVAs to the fields at link
533/// time. This function interprets the relocations to find the data to be used
534/// in the resulting executable.
535static void printRuntimeFunctionRels(const COFFObjectFile *Obj,
536 const RuntimeFunction &RF,
537 uint64_t SectionOffset,
538 const std::vector<RelocationRef> &Rels) {
539 outs() << "Function Table:\n";
540 outs() << " Start Address: ";
541 printCOFFSymbolAddress(outs(), Rels,
542 SectionOffset +
543 /*offsetof(RuntimeFunction, StartAddress)*/ 0,
544 RF.StartAddress);
545 outs() << "\n";
546
547 outs() << " End Address: ";
548 printCOFFSymbolAddress(outs(), Rels,
549 SectionOffset +
550 /*offsetof(RuntimeFunction, EndAddress)*/ 4,
551 RF.EndAddress);
552 outs() << "\n";
553
554 outs() << " Unwind Info Address: ";
555 printCOFFSymbolAddress(outs(), Rels,
556 SectionOffset +
557 /*offsetof(RuntimeFunction, UnwindInfoOffset)*/ 8,
558 RF.UnwindInfoOffset);
559 outs() << "\n";
560
561 ArrayRef<uint8_t> XContents;
562 uint64_t UnwindInfoOffset = 0;
563 error(getSectionContents(
564 Obj, Rels, SectionOffset +
565 /*offsetof(RuntimeFunction, UnwindInfoOffset)*/ 8,
566 XContents, UnwindInfoOffset));
567 if (XContents.empty())
568 return;
569
570 UnwindInfoOffset += RF.UnwindInfoOffset;
571 if (UnwindInfoOffset > XContents.size())
572 return;
573
574 auto *UI = reinterpret_cast<const Win64EH::UnwindInfo *>(XContents.data() +
575 UnwindInfoOffset);
576 printWin64EHUnwindInfo(UI);
577}
578
579void llvm::printCOFFUnwindInfo(const COFFObjectFile *Obj) {
580 if (Obj->getMachine() != COFF::IMAGE_FILE_MACHINE_AMD64) {
581 errs() << "Unsupported image machine type "
582 "(currently only AMD64 is supported).\n";
583 return;
584 }
585
586 std::vector<RelocationRef> Rels;
587 const RuntimeFunction *RFStart;
588 int NumRFs;
589 if (!getPDataSection(Obj, Rels, RFStart, NumRFs))
590 return;
591 ArrayRef<RuntimeFunction> RFs(RFStart, NumRFs);
592
593 bool IsExecutable = Rels.empty();
594 if (IsExecutable) {
595 for (const RuntimeFunction &RF : RFs)
596 printRuntimeFunction(Obj, RF);
597 return;
598 }
599
600 for (const RuntimeFunction &RF : RFs) {
601 uint64_t SectionOffset =
602 std::distance(RFs.begin(), &RF) * sizeof(RuntimeFunction);
603 printRuntimeFunctionRels(Obj, RF, SectionOffset, Rels);
604 }
605}
606
607void llvm::printCOFFFileHeader(const object::ObjectFile *Obj) {
608 const COFFObjectFile *file = dyn_cast<const COFFObjectFile>(Obj);
609 printTLSDirectory(file);
610 printLoadConfiguration(file);
611 printImportTables(file);
612 printExportTable(file);
613}
614
615void llvm::printCOFFSymbolTable(const object::COFFImportFile *i) {
616 unsigned Index = 0;
617 bool IsCode = i->getCOFFImportHeader()->getType() == COFF::IMPORT_CODE;
618
619 for (const object::BasicSymbolRef &Sym : i->symbols()) {
620 std::string Name;
621 raw_string_ostream NS(Name);
622
623 Sym.printName(NS);
624 NS.flush();
625
626 outs() << "[" << format("%2d", Index) << "]"
627 << "(sec " << format("%2d", 0) << ")"
628 << "(fl 0x00)" // Flag bits, which COFF doesn't have.
629 << "(ty " << format("%3x", (IsCode && Index) ? 32 : 0) << ")"
630 << "(scl " << format("%3x", 0) << ") "
631 << "(nx " << 0 << ") "
632 << "0x" << format("%08x", 0) << " " << Name << '\n';
633
634 ++Index;
635 }
636}
637
638void llvm::printCOFFSymbolTable(const COFFObjectFile *coff) {
639 for (unsigned SI = 0, SE = coff->getNumberOfSymbols(); SI != SE; ++SI) {
1
Assuming 'SI' is not equal to 'SE'
2
Loop condition is true. Entering loop body
5
Assuming 'SI' is not equal to 'SE'
6
Loop condition is true. Entering loop body
9
Assuming 'SI' is not equal to 'SE'
10
Loop condition is true. Entering loop body
13
Assuming 'SI' is not equal to 'SE'
14
Loop condition is true. Entering loop body
640 Expected<COFFSymbolRef> Symbol = coff->getSymbol(SI);
641 StringRef Name;
642 error(errorToErrorCode(Symbol.takeError()));
643 error(coff->getSymbolName(*Symbol, Name));
644
645 outs() << "[" << format("%2d", SI) << "]"
646 << "(sec " << format("%2d", int(Symbol->getSectionNumber())) << ")"
647 << "(fl 0x00)" // Flag bits, which COFF doesn't have.
648 << "(ty " << format("%3x", unsigned(Symbol->getType())) << ")"
649 << "(scl " << format("%3x", unsigned(Symbol->getStorageClass())) << ") "
650 << "(nx " << unsigned(Symbol->getNumberOfAuxSymbols()) << ") "
651 << "0x" << format("%08x", unsigned(Symbol->getValue())) << " "
652 << Name << "\n";
653
654 for (unsigned AI = 0, AE = Symbol->getNumberOfAuxSymbols(); AI < AE; ++AI, ++SI) {
3
Assuming 'AI' is >= 'AE'
4
Loop condition is false. Execution continues on line 501
7
Assuming 'AI' is >= 'AE'
8
Loop condition is false. Execution continues on line 501
11
Assuming 'AI' is >= 'AE'
12
Loop condition is false. Execution continues on line 501
15
Assuming 'AI' is < 'AE'
16
Loop condition is true. Entering loop body
655 if (Symbol->isSectionDefinition()) {
17
Assuming the condition is false
18
Taking false branch
656 const coff_aux_section_definition *asd;
657 error(coff->getAuxSymbol<coff_aux_section_definition>(SI + 1, asd));
658
659 int32_t AuxNumber = asd->getNumber(Symbol->isBigObj());
660
661 outs() << "AUX "
662 << format("scnlen 0x%x nreloc %d nlnno %d checksum 0x%x "
663 , unsigned(asd->Length)
664 , unsigned(asd->NumberOfRelocations)
665 , unsigned(asd->NumberOfLinenumbers)
666 , unsigned(asd->CheckSum))
667 << format("assoc %d comdat %d\n"
668 , unsigned(AuxNumber)
669 , unsigned(asd->Selection));
670 } else if (Symbol->isFileRecord()) {
19
Taking false branch
671 const char *FileName;
672 error(coff->getAuxSymbol<char>(SI + 1, FileName));
673
674 StringRef Name(FileName, Symbol->getNumberOfAuxSymbols() *
675 coff->getSymbolTableEntrySize());
676 outs() << "AUX " << Name.rtrim(StringRef("\0", 1)) << '\n';
677
678 SI = SI + Symbol->getNumberOfAuxSymbols();
679 break;
680 } else if (Symbol->isWeakExternal()) {
20
Taking true branch
681 const coff_aux_weak_external *awe;
21
'awe' declared without an initial value
682 error(coff->getAuxSymbol<coff_aux_weak_external>(SI + 1, awe));
22
Calling 'COFFObjectFile::getAuxSymbol'
112
Returning from 'COFFObjectFile::getAuxSymbol'
683
684 outs() << "AUX " << format("indx %d srch %d\n",
685 static_cast<uint32_t>(awe->TagIndex),
113
Called C++ object pointer is uninitialized
686 static_cast<uint32_t>(awe->Characteristics));
687 } else {
688 outs() << "AUX Unknown\n";
689 }
690 }
691 }
692}

/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Object/COFF.h

1//===- COFF.h - COFF object file implementation -----------------*- 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 declares the COFFObjectFile class.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_OBJECT_COFF_H
15#define LLVM_OBJECT_COFF_H
16
17#include "llvm/ADT/iterator_range.h"
18#include "llvm/BinaryFormat/COFF.h"
19#include "llvm/DebugInfo/CodeView/CVDebugRecord.h"
20#include "llvm/MC/SubtargetFeature.h"
21#include "llvm/Object/Binary.h"
22#include "llvm/Object/Error.h"
23#include "llvm/Object/ObjectFile.h"
24#include "llvm/Support/BinaryByteStream.h"
25#include "llvm/Support/ConvertUTF.h"
26#include "llvm/Support/Endian.h"
27#include "llvm/Support/ErrorHandling.h"
28#include <cassert>
29#include <cstddef>
30#include <cstdint>
31#include <system_error>
32
33namespace llvm {
34
35template <typename T> class ArrayRef;
36
37namespace object {
38
39class BaseRelocRef;
40class DelayImportDirectoryEntryRef;
41class ExportDirectoryEntryRef;
42class ImportDirectoryEntryRef;
43class ImportedSymbolRef;
44class ResourceSectionRef;
45
46using import_directory_iterator = content_iterator<ImportDirectoryEntryRef>;
47using delay_import_directory_iterator =
48 content_iterator<DelayImportDirectoryEntryRef>;
49using export_directory_iterator = content_iterator<ExportDirectoryEntryRef>;
50using imported_symbol_iterator = content_iterator<ImportedSymbolRef>;
51using base_reloc_iterator = content_iterator<BaseRelocRef>;
52
53/// The DOS compatible header at the front of all PE/COFF executables.
54struct dos_header {
55 char Magic[2];
56 support::ulittle16_t UsedBytesInTheLastPage;
57 support::ulittle16_t FileSizeInPages;
58 support::ulittle16_t NumberOfRelocationItems;
59 support::ulittle16_t HeaderSizeInParagraphs;
60 support::ulittle16_t MinimumExtraParagraphs;
61 support::ulittle16_t MaximumExtraParagraphs;
62 support::ulittle16_t InitialRelativeSS;
63 support::ulittle16_t InitialSP;
64 support::ulittle16_t Checksum;
65 support::ulittle16_t InitialIP;
66 support::ulittle16_t InitialRelativeCS;
67 support::ulittle16_t AddressOfRelocationTable;
68 support::ulittle16_t OverlayNumber;
69 support::ulittle16_t Reserved[4];
70 support::ulittle16_t OEMid;
71 support::ulittle16_t OEMinfo;
72 support::ulittle16_t Reserved2[10];
73 support::ulittle32_t AddressOfNewExeHeader;
74};
75
76struct coff_file_header {
77 support::ulittle16_t Machine;
78 support::ulittle16_t NumberOfSections;
79 support::ulittle32_t TimeDateStamp;
80 support::ulittle32_t PointerToSymbolTable;
81 support::ulittle32_t NumberOfSymbols;
82 support::ulittle16_t SizeOfOptionalHeader;
83 support::ulittle16_t Characteristics;
84
85 bool isImportLibrary() const { return NumberOfSections == 0xffff; }
86};
87
88struct coff_bigobj_file_header {
89 support::ulittle16_t Sig1;
90 support::ulittle16_t Sig2;
91 support::ulittle16_t Version;
92 support::ulittle16_t Machine;
93 support::ulittle32_t TimeDateStamp;
94 uint8_t UUID[16];
95 support::ulittle32_t unused1;
96 support::ulittle32_t unused2;
97 support::ulittle32_t unused3;
98 support::ulittle32_t unused4;
99 support::ulittle32_t NumberOfSections;
100 support::ulittle32_t PointerToSymbolTable;
101 support::ulittle32_t NumberOfSymbols;
102};
103
104/// The 32-bit PE header that follows the COFF header.
105struct pe32_header {
106 support::ulittle16_t Magic;
107 uint8_t MajorLinkerVersion;
108 uint8_t MinorLinkerVersion;
109 support::ulittle32_t SizeOfCode;
110 support::ulittle32_t SizeOfInitializedData;
111 support::ulittle32_t SizeOfUninitializedData;
112 support::ulittle32_t AddressOfEntryPoint;
113 support::ulittle32_t BaseOfCode;
114 support::ulittle32_t BaseOfData;
115 support::ulittle32_t ImageBase;
116 support::ulittle32_t SectionAlignment;
117 support::ulittle32_t FileAlignment;
118 support::ulittle16_t MajorOperatingSystemVersion;
119 support::ulittle16_t MinorOperatingSystemVersion;
120 support::ulittle16_t MajorImageVersion;
121 support::ulittle16_t MinorImageVersion;
122 support::ulittle16_t MajorSubsystemVersion;
123 support::ulittle16_t MinorSubsystemVersion;
124 support::ulittle32_t Win32VersionValue;
125 support::ulittle32_t SizeOfImage;
126 support::ulittle32_t SizeOfHeaders;
127 support::ulittle32_t CheckSum;
128 support::ulittle16_t Subsystem;
129 // FIXME: This should be DllCharacteristics.
130 support::ulittle16_t DLLCharacteristics;
131 support::ulittle32_t SizeOfStackReserve;
132 support::ulittle32_t SizeOfStackCommit;
133 support::ulittle32_t SizeOfHeapReserve;
134 support::ulittle32_t SizeOfHeapCommit;
135 support::ulittle32_t LoaderFlags;
136 // FIXME: This should be NumberOfRvaAndSizes.
137 support::ulittle32_t NumberOfRvaAndSize;
138};
139
140/// The 64-bit PE header that follows the COFF header.
141struct pe32plus_header {
142 support::ulittle16_t Magic;
143 uint8_t MajorLinkerVersion;
144 uint8_t MinorLinkerVersion;
145 support::ulittle32_t SizeOfCode;
146 support::ulittle32_t SizeOfInitializedData;
147 support::ulittle32_t SizeOfUninitializedData;
148 support::ulittle32_t AddressOfEntryPoint;
149 support::ulittle32_t BaseOfCode;
150 support::ulittle64_t ImageBase;
151 support::ulittle32_t SectionAlignment;
152 support::ulittle32_t FileAlignment;
153 support::ulittle16_t MajorOperatingSystemVersion;
154 support::ulittle16_t MinorOperatingSystemVersion;
155 support::ulittle16_t MajorImageVersion;
156 support::ulittle16_t MinorImageVersion;
157 support::ulittle16_t MajorSubsystemVersion;
158 support::ulittle16_t MinorSubsystemVersion;
159 support::ulittle32_t Win32VersionValue;
160 support::ulittle32_t SizeOfImage;
161 support::ulittle32_t SizeOfHeaders;
162 support::ulittle32_t CheckSum;
163 support::ulittle16_t Subsystem;
164 support::ulittle16_t DLLCharacteristics;
165 support::ulittle64_t SizeOfStackReserve;
166 support::ulittle64_t SizeOfStackCommit;
167 support::ulittle64_t SizeOfHeapReserve;
168 support::ulittle64_t SizeOfHeapCommit;
169 support::ulittle32_t LoaderFlags;
170 support::ulittle32_t NumberOfRvaAndSize;
171};
172
173struct data_directory {
174 support::ulittle32_t RelativeVirtualAddress;
175 support::ulittle32_t Size;
176};
177
178struct debug_directory {
179 support::ulittle32_t Characteristics;
180 support::ulittle32_t TimeDateStamp;
181 support::ulittle16_t MajorVersion;
182 support::ulittle16_t MinorVersion;
183 support::ulittle32_t Type;
184 support::ulittle32_t SizeOfData;
185 support::ulittle32_t AddressOfRawData;
186 support::ulittle32_t PointerToRawData;
187};
188
189template <typename IntTy>
190struct import_lookup_table_entry {
191 IntTy Data;
192
193 bool isOrdinal() const { return Data < 0; }
194
195 uint16_t getOrdinal() const {
196 assert(isOrdinal() && "ILT entry is not an ordinal!")(static_cast <bool> (isOrdinal() && "ILT entry is not an ordinal!"
) ? void (0) : __assert_fail ("isOrdinal() && \"ILT entry is not an ordinal!\""
, "/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Object/COFF.h"
, 196, __extension__ __PRETTY_FUNCTION__))
;
197 return Data & 0xFFFF;
198 }
199
200 uint32_t getHintNameRVA() const {
201 assert(!isOrdinal() && "ILT entry is not a Hint/Name RVA!")(static_cast <bool> (!isOrdinal() && "ILT entry is not a Hint/Name RVA!"
) ? void (0) : __assert_fail ("!isOrdinal() && \"ILT entry is not a Hint/Name RVA!\""
, "/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Object/COFF.h"
, 201, __extension__ __PRETTY_FUNCTION__))
;
202 return Data & 0xFFFFFFFF;
203 }
204};
205
206using import_lookup_table_entry32 =
207 import_lookup_table_entry<support::little32_t>;
208using import_lookup_table_entry64 =
209 import_lookup_table_entry<support::little64_t>;
210
211struct delay_import_directory_table_entry {
212 // dumpbin reports this field as "Characteristics" instead of "Attributes".
213 support::ulittle32_t Attributes;
214 support::ulittle32_t Name;
215 support::ulittle32_t ModuleHandle;
216 support::ulittle32_t DelayImportAddressTable;
217 support::ulittle32_t DelayImportNameTable;
218 support::ulittle32_t BoundDelayImportTable;
219 support::ulittle32_t UnloadDelayImportTable;
220 support::ulittle32_t TimeStamp;
221};
222
223struct export_directory_table_entry {
224 support::ulittle32_t ExportFlags;
225 support::ulittle32_t TimeDateStamp;
226 support::ulittle16_t MajorVersion;
227 support::ulittle16_t MinorVersion;
228 support::ulittle32_t NameRVA;
229 support::ulittle32_t OrdinalBase;
230 support::ulittle32_t AddressTableEntries;
231 support::ulittle32_t NumberOfNamePointers;
232 support::ulittle32_t ExportAddressTableRVA;
233 support::ulittle32_t NamePointerRVA;
234 support::ulittle32_t OrdinalTableRVA;
235};
236
237union export_address_table_entry {
238 support::ulittle32_t ExportRVA;
239 support::ulittle32_t ForwarderRVA;
240};
241
242using export_name_pointer_table_entry = support::ulittle32_t;
243using export_ordinal_table_entry = support::ulittle16_t;
244
245struct StringTableOffset {
246 support::ulittle32_t Zeroes;
247 support::ulittle32_t Offset;
248};
249
250template <typename SectionNumberType>
251struct coff_symbol {
252 union {
253 char ShortName[COFF::NameSize];
254 StringTableOffset Offset;
255 } Name;
256
257 support::ulittle32_t Value;
258 SectionNumberType SectionNumber;
259
260 support::ulittle16_t Type;
261
262 uint8_t StorageClass;
263 uint8_t NumberOfAuxSymbols;
264};
265
266using coff_symbol16 = coff_symbol<support::ulittle16_t>;
267using coff_symbol32 = coff_symbol<support::ulittle32_t>;
268
269// Contains only common parts of coff_symbol16 and coff_symbol32.
270struct coff_symbol_generic {
271 union {
272 char ShortName[COFF::NameSize];
273 StringTableOffset Offset;
274 } Name;
275 support::ulittle32_t Value;
276};
277
278struct coff_aux_section_definition;
279
280class COFFSymbolRef {
281public:
282 COFFSymbolRef() = default;
283 COFFSymbolRef(const coff_symbol16 *CS) : CS16(CS) {}
284 COFFSymbolRef(const coff_symbol32 *CS) : CS32(CS) {}
285
286 const void *getRawPtr() const {
287 return CS16 ? static_cast<const void *>(CS16) : CS32;
288 }
289
290 const coff_symbol_generic *getGeneric() const {
291 if (CS16)
292 return reinterpret_cast<const coff_symbol_generic *>(CS16);
293 return reinterpret_cast<const coff_symbol_generic *>(CS32);
294 }
295
296 friend bool operator<(COFFSymbolRef A, COFFSymbolRef B) {
297 return A.getRawPtr() < B.getRawPtr();
298 }
299
300 bool isBigObj() const {
301 if (CS16)
302 return false;
303 if (CS32)
304 return true;
305 llvm_unreachable("COFFSymbolRef points to nothing!")::llvm::llvm_unreachable_internal("COFFSymbolRef points to nothing!"
, "/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Object/COFF.h"
, 305)
;
306 }
307
308 const char *getShortName() const {
309 return CS16 ? CS16->Name.ShortName : CS32->Name.ShortName;
310 }
311
312 const StringTableOffset &getStringTableOffset() const {
313 assert(isSet() && "COFFSymbolRef points to nothing!")(static_cast <bool> (isSet() && "COFFSymbolRef points to nothing!"
) ? void (0) : __assert_fail ("isSet() && \"COFFSymbolRef points to nothing!\""
, "/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Object/COFF.h"
, 313, __extension__ __PRETTY_FUNCTION__))
;
314 return CS16 ? CS16->Name.Offset : CS32->Name.Offset;
315 }
316
317 uint32_t getValue() const { return CS16 ? CS16->Value : CS32->Value; }
318
319 int32_t getSectionNumber() const {
320 assert(isSet() && "COFFSymbolRef points to nothing!")(static_cast <bool> (isSet() && "COFFSymbolRef points to nothing!"
) ? void (0) : __assert_fail ("isSet() && \"COFFSymbolRef points to nothing!\""
, "/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Object/COFF.h"
, 320, __extension__ __PRETTY_FUNCTION__))
;
321 if (CS16) {
322 // Reserved sections are returned as negative numbers.
323 if (CS16->SectionNumber <= COFF::MaxNumberOfSections16)
324 return CS16->SectionNumber;
325 return static_cast<int16_t>(CS16->SectionNumber);
326 }
327 return static_cast<int32_t>(CS32->SectionNumber);
328 }
329
330 uint16_t getType() const {
331 assert(isSet() && "COFFSymbolRef points to nothing!")(static_cast <bool> (isSet() && "COFFSymbolRef points to nothing!"
) ? void (0) : __assert_fail ("isSet() && \"COFFSymbolRef points to nothing!\""
, "/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Object/COFF.h"
, 331, __extension__ __PRETTY_FUNCTION__))
;
332 return CS16 ? CS16->Type : CS32->Type;
333 }
334
335 uint8_t getStorageClass() const {
336 assert(isSet() && "COFFSymbolRef points to nothing!")(static_cast <bool> (isSet() && "COFFSymbolRef points to nothing!"
) ? void (0) : __assert_fail ("isSet() && \"COFFSymbolRef points to nothing!\""
, "/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Object/COFF.h"
, 336, __extension__ __PRETTY_FUNCTION__))
;
337 return CS16 ? CS16->StorageClass : CS32->StorageClass;
338 }
339
340 uint8_t getNumberOfAuxSymbols() const {
341 assert(isSet() && "COFFSymbolRef points to nothing!")(static_cast <bool> (isSet() && "COFFSymbolRef points to nothing!"
) ? void (0) : __assert_fail ("isSet() && \"COFFSymbolRef points to nothing!\""
, "/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Object/COFF.h"
, 341, __extension__ __PRETTY_FUNCTION__))
;
342 return CS16 ? CS16->NumberOfAuxSymbols : CS32->NumberOfAuxSymbols;
343 }
344
345 uint8_t getBaseType() const { return getType() & 0x0F; }
346
347 uint8_t getComplexType() const {
348 return (getType() & 0xF0) >> COFF::SCT_COMPLEX_TYPE_SHIFT;
349 }
350
351 template <typename T> const T *getAux() const {
352 return CS16 ? reinterpret_cast<const T *>(CS16 + 1)
353 : reinterpret_cast<const T *>(CS32 + 1);
354 }
355
356 const coff_aux_section_definition *getSectionDefinition() const {
357 if (!getNumberOfAuxSymbols() ||
358 getStorageClass() != COFF::IMAGE_SYM_CLASS_STATIC)
359 return nullptr;
360 return getAux<coff_aux_section_definition>();
361 }
362
363 bool isAbsolute() const {
364 return getSectionNumber() == -1;
365 }
366
367 bool isExternal() const {
368 return getStorageClass() == COFF::IMAGE_SYM_CLASS_EXTERNAL;
369 }
370
371 bool isCommon() const {
372 return isExternal() && getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED &&
373 getValue() != 0;
374 }
375
376 bool isUndefined() const {
377 return isExternal() && getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED &&
378 getValue() == 0;
379 }
380
381 bool isWeakExternal() const {
382 return getStorageClass() == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL;
383 }
384
385 bool isFunctionDefinition() const {
386 return isExternal() && getBaseType() == COFF::IMAGE_SYM_TYPE_NULL &&
387 getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION &&
388 !COFF::isReservedSectionNumber(getSectionNumber());
389 }
390
391 bool isFunctionLineInfo() const {
392 return getStorageClass() == COFF::IMAGE_SYM_CLASS_FUNCTION;
393 }
394
395 bool isAnyUndefined() const {
396 return isUndefined() || isWeakExternal();
397 }
398
399 bool isFileRecord() const {
400 return getStorageClass() == COFF::IMAGE_SYM_CLASS_FILE;
401 }
402
403 bool isSection() const {
404 return getStorageClass() == COFF::IMAGE_SYM_CLASS_SECTION;
405 }
406
407 bool isSectionDefinition() const {
408 // C++/CLI creates external ABS symbols for non-const appdomain globals.
409 // These are also followed by an auxiliary section definition.
410 bool isAppdomainGlobal =
411 getStorageClass() == COFF::IMAGE_SYM_CLASS_EXTERNAL &&
412 getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE;
413 bool isOrdinarySection = getStorageClass() == COFF::IMAGE_SYM_CLASS_STATIC;
414 if (!getNumberOfAuxSymbols())
415 return false;
416 return isAppdomainGlobal || isOrdinarySection;
417 }
418
419 bool isCLRToken() const {
420 return getStorageClass() == COFF::IMAGE_SYM_CLASS_CLR_TOKEN;
421 }
422
423private:
424 bool isSet() const { return CS16 || CS32; }
425
426 const coff_symbol16 *CS16 = nullptr;
427 const coff_symbol32 *CS32 = nullptr;
428};
429
430struct coff_section {
431 char Name[COFF::NameSize];
432 support::ulittle32_t VirtualSize;
433 support::ulittle32_t VirtualAddress;
434 support::ulittle32_t SizeOfRawData;
435 support::ulittle32_t PointerToRawData;
436 support::ulittle32_t PointerToRelocations;
437 support::ulittle32_t PointerToLinenumbers;
438 support::ulittle16_t NumberOfRelocations;
439 support::ulittle16_t NumberOfLinenumbers;
440 support::ulittle32_t Characteristics;
441
442 // Returns true if the actual number of relocations is stored in
443 // VirtualAddress field of the first relocation table entry.
444 bool hasExtendedRelocations() const {
445 return (Characteristics & COFF::IMAGE_SCN_LNK_NRELOC_OVFL) &&
446 NumberOfRelocations == UINT16_MAX(65535);
447 }
448
449 uint32_t getAlignment() const {
450 // The IMAGE_SCN_TYPE_NO_PAD bit is a legacy way of getting to
451 // IMAGE_SCN_ALIGN_1BYTES.
452 if (Characteristics & COFF::IMAGE_SCN_TYPE_NO_PAD)
453 return 1;
454
455 // Bit [20:24] contains section alignment. Both 0 and 1 mean alignment 1.
456 uint32_t Shift = (Characteristics >> 20) & 0xF;
457 if (Shift > 0)
458 return 1U << (Shift - 1);
459 return 1;
460 }
461};
462
463struct coff_relocation {
464 support::ulittle32_t VirtualAddress;
465 support::ulittle32_t SymbolTableIndex;
466 support::ulittle16_t Type;
467};
468
469struct coff_aux_function_definition {
470 support::ulittle32_t TagIndex;
471 support::ulittle32_t TotalSize;
472 support::ulittle32_t PointerToLinenumber;
473 support::ulittle32_t PointerToNextFunction;
474 char Unused1[2];
475};
476
477static_assert(sizeof(coff_aux_function_definition) == 18,
478 "auxiliary entry must be 18 bytes");
479
480struct coff_aux_bf_and_ef_symbol {
481 char Unused1[4];
482 support::ulittle16_t Linenumber;
483 char Unused2[6];
484 support::ulittle32_t PointerToNextFunction;
485 char Unused3[2];
486};
487
488static_assert(sizeof(coff_aux_bf_and_ef_symbol) == 18,
489 "auxiliary entry must be 18 bytes");
490
491struct coff_aux_weak_external {
492 support::ulittle32_t TagIndex;
493 support::ulittle32_t Characteristics;
494 char Unused1[10];
495};
496
497static_assert(sizeof(coff_aux_weak_external) == 18,
498 "auxiliary entry must be 18 bytes");
499
500struct coff_aux_section_definition {
501 support::ulittle32_t Length;
502 support::ulittle16_t NumberOfRelocations;
503 support::ulittle16_t NumberOfLinenumbers;
504 support::ulittle32_t CheckSum;
505 support::ulittle16_t NumberLowPart;
506 uint8_t Selection;
507 uint8_t Unused;
508 support::ulittle16_t NumberHighPart;
509 int32_t getNumber(bool IsBigObj) const {
510 uint32_t Number = static_cast<uint32_t>(NumberLowPart);
511 if (IsBigObj)
512 Number |= static_cast<uint32_t>(NumberHighPart) << 16;
513 return static_cast<int32_t>(Number);
514 }
515};
516
517static_assert(sizeof(coff_aux_section_definition) == 18,
518 "auxiliary entry must be 18 bytes");
519
520struct coff_aux_clr_token {
521 uint8_t AuxType;
522 uint8_t Reserved;
523 support::ulittle32_t SymbolTableIndex;
524 char MBZ[12];
525};
526
527static_assert(sizeof(coff_aux_clr_token) == 18,
528 "auxiliary entry must be 18 bytes");
529
530struct coff_import_header {
531 support::ulittle16_t Sig1;
532 support::ulittle16_t Sig2;
533 support::ulittle16_t Version;
534 support::ulittle16_t Machine;
535 support::ulittle32_t TimeDateStamp;
536 support::ulittle32_t SizeOfData;
537 support::ulittle16_t OrdinalHint;
538 support::ulittle16_t TypeInfo;
539
540 int getType() const { return TypeInfo & 0x3; }
541 int getNameType() const { return (TypeInfo >> 2) & 0x7; }
542};
543
544struct coff_import_directory_table_entry {
545 support::ulittle32_t ImportLookupTableRVA;
546 support::ulittle32_t TimeDateStamp;
547 support::ulittle32_t ForwarderChain;
548 support::ulittle32_t NameRVA;
549 support::ulittle32_t ImportAddressTableRVA;
550
551 bool isNull() const {
552 return ImportLookupTableRVA == 0 && TimeDateStamp == 0 &&
553 ForwarderChain == 0 && NameRVA == 0 && ImportAddressTableRVA == 0;
554 }
555};
556
557template <typename IntTy>
558struct coff_tls_directory {
559 IntTy StartAddressOfRawData;
560 IntTy EndAddressOfRawData;
561 IntTy AddressOfIndex;
562 IntTy AddressOfCallBacks;
563 support::ulittle32_t SizeOfZeroFill;
564 support::ulittle32_t Characteristics;
565
566 uint32_t getAlignment() const {
567 // Bit [20:24] contains section alignment.
568 uint32_t Shift = (Characteristics & 0x00F00000) >> 20;
569 if (Shift > 0)
570 return 1U << (Shift - 1);
571 return 0;
572 }
573};
574
575using coff_tls_directory32 = coff_tls_directory<support::little32_t>;
576using coff_tls_directory64 = coff_tls_directory<support::little64_t>;
577
578/// Bits in control flow guard flags as we understand them.
579enum class coff_guard_flags : uint32_t {
580 CFInstrumented = 0x00000100,
581 HasFidTable = 0x00000400,
582 ProtectDelayLoadIAT = 0x00001000,
583 DelayLoadIATSection = 0x00002000, // Delay load in separate section
584 HasLongJmpTable = 0x00010000,
585 FidTableHasFlags = 0x10000000, // Indicates that fid tables are 5 bytes
586};
587
588struct coff_load_config_code_integrity {
589 support::ulittle16_t Flags;
590 support::ulittle16_t Catalog;
591 support::ulittle32_t CatalogOffset;
592 support::ulittle32_t Reserved;
593};
594
595/// 32-bit load config (IMAGE_LOAD_CONFIG_DIRECTORY32)
596struct coff_load_configuration32 {
597 support::ulittle32_t Size;
598 support::ulittle32_t TimeDateStamp;
599 support::ulittle16_t MajorVersion;
600 support::ulittle16_t MinorVersion;
601 support::ulittle32_t GlobalFlagsClear;
602 support::ulittle32_t GlobalFlagsSet;
603 support::ulittle32_t CriticalSectionDefaultTimeout;
604 support::ulittle32_t DeCommitFreeBlockThreshold;
605 support::ulittle32_t DeCommitTotalFreeThreshold;
606 support::ulittle32_t LockPrefixTable;
607 support::ulittle32_t MaximumAllocationSize;
608 support::ulittle32_t VirtualMemoryThreshold;
609 support::ulittle32_t ProcessAffinityMask;
610 support::ulittle32_t ProcessHeapFlags;
611 support::ulittle16_t CSDVersion;
612 support::ulittle16_t DependentLoadFlags;
613 support::ulittle32_t EditList;
614 support::ulittle32_t SecurityCookie;
615 support::ulittle32_t SEHandlerTable;
616 support::ulittle32_t SEHandlerCount;
617
618 // Added in MSVC 2015 for /guard:cf.
619 support::ulittle32_t GuardCFCheckFunction;
620 support::ulittle32_t GuardCFCheckDispatch;
621 support::ulittle32_t GuardCFFunctionTable;
622 support::ulittle32_t GuardCFFunctionCount;
623 support::ulittle32_t GuardFlags; // coff_guard_flags
624
625 // Added in MSVC 2017
626 coff_load_config_code_integrity CodeIntegrity;
627 support::ulittle32_t GuardAddressTakenIatEntryTable;
628 support::ulittle32_t GuardAddressTakenIatEntryCount;
629 support::ulittle32_t GuardLongJumpTargetTable;
630 support::ulittle32_t GuardLongJumpTargetCount;
631 support::ulittle32_t DynamicValueRelocTable;
632 support::ulittle32_t CHPEMetadataPointer;
633 support::ulittle32_t GuardRFFailureRoutine;
634 support::ulittle32_t GuardRFFailureRoutineFunctionPointer;
635 support::ulittle32_t DynamicValueRelocTableOffset;
636 support::ulittle16_t DynamicValueRelocTableSection;
637 support::ulittle16_t Reserved2;
638 support::ulittle32_t GuardRFVerifyStackPointerFunctionPointer;
639 support::ulittle32_t HotPatchTableOffset;
640};
641
642/// 64-bit load config (IMAGE_LOAD_CONFIG_DIRECTORY64)
643struct coff_load_configuration64 {
644 support::ulittle32_t Size;
645 support::ulittle32_t TimeDateStamp;
646 support::ulittle16_t MajorVersion;
647 support::ulittle16_t MinorVersion;
648 support::ulittle32_t GlobalFlagsClear;
649 support::ulittle32_t GlobalFlagsSet;
650 support::ulittle32_t CriticalSectionDefaultTimeout;
651 support::ulittle64_t DeCommitFreeBlockThreshold;
652 support::ulittle64_t DeCommitTotalFreeThreshold;
653 support::ulittle64_t LockPrefixTable;
654 support::ulittle64_t MaximumAllocationSize;
655 support::ulittle64_t VirtualMemoryThreshold;
656 support::ulittle64_t ProcessAffinityMask;
657 support::ulittle32_t ProcessHeapFlags;
658 support::ulittle16_t CSDVersion;
659 support::ulittle16_t DependentLoadFlags;
660 support::ulittle64_t EditList;
661 support::ulittle64_t SecurityCookie;
662 support::ulittle64_t SEHandlerTable;
663 support::ulittle64_t SEHandlerCount;
664
665 // Added in MSVC 2015 for /guard:cf.
666 support::ulittle64_t GuardCFCheckFunction;
667 support::ulittle64_t GuardCFCheckDispatch;
668 support::ulittle64_t GuardCFFunctionTable;
669 support::ulittle64_t GuardCFFunctionCount;
670 support::ulittle32_t GuardFlags;
671
672 // Added in MSVC 2017
673 coff_load_config_code_integrity CodeIntegrity;
674 support::ulittle64_t GuardAddressTakenIatEntryTable;
675 support::ulittle64_t GuardAddressTakenIatEntryCount;
676 support::ulittle64_t GuardLongJumpTargetTable;
677 support::ulittle64_t GuardLongJumpTargetCount;
678 support::ulittle64_t DynamicValueRelocTable;
679 support::ulittle64_t CHPEMetadataPointer;
680 support::ulittle64_t GuardRFFailureRoutine;
681 support::ulittle64_t GuardRFFailureRoutineFunctionPointer;
682 support::ulittle32_t DynamicValueRelocTableOffset;
683 support::ulittle16_t DynamicValueRelocTableSection;
684 support::ulittle16_t Reserved2;
685 support::ulittle64_t GuardRFVerifyStackPointerFunctionPointer;
686 support::ulittle32_t HotPatchTableOffset;
687};
688
689struct coff_runtime_function_x64 {
690 support::ulittle32_t BeginAddress;
691 support::ulittle32_t EndAddress;
692 support::ulittle32_t UnwindInformation;
693};
694
695struct coff_base_reloc_block_header {
696 support::ulittle32_t PageRVA;
697 support::ulittle32_t BlockSize;
698};
699
700struct coff_base_reloc_block_entry {
701 support::ulittle16_t Data;
702
703 int getType() const { return Data >> 12; }
704 int getOffset() const { return Data & ((1 << 12) - 1); }
705};
706
707struct coff_resource_dir_entry {
708 union {
709 support::ulittle32_t NameOffset;
710 support::ulittle32_t ID;
711 uint32_t getNameOffset() const {
712 return maskTrailingOnes<uint32_t>(31) & NameOffset;
713 }
714 // Even though the PE/COFF spec doesn't mention this, the high bit of a name
715 // offset is set.
716 void setNameOffset(uint32_t Offset) { NameOffset = Offset | (1 << 31); }
717 } Identifier;
718 union {
719 support::ulittle32_t DataEntryOffset;
720 support::ulittle32_t SubdirOffset;
721
722 bool isSubDir() const { return SubdirOffset >> 31; }
723 uint32_t value() const {
724 return maskTrailingOnes<uint32_t>(31) & SubdirOffset;
725 }
726
727 } Offset;
728};
729
730struct coff_resource_data_entry {
731 support::ulittle32_t DataRVA;
732 support::ulittle32_t DataSize;
733 support::ulittle32_t Codepage;
734 support::ulittle32_t Reserved;
735};
736
737struct coff_resource_dir_table {
738 support::ulittle32_t Characteristics;
739 support::ulittle32_t TimeDateStamp;
740 support::ulittle16_t MajorVersion;
741 support::ulittle16_t MinorVersion;
742 support::ulittle16_t NumberOfNameEntries;
743 support::ulittle16_t NumberOfIDEntries;
744};
745
746struct debug_h_header {
747 support::ulittle32_t Magic;
748 support::ulittle16_t Version;
749 support::ulittle16_t HashAlgorithm;
750};
751
752class COFFObjectFile : public ObjectFile {
753private:
754 friend class ImportDirectoryEntryRef;
755 friend class ExportDirectoryEntryRef;
756 const coff_file_header *COFFHeader;
757 const coff_bigobj_file_header *COFFBigObjHeader;
758 const pe32_header *PE32Header;
759 const pe32plus_header *PE32PlusHeader;
760 const data_directory *DataDirectory;
761 const coff_section *SectionTable;
762 const coff_symbol16 *SymbolTable16;
763 const coff_symbol32 *SymbolTable32;
764 const char *StringTable;
765 uint32_t StringTableSize;
766 const coff_import_directory_table_entry *ImportDirectory;
767 const delay_import_directory_table_entry *DelayImportDirectory;
768 uint32_t NumberOfDelayImportDirectory;
769 const export_directory_table_entry *ExportDirectory;
770 const coff_base_reloc_block_header *BaseRelocHeader;
771 const coff_base_reloc_block_header *BaseRelocEnd;
772 const debug_directory *DebugDirectoryBegin;
773 const debug_directory *DebugDirectoryEnd;
774 // Either coff_load_configuration32 or coff_load_configuration64.
775 const void *LoadConfig = nullptr;
776
777 std::error_code getString(uint32_t offset, StringRef &Res) const;
778
779 template <typename coff_symbol_type>
780 const coff_symbol_type *toSymb(DataRefImpl Symb) const;
781 const coff_section *toSec(DataRefImpl Sec) const;
782 const coff_relocation *toRel(DataRefImpl Rel) const;
783
784 std::error_code initSymbolTablePtr();
785 std::error_code initImportTablePtr();
786 std::error_code initDelayImportTablePtr();
787 std::error_code initExportTablePtr();
788 std::error_code initBaseRelocPtr();
789 std::error_code initDebugDirectoryPtr();
790 std::error_code initLoadConfigPtr();
791
792public:
793 uintptr_t getSymbolTable() const {
794 if (SymbolTable16)
795 return reinterpret_cast<uintptr_t>(SymbolTable16);
796 if (SymbolTable32)
797 return reinterpret_cast<uintptr_t>(SymbolTable32);
798 return uintptr_t(0);
799 }
800
801 uint16_t getMachine() const {
802 if (COFFHeader)
803 return COFFHeader->Machine;
804 if (COFFBigObjHeader)
805 return COFFBigObjHeader->Machine;
806 llvm_unreachable("no COFF header!")::llvm::llvm_unreachable_internal("no COFF header!", "/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Object/COFF.h"
, 806)
;
807 }
808
809 uint16_t getSizeOfOptionalHeader() const {
810 if (COFFHeader)
811 return COFFHeader->isImportLibrary() ? 0
812 : COFFHeader->SizeOfOptionalHeader;
813 // bigobj doesn't have this field.
814 if (COFFBigObjHeader)
815 return 0;
816 llvm_unreachable("no COFF header!")::llvm::llvm_unreachable_internal("no COFF header!", "/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Object/COFF.h"
, 816)
;
817 }
818
819 uint16_t getCharacteristics() const {
820 if (COFFHeader)
821 return COFFHeader->isImportLibrary() ? 0 : COFFHeader->Characteristics;
822 // bigobj doesn't have characteristics to speak of,
823 // editbin will silently lie to you if you attempt to set any.
824 if (COFFBigObjHeader)
825 return 0;
826 llvm_unreachable("no COFF header!")::llvm::llvm_unreachable_internal("no COFF header!", "/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Object/COFF.h"
, 826)
;
827 }
828
829 uint32_t getTimeDateStamp() const {
830 if (COFFHeader)
831 return COFFHeader->TimeDateStamp;
832 if (COFFBigObjHeader)
833 return COFFBigObjHeader->TimeDateStamp;
834 llvm_unreachable("no COFF header!")::llvm::llvm_unreachable_internal("no COFF header!", "/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Object/COFF.h"
, 834)
;
835 }
836
837 uint32_t getNumberOfSections() const {
838 if (COFFHeader)
839 return COFFHeader->isImportLibrary() ? 0 : COFFHeader->NumberOfSections;
840 if (COFFBigObjHeader)
841 return COFFBigObjHeader->NumberOfSections;
842 llvm_unreachable("no COFF header!")::llvm::llvm_unreachable_internal("no COFF header!", "/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Object/COFF.h"
, 842)
;
843 }
844
845 uint32_t getPointerToSymbolTable() const {
846 if (COFFHeader)
847 return COFFHeader->isImportLibrary() ? 0
848 : COFFHeader->PointerToSymbolTable;
849 if (COFFBigObjHeader)
850 return COFFBigObjHeader->PointerToSymbolTable;
851 llvm_unreachable("no COFF header!")::llvm::llvm_unreachable_internal("no COFF header!", "/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Object/COFF.h"
, 851)
;
852 }
853
854 uint32_t getRawNumberOfSymbols() const {
855 if (COFFHeader)
856 return COFFHeader->isImportLibrary() ? 0 : COFFHeader->NumberOfSymbols;
857 if (COFFBigObjHeader)
858 return COFFBigObjHeader->NumberOfSymbols;
859 llvm_unreachable("no COFF header!")::llvm::llvm_unreachable_internal("no COFF header!", "/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Object/COFF.h"
, 859)
;
860 }
861
862 uint32_t getNumberOfSymbols() const {
863 if (!SymbolTable16 && !SymbolTable32)
864 return 0;
865 return getRawNumberOfSymbols();
866 }
867
868 const coff_load_configuration32 *getLoadConfig32() const {
869 assert(!is64())(static_cast <bool> (!is64()) ? void (0) : __assert_fail
("!is64()", "/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Object/COFF.h"
, 869, __extension__ __PRETTY_FUNCTION__))
;
870 return reinterpret_cast<const coff_load_configuration32 *>(LoadConfig);
871 }
872
873 const coff_load_configuration64 *getLoadConfig64() const {
874 assert(is64())(static_cast <bool> (is64()) ? void (0) : __assert_fail
("is64()", "/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Object/COFF.h"
, 874, __extension__ __PRETTY_FUNCTION__))
;
875 return reinterpret_cast<const coff_load_configuration64 *>(LoadConfig);
876 }
877
878protected:
879 void moveSymbolNext(DataRefImpl &Symb) const override;
880 Expected<StringRef> getSymbolName(DataRefImpl Symb) const override;
881 Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override;
882 uint32_t getSymbolAlignment(DataRefImpl Symb) const override;
883 uint64_t getSymbolValueImpl(DataRefImpl Symb) const override;
884 uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override;
885 uint32_t getSymbolFlags(DataRefImpl Symb) const override;
886 Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override;
887 Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override;
888 void moveSectionNext(DataRefImpl &Sec) const override;
889 std::error_code getSectionName(DataRefImpl Sec,
890 StringRef &Res) const override;
891 uint64_t getSectionAddress(DataRefImpl Sec) const override;
892 uint64_t getSectionIndex(DataRefImpl Sec) const override;
893 uint64_t getSectionSize(DataRefImpl Sec) const override;
894 std::error_code getSectionContents(DataRefImpl Sec,
895 StringRef &Res) const override;
896 uint64_t getSectionAlignment(DataRefImpl Sec) const override;
897 bool isSectionCompressed(DataRefImpl Sec) const override;
898 bool isSectionText(DataRefImpl Sec) const override;
899 bool isSectionData(DataRefImpl Sec) const override;
900 bool isSectionBSS(DataRefImpl Sec) const override;
901 bool isSectionVirtual(DataRefImpl Sec) const override;
902 relocation_iterator section_rel_begin(DataRefImpl Sec) const override;
903 relocation_iterator section_rel_end(DataRefImpl Sec) const override;
904
905 void moveRelocationNext(DataRefImpl &Rel) const override;
906 uint64_t getRelocationOffset(DataRefImpl Rel) const override;
907 symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override;
908 uint64_t getRelocationType(DataRefImpl Rel) const override;
909 void getRelocationTypeName(DataRefImpl Rel,
910 SmallVectorImpl<char> &Result) const override;
911
912public:
913 COFFObjectFile(MemoryBufferRef Object, std::error_code &EC);
914
915 basic_symbol_iterator symbol_begin() const override;
916 basic_symbol_iterator symbol_end() const override;
917 section_iterator section_begin() const override;
918 section_iterator section_end() const override;
919
920 const coff_section *getCOFFSection(const SectionRef &Section) const;
921 COFFSymbolRef getCOFFSymbol(const DataRefImpl &Ref) const;
922 COFFSymbolRef getCOFFSymbol(const SymbolRef &Symbol) const;
923 const coff_relocation *getCOFFRelocation(const RelocationRef &Reloc) const;
924 unsigned getSectionID(SectionRef Sec) const;
925 unsigned getSymbolSectionID(SymbolRef Sym) const;
926
927 uint8_t getBytesInAddress() const override;
928 StringRef getFileFormatName() const override;
929 Triple::ArchType getArch() const override;
930 SubtargetFeatures getFeatures() const override { return SubtargetFeatures(); }
931
932 import_directory_iterator import_directory_begin() const;
933 import_directory_iterator import_directory_end() const;
934 delay_import_directory_iterator delay_import_directory_begin() const;
935 delay_import_directory_iterator delay_import_directory_end() const;
936 export_directory_iterator export_directory_begin() const;
937 export_directory_iterator export_directory_end() const;
938 base_reloc_iterator base_reloc_begin() const;
939 base_reloc_iterator base_reloc_end() const;
940 const debug_directory *debug_directory_begin() const {
941 return DebugDirectoryBegin;
942 }
943 const debug_directory *debug_directory_end() const {
944 return DebugDirectoryEnd;
945 }
946
947 iterator_range<import_directory_iterator> import_directories() const;
948 iterator_range<delay_import_directory_iterator>
949 delay_import_directories() const;
950 iterator_range<export_directory_iterator> export_directories() const;
951 iterator_range<base_reloc_iterator> base_relocs() const;
952 iterator_range<const debug_directory *> debug_directories() const {
953 return make_range(debug_directory_begin(), debug_directory_end());
954 }
955
956 const dos_header *getDOSHeader() const {
957 if (!PE32Header && !PE32PlusHeader)
958 return nullptr;
959 return reinterpret_cast<const dos_header *>(base());
960 }
961 std::error_code getPE32Header(const pe32_header *&Res) const;
962 std::error_code getPE32PlusHeader(const pe32plus_header *&Res) const;
963 std::error_code getDataDirectory(uint32_t index,
964 const data_directory *&Res) const;
965 std::error_code getSection(int32_t index, const coff_section *&Res) const;
966
967 template <typename coff_symbol_type>
968 std::error_code getSymbol(uint32_t Index,
969 const coff_symbol_type *&Res) const {
970 if (Index >= getNumberOfSymbols())
971 return object_error::parse_failed;
972
973 Res = reinterpret_cast<coff_symbol_type *>(getSymbolTable()) + Index;
974 return std::error_code();
975 }
976 Expected<COFFSymbolRef> getSymbol(uint32_t index) const {
977 if (SymbolTable16) {
24
Assuming the condition is false
25
Taking false branch
978 const coff_symbol16 *Symb = nullptr;
979 if (std::error_code EC = getSymbol(index, Symb))
980 return errorCodeToError(EC);
981 return COFFSymbolRef(Symb);
982 }
983 if (SymbolTable32) {
26
Assuming the condition is false
27
Taking false branch
984 const coff_symbol32 *Symb = nullptr;
985 if (std::error_code EC = getSymbol(index, Symb))
986 return errorCodeToError(EC);
987 return COFFSymbolRef(Symb);
988 }
989 return errorCodeToError(object_error::parse_failed);
28
Calling constructor for 'error_code'
33
Returning from constructor for 'error_code'
990 }
991
992 template <typename T>
993 std::error_code getAuxSymbol(uint32_t index, const T *&Res) const {
994 Expected<COFFSymbolRef> S = getSymbol(index);
23
Calling 'COFFObjectFile::getSymbol'
34
Returning from 'COFFObjectFile::getSymbol'
35
Calling move constructor for 'Expected'
50
Returning from move constructor for 'Expected'
995 if (Error E = S.takeError())
51
Calling 'Expected::takeError'
56
Returning from 'Expected::takeError'
57
Calling move constructor for 'Error'
81
Returning from move constructor for 'Error'
82
Calling 'Error::operator bool'
91
Returning from 'Error::operator bool'
92
Taking true branch
996 return errorToErrorCode(std::move(E));
93
Calling 'move'
94
Returning from 'move'
95
Calling '~Error'
102
Returning from '~Error'
103
Calling '~Expected'
111
Returning from '~Expected'
997 Res = reinterpret_cast<const T *>(S->getRawPtr());
998 return std::error_code();
999 }
1000
1001 std::error_code getSymbolName(COFFSymbolRef Symbol, StringRef &Res) const;
1002 std::error_code getSymbolName(const coff_symbol_generic *Symbol,
1003 StringRef &Res) const;
1004
1005 ArrayRef<uint8_t> getSymbolAuxData(COFFSymbolRef Symbol) const;
1006
1007 size_t getSymbolTableEntrySize() const {
1008 if (COFFHeader)
1009 return sizeof(coff_symbol16);
1010 if (COFFBigObjHeader)
1011 return sizeof(coff_symbol32);
1012 llvm_unreachable("null symbol table pointer!")::llvm::llvm_unreachable_internal("null symbol table pointer!"
, "/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Object/COFF.h"
, 1012)
;
1013 }
1014
1015 iterator_range<const coff_relocation *>
1016 getRelocations(const coff_section *Sec) const;
1017
1018 std::error_code getSectionName(const coff_section *Sec, StringRef &Res) const;
1019 uint64_t getSectionSize(const coff_section *Sec) const;
1020 std::error_code getSectionContents(const coff_section *Sec,
1021 ArrayRef<uint8_t> &Res) const;
1022
1023 uint64_t getImageBase() const;
1024 std::error_code getVaPtr(uint64_t VA, uintptr_t &Res) const;
1025 std::error_code getRvaPtr(uint32_t Rva, uintptr_t &Res) const;
1026
1027 /// Given an RVA base and size, returns a valid array of bytes or an error
1028 /// code if the RVA and size is not contained completely within a valid
1029 /// section.
1030 std::error_code getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size,
1031 ArrayRef<uint8_t> &Contents) const;
1032
1033 std::error_code getHintName(uint32_t Rva, uint16_t &Hint,
1034 StringRef &Name) const;
1035
1036 /// Get PDB information out of a codeview debug directory entry.
1037 std::error_code getDebugPDBInfo(const debug_directory *DebugDir,
1038 const codeview::DebugInfo *&Info,
1039 StringRef &PDBFileName) const;
1040
1041 /// Get PDB information from an executable. If the information is not present,
1042 /// Info will be set to nullptr and PDBFileName will be empty. An error is
1043 /// returned only on corrupt object files. Convenience accessor that can be
1044 /// used if the debug directory is not already handy.
1045 std::error_code getDebugPDBInfo(const codeview::DebugInfo *&Info,
1046 StringRef &PDBFileName) const;
1047
1048 bool isRelocatableObject() const override;
1049 bool is64() const { return PE32PlusHeader; }
1050
1051 static bool classof(const Binary *v) { return v->isCOFF(); }
1052};
1053
1054// The iterator for the import directory table.
1055class ImportDirectoryEntryRef {
1056public:
1057 ImportDirectoryEntryRef() = default;
1058 ImportDirectoryEntryRef(const coff_import_directory_table_entry *Table,
1059 uint32_t I, const COFFObjectFile *Owner)
1060 : ImportTable(Table), Index(I), OwningObject(Owner) {}
1061
1062 bool operator==(const ImportDirectoryEntryRef &Other) const;
1063 void moveNext();
1064
1065 imported_symbol_iterator imported_symbol_begin() const;
1066 imported_symbol_iterator imported_symbol_end() const;
1067 iterator_range<imported_symbol_iterator> imported_symbols() const;
1068
1069 imported_symbol_iterator lookup_table_begin() const;
1070 imported_symbol_iterator lookup_table_end() const;
1071 iterator_range<imported_symbol_iterator> lookup_table_symbols() const;
1072
1073 std::error_code getName(StringRef &Result) const;
1074 std::error_code getImportLookupTableRVA(uint32_t &Result) const;
1075 std::error_code getImportAddressTableRVA(uint32_t &Result) const;
1076
1077 std::error_code
1078 getImportTableEntry(const coff_import_directory_table_entry *&Result) const;
1079
1080private:
1081 const coff_import_directory_table_entry *ImportTable;
1082 uint32_t Index;
1083 const COFFObjectFile *OwningObject = nullptr;
1084};
1085
1086class DelayImportDirectoryEntryRef {
1087public:
1088 DelayImportDirectoryEntryRef() = default;
1089 DelayImportDirectoryEntryRef(const delay_import_directory_table_entry *T,
1090 uint32_t I, const COFFObjectFile *Owner)
1091 : Table(T), Index(I), OwningObject(Owner) {}
1092
1093 bool operator==(const DelayImportDirectoryEntryRef &Other) const;
1094 void moveNext();
1095
1096 imported_symbol_iterator imported_symbol_begin() const;
1097 imported_symbol_iterator imported_symbol_end() const;
1098 iterator_range<imported_symbol_iterator> imported_symbols() const;
1099
1100 std::error_code getName(StringRef &Result) const;
1101 std::error_code getDelayImportTable(
1102 const delay_import_directory_table_entry *&Result) const;
1103 std::error_code getImportAddress(int AddrIndex, uint64_t &Result) const;
1104
1105private:
1106 const delay_import_directory_table_entry *Table;
1107 uint32_t Index;
1108 const COFFObjectFile *OwningObject = nullptr;
1109};
1110
1111// The iterator for the export directory table entry.
1112class ExportDirectoryEntryRef {
1113public:
1114 ExportDirectoryEntryRef() = default;
1115 ExportDirectoryEntryRef(const export_directory_table_entry *Table, uint32_t I,
1116 const COFFObjectFile *Owner)
1117 : ExportTable(Table), Index(I), OwningObject(Owner) {}
1118
1119 bool operator==(const ExportDirectoryEntryRef &Other) const;
1120 void moveNext();
1121
1122 std::error_code getDllName(StringRef &Result) const;
1123 std::error_code getOrdinalBase(uint32_t &Result) const;
1124 std::error_code getOrdinal(uint32_t &Result) const;
1125 std::error_code getExportRVA(uint32_t &Result) const;
1126 std::error_code getSymbolName(StringRef &Result) const;
1127
1128 std::error_code isForwarder(bool &Result) const;
1129 std::error_code getForwardTo(StringRef &Result) const;
1130
1131private:
1132 const export_directory_table_entry *ExportTable;
1133 uint32_t Index;
1134 const COFFObjectFile *OwningObject = nullptr;
1135};
1136
1137class ImportedSymbolRef {
1138public:
1139 ImportedSymbolRef() = default;
1140 ImportedSymbolRef(const import_lookup_table_entry32 *Entry, uint32_t I,
1141 const COFFObjectFile *Owner)
1142 : Entry32(Entry), Entry64(nullptr), Index(I), OwningObject(Owner) {}
1143 ImportedSymbolRef(const import_lookup_table_entry64 *Entry, uint32_t I,
1144 const COFFObjectFile *Owner)
1145 : Entry32(nullptr), Entry64(Entry), Index(I), OwningObject(Owner) {}
1146
1147 bool operator==(const ImportedSymbolRef &Other) const;
1148 void moveNext();
1149
1150 std::error_code getSymbolName(StringRef &Result) const;
1151 std::error_code isOrdinal(bool &Result) const;
1152 std::error_code getOrdinal(uint16_t &Result) const;
1153 std::error_code getHintNameRVA(uint32_t &Result) const;
1154
1155private:
1156 const import_lookup_table_entry32 *Entry32;
1157 const import_lookup_table_entry64 *Entry64;
1158 uint32_t Index;
1159 const COFFObjectFile *OwningObject = nullptr;
1160};
1161
1162class BaseRelocRef {
1163public:
1164 BaseRelocRef() = default;
1165 BaseRelocRef(const coff_base_reloc_block_header *Header,
1166 const COFFObjectFile *Owner)
1167 : Header(Header), Index(0) {}
1168
1169 bool operator==(const BaseRelocRef &Other) const;
1170 void moveNext();
1171
1172 std::error_code getType(uint8_t &Type) const;
1173 std::error_code getRVA(uint32_t &Result) const;
1174
1175private:
1176 const coff_base_reloc_block_header *Header;
1177 uint32_t Index;
1178};
1179
1180class ResourceSectionRef {
1181public:
1182 ResourceSectionRef() = default;
1183 explicit ResourceSectionRef(StringRef Ref) : BBS(Ref, support::little) {}
1184
1185 Expected<ArrayRef<UTF16>>
1186 getEntryNameString(const coff_resource_dir_entry &Entry);
1187 Expected<const coff_resource_dir_table &>
1188 getEntrySubDir(const coff_resource_dir_entry &Entry);
1189 Expected<const coff_resource_dir_table &> getBaseTable();
1190
1191private:
1192 BinaryByteStream BBS;
1193
1194 Expected<const coff_resource_dir_table &> getTableAtOffset(uint32_t Offset);
1195 Expected<ArrayRef<UTF16>> getDirStringAtOffset(uint32_t Offset);
1196};
1197
1198// Corresponds to `_FPO_DATA` structure in the PE/COFF spec.
1199struct FpoData {
1200 support::ulittle32_t Offset; // ulOffStart: Offset 1st byte of function code
1201 support::ulittle32_t Size; // cbProcSize: # bytes in function
1202 support::ulittle32_t NumLocals; // cdwLocals: # bytes in locals/4
1203 support::ulittle16_t NumParams; // cdwParams: # bytes in params/4
1204 support::ulittle16_t Attributes;
1205
1206 // cbProlog: # bytes in prolog
1207 int getPrologSize() const { return Attributes & 0xF; }
1208
1209 // cbRegs: # regs saved
1210 int getNumSavedRegs() const { return (Attributes >> 8) & 0x7; }
1211
1212 // fHasSEH: true if seh is func
1213 bool hasSEH() const { return (Attributes >> 9) & 1; }
1214
1215 // fUseBP: true if EBP has been allocated
1216 bool useBP() const { return (Attributes >> 10) & 1; }
1217
1218 // cbFrame: frame pointer
1219 int getFP() const { return Attributes >> 14; }
1220};
1221
1222} // end namespace object
1223
1224} // end namespace llvm
1225
1226#endif // LLVM_OBJECT_COFF_H

/usr/lib/gcc/x86_64-linux-gnu/7.2.0/../../../../include/c++/7.2.0/system_error

1// <system_error> -*- C++ -*-
2
3// Copyright (C) 2007-2017 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25/** @file include/system_error
26 * This is a Standard C++ Library header.
27 */
28
29#ifndef _GLIBCXX_SYSTEM_ERROR1
30#define _GLIBCXX_SYSTEM_ERROR1 1
31
32#pragma GCC system_header
33
34#if __cplusplus201103L < 201103L
35# include <bits/c++0x_warning.h>
36#else
37
38#include <bits/c++config.h>
39#include <bits/error_constants.h>
40#include <iosfwd>
41#include <stdexcept>
42
43namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
44{
45_GLIBCXX_BEGIN_NAMESPACE_VERSION
46
47 class error_code;
48 class error_condition;
49 class system_error;
50
51 /// is_error_code_enum
52 template<typename _Tp>
53 struct is_error_code_enum : public false_type { };
54
55 /// is_error_condition_enum
56 template<typename _Tp>
57 struct is_error_condition_enum : public false_type { };
58
59 template<>
60 struct is_error_condition_enum<errc>
61 : public true_type { };
62
63#if __cplusplus201103L > 201402L
64 template <typename _Tp>
65 inline constexpr bool is_error_code_enum_v =
66 is_error_code_enum<_Tp>::value;
67 template <typename _Tp>
68 inline constexpr bool is_error_condition_enum_v =
69 is_error_condition_enum<_Tp>::value;
70#endif // C++17
71 inline namespace _V2 {
72
73 /// error_category
74 class error_category
75 {
76 public:
77 constexpr error_category() noexcept = default;
78
79 virtual ~error_category();
80
81 error_category(const error_category&) = delete;
82 error_category& operator=(const error_category&) = delete;
83
84 virtual const char*
85 name() const noexcept = 0;
86
87 // We need two different virtual functions here, one returning a
88 // COW string and one returning an SSO string. Their positions in the
89 // vtable must be consistent for dynamic dispatch to work, but which one
90 // the name "message()" finds depends on which ABI the caller is using.
91#if _GLIBCXX_USE_CXX11_ABI1
92 private:
93 _GLIBCXX_DEFAULT_ABI_TAG__attribute ((__abi_tag__ ("cxx11")))
94 virtual __cow_string
95 _M_message(int) const;
96
97 public:
98 _GLIBCXX_DEFAULT_ABI_TAG__attribute ((__abi_tag__ ("cxx11")))
99 virtual string
100 message(int) const = 0;
101#else
102 virtual string
103 message(int) const = 0;
104
105 private:
106 virtual __sso_string
107 _M_message(int) const;
108#endif
109
110 public:
111 virtual error_condition
112 default_error_condition(int __i) const noexcept;
113
114 virtual bool
115 equivalent(int __i, const error_condition& __cond) const noexcept;
116
117 virtual bool
118 equivalent(const error_code& __code, int __i) const noexcept;
119
120 bool
121 operator<(const error_category& __other) const noexcept
122 { return less<const error_category*>()(this, &__other); }
123
124 bool
125 operator==(const error_category& __other) const noexcept
126 { return this == &__other; }
127
128 bool
129 operator!=(const error_category& __other) const noexcept
130 { return this != &__other; }
131 };
132
133 // DR 890.
134 _GLIBCXX_CONST__attribute__ ((__const__)) const error_category& system_category() noexcept;
135 _GLIBCXX_CONST__attribute__ ((__const__)) const error_category& generic_category() noexcept;
136
137 } // end inline namespace
138
139 error_code make_error_code(errc) noexcept;
140
141 template<typename _Tp>
142 struct hash;
143
144 /// error_code
145 // Implementation-specific error identification
146 struct error_code
147 {
148 error_code() noexcept
149 : _M_value(0), _M_cat(&system_category()) { }
150
151 error_code(int __v, const error_category& __cat) noexcept
152 : _M_value(__v), _M_cat(&__cat) { }
153
154 template<typename _ErrorCodeEnum, typename = typename
155 enable_if<is_error_code_enum<_ErrorCodeEnum>::value>::type>
156 error_code(_ErrorCodeEnum __e) noexcept
157 { *this = make_error_code(__e); }
29
Calling 'make_error_code'
32
Returning from 'make_error_code'
158
159 void
160 assign(int __v, const error_category& __cat) noexcept
161 {
162 _M_value = __v;
163 _M_cat = &__cat;
164 }
165
166 void
167 clear() noexcept
168 { assign(0, system_category()); }
169
170 // DR 804.
171 template<typename _ErrorCodeEnum>
172 typename enable_if<is_error_code_enum<_ErrorCodeEnum>::value,
173 error_code&>::type
174 operator=(_ErrorCodeEnum __e) noexcept
175 { return *this = make_error_code(__e); }
176
177 int
178 value() const noexcept { return _M_value; }
179
180 const error_category&
181 category() const noexcept { return *_M_cat; }
182
183 error_condition
184 default_error_condition() const noexcept;
185
186 _GLIBCXX_DEFAULT_ABI_TAG__attribute ((__abi_tag__ ("cxx11")))
187 string
188 message() const
189 { return category().message(value()); }
190
191 explicit operator bool() const noexcept
192 { return _M_value != 0; }
193
194 // DR 804.
195 private:
196 friend class hash<error_code>;
197
198 int _M_value;
199 const error_category* _M_cat;
200 };
201
202 // 19.4.2.6 non-member functions
203 inline error_code
204 make_error_code(errc __e) noexcept
205 { return error_code(static_cast<int>(__e), generic_category()); }
206
207 inline bool
208 operator<(const error_code& __lhs, const error_code& __rhs) noexcept
209 {
210 return (__lhs.category() < __rhs.category()
211 || (__lhs.category() == __rhs.category()
212 && __lhs.value() < __rhs.value()));
213 }
214
215 template<typename _CharT, typename _Traits>
216 basic_ostream<_CharT, _Traits>&
217 operator<<(basic_ostream<_CharT, _Traits>& __os, const error_code& __e)
218 { return (__os << __e.category().name() << ':' << __e.value()); }
219
220 error_condition make_error_condition(errc) noexcept;
221
222 /// error_condition
223 // Portable error identification
224 struct error_condition
225 {
226 error_condition() noexcept
227 : _M_value(0), _M_cat(&generic_category()) { }
228
229 error_condition(int __v, const error_category& __cat) noexcept
230 : _M_value(__v), _M_cat(&__cat) { }
231
232 template<typename _ErrorConditionEnum, typename = typename
233 enable_if<is_error_condition_enum<_ErrorConditionEnum>::value>::type>
234 error_condition(_ErrorConditionEnum __e) noexcept
235 { *this = make_error_condition(__e); }
236
237 void
238 assign(int __v, const error_category& __cat) noexcept
239 {
240 _M_value = __v;
241 _M_cat = &__cat;
242 }
243
244 // DR 804.
245 template<typename _ErrorConditionEnum>
246 typename enable_if<is_error_condition_enum
247 <_ErrorConditionEnum>::value, error_condition&>::type
248 operator=(_ErrorConditionEnum __e) noexcept
249 { return *this = make_error_condition(__e); }
250
251 void
252 clear() noexcept
253 { assign(0, generic_category()); }
254
255 // 19.4.3.4 observers
256 int
257 value() const noexcept { return _M_value; }
258
259 const error_category&
260 category() const noexcept { return *_M_cat; }
261
262 _GLIBCXX_DEFAULT_ABI_TAG__attribute ((__abi_tag__ ("cxx11")))
263 string
264 message() const
265 { return category().message(value()); }
266
267 explicit operator bool() const noexcept
268 { return _M_value != 0; }
269
270 // DR 804.
271 private:
272 int _M_value;
273 const error_category* _M_cat;
274 };
275
276 // 19.4.3.6 non-member functions
277 inline error_condition
278 make_error_condition(errc __e) noexcept
279 { return error_condition(static_cast<int>(__e), generic_category()); }
280
281 inline bool
282 operator<(const error_condition& __lhs,
283 const error_condition& __rhs) noexcept
284 {
285 return (__lhs.category() < __rhs.category()
286 || (__lhs.category() == __rhs.category()
287 && __lhs.value() < __rhs.value()));
288 }
289
290 // 19.4.4 Comparison operators
291 inline bool
292 operator==(const error_code& __lhs, const error_code& __rhs) noexcept
293 { return (__lhs.category() == __rhs.category()
294 && __lhs.value() == __rhs.value()); }
295
296 inline bool
297 operator==(const error_code& __lhs, const error_condition& __rhs) noexcept
298 {
299 return (__lhs.category().equivalent(__lhs.value(), __rhs)
300 || __rhs.category().equivalent(__lhs, __rhs.value()));
301 }
302
303 inline bool
304 operator==(const error_condition& __lhs, const error_code& __rhs) noexcept
305 {
306 return (__rhs.category().equivalent(__rhs.value(), __lhs)
307 || __lhs.category().equivalent(__rhs, __lhs.value()));
308 }
309
310 inline bool
311 operator==(const error_condition& __lhs,
312 const error_condition& __rhs) noexcept
313 {
314 return (__lhs.category() == __rhs.category()
315 && __lhs.value() == __rhs.value());
316 }
317
318 inline bool
319 operator!=(const error_code& __lhs, const error_code& __rhs) noexcept
320 { return !(__lhs == __rhs); }
321
322 inline bool
323 operator!=(const error_code& __lhs, const error_condition& __rhs) noexcept
324 { return !(__lhs == __rhs); }
325
326 inline bool
327 operator!=(const error_condition& __lhs, const error_code& __rhs) noexcept
328 { return !(__lhs == __rhs); }
329
330 inline bool
331 operator!=(const error_condition& __lhs,
332 const error_condition& __rhs) noexcept
333 { return !(__lhs == __rhs); }
334
335
336 /**
337 * @brief Thrown to indicate error code of underlying system.
338 *
339 * @ingroup exceptions
340 */
341 class system_error : public std::runtime_error
342 {
343 private:
344 error_code _M_code;
345
346 public:
347 system_error(error_code __ec = error_code())
348 : runtime_error(__ec.message()), _M_code(__ec) { }
349
350 system_error(error_code __ec, const string& __what)
351 : runtime_error(__what + ": " + __ec.message()), _M_code(__ec) { }
352
353 system_error(error_code __ec, const char* __what)
354 : runtime_error(__what + (": " + __ec.message())), _M_code(__ec) { }
355
356 system_error(int __v, const error_category& __ecat, const char* __what)
357 : system_error(error_code(__v, __ecat), __what) { }
358
359 system_error(int __v, const error_category& __ecat)
360 : runtime_error(error_code(__v, __ecat).message()),
361 _M_code(__v, __ecat) { }
362
363 system_error(int __v, const error_category& __ecat, const string& __what)
364 : runtime_error(__what + ": " + error_code(__v, __ecat).message()),
365 _M_code(__v, __ecat) { }
366
367 virtual ~system_error() noexcept;
368
369 const error_code&
370 code() const noexcept { return _M_code; }
371 };
372
373_GLIBCXX_END_NAMESPACE_VERSION
374} // namespace
375
376#include <bits/functional_hash.h>
377
378namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
379{
380_GLIBCXX_BEGIN_NAMESPACE_VERSION
381
382#ifndef _GLIBCXX_COMPATIBILITY_CXX0X
383 // DR 1182.
384 /// std::hash specialization for error_code.
385 template<>
386 struct hash<error_code>
387 : public __hash_base<size_t, error_code>
388 {
389 size_t
390 operator()(const error_code& __e) const noexcept
391 {
392 const size_t __tmp = std::_Hash_impl::hash(__e._M_value);
393 return std::_Hash_impl::__hash_combine(__e._M_cat, __tmp);
394 }
395 };
396#endif // _GLIBCXX_COMPATIBILITY_CXX0X
397
398#if __cplusplus201103L > 201402L
399 // DR 2686.
400 /// std::hash specialization for error_condition.
401 template<>
402 struct hash<error_condition>
403 : public __hash_base<size_t, error_condition>
404 {
405 size_t
406 operator()(const error_condition& __e) const noexcept
407 {
408 const size_t __tmp = std::_Hash_impl::hash(__e.value());
409 return std::_Hash_impl::__hash_combine(__e.category(), __tmp);
410 }
411 };
412#endif
413
414_GLIBCXX_END_NAMESPACE_VERSION
415} // namespace
416
417#endif // C++11
418
419#endif // _GLIBCXX_SYSTEM_ERROR

/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Object/Error.h

1//===- Error.h - system_error extensions for Object -------------*- 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 declares a new error_category for the Object library.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_OBJECT_ERROR_H
15#define LLVM_OBJECT_ERROR_H
16
17#include "llvm/ADT/Twine.h"
18#include "llvm/Support/Error.h"
19#include <system_error>
20
21namespace llvm {
22namespace object {
23
24class Binary;
25
26const std::error_category &object_category();
27
28enum class object_error {
29 // Error code 0 is absent. Use std::error_code() instead.
30 arch_not_found = 1,
31 invalid_file_type,
32 parse_failed,
33 unexpected_eof,
34 string_table_non_null_end,
35 invalid_section_index,
36 bitcode_section_not_found,
37 invalid_symbol_index,
38};
39
40inline std::error_code make_error_code(object_error e) {
41 return std::error_code(static_cast<int>(e), object_category());
30
Calling constructor for 'error_code'
31
Returning from constructor for 'error_code'
42}
43
44/// Base class for all errors indicating malformed binary files.
45///
46/// Having a subclass for all malformed binary files allows archive-walking
47/// code to skip malformed files without having to understand every possible
48/// way that a binary file might be malformed.
49///
50/// Currently inherits from ECError for easy interoperability with
51/// std::error_code, but this will be removed in the future.
52class BinaryError : public ErrorInfo<BinaryError, ECError> {
53public:
54 static char ID;
55 BinaryError() {
56 // Default to parse_failed, can be overridden with setErrorCode.
57 setErrorCode(make_error_code(object_error::parse_failed));
58 }
59};
60
61/// Generic binary error.
62///
63/// For errors that don't require their own specific sub-error (most errors)
64/// this class can be used to describe the error via a string message.
65class GenericBinaryError : public ErrorInfo<GenericBinaryError, BinaryError> {
66public:
67 static char ID;
68 GenericBinaryError(Twine Msg);
69 GenericBinaryError(Twine Msg, object_error ECOverride);
70 const std::string &getMessage() const { return Msg; }
71 void log(raw_ostream &OS) const override;
72private:
73 std::string Msg;
74};
75
76/// isNotObjectErrorInvalidFileType() is used when looping through the children
77/// of an archive after calling getAsBinary() on the child and it returns an
78/// llvm::Error. In the cases we want to loop through the children and ignore the
79/// non-objects in the archive this is used to test the error to see if an
80/// error() function needs to called on the llvm::Error.
81Error isNotObjectErrorInvalidFileType(llvm::Error Err);
82
83} // end namespace object.
84
85} // end namespace llvm.
86
87namespace std {
88template <>
89struct is_error_code_enum<llvm::object::object_error> : std::true_type {};
90}
91
92#endif

/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Support/Error.h

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/ADT/SmallVector.h"
18#include "llvm/ADT/STLExtras.h"
19#include "llvm/ADT/StringExtras.h"
20#include "llvm/ADT/Twine.h"
21#include "llvm/Config/abi-breaking.h"
22#include "llvm/Support/AlignOf.h"
23#include "llvm/Support/Compiler.h"
24#include "llvm/Support/Debug.h"
25#include "llvm/Support/ErrorHandling.h"
26#include "llvm/Support/ErrorOr.h"
27#include "llvm/Support/raw_ostream.h"
28#include <algorithm>
29#include <cassert>
30#include <cstdint>
31#include <cstdlib>
32#include <functional>
33#include <memory>
34#include <new>
35#include <string>
36#include <system_error>
37#include <type_traits>
38#include <utility>
39#include <vector>
40
41namespace llvm {
42
43class ErrorSuccess;
44
45/// Base class for error info classes. Do not extend this directly: Extend
46/// the ErrorInfo template subclass instead.
47class ErrorInfoBase {
48public:
49 virtual ~ErrorInfoBase() = default;
50
51 /// Print an error message to an output stream.
52 virtual void log(raw_ostream &OS) const = 0;
53
54 /// Return the error message as a string.
55 virtual std::string message() const {
56 std::string Msg;
57 raw_string_ostream OS(Msg);
58 log(OS);
59 return OS.str();
60 }
61
62 /// Convert this error to a std::error_code.
63 ///
64 /// This is a temporary crutch to enable interaction with code still
65 /// using std::error_code. It will be removed in the future.
66 virtual std::error_code convertToErrorCode() const = 0;
67
68 // Returns the class ID for this type.
69 static const void *classID() { return &ID; }
70
71 // Returns the class ID for the dynamic type of this ErrorInfoBase instance.
72 virtual const void *dynamicClassID() const = 0;
73
74 // Check whether this instance is a subclass of the class identified by
75 // ClassID.
76 virtual bool isA(const void *const ClassID) const {
77 return ClassID == classID();
78 }
79
80 // Check whether this instance is a subclass of ErrorInfoT.
81 template <typename ErrorInfoT> bool isA() const {
82 return isA(ErrorInfoT::classID());
83 }
84
85private:
86 virtual void anchor();
87
88 static char ID;
89};
90
91/// Lightweight error class with error context and mandatory checking.
92///
93/// Instances of this class wrap a ErrorInfoBase pointer. Failure states
94/// are represented by setting the pointer to a ErrorInfoBase subclass
95/// instance containing information describing the failure. Success is
96/// represented by a null pointer value.
97///
98/// Instances of Error also contains a 'Checked' flag, which must be set
99/// before the destructor is called, otherwise the destructor will trigger a
100/// runtime error. This enforces at runtime the requirement that all Error
101/// instances be checked or returned to the caller.
102///
103/// There are two ways to set the checked flag, depending on what state the
104/// Error instance is in. For Error instances indicating success, it
105/// is sufficient to invoke the boolean conversion operator. E.g.:
106///
107/// @code{.cpp}
108/// Error foo(<...>);
109///
110/// if (auto E = foo(<...>))
111/// return E; // <- Return E if it is in the error state.
112/// // We have verified that E was in the success state. It can now be safely
113/// // destroyed.
114/// @endcode
115///
116/// A success value *can not* be dropped. For example, just calling 'foo(<...>)'
117/// without testing the return value will raise a runtime error, even if foo
118/// returns success.
119///
120/// For Error instances representing failure, you must use either the
121/// handleErrors or handleAllErrors function with a typed handler. E.g.:
122///
123/// @code{.cpp}
124/// class MyErrorInfo : public ErrorInfo<MyErrorInfo> {
125/// // Custom error info.
126/// };
127///
128/// Error foo(<...>) { return make_error<MyErrorInfo>(...); }
129///
130/// auto E = foo(<...>); // <- foo returns failure with MyErrorInfo.
131/// auto NewE =
132/// handleErrors(E,
133/// [](const MyErrorInfo &M) {
134/// // Deal with the error.
135/// },
136/// [](std::unique_ptr<OtherError> M) -> Error {
137/// if (canHandle(*M)) {
138/// // handle error.
139/// return Error::success();
140/// }
141/// // Couldn't handle this error instance. Pass it up the stack.
142/// return Error(std::move(M));
143/// );
144/// // Note - we must check or return NewE in case any of the handlers
145/// // returned a new error.
146/// @endcode
147///
148/// The handleAllErrors function is identical to handleErrors, except
149/// that it has a void return type, and requires all errors to be handled and
150/// no new errors be returned. It prevents errors (assuming they can all be
151/// handled) from having to be bubbled all the way to the top-level.
152///
153/// *All* Error instances must be checked before destruction, even if
154/// they're moved-assigned or constructed from Success values that have already
155/// been checked. This enforces checking through all levels of the call stack.
156class LLVM_NODISCARD[[clang::warn_unused_result]] Error {
157 // ErrorList needs to be able to yank ErrorInfoBase pointers out of this
158 // class to add to the error list.
159 friend class ErrorList;
160
161 // handleErrors needs to be able to set the Checked flag.
162 template <typename... HandlerTs>
163 friend Error handleErrors(Error E, HandlerTs &&... Handlers);
164
165 // Expected<T> needs to be able to steal the payload when constructed from an
166 // error.
167 template <typename T> friend class Expected;
168
169protected:
170 /// Create a success value. Prefer using 'Error::success()' for readability
171 Error() {
172 setPtr(nullptr);
173 setChecked(false);
174 }
175
176public:
177 /// Create a success value.
178 static ErrorSuccess success();
179
180 // Errors are not copy-constructable.
181 Error(const Error &Other) = delete;
182
183 /// Move-construct an error value. The newly constructed error is considered
184 /// unchecked, even if the source error had been checked. The original error
185 /// becomes a checked Success value, regardless of its original state.
186 Error(Error &&Other) {
187 setChecked(true);
58
Calling 'Error::setChecked'
60
Returning from 'Error::setChecked'
188 *this = std::move(Other);
61
Calling 'move'
62
Returning from 'move'
63
Calling move assignment operator for 'Error'
80
Returning from move assignment operator for 'Error'
189 }
190
191 /// Create an error value. Prefer using the 'make_error' function, but
192 /// this constructor can be useful when "re-throwing" errors from handlers.
193 Error(std::unique_ptr<ErrorInfoBase> Payload) {
194 setPtr(Payload.release());
195 setChecked(false);
196 }
197
198 // Errors are not copy-assignable.
199 Error &operator=(const Error &Other) = delete;
200
201 /// Move-assign an error value. The current error must represent success, you
202 /// you cannot overwrite an unhandled error. The current error is then
203 /// considered unchecked. The source error becomes a checked success value,
204 /// regardless of its original state.
205 Error &operator=(Error &&Other) {
206 // Don't allow overwriting of unchecked values.
207 assertIsChecked();
64
Calling 'Error::assertIsChecked'
67
Returning from 'Error::assertIsChecked'
208 setPtr(Other.getPtr());
68
Calling 'Error::getPtr'
69
Returning from 'Error::getPtr'
70
Calling 'Error::setPtr'
71
Returning from 'Error::setPtr'
209
210 // This Error is unchecked, even if the source error was checked.
211 setChecked(false);
72
Calling 'Error::setChecked'
74
Returning from 'Error::setChecked'
212
213 // Null out Other's payload and set its checked bit.
214 Other.setPtr(nullptr);
75
Calling 'Error::setPtr'
76
Returning from 'Error::setPtr'
215 Other.setChecked(true);
77
Calling 'Error::setChecked'
79
Returning from 'Error::setChecked'
216
217 return *this;
218 }
219
220 /// Destroy a Error. Fails with a call to abort() if the error is
221 /// unchecked.
222 ~Error() {
223 assertIsChecked();
96
Calling 'Error::assertIsChecked'
99
Returning from 'Error::assertIsChecked'
224 delete getPtr();
100
Calling 'Error::getPtr'
101
Returning from 'Error::getPtr'
225 }
226
227 /// Bool conversion. Returns true if this Error is in a failure state,
228 /// and false if it is in an accept state. If the error is in a Success state
229 /// it will be considered checked.
230 explicit operator bool() {
231 setChecked(getPtr() == nullptr);
83
Calling 'Error::getPtr'
84
Returning from 'Error::getPtr'
85
Calling 'Error::setChecked'
88
Returning from 'Error::setChecked'
232 return getPtr() != nullptr;
89
Calling 'Error::getPtr'
90
Returning from 'Error::getPtr'
233 }
234
235 /// Check whether one error is a subclass of another.
236 template <typename ErrT> bool isA() const {
237 return getPtr() && getPtr()->isA(ErrT::classID());
238 }
239
240 /// Returns the dynamic class id of this error, or null if this is a success
241 /// value.
242 const void* dynamicClassID() const {
243 if (!getPtr())
244 return nullptr;
245 return getPtr()->dynamicClassID();
246 }
247
248private:
249#if LLVM_ENABLE_ABI_BREAKING_CHECKS1
250 // assertIsChecked() happens very frequently, but under normal circumstances
251 // is supposed to be a no-op. So we want it to be inlined, but having a bunch
252 // of debug prints can cause the function to be too large for inlining. So
253 // it's important that we define this function out of line so that it can't be
254 // inlined.
255 LLVM_ATTRIBUTE_NORETURN__attribute__((noreturn))
256 void fatalUncheckedError() const;
257#endif
258
259 void assertIsChecked() {
260#if LLVM_ENABLE_ABI_BREAKING_CHECKS1
261 if (LLVM_UNLIKELY(!getChecked() || getPtr())__builtin_expect((bool)(!getChecked() || getPtr()), false))
65
Within the expansion of the macro 'LLVM_UNLIKELY':
a
Calling 'Error::getChecked'
b
Returning from 'Error::getChecked'
c
Calling 'Error::getPtr'
d
Returning from 'Error::getPtr'
66
Taking false branch
97
Within the expansion of the macro 'LLVM_UNLIKELY':
a
Calling 'Error::getChecked'
b
Returning from 'Error::getChecked'
98
Taking false branch
262 fatalUncheckedError();
263#endif
264 }
265
266 ErrorInfoBase *getPtr() const {
267 return reinterpret_cast<ErrorInfoBase*>(
268 reinterpret_cast<uintptr_t>(Payload) &
269 ~static_cast<uintptr_t>(0x1));
270 }
271
272 void setPtr(ErrorInfoBase *EI) {
273#if LLVM_ENABLE_ABI_BREAKING_CHECKS1
274 Payload = reinterpret_cast<ErrorInfoBase*>(
275 (reinterpret_cast<uintptr_t>(EI) &
276 ~static_cast<uintptr_t>(0x1)) |
277 (reinterpret_cast<uintptr_t>(Payload) & 0x1));
278#else
279 Payload = EI;
280#endif
281 }
282
283 bool getChecked() const {
284#if LLVM_ENABLE_ABI_BREAKING_CHECKS1
285 return (reinterpret_cast<uintptr_t>(Payload) & 0x1) == 0;
286#else
287 return true;
288#endif
289 }
290
291 void setChecked(bool V) {
292 Payload = reinterpret_cast<ErrorInfoBase*>(
293 (reinterpret_cast<uintptr_t>(Payload) &
294 ~static_cast<uintptr_t>(0x1)) |
295 (V ? 0 : 1));
59
'?' condition is true
73
'?' condition is false
78
'?' condition is true
86
Assuming 'V' is 0
87
'?' condition is false
296 }
297
298 std::unique_ptr<ErrorInfoBase> takePayload() {
299 std::unique_ptr<ErrorInfoBase> Tmp(getPtr());
300 setPtr(nullptr);
301 setChecked(true);
302 return Tmp;
303 }
304
305 ErrorInfoBase *Payload = nullptr;
306};
307
308/// Subclass of Error for the sole purpose of identifying the success path in
309/// the type system. This allows to catch invalid conversion to Expected<T> at
310/// compile time.
311class ErrorSuccess : public Error {};
312
313inline ErrorSuccess Error::success() { return ErrorSuccess(); }
314
315/// Make a Error instance representing failure using the given error info
316/// type.
317template <typename ErrT, typename... ArgTs> Error make_error(ArgTs &&... Args) {
318 return Error(llvm::make_unique<ErrT>(std::forward<ArgTs>(Args)...));
319}
320
321/// Base class for user error types. Users should declare their error types
322/// like:
323///
324/// class MyError : public ErrorInfo<MyError> {
325/// ....
326/// };
327///
328/// This class provides an implementation of the ErrorInfoBase::kind
329/// method, which is used by the Error RTTI system.
330template <typename ThisErrT, typename ParentErrT = ErrorInfoBase>
331class ErrorInfo : public ParentErrT {
332public:
333 static const void *classID() { return &ThisErrT::ID; }
334
335 const void *dynamicClassID() const override { return &ThisErrT::ID; }
336
337 bool isA(const void *const ClassID) const override {
338 return ClassID == classID() || ParentErrT::isA(ClassID);
339 }
340};
341
342/// Special ErrorInfo subclass representing a list of ErrorInfos.
343/// Instances of this class are constructed by joinError.
344class ErrorList final : public ErrorInfo<ErrorList> {
345 // handleErrors needs to be able to iterate the payload list of an
346 // ErrorList.
347 template <typename... HandlerTs>
348 friend Error handleErrors(Error E, HandlerTs &&... Handlers);
349
350 // joinErrors is implemented in terms of join.
351 friend Error joinErrors(Error, Error);
352
353public:
354 void log(raw_ostream &OS) const override {
355 OS << "Multiple errors:\n";
356 for (auto &ErrPayload : Payloads) {
357 ErrPayload->log(OS);
358 OS << "\n";
359 }
360 }
361
362 std::error_code convertToErrorCode() const override;
363
364 // Used by ErrorInfo::classID.
365 static char ID;
366
367private:
368 ErrorList(std::unique_ptr<ErrorInfoBase> Payload1,
369 std::unique_ptr<ErrorInfoBase> Payload2) {
370 assert(!Payload1->isA<ErrorList>() && !Payload2->isA<ErrorList>() &&(static_cast <bool> (!Payload1->isA<ErrorList>
() && !Payload2->isA<ErrorList>() &&
"ErrorList constructor payloads should be singleton errors")
? void (0) : __assert_fail ("!Payload1->isA<ErrorList>() && !Payload2->isA<ErrorList>() && \"ErrorList constructor payloads should be singleton errors\""
, "/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Support/Error.h"
, 371, __extension__ __PRETTY_FUNCTION__))
371 "ErrorList constructor payloads should be singleton errors")(static_cast <bool> (!Payload1->isA<ErrorList>
() && !Payload2->isA<ErrorList>() &&
"ErrorList constructor payloads should be singleton errors")
? void (0) : __assert_fail ("!Payload1->isA<ErrorList>() && !Payload2->isA<ErrorList>() && \"ErrorList constructor payloads should be singleton errors\""
, "/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Support/Error.h"
, 371, __extension__ __PRETTY_FUNCTION__))
;
372 Payloads.push_back(std::move(Payload1));
373 Payloads.push_back(std::move(Payload2));
374 }
375
376 static Error join(Error E1, Error E2) {
377 if (!E1)
378 return E2;
379 if (!E2)
380 return E1;
381 if (E1.isA<ErrorList>()) {
382 auto &E1List = static_cast<ErrorList &>(*E1.getPtr());
383 if (E2.isA<ErrorList>()) {
384 auto E2Payload = E2.takePayload();
385 auto &E2List = static_cast<ErrorList &>(*E2Payload);
386 for (auto &Payload : E2List.Payloads)
387 E1List.Payloads.push_back(std::move(Payload));
388 } else
389 E1List.Payloads.push_back(E2.takePayload());
390
391 return E1;
392 }
393 if (E2.isA<ErrorList>()) {
394 auto &E2List = static_cast<ErrorList &>(*E2.getPtr());
395 E2List.Payloads.insert(E2List.Payloads.begin(), E1.takePayload());
396 return E2;
397 }
398 return Error(std::unique_ptr<ErrorList>(
399 new ErrorList(E1.takePayload(), E2.takePayload())));
400 }
401
402 std::vector<std::unique_ptr<ErrorInfoBase>> Payloads;
403};
404
405/// Concatenate errors. The resulting Error is unchecked, and contains the
406/// ErrorInfo(s), if any, contained in E1, followed by the
407/// ErrorInfo(s), if any, contained in E2.
408inline Error joinErrors(Error E1, Error E2) {
409 return ErrorList::join(std::move(E1), std::move(E2));
410}
411
412/// Tagged union holding either a T or a Error.
413///
414/// This class parallels ErrorOr, but replaces error_code with Error. Since
415/// Error cannot be copied, this class replaces getError() with
416/// takeError(). It also adds an bool errorIsA<ErrT>() method for testing the
417/// error class type.
418template <class T> class LLVM_NODISCARD[[clang::warn_unused_result]] Expected {
419 template <class T1> friend class ExpectedAsOutParameter;
420 template <class OtherT> friend class Expected;
421
422 static const bool isRef = std::is_reference<T>::value;
423
424 using wrap = ReferenceStorage<typename std::remove_reference<T>::type>;
425
426 using error_type = std::unique_ptr<ErrorInfoBase>;
427
428public:
429 using storage_type = typename std::conditional<isRef, wrap, T>::type;
430 using value_type = T;
431
432private:
433 using reference = typename std::remove_reference<T>::type &;
434 using const_reference = const typename std::remove_reference<T>::type &;
435 using pointer = typename std::remove_reference<T>::type *;
436 using const_pointer = const typename std::remove_reference<T>::type *;
437
438public:
439 /// Create an Expected<T> error value from the given Error.
440 Expected(Error Err)
441 : HasError(true)
442#if LLVM_ENABLE_ABI_BREAKING_CHECKS1
443 // Expected is unchecked upon construction in Debug builds.
444 , Unchecked(true)
445#endif
446 {
447 assert(Err && "Cannot create Expected<T> from Error success value.")(static_cast <bool> (Err && "Cannot create Expected<T> from Error success value."
) ? void (0) : __assert_fail ("Err && \"Cannot create Expected<T> from Error success value.\""
, "/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Support/Error.h"
, 447, __extension__ __PRETTY_FUNCTION__))
;
448 new (getErrorStorage()) error_type(Err.takePayload());
449 }
450
451 /// Forbid to convert from Error::success() implicitly, this avoids having
452 /// Expected<T> foo() { return Error::success(); } which compiles otherwise
453 /// but triggers the assertion above.
454 Expected(ErrorSuccess) = delete;
455
456 /// Create an Expected<T> success value from the given OtherT value, which
457 /// must be convertible to T.
458 template <typename OtherT>
459 Expected(OtherT &&Val,
460 typename std::enable_if<std::is_convertible<OtherT, T>::value>::type
461 * = nullptr)
462 : HasError(false)
463#if LLVM_ENABLE_ABI_BREAKING_CHECKS1
464 // Expected is unchecked upon construction in Debug builds.
465 , Unchecked(true)
466#endif
467 {
468 new (getStorage()) storage_type(std::forward<OtherT>(Val));
469 }
470
471 /// Move construct an Expected<T> value.
472 Expected(Expected &&Other) { moveConstruct(std::move(Other)); }
36
Calling 'move'
37
Returning from 'move'
38
Calling 'Expected::moveConstruct'
49
Returning from 'Expected::moveConstruct'
473
474 /// Move construct an Expected<T> value from an Expected<OtherT>, where OtherT
475 /// must be convertible to T.
476 template <class OtherT>
477 Expected(Expected<OtherT> &&Other,
478 typename std::enable_if<std::is_convertible<OtherT, T>::value>::type
479 * = nullptr) {
480 moveConstruct(std::move(Other));
481 }
482
483 /// Move construct an Expected<T> value from an Expected<OtherT>, where OtherT
484 /// isn't convertible to T.
485 template <class OtherT>
486 explicit Expected(
487 Expected<OtherT> &&Other,
488 typename std::enable_if<!std::is_convertible<OtherT, T>::value>::type * =
489 nullptr) {
490 moveConstruct(std::move(Other));
491 }
492
493 /// Move-assign from another Expected<T>.
494 Expected &operator=(Expected &&Other) {
495 moveAssign(std::move(Other));
496 return *this;
497 }
498
499 /// Destroy an Expected<T>.
500 ~Expected() {
501 assertIsChecked();
104
Calling 'Expected::assertIsChecked'
106
Returning from 'Expected::assertIsChecked'
502 if (!HasError)
107
Taking true branch
503 getStorage()->~storage_type();
108
Calling 'Expected::getStorage'
110
Returning from 'Expected::getStorage'
504 else
505 getErrorStorage()->~error_type();
506 }
507
508 /// \brief Return false if there is an error.
509 explicit operator bool() {
510#if LLVM_ENABLE_ABI_BREAKING_CHECKS1
511 Unchecked = HasError;
512#endif
513 return !HasError;
514 }
515
516 /// \brief Returns a reference to the stored T value.
517 reference get() {
518 assertIsChecked();
519 return *getStorage();
520 }
521
522 /// \brief Returns a const reference to the stored T value.
523 const_reference get() const {
524 assertIsChecked();
525 return const_cast<Expected<T> *>(this)->get();
526 }
527
528 /// \brief Check that this Expected<T> is an error of type ErrT.
529 template <typename ErrT> bool errorIsA() const {
530 return HasError && (*getErrorStorage())->template isA<ErrT>();
531 }
532
533 /// \brief Take ownership of the stored error.
534 /// After calling this the Expected<T> is in an indeterminate state that can
535 /// only be safely destructed. No further calls (beside the destructor) should
536 /// be made on the Expected<T> vaule.
537 Error takeError() {
538#if LLVM_ENABLE_ABI_BREAKING_CHECKS1
539 Unchecked = false;
540#endif
541 return HasError ? Error(std::move(*getErrorStorage())) : Error::success();
52
Assuming the condition is false
53
'?' condition is false
54
Calling 'Error::success'
55
Returning from 'Error::success'
542 }
543
544 /// \brief Returns a pointer to the stored T value.
545 pointer operator->() {
546 assertIsChecked();
547 return toPointer(getStorage());
548 }
549
550 /// \brief Returns a const pointer to the stored T value.
551 const_pointer operator->() const {
552 assertIsChecked();
553 return toPointer(getStorage());
554 }
555
556 /// \brief Returns a reference to the stored T value.
557 reference operator*() {
558 assertIsChecked();
559 return *getStorage();
560 }
561
562 /// \brief Returns a const reference to the stored T value.
563 const_reference operator*() const {
564 assertIsChecked();
565 return *getStorage();
566 }
567
568private:
569 template <class T1>
570 static bool compareThisIfSameType(const T1 &a, const T1 &b) {
571 return &a == &b;
572 }
573
574 template <class T1, class T2>
575 static bool compareThisIfSameType(const T1 &a, const T2 &b) {
576 return false;
577 }
578
579 template <class OtherT> void moveConstruct(Expected<OtherT> &&Other) {
580 HasError = Other.HasError;
581#if LLVM_ENABLE_ABI_BREAKING_CHECKS1
582 Unchecked = true;
583 Other.Unchecked = false;
584#endif
585
586 if (!HasError)
39
Assuming the condition is false
40
Taking false branch
587 new (getStorage()) storage_type(std::move(*Other.getStorage()));
588 else
589 new (getErrorStorage()) error_type(std::move(*Other.getErrorStorage()));
41
Calling 'Expected::getErrorStorage'
43
Returning from 'Expected::getErrorStorage'
44
Calling 'Expected::getErrorStorage'
46
Returning from 'Expected::getErrorStorage'
47
Calling 'move'
48
Returning from 'move'
590 }
591
592 template <class OtherT> void moveAssign(Expected<OtherT> &&Other) {
593 assertIsChecked();
594
595 if (compareThisIfSameType(*this, Other))
596 return;
597
598 this->~Expected();
599 new (this) Expected(std::move(Other));
600 }
601
602 pointer toPointer(pointer Val) { return Val; }
603
604 const_pointer toPointer(const_pointer Val) const { return Val; }
605
606 pointer toPointer(wrap *Val) { return &Val->get(); }
607
608 const_pointer toPointer(const wrap *Val) const { return &Val->get(); }
609
610 storage_type *getStorage() {
611 assert(!HasError && "Cannot get value when an error exists!")(static_cast <bool> (!HasError && "Cannot get value when an error exists!"
) ? void (0) : __assert_fail ("!HasError && \"Cannot get value when an error exists!\""
, "/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Support/Error.h"
, 611, __extension__ __PRETTY_FUNCTION__))
;
109
Within the expansion of the macro 'assert':
612 return reinterpret_cast<storage_type *>(TStorage.buffer);
613 }
614
615 const storage_type *getStorage() const {
616 assert(!HasError && "Cannot get value when an error exists!")(static_cast <bool> (!HasError && "Cannot get value when an error exists!"
) ? void (0) : __assert_fail ("!HasError && \"Cannot get value when an error exists!\""
, "/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Support/Error.h"
, 616, __extension__ __PRETTY_FUNCTION__))
;
617 return reinterpret_cast<const storage_type *>(TStorage.buffer);
618 }
619
620 error_type *getErrorStorage() {
621 assert(HasError && "Cannot get error when a value exists!")(static_cast <bool> (HasError && "Cannot get error when a value exists!"
) ? void (0) : __assert_fail ("HasError && \"Cannot get error when a value exists!\""
, "/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Support/Error.h"
, 621, __extension__ __PRETTY_FUNCTION__))
;
42
Within the expansion of the macro 'assert':
45
Within the expansion of the macro 'assert':
622 return reinterpret_cast<error_type *>(ErrorStorage.buffer);
623 }
624
625 const error_type *getErrorStorage() const {
626 assert(HasError && "Cannot get error when a value exists!")(static_cast <bool> (HasError && "Cannot get error when a value exists!"
) ? void (0) : __assert_fail ("HasError && \"Cannot get error when a value exists!\""
, "/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Support/Error.h"
, 626, __extension__ __PRETTY_FUNCTION__))
;
627 return reinterpret_cast<const error_type *>(ErrorStorage.buffer);
628 }
629
630 // Used by ExpectedAsOutParameter to reset the checked flag.
631 void setUnchecked() {
632#if LLVM_ENABLE_ABI_BREAKING_CHECKS1
633 Unchecked = true;
634#endif
635 }
636
637#if LLVM_ENABLE_ABI_BREAKING_CHECKS1
638 LLVM_ATTRIBUTE_NORETURN__attribute__((noreturn))
639 LLVM_ATTRIBUTE_NOINLINE__attribute__((noinline))
640 void fatalUncheckedExpected() const {
641 dbgs() << "Expected<T> must be checked before access or destruction.\n";
642 if (HasError) {
643 dbgs() << "Unchecked Expected<T> contained error:\n";
644 (*getErrorStorage())->log(dbgs());
645 } else
646 dbgs() << "Expected<T> value was in success state. (Note: Expected<T> "
647 "values in success mode must still be checked prior to being "
648 "destroyed).\n";
649 abort();
650 }
651#endif
652
653 void assertIsChecked() {
654#if LLVM_ENABLE_ABI_BREAKING_CHECKS1
655 if (LLVM_UNLIKELY(Unchecked)__builtin_expect((bool)(Unchecked), false))
105
Taking false branch
656 fatalUncheckedExpected();
657#endif
658 }
659
660 union {
661 AlignedCharArrayUnion<storage_type> TStorage;
662 AlignedCharArrayUnion<error_type> ErrorStorage;
663 };
664 bool HasError : 1;
665#if LLVM_ENABLE_ABI_BREAKING_CHECKS1
666 bool Unchecked : 1;
667#endif
668};
669
670/// Report a serious error, calling any installed error handler. See
671/// ErrorHandling.h.
672LLVM_ATTRIBUTE_NORETURN__attribute__((noreturn)) void report_fatal_error(Error Err,
673 bool gen_crash_diag = true);
674
675/// Report a fatal error if Err is a failure value.
676///
677/// This function can be used to wrap calls to fallible functions ONLY when it
678/// is known that the Error will always be a success value. E.g.
679///
680/// @code{.cpp}
681/// // foo only attempts the fallible operation if DoFallibleOperation is
682/// // true. If DoFallibleOperation is false then foo always returns
683/// // Error::success().
684/// Error foo(bool DoFallibleOperation);
685///
686/// cantFail(foo(false));
687/// @endcode
688inline void cantFail(Error Err, const char *Msg = nullptr) {
689 if (Err) {
690 if (!Msg)
691 Msg = "Failure value returned from cantFail wrapped call";
692 llvm_unreachable(Msg)::llvm::llvm_unreachable_internal(Msg, "/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Support/Error.h"
, 692)
;
693 }
694}
695
696/// Report a fatal error if ValOrErr is a failure value, otherwise unwraps and
697/// returns the contained value.
698///
699/// This function can be used to wrap calls to fallible functions ONLY when it
700/// is known that the Error will always be a success value. E.g.
701///
702/// @code{.cpp}
703/// // foo only attempts the fallible operation if DoFallibleOperation is
704/// // true. If DoFallibleOperation is false then foo always returns an int.
705/// Expected<int> foo(bool DoFallibleOperation);
706///
707/// int X = cantFail(foo(false));
708/// @endcode
709template <typename T>
710T cantFail(Expected<T> ValOrErr, const char *Msg = nullptr) {
711 if (ValOrErr)
712 return std::move(*ValOrErr);
713 else {
714 if (!Msg)
715 Msg = "Failure value returned from cantFail wrapped call";
716 llvm_unreachable(Msg)::llvm::llvm_unreachable_internal(Msg, "/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Support/Error.h"
, 716)
;
717 }
718}
719
720/// Report a fatal error if ValOrErr is a failure value, otherwise unwraps and
721/// returns the contained reference.
722///
723/// This function can be used to wrap calls to fallible functions ONLY when it
724/// is known that the Error will always be a success value. E.g.
725///
726/// @code{.cpp}
727/// // foo only attempts the fallible operation if DoFallibleOperation is
728/// // true. If DoFallibleOperation is false then foo always returns a Bar&.
729/// Expected<Bar&> foo(bool DoFallibleOperation);
730///
731/// Bar &X = cantFail(foo(false));
732/// @endcode
733template <typename T>
734T& cantFail(Expected<T&> ValOrErr, const char *Msg = nullptr) {
735 if (ValOrErr)
736 return *ValOrErr;
737 else {
738 if (!Msg)
739 Msg = "Failure value returned from cantFail wrapped call";
740 llvm_unreachable(Msg)::llvm::llvm_unreachable_internal(Msg, "/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Support/Error.h"
, 740)
;
741 }
742}
743
744/// Helper for testing applicability of, and applying, handlers for
745/// ErrorInfo types.
746template <typename HandlerT>
747class ErrorHandlerTraits
748 : public ErrorHandlerTraits<decltype(
749 &std::remove_reference<HandlerT>::type::operator())> {};
750
751// Specialization functions of the form 'Error (const ErrT&)'.
752template <typename ErrT> class ErrorHandlerTraits<Error (&)(ErrT &)> {
753public:
754 static bool appliesTo(const ErrorInfoBase &E) {
755 return E.template isA<ErrT>();
756 }
757
758 template <typename HandlerT>
759 static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) {
760 assert(appliesTo(*E) && "Applying incorrect handler")(static_cast <bool> (appliesTo(*E) && "Applying incorrect handler"
) ? void (0) : __assert_fail ("appliesTo(*E) && \"Applying incorrect handler\""
, "/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Support/Error.h"
, 760, __extension__ __PRETTY_FUNCTION__))
;
761 return H(static_cast<ErrT &>(*E));
762 }
763};
764
765// Specialization functions of the form 'void (const ErrT&)'.
766template <typename ErrT> class ErrorHandlerTraits<void (&)(ErrT &)> {
767public:
768 static bool appliesTo(const ErrorInfoBase &E) {
769 return E.template isA<ErrT>();
770 }
771
772 template <typename HandlerT>
773 static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) {
774 assert(appliesTo(*E) && "Applying incorrect handler")(static_cast <bool> (appliesTo(*E) && "Applying incorrect handler"
) ? void (0) : __assert_fail ("appliesTo(*E) && \"Applying incorrect handler\""
, "/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Support/Error.h"
, 774, __extension__ __PRETTY_FUNCTION__))
;
775 H(static_cast<ErrT &>(*E));
776 return Error::success();
777 }
778};
779
780/// Specialization for functions of the form 'Error (std::unique_ptr<ErrT>)'.
781template <typename ErrT>
782class ErrorHandlerTraits<Error (&)(std::unique_ptr<ErrT>)> {
783public:
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")(static_cast <bool> (appliesTo(*E) && "Applying incorrect handler"
) ? void (0) : __assert_fail ("appliesTo(*E) && \"Applying incorrect handler\""
, "/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Support/Error.h"
, 790, __extension__ __PRETTY_FUNCTION__))
;
791 std::unique_ptr<ErrT> SubE(static_cast<ErrT *>(E.release()));
792 return H(std::move(SubE));
793 }
794};
795
796/// Specialization for functions of the form 'void (std::unique_ptr<ErrT>)'.
797template <typename ErrT>
798class ErrorHandlerTraits<void (&)(std::unique_ptr<ErrT>)> {
799public:
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")(static_cast <bool> (appliesTo(*E) && "Applying incorrect handler"
) ? void (0) : __assert_fail ("appliesTo(*E) && \"Applying incorrect handler\""
, "/build/llvm-toolchain-snapshot-6.0~svn321639/include/llvm/Support/Error.h"
, 806, __extension__ __PRETTY_FUNCTION__))
;
807 std::unique_ptr<ErrT> SubE(static_cast<ErrT *>(E.release()));
808 H(std::move(SubE));
809 return Error::success();
810 }
811};
812
813// Specialization for member functions of the form 'RetT (const ErrT&)'.
814template <typename C, typename RetT, typename ErrT>
815class ErrorHandlerTraits<RetT (C::*)(ErrT &)>
816 : public ErrorHandlerTraits<RetT (&)(ErrT &)> {};
817
818// Specialization for member functions of the form 'RetT (const ErrT&) const'.
819template <typename C, typename RetT, typename ErrT>
820class ErrorHandlerTraits<RetT (C::*)(ErrT &) const>
821 : public ErrorHandlerTraits<RetT (&)(ErrT &)> {};
822
823// Specialization for member functions of the form 'RetT (const ErrT&)'.
824template <typename C, typename RetT, typename ErrT>
825class ErrorHandlerTraits<RetT (C::*)(const ErrT &)>
826 : public ErrorHandlerTraits<RetT (&)(ErrT &)> {};
827
828// Specialization for member functions of the form 'RetT (const ErrT&) const'.
829template <typename C, typename RetT, typename ErrT>
830class ErrorHandlerTraits<RetT (C::*)(const ErrT &) const>
831 : public ErrorHandlerTraits<RetT (&)(ErrT &)> {};
832
833/// Specialization for member functions of the form
834/// 'RetT (std::unique_ptr<ErrT>)'.
835template <typename C, typename RetT, typename ErrT>
836class ErrorHandlerTraits<RetT (C::*)(std::unique_ptr<ErrT>)>
837 : public ErrorHandlerTraits<RetT (&)(std::unique_ptr<ErrT>)> {};
838
839/// Specialization for member functions of the form
840/// 'RetT (std::unique_ptr<ErrT>) const'.
841template <typename C, typename RetT, typename ErrT>
842class ErrorHandlerTraits<RetT (C::*)(std::unique_ptr<ErrT>) const>
843 : public ErrorHandlerTraits<RetT (&)(std::unique_ptr<ErrT>)> {};
844
845inline Error handleErrorImpl(std::unique_ptr<ErrorInfoBase> Payload) {
846 return Error(std::move(Payload));
847}
848
849template <typename HandlerT, typename... HandlerTs>
850Error handleErrorImpl(std::unique_ptr<ErrorInfoBase> Payload,
851 HandlerT &&Handler, HandlerTs &&... Handlers) {
852 if (ErrorHandlerTraits<HandlerT>::appliesTo(*Payload))
853 return ErrorHandlerTraits<HandlerT>::apply(std::forward<HandlerT>(Handler),
854 std::move(Payload));
855 return handleErrorImpl(std::move(Payload),
856 std::forward<HandlerTs>(Handlers)...);
857}
858
859/// Pass the ErrorInfo(s) contained in E to their respective handlers. Any
860/// unhandled errors (or Errors returned by handlers) are re-concatenated and
861/// returned.
862/// Because this function returns an error, its result must also be checked
863/// or returned. If you intend to handle all errors use handleAllErrors
864/// (which returns void, and will abort() on unhandled errors) instead.
865template <typename... HandlerTs>
866Error handleErrors(Error E, HandlerTs &&... Hs) {
867 if (!E)
868 return Error::success();
869
870 std::unique_ptr<ErrorInfoBase> Payload = E.takePayload();
871
872 if (Payload->isA<ErrorList>()) {
873 ErrorList &List = static_cast<ErrorList &>(*Payload);
874 Error R;
875 for (auto &P : List.Payloads)
876 R = ErrorList::join(
877 std::move(R),
878 handleErrorImpl(std::move(P), std::forward<HandlerTs>(Hs)...));
879 return R;
880 }
881
882 return handleErrorImpl(std::move(Payload), std::forward<HandlerTs>(Hs)...);
883}
884
885/// Behaves the same as handleErrors, except that it requires that all
886/// errors be handled by the given handlers. If any unhandled error remains
887/// after the handlers have run, report_fatal_error() will be called.
888template <typename... HandlerTs>
889void handleAllErrors(Error E, HandlerTs &&... Handlers) {
890 cantFail(handleErrors(std::move(E), std::forward<HandlerTs>(Handlers)...));
891}
892
893/// Check that E is a non-error, then drop it.
894/// If E is an error report_fatal_error will be called.
895inline void handleAllErrors(Error E) {
896 cantFail(std::move(E));
897}
898
899/// Handle any errors (if present) in an Expected<T>, then try a recovery path.
900///
901/// If the incoming value is a success value it is returned unmodified. If it
902/// is a failure value then it the contained error is passed to handleErrors.
903/// If handleErrors is able to handle the error then the RecoveryPath functor
904/// is called to supply the final result. If handleErrors is not able to
905/// handle all errors then the unhandled errors are returned.
906///
907/// This utility enables the follow pattern:
908///
909/// @code{.cpp}
910/// enum FooStrategy { Aggressive, Conservative };
911/// Expected<Foo> foo(FooStrategy S);
912///
913/// auto ResultOrErr =
914/// handleExpected(
915/// foo(Aggressive),
916/// []() { return foo(Conservative); },
917/// [](AggressiveStrategyError&) {
918/// // Implicitly conusme this - we'll recover by using a conservative
919/// // strategy.
920/// });
921///
922/// @endcode
923template <typename T, typename RecoveryFtor, typename... HandlerTs>
924Expected<T> handleExpected(Expected<T> ValOrErr, RecoveryFtor &&RecoveryPath,
925 HandlerTs &&... Handlers) {
926 if (ValOrErr)
927 return ValOrErr;
928
929 if (auto Err = handleErrors(ValOrErr.takeError(),
930 std::forward<HandlerTs>(Handlers)...))
931 return std::move(Err);
932
933 return RecoveryPath();
934}
935
936/// Log all errors (if any) in E to OS. If there are any errors, ErrorBanner
937/// will be printed before the first one is logged. A newline will be printed
938/// after each error.
939///
940/// This is useful in the base level of your program to allow clean termination
941/// (allowing clean deallocation of resources, etc.), while reporting error
942/// information to the user.
943void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner);
944
945/// Write all error messages (if any) in E to a string. The newline character
946/// is used to separate error messages.
947inline std::string toString(Error E) {
948 SmallVector<std::string, 2> Errors;
949 handleAllErrors(std::move(E), [&Errors](const ErrorInfoBase &EI) {
950 Errors.push_back(EI.message());
951 });
952 return join(Errors.begin(), Errors.end(), "\n");
953}
954
955/// Consume a Error without doing anything. This method should be used
956/// only where an error can be considered a reasonable and expected return
957/// value.
958///
959/// Uses of this method are potentially indicative of design problems: If it's
960/// legitimate to do nothing while processing an "error", the error-producer
961/// might be more clearly refactored to return an Optional<T>.
962inline void consumeError(Error Err) {
963 handleAllErrors(std::move(Err), [](const ErrorInfoBase &) {});
964}
965
966/// Helper for Errors used as out-parameters.
967///
968/// This helper is for use with the Error-as-out-parameter idiom, where an error
969/// is passed to a function or method by reference, rather than being returned.
970/// In such cases it is helpful to set the checked bit on entry to the function
971/// so that the error can be written to (unchecked Errors abort on assignment)
972/// and clear the checked bit on exit so that clients cannot accidentally forget
973/// to check the result. This helper performs these actions automatically using
974/// RAII:
975///
976/// @code{.cpp}
977/// Result foo(Error &Err) {
978/// ErrorAsOutParameter ErrAsOutParam(&Err); // 'Checked' flag set
979/// // <body of foo>
980/// // <- 'Checked' flag auto-cleared when ErrAsOutParam is destructed.
981/// }
982/// @endcode
983///
984/// ErrorAsOutParameter takes an Error* rather than Error& so that it can be
985/// used with optional Errors (Error pointers that are allowed to be null). If
986/// ErrorAsOutParameter took an Error reference, an instance would have to be
987/// created inside every condition that verified that Error was non-null. By
988/// taking an Error pointer we can just create one instance at the top of the
989/// function.
990class ErrorAsOutParameter {
991public:
992 ErrorAsOutParameter(Error *Err) : Err(Err) {
993 // Raise the checked bit if Err is success.
994 if (Err)
995 (void)!!*Err;
996 }
997
998 ~ErrorAsOutParameter() {
999 // Clear the checked bit.
1000 if (Err && !*Err)
1001 *Err = Error::success();
1002 }
1003
1004private:
1005 Error *Err;
1006};
1007
1008/// Helper for Expected<T>s used as out-parameters.
1009///
1010/// See ErrorAsOutParameter.
1011template <typename T>
1012class ExpectedAsOutParameter {
1013public:
1014 ExpectedAsOutParameter(Expected<T> *ValOrErr)
1015 : ValOrErr(ValOrErr) {
1016 if (ValOrErr)
1017 (void)!!*ValOrErr;
1018 }
1019
1020 ~ExpectedAsOutParameter() {
1021 if (ValOrErr)
1022 ValOrErr->setUnchecked();
1023 }
1024
1025private:
1026 Expected<T> *ValOrErr;
1027};
1028
1029/// This class wraps a std::error_code in a Error.
1030///
1031/// This is useful if you're writing an interface that returns a Error
1032/// (or Expected) and you want to call code that still returns
1033/// std::error_codes.
1034class ECError : public ErrorInfo<ECError> {
1035 friend Error errorCodeToError(std::error_code);
1036
1037public:
1038 void setErrorCode(std::error_code EC) { this->EC = EC; }
1039 std::error_code convertToErrorCode() const override { return EC; }
1040 void log(raw_ostream &OS) const override { OS << EC.message(); }
1041
1042 // Used by ErrorInfo::classID.
1043 static char ID;
1044
1045protected:
1046 ECError() = default;
1047 ECError(std::error_code EC) : EC(EC) {}
1048
1049 std::error_code EC;
1050};
1051
1052/// The value returned by this function can be returned from convertToErrorCode
1053/// for Error values where no sensible translation to std::error_code exists.
1054/// It should only be used in this situation, and should never be used where a
1055/// sensible conversion to std::error_code is available, as attempts to convert
1056/// to/from this error will result in a fatal error. (i.e. it is a programmatic
1057///error to try to convert such a value).
1058std::error_code inconvertibleErrorCode();
1059
1060/// Helper for converting an std::error_code to a Error.
1061Error errorCodeToError(std::error_code EC);
1062
1063/// Helper for converting an ECError to a std::error_code.
1064///
1065/// This method requires that Err be Error() or an ECError, otherwise it
1066/// will trigger a call to abort().
1067std::error_code errorToErrorCode(Error Err);
1068
1069/// Convert an ErrorOr<T> to an Expected<T>.
1070template <typename T> Expected<T> errorOrToExpected(ErrorOr<T> &&EO) {
1071 if (auto EC = EO.getError())
1072 return errorCodeToError(EC);
1073 return std::move(*EO);
1074}
1075
1076/// Convert an Expected<T> to an ErrorOr<T>.
1077template <typename T> ErrorOr<T> expectedToErrorOr(Expected<T> &&E) {
1078 if (auto Err = E.takeError())
1079 return errorToErrorCode(std::move(Err));
1080 return std::move(*E);
1081}
1082
1083/// This class wraps a string in an Error.
1084///
1085/// StringError is useful in cases where the client is not expected to be able
1086/// to consume the specific error message programmatically (for example, if the
1087/// error message is to be presented to the user).
1088class StringError : public ErrorInfo<StringError> {
1089public:
1090 static char ID;
1091
1092 StringError(const Twine &S, std::error_code EC);
1093
1094 void log(raw_ostream &OS) const override;
1095 std::error_code convertToErrorCode() const override;
1096
1097 const std::string &getMessage() const { return Msg; }
1098
1099private:
1100 std::string Msg;
1101 std::error_code EC;
1102};
1103
1104/// Helper for check-and-exit error handling.
1105///
1106/// For tool use only. NOT FOR USE IN LIBRARY CODE.
1107///
1108class ExitOnError {
1109public:
1110 /// Create an error on exit helper.
1111 ExitOnError(std::string Banner = "", int DefaultErrorExitCode = 1)
1112 : Banner(std::move(Banner)),
1113 GetExitCode([=](const Error &) { return DefaultErrorExitCode; }) {}
1114
1115 /// Set the banner string for any errors caught by operator().
1116 void setBanner(std::string Banner) { this->Banner = std::move(Banner); }
1117
1118 /// Set the exit-code mapper function.
1119 void setExitCodeMapper(std::function<int(const Error &)> GetExitCode) {
1120 this->GetExitCode = std::move(GetExitCode);
1121 }
1122
1123 /// Check Err. If it's in a failure state log the error(s) and exit.
1124 void operator()(Error Err) const { checkError(std::move(Err)); }
1125
1126 /// Check E. If it's in a success state then return the contained value. If
1127 /// it's in a failure state log the error(s) and exit.
1128 template <typename T> T operator()(Expected<T> &&E) const {
1129 checkError(E.takeError());
1130 return std::move(*E);
1131 }
1132
1133 /// Check E. If it's in a success state then return the contained reference. If
1134 /// it's in a failure state log the error(s) and exit.
1135 template <typename T> T& operator()(Expected<T&> &&E) const {
1136 checkError(E.takeError());
1137 return *E;
1138 }
1139
1140private:
1141 void checkError(Error Err) const {
1142 if (Err) {
1143 int ExitCode = GetExitCode(Err);
1144 logAllUnhandledErrors(std::move(Err), errs(), Banner);
1145 exit(ExitCode);
1146 }
1147 }
1148
1149 std::string Banner;
1150 std::function<int(const Error &)> GetExitCode;
1151};
1152
1153} // end namespace llvm
1154
1155#endif // LLVM_SUPPORT_ERROR_H