xref: /freebsd-src/contrib/llvm-project/llvm/tools/llvm-objdump/COFFDump.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
10b57cec5SDimitry Andric //===-- COFFDump.cpp - COFF-specific dumper ---------------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric ///
90b57cec5SDimitry Andric /// \file
100b57cec5SDimitry Andric /// This file implements the COFF-specific dumper for llvm-objdump.
110b57cec5SDimitry Andric /// It outputs the Win64 EH data structures as plain text.
120b57cec5SDimitry Andric /// The encoding of the unwind codes is described in MSDN:
13bdd1243dSDimitry Andric /// https://docs.microsoft.com/en-us/cpp/build/exception-handling-x64
140b57cec5SDimitry Andric ///
150b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
160b57cec5SDimitry Andric 
175ffd83dbSDimitry Andric #include "COFFDump.h"
185ffd83dbSDimitry Andric 
190b57cec5SDimitry Andric #include "llvm-objdump.h"
200b57cec5SDimitry Andric #include "llvm/Demangle/Demangle.h"
210b57cec5SDimitry Andric #include "llvm/Object/COFF.h"
220b57cec5SDimitry Andric #include "llvm/Object/COFFImportFile.h"
230b57cec5SDimitry Andric #include "llvm/Object/ObjectFile.h"
240b57cec5SDimitry Andric #include "llvm/Support/Format.h"
250b57cec5SDimitry Andric #include "llvm/Support/Win64EH.h"
260b57cec5SDimitry Andric #include "llvm/Support/WithColor.h"
270b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
280b57cec5SDimitry Andric 
295ffd83dbSDimitry Andric using namespace llvm;
305ffd83dbSDimitry Andric using namespace llvm::objdump;
310b57cec5SDimitry Andric using namespace llvm::object;
320b57cec5SDimitry Andric using namespace llvm::Win64EH;
330b57cec5SDimitry Andric 
34349cc55cSDimitry Andric namespace {
35349cc55cSDimitry Andric template <typename T> struct EnumEntry {
36349cc55cSDimitry Andric   T Value;
37349cc55cSDimitry Andric   StringRef Name;
38349cc55cSDimitry Andric };
39349cc55cSDimitry Andric 
4006c3fb27SDimitry Andric class COFFDumper : public Dumper {
41349cc55cSDimitry Andric public:
COFFDumper(const llvm::object::COFFObjectFile & O)4206c3fb27SDimitry Andric   explicit COFFDumper(const llvm::object::COFFObjectFile &O)
4306c3fb27SDimitry Andric       : Dumper(O), Obj(O) {
44349cc55cSDimitry Andric     Is64 = !Obj.getPE32Header();
45349cc55cSDimitry Andric   }
46349cc55cSDimitry Andric 
47349cc55cSDimitry Andric   template <class PEHeader> void printPEHeader(const PEHeader &Hdr) const;
48*5f757f3fSDimitry Andric   void printPrivateHeaders() override;
49349cc55cSDimitry Andric 
50349cc55cSDimitry Andric private:
formatAddr(T V) const51349cc55cSDimitry Andric   template <typename T> FormattedNumber formatAddr(T V) const {
52349cc55cSDimitry Andric     return format_hex_no_prefix(V, Is64 ? 16 : 8);
53349cc55cSDimitry Andric   }
54349cc55cSDimitry Andric 
getBaseOfData(const void * Hdr) const55349cc55cSDimitry Andric   uint32_t getBaseOfData(const void *Hdr) const {
56349cc55cSDimitry Andric     return Is64 ? 0 : static_cast<const pe32_header *>(Hdr)->BaseOfData;
57349cc55cSDimitry Andric   }
58349cc55cSDimitry Andric 
59349cc55cSDimitry Andric   const llvm::object::COFFObjectFile &Obj;
60349cc55cSDimitry Andric   bool Is64;
61349cc55cSDimitry Andric };
62349cc55cSDimitry Andric } // namespace
63349cc55cSDimitry Andric 
6406c3fb27SDimitry Andric std::unique_ptr<Dumper>
createCOFFDumper(const object::COFFObjectFile & Obj)6506c3fb27SDimitry Andric objdump::createCOFFDumper(const object::COFFObjectFile &Obj) {
6606c3fb27SDimitry Andric   return std::make_unique<COFFDumper>(Obj);
6706c3fb27SDimitry Andric }
6806c3fb27SDimitry Andric 
69349cc55cSDimitry Andric constexpr EnumEntry<uint16_t> PEHeaderMagic[] = {
70349cc55cSDimitry Andric     {uint16_t(COFF::PE32Header::PE32), "PE32"},
71349cc55cSDimitry Andric     {uint16_t(COFF::PE32Header::PE32_PLUS), "PE32+"},
72349cc55cSDimitry Andric };
73349cc55cSDimitry Andric 
74349cc55cSDimitry Andric constexpr EnumEntry<COFF::WindowsSubsystem> PEWindowsSubsystem[] = {
75349cc55cSDimitry Andric     {COFF::IMAGE_SUBSYSTEM_UNKNOWN, "unspecified"},
76349cc55cSDimitry Andric     {COFF::IMAGE_SUBSYSTEM_NATIVE, "NT native"},
77349cc55cSDimitry Andric     {COFF::IMAGE_SUBSYSTEM_WINDOWS_GUI, "Windows GUI"},
78349cc55cSDimitry Andric     {COFF::IMAGE_SUBSYSTEM_WINDOWS_CUI, "Windows CUI"},
79349cc55cSDimitry Andric     {COFF::IMAGE_SUBSYSTEM_POSIX_CUI, "POSIX CUI"},
80349cc55cSDimitry Andric     {COFF::IMAGE_SUBSYSTEM_WINDOWS_CE_GUI, "Wince CUI"},
81349cc55cSDimitry Andric     {COFF::IMAGE_SUBSYSTEM_EFI_APPLICATION, "EFI application"},
82349cc55cSDimitry Andric     {COFF::IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER, "EFI boot service driver"},
83349cc55cSDimitry Andric     {COFF::IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER, "EFI runtime driver"},
84349cc55cSDimitry Andric     {COFF::IMAGE_SUBSYSTEM_EFI_ROM, "SAL runtime driver"},
85349cc55cSDimitry Andric     {COFF::IMAGE_SUBSYSTEM_XBOX, "XBOX"},
86349cc55cSDimitry Andric };
87349cc55cSDimitry Andric 
88349cc55cSDimitry Andric template <typename T, typename TEnum>
printOptionalEnumName(T Value,ArrayRef<EnumEntry<TEnum>> EnumValues)89349cc55cSDimitry Andric static void printOptionalEnumName(T Value,
90349cc55cSDimitry Andric                                   ArrayRef<EnumEntry<TEnum>> EnumValues) {
91349cc55cSDimitry Andric   for (const EnumEntry<TEnum> &I : EnumValues)
92349cc55cSDimitry Andric     if (I.Value == Value) {
93349cc55cSDimitry Andric       outs() << "\t(" << I.Name << ')';
94349cc55cSDimitry Andric       return;
95349cc55cSDimitry Andric     }
96349cc55cSDimitry Andric }
97349cc55cSDimitry Andric 
98349cc55cSDimitry Andric template <class PEHeader>
printPEHeader(const PEHeader & Hdr) const99349cc55cSDimitry Andric void COFFDumper::printPEHeader(const PEHeader &Hdr) const {
100349cc55cSDimitry Andric   auto print = [](const char *K, auto V, const char *Fmt = "%d\n") {
101349cc55cSDimitry Andric     outs() << format("%-23s ", K) << format(Fmt, V);
102349cc55cSDimitry Andric   };
103349cc55cSDimitry Andric   auto printU16 = [&](const char *K, support::ulittle16_t V,
104349cc55cSDimitry Andric                       const char *Fmt = "%d\n") { print(K, uint16_t(V), Fmt); };
105349cc55cSDimitry Andric   auto printU32 = [&](const char *K, support::ulittle32_t V,
106349cc55cSDimitry Andric                       const char *Fmt = "%d\n") { print(K, uint32_t(V), Fmt); };
107349cc55cSDimitry Andric   auto printAddr = [=](const char *K, uint64_t V) {
108349cc55cSDimitry Andric     outs() << format("%-23s ", K) << formatAddr(V) << '\n';
109349cc55cSDimitry Andric   };
110349cc55cSDimitry Andric 
111349cc55cSDimitry Andric   printU16("Magic", Hdr.Magic, "%04x");
112bdd1243dSDimitry Andric   printOptionalEnumName(Hdr.Magic, ArrayRef(PEHeaderMagic));
113349cc55cSDimitry Andric   outs() << '\n';
114349cc55cSDimitry Andric   print("MajorLinkerVersion", Hdr.MajorLinkerVersion);
115349cc55cSDimitry Andric   print("MinorLinkerVersion", Hdr.MinorLinkerVersion);
116349cc55cSDimitry Andric   printAddr("SizeOfCode", Hdr.SizeOfCode);
117349cc55cSDimitry Andric   printAddr("SizeOfInitializedData", Hdr.SizeOfInitializedData);
118349cc55cSDimitry Andric   printAddr("SizeOfUninitializedData", Hdr.SizeOfUninitializedData);
119349cc55cSDimitry Andric   printAddr("AddressOfEntryPoint", Hdr.AddressOfEntryPoint);
120349cc55cSDimitry Andric   printAddr("BaseOfCode", Hdr.BaseOfCode);
121349cc55cSDimitry Andric   if (!Is64)
122349cc55cSDimitry Andric     printAddr("BaseOfData", getBaseOfData(&Hdr));
123349cc55cSDimitry Andric   printAddr("ImageBase", Hdr.ImageBase);
124349cc55cSDimitry Andric   printU32("SectionAlignment", Hdr.SectionAlignment, "%08x\n");
125349cc55cSDimitry Andric   printU32("FileAlignment", Hdr.FileAlignment, "%08x\n");
126349cc55cSDimitry Andric   printU16("MajorOSystemVersion", Hdr.MajorOperatingSystemVersion);
127349cc55cSDimitry Andric   printU16("MinorOSystemVersion", Hdr.MinorOperatingSystemVersion);
128349cc55cSDimitry Andric   printU16("MajorImageVersion", Hdr.MajorImageVersion);
129349cc55cSDimitry Andric   printU16("MinorImageVersion", Hdr.MinorImageVersion);
130349cc55cSDimitry Andric   printU16("MajorSubsystemVersion", Hdr.MajorSubsystemVersion);
131349cc55cSDimitry Andric   printU16("MinorSubsystemVersion", Hdr.MinorSubsystemVersion);
132349cc55cSDimitry Andric   printU32("Win32Version", Hdr.Win32VersionValue, "%08x\n");
133349cc55cSDimitry Andric   printU32("SizeOfImage", Hdr.SizeOfImage, "%08x\n");
134349cc55cSDimitry Andric   printU32("SizeOfHeaders", Hdr.SizeOfHeaders, "%08x\n");
135349cc55cSDimitry Andric   printU32("CheckSum", Hdr.CheckSum, "%08x\n");
136349cc55cSDimitry Andric   printU16("Subsystem", Hdr.Subsystem, "%08x");
137bdd1243dSDimitry Andric   printOptionalEnumName(Hdr.Subsystem, ArrayRef(PEWindowsSubsystem));
138349cc55cSDimitry Andric   outs() << '\n';
139349cc55cSDimitry Andric 
140349cc55cSDimitry Andric   printU16("DllCharacteristics", Hdr.DLLCharacteristics, "%08x\n");
141349cc55cSDimitry Andric #define FLAG(Name)                                                             \
142349cc55cSDimitry Andric   if (Hdr.DLLCharacteristics & COFF::IMAGE_DLL_CHARACTERISTICS_##Name)         \
143349cc55cSDimitry Andric     outs() << "\t\t\t\t\t" << #Name << '\n';
144349cc55cSDimitry Andric   FLAG(HIGH_ENTROPY_VA);
145349cc55cSDimitry Andric   FLAG(DYNAMIC_BASE);
146349cc55cSDimitry Andric   FLAG(FORCE_INTEGRITY);
147349cc55cSDimitry Andric   FLAG(NX_COMPAT);
148349cc55cSDimitry Andric   FLAG(NO_ISOLATION);
149349cc55cSDimitry Andric   FLAG(NO_SEH);
150349cc55cSDimitry Andric   FLAG(NO_BIND);
151349cc55cSDimitry Andric   FLAG(APPCONTAINER);
152349cc55cSDimitry Andric   FLAG(WDM_DRIVER);
153349cc55cSDimitry Andric   FLAG(GUARD_CF);
154349cc55cSDimitry Andric   FLAG(TERMINAL_SERVER_AWARE);
155349cc55cSDimitry Andric #undef FLAG
156349cc55cSDimitry Andric 
157349cc55cSDimitry Andric   printAddr("SizeOfStackReserve", Hdr.SizeOfStackReserve);
158349cc55cSDimitry Andric   printAddr("SizeOfStackCommit", Hdr.SizeOfStackCommit);
159349cc55cSDimitry Andric   printAddr("SizeOfHeapReserve", Hdr.SizeOfHeapReserve);
160349cc55cSDimitry Andric   printAddr("SizeOfHeapCommit", Hdr.SizeOfHeapCommit);
161349cc55cSDimitry Andric   printU32("LoaderFlags", Hdr.LoaderFlags, "%08x\n");
162349cc55cSDimitry Andric   printU32("NumberOfRvaAndSizes", Hdr.NumberOfRvaAndSize, "%08x\n");
163349cc55cSDimitry Andric 
164349cc55cSDimitry Andric   static const char *DirName[COFF::NUM_DATA_DIRECTORIES + 1] = {
165349cc55cSDimitry Andric       "Export Directory [.edata (or where ever we found it)]",
166349cc55cSDimitry Andric       "Import Directory [parts of .idata]",
167349cc55cSDimitry Andric       "Resource Directory [.rsrc]",
168349cc55cSDimitry Andric       "Exception Directory [.pdata]",
169349cc55cSDimitry Andric       "Security Directory",
170349cc55cSDimitry Andric       "Base Relocation Directory [.reloc]",
171349cc55cSDimitry Andric       "Debug Directory",
172349cc55cSDimitry Andric       "Description Directory",
173349cc55cSDimitry Andric       "Special Directory",
174349cc55cSDimitry Andric       "Thread Storage Directory [.tls]",
175349cc55cSDimitry Andric       "Load Configuration Directory",
176349cc55cSDimitry Andric       "Bound Import Directory",
177349cc55cSDimitry Andric       "Import Address Table Directory",
178349cc55cSDimitry Andric       "Delay Import Directory",
179349cc55cSDimitry Andric       "CLR Runtime Header",
180349cc55cSDimitry Andric       "Reserved",
181349cc55cSDimitry Andric   };
182349cc55cSDimitry Andric   outs() << "\nThe Data Directory\n";
183bdd1243dSDimitry Andric   for (uint32_t I = 0; I != std::size(DirName); ++I) {
184349cc55cSDimitry Andric     uint32_t Addr = 0, Size = 0;
185349cc55cSDimitry Andric     if (const data_directory *Data = Obj.getDataDirectory(I)) {
186349cc55cSDimitry Andric       Addr = Data->RelativeVirtualAddress;
187349cc55cSDimitry Andric       Size = Data->Size;
188349cc55cSDimitry Andric     }
189349cc55cSDimitry Andric     outs() << format("Entry %x ", I) << formatAddr(Addr)
190349cc55cSDimitry Andric            << format(" %08x %s\n", uint32_t(Size), DirName[I]);
191349cc55cSDimitry Andric   }
192349cc55cSDimitry Andric }
193349cc55cSDimitry Andric 
1940b57cec5SDimitry Andric // Returns the name of the unwind code.
getUnwindCodeTypeName(uint8_t Code)1950b57cec5SDimitry Andric static StringRef getUnwindCodeTypeName(uint8_t Code) {
1960b57cec5SDimitry Andric   switch(Code) {
1970b57cec5SDimitry Andric   default: llvm_unreachable("Invalid unwind code");
1980b57cec5SDimitry Andric   case UOP_PushNonVol: return "UOP_PushNonVol";
1990b57cec5SDimitry Andric   case UOP_AllocLarge: return "UOP_AllocLarge";
2000b57cec5SDimitry Andric   case UOP_AllocSmall: return "UOP_AllocSmall";
2010b57cec5SDimitry Andric   case UOP_SetFPReg: return "UOP_SetFPReg";
2020b57cec5SDimitry Andric   case UOP_SaveNonVol: return "UOP_SaveNonVol";
2030b57cec5SDimitry Andric   case UOP_SaveNonVolBig: return "UOP_SaveNonVolBig";
204bdd1243dSDimitry Andric   case UOP_Epilog: return "UOP_Epilog";
205bdd1243dSDimitry Andric   case UOP_SpareCode: return "UOP_SpareCode";
2060b57cec5SDimitry Andric   case UOP_SaveXMM128: return "UOP_SaveXMM128";
2070b57cec5SDimitry Andric   case UOP_SaveXMM128Big: return "UOP_SaveXMM128Big";
2080b57cec5SDimitry Andric   case UOP_PushMachFrame: return "UOP_PushMachFrame";
2090b57cec5SDimitry Andric   }
2100b57cec5SDimitry Andric }
2110b57cec5SDimitry Andric 
2120b57cec5SDimitry Andric // Returns the name of a referenced register.
getUnwindRegisterName(uint8_t Reg)2130b57cec5SDimitry Andric static StringRef getUnwindRegisterName(uint8_t Reg) {
2140b57cec5SDimitry Andric   switch(Reg) {
2150b57cec5SDimitry Andric   default: llvm_unreachable("Invalid register");
2160b57cec5SDimitry Andric   case 0: return "RAX";
2170b57cec5SDimitry Andric   case 1: return "RCX";
2180b57cec5SDimitry Andric   case 2: return "RDX";
2190b57cec5SDimitry Andric   case 3: return "RBX";
2200b57cec5SDimitry Andric   case 4: return "RSP";
2210b57cec5SDimitry Andric   case 5: return "RBP";
2220b57cec5SDimitry Andric   case 6: return "RSI";
2230b57cec5SDimitry Andric   case 7: return "RDI";
2240b57cec5SDimitry Andric   case 8: return "R8";
2250b57cec5SDimitry Andric   case 9: return "R9";
2260b57cec5SDimitry Andric   case 10: return "R10";
2270b57cec5SDimitry Andric   case 11: return "R11";
2280b57cec5SDimitry Andric   case 12: return "R12";
2290b57cec5SDimitry Andric   case 13: return "R13";
2300b57cec5SDimitry Andric   case 14: return "R14";
2310b57cec5SDimitry Andric   case 15: return "R15";
2320b57cec5SDimitry Andric   }
2330b57cec5SDimitry Andric }
2340b57cec5SDimitry Andric 
2350b57cec5SDimitry Andric // Calculates the number of array slots required for the unwind code.
getNumUsedSlots(const UnwindCode & UnwindCode)2360b57cec5SDimitry Andric static unsigned getNumUsedSlots(const UnwindCode &UnwindCode) {
2370b57cec5SDimitry Andric   switch (UnwindCode.getUnwindOp()) {
2380b57cec5SDimitry Andric   default: llvm_unreachable("Invalid unwind code");
2390b57cec5SDimitry Andric   case UOP_PushNonVol:
2400b57cec5SDimitry Andric   case UOP_AllocSmall:
2410b57cec5SDimitry Andric   case UOP_SetFPReg:
2420b57cec5SDimitry Andric   case UOP_PushMachFrame:
2430b57cec5SDimitry Andric     return 1;
2440b57cec5SDimitry Andric   case UOP_SaveNonVol:
2450b57cec5SDimitry Andric   case UOP_SaveXMM128:
246bdd1243dSDimitry Andric   case UOP_Epilog:
2470b57cec5SDimitry Andric     return 2;
2480b57cec5SDimitry Andric   case UOP_SaveNonVolBig:
2490b57cec5SDimitry Andric   case UOP_SaveXMM128Big:
250bdd1243dSDimitry Andric   case UOP_SpareCode:
2510b57cec5SDimitry Andric     return 3;
2520b57cec5SDimitry Andric   case UOP_AllocLarge:
2530b57cec5SDimitry Andric     return (UnwindCode.getOpInfo() == 0) ? 2 : 3;
2540b57cec5SDimitry Andric   }
2550b57cec5SDimitry Andric }
2560b57cec5SDimitry Andric 
2570b57cec5SDimitry Andric // Prints one unwind code. Because an unwind code can occupy up to 3 slots in
2580b57cec5SDimitry Andric // the unwind codes array, this function requires that the correct number of
2590b57cec5SDimitry Andric // slots is provided.
printUnwindCode(ArrayRef<UnwindCode> UCs)2600b57cec5SDimitry Andric static void printUnwindCode(ArrayRef<UnwindCode> UCs) {
2610b57cec5SDimitry Andric   assert(UCs.size() >= getNumUsedSlots(UCs[0]));
2620b57cec5SDimitry Andric   outs() <<  format("      0x%02x: ", unsigned(UCs[0].u.CodeOffset))
2630b57cec5SDimitry Andric          << getUnwindCodeTypeName(UCs[0].getUnwindOp());
2640b57cec5SDimitry Andric   switch (UCs[0].getUnwindOp()) {
2650b57cec5SDimitry Andric   case UOP_PushNonVol:
2660b57cec5SDimitry Andric     outs() << " " << getUnwindRegisterName(UCs[0].getOpInfo());
2670b57cec5SDimitry Andric     break;
2680b57cec5SDimitry Andric   case UOP_AllocLarge:
2690b57cec5SDimitry Andric     if (UCs[0].getOpInfo() == 0) {
2700b57cec5SDimitry Andric       outs() << " " << UCs[1].FrameOffset;
2710b57cec5SDimitry Andric     } else {
2720b57cec5SDimitry Andric       outs() << " " << UCs[1].FrameOffset
2730b57cec5SDimitry Andric                        + (static_cast<uint32_t>(UCs[2].FrameOffset) << 16);
2740b57cec5SDimitry Andric     }
2750b57cec5SDimitry Andric     break;
2760b57cec5SDimitry Andric   case UOP_AllocSmall:
2770b57cec5SDimitry Andric     outs() << " " << ((UCs[0].getOpInfo() + 1) * 8);
2780b57cec5SDimitry Andric     break;
2790b57cec5SDimitry Andric   case UOP_SetFPReg:
2800b57cec5SDimitry Andric     outs() << " ";
2810b57cec5SDimitry Andric     break;
2820b57cec5SDimitry Andric   case UOP_SaveNonVol:
2830b57cec5SDimitry Andric     outs() << " " << getUnwindRegisterName(UCs[0].getOpInfo())
2840b57cec5SDimitry Andric            << format(" [0x%04x]", 8 * UCs[1].FrameOffset);
2850b57cec5SDimitry Andric     break;
2860b57cec5SDimitry Andric   case UOP_SaveNonVolBig:
2870b57cec5SDimitry Andric     outs() << " " << getUnwindRegisterName(UCs[0].getOpInfo())
2880b57cec5SDimitry Andric            << format(" [0x%08x]", UCs[1].FrameOffset
2890b57cec5SDimitry Andric                     + (static_cast<uint32_t>(UCs[2].FrameOffset) << 16));
2900b57cec5SDimitry Andric     break;
2910b57cec5SDimitry Andric   case UOP_SaveXMM128:
2920b57cec5SDimitry Andric     outs() << " XMM" << static_cast<uint32_t>(UCs[0].getOpInfo())
2930b57cec5SDimitry Andric            << format(" [0x%04x]", 16 * UCs[1].FrameOffset);
2940b57cec5SDimitry Andric     break;
2950b57cec5SDimitry Andric   case UOP_SaveXMM128Big:
2960b57cec5SDimitry Andric     outs() << " XMM" << UCs[0].getOpInfo()
2970b57cec5SDimitry Andric            << format(" [0x%08x]", UCs[1].FrameOffset
2980b57cec5SDimitry Andric                            + (static_cast<uint32_t>(UCs[2].FrameOffset) << 16));
2990b57cec5SDimitry Andric     break;
3000b57cec5SDimitry Andric   case UOP_PushMachFrame:
3010b57cec5SDimitry Andric     outs() << " " << (UCs[0].getOpInfo() ? "w/o" : "w")
3020b57cec5SDimitry Andric            << " error code";
3030b57cec5SDimitry Andric     break;
3040b57cec5SDimitry Andric   }
3050b57cec5SDimitry Andric   outs() << "\n";
3060b57cec5SDimitry Andric }
3070b57cec5SDimitry Andric 
printAllUnwindCodes(ArrayRef<UnwindCode> UCs)3080b57cec5SDimitry Andric static void printAllUnwindCodes(ArrayRef<UnwindCode> UCs) {
3090b57cec5SDimitry Andric   for (const UnwindCode *I = UCs.begin(), *E = UCs.end(); I < E; ) {
3100b57cec5SDimitry Andric     unsigned UsedSlots = getNumUsedSlots(*I);
3110b57cec5SDimitry Andric     if (UsedSlots > UCs.size()) {
3120b57cec5SDimitry Andric       outs() << "Unwind data corrupted: Encountered unwind op "
3130b57cec5SDimitry Andric              << getUnwindCodeTypeName((*I).getUnwindOp())
3140b57cec5SDimitry Andric              << " which requires " << UsedSlots
3150b57cec5SDimitry Andric              << " slots, but only " << UCs.size()
3160b57cec5SDimitry Andric              << " remaining in buffer";
3170b57cec5SDimitry Andric       return ;
3180b57cec5SDimitry Andric     }
319bdd1243dSDimitry Andric     printUnwindCode(ArrayRef(I, E));
3200b57cec5SDimitry Andric     I += UsedSlots;
3210b57cec5SDimitry Andric   }
3220b57cec5SDimitry Andric }
3230b57cec5SDimitry Andric 
3240b57cec5SDimitry Andric // Given a symbol sym this functions returns the address and section of it.
resolveSectionAndAddress(const COFFObjectFile * Obj,const SymbolRef & Sym,const coff_section * & ResolvedSection,uint64_t & ResolvedAddr)3250b57cec5SDimitry Andric static Error resolveSectionAndAddress(const COFFObjectFile *Obj,
3260b57cec5SDimitry Andric                                       const SymbolRef &Sym,
3270b57cec5SDimitry Andric                                       const coff_section *&ResolvedSection,
3280b57cec5SDimitry Andric                                       uint64_t &ResolvedAddr) {
3290b57cec5SDimitry Andric   Expected<uint64_t> ResolvedAddrOrErr = Sym.getAddress();
3300b57cec5SDimitry Andric   if (!ResolvedAddrOrErr)
3310b57cec5SDimitry Andric     return ResolvedAddrOrErr.takeError();
3320b57cec5SDimitry Andric   ResolvedAddr = *ResolvedAddrOrErr;
3330b57cec5SDimitry Andric   Expected<section_iterator> Iter = Sym.getSection();
3340b57cec5SDimitry Andric   if (!Iter)
3350b57cec5SDimitry Andric     return Iter.takeError();
3360b57cec5SDimitry Andric   ResolvedSection = Obj->getCOFFSection(**Iter);
3370b57cec5SDimitry Andric   return Error::success();
3380b57cec5SDimitry Andric }
3390b57cec5SDimitry Andric 
3400b57cec5SDimitry Andric // Given a vector of relocations for a section and an offset into this section
3410b57cec5SDimitry Andric // the function returns the symbol used for the relocation at the offset.
resolveSymbol(const std::vector<RelocationRef> & Rels,uint64_t Offset,SymbolRef & Sym)3420b57cec5SDimitry Andric static Error resolveSymbol(const std::vector<RelocationRef> &Rels,
3430b57cec5SDimitry Andric                                      uint64_t Offset, SymbolRef &Sym) {
3440b57cec5SDimitry Andric   for (auto &R : Rels) {
3450b57cec5SDimitry Andric     uint64_t Ofs = R.getOffset();
3460b57cec5SDimitry Andric     if (Ofs == Offset) {
3470b57cec5SDimitry Andric       Sym = *R.getSymbol();
3480b57cec5SDimitry Andric       return Error::success();
3490b57cec5SDimitry Andric     }
3500b57cec5SDimitry Andric   }
3510b57cec5SDimitry Andric   return make_error<BinaryError>();
3520b57cec5SDimitry Andric }
3530b57cec5SDimitry Andric 
3540b57cec5SDimitry Andric // Given a vector of relocations for a section and an offset into this section
3550b57cec5SDimitry Andric // the function resolves the symbol used for the relocation at the offset and
3560b57cec5SDimitry Andric // returns the section content and the address inside the content pointed to
3570b57cec5SDimitry Andric // by the symbol.
3580b57cec5SDimitry Andric static Error
getSectionContents(const COFFObjectFile * Obj,const std::vector<RelocationRef> & Rels,uint64_t Offset,ArrayRef<uint8_t> & Contents,uint64_t & Addr)3590b57cec5SDimitry Andric getSectionContents(const COFFObjectFile *Obj,
3600b57cec5SDimitry Andric                    const std::vector<RelocationRef> &Rels, uint64_t Offset,
3610b57cec5SDimitry Andric                    ArrayRef<uint8_t> &Contents, uint64_t &Addr) {
3620b57cec5SDimitry Andric   SymbolRef Sym;
3630b57cec5SDimitry Andric   if (Error E = resolveSymbol(Rels, Offset, Sym))
3640b57cec5SDimitry Andric     return E;
3650b57cec5SDimitry Andric   const coff_section *Section;
3660b57cec5SDimitry Andric   if (Error E = resolveSectionAndAddress(Obj, Sym, Section, Addr))
3670b57cec5SDimitry Andric     return E;
3680b57cec5SDimitry Andric   return Obj->getSectionContents(Section, Contents);
3690b57cec5SDimitry Andric }
3700b57cec5SDimitry Andric 
3710b57cec5SDimitry Andric // Given a vector of relocations for a section and an offset into this section
3720b57cec5SDimitry Andric // the function returns the name of the symbol used for the relocation at the
3730b57cec5SDimitry Andric // offset.
resolveSymbolName(const std::vector<RelocationRef> & Rels,uint64_t Offset,StringRef & Name)3740b57cec5SDimitry Andric static Error resolveSymbolName(const std::vector<RelocationRef> &Rels,
3750b57cec5SDimitry Andric                                uint64_t Offset, StringRef &Name) {
3760b57cec5SDimitry Andric   SymbolRef Sym;
3770b57cec5SDimitry Andric   if (Error EC = resolveSymbol(Rels, Offset, Sym))
3780b57cec5SDimitry Andric     return EC;
3790b57cec5SDimitry Andric   Expected<StringRef> NameOrErr = Sym.getName();
3800b57cec5SDimitry Andric   if (!NameOrErr)
3810b57cec5SDimitry Andric     return NameOrErr.takeError();
3820b57cec5SDimitry Andric   Name = *NameOrErr;
3830b57cec5SDimitry Andric   return Error::success();
3840b57cec5SDimitry Andric }
3850b57cec5SDimitry Andric 
printCOFFSymbolAddress(raw_ostream & Out,const std::vector<RelocationRef> & Rels,uint64_t Offset,uint32_t Disp)3860b57cec5SDimitry Andric static void printCOFFSymbolAddress(raw_ostream &Out,
3870b57cec5SDimitry Andric                                    const std::vector<RelocationRef> &Rels,
3880b57cec5SDimitry Andric                                    uint64_t Offset, uint32_t Disp) {
3890b57cec5SDimitry Andric   StringRef Sym;
3900b57cec5SDimitry Andric   if (!resolveSymbolName(Rels, Offset, Sym)) {
3910b57cec5SDimitry Andric     Out << Sym;
3920b57cec5SDimitry Andric     if (Disp > 0)
3930b57cec5SDimitry Andric       Out << format(" + 0x%04x", Disp);
3940b57cec5SDimitry Andric   } else {
3950b57cec5SDimitry Andric     Out << format("0x%04x", Disp);
3960b57cec5SDimitry Andric   }
3970b57cec5SDimitry Andric }
3980b57cec5SDimitry Andric 
3990b57cec5SDimitry Andric static void
printSEHTable(const COFFObjectFile * Obj,uint32_t TableVA,int Count)4000b57cec5SDimitry Andric printSEHTable(const COFFObjectFile *Obj, uint32_t TableVA, int Count) {
4010b57cec5SDimitry Andric   if (Count == 0)
4020b57cec5SDimitry Andric     return;
4030b57cec5SDimitry Andric 
4040b57cec5SDimitry Andric   uintptr_t IntPtr = 0;
4055ffd83dbSDimitry Andric   if (Error E = Obj->getVaPtr(TableVA, IntPtr))
4065ffd83dbSDimitry Andric     reportError(std::move(E), Obj->getFileName());
4078bcb0991SDimitry Andric 
4080b57cec5SDimitry Andric   const support::ulittle32_t *P = (const support::ulittle32_t *)IntPtr;
4090b57cec5SDimitry Andric   outs() << "SEH Table:";
4100b57cec5SDimitry Andric   for (int I = 0; I < Count; ++I)
4118bcb0991SDimitry Andric     outs() << format(" 0x%x", P[I] + Obj->getPE32Header()->ImageBase);
4120b57cec5SDimitry Andric   outs() << "\n\n";
4130b57cec5SDimitry Andric }
4140b57cec5SDimitry Andric 
4150b57cec5SDimitry Andric template <typename T>
printTLSDirectoryT(const coff_tls_directory<T> * TLSDir)4160b57cec5SDimitry Andric static void printTLSDirectoryT(const coff_tls_directory<T> *TLSDir) {
4170b57cec5SDimitry Andric   size_t FormatWidth = sizeof(T) * 2;
4180b57cec5SDimitry Andric   outs() << "TLS directory:"
4190b57cec5SDimitry Andric          << "\n  StartAddressOfRawData: "
4200b57cec5SDimitry Andric          << format_hex(TLSDir->StartAddressOfRawData, FormatWidth)
4210b57cec5SDimitry Andric          << "\n  EndAddressOfRawData: "
4220b57cec5SDimitry Andric          << format_hex(TLSDir->EndAddressOfRawData, FormatWidth)
4230b57cec5SDimitry Andric          << "\n  AddressOfIndex: "
4240b57cec5SDimitry Andric          << format_hex(TLSDir->AddressOfIndex, FormatWidth)
4250b57cec5SDimitry Andric          << "\n  AddressOfCallBacks: "
4260b57cec5SDimitry Andric          << format_hex(TLSDir->AddressOfCallBacks, FormatWidth)
4270b57cec5SDimitry Andric          << "\n  SizeOfZeroFill: "
4280b57cec5SDimitry Andric          << TLSDir->SizeOfZeroFill
4290b57cec5SDimitry Andric          << "\n  Characteristics: "
4300b57cec5SDimitry Andric          << TLSDir->Characteristics
4310b57cec5SDimitry Andric          << "\n  Alignment: "
4320b57cec5SDimitry Andric          << TLSDir->getAlignment()
4330b57cec5SDimitry Andric          << "\n\n";
4340b57cec5SDimitry Andric }
4350b57cec5SDimitry Andric 
printTLSDirectory(const COFFObjectFile * Obj)4360b57cec5SDimitry Andric static void printTLSDirectory(const COFFObjectFile *Obj) {
4378bcb0991SDimitry Andric   const pe32_header *PE32Header = Obj->getPE32Header();
4388bcb0991SDimitry Andric   const pe32plus_header *PE32PlusHeader = Obj->getPE32PlusHeader();
4390b57cec5SDimitry Andric 
4400b57cec5SDimitry Andric   // Skip if it's not executable.
4410b57cec5SDimitry Andric   if (!PE32Header && !PE32PlusHeader)
4420b57cec5SDimitry Andric     return;
4430b57cec5SDimitry Andric 
4440b57cec5SDimitry Andric   if (PE32Header) {
44581ad6265SDimitry Andric     if (auto *TLSDir = Obj->getTLSDirectory32())
4460b57cec5SDimitry Andric       printTLSDirectoryT(TLSDir);
4470b57cec5SDimitry Andric   } else {
44881ad6265SDimitry Andric     if (auto *TLSDir = Obj->getTLSDirectory64())
4490b57cec5SDimitry Andric       printTLSDirectoryT(TLSDir);
4500b57cec5SDimitry Andric   }
4510b57cec5SDimitry Andric 
4520b57cec5SDimitry Andric   outs() << "\n";
4530b57cec5SDimitry Andric }
4540b57cec5SDimitry Andric 
printLoadConfiguration(const COFFObjectFile * Obj)4550b57cec5SDimitry Andric static void printLoadConfiguration(const COFFObjectFile *Obj) {
4560b57cec5SDimitry Andric   // Skip if it's not executable.
4578bcb0991SDimitry Andric   if (!Obj->getPE32Header())
4580b57cec5SDimitry Andric     return;
4590b57cec5SDimitry Andric 
4600b57cec5SDimitry Andric   // Currently only x86 is supported
4610b57cec5SDimitry Andric   if (Obj->getMachine() != COFF::IMAGE_FILE_MACHINE_I386)
4620b57cec5SDimitry Andric     return;
4630b57cec5SDimitry Andric 
46481ad6265SDimitry Andric   auto *LoadConf = Obj->getLoadConfig32();
46581ad6265SDimitry Andric   if (!LoadConf)
4660b57cec5SDimitry Andric     return;
4678bcb0991SDimitry Andric 
4680b57cec5SDimitry Andric   outs() << "Load configuration:"
4690b57cec5SDimitry Andric          << "\n  Timestamp: " << LoadConf->TimeDateStamp
4700b57cec5SDimitry Andric          << "\n  Major Version: " << LoadConf->MajorVersion
4710b57cec5SDimitry Andric          << "\n  Minor Version: " << LoadConf->MinorVersion
4720b57cec5SDimitry Andric          << "\n  GlobalFlags Clear: " << LoadConf->GlobalFlagsClear
4730b57cec5SDimitry Andric          << "\n  GlobalFlags Set: " << LoadConf->GlobalFlagsSet
4740b57cec5SDimitry Andric          << "\n  Critical Section Default Timeout: " << LoadConf->CriticalSectionDefaultTimeout
4750b57cec5SDimitry Andric          << "\n  Decommit Free Block Threshold: " << LoadConf->DeCommitFreeBlockThreshold
4760b57cec5SDimitry Andric          << "\n  Decommit Total Free Threshold: " << LoadConf->DeCommitTotalFreeThreshold
4770b57cec5SDimitry Andric          << "\n  Lock Prefix Table: " << LoadConf->LockPrefixTable
4780b57cec5SDimitry Andric          << "\n  Maximum Allocation Size: " << LoadConf->MaximumAllocationSize
4790b57cec5SDimitry Andric          << "\n  Virtual Memory Threshold: " << LoadConf->VirtualMemoryThreshold
4800b57cec5SDimitry Andric          << "\n  Process Affinity Mask: " << LoadConf->ProcessAffinityMask
4810b57cec5SDimitry Andric          << "\n  Process Heap Flags: " << LoadConf->ProcessHeapFlags
4820b57cec5SDimitry Andric          << "\n  CSD Version: " << LoadConf->CSDVersion
4830b57cec5SDimitry Andric          << "\n  Security Cookie: " << LoadConf->SecurityCookie
4840b57cec5SDimitry Andric          << "\n  SEH Table: " << LoadConf->SEHandlerTable
4850b57cec5SDimitry Andric          << "\n  SEH Count: " << LoadConf->SEHandlerCount
4860b57cec5SDimitry Andric          << "\n\n";
4870b57cec5SDimitry Andric   printSEHTable(Obj, LoadConf->SEHandlerTable, LoadConf->SEHandlerCount);
4880b57cec5SDimitry Andric   outs() << "\n";
4890b57cec5SDimitry Andric }
4900b57cec5SDimitry Andric 
4910b57cec5SDimitry Andric // Prints import tables. The import table is a table containing the list of
4920b57cec5SDimitry Andric // DLL name and symbol names which will be linked by the loader.
printImportTables(const COFFObjectFile * Obj)4930b57cec5SDimitry Andric static void printImportTables(const COFFObjectFile *Obj) {
4940b57cec5SDimitry Andric   import_directory_iterator I = Obj->import_directory_begin();
4950b57cec5SDimitry Andric   import_directory_iterator E = Obj->import_directory_end();
4960b57cec5SDimitry Andric   if (I == E)
4970b57cec5SDimitry Andric     return;
4980b57cec5SDimitry Andric   outs() << "The Import Tables:\n";
4990b57cec5SDimitry Andric   for (const ImportDirectoryEntryRef &DirRef : Obj->import_directories()) {
5000b57cec5SDimitry Andric     const coff_import_directory_table_entry *Dir;
5010b57cec5SDimitry Andric     StringRef Name;
5020b57cec5SDimitry Andric     if (DirRef.getImportTableEntry(Dir)) return;
5030b57cec5SDimitry Andric     if (DirRef.getName(Name)) return;
5040b57cec5SDimitry Andric 
5050b57cec5SDimitry Andric     outs() << format("  lookup %08x time %08x fwd %08x name %08x addr %08x\n\n",
5060b57cec5SDimitry Andric                      static_cast<uint32_t>(Dir->ImportLookupTableRVA),
5070b57cec5SDimitry Andric                      static_cast<uint32_t>(Dir->TimeDateStamp),
5080b57cec5SDimitry Andric                      static_cast<uint32_t>(Dir->ForwarderChain),
5090b57cec5SDimitry Andric                      static_cast<uint32_t>(Dir->NameRVA),
5100b57cec5SDimitry Andric                      static_cast<uint32_t>(Dir->ImportAddressTableRVA));
5110b57cec5SDimitry Andric     outs() << "    DLL Name: " << Name << "\n";
5120b57cec5SDimitry Andric     outs() << "    Hint/Ord  Name\n";
5130b57cec5SDimitry Andric     for (const ImportedSymbolRef &Entry : DirRef.imported_symbols()) {
5140b57cec5SDimitry Andric       bool IsOrdinal;
5150b57cec5SDimitry Andric       if (Entry.isOrdinal(IsOrdinal))
5160b57cec5SDimitry Andric         return;
5170b57cec5SDimitry Andric       if (IsOrdinal) {
5180b57cec5SDimitry Andric         uint16_t Ordinal;
5190b57cec5SDimitry Andric         if (Entry.getOrdinal(Ordinal))
5200b57cec5SDimitry Andric           return;
5210b57cec5SDimitry Andric         outs() << format("      % 6d\n", Ordinal);
5220b57cec5SDimitry Andric         continue;
5230b57cec5SDimitry Andric       }
5240b57cec5SDimitry Andric       uint32_t HintNameRVA;
5250b57cec5SDimitry Andric       if (Entry.getHintNameRVA(HintNameRVA))
5260b57cec5SDimitry Andric         return;
5270b57cec5SDimitry Andric       uint16_t Hint;
5280b57cec5SDimitry Andric       StringRef Name;
5290b57cec5SDimitry Andric       if (Obj->getHintName(HintNameRVA, Hint, Name))
5300b57cec5SDimitry Andric         return;
5310b57cec5SDimitry Andric       outs() << format("      % 6d  ", Hint) << Name << "\n";
5320b57cec5SDimitry Andric     }
5330b57cec5SDimitry Andric     outs() << "\n";
5340b57cec5SDimitry Andric   }
5350b57cec5SDimitry Andric }
5360b57cec5SDimitry Andric 
5370b57cec5SDimitry Andric // Prints export tables. The export table is a table containing the list of
5380b57cec5SDimitry Andric // exported symbol from the DLL.
printExportTable(const COFFObjectFile * Obj)5390b57cec5SDimitry Andric static void printExportTable(const COFFObjectFile *Obj) {
5400b57cec5SDimitry Andric   export_directory_iterator I = Obj->export_directory_begin();
5410b57cec5SDimitry Andric   export_directory_iterator E = Obj->export_directory_end();
5420b57cec5SDimitry Andric   if (I == E)
5430b57cec5SDimitry Andric     return;
54481ad6265SDimitry Andric   outs() << "Export Table:\n";
5450b57cec5SDimitry Andric   StringRef DllName;
5460b57cec5SDimitry Andric   uint32_t OrdinalBase;
5470b57cec5SDimitry Andric   if (I->getDllName(DllName))
5480b57cec5SDimitry Andric     return;
5490b57cec5SDimitry Andric   if (I->getOrdinalBase(OrdinalBase))
5500b57cec5SDimitry Andric     return;
5510b57cec5SDimitry Andric   outs() << " DLL name: " << DllName << "\n";
5520b57cec5SDimitry Andric   outs() << " Ordinal base: " << OrdinalBase << "\n";
5530b57cec5SDimitry Andric   outs() << " Ordinal      RVA  Name\n";
5540b57cec5SDimitry Andric   for (; I != E; I = ++I) {
5550b57cec5SDimitry Andric     uint32_t RVA;
5560b57cec5SDimitry Andric     if (I->getExportRVA(RVA))
5570b57cec5SDimitry Andric       return;
55806c3fb27SDimitry Andric     StringRef Name;
55906c3fb27SDimitry Andric     if (I->getSymbolName(Name))
56006c3fb27SDimitry Andric       continue;
56106c3fb27SDimitry Andric     if (!RVA && Name.empty())
56206c3fb27SDimitry Andric       continue;
56306c3fb27SDimitry Andric 
56406c3fb27SDimitry Andric     uint32_t Ordinal;
56506c3fb27SDimitry Andric     if (I->getOrdinal(Ordinal))
56606c3fb27SDimitry Andric       return;
5670b57cec5SDimitry Andric     bool IsForwarder;
5680b57cec5SDimitry Andric     if (I->isForwarder(IsForwarder))
5690b57cec5SDimitry Andric       return;
5700b57cec5SDimitry Andric 
5710b57cec5SDimitry Andric     if (IsForwarder) {
5720b57cec5SDimitry Andric       // Export table entries can be used to re-export symbols that
5730b57cec5SDimitry Andric       // this COFF file is imported from some DLLs. This is rare.
5740b57cec5SDimitry Andric       // In most cases IsForwarder is false.
57506c3fb27SDimitry Andric       outs() << format("   %5d         ", Ordinal);
5760b57cec5SDimitry Andric     } else {
57706c3fb27SDimitry Andric       outs() << format("   %5d %# 8x", Ordinal, RVA);
5780b57cec5SDimitry Andric     }
5790b57cec5SDimitry Andric 
5800b57cec5SDimitry Andric     if (!Name.empty())
5810b57cec5SDimitry Andric       outs() << "  " << Name;
5820b57cec5SDimitry Andric     if (IsForwarder) {
5830b57cec5SDimitry Andric       StringRef S;
5840b57cec5SDimitry Andric       if (I->getForwardTo(S))
5850b57cec5SDimitry Andric         return;
5860b57cec5SDimitry Andric       outs() << " (forwarded to " << S << ")";
5870b57cec5SDimitry Andric     }
5880b57cec5SDimitry Andric     outs() << "\n";
5890b57cec5SDimitry Andric   }
5900b57cec5SDimitry Andric }
5910b57cec5SDimitry Andric 
5920b57cec5SDimitry Andric // Given the COFF object file, this function returns the relocations for .pdata
5930b57cec5SDimitry Andric // and the pointer to "runtime function" structs.
getPDataSection(const COFFObjectFile * Obj,std::vector<RelocationRef> & Rels,const RuntimeFunction * & RFStart,int & NumRFs)5940b57cec5SDimitry Andric static bool getPDataSection(const COFFObjectFile *Obj,
5950b57cec5SDimitry Andric                             std::vector<RelocationRef> &Rels,
5960b57cec5SDimitry Andric                             const RuntimeFunction *&RFStart, int &NumRFs) {
5970b57cec5SDimitry Andric   for (const SectionRef &Section : Obj->sections()) {
5988bcb0991SDimitry Andric     StringRef Name = unwrapOrError(Section.getName(), Obj->getFileName());
5990b57cec5SDimitry Andric     if (Name != ".pdata")
6000b57cec5SDimitry Andric       continue;
6010b57cec5SDimitry Andric 
6020b57cec5SDimitry Andric     const coff_section *Pdata = Obj->getCOFFSection(Section);
603fe6060f1SDimitry Andric     append_range(Rels, Section.relocations());
6040b57cec5SDimitry Andric 
6050b57cec5SDimitry Andric     // Sort relocations by address.
6060b57cec5SDimitry Andric     llvm::sort(Rels, isRelocAddressLess);
6070b57cec5SDimitry Andric 
6080b57cec5SDimitry Andric     ArrayRef<uint8_t> Contents;
6098bcb0991SDimitry Andric     if (Error E = Obj->getSectionContents(Pdata, Contents))
6108bcb0991SDimitry Andric       reportError(std::move(E), Obj->getFileName());
6118bcb0991SDimitry Andric 
6120b57cec5SDimitry Andric     if (Contents.empty())
6130b57cec5SDimitry Andric       continue;
6140b57cec5SDimitry Andric 
6150b57cec5SDimitry Andric     RFStart = reinterpret_cast<const RuntimeFunction *>(Contents.data());
6160b57cec5SDimitry Andric     NumRFs = Contents.size() / sizeof(RuntimeFunction);
6170b57cec5SDimitry Andric     return true;
6180b57cec5SDimitry Andric   }
6190b57cec5SDimitry Andric   return false;
6200b57cec5SDimitry Andric }
6210b57cec5SDimitry Andric 
getCOFFRelocationValueString(const COFFObjectFile * Obj,const RelocationRef & Rel,SmallVectorImpl<char> & Result)6225ffd83dbSDimitry Andric Error objdump::getCOFFRelocationValueString(const COFFObjectFile *Obj,
6230b57cec5SDimitry Andric                                             const RelocationRef &Rel,
6240b57cec5SDimitry Andric                                             SmallVectorImpl<char> &Result) {
6250b57cec5SDimitry Andric   symbol_iterator SymI = Rel.getSymbol();
6260b57cec5SDimitry Andric   Expected<StringRef> SymNameOrErr = SymI->getName();
6270b57cec5SDimitry Andric   if (!SymNameOrErr)
6280b57cec5SDimitry Andric     return SymNameOrErr.takeError();
6290b57cec5SDimitry Andric   StringRef SymName = *SymNameOrErr;
6300b57cec5SDimitry Andric   Result.append(SymName.begin(), SymName.end());
6310b57cec5SDimitry Andric   return Error::success();
6320b57cec5SDimitry Andric }
6330b57cec5SDimitry Andric 
printWin64EHUnwindInfo(const Win64EH::UnwindInfo * UI)6340b57cec5SDimitry Andric static void printWin64EHUnwindInfo(const Win64EH::UnwindInfo *UI) {
6350b57cec5SDimitry Andric   // The casts to int are required in order to output the value as number.
6360b57cec5SDimitry Andric   // Without the casts the value would be interpreted as char data (which
6370b57cec5SDimitry Andric   // results in garbage output).
6380b57cec5SDimitry Andric   outs() << "    Version: " << static_cast<int>(UI->getVersion()) << "\n";
6390b57cec5SDimitry Andric   outs() << "    Flags: " << static_cast<int>(UI->getFlags());
6400b57cec5SDimitry Andric   if (UI->getFlags()) {
6410b57cec5SDimitry Andric     if (UI->getFlags() & UNW_ExceptionHandler)
6420b57cec5SDimitry Andric       outs() << " UNW_ExceptionHandler";
6430b57cec5SDimitry Andric     if (UI->getFlags() & UNW_TerminateHandler)
6440b57cec5SDimitry Andric       outs() << " UNW_TerminateHandler";
6450b57cec5SDimitry Andric     if (UI->getFlags() & UNW_ChainInfo)
6460b57cec5SDimitry Andric       outs() << " UNW_ChainInfo";
6470b57cec5SDimitry Andric   }
6480b57cec5SDimitry Andric   outs() << "\n";
6490b57cec5SDimitry Andric   outs() << "    Size of prolog: " << static_cast<int>(UI->PrologSize) << "\n";
6500b57cec5SDimitry Andric   outs() << "    Number of Codes: " << static_cast<int>(UI->NumCodes) << "\n";
6510b57cec5SDimitry Andric   // Maybe this should move to output of UOP_SetFPReg?
6520b57cec5SDimitry Andric   if (UI->getFrameRegister()) {
6530b57cec5SDimitry Andric     outs() << "    Frame register: "
6540b57cec5SDimitry Andric            << getUnwindRegisterName(UI->getFrameRegister()) << "\n";
6550b57cec5SDimitry Andric     outs() << "    Frame offset: " << 16 * UI->getFrameOffset() << "\n";
6560b57cec5SDimitry Andric   } else {
6570b57cec5SDimitry Andric     outs() << "    No frame pointer used\n";
6580b57cec5SDimitry Andric   }
6590b57cec5SDimitry Andric   if (UI->getFlags() & (UNW_ExceptionHandler | UNW_TerminateHandler)) {
6600b57cec5SDimitry Andric     // FIXME: Output exception handler data
6610b57cec5SDimitry Andric   } else if (UI->getFlags() & UNW_ChainInfo) {
6620b57cec5SDimitry Andric     // FIXME: Output chained unwind info
6630b57cec5SDimitry Andric   }
6640b57cec5SDimitry Andric 
6650b57cec5SDimitry Andric   if (UI->NumCodes)
6660b57cec5SDimitry Andric     outs() << "    Unwind Codes:\n";
6670b57cec5SDimitry Andric 
668bdd1243dSDimitry Andric   printAllUnwindCodes(ArrayRef(&UI->UnwindCodes[0], UI->NumCodes));
6690b57cec5SDimitry Andric 
6700b57cec5SDimitry Andric   outs() << "\n";
6710b57cec5SDimitry Andric   outs().flush();
6720b57cec5SDimitry Andric }
6730b57cec5SDimitry Andric 
6740b57cec5SDimitry Andric /// Prints out the given RuntimeFunction struct for x64, assuming that Obj is
6750b57cec5SDimitry Andric /// pointing to an executable file.
printRuntimeFunction(const COFFObjectFile * Obj,const RuntimeFunction & RF)6760b57cec5SDimitry Andric static void printRuntimeFunction(const COFFObjectFile *Obj,
6770b57cec5SDimitry Andric                                  const RuntimeFunction &RF) {
6780b57cec5SDimitry Andric   if (!RF.StartAddress)
6790b57cec5SDimitry Andric     return;
6800b57cec5SDimitry Andric   outs() << "Function Table:\n"
6810b57cec5SDimitry Andric          << format("  Start Address: 0x%04x\n",
6820b57cec5SDimitry Andric                    static_cast<uint32_t>(RF.StartAddress))
6830b57cec5SDimitry Andric          << format("  End Address: 0x%04x\n",
6840b57cec5SDimitry Andric                    static_cast<uint32_t>(RF.EndAddress))
6850b57cec5SDimitry Andric          << format("  Unwind Info Address: 0x%04x\n",
6860b57cec5SDimitry Andric                    static_cast<uint32_t>(RF.UnwindInfoOffset));
6870b57cec5SDimitry Andric   uintptr_t addr;
6880b57cec5SDimitry Andric   if (Obj->getRvaPtr(RF.UnwindInfoOffset, addr))
6890b57cec5SDimitry Andric     return;
6900b57cec5SDimitry Andric   printWin64EHUnwindInfo(reinterpret_cast<const Win64EH::UnwindInfo *>(addr));
6910b57cec5SDimitry Andric }
6920b57cec5SDimitry Andric 
6930b57cec5SDimitry Andric /// Prints out the given RuntimeFunction struct for x64, assuming that Obj is
6940b57cec5SDimitry Andric /// pointing to an object file. Unlike executable, fields in RuntimeFunction
6950b57cec5SDimitry Andric /// struct are filled with zeros, but instead there are relocations pointing to
6960b57cec5SDimitry Andric /// them so that the linker will fill targets' RVAs to the fields at link
6970b57cec5SDimitry Andric /// time. This function interprets the relocations to find the data to be used
6980b57cec5SDimitry Andric /// in the resulting executable.
printRuntimeFunctionRels(const COFFObjectFile * Obj,const RuntimeFunction & RF,uint64_t SectionOffset,const std::vector<RelocationRef> & Rels)6990b57cec5SDimitry Andric static void printRuntimeFunctionRels(const COFFObjectFile *Obj,
7000b57cec5SDimitry Andric                                      const RuntimeFunction &RF,
7010b57cec5SDimitry Andric                                      uint64_t SectionOffset,
7020b57cec5SDimitry Andric                                      const std::vector<RelocationRef> &Rels) {
7030b57cec5SDimitry Andric   outs() << "Function Table:\n";
7040b57cec5SDimitry Andric   outs() << "  Start Address: ";
7050b57cec5SDimitry Andric   printCOFFSymbolAddress(outs(), Rels,
7060b57cec5SDimitry Andric                          SectionOffset +
7070b57cec5SDimitry Andric                              /*offsetof(RuntimeFunction, StartAddress)*/ 0,
7080b57cec5SDimitry Andric                          RF.StartAddress);
7090b57cec5SDimitry Andric   outs() << "\n";
7100b57cec5SDimitry Andric 
7110b57cec5SDimitry Andric   outs() << "  End Address: ";
7120b57cec5SDimitry Andric   printCOFFSymbolAddress(outs(), Rels,
7130b57cec5SDimitry Andric                          SectionOffset +
7140b57cec5SDimitry Andric                              /*offsetof(RuntimeFunction, EndAddress)*/ 4,
7150b57cec5SDimitry Andric                          RF.EndAddress);
7160b57cec5SDimitry Andric   outs() << "\n";
7170b57cec5SDimitry Andric 
7180b57cec5SDimitry Andric   outs() << "  Unwind Info Address: ";
7190b57cec5SDimitry Andric   printCOFFSymbolAddress(outs(), Rels,
7200b57cec5SDimitry Andric                          SectionOffset +
7210b57cec5SDimitry Andric                              /*offsetof(RuntimeFunction, UnwindInfoOffset)*/ 8,
7220b57cec5SDimitry Andric                          RF.UnwindInfoOffset);
7230b57cec5SDimitry Andric   outs() << "\n";
7240b57cec5SDimitry Andric 
7250b57cec5SDimitry Andric   ArrayRef<uint8_t> XContents;
7260b57cec5SDimitry Andric   uint64_t UnwindInfoOffset = 0;
7278bcb0991SDimitry Andric   if (Error E = getSectionContents(
7288bcb0991SDimitry Andric           Obj, Rels,
7298bcb0991SDimitry Andric           SectionOffset +
7300b57cec5SDimitry Andric               /*offsetof(RuntimeFunction, UnwindInfoOffset)*/ 8,
7318bcb0991SDimitry Andric           XContents, UnwindInfoOffset))
7328bcb0991SDimitry Andric     reportError(std::move(E), Obj->getFileName());
7330b57cec5SDimitry Andric   if (XContents.empty())
7340b57cec5SDimitry Andric     return;
7350b57cec5SDimitry Andric 
7360b57cec5SDimitry Andric   UnwindInfoOffset += RF.UnwindInfoOffset;
7370b57cec5SDimitry Andric   if (UnwindInfoOffset > XContents.size())
7380b57cec5SDimitry Andric     return;
7390b57cec5SDimitry Andric 
7400b57cec5SDimitry Andric   auto *UI = reinterpret_cast<const Win64EH::UnwindInfo *>(XContents.data() +
7410b57cec5SDimitry Andric                                                            UnwindInfoOffset);
7420b57cec5SDimitry Andric   printWin64EHUnwindInfo(UI);
7430b57cec5SDimitry Andric }
7440b57cec5SDimitry Andric 
printCOFFUnwindInfo(const COFFObjectFile * Obj)7455ffd83dbSDimitry Andric void objdump::printCOFFUnwindInfo(const COFFObjectFile *Obj) {
7460b57cec5SDimitry Andric   if (Obj->getMachine() != COFF::IMAGE_FILE_MACHINE_AMD64) {
7470b57cec5SDimitry Andric     WithColor::error(errs(), "llvm-objdump")
7480b57cec5SDimitry Andric         << "unsupported image machine type "
7490b57cec5SDimitry Andric            "(currently only AMD64 is supported).\n";
7500b57cec5SDimitry Andric     return;
7510b57cec5SDimitry Andric   }
7520b57cec5SDimitry Andric 
7530b57cec5SDimitry Andric   std::vector<RelocationRef> Rels;
7540b57cec5SDimitry Andric   const RuntimeFunction *RFStart;
7550b57cec5SDimitry Andric   int NumRFs;
7560b57cec5SDimitry Andric   if (!getPDataSection(Obj, Rels, RFStart, NumRFs))
7570b57cec5SDimitry Andric     return;
7580b57cec5SDimitry Andric   ArrayRef<RuntimeFunction> RFs(RFStart, NumRFs);
7590b57cec5SDimitry Andric 
7600b57cec5SDimitry Andric   bool IsExecutable = Rels.empty();
7610b57cec5SDimitry Andric   if (IsExecutable) {
7620b57cec5SDimitry Andric     for (const RuntimeFunction &RF : RFs)
7630b57cec5SDimitry Andric       printRuntimeFunction(Obj, RF);
7640b57cec5SDimitry Andric     return;
7650b57cec5SDimitry Andric   }
7660b57cec5SDimitry Andric 
7670b57cec5SDimitry Andric   for (const RuntimeFunction &RF : RFs) {
7680b57cec5SDimitry Andric     uint64_t SectionOffset =
7690b57cec5SDimitry Andric         std::distance(RFs.begin(), &RF) * sizeof(RuntimeFunction);
7700b57cec5SDimitry Andric     printRuntimeFunctionRels(Obj, RF, SectionOffset, Rels);
7710b57cec5SDimitry Andric   }
7720b57cec5SDimitry Andric }
7730b57cec5SDimitry Andric 
printPrivateHeaders()774*5f757f3fSDimitry Andric void COFFDumper::printPrivateHeaders() {
775349cc55cSDimitry Andric   COFFDumper CD(Obj);
776349cc55cSDimitry Andric   const uint16_t Cha = Obj.getCharacteristics();
777349cc55cSDimitry Andric   outs() << "Characteristics 0x" << Twine::utohexstr(Cha) << '\n';
778349cc55cSDimitry Andric #define FLAG(F, Name)                                                          \
779349cc55cSDimitry Andric   if (Cha & F)                                                                 \
780349cc55cSDimitry Andric     outs() << '\t' << Name << '\n';
781349cc55cSDimitry Andric   FLAG(COFF::IMAGE_FILE_RELOCS_STRIPPED, "relocations stripped");
782349cc55cSDimitry Andric   FLAG(COFF::IMAGE_FILE_EXECUTABLE_IMAGE, "executable");
783349cc55cSDimitry Andric   FLAG(COFF::IMAGE_FILE_LINE_NUMS_STRIPPED, "line numbers stripped");
784349cc55cSDimitry Andric   FLAG(COFF::IMAGE_FILE_LOCAL_SYMS_STRIPPED, "symbols stripped");
785349cc55cSDimitry Andric   FLAG(COFF::IMAGE_FILE_LARGE_ADDRESS_AWARE, "large address aware");
786349cc55cSDimitry Andric   FLAG(COFF::IMAGE_FILE_BYTES_REVERSED_LO, "little endian");
787349cc55cSDimitry Andric   FLAG(COFF::IMAGE_FILE_32BIT_MACHINE, "32 bit words");
788349cc55cSDimitry Andric   FLAG(COFF::IMAGE_FILE_DEBUG_STRIPPED, "debugging information removed");
789349cc55cSDimitry Andric   FLAG(COFF::IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP,
790349cc55cSDimitry Andric        "copy to swap file if on removable media");
791349cc55cSDimitry Andric   FLAG(COFF::IMAGE_FILE_NET_RUN_FROM_SWAP,
792349cc55cSDimitry Andric        "copy to swap file if on network media");
793349cc55cSDimitry Andric   FLAG(COFF::IMAGE_FILE_SYSTEM, "system file");
794349cc55cSDimitry Andric   FLAG(COFF::IMAGE_FILE_DLL, "DLL");
795349cc55cSDimitry Andric   FLAG(COFF::IMAGE_FILE_UP_SYSTEM_ONLY, "run only on uniprocessor machine");
796349cc55cSDimitry Andric   FLAG(COFF::IMAGE_FILE_BYTES_REVERSED_HI, "big endian");
797349cc55cSDimitry Andric #undef FLAG
798349cc55cSDimitry Andric 
799349cc55cSDimitry Andric   // TODO Support PE_IMAGE_DEBUG_TYPE_REPRO.
800349cc55cSDimitry Andric   // Since ctime(3) returns a 26 character string of the form:
801349cc55cSDimitry Andric   // "Sun Sep 16 01:03:52 1973\n\0"
802349cc55cSDimitry Andric   // just print 24 characters.
803349cc55cSDimitry Andric   const time_t Timestamp = Obj.getTimeDateStamp();
804349cc55cSDimitry Andric   outs() << format("\nTime/Date               %.24s\n", ctime(&Timestamp));
805349cc55cSDimitry Andric 
806349cc55cSDimitry Andric   if (const pe32_header *Hdr = Obj.getPE32Header())
807349cc55cSDimitry Andric     CD.printPEHeader<pe32_header>(*Hdr);
808349cc55cSDimitry Andric   else if (const pe32plus_header *Hdr = Obj.getPE32PlusHeader())
809349cc55cSDimitry Andric     CD.printPEHeader<pe32plus_header>(*Hdr);
810349cc55cSDimitry Andric 
811349cc55cSDimitry Andric   printTLSDirectory(&Obj);
812349cc55cSDimitry Andric   printLoadConfiguration(&Obj);
813349cc55cSDimitry Andric   printImportTables(&Obj);
814349cc55cSDimitry Andric   printExportTable(&Obj);
8150b57cec5SDimitry Andric }
8160b57cec5SDimitry Andric 
printCOFFSymbolTable(const object::COFFImportFile & i)817753f127fSDimitry Andric void objdump::printCOFFSymbolTable(const object::COFFImportFile &i) {
8180b57cec5SDimitry Andric   unsigned Index = 0;
819753f127fSDimitry Andric   bool IsCode = i.getCOFFImportHeader()->getType() == COFF::IMPORT_CODE;
8200b57cec5SDimitry Andric 
821753f127fSDimitry Andric   for (const object::BasicSymbolRef &Sym : i.symbols()) {
8220b57cec5SDimitry Andric     std::string Name;
8230b57cec5SDimitry Andric     raw_string_ostream NS(Name);
8240b57cec5SDimitry Andric 
8250b57cec5SDimitry Andric     cantFail(Sym.printName(NS));
8260b57cec5SDimitry Andric     NS.flush();
8270b57cec5SDimitry Andric 
8280b57cec5SDimitry Andric     outs() << "[" << format("%2d", Index) << "]"
8290b57cec5SDimitry Andric            << "(sec " << format("%2d", 0) << ")"
8300b57cec5SDimitry Andric            << "(fl 0x00)" // Flag bits, which COFF doesn't have.
8310b57cec5SDimitry Andric            << "(ty " << format("%3x", (IsCode && Index) ? 32 : 0) << ")"
8320b57cec5SDimitry Andric            << "(scl " << format("%3x", 0) << ") "
8330b57cec5SDimitry Andric            << "(nx " << 0 << ") "
8340b57cec5SDimitry Andric            << "0x" << format("%08x", 0) << " " << Name << '\n';
8350b57cec5SDimitry Andric 
8360b57cec5SDimitry Andric     ++Index;
8370b57cec5SDimitry Andric   }
8380b57cec5SDimitry Andric }
8390b57cec5SDimitry Andric 
printCOFFSymbolTable(const COFFObjectFile & coff)840753f127fSDimitry Andric void objdump::printCOFFSymbolTable(const COFFObjectFile &coff) {
841753f127fSDimitry Andric   for (unsigned SI = 0, SE = coff.getNumberOfSymbols(); SI != SE; ++SI) {
842753f127fSDimitry Andric     Expected<COFFSymbolRef> Symbol = coff.getSymbol(SI);
8438bcb0991SDimitry Andric     if (!Symbol)
844753f127fSDimitry Andric       reportError(Symbol.takeError(), coff.getFileName());
8458bcb0991SDimitry Andric 
846753f127fSDimitry Andric     Expected<StringRef> NameOrErr = coff.getSymbolName(*Symbol);
8475ffd83dbSDimitry Andric     if (!NameOrErr)
848753f127fSDimitry Andric       reportError(NameOrErr.takeError(), coff.getFileName());
8495ffd83dbSDimitry Andric     StringRef Name = *NameOrErr;
8500b57cec5SDimitry Andric 
8510b57cec5SDimitry Andric     outs() << "[" << format("%2d", SI) << "]"
8520b57cec5SDimitry Andric            << "(sec " << format("%2d", int(Symbol->getSectionNumber())) << ")"
8530b57cec5SDimitry Andric            << "(fl 0x00)" // Flag bits, which COFF doesn't have.
8540b57cec5SDimitry Andric            << "(ty " << format("%3x", unsigned(Symbol->getType())) << ")"
8550b57cec5SDimitry Andric            << "(scl " << format("%3x", unsigned(Symbol->getStorageClass()))
8560b57cec5SDimitry Andric            << ") "
8570b57cec5SDimitry Andric            << "(nx " << unsigned(Symbol->getNumberOfAuxSymbols()) << ") "
8580b57cec5SDimitry Andric            << "0x" << format("%08x", unsigned(Symbol->getValue())) << " "
8590b57cec5SDimitry Andric            << Name;
860*5f757f3fSDimitry Andric     if (Demangle && Name.starts_with("?")) {
8610b57cec5SDimitry Andric       int Status = -1;
86206c3fb27SDimitry Andric       char *DemangledSymbol = microsoftDemangle(Name, nullptr, &Status);
8630b57cec5SDimitry Andric 
8640b57cec5SDimitry Andric       if (Status == 0 && DemangledSymbol) {
8650b57cec5SDimitry Andric         outs() << " (" << StringRef(DemangledSymbol) << ")";
8660b57cec5SDimitry Andric         std::free(DemangledSymbol);
8670b57cec5SDimitry Andric       } else {
8680b57cec5SDimitry Andric         outs() << " (invalid mangled name)";
8690b57cec5SDimitry Andric       }
8700b57cec5SDimitry Andric     }
8710b57cec5SDimitry Andric     outs() << "\n";
8720b57cec5SDimitry Andric 
8730b57cec5SDimitry Andric     for (unsigned AI = 0, AE = Symbol->getNumberOfAuxSymbols(); AI < AE; ++AI, ++SI) {
8740b57cec5SDimitry Andric       if (Symbol->isSectionDefinition()) {
8750b57cec5SDimitry Andric         const coff_aux_section_definition *asd;
8765ffd83dbSDimitry Andric         if (Error E =
877753f127fSDimitry Andric                 coff.getAuxSymbol<coff_aux_section_definition>(SI + 1, asd))
878753f127fSDimitry Andric           reportError(std::move(E), coff.getFileName());
8790b57cec5SDimitry Andric 
8800b57cec5SDimitry Andric         int32_t AuxNumber = asd->getNumber(Symbol->isBigObj());
8810b57cec5SDimitry Andric 
8820b57cec5SDimitry Andric         outs() << "AUX "
8830b57cec5SDimitry Andric                << format("scnlen 0x%x nreloc %d nlnno %d checksum 0x%x "
8840b57cec5SDimitry Andric                          , unsigned(asd->Length)
8850b57cec5SDimitry Andric                          , unsigned(asd->NumberOfRelocations)
8860b57cec5SDimitry Andric                          , unsigned(asd->NumberOfLinenumbers)
8870b57cec5SDimitry Andric                          , unsigned(asd->CheckSum))
8880b57cec5SDimitry Andric                << format("assoc %d comdat %d\n"
8890b57cec5SDimitry Andric                          , unsigned(AuxNumber)
8900b57cec5SDimitry Andric                          , unsigned(asd->Selection));
8910b57cec5SDimitry Andric       } else if (Symbol->isFileRecord()) {
8920b57cec5SDimitry Andric         const char *FileName;
893753f127fSDimitry Andric         if (Error E = coff.getAuxSymbol<char>(SI + 1, FileName))
894753f127fSDimitry Andric           reportError(std::move(E), coff.getFileName());
8950b57cec5SDimitry Andric 
8960b57cec5SDimitry Andric         StringRef Name(FileName, Symbol->getNumberOfAuxSymbols() *
897753f127fSDimitry Andric                                      coff.getSymbolTableEntrySize());
8980b57cec5SDimitry Andric         outs() << "AUX " << Name.rtrim(StringRef("\0", 1))  << '\n';
8990b57cec5SDimitry Andric 
9000b57cec5SDimitry Andric         SI = SI + Symbol->getNumberOfAuxSymbols();
9010b57cec5SDimitry Andric         break;
9020b57cec5SDimitry Andric       } else if (Symbol->isWeakExternal()) {
9030b57cec5SDimitry Andric         const coff_aux_weak_external *awe;
904753f127fSDimitry Andric         if (Error E = coff.getAuxSymbol<coff_aux_weak_external>(SI + 1, awe))
905753f127fSDimitry Andric           reportError(std::move(E), coff.getFileName());
9060b57cec5SDimitry Andric 
9070b57cec5SDimitry Andric         outs() << "AUX " << format("indx %d srch %d\n",
9080b57cec5SDimitry Andric                                    static_cast<uint32_t>(awe->TagIndex),
9090b57cec5SDimitry Andric                                    static_cast<uint32_t>(awe->Characteristics));
9100b57cec5SDimitry Andric       } else {
9110b57cec5SDimitry Andric         outs() << "AUX Unknown\n";
9120b57cec5SDimitry Andric       }
9130b57cec5SDimitry Andric     }
9140b57cec5SDimitry Andric   }
9150b57cec5SDimitry Andric }
916