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