1*f754f88fSGreg Clayton //===-- ObjectFilePECOFF.cpp ------------------------------------*- C++ -*-===//
2*f754f88fSGreg Clayton //
3*f754f88fSGreg Clayton //                     The LLVM Compiler Infrastructure
4*f754f88fSGreg Clayton //
5*f754f88fSGreg Clayton // This file is distributed under the University of Illinois Open Source
6*f754f88fSGreg Clayton // License. See LICENSE.TXT for details.
7*f754f88fSGreg Clayton //
8*f754f88fSGreg Clayton //===----------------------------------------------------------------------===//
9*f754f88fSGreg Clayton 
10*f754f88fSGreg Clayton #include "ObjectFilePECOFF.h"
11*f754f88fSGreg Clayton 
12*f754f88fSGreg Clayton #include "llvm/Support/MachO.h"
13*f754f88fSGreg Clayton 
14*f754f88fSGreg Clayton #include "lldb/Core/ArchSpec.h"
15*f754f88fSGreg Clayton #include "lldb/Core/DataBuffer.h"
16*f754f88fSGreg Clayton #include "lldb/Host/FileSpec.h"
17*f754f88fSGreg Clayton #include "lldb/Core/FileSpecList.h"
18*f754f88fSGreg Clayton #include "lldb/Core/Module.h"
19*f754f88fSGreg Clayton #include "lldb/Core/PluginManager.h"
20*f754f88fSGreg Clayton #include "lldb/Core/Section.h"
21*f754f88fSGreg Clayton #include "lldb/Core/StreamFile.h"
22*f754f88fSGreg Clayton #include "lldb/Core/StreamString.h"
23*f754f88fSGreg Clayton #include "lldb/Core/Timer.h"
24*f754f88fSGreg Clayton #include "lldb/Core/UUID.h"
25*f754f88fSGreg Clayton #include "lldb/Symbol/ObjectFile.h"
26*f754f88fSGreg Clayton 
27*f754f88fSGreg Clayton static uint32_t COFFMachineToMachCPU(uint16_t machine);
28*f754f88fSGreg Clayton 
29*f754f88fSGreg Clayton #define IMAGE_FILE_MACHINE_UNKNOWN      0x0000
30*f754f88fSGreg Clayton #define IMAGE_FILE_MACHINE_AM33         0x01d3  // Matsushita AM33
31*f754f88fSGreg Clayton #define IMAGE_FILE_MACHINE_AMD64        0x8664  // x64
32*f754f88fSGreg Clayton #define IMAGE_FILE_MACHINE_ARM          0x01c0  // ARM little endian
33*f754f88fSGreg Clayton #define IMAGE_FILE_MACHINE_EBC          0x0ebc  // EFI byte code
34*f754f88fSGreg Clayton #define IMAGE_FILE_MACHINE_I386         0x014c  // Intel 386 or later processors and compatible processors
35*f754f88fSGreg Clayton #define IMAGE_FILE_MACHINE_IA64         0x0200  // Intel Itanium processor family
36*f754f88fSGreg Clayton #define IMAGE_FILE_MACHINE_M32R         0x9041  // Mitsubishi M32R little endian
37*f754f88fSGreg Clayton #define IMAGE_FILE_MACHINE_MIPS16       0x0266  // MIPS16
38*f754f88fSGreg Clayton #define IMAGE_FILE_MACHINE_MIPSFPU      0x0366  // MIPS with FPU
39*f754f88fSGreg Clayton #define IMAGE_FILE_MACHINE_MIPSFPU16    0x0466  // MIPS16 with FPU
40*f754f88fSGreg Clayton #define IMAGE_FILE_MACHINE_POWERPC      0x01f0  // Power PC little endian
41*f754f88fSGreg Clayton #define IMAGE_FILE_MACHINE_POWERPCFP    0x01f1  // Power PC with floating point support
42*f754f88fSGreg Clayton #define IMAGE_FILE_MACHINE_R4000        0x0166  // MIPS little endian
43*f754f88fSGreg Clayton #define IMAGE_FILE_MACHINE_SH3          0x01a2  // Hitachi SH3
44*f754f88fSGreg Clayton #define IMAGE_FILE_MACHINE_SH3DSP       0x01a3  // Hitachi SH3 DSP
45*f754f88fSGreg Clayton #define IMAGE_FILE_MACHINE_SH4          0x01a6  // Hitachi SH4
46*f754f88fSGreg Clayton #define IMAGE_FILE_MACHINE_SH5          0x01a8  // Hitachi SH5
47*f754f88fSGreg Clayton #define IMAGE_FILE_MACHINE_THUMB        0x01c2  // Thumb
48*f754f88fSGreg Clayton #define IMAGE_FILE_MACHINE_WCEMIPSV2    0x0169  // MIPS little-endian WCE v2
49*f754f88fSGreg Clayton 
50*f754f88fSGreg Clayton 
51*f754f88fSGreg Clayton #define IMAGE_DOS_SIGNATURE             0x5A4D      // MZ
52*f754f88fSGreg Clayton #define IMAGE_OS2_SIGNATURE             0x454E      // NE
53*f754f88fSGreg Clayton #define IMAGE_OS2_SIGNATURE_LE          0x454C      // LE
54*f754f88fSGreg Clayton #define IMAGE_NT_SIGNATURE              0x00004550  // PE00
55*f754f88fSGreg Clayton #define OPT_HEADER_MAGIC_PE32           0x010b
56*f754f88fSGreg Clayton #define OPT_HEADER_MAGIC_PE32_PLUS      0x020b
57*f754f88fSGreg Clayton 
58*f754f88fSGreg Clayton #define IMAGE_FILE_RELOCS_STRIPPED          0x0001
59*f754f88fSGreg Clayton #define IMAGE_FILE_EXECUTABLE_IMAGE         0x0002
60*f754f88fSGreg Clayton #define IMAGE_FILE_LINE_NUMS_STRIPPED       0x0004
61*f754f88fSGreg Clayton #define IMAGE_FILE_LOCAL_SYMS_STRIPPED      0x0008
62*f754f88fSGreg Clayton #define IMAGE_FILE_AGGRESSIVE_WS_TRIM       0x0010
63*f754f88fSGreg Clayton #define IMAGE_FILE_LARGE_ADDRESS_AWARE      0x0020
64*f754f88fSGreg Clayton //#define                                   0x0040  // Reserved
65*f754f88fSGreg Clayton #define IMAGE_FILE_BYTES_REVERSED_LO        0x0080
66*f754f88fSGreg Clayton #define IMAGE_FILE_32BIT_MACHINE            0x0100
67*f754f88fSGreg Clayton #define IMAGE_FILE_DEBUG_STRIPPED           0x0200
68*f754f88fSGreg Clayton #define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP  0x0400
69*f754f88fSGreg Clayton #define IMAGE_FILE_NET_RUN_FROM_SWAP        0x0800
70*f754f88fSGreg Clayton #define IMAGE_FILE_SYSTEM                   0x1000
71*f754f88fSGreg Clayton #define IMAGE_FILE_DLL                      0x2000
72*f754f88fSGreg Clayton #define IMAGE_FILE_UP_SYSTEM_ONLY           0x4000
73*f754f88fSGreg Clayton #define IMAGE_FILE_BYTES_REVERSED_HI        0x8000
74*f754f88fSGreg Clayton 
75*f754f88fSGreg Clayton using namespace lldb;
76*f754f88fSGreg Clayton using namespace lldb_private;
77*f754f88fSGreg Clayton 
78*f754f88fSGreg Clayton void
79*f754f88fSGreg Clayton ObjectFilePECOFF::Initialize()
80*f754f88fSGreg Clayton {
81*f754f88fSGreg Clayton     PluginManager::RegisterPlugin (GetPluginNameStatic(),
82*f754f88fSGreg Clayton                                    GetPluginDescriptionStatic(),
83*f754f88fSGreg Clayton                                    CreateInstance);
84*f754f88fSGreg Clayton }
85*f754f88fSGreg Clayton 
86*f754f88fSGreg Clayton void
87*f754f88fSGreg Clayton ObjectFilePECOFF::Terminate()
88*f754f88fSGreg Clayton {
89*f754f88fSGreg Clayton     PluginManager::UnregisterPlugin (CreateInstance);
90*f754f88fSGreg Clayton }
91*f754f88fSGreg Clayton 
92*f754f88fSGreg Clayton 
93*f754f88fSGreg Clayton const char *
94*f754f88fSGreg Clayton ObjectFilePECOFF::GetPluginNameStatic()
95*f754f88fSGreg Clayton {
96*f754f88fSGreg Clayton     return "object-file.pe-coff";
97*f754f88fSGreg Clayton }
98*f754f88fSGreg Clayton 
99*f754f88fSGreg Clayton const char *
100*f754f88fSGreg Clayton ObjectFilePECOFF::GetPluginDescriptionStatic()
101*f754f88fSGreg Clayton {
102*f754f88fSGreg Clayton     return "Portable Executable and Common Object File Format object file reader (32 and 64 bit)";
103*f754f88fSGreg Clayton }
104*f754f88fSGreg Clayton 
105*f754f88fSGreg Clayton 
106*f754f88fSGreg Clayton ObjectFile *
107*f754f88fSGreg Clayton ObjectFilePECOFF::CreateInstance (Module* module, DataBufferSP& dataSP, const FileSpec* file, addr_t offset, addr_t length)
108*f754f88fSGreg Clayton {
109*f754f88fSGreg Clayton     if (ObjectFilePECOFF::MagicBytesMatch(dataSP))
110*f754f88fSGreg Clayton     {
111*f754f88fSGreg Clayton         std::auto_ptr<ObjectFile> objfile_ap(new ObjectFilePECOFF (module, dataSP, file, offset, length));
112*f754f88fSGreg Clayton         if (objfile_ap.get() && objfile_ap->ParseHeader())
113*f754f88fSGreg Clayton             return objfile_ap.release();
114*f754f88fSGreg Clayton     }
115*f754f88fSGreg Clayton     return NULL;
116*f754f88fSGreg Clayton }
117*f754f88fSGreg Clayton 
118*f754f88fSGreg Clayton bool
119*f754f88fSGreg Clayton ObjectFilePECOFF::MagicBytesMatch (DataBufferSP& dataSP)
120*f754f88fSGreg Clayton {
121*f754f88fSGreg Clayton     DataExtractor data(dataSP, eByteOrderLittle, 4);
122*f754f88fSGreg Clayton     uint32_t offset = 0;
123*f754f88fSGreg Clayton     uint16_t magic = data.GetU16 (&offset);
124*f754f88fSGreg Clayton     return magic == IMAGE_DOS_SIGNATURE;
125*f754f88fSGreg Clayton }
126*f754f88fSGreg Clayton 
127*f754f88fSGreg Clayton 
128*f754f88fSGreg Clayton ObjectFilePECOFF::ObjectFilePECOFF (Module* module,
129*f754f88fSGreg Clayton                                     DataBufferSP& dataSP,
130*f754f88fSGreg Clayton                                     const FileSpec* file,
131*f754f88fSGreg Clayton                                     addr_t offset,
132*f754f88fSGreg Clayton                                     addr_t length) :
133*f754f88fSGreg Clayton     ObjectFile (module, file, offset, length, dataSP),
134*f754f88fSGreg Clayton     m_mutex (Mutex::eMutexTypeRecursive),
135*f754f88fSGreg Clayton     m_dos_header (),
136*f754f88fSGreg Clayton     m_coff_header (),
137*f754f88fSGreg Clayton     m_coff_header_opt (),
138*f754f88fSGreg Clayton     m_sect_headers ()
139*f754f88fSGreg Clayton {
140*f754f88fSGreg Clayton     ::memset (&m_dos_header, 0, sizeof(m_dos_header));
141*f754f88fSGreg Clayton     ::memset (&m_coff_header, 0, sizeof(m_coff_header));
142*f754f88fSGreg Clayton     ::memset (&m_coff_header_opt, 0, sizeof(m_coff_header_opt));
143*f754f88fSGreg Clayton }
144*f754f88fSGreg Clayton 
145*f754f88fSGreg Clayton 
146*f754f88fSGreg Clayton ObjectFilePECOFF::~ObjectFilePECOFF()
147*f754f88fSGreg Clayton {
148*f754f88fSGreg Clayton }
149*f754f88fSGreg Clayton 
150*f754f88fSGreg Clayton 
151*f754f88fSGreg Clayton bool
152*f754f88fSGreg Clayton ObjectFilePECOFF::ParseHeader ()
153*f754f88fSGreg Clayton {
154*f754f88fSGreg Clayton     Mutex::Locker locker(m_mutex);
155*f754f88fSGreg Clayton     m_sect_headers.clear();
156*f754f88fSGreg Clayton     m_data.SetByteOrder (eByteOrderLittle);
157*f754f88fSGreg Clayton     uint32_t offset = 0;
158*f754f88fSGreg Clayton 
159*f754f88fSGreg Clayton     if (ParseDOSHeader())
160*f754f88fSGreg Clayton     {
161*f754f88fSGreg Clayton         offset = m_dos_header.e_lfanew;
162*f754f88fSGreg Clayton         uint32_t pe_signature = m_data.GetU32 (&offset);
163*f754f88fSGreg Clayton         if (pe_signature != IMAGE_NT_SIGNATURE)
164*f754f88fSGreg Clayton             return false;
165*f754f88fSGreg Clayton     }
166*f754f88fSGreg Clayton     if (ParseCOFFHeader(&offset))
167*f754f88fSGreg Clayton     {
168*f754f88fSGreg Clayton         if (m_coff_header.hdrsize > 0)
169*f754f88fSGreg Clayton             ParseCOFFOptionalHeader(&offset);
170*f754f88fSGreg Clayton         ParseSectionHeaders (offset);
171*f754f88fSGreg Clayton         return true;
172*f754f88fSGreg Clayton     }
173*f754f88fSGreg Clayton     return false;
174*f754f88fSGreg Clayton }
175*f754f88fSGreg Clayton 
176*f754f88fSGreg Clayton 
177*f754f88fSGreg Clayton ByteOrder
178*f754f88fSGreg Clayton ObjectFilePECOFF::GetByteOrder () const
179*f754f88fSGreg Clayton {
180*f754f88fSGreg Clayton     return eByteOrderLittle;
181*f754f88fSGreg Clayton }
182*f754f88fSGreg Clayton 
183*f754f88fSGreg Clayton bool
184*f754f88fSGreg Clayton ObjectFilePECOFF::IsExecutable() const
185*f754f88fSGreg Clayton {
186*f754f88fSGreg Clayton     return (m_coff_header.flags & IMAGE_FILE_DLL) == 0;
187*f754f88fSGreg Clayton }
188*f754f88fSGreg Clayton 
189*f754f88fSGreg Clayton size_t
190*f754f88fSGreg Clayton ObjectFilePECOFF::GetAddressByteSize () const
191*f754f88fSGreg Clayton {
192*f754f88fSGreg Clayton     if (m_coff_header_opt.magic == OPT_HEADER_MAGIC_PE32_PLUS)
193*f754f88fSGreg Clayton         return 8;
194*f754f88fSGreg Clayton     else if (m_coff_header_opt.magic == OPT_HEADER_MAGIC_PE32)
195*f754f88fSGreg Clayton         return 4;
196*f754f88fSGreg Clayton     return 4;
197*f754f88fSGreg Clayton }
198*f754f88fSGreg Clayton 
199*f754f88fSGreg Clayton //----------------------------------------------------------------------
200*f754f88fSGreg Clayton // NeedsEndianSwap
201*f754f88fSGreg Clayton //
202*f754f88fSGreg Clayton // Return true if an endian swap needs to occur when extracting data
203*f754f88fSGreg Clayton // from this file.
204*f754f88fSGreg Clayton //----------------------------------------------------------------------
205*f754f88fSGreg Clayton bool
206*f754f88fSGreg Clayton ObjectFilePECOFF::NeedsEndianSwap() const
207*f754f88fSGreg Clayton {
208*f754f88fSGreg Clayton #if defined(__LITTLE_ENDIAN__)
209*f754f88fSGreg Clayton     return false;
210*f754f88fSGreg Clayton #else
211*f754f88fSGreg Clayton     return true;
212*f754f88fSGreg Clayton #endif
213*f754f88fSGreg Clayton }
214*f754f88fSGreg Clayton //----------------------------------------------------------------------
215*f754f88fSGreg Clayton // ParseDOSHeader
216*f754f88fSGreg Clayton //----------------------------------------------------------------------
217*f754f88fSGreg Clayton bool
218*f754f88fSGreg Clayton ObjectFilePECOFF::ParseDOSHeader ()
219*f754f88fSGreg Clayton {
220*f754f88fSGreg Clayton     bool success = false;
221*f754f88fSGreg Clayton     uint32_t offset = 0;
222*f754f88fSGreg Clayton     success = m_data.ValidOffsetForDataOfSize(0, sizeof(m_dos_header));
223*f754f88fSGreg Clayton 
224*f754f88fSGreg Clayton     if (success)
225*f754f88fSGreg Clayton     {
226*f754f88fSGreg Clayton         m_dos_header.e_magic = m_data.GetU16(&offset); // Magic number
227*f754f88fSGreg Clayton         success = m_dos_header.e_magic == IMAGE_DOS_SIGNATURE;
228*f754f88fSGreg Clayton 
229*f754f88fSGreg Clayton         if (success)
230*f754f88fSGreg Clayton         {
231*f754f88fSGreg Clayton             m_dos_header.e_cblp     = m_data.GetU16(&offset); // Bytes on last page of file
232*f754f88fSGreg Clayton             m_dos_header.e_cp       = m_data.GetU16(&offset); // Pages in file
233*f754f88fSGreg Clayton             m_dos_header.e_crlc     = m_data.GetU16(&offset); // Relocations
234*f754f88fSGreg Clayton             m_dos_header.e_cparhdr  = m_data.GetU16(&offset); // Size of header in paragraphs
235*f754f88fSGreg Clayton             m_dos_header.e_minalloc = m_data.GetU16(&offset); // Minimum extra paragraphs needed
236*f754f88fSGreg Clayton             m_dos_header.e_maxalloc = m_data.GetU16(&offset); // Maximum extra paragraphs needed
237*f754f88fSGreg Clayton             m_dos_header.e_ss       = m_data.GetU16(&offset); // Initial (relative) SS value
238*f754f88fSGreg Clayton             m_dos_header.e_sp       = m_data.GetU16(&offset); // Initial SP value
239*f754f88fSGreg Clayton             m_dos_header.e_csum     = m_data.GetU16(&offset); // Checksum
240*f754f88fSGreg Clayton             m_dos_header.e_ip       = m_data.GetU16(&offset); // Initial IP value
241*f754f88fSGreg Clayton             m_dos_header.e_cs       = m_data.GetU16(&offset); // Initial (relative) CS value
242*f754f88fSGreg Clayton             m_dos_header.e_lfarlc   = m_data.GetU16(&offset); // File address of relocation table
243*f754f88fSGreg Clayton             m_dos_header.e_ovno     = m_data.GetU16(&offset); // Overlay number
244*f754f88fSGreg Clayton 
245*f754f88fSGreg Clayton             m_dos_header.e_res[0]   = m_data.GetU16(&offset); // Reserved words
246*f754f88fSGreg Clayton             m_dos_header.e_res[1]   = m_data.GetU16(&offset); // Reserved words
247*f754f88fSGreg Clayton             m_dos_header.e_res[2]   = m_data.GetU16(&offset); // Reserved words
248*f754f88fSGreg Clayton             m_dos_header.e_res[3]   = m_data.GetU16(&offset); // Reserved words
249*f754f88fSGreg Clayton 
250*f754f88fSGreg Clayton             m_dos_header.e_oemid    = m_data.GetU16(&offset); // OEM identifier (for e_oeminfo)
251*f754f88fSGreg Clayton             m_dos_header.e_oeminfo  = m_data.GetU16(&offset); // OEM information; e_oemid specific
252*f754f88fSGreg Clayton             m_dos_header.e_res2[0]  = m_data.GetU16(&offset); // Reserved words
253*f754f88fSGreg Clayton             m_dos_header.e_res2[1]  = m_data.GetU16(&offset); // Reserved words
254*f754f88fSGreg Clayton             m_dos_header.e_res2[2]  = m_data.GetU16(&offset); // Reserved words
255*f754f88fSGreg Clayton             m_dos_header.e_res2[3]  = m_data.GetU16(&offset); // Reserved words
256*f754f88fSGreg Clayton             m_dos_header.e_res2[4]  = m_data.GetU16(&offset); // Reserved words
257*f754f88fSGreg Clayton             m_dos_header.e_res2[5]  = m_data.GetU16(&offset); // Reserved words
258*f754f88fSGreg Clayton             m_dos_header.e_res2[6]  = m_data.GetU16(&offset); // Reserved words
259*f754f88fSGreg Clayton             m_dos_header.e_res2[7]  = m_data.GetU16(&offset); // Reserved words
260*f754f88fSGreg Clayton             m_dos_header.e_res2[8]  = m_data.GetU16(&offset); // Reserved words
261*f754f88fSGreg Clayton             m_dos_header.e_res2[9]  = m_data.GetU16(&offset); // Reserved words
262*f754f88fSGreg Clayton 
263*f754f88fSGreg Clayton             m_dos_header.e_lfanew   = m_data.GetU32(&offset); // File address of new exe header
264*f754f88fSGreg Clayton         }
265*f754f88fSGreg Clayton     }
266*f754f88fSGreg Clayton     if (!success)
267*f754f88fSGreg Clayton         memset(&m_dos_header, 0, sizeof(m_dos_header));
268*f754f88fSGreg Clayton     return success;
269*f754f88fSGreg Clayton }
270*f754f88fSGreg Clayton 
271*f754f88fSGreg Clayton 
272*f754f88fSGreg Clayton //----------------------------------------------------------------------
273*f754f88fSGreg Clayton // ParserCOFFHeader
274*f754f88fSGreg Clayton //----------------------------------------------------------------------
275*f754f88fSGreg Clayton bool
276*f754f88fSGreg Clayton ObjectFilePECOFF::ParseCOFFHeader(uint32_t* offset_ptr)
277*f754f88fSGreg Clayton {
278*f754f88fSGreg Clayton     bool success = m_data.ValidOffsetForDataOfSize (*offset_ptr, sizeof(m_coff_header));
279*f754f88fSGreg Clayton     if (success)
280*f754f88fSGreg Clayton     {
281*f754f88fSGreg Clayton         m_coff_header.machine   = m_data.GetU16(offset_ptr);
282*f754f88fSGreg Clayton         m_coff_header.nsects    = m_data.GetU16(offset_ptr);
283*f754f88fSGreg Clayton         m_coff_header.modtime   = m_data.GetU32(offset_ptr);
284*f754f88fSGreg Clayton         m_coff_header.symoff    = m_data.GetU32(offset_ptr);
285*f754f88fSGreg Clayton         m_coff_header.nsyms     = m_data.GetU32(offset_ptr);
286*f754f88fSGreg Clayton         m_coff_header.hdrsize   = m_data.GetU16(offset_ptr);
287*f754f88fSGreg Clayton         m_coff_header.flags     = m_data.GetU16(offset_ptr);
288*f754f88fSGreg Clayton     }
289*f754f88fSGreg Clayton     if (!success)
290*f754f88fSGreg Clayton         memset(&m_coff_header, 0, sizeof(m_coff_header));
291*f754f88fSGreg Clayton     return success;
292*f754f88fSGreg Clayton }
293*f754f88fSGreg Clayton 
294*f754f88fSGreg Clayton bool
295*f754f88fSGreg Clayton ObjectFilePECOFF::ParseCOFFOptionalHeader(uint32_t* offset_ptr)
296*f754f88fSGreg Clayton {
297*f754f88fSGreg Clayton     bool success = false;
298*f754f88fSGreg Clayton     const uint32_t end_offset = *offset_ptr + m_coff_header.hdrsize;
299*f754f88fSGreg Clayton     if (*offset_ptr < end_offset)
300*f754f88fSGreg Clayton     {
301*f754f88fSGreg Clayton         success = true;
302*f754f88fSGreg Clayton         m_coff_header_opt.magic                         = m_data.GetU16(offset_ptr);
303*f754f88fSGreg Clayton         m_coff_header_opt.major_linker_version          = m_data.GetU8 (offset_ptr);
304*f754f88fSGreg Clayton         m_coff_header_opt.minor_linker_version          = m_data.GetU8 (offset_ptr);
305*f754f88fSGreg Clayton         m_coff_header_opt.code_size                     = m_data.GetU32(offset_ptr);
306*f754f88fSGreg Clayton         m_coff_header_opt.data_size                     = m_data.GetU32(offset_ptr);
307*f754f88fSGreg Clayton         m_coff_header_opt.bss_size                      = m_data.GetU32(offset_ptr);
308*f754f88fSGreg Clayton         m_coff_header_opt.entry                         = m_data.GetU32(offset_ptr);
309*f754f88fSGreg Clayton         m_coff_header_opt.code_offset                   = m_data.GetU32(offset_ptr);
310*f754f88fSGreg Clayton 
311*f754f88fSGreg Clayton         const uint32_t addr_byte_size = GetAddressByteSize ();
312*f754f88fSGreg Clayton 
313*f754f88fSGreg Clayton         if (*offset_ptr < end_offset)
314*f754f88fSGreg Clayton         {
315*f754f88fSGreg Clayton             if (m_coff_header_opt.magic == OPT_HEADER_MAGIC_PE32)
316*f754f88fSGreg Clayton             {
317*f754f88fSGreg Clayton                 // PE32 only
318*f754f88fSGreg Clayton                 m_coff_header_opt.data_offset               = m_data.GetU32(offset_ptr);
319*f754f88fSGreg Clayton             }
320*f754f88fSGreg Clayton             else
321*f754f88fSGreg Clayton                 m_coff_header_opt.data_offset = 0;
322*f754f88fSGreg Clayton 
323*f754f88fSGreg Clayton             if (*offset_ptr < end_offset)
324*f754f88fSGreg Clayton             {
325*f754f88fSGreg Clayton                 m_coff_header_opt.image_base                    = m_data.GetMaxU64 (offset_ptr, addr_byte_size);
326*f754f88fSGreg Clayton                 m_coff_header_opt.sect_alignment                = m_data.GetU32(offset_ptr);
327*f754f88fSGreg Clayton                 m_coff_header_opt.file_alignment                = m_data.GetU32(offset_ptr);
328*f754f88fSGreg Clayton                 m_coff_header_opt.major_os_system_version       = m_data.GetU16(offset_ptr);
329*f754f88fSGreg Clayton                 m_coff_header_opt.minor_os_system_version       = m_data.GetU16(offset_ptr);
330*f754f88fSGreg Clayton                 m_coff_header_opt.major_image_version           = m_data.GetU16(offset_ptr);
331*f754f88fSGreg Clayton                 m_coff_header_opt.minor_image_version           = m_data.GetU16(offset_ptr);
332*f754f88fSGreg Clayton                 m_coff_header_opt.major_subsystem_version       = m_data.GetU16(offset_ptr);
333*f754f88fSGreg Clayton                 m_coff_header_opt.minor_subsystem_version       = m_data.GetU16(offset_ptr);
334*f754f88fSGreg Clayton                 m_coff_header_opt.reserved1                     = m_data.GetU32(offset_ptr);
335*f754f88fSGreg Clayton                 m_coff_header_opt.image_size                    = m_data.GetU32(offset_ptr);
336*f754f88fSGreg Clayton                 m_coff_header_opt.header_size                   = m_data.GetU32(offset_ptr);
337*f754f88fSGreg Clayton                 m_coff_header_opt.checksym                      = m_data.GetU32(offset_ptr);
338*f754f88fSGreg Clayton                 m_coff_header_opt.subsystem                     = m_data.GetU16(offset_ptr);
339*f754f88fSGreg Clayton                 m_coff_header_opt.dll_flags                     = m_data.GetU16(offset_ptr);
340*f754f88fSGreg Clayton                 m_coff_header_opt.stack_reserve_size            = m_data.GetMaxU64 (offset_ptr, addr_byte_size);
341*f754f88fSGreg Clayton                 m_coff_header_opt.stack_commit_size             = m_data.GetMaxU64 (offset_ptr, addr_byte_size);
342*f754f88fSGreg Clayton                 m_coff_header_opt.heap_reserve_size             = m_data.GetMaxU64 (offset_ptr, addr_byte_size);
343*f754f88fSGreg Clayton                 m_coff_header_opt.heap_commit_size              = m_data.GetMaxU64 (offset_ptr, addr_byte_size);
344*f754f88fSGreg Clayton                 m_coff_header_opt.loader_flags                  = m_data.GetU32(offset_ptr);
345*f754f88fSGreg Clayton                 uint32_t num_data_dir_entries = m_data.GetU32(offset_ptr);
346*f754f88fSGreg Clayton                 m_coff_header_opt.data_dirs.clear();
347*f754f88fSGreg Clayton                 m_coff_header_opt.data_dirs.resize(num_data_dir_entries);
348*f754f88fSGreg Clayton                 uint32_t i;
349*f754f88fSGreg Clayton                 for (i=0; i<num_data_dir_entries; i++)
350*f754f88fSGreg Clayton                 {
351*f754f88fSGreg Clayton                     m_coff_header_opt.data_dirs[i].vmaddr = m_data.GetU32(offset_ptr);
352*f754f88fSGreg Clayton                     m_coff_header_opt.data_dirs[i].vmsize = m_data.GetU32(offset_ptr);
353*f754f88fSGreg Clayton                 }
354*f754f88fSGreg Clayton             }
355*f754f88fSGreg Clayton         }
356*f754f88fSGreg Clayton     }
357*f754f88fSGreg Clayton     // Make sure we are on track for section data which follows
358*f754f88fSGreg Clayton     *offset_ptr = end_offset;
359*f754f88fSGreg Clayton     return success;
360*f754f88fSGreg Clayton }
361*f754f88fSGreg Clayton 
362*f754f88fSGreg Clayton 
363*f754f88fSGreg Clayton //----------------------------------------------------------------------
364*f754f88fSGreg Clayton // ParseSectionHeaders
365*f754f88fSGreg Clayton //----------------------------------------------------------------------
366*f754f88fSGreg Clayton bool
367*f754f88fSGreg Clayton ObjectFilePECOFF::ParseSectionHeaders (uint32_t section_header_data_offset)
368*f754f88fSGreg Clayton {
369*f754f88fSGreg Clayton     const uint32_t nsects = m_coff_header.nsects;
370*f754f88fSGreg Clayton     m_sect_headers.clear();
371*f754f88fSGreg Clayton 
372*f754f88fSGreg Clayton     if (nsects > 0)
373*f754f88fSGreg Clayton     {
374*f754f88fSGreg Clayton         const uint32_t addr_byte_size = GetAddressByteSize ();
375*f754f88fSGreg Clayton         const size_t section_header_byte_size = nsects * sizeof(section_header_t);
376*f754f88fSGreg Clayton         DataBufferSP section_header_data_sp(m_file.ReadFileContents (section_header_data_offset, section_header_byte_size));
377*f754f88fSGreg Clayton         DataExtractor section_header_data (section_header_data_sp, GetByteOrder(), addr_byte_size);
378*f754f88fSGreg Clayton 
379*f754f88fSGreg Clayton         uint32_t offset = 0;
380*f754f88fSGreg Clayton         if (section_header_data.ValidOffsetForDataOfSize (offset, section_header_byte_size))
381*f754f88fSGreg Clayton         {
382*f754f88fSGreg Clayton             m_sect_headers.resize(nsects);
383*f754f88fSGreg Clayton 
384*f754f88fSGreg Clayton             for (uint32_t idx = 0; idx<nsects; ++idx)
385*f754f88fSGreg Clayton             {
386*f754f88fSGreg Clayton                 const void *name_data = section_header_data.GetData(&offset, 8);
387*f754f88fSGreg Clayton                 if (name_data)
388*f754f88fSGreg Clayton                 {
389*f754f88fSGreg Clayton                     memcpy(m_sect_headers[idx].name, name_data, 8);
390*f754f88fSGreg Clayton                     m_sect_headers[idx].vmsize  = section_header_data.GetU32(&offset);
391*f754f88fSGreg Clayton                     m_sect_headers[idx].vmaddr  = section_header_data.GetU32(&offset);
392*f754f88fSGreg Clayton                     m_sect_headers[idx].size    = section_header_data.GetU32(&offset);
393*f754f88fSGreg Clayton                     m_sect_headers[idx].offset  = section_header_data.GetU32(&offset);
394*f754f88fSGreg Clayton                     m_sect_headers[idx].reloff  = section_header_data.GetU32(&offset);
395*f754f88fSGreg Clayton                     m_sect_headers[idx].lineoff = section_header_data.GetU32(&offset);
396*f754f88fSGreg Clayton                     m_sect_headers[idx].nreloc  = section_header_data.GetU16(&offset);
397*f754f88fSGreg Clayton                     m_sect_headers[idx].nline   = section_header_data.GetU16(&offset);
398*f754f88fSGreg Clayton                     m_sect_headers[idx].flags   = section_header_data.GetU32(&offset);
399*f754f88fSGreg Clayton                 }
400*f754f88fSGreg Clayton             }
401*f754f88fSGreg Clayton         }
402*f754f88fSGreg Clayton     }
403*f754f88fSGreg Clayton 
404*f754f88fSGreg Clayton     return m_sect_headers.empty() == false;
405*f754f88fSGreg Clayton }
406*f754f88fSGreg Clayton 
407*f754f88fSGreg Clayton bool
408*f754f88fSGreg Clayton ObjectFilePECOFF::GetSectionName(std::string& sect_name, const section_header_t& sect)
409*f754f88fSGreg Clayton {
410*f754f88fSGreg Clayton     if (sect.name[0] == '/')
411*f754f88fSGreg Clayton     {
412*f754f88fSGreg Clayton         uint32_t stroff = strtoul(&sect.name[1], NULL, 10);
413*f754f88fSGreg Clayton         uint32_t string_file_offset = m_coff_header.symoff + (m_coff_header.nsyms * 18) + stroff;
414*f754f88fSGreg Clayton         const char *name = m_data.GetCStr (&string_file_offset);
415*f754f88fSGreg Clayton         if (name)
416*f754f88fSGreg Clayton         {
417*f754f88fSGreg Clayton             sect_name = name;
418*f754f88fSGreg Clayton             return true;
419*f754f88fSGreg Clayton         }
420*f754f88fSGreg Clayton 
421*f754f88fSGreg Clayton         return false;
422*f754f88fSGreg Clayton     }
423*f754f88fSGreg Clayton     sect_name = sect.name;
424*f754f88fSGreg Clayton     return true;
425*f754f88fSGreg Clayton }
426*f754f88fSGreg Clayton 
427*f754f88fSGreg Clayton //----------------------------------------------------------------------
428*f754f88fSGreg Clayton // GetNListSymtab
429*f754f88fSGreg Clayton //----------------------------------------------------------------------
430*f754f88fSGreg Clayton Symtab *
431*f754f88fSGreg Clayton ObjectFilePECOFF::GetSymtab()
432*f754f88fSGreg Clayton {
433*f754f88fSGreg Clayton     Mutex::Locker symfile_locker(m_mutex);
434*f754f88fSGreg Clayton     if (m_symtab_ap.get() == NULL)
435*f754f88fSGreg Clayton     {
436*f754f88fSGreg Clayton         SectionList *sect_list = GetSectionList();
437*f754f88fSGreg Clayton         m_symtab_ap.reset(new Symtab(this));
438*f754f88fSGreg Clayton         Mutex::Locker symtab_locker (m_symtab_ap->GetMutex());
439*f754f88fSGreg Clayton         DataExtractor stab_data;
440*f754f88fSGreg Clayton         DataExtractor stabstr_data;
441*f754f88fSGreg Clayton         static ConstString g_stab_sect_name(".stab");
442*f754f88fSGreg Clayton         static ConstString g_stabstr_sect_name(".stabstr");
443*f754f88fSGreg Clayton         const Section *stab_section = sect_list->FindSectionByName (g_stab_sect_name).get();
444*f754f88fSGreg Clayton         if (stab_section == NULL)
445*f754f88fSGreg Clayton             return m_symtab_ap.get();
446*f754f88fSGreg Clayton         const Section *stabstr_section = sect_list->FindSectionByName (g_stabstr_sect_name).get();
447*f754f88fSGreg Clayton         if (stabstr_section == NULL)
448*f754f88fSGreg Clayton             return m_symtab_ap.get();
449*f754f88fSGreg Clayton         uint32_t offset = 0;
450*f754f88fSGreg Clayton         if (stab_section->ReadSectionDataFromObjectFile (this, stab_data) &&
451*f754f88fSGreg Clayton             stabstr_section->ReadSectionDataFromObjectFile (this, stabstr_data))
452*f754f88fSGreg Clayton         {
453*f754f88fSGreg Clayton             const uint32_t num_syms = stab_data.GetByteSize() / sizeof (coff_symbol_t);
454*f754f88fSGreg Clayton             Symbol *symbols = m_symtab_ap->Resize (num_syms);
455*f754f88fSGreg Clayton             for (uint32_t i=0; i<num_syms; ++i)
456*f754f88fSGreg Clayton             {
457*f754f88fSGreg Clayton                 coff_symbol_t symbol;
458*f754f88fSGreg Clayton                 const void *name_data = stab_data.GetData(&offset, sizeof(symbol.name));
459*f754f88fSGreg Clayton 
460*f754f88fSGreg Clayton                 if (name_data == NULL)
461*f754f88fSGreg Clayton                     break;
462*f754f88fSGreg Clayton                 memcpy (symbol.name, name_data, sizeof(symbol.name));
463*f754f88fSGreg Clayton                 symbol.value = stab_data.GetU32 (&offset);
464*f754f88fSGreg Clayton                 symbol.sect = stab_data.GetU16 (&offset);
465*f754f88fSGreg Clayton                 symbol.type = stab_data.GetU16 (&offset);
466*f754f88fSGreg Clayton                 symbol.storage = stab_data.GetU8 (&offset);
467*f754f88fSGreg Clayton                 symbol.naux = stab_data.GetU8 (&offset);
468*f754f88fSGreg Clayton 
469*f754f88fSGreg Clayton                 symbol.name[sizeof(symbol.name)-1] = '\0';
470*f754f88fSGreg Clayton                 Address symbol_addr(sect_list->GetSectionAtIndex(symbol.sect-1).get(), symbol.value);
471*f754f88fSGreg Clayton                 symbols[i].GetMangled ().SetValue(symbol.name, symbol.name[0]=='_' && symbol.name[1] == 'Z');
472*f754f88fSGreg Clayton                 symbols[i].SetValue(symbol_addr);
473*f754f88fSGreg Clayton 
474*f754f88fSGreg Clayton                 if (symbol.naux > 0)
475*f754f88fSGreg Clayton                     i += symbol.naux;
476*f754f88fSGreg Clayton             }
477*f754f88fSGreg Clayton 
478*f754f88fSGreg Clayton         }
479*f754f88fSGreg Clayton     }
480*f754f88fSGreg Clayton     return m_symtab_ap.get();
481*f754f88fSGreg Clayton 
482*f754f88fSGreg Clayton }
483*f754f88fSGreg Clayton 
484*f754f88fSGreg Clayton SectionList *
485*f754f88fSGreg Clayton ObjectFilePECOFF::GetSectionList()
486*f754f88fSGreg Clayton {
487*f754f88fSGreg Clayton     Mutex::Locker symfile_locker(m_mutex);
488*f754f88fSGreg Clayton     if (m_sections_ap.get() == NULL)
489*f754f88fSGreg Clayton     {
490*f754f88fSGreg Clayton         m_sections_ap.reset(new SectionList());
491*f754f88fSGreg Clayton         const uint32_t nsects = m_sect_headers.size();
492*f754f88fSGreg Clayton         Module *module = GetModule();
493*f754f88fSGreg Clayton         for (uint32_t idx = 0; idx<nsects; ++idx)
494*f754f88fSGreg Clayton         {
495*f754f88fSGreg Clayton             std::string sect_name;
496*f754f88fSGreg Clayton             GetSectionName (sect_name, m_sect_headers[idx]);
497*f754f88fSGreg Clayton             ConstString const_sect_name (sect_name.c_str());
498*f754f88fSGreg Clayton 
499*f754f88fSGreg Clayton             // Use a segment ID of the segment index shifted left by 8 so they
500*f754f88fSGreg Clayton             // never conflict with any of the sections.
501*f754f88fSGreg Clayton             SectionSP section_sp (new Section (NULL,
502*f754f88fSGreg Clayton                                                module,                       // Module to which this section belongs
503*f754f88fSGreg Clayton                                                idx + 1,                      // Section ID is the 1 based segment index shifted right by 8 bits as not to collide with any of the 256 section IDs that are possible
504*f754f88fSGreg Clayton                                                const_sect_name,              // Name of this section
505*f754f88fSGreg Clayton                                                eSectionTypeCode,             // This section is a container of other sections.
506*f754f88fSGreg Clayton                                                m_sect_headers[idx].vmaddr,   // File VM address == addresses as they are found in the object file
507*f754f88fSGreg Clayton                                                m_sect_headers[idx].vmsize,   // VM size in bytes of this section
508*f754f88fSGreg Clayton                                                m_sect_headers[idx].offset,   // Offset to the data for this section in the file
509*f754f88fSGreg Clayton                                                m_sect_headers[idx].size,     // Size in bytes of this section as found in the the file
510*f754f88fSGreg Clayton                                                m_sect_headers[idx].flags));  // Flags for this section
511*f754f88fSGreg Clayton 
512*f754f88fSGreg Clayton             //section_sp->SetIsEncrypted (segment_is_encrypted);
513*f754f88fSGreg Clayton 
514*f754f88fSGreg Clayton             m_sections_ap->AddSection(section_sp);
515*f754f88fSGreg Clayton         }
516*f754f88fSGreg Clayton     }
517*f754f88fSGreg Clayton     return m_sections_ap.get();
518*f754f88fSGreg Clayton }
519*f754f88fSGreg Clayton 
520*f754f88fSGreg Clayton bool
521*f754f88fSGreg Clayton ObjectFilePECOFF::GetUUID (UUID* uuid)
522*f754f88fSGreg Clayton {
523*f754f88fSGreg Clayton     return false;
524*f754f88fSGreg Clayton }
525*f754f88fSGreg Clayton 
526*f754f88fSGreg Clayton uint32_t
527*f754f88fSGreg Clayton ObjectFilePECOFF::GetDependentModules (FileSpecList& files)
528*f754f88fSGreg Clayton {
529*f754f88fSGreg Clayton     return 0;
530*f754f88fSGreg Clayton }
531*f754f88fSGreg Clayton 
532*f754f88fSGreg Clayton 
533*f754f88fSGreg Clayton //----------------------------------------------------------------------
534*f754f88fSGreg Clayton // Dump
535*f754f88fSGreg Clayton //
536*f754f88fSGreg Clayton // Dump the specifics of the runtime file container (such as any headers
537*f754f88fSGreg Clayton // segments, sections, etc).
538*f754f88fSGreg Clayton //----------------------------------------------------------------------
539*f754f88fSGreg Clayton void
540*f754f88fSGreg Clayton ObjectFilePECOFF::Dump(Stream *s)
541*f754f88fSGreg Clayton {
542*f754f88fSGreg Clayton     Mutex::Locker locker(m_mutex);
543*f754f88fSGreg Clayton     s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
544*f754f88fSGreg Clayton     s->Indent();
545*f754f88fSGreg Clayton     s->PutCString("ObjectFilePECOFF");
546*f754f88fSGreg Clayton 
547*f754f88fSGreg Clayton     ArchSpec header_arch;
548*f754f88fSGreg Clayton     GetArchitecture (header_arch);
549*f754f88fSGreg Clayton 
550*f754f88fSGreg Clayton     *s << ", file = '" << m_file << "', arch = " << header_arch.GetArchitectureName() << "\n";
551*f754f88fSGreg Clayton 
552*f754f88fSGreg Clayton     if (m_sections_ap.get())
553*f754f88fSGreg Clayton         m_sections_ap->Dump(s, NULL, true, UINT32_MAX);
554*f754f88fSGreg Clayton 
555*f754f88fSGreg Clayton     if (m_symtab_ap.get())
556*f754f88fSGreg Clayton         m_symtab_ap->Dump(s, NULL, eSortOrderNone);
557*f754f88fSGreg Clayton 
558*f754f88fSGreg Clayton     if (m_dos_header.e_magic)
559*f754f88fSGreg Clayton         DumpDOSHeader (s, m_dos_header);
560*f754f88fSGreg Clayton     if (m_coff_header.machine)
561*f754f88fSGreg Clayton     {
562*f754f88fSGreg Clayton         DumpCOFFHeader (s, m_coff_header);
563*f754f88fSGreg Clayton         if (m_coff_header.hdrsize)
564*f754f88fSGreg Clayton             DumpOptCOFFHeader (s, m_coff_header_opt);
565*f754f88fSGreg Clayton     }
566*f754f88fSGreg Clayton     s->EOL();
567*f754f88fSGreg Clayton     DumpSectionHeaders(s);
568*f754f88fSGreg Clayton     s->EOL();
569*f754f88fSGreg Clayton }
570*f754f88fSGreg Clayton 
571*f754f88fSGreg Clayton //----------------------------------------------------------------------
572*f754f88fSGreg Clayton // DumpDOSHeader
573*f754f88fSGreg Clayton //
574*f754f88fSGreg Clayton // Dump the MS-DOS header to the specified output stream
575*f754f88fSGreg Clayton //----------------------------------------------------------------------
576*f754f88fSGreg Clayton void
577*f754f88fSGreg Clayton ObjectFilePECOFF::DumpDOSHeader(Stream *s, const dos_header_t& header)
578*f754f88fSGreg Clayton {
579*f754f88fSGreg Clayton     s->PutCString ("MSDOS Header\n");
580*f754f88fSGreg Clayton     s->Printf ("  e_magic    = 0x%4.4x\n", header.e_magic);
581*f754f88fSGreg Clayton     s->Printf ("  e_cblp     = 0x%4.4x\n", header.e_cblp);
582*f754f88fSGreg Clayton     s->Printf ("  e_cp       = 0x%4.4x\n", header.e_cp);
583*f754f88fSGreg Clayton     s->Printf ("  e_crlc     = 0x%4.4x\n", header.e_crlc);
584*f754f88fSGreg Clayton     s->Printf ("  e_cparhdr  = 0x%4.4x\n", header.e_cparhdr);
585*f754f88fSGreg Clayton     s->Printf ("  e_minalloc = 0x%4.4x\n", header.e_minalloc);
586*f754f88fSGreg Clayton     s->Printf ("  e_maxalloc = 0x%4.4x\n", header.e_maxalloc);
587*f754f88fSGreg Clayton     s->Printf ("  e_ss       = 0x%4.4x\n", header.e_ss);
588*f754f88fSGreg Clayton     s->Printf ("  e_sp       = 0x%4.4x\n", header.e_sp);
589*f754f88fSGreg Clayton     s->Printf ("  e_csum     = 0x%4.4x\n", header.e_csum);
590*f754f88fSGreg Clayton     s->Printf ("  e_ip       = 0x%4.4x\n", header.e_ip);
591*f754f88fSGreg Clayton     s->Printf ("  e_cs       = 0x%4.4x\n", header.e_cs);
592*f754f88fSGreg Clayton     s->Printf ("  e_lfarlc   = 0x%4.4x\n", header.e_lfarlc);
593*f754f88fSGreg Clayton     s->Printf ("  e_ovno     = 0x%4.4x\n", header.e_ovno);
594*f754f88fSGreg Clayton     s->Printf ("  e_res[4]   = { 0x%4.4x, 0x%4.4x, 0x%4.4x, 0x%4.4x }\n",
595*f754f88fSGreg Clayton                header.e_res[0],
596*f754f88fSGreg Clayton                header.e_res[1],
597*f754f88fSGreg Clayton                header.e_res[2],
598*f754f88fSGreg Clayton                header.e_res[3]);
599*f754f88fSGreg Clayton     s->Printf ("  e_oemid    = 0x%4.4x\n", header.e_oemid);
600*f754f88fSGreg Clayton     s->Printf ("  e_oeminfo  = 0x%4.4x\n", header.e_oeminfo);
601*f754f88fSGreg Clayton     s->Printf ("  e_res2[10] = { 0x%4.4x, 0x%4.4x, 0x%4.4x, 0x%4.4x, 0x%4.4x, 0x%4.4x, 0x%4.4x, 0x%4.4x, 0x%4.4x, 0x%4.4x }\n",
602*f754f88fSGreg Clayton                header.e_res2[0],
603*f754f88fSGreg Clayton                header.e_res2[1],
604*f754f88fSGreg Clayton                header.e_res2[2],
605*f754f88fSGreg Clayton                header.e_res2[3],
606*f754f88fSGreg Clayton                header.e_res2[4],
607*f754f88fSGreg Clayton                header.e_res2[5],
608*f754f88fSGreg Clayton                header.e_res2[6],
609*f754f88fSGreg Clayton                header.e_res2[7],
610*f754f88fSGreg Clayton                header.e_res2[8],
611*f754f88fSGreg Clayton                header.e_res2[9]);
612*f754f88fSGreg Clayton     s->Printf ("  e_lfanew   = 0x%8.8x\n", header.e_lfanew);
613*f754f88fSGreg Clayton }
614*f754f88fSGreg Clayton 
615*f754f88fSGreg Clayton //----------------------------------------------------------------------
616*f754f88fSGreg Clayton // DumpCOFFHeader
617*f754f88fSGreg Clayton //
618*f754f88fSGreg Clayton // Dump the COFF header to the specified output stream
619*f754f88fSGreg Clayton //----------------------------------------------------------------------
620*f754f88fSGreg Clayton void
621*f754f88fSGreg Clayton ObjectFilePECOFF::DumpCOFFHeader(Stream *s, const coff_header_t& header)
622*f754f88fSGreg Clayton {
623*f754f88fSGreg Clayton     s->PutCString ("COFF Header\n");
624*f754f88fSGreg Clayton     s->Printf ("  machine = 0x%4.4x\n", header.machine);
625*f754f88fSGreg Clayton     s->Printf ("  nsects  = 0x%4.4x\n", header.nsects);
626*f754f88fSGreg Clayton     s->Printf ("  modtime = 0x%8.8x\n", header.modtime);
627*f754f88fSGreg Clayton     s->Printf ("  symoff  = 0x%8.8x\n", header.symoff);
628*f754f88fSGreg Clayton     s->Printf ("  nsyms   = 0x%8.8x\n", header.nsyms);
629*f754f88fSGreg Clayton     s->Printf ("  hdrsize = 0x%4.4x\n", header.hdrsize);
630*f754f88fSGreg Clayton }
631*f754f88fSGreg Clayton 
632*f754f88fSGreg Clayton //----------------------------------------------------------------------
633*f754f88fSGreg Clayton // DumpOptCOFFHeader
634*f754f88fSGreg Clayton //
635*f754f88fSGreg Clayton // Dump the optional COFF header to the specified output stream
636*f754f88fSGreg Clayton //----------------------------------------------------------------------
637*f754f88fSGreg Clayton void
638*f754f88fSGreg Clayton ObjectFilePECOFF::DumpOptCOFFHeader(Stream *s, const coff_opt_header_t& header)
639*f754f88fSGreg Clayton {
640*f754f88fSGreg Clayton     s->PutCString ("Optional COFF Header\n");
641*f754f88fSGreg Clayton     s->Printf ("  magic                   = 0x%4.4x\n", header.magic);
642*f754f88fSGreg Clayton     s->Printf ("  major_linker_version    = 0x%2.2x\n", header.major_linker_version);
643*f754f88fSGreg Clayton     s->Printf ("  minor_linker_version    = 0x%2.2x\n", header.minor_linker_version);
644*f754f88fSGreg Clayton     s->Printf ("  code_size               = 0x%8.8x\n", header.code_size);
645*f754f88fSGreg Clayton     s->Printf ("  data_size               = 0x%8.8x\n", header.data_size);
646*f754f88fSGreg Clayton     s->Printf ("  bss_size                = 0x%8.8x\n", header.bss_size);
647*f754f88fSGreg Clayton     s->Printf ("  entry                   = 0x%8.8x\n", header.entry);
648*f754f88fSGreg Clayton     s->Printf ("  code_offset             = 0x%8.8x\n", header.code_offset);
649*f754f88fSGreg Clayton     s->Printf ("  data_offset             = 0x%8.8x\n", header.data_offset);
650*f754f88fSGreg Clayton     s->Printf ("  image_base              = 0x%16.16llx\n", header.image_base);
651*f754f88fSGreg Clayton     s->Printf ("  sect_alignment          = 0x%8.8x\n", header.sect_alignment);
652*f754f88fSGreg Clayton     s->Printf ("  file_alignment          = 0x%8.8x\n", header.file_alignment);
653*f754f88fSGreg Clayton     s->Printf ("  major_os_system_version = 0x%4.4x\n", header.major_os_system_version);
654*f754f88fSGreg Clayton     s->Printf ("  minor_os_system_version = 0x%4.4x\n", header.minor_os_system_version);
655*f754f88fSGreg Clayton     s->Printf ("  major_image_version     = 0x%4.4x\n", header.major_image_version);
656*f754f88fSGreg Clayton     s->Printf ("  minor_image_version     = 0x%4.4x\n", header.minor_image_version);
657*f754f88fSGreg Clayton     s->Printf ("  major_subsystem_version = 0x%4.4x\n", header.major_subsystem_version);
658*f754f88fSGreg Clayton     s->Printf ("  minor_subsystem_version = 0x%4.4x\n", header.minor_subsystem_version);
659*f754f88fSGreg Clayton     s->Printf ("  reserved1               = 0x%8.8x\n", header.reserved1);
660*f754f88fSGreg Clayton     s->Printf ("  image_size              = 0x%8.8x\n", header.image_size);
661*f754f88fSGreg Clayton     s->Printf ("  header_size             = 0x%8.8x\n", header.header_size);
662*f754f88fSGreg Clayton     s->Printf ("  checksym                = 0x%8.8x\n", header.checksym);
663*f754f88fSGreg Clayton     s->Printf ("  subsystem               = 0x%4.4x\n", header.subsystem);
664*f754f88fSGreg Clayton     s->Printf ("  dll_flags               = 0x%4.4x\n", header.dll_flags);
665*f754f88fSGreg Clayton     s->Printf ("  stack_reserve_size      = 0x%16.16llx\n", header.stack_reserve_size);
666*f754f88fSGreg Clayton     s->Printf ("  stack_commit_size       = 0x%16.16llx\n", header.stack_commit_size);
667*f754f88fSGreg Clayton     s->Printf ("  heap_reserve_size       = 0x%16.16llx\n", header.heap_reserve_size);
668*f754f88fSGreg Clayton     s->Printf ("  heap_commit_size        = 0x%16.16llx\n", header.heap_commit_size);
669*f754f88fSGreg Clayton     s->Printf ("  loader_flags            = 0x%8.8x\n", header.loader_flags);
670*f754f88fSGreg Clayton     s->Printf ("  num_data_dir_entries    = 0x%8.8zx\n", header.data_dirs.size());
671*f754f88fSGreg Clayton     uint32_t i;
672*f754f88fSGreg Clayton     for (i=0; i<header.data_dirs.size(); i++)
673*f754f88fSGreg Clayton     {
674*f754f88fSGreg Clayton         s->Printf ("  data_dirs[%u] vmaddr = 0x%8.8x, vmsize = 0x%8.8x\n",
675*f754f88fSGreg Clayton                    i,
676*f754f88fSGreg Clayton                    header.data_dirs[i].vmaddr,
677*f754f88fSGreg Clayton                    header.data_dirs[i].vmsize);
678*f754f88fSGreg Clayton     }
679*f754f88fSGreg Clayton }
680*f754f88fSGreg Clayton //----------------------------------------------------------------------
681*f754f88fSGreg Clayton // DumpSectionHeader
682*f754f88fSGreg Clayton //
683*f754f88fSGreg Clayton // Dump a single ELF section header to the specified output stream
684*f754f88fSGreg Clayton //----------------------------------------------------------------------
685*f754f88fSGreg Clayton void
686*f754f88fSGreg Clayton ObjectFilePECOFF::DumpSectionHeader(Stream *s, const section_header_t& sh)
687*f754f88fSGreg Clayton {
688*f754f88fSGreg Clayton     std::string name;
689*f754f88fSGreg Clayton     GetSectionName(name, sh);
690*f754f88fSGreg Clayton     s->Printf ("%-16s 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x 0x%4.4x 0x%4.4x 0x%8.8x\n",
691*f754f88fSGreg Clayton                name.c_str(),
692*f754f88fSGreg Clayton                sh.vmsize,
693*f754f88fSGreg Clayton                sh.vmaddr,
694*f754f88fSGreg Clayton                sh.size,
695*f754f88fSGreg Clayton                sh.offset,
696*f754f88fSGreg Clayton                sh.reloff,
697*f754f88fSGreg Clayton                sh.lineoff,
698*f754f88fSGreg Clayton                sh.nreloc,
699*f754f88fSGreg Clayton                sh.nline,
700*f754f88fSGreg Clayton                sh.flags);
701*f754f88fSGreg Clayton }
702*f754f88fSGreg Clayton 
703*f754f88fSGreg Clayton 
704*f754f88fSGreg Clayton //----------------------------------------------------------------------
705*f754f88fSGreg Clayton // DumpSectionHeaders
706*f754f88fSGreg Clayton //
707*f754f88fSGreg Clayton // Dump all of the ELF section header to the specified output stream
708*f754f88fSGreg Clayton //----------------------------------------------------------------------
709*f754f88fSGreg Clayton void
710*f754f88fSGreg Clayton ObjectFilePECOFF::DumpSectionHeaders(Stream *s)
711*f754f88fSGreg Clayton {
712*f754f88fSGreg Clayton 
713*f754f88fSGreg Clayton     s->PutCString ("Section Headers\n");
714*f754f88fSGreg Clayton     s->PutCString ("IDX  name             vm size  vm addr  size     offset   reloff   lineoff  nrel nlin flags\n");
715*f754f88fSGreg Clayton     s->PutCString ("==== ---------------- -------- -------- -------- -------- -------- -------- ---- ---- --------\n");
716*f754f88fSGreg Clayton 
717*f754f88fSGreg Clayton     uint32_t idx = 0;
718*f754f88fSGreg Clayton     SectionHeaderCollIter pos, end = m_sect_headers.end();
719*f754f88fSGreg Clayton 
720*f754f88fSGreg Clayton     for (pos = m_sect_headers.begin(); pos != end; ++pos, ++idx)
721*f754f88fSGreg Clayton     {
722*f754f88fSGreg Clayton         s->Printf ("[%2u]", idx);
723*f754f88fSGreg Clayton         ObjectFilePECOFF::DumpSectionHeader(s, *pos);
724*f754f88fSGreg Clayton     }
725*f754f88fSGreg Clayton }
726*f754f88fSGreg Clayton 
727*f754f88fSGreg Clayton static bool
728*f754f88fSGreg Clayton COFFMachineToMachCPU (uint16_t machine, ArchSpec &arch)
729*f754f88fSGreg Clayton {
730*f754f88fSGreg Clayton     switch (machine)
731*f754f88fSGreg Clayton     {
732*f754f88fSGreg Clayton         case IMAGE_FILE_MACHINE_AMD64:
733*f754f88fSGreg Clayton         case IMAGE_FILE_MACHINE_IA64:
734*f754f88fSGreg Clayton             arch.SetArchitecture (eArchTypeMachO,
735*f754f88fSGreg Clayton                                   llvm::MachO::CPUTypeX86_64,
736*f754f88fSGreg Clayton                                   llvm::MachO::CPUSubType_X86_64_ALL);
737*f754f88fSGreg Clayton             return true;
738*f754f88fSGreg Clayton 
739*f754f88fSGreg Clayton         case IMAGE_FILE_MACHINE_I386:
740*f754f88fSGreg Clayton             arch.SetArchitecture (eArchTypeMachO,
741*f754f88fSGreg Clayton                                   llvm::MachO::CPUTypeI386,
742*f754f88fSGreg Clayton                                   llvm::MachO::CPUSubType_I386_ALL);
743*f754f88fSGreg Clayton             return true;
744*f754f88fSGreg Clayton 
745*f754f88fSGreg Clayton         case IMAGE_FILE_MACHINE_POWERPC:
746*f754f88fSGreg Clayton         case IMAGE_FILE_MACHINE_POWERPCFP:
747*f754f88fSGreg Clayton             arch.SetArchitecture (eArchTypeMachO,
748*f754f88fSGreg Clayton                                   llvm::MachO::CPUTypePowerPC,
749*f754f88fSGreg Clayton                                   llvm::MachO::CPUSubType_POWERPC_ALL);
750*f754f88fSGreg Clayton             return true;
751*f754f88fSGreg Clayton         case IMAGE_FILE_MACHINE_ARM:
752*f754f88fSGreg Clayton         case IMAGE_FILE_MACHINE_THUMB:
753*f754f88fSGreg Clayton             arch.SetArchitecture (eArchTypeMachO,
754*f754f88fSGreg Clayton                                   llvm::MachO::CPUTypeARM,
755*f754f88fSGreg Clayton                                   llvm::MachO::CPUSubType_ARM_V7);
756*f754f88fSGreg Clayton             return true;
757*f754f88fSGreg Clayton     }
758*f754f88fSGreg Clayton     return false;
759*f754f88fSGreg Clayton }
760*f754f88fSGreg Clayton bool
761*f754f88fSGreg Clayton ObjectFilePECOFF::GetArchitecture (ArchSpec &arch)
762*f754f88fSGreg Clayton {
763*f754f88fSGreg Clayton     // For index zero return our cpu type
764*f754f88fSGreg Clayton     return COFFMachineToMachCPU (m_coff_header.machine, arch);
765*f754f88fSGreg Clayton }
766*f754f88fSGreg Clayton 
767*f754f88fSGreg Clayton ObjectFile::Type
768*f754f88fSGreg Clayton ObjectFilePECOFF::CalculateType()
769*f754f88fSGreg Clayton {
770*f754f88fSGreg Clayton     if (m_coff_header.machine != 0)
771*f754f88fSGreg Clayton     {
772*f754f88fSGreg Clayton         if ((m_coff_header.flags & IMAGE_FILE_DLL) == 0)
773*f754f88fSGreg Clayton             return eTypeExecutable;
774*f754f88fSGreg Clayton         else
775*f754f88fSGreg Clayton             return eTypeSharedLibrary;
776*f754f88fSGreg Clayton     }
777*f754f88fSGreg Clayton     return eTypeExecutable;
778*f754f88fSGreg Clayton }
779*f754f88fSGreg Clayton 
780*f754f88fSGreg Clayton ObjectFile::Strata
781*f754f88fSGreg Clayton ObjectFilePECOFF::CalculateStrata()
782*f754f88fSGreg Clayton {
783*f754f88fSGreg Clayton     return eStrataUser;
784*f754f88fSGreg Clayton }
785*f754f88fSGreg Clayton //------------------------------------------------------------------
786*f754f88fSGreg Clayton // PluginInterface protocol
787*f754f88fSGreg Clayton //------------------------------------------------------------------
788*f754f88fSGreg Clayton const char *
789*f754f88fSGreg Clayton ObjectFilePECOFF::GetPluginName()
790*f754f88fSGreg Clayton {
791*f754f88fSGreg Clayton     return "ObjectFilePECOFF";
792*f754f88fSGreg Clayton }
793*f754f88fSGreg Clayton 
794*f754f88fSGreg Clayton const char *
795*f754f88fSGreg Clayton ObjectFilePECOFF::GetShortPluginName()
796*f754f88fSGreg Clayton {
797*f754f88fSGreg Clayton     return GetPluginNameStatic();
798*f754f88fSGreg Clayton }
799*f754f88fSGreg Clayton 
800*f754f88fSGreg Clayton uint32_t
801*f754f88fSGreg Clayton ObjectFilePECOFF::GetPluginVersion()
802*f754f88fSGreg Clayton {
803*f754f88fSGreg Clayton     return 1;
804*f754f88fSGreg Clayton }
805*f754f88fSGreg Clayton 
806