1 /*
2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
4 *
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
8
9 #include <stdlib.h>
10 #include <string.h>
11 #include "coff.h"
12 #include "coffldr.h"
13
14 //#define DUMPING_DATA 1
15
16 #ifndef __GNUC__
17 #pragma warning (disable:4806)
18 #endif
19
20 #include "utils/log.h"
21 #define printf(format, ...) CLog::Log(LOGDEBUG, format , ##__VA_ARGS__)
22
23 const char *DATA_DIR_NAME[16] =
24 {
25 "Export Table",
26 "Import Table",
27 "Resource Table",
28 "Exception Table",
29 "Certificate Table",
30 "Base Relocation Table",
31 "Debug",
32 "Architecture",
33 "Global Ptr",
34 "TLS Table",
35 "Load Config Table",
36 "Bound Import",
37 "IAT",
38 "Delay Import Descriptor",
39 "COM+ Runtime Header",
40 "Reserved"
41 };
42
43
CoffLoader()44 CoffLoader::CoffLoader()
45 {
46 CoffFileHeader = 0;
47 OptionHeader = 0;
48 WindowsHeader = 0;
49 Directory = 0;
50 SectionHeader = 0;
51 SymTable = 0;
52 StringTable = 0;
53 SectionData = 0;
54
55 NumberOfSymbols = 0;
56 SizeOfStringTable = 0;
57 NumOfDirectories = 0;
58 NumOfSections = 0;
59 FileHeaderOffset = 0;
60 EntryAddress = 0;
61 hModule = NULL;
62 }
63
~CoffLoader()64 CoffLoader::~CoffLoader()
65 {
66 if ( hModule )
67 {
68 #ifdef TARGET_POSIX
69 free(hModule);
70 #else
71 VirtualFree(hModule, 0, MEM_RELEASE);
72 #endif
73 hModule = NULL;
74 }
75 if ( SymTable )
76 {
77 delete [] SymTable;
78 SymTable = 0;
79 }
80 if ( StringTable )
81 {
82 delete [] StringTable;
83 StringTable = 0;
84 }
85 if ( SectionData )
86 {
87 delete [] SectionData;
88 SectionData = 0;
89 }
90 }
91
92 // Has nothing to do with the coff loader itself
93 // it can be used to parse the headers of a dll
94 // already loaded into memory
ParseHeaders(void * hModule)95 int CoffLoader::ParseHeaders(void* hModule)
96 {
97 if (strncmp((char*)hModule, "MZ", 2) != 0)
98 return 0;
99
100 int* Offset = (int*)((char*)hModule+0x3c);
101 if (*Offset <= 0)
102 return 0;
103
104 if (strncmp((char*)hModule+*Offset, "PE\0\0", 4) != 0)
105 return 0;
106
107 FileHeaderOffset = *Offset + 4;
108
109 CoffFileHeader = (COFF_FileHeader_t *) ( (char*)hModule + FileHeaderOffset );
110 NumOfSections = CoffFileHeader->NumberOfSections;
111
112 OptionHeader = (OptionHeader_t *) ( (char*)CoffFileHeader + sizeof(COFF_FileHeader_t) );
113 WindowsHeader = (WindowsHeader_t *) ( (char*)OptionHeader + OPTHDR_SIZE );
114 EntryAddress = OptionHeader->Entry;
115 NumOfDirectories = WindowsHeader->NumDirectories;
116
117 Directory = (Image_Data_Directory_t *) ( (char*)WindowsHeader + WINHDR_SIZE);
118 SectionHeader = (SectionHeader_t *) ( (char*)Directory + sizeof(Image_Data_Directory_t) * NumOfDirectories);
119
120 if (CoffFileHeader->MachineType != IMAGE_FILE_MACHINE_I386)
121 return 0;
122
123 #ifdef DUMPING_DATA
124 PrintFileHeader(CoffFileHeader);
125 #endif
126
127 if ( CoffFileHeader->SizeOfOptionHeader == 0 ) //not an image file, object file maybe
128 return 0;
129
130 // process Option Header
131 if (OptionHeader->Magic == OPTMAGIC_PE32P)
132 {
133 printf("PE32+ not supported\n");
134 return 0;
135 }
136 else if (OptionHeader->Magic == OPTMAGIC_PE32)
137 {
138
139 #ifdef DUMPING_DATA
140 PrintOptionHeader(OptionHeader);
141 PrintWindowsHeader(WindowsHeader);
142 #endif
143
144 }
145 else
146 {
147 //add error message
148 return 0;
149 }
150
151 #ifdef DUMPING_DATA
152 for (int DirCount = 0; DirCount < NumOfDirectories; DirCount++)
153 {
154 printf("Data Directory %02d: %s\n", DirCount + 1, DATA_DIR_NAME[DirCount]);
155 printf(" RVA: %08X\n", Directory[DirCount].RVA);
156 printf(" Size: %08X\n\n", Directory[DirCount].Size);
157 }
158 #endif
159
160 return 1;
161
162 }
163
LoadCoffHModule(FILE * fp)164 int CoffLoader::LoadCoffHModule(FILE *fp)
165 {
166 //test file signatures
167 char Sig[4];
168 rewind(fp);
169 memset(Sig, 0, sizeof(Sig));
170 if (!fread(Sig, 1, 2, fp) || strncmp(Sig, "MZ", 2) != 0)
171 return 0;
172
173 if (fseek(fp, 0x3c, SEEK_SET) != 0)
174 return 0;
175
176 int Offset = 0;
177 if (!fread(&Offset, sizeof(int), 1, fp) || (Offset <= 0))
178 return 0;
179
180 if (fseek(fp, Offset, SEEK_SET) != 0)
181 return 0;
182
183 memset(Sig, 0, sizeof(Sig));
184 if (!fread(Sig, 1, 4, fp) || strncmp(Sig, "PE\0\0", 4) != 0)
185 return 0;
186
187 Offset += 4;
188 FileHeaderOffset = Offset;
189
190 // Load and process Header
191 if (fseek(fp, FileHeaderOffset + sizeof(COFF_FileHeader_t) + OPTHDR_SIZE, SEEK_SET)) //skip to winows headers
192 return 0;
193
194 WindowsHeader_t tempWindowsHeader;
195 size_t readcount = fread(&tempWindowsHeader, 1, WINHDR_SIZE, fp);
196 if (readcount != WINHDR_SIZE) //test file size error
197 return 0;
198
199 // alloc aligned memory
200 #ifdef TARGET_POSIX
201 hModule = malloc(tempWindowsHeader.SizeOfImage);
202 #elif defined TARGET_WINDOWS_STORE
203 hModule = VirtualAllocFromApp(GetCurrentProcess(), tempWindowsHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
204 #else
205 hModule = VirtualAllocEx(GetCurrentProcess(), (PVOID)tempWindowsHeader.ImageBase, tempWindowsHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
206 if (hModule == NULL)
207 hModule = VirtualAlloc(GetCurrentProcess(), tempWindowsHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
208 #endif
209 if (hModule == NULL)
210 return 0; //memory allocation fails
211
212 rewind(fp);
213 readcount = fread(hModule, 1, tempWindowsHeader.SizeOfHeaders, fp);
214 if (readcount != tempWindowsHeader.SizeOfHeaders) //file size error
215 return 0;
216
217 CoffFileHeader = (COFF_FileHeader_t *) ( (char*)hModule + FileHeaderOffset );
218 NumOfSections = CoffFileHeader->NumberOfSections;
219
220 OptionHeader = (OptionHeader_t *) ( (char*)CoffFileHeader + sizeof(COFF_FileHeader_t) );
221 WindowsHeader = (WindowsHeader_t *) ( (char*)OptionHeader + OPTHDR_SIZE );
222 EntryAddress = OptionHeader->Entry;
223 NumOfDirectories = WindowsHeader->NumDirectories;
224
225 Directory = (Image_Data_Directory_t *) ( (char*)WindowsHeader + WINHDR_SIZE);
226 SectionHeader = (SectionHeader_t *) ( (char*)Directory + sizeof(Image_Data_Directory_t) * NumOfDirectories);
227
228 if (CoffFileHeader->MachineType != IMAGE_FILE_MACHINE_I386)
229 return 0;
230
231 #ifdef DUMPING_DATA
232 PrintFileHeader(CoffFileHeader);
233 #endif
234
235 if ( CoffFileHeader->SizeOfOptionHeader == 0 ) //not an image file, object file maybe
236 return 0;
237
238 // process Option Header
239 if (OptionHeader->Magic == OPTMAGIC_PE32P)
240 {
241 printf("PE32+ not supported\n");
242 return 0;
243 }
244 else if (OptionHeader->Magic == OPTMAGIC_PE32)
245 {
246
247 #ifdef DUMPING_DATA
248 PrintOptionHeader(OptionHeader);
249 PrintWindowsHeader(WindowsHeader);
250 #endif
251
252 }
253 else
254 {
255 //add error message
256 return 0;
257 }
258
259 #ifdef DUMPING_DATA
260 for (int DirCount = 0; DirCount < NumOfDirectories; DirCount++)
261 {
262 printf("Data Directory %02d: %s\n", DirCount + 1, DATA_DIR_NAME[DirCount]);
263 printf(" RVA: %08X\n", Directory[DirCount].RVA);
264 printf(" Size: %08X\n\n", Directory[DirCount].Size);
265 }
266 #endif
267
268 return 1;
269
270 }
271
LoadSymTable(FILE * fp)272 int CoffLoader::LoadSymTable(FILE *fp)
273 {
274 int Offset = ftell(fp);
275 if (Offset < 0)
276 return 0;
277
278 if ( CoffFileHeader->PointerToSymbolTable == 0 )
279 return 1;
280
281 if (fseek(fp, CoffFileHeader->PointerToSymbolTable /* + CoffBeginOffset*/, SEEK_SET) != 0)
282 return 0;
283
284 SymbolTable_t *tmp = new SymbolTable_t[CoffFileHeader->NumberOfSymbols];
285 if (!tmp)
286 {
287 printf("Could not allocate memory for symbol table!\n");
288 return 0;
289 }
290 if (!fread((void *)tmp, CoffFileHeader->NumberOfSymbols, sizeof(SymbolTable_t), fp))
291 {
292 delete[] tmp;
293 return 0;
294 }
295 NumberOfSymbols = CoffFileHeader->NumberOfSymbols;
296 SymTable = tmp;
297 if (fseek(fp, Offset, SEEK_SET) != 0)
298 return 0;
299 return 1;
300 }
301
LoadStringTable(FILE * fp)302 int CoffLoader::LoadStringTable(FILE *fp)
303 {
304 int StringTableSize;
305 char *tmp = NULL;
306
307 int Offset = ftell(fp);
308 if (Offset < 0)
309 return 0;
310
311 if ( CoffFileHeader->PointerToSymbolTable == 0 )
312 return 1;
313
314 if (fseek(fp, CoffFileHeader->PointerToSymbolTable +
315 CoffFileHeader->NumberOfSymbols * sizeof(SymbolTable_t),
316 SEEK_SET) != 0)
317 return 0;
318
319 if (!fread(&StringTableSize, 1, sizeof(int), fp))
320 return 0;
321 StringTableSize -= 4;
322 if (StringTableSize != 0)
323 {
324 tmp = new char[StringTableSize];
325 if (tmp == NULL)
326 {
327 printf("Could not allocate memory for string table\n");
328 return 0;
329 }
330 if (!fread((void *)tmp, StringTableSize, sizeof(char), fp))
331 {
332 delete[] tmp;
333 return 0;
334 }
335 }
336 SizeOfStringTable = StringTableSize;
337 StringTable = tmp;
338 if (fseek(fp, Offset, SEEK_SET) != 0)
339 return 0;
340 return 1;
341 }
342
LoadSections(FILE * fp)343 int CoffLoader::LoadSections(FILE *fp)
344 {
345 NumOfSections = CoffFileHeader->NumberOfSections;
346
347 SectionData = new char * [NumOfSections];
348 if ( !SectionData )
349 return 0;
350
351 // Bobbin007: for debug dlls this check always fails
352
353 //////check VMA size!!!!!
354 //unsigned long vma_size = 0;
355 //for (int SctnCnt = 0; SctnCnt < NumOfSections; SctnCnt++)
356 //{
357 // SectionHeader_t *ScnHdr = (SectionHeader_t *)(SectionHeader + SctnCnt);
358 // vma_size = max(vma_size, ScnHdr->VirtualAddress + ScnHdr->SizeOfRawData);
359 // vma_size = max(vma_size, ScnHdr->VirtualAddress + ScnHdr->VirtualSize);
360 //}
361
362 //if (WindowsHeader->SizeOfImage < vma_size)
363 // return 0; //something wrong with file
364
365 for (int SctnCnt = 0; SctnCnt < NumOfSections; SctnCnt++)
366 {
367 SectionHeader_t *ScnHdr = SectionHeader + SctnCnt;
368 SectionData[SctnCnt] = ((char*)hModule + ScnHdr->VirtualAddress);
369
370 if (fseek(fp, ScnHdr->PtrToRawData, SEEK_SET) != 0)
371 return 0;
372
373 if (!fread(SectionData[SctnCnt], 1, ScnHdr->SizeOfRawData, fp))
374 return 0;
375
376 #ifdef DUMPING_DATA
377 //debug blocks
378 char szBuf[128];
379 char namebuf[9];
380 for (int i = 0; i < 8; i++)
381 namebuf[i] = ScnHdr->Name[i];
382 namebuf[8] = '\0';
383 sprintf(szBuf, "Load code Sections %s Memory %p,Length %x\n", namebuf,
384 SectionData[SctnCnt], max(ScnHdr->VirtualSize, ScnHdr->SizeOfRawData));
385 OutputDebugString(szBuf);
386 #endif
387
388 if ( ScnHdr->SizeOfRawData < ScnHdr->VirtualSize ) //initialize BSS data in the end of section
389 {
390 memset((char*)((long)(SectionData[SctnCnt]) + ScnHdr->SizeOfRawData), 0, ScnHdr->VirtualSize - ScnHdr->SizeOfRawData);
391 }
392
393 if (ScnHdr->Characteristics & IMAGE_SCN_CNT_BSS) //initialize whole .BSS section, pure .BSS is obsolete
394 {
395 memset(SectionData[SctnCnt], 0, ScnHdr->VirtualSize);
396 }
397
398 #ifdef DUMPING_DATA
399 PrintSection(SectionHeader + SctnCnt, SectionData[SctnCnt]);
400 #endif
401
402 }
403 return 1;
404 }
405
406 //FIXME: Add the Free Resources functions
407
RVA2Section(unsigned long RVA)408 int CoffLoader::RVA2Section(unsigned long RVA)
409 {
410 NumOfSections = CoffFileHeader->NumberOfSections;
411 for ( int i = 0; i < NumOfSections; i++)
412 {
413 if ( SectionHeader[i].VirtualAddress <= RVA )
414 {
415 if ( i + 1 != NumOfSections )
416 {
417 if ( RVA < SectionHeader[i + 1].VirtualAddress )
418 {
419 if ( SectionHeader[i].VirtualAddress + SectionHeader[i].VirtualSize <= RVA )
420 printf("Warning! Address outside of Section: %lx!\n", RVA);
421 // else
422 return i;
423 }
424 }
425 else
426 {
427 if ( SectionHeader[i].VirtualAddress + SectionHeader[i].VirtualSize <= RVA )
428 printf("Warning! Address outside of Section: %lx!\n", RVA);
429 // else
430 return i;
431 }
432 }
433 }
434 printf("RVA2Section lookup failure!\n");
435 return 0;
436 }
437
RVA2Data(unsigned long RVA)438 void* CoffLoader::RVA2Data(unsigned long RVA)
439 {
440 int Sctn = RVA2Section(RVA);
441
442 if( RVA < SectionHeader[Sctn].VirtualAddress
443 || RVA >= SectionHeader[Sctn].VirtualAddress + SectionHeader[Sctn].VirtualSize)
444 {
445 // RVA2Section is lying, let's use base address of dll instead, only works if
446 // DLL has been loaded fully into memory, wich we normally do
447 return (void*)(RVA + (unsigned long)hModule);
448 }
449 return SectionData[Sctn] + RVA - SectionHeader[Sctn].VirtualAddress;
450 }
451
Data2RVA(void * address)452 unsigned long CoffLoader::Data2RVA(void* address)
453 {
454 for ( int i = 0; i < CoffFileHeader->NumberOfSections; i++)
455 {
456 if(address >= SectionData[i] && address < SectionData[i] + SectionHeader[i].VirtualSize)
457 return (unsigned long)address - (unsigned long)SectionData[i] + SectionHeader[i].VirtualAddress;
458 }
459
460 // Section wasn't found, so use relative to main load of dll
461 return (unsigned long)address - (unsigned long)hModule;
462 }
463
GetStringTblIndex(int index)464 char *CoffLoader::GetStringTblIndex(int index)
465 {
466 char *table = StringTable;
467
468 while (index--)
469 table += strlen(table) + 1;
470 return table;
471 }
472
GetStringTblOff(int Offset)473 char *CoffLoader::GetStringTblOff(int Offset)
474 {
475 return StringTable + Offset - 4;
476 }
477
GetSymbolName(SymbolTable_t * sym)478 char *CoffLoader::GetSymbolName(SymbolTable_t *sym)
479 {
480 long long index = sym->Name.Offset;
481 int low = (int)(index & 0xFFFFFFFF);
482 int high = (int)((index >> 32) & 0xFFFFFFFF);
483
484 if (low == 0)
485 {
486 return GetStringTblOff(high);
487 }
488 else
489 {
490 static char shortname[9];
491 memset(shortname, 0, 9);
492 strncpy(shortname, (char *)sym->Name.ShortName, 8);
493 return shortname;
494 }
495 }
496
GetSymbolName(int index)497 char *CoffLoader::GetSymbolName(int index)
498 {
499 SymbolTable_t *sym = &(SymTable[index]);
500 return GetSymbolName(sym);
501 }
502
PrintStringTable(void)503 void CoffLoader::PrintStringTable(void)
504 {
505 int size = SizeOfStringTable;
506 int index = 0;
507 char *table = StringTable;
508
509 printf("\nSTRING TABLE\n");
510 while (size)
511 {
512 printf("%2d: %s\n", index++, table);
513 size -= strlen(table) + 1;
514 table += strlen(table) + 1;
515 }
516 printf("\n");
517 }
518
519
PrintSymbolTable(void)520 void CoffLoader::PrintSymbolTable(void)
521 {
522 int SymIndex;
523
524 printf("COFF SYMBOL TABLE\n");
525 for (SymIndex = 0; SymIndex < NumberOfSymbols; SymIndex++)
526 {
527 printf("%03X ", SymIndex);
528 printf("%08lX ", SymTable[SymIndex].Value);
529
530 if (SymTable[SymIndex].SectionNumber == IMAGE_SYM_ABSOLUTE)
531 printf("ABS ");
532 else if (SymTable[SymIndex].SectionNumber == IMAGE_SYM_DEBUG)
533 printf("DEBUG ");
534 else if (SymTable[SymIndex].SectionNumber == IMAGE_SYM_UNDEFINED)
535 printf("UNDEF ");
536 else
537 {
538 printf("SECT%d ", SymTable[SymIndex].SectionNumber);
539 if (SymTable[SymIndex].SectionNumber < 10)
540 printf(" ");
541 if (SymTable[SymIndex].SectionNumber < 100)
542 printf(" ");
543 }
544
545 if (SymTable[SymIndex].Type == 0)
546 printf("notype ");
547 else
548 {
549 printf("%X ", SymTable[SymIndex].Type);
550 if (SymTable[SymIndex].Type < 0x10)
551 printf(" ");
552 if (SymTable[SymIndex].Type < 0x100)
553 printf(" ");
554 if (SymTable[SymIndex].Type < 0x1000)
555 printf(" ");
556 }
557
558 if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_END_OF_FUNCTION)
559 printf("End of Function ");
560 if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_NULL)
561 printf("Null ");
562 if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_AUTOMATIC)
563 printf("Automatic ");
564 if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_EXTERNAL)
565 printf("External ");
566 if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_STATIC)
567 printf("Static ");
568 if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_REGISTER)
569 printf("Register ");
570 if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_EXTERNAL_DEF)
571 printf("External Def ");
572 if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_LABEL)
573 printf("Label ");
574 if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_UNDEFINED_LABEL)
575 printf("Undefined Label ");
576 if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_MEMBER_OF_STRUCT)
577 printf("Member Of Struct ");
578 if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_ARGUMENT)
579 printf("Argument ");
580 if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_STRUCT_TAG)
581 printf("Struct Tag ");
582 if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_MEMBER_OF_UNION)
583 printf("Member Of Union ");
584 if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_UNION_TAG)
585 printf("Union Tag ");
586 if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_TYPE_DEFINITION)
587 printf("Type Definition ");
588 if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_UNDEFINED_STATIC)
589 printf("Undefined Static ");
590 if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_ENUM_TAG)
591 printf("Enum Tag ");
592 if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_MEMBER_OF_ENUM)
593 printf("Member Of Enum ");
594 if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_REGISTER_PARAM)
595 printf("Register Param ");
596 if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_BIT_FIELD)
597 printf("Bit Field ");
598 if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_BLOCK)
599 printf("Block ");
600 if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_FUNCTION)
601 printf("Function ");
602 if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_END_OF_STRUCT)
603 printf("End Of Struct ");
604 if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_FILE)
605 printf("File ");
606 if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_SECTION)
607 printf("Section ");
608 if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_WEAK_EXTERNAL)
609 printf("Weak External ");
610
611 printf("| %s", GetSymbolName(SymIndex));
612
613 SymIndex += SymTable[SymIndex].NumberOfAuxSymbols;
614 printf("\n");
615 }
616 printf("\n");
617
618 }
619
PrintFileHeader(COFF_FileHeader_t * FileHeader)620 void CoffLoader::PrintFileHeader(COFF_FileHeader_t *FileHeader)
621 {
622 printf("COFF Header\n");
623 printf("------------------------------------------\n\n");
624
625 printf("MachineType: 0x%04X\n", FileHeader->MachineType);
626 printf("NumberOfSections: 0x%04X\n", FileHeader->NumberOfSections);
627 printf("TimeDateStamp: 0x%08lX\n",FileHeader->TimeDateStamp);
628 printf("PointerToSymbolTable: 0x%08lX\n",FileHeader->PointerToSymbolTable);
629 printf("NumberOfSymbols: 0x%08lX\n",FileHeader->NumberOfSymbols);
630 printf("SizeOfOptionHeader: 0x%04X\n", FileHeader->SizeOfOptionHeader);
631 printf("Characteristics: 0x%04X\n", FileHeader->Characteristics);
632
633 if (FileHeader->Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
634 printf(" IMAGE_FILE_RELOCS_STRIPPED\n");
635
636 if (FileHeader->Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE)
637 printf(" IMAGE_FILE_EXECUTABLE_IMAGE\n");
638
639 if (FileHeader->Characteristics & IMAGE_FILE_LINE_NUMS_STRIPPED)
640 printf(" IMAGE_FILE_LINE_NUMS_STRIPPED\n");
641
642 if (FileHeader->Characteristics & IMAGE_FILE_LOCAL_SYMS_STRIPPED)
643 printf(" IMAGE_FILE_LOCAL_SYMS_STRIPPED\n");
644
645 if (FileHeader->Characteristics & IMAGE_FILE_AGGRESSIVE_WS_TRIM)
646 printf(" IMAGE_FILE_AGGRESSIVE_WS_TRIM\n");
647
648 if (FileHeader->Characteristics & IMAGE_FILE_LARGE_ADDRESS_AWARE)
649 printf(" IMAGE_FILE_LARGE_ADDRESS_AWARE\n");
650
651 if (FileHeader->Characteristics & IMAGE_FILE_16BIT_MACHINE)
652 printf(" IMAGE_FILE_16BIT_MACHINE\n");
653
654 if (FileHeader->Characteristics & IMAGE_FILE_BYTES_REVERSED_LO)
655 printf(" IMAGE_FILE_BYTES_REVERSED_LO\n");
656
657 if (FileHeader->Characteristics & IMAGE_FILE_32BIT_MACHINE)
658 printf(" IMAGE_FILE_32BIT_MACHINE\n");
659
660 if (FileHeader->Characteristics & IMAGE_FILE_DEBUG_STRIPPED)
661 printf(" IMAGE_FILE_DEBUG_STRIPPED\n");
662
663 if (FileHeader->Characteristics & IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP)
664 printf(" IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP\n");
665
666 if (FileHeader->Characteristics & IMAGE_FILE_SYSTEM)
667 printf(" IMAGE_FILE_SYSTEM\n");
668
669 if (FileHeader->Characteristics & IMAGE_FILE_DLL)
670 printf(" IMAGE_FILE_DLL\n");
671
672 if (FileHeader->Characteristics & IMAGE_FILE_UP_SYSTEM_ONLY)
673 printf(" IMAGE_FILE_UP_SYSTEM_ONLY\n");
674
675 if (FileHeader->Characteristics & IMAGE_FILE_BYTES_REVERSED_HI)
676 printf(" IMAGE_FILE_BYTES_REVERSED_HI\n");
677
678 printf("\n");
679 }
680
PrintOptionHeader(OptionHeader_t * OptHdr)681 void CoffLoader::PrintOptionHeader(OptionHeader_t *OptHdr)
682 {
683 printf("Option Header\n");
684 printf("------------------------------------------\n\n");
685
686 printf("Magic: 0x%04X\n", OptHdr->Magic);
687 printf("Linker Major Ver: 0x%02X\n", VERSION_MAJOR(OptHdr->LinkVersion));
688 printf("Linker Minor Ver: 0x%02X\n", VERSION_MINOR(OptHdr->LinkVersion));
689 printf("Code Size: 0x%08lX\n", OptHdr->CodeSize);
690 printf("Data Size: 0x%08lX\n", OptHdr->DataSize);
691 printf("BSS Size: 0x%08lX\n", OptHdr->BssSize);
692 printf("Entry: 0x%08lX\n", OptHdr->Entry);
693 printf("Code Base: 0x%08lX\n", OptHdr->CodeBase);
694 printf("Data Base: 0x%08lX\n", OptHdr->DataBase);
695 printf("\n");
696 }
697
PrintWindowsHeader(WindowsHeader_t * WinHdr)698 void CoffLoader::PrintWindowsHeader(WindowsHeader_t *WinHdr)
699 {
700 printf("Windows Specific Option Header\n");
701 printf("------------------------------------------\n\n");
702
703 printf("Image Base: 0x%08lX\n", WinHdr->ImageBase);
704 printf("Section Alignment: 0x%08lX\n", WinHdr->SectionAlignment);
705 printf("File Alignment: 0x%08lX\n", WinHdr->FileAlignment);
706 printf("OS Version: %d.%08d\n", BIGVERSION_MAJOR(WinHdr->OSVer), BIGVERSION_MINOR(WinHdr->OSVer));
707 printf("Image Version: %d.%08d\n", BIGVERSION_MAJOR(WinHdr->ImgVer), BIGVERSION_MINOR(WinHdr->ImgVer));
708 printf("SubSystem Version: %d.%08d\n", BIGVERSION_MAJOR(WinHdr->SubSysVer), BIGVERSION_MINOR(WinHdr->SubSysVer));
709 printf("Size of Image: 0x%08lX\n", WinHdr->SizeOfImage);
710 printf("Size of Headers: 0x%08lX\n", WinHdr->SizeOfHeaders);
711 printf("Checksum: 0x%08lX\n", WinHdr->CheckSum);
712 printf("Subsystem: 0x%04X\n", WinHdr->Subsystem);
713 printf("DLL Flags: 0x%04X\n", WinHdr->DLLFlags);
714 printf("Sizeof Stack Resv: 0x%08lX\n", WinHdr->SizeOfStackReserve);
715 printf("Sizeof Stack Comm: 0x%08lX\n", WinHdr->SizeOfStackCommit);
716 printf("Sizeof Heap Resv: 0x%08lX\n", WinHdr->SizeOfHeapReserve);
717 printf("Sizeof Heap Comm: 0x%08lX\n", WinHdr->SizeOfHeapCommit);
718 printf("Loader Flags: 0x%08lX\n", WinHdr->LoaderFlags);
719 printf("Num Directories: %ld\n", WinHdr->NumDirectories);
720 printf("\n");
721 }
722
PrintSection(SectionHeader_t * ScnHdr,char * data)723 void CoffLoader::PrintSection(SectionHeader_t *ScnHdr, char* data)
724 {
725 char SectionName[9];
726
727 strncpy(SectionName, (char *)ScnHdr->Name, 8);
728 SectionName[8] = 0;
729 printf("Section: %s\n", SectionName);
730 printf("------------------------------------------\n\n");
731
732 printf("Virtual Size: 0x%08lX\n", ScnHdr->VirtualSize);
733 printf("Virtual Address: 0x%08lX\n", ScnHdr->VirtualAddress);
734 printf("Sizeof Raw Data: 0x%08lX\n", ScnHdr->SizeOfRawData);
735 printf("Ptr To Raw Data: 0x%08lX\n", ScnHdr->PtrToRawData);
736 printf("Ptr To Relocations: 0x%08lX\n", ScnHdr->PtrToRelocations);
737 printf("Ptr To Line Nums: 0x%08lX\n", ScnHdr->PtrToLineNums);
738 printf("Num Relocations: 0x%04X\n", ScnHdr->NumRelocations);
739 printf("Num Line Numbers: 0x%04X\n", ScnHdr->NumLineNumbers);
740 printf("Characteristics: 0x%08lX\n", ScnHdr->Characteristics);
741 if (ScnHdr->Characteristics & IMAGE_SCN_CNT_CODE)
742 printf(" IMAGE_SCN_CNT_CODE\n");
743 if (ScnHdr->Characteristics & IMAGE_SCN_CNT_DATA)
744 printf(" IMAGE_SCN_CNT_DATA\n");
745 if (ScnHdr->Characteristics & IMAGE_SCN_CNT_BSS)
746 printf(" IMAGE_SCN_CNT_BSS\n");
747 if (ScnHdr->Characteristics & IMAGE_SCN_LNK_INFO)
748 printf(" IMAGE_SCN_LNK_INFO\n");
749 if (ScnHdr->Characteristics & IMAGE_SCN_LNK_REMOVE)
750 printf(" IMAGE_SCN_LNK_REMOVE\n");
751 if (ScnHdr->Characteristics & IMAGE_SCN_LNK_COMDAT)
752 printf(" IMAGE_SCN_LNK_COMDAT\n");
753
754 if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_1BYTES)
755 printf(" IMAGE_SCN_ALIGN_1BYTES\n");
756 if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_2BYTES)
757 printf(" IMAGE_SCN_ALIGN_2BYTES\n");
758 if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_4BYTES)
759 printf(" IMAGE_SCN_ALIGN_4BYTES\n");
760 if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_8BYTES)
761 printf(" IMAGE_SCN_ALIGN_8BYTES\n");
762 if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_16BYTES)
763 printf(" IMAGE_SCN_ALIGN_16BYTES\n");
764 if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_32BYTES)
765 printf(" IMAGE_SCN_ALIGN_32BYTES\n");
766 if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_64BYTES)
767 printf(" IMAGE_SCN_ALIGN_64BYTES\n");
768 if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_128BYTES)
769 printf(" IMAGE_SCN_ALIGN_128BYTES\n");
770 if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_256BYTES)
771 printf(" IMAGE_SCN_ALIGN_256BYTES\n");
772 if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_512BYTES)
773 printf(" IMAGE_SCN_ALIGN_512BYTES\n");
774 if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_1024BYTES)
775 printf(" IMAGE_SCN_ALIGN_1024BYTES\n");
776 if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_2048BYTES)
777 printf(" IMAGE_SCN_ALIGN_2048BYTES\n");
778 if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_4096BYTES)
779 printf(" IMAGE_SCN_ALIGN_4096BYTES\n");
780 if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_8192BYTES)
781 printf(" IMAGE_SCN_ALIGN_8192BYTES\n");
782
783 if (ScnHdr->Characteristics & IMAGE_SCN_LNK_NRELOC_OVFL)
784 printf(" IMAGE_SCN_LNK_NRELOC_OVFL\n");
785 if (ScnHdr->Characteristics & IMAGE_SCN_MEM_DISCARDABLE)
786 printf(" IMAGE_SCN_MEM_DISCARDABLE\n");
787 if (ScnHdr->Characteristics & IMAGE_SCN_MEM_NOT_CACHED)
788 printf(" IMAGE_SCN_MEM_NOT_CACHED\n");
789 if (ScnHdr->Characteristics & IMAGE_SCN_MEM_NOT_PAGED)
790 printf(" IMAGE_SCN_MEM_NOT_PAGED\n");
791 if (ScnHdr->Characteristics & IMAGE_SCN_MEM_SHARED)
792 printf(" IMAGE_SCN_MEM_SHARED\n");
793 if (ScnHdr->Characteristics & IMAGE_SCN_MEM_EXECUTE)
794 printf(" IMAGE_SCN_MEM_EXECUTE\n");
795 if (ScnHdr->Characteristics & IMAGE_SCN_MEM_READ)
796 printf(" IMAGE_SCN_MEM_READ\n");
797 if (ScnHdr->Characteristics & IMAGE_SCN_MEM_WRITE)
798 printf(" IMAGE_SCN_MEM_WRITE\n");
799 printf("\n");
800
801 // Read the section Data, Relocations, & Line Nums
802 // Save the offset
803
804 if (ScnHdr->SizeOfRawData > 0)
805 {
806 unsigned int i;
807 // Print the Raw Data
808
809 printf("\nRAW DATA");
810 for (i = 0; i < ScnHdr->VirtualSize; i++)
811 {
812 if ((i % 16) == 0)
813 printf("\n %08X: ", i);
814 char ch = data[i];
815 printf("%02X ", (unsigned int)ch);
816 }
817 printf("\n\n");
818 }
819
820 /*
821 #if 0
822 if (ScnHdr->NumRelocations > 0)
823 {
824 // Print Section Relocations
825 ObjReloc_t ObjReloc;
826
827 fseek(fp, ScnHdr->PtrToRelocations/ * + CoffBeginOffset* /, SEEK_SET);
828 printf("RELOCATIONS\n");
829 printf(" Symbol Symbol\n");
830 printf(" Offset Type Index Name\n");
831 printf(" -------- -------- -------- ------\n");
832 for (int i = 0; i < ScnHdr->NumRelocations; i++)
833 {
834 fread(&ObjReloc, 1, sizeof(ObjReloc_t), fp);
835 printf(" %08X ", ObjReloc.VirtualAddress);
836
837 if (ObjReloc.Type == IMAGE_REL_I386_ABSOLUTE)
838 printf("ABSOLUTE ");
839 if (ObjReloc.Type == IMAGE_REL_I386_DIR16)
840 printf("DIR16 ");
841 if (ObjReloc.Type == IMAGE_REL_I386_REL16)
842 printf("REL16 ");
843 if (ObjReloc.Type == IMAGE_REL_I386_DIR32)
844 printf("DIR32 ");
845 if (ObjReloc.Type == IMAGE_REL_I386_DIR32NB)
846 printf("DIR32NB ");
847 if (ObjReloc.Type == IMAGE_REL_I386_SEG12)
848 printf("SEG12 ");
849 if (ObjReloc.Type == IMAGE_REL_I386_SECTION)
850 printf("SECTION ");
851 if (ObjReloc.Type == IMAGE_REL_I386_SECREL)
852 printf("SECREL ");
853 if (ObjReloc.Type == IMAGE_REL_I386_REL32)
854 printf("REL32 ");
855 printf("%8X ", ObjReloc.SymTableIndex);
856 printf("%s\n", GetSymbolName(ObjReloc.SymTableIndex));
857 }
858 printf("\n");
859 }
860
861 if (ScnHdr->NumLineNumbers > 0)
862 {
863 // Print The Line Number Info
864 LineNumbers_t LineNumber;
865 int LineCnt = 0;
866 int BaseLineNum = -1;
867
868 fseek(fp, ScnHdr->PtrToLineNums/ * + CoffBeginOffset* /, SEEK_SET);
869 printf("LINE NUMBERS");
870 for (int i = 0; i < ScnHdr->NumLineNumbers; i++)
871 {
872 int LNOffset = ftell(fp);
873
874 fread(&LineNumber, 1, sizeof(LineNumbers_t), fp);
875 if (LineNumber.LineNum == 0)
876 {
877 SymbolTable_t *Sym;
878 int SymIndex;
879
880 printf("\n");
881 SymIndex = LineNumber.Type.SymbolTableIndex;
882 Sym = &(SymTable[SymIndex]);
883 if (Sym->NumberOfAuxSymbols > 0)
884 {
885 Sym = &(SymTable[SymIndex+1]);
886 AuxFuncDef_t *FuncDef = (AuxFuncDef_t *)Sym;
887
888 if (FuncDef->PtrToLineNumber == LNOffset)
889 {
890 Sym = &(SymTable[FuncDef->TagIndex]);
891 if (Sym->NumberOfAuxSymbols > 0)
892 {
893 Sym = &(SymTable[FuncDef->TagIndex+1]);
894 AuxBfEf_t *Bf = (AuxBfEf_t *)Sym;
895 BaseLineNum = Bf->LineNumber;
896 }
897 }
898 }
899 printf(" Symbol Index: %8x ", SymIndex);
900 printf(" Base line number: %8d\n", BaseLineNum);
901 printf(" Symbol name = %s", GetSymbolName(SymIndex));
902 LineCnt = 0;
903 }
904 else
905 {
906 if ((LineCnt%4) == 0)
907 {
908 printf("\n ");
909 LineCnt = 0;
910 }
911 printf("%08X(%5d) ", LineNumber.Type.VirtualAddress,
912 LineNumber.LineNum + BaseLineNum);
913 LineCnt ++;
914 }
915 }
916 printf("\n");
917 }
918 #endif
919 */
920
921 printf("\n");
922 }
923
ParseCoff(FILE * fp)924 int CoffLoader::ParseCoff(FILE *fp)
925 {
926 if ( !LoadCoffHModule(fp) )
927 {
928 printf("Failed to load/find COFF hModule header\n");
929 return 0;
930 }
931 if ( !LoadSymTable(fp) ||
932 !LoadStringTable(fp) ||
933 !LoadSections(fp) )
934 return 0;
935
936 PerformFixups();
937
938 #ifdef DUMPING_DATA
939 PrintSymbolTable();
940 PrintStringTable();
941 #endif
942 return 1;
943 }
944
PerformFixups(void)945 void CoffLoader::PerformFixups(void)
946 {
947 int FixupDataSize;
948 char *FixupData;
949 char *EndData;
950
951 EntryAddress = (unsigned long)RVA2Data(EntryAddress);
952
953 if( reinterpret_cast<void*>(WindowsHeader->ImageBase) == hModule )
954 return;
955
956 if ( !Directory )
957 return ;
958
959 if ( NumOfDirectories <= BASE_RELOCATION_TABLE )
960 return ;
961
962 if ( !Directory[BASE_RELOCATION_TABLE].Size )
963 return ;
964
965 FixupDataSize = Directory[BASE_RELOCATION_TABLE].Size;
966 FixupData = (char*)RVA2Data(Directory[BASE_RELOCATION_TABLE].RVA);
967 EndData = FixupData + FixupDataSize;
968
969 while (FixupData < EndData)
970 {
971 // Starting a new Fixup Block
972 unsigned long PageRVA = *((unsigned long*)FixupData);
973 FixupData += 4;
974 unsigned long BlockSize = *((unsigned long*)FixupData);
975 FixupData += 4;
976
977 BlockSize -= 8;
978 for (unsigned int i = 0; i < BlockSize / 2; i++)
979 {
980 unsigned short Fixup = *((unsigned short*)FixupData);
981 FixupData += 2;
982 int Type = (Fixup >> 12) & 0x0f;
983 Fixup &= 0xfff;
984 if (Type == IMAGE_REL_BASED_HIGHLOW)
985 {
986 unsigned long *Off = (unsigned long*)RVA2Data(Fixup + PageRVA);
987 *Off = (unsigned long)RVA2Data(*Off - WindowsHeader->ImageBase);
988 }
989 else if (Type == IMAGE_REL_BASED_ABSOLUTE)
990 {}
991 else
992 {
993 printf("Unsupported fixup type!!\n");
994 }
995 }
996 }
997 }
998