Bug Summary

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

Annotated Source Code

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

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