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