source: trunk/tools/common/kFilePE.cpp@ 5053

Last change on this file since 5053 was 5053, checked in by bird, 25 years ago

Corrected kFileLX and kFilePE constructors.
Made kDump.exe work again.
Added import module dump to kFilePE.

File size: 13.1 KB
Line 
1/*
2 * kFilePE - PE files.
3 *
4 * Copyright (c) 1999 knut st. osmundsen
5 *
6 */
7
8/*******************************************************************************
9* Defined Constants *
10*******************************************************************************/
11/* emx fixups */
12#ifdef __EMX__
13 #define __stdcall
14 #define max(a,b) (((a) > (b)) ? (a) : (b))
15 #define min(a,b) (((a) < (b)) ? (a) : (b))
16#endif
17
18/******************************************************************************
19* Header Files *
20******************************************************************************/
21#ifdef __EMX__
22#define INT INT_
23#define PCHAR PCHAR_
24#endif
25#include <os2.h>
26#ifdef __EMX__
27#undef PCHAR
28#undef INT
29#endif
30#include <stdio.h>
31#include <stdlib.h>
32#include <string.h>
33#include <malloc.h>
34#include <assert.h>
35#include <peexe.h>
36#include "kFile.h"
37#include "kFileFormatBase.h"
38#include "kFilePe.h"
39
40
41/**
42 * Constructs a kFilePE object for a file.
43 * @param pFile File to create object from.
44 * @remark throws errorcode (TODO: errorhandling.)
45 */
46kFilePE::kFilePE(kFile *pFile) throw(int) : pvBase(NULL),
47 pDosHdr(NULL), pFileHdr(NULL), pOptHdr(NULL), paDataDir(NULL), paSectionHdr(NULL),
48 pExportDir(NULL),
49 pImportDir(NULL),
50 pRsrcDir(NULL),
51 pBRelocDir(NULL),
52 pDebugDir(NULL),
53 pCopyright(NULL),
54 pulGlobalPtr(NULL),
55 pTLSDir(NULL),
56 pLoadConfigDir(NULL),
57 pBoundImportDir(NULL),
58 pIATDir(NULL),
59 pDelayImportDir(NULL)
60{
61 IMAGE_DOS_HEADER doshdr;
62
63 /* read dos-header - assumes there is one */
64 if ( pFile->readAt(&doshdr, sizeof(doshdr), 0)
65 && doshdr.e_magic == IMAGE_DOS_SIGNATURE
66 && doshdr.e_lfanew > sizeof(doshdr)
67 )
68 {
69 IMAGE_NT_HEADERS pehdr;
70
71 /* read pe headers */
72 if ( pFile->readAt(&pehdr, sizeof(pehdr), doshdr.e_lfanew)
73 && pehdr.Signature == IMAGE_NT_SIGNATURE
74 && pehdr.FileHeader.SizeOfOptionalHeader == sizeof(IMAGE_OPTIONAL_HEADER)
75 && pehdr.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR_MAGIC)
76 {
77 /* create mapping */
78 pvBase = calloc((size_t)pehdr.OptionalHeader.SizeOfImage, 1);
79 if (pvBase != NULL)
80 {
81 /*
82 printf("%ld\n", pehdr.OptionalHeader.SizeOfHeaders);
83 printf("%ld\n", sizeof(IMAGE_NT_HEADERS) + sizeof(IMAGE_SECTION_HEADER) * pehdr.FileHeader.NumberOfSections);
84 assert(pehdr.OptionalHeader.SizeOfHeaders ==
85 sizeof(IMAGE_NT_HEADERS) + sizeof(IMAGE_SECTION_HEADER) * pehdr.FileHeader.NumberOfSections);
86 */
87 if (pFile->readAt(pvBase, pehdr.OptionalHeader.SizeOfHeaders, 0))
88 {
89 /* read sections */
90 for (int i = 0; i < pehdr.FileHeader.NumberOfSections; i++)
91 {
92 ULONG cbSection;
93 PIMAGE_SECTION_HEADER pSectionHdr =
94 #if 0
95 IMAGE_FIRST_SECTION(((ULONG)pvBase + ((PIMAGE_DOS_HEADER)pvBase)->e_lfanew));
96 #else
97 (PIMAGE_SECTION_HEADER) ( (ULONG)pvBase + doshdr.e_lfanew + sizeof(IMAGE_NT_HEADERS) );
98 #endif
99 pSectionHdr += i;
100
101 cbSection = min(pSectionHdr->Misc.VirtualSize, pSectionHdr->SizeOfRawData);
102 if ( cbSection
103 && !pFile->readAt((char*)pvBase + pSectionHdr->VirtualAddress,
104 cbSection,
105 pSectionHdr->PointerToRawData)
106 )
107 {
108 /* error */
109 free(pvBase);
110 pvBase = NULL;
111 throw(6);
112 }
113 }
114
115 /* set pointers */
116 if (*(unsigned short*)pvBase == IMAGE_DOS_SIGNATURE)
117 {
118 pDosHdr = (PIMAGE_DOS_HEADER)pvBase;
119 pFileHdr = (PIMAGE_FILE_HEADER)((DWORD)pvBase + pDosHdr->e_lfanew + 4);
120 }
121 else
122 pFileHdr = (PIMAGE_FILE_HEADER)((DWORD)pvBase + 4);
123
124 pOptHdr = (PIMAGE_OPTIONAL_HEADER)((int)pFileHdr + sizeof(*pFileHdr));
125 paDataDir = (PIMAGE_DATA_DIRECTORY)((int)pOptHdr + pFileHdr->SizeOfOptionalHeader
126 - pOptHdr->NumberOfRvaAndSizes*sizeof(*paDataDir));
127 paSectionHdr = (PIMAGE_SECTION_HEADER)((int)paDataDir +
128 pOptHdr->NumberOfRvaAndSizes*sizeof(*paDataDir));
129
130 //if (paDataDir[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress)
131 // pExportDir = (PIMAGE_EXPORT_DIRECTORY)((int)pvBase + paDataDir[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
132 for (i = 0; i < pOptHdr->NumberOfRvaAndSizes && i < 16; i++)
133 {
134 if (paDataDir[i].VirtualAddress != 0)
135 {
136 if (paDataDir[i].VirtualAddress < pOptHdr->SizeOfImage)
137 ((PULONG)&this->pExportDir)[i] = (int)pvBase + paDataDir[i].VirtualAddress;
138 #ifdef DEBUG
139 else
140 fprintf(stderr, "bad directory pointer %d\n", i);
141 #endif
142 }
143 }
144 }
145 else
146 throw(4);
147 }
148 else
149 throw(3);
150 }
151 else
152 throw(2);
153 }
154 else
155 throw(1);
156}
157
158
159/**
160 * Destructor.
161 */
162kFilePE::~kFilePE()
163{
164 if (pvBase)
165 delete pvBase;
166}
167
168
169/**
170 * Query for the module name.
171 * @returns Success indicator. TRUE / FALSE.
172 * @param pszBuffer Pointer to buffer which to put the name into.
173 */
174BOOL kFilePE::queryModuleName(char *pszBuffer)
175{
176 if (pExportDir && pExportDir->Name)
177 strcpy(pszBuffer, (char*)((int)pExportDir->Name + (int)pvBase));
178 else
179 return FALSE;
180
181 return TRUE;
182}
183
184
185/**
186 * Finds the first exports.
187 * @returns Success indicator. TRUE / FALSE.
188 * @param pExport Pointer to export structure.
189 * @remark
190 */
191BOOL kFilePE::findFirstExport(PEXPORTENTRY pExport)
192{
193 if (pExportDir && pExportDir->NumberOfFunctions)
194 {
195 memset(pExport, 0, sizeof(EXPORTENTRY));
196 pExport->ulOrdinal = pExportDir->Base - 1;
197 return findNextExport(pExport);
198 }
199
200 return FALSE;
201}
202
203
204/**
205 * Finds the next export.
206 * @returns Success indicator. TRUE / FALSE.
207 * @param pExport Pointer to export structure.
208 * @remark
209 */
210BOOL kFilePE::findNextExport(PEXPORTENTRY pExport)
211{
212 if (pExportDir && pExportDir->NumberOfFunctions)
213 {
214 void **ppv = (void**)((int)pExportDir->AddressOfFunctions + (int)pvBase);
215
216 ++pExport->ulOrdinal -= pExportDir->Base;
217 while (ppv[pExport->ulOrdinal] == NULL && pExport->ulOrdinal < pExportDir->NumberOfFunctions)
218 pExport->ulOrdinal++;
219
220 if (pExport->ulOrdinal < pExportDir->NumberOfFunctions)
221 {
222 int iName = 0;
223 unsigned short *pawNameOrdinals = (unsigned short *)
224 ((int)pExportDir->AddressOfNameOrdinals + (int)pvBase);
225
226 /* look for name */
227 while (iName < (int)pExportDir->NumberOfNames &&
228 pawNameOrdinals[iName] != pExport->ulOrdinal)
229 iName++;
230 if (iName < (int)pExportDir->NumberOfNames)
231 strcpy(&pExport->achName[0],
232 (char*)((int)pvBase + ((int*)((int)pvBase + (int)pExportDir->AddressOfNames))[iName]));
233 else
234 pExport->achName[0] = '\0';
235 pExport->ulOrdinal += pExportDir->Base;
236 }
237 else
238 return FALSE;
239 }
240 else
241 return FALSE;
242
243 pExport->achIntName[0] = '\0';
244 pExport->pv = NULL;
245 return TRUE;
246}
247
248
249/**
250 * Mini dump function.
251 */
252BOOL kFilePE::dump(kFile *pOut)
253{
254 int i,j,k;
255 int c;
256
257 /*
258 * Dump sections.
259 */
260 pOut->printf("Sections\n"
261 "--------\n");
262 for (i = 0; i < pFileHdr->NumberOfSections; i++)
263 {
264 pOut->printf("%2d %-8.8s VirtSize: 0x%08x RVA: 0x%08x\n"
265 " RawSize: 0x%08x FileOffset: 0x%08x\n"
266 " #Relocs: 0x%08x FileOffset: 0x%08x\n"
267 " #LineNbr: 0x%08x FileOffset: 0x%08x\n"
268 " Characteristics: 0x%08x\n",
269 i,
270 paSectionHdr[i].Name,
271 paSectionHdr[i].Misc.VirtualSize,
272 paSectionHdr[i].VirtualAddress,
273 paSectionHdr[i].PointerToRawData,
274 paSectionHdr[i].PointerToRawData,
275 paSectionHdr[i].NumberOfRelocations,
276 paSectionHdr[i].PointerToRelocations,
277 paSectionHdr[i].NumberOfLinenumbers,
278 paSectionHdr[i].PointerToLinenumbers,
279 paSectionHdr[i].Characteristics
280 );
281 }
282 pOut->printf("\n");
283
284
285 /*
286 * Dump the directories.
287 */
288 pOut->printf("Data Directory\n"
289 "--------------\n");
290 for (i = 0; i < pOptHdr->NumberOfRvaAndSizes; i++)
291 {
292 static const char * apszDirectoryNames[] =
293 {
294 "Export",
295 "Import",
296 "Resource",
297 "Exception",
298 "Security",
299 "Base Reloc",
300 "Debug",
301 "Copyright",
302 "Global Ptr",
303 "TLS",
304 "Load Config",
305 "Bound Import",
306 "IAT",
307 "Delay Import",
308 "COM Descriptor",
309 "unknown",
310 "unknown"
311 };
312
313 pOut->printf("%2d %-16s Size: 0x%08x RVA: 0x%08x\n",
314 i,
315 apszDirectoryNames[i],
316 pOptHdr->DataDirectory[i].Size,
317 pOptHdr->DataDirectory[i].VirtualAddress);
318 }
319 pOut->printf("\n");
320
321
322 /*
323 * Dump Import Directory if present.
324 */
325 if (pImportDir)
326 {
327 pOut->printf("Import Directory\n"
328 "----------------\n");
329
330 PIMAGE_IMPORT_DESCRIPTOR pCur = pImportDir;
331 while (pCur->u.Characteristics != 0)
332 {
333 pOut->printf("%s\n", (char*)pvBase + pCur->Name);
334 pCur++;
335 }
336 }
337
338
339 /*
340 * Dump TLS directory if present
341 */
342 if (pTLSDir)
343 {
344 pOut->printf("TLS Directory\n"
345 "-------------\n");
346 if (pOptHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size % sizeof(IMAGE_TLS_DIRECTORY))
347 pOut->printf(" Warning! The size directory isn't a multiple of the directory struct!");
348
349 c = (int)(pOptHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size / sizeof(IMAGE_TLS_DIRECTORY));
350 for (i = 0; i < c; i++)
351 {
352
353 pOut->printf("%2d StartAddressOfRawData %p\n"
354 " EndAddressOfRawData %p\n"
355 " AddressOfIndex %p\n"
356 " AddressOfCallBacks %p\n"
357 " SizeOfZeroFill %p\n"
358 " Characteristics %p\n",
359 i,
360 pTLSDir[i].StartAddressOfRawData,
361 pTLSDir[i].EndAddressOfRawData,
362 pTLSDir[i].AddressOfIndex,
363 pTLSDir[i].AddressOfCallBacks,
364 pTLSDir[i].SizeOfZeroFill,
365 pTLSDir[i].Characteristics);
366
367 /* Print Callbacks */
368 if (pTLSDir[i].AddressOfCallBacks)
369 {
370 PULONG paulIndex;
371 PULONG paulCallback;
372 ULONG ulBorlandRVAFix = 0UL;
373
374 /* Check if the addresses in the TLSDir is RVAs or real addresses */
375 if (pTLSDir[i].StartAddressOfRawData > pOptHdr->ImageBase)
376 ulBorlandRVAFix = pOptHdr->ImageBase;
377
378 j = 0;
379 paulIndex = (PULONG)((ULONG)pTLSDir[i].AddressOfIndex - ulBorlandRVAFix + (ULONG)this->pvBase);
380 paulCallback = (PULONG)((ULONG)pTLSDir[i].AddressOfCallBacks - ulBorlandRVAFix + (ULONG)this->pvBase);
381 if (*paulCallback)
382 {
383 pOut->printf(" Callbacks:\n");
384 for (j = 0; paulCallback[j] != 0; j++)
385 {
386 pOut->printf(" %02d Address: 0x%08x Index: 0x%08x\n",
387 paulIndex[j],
388 paulCallback[j]);
389 }
390 }
391 else
392 pOut->printf(" (Empty callback array!)\n");
393 }
394
395 }
396
397 pOut->printf("\n");
398 }
399
400
401 return TRUE;
402}
403
Note: See TracBrowser for help on using the repository browser.