PageRenderTime 111ms CodeModel.GetById 9ms app.highlight 94ms RepoModel.GetById 1ms app.codeStats 0ms

/xbmc/cores/DllLoader/coff.cpp

http://github.com/xbmc/xbmc
C++ | 997 lines | 721 code | 136 blank | 140 comment | 239 complexity | dc2c624a8c9f91df934abb6d9a233b4f MD5 | raw file
  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
 23const 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
 44CoffLoader::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
 64CoffLoader::~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
 95int 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
164int 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
272int 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
302int 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
343int 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
408int 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
438void* 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
452unsigned 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
464char *CoffLoader::GetStringTblIndex(int index)
465{
466  char *table = StringTable;
467
468  while (index--)
469    table += strlen(table) + 1;
470  return table;
471}
472
473char *CoffLoader::GetStringTblOff(int Offset)
474{
475  return StringTable + Offset - 4;
476}
477
478char *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
497char *CoffLoader::GetSymbolName(int index)
498{
499  SymbolTable_t *sym = &(SymTable[index]);
500  return GetSymbolName(sym);
501}
502
503void 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
520void 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
620void 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
681void 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
698void 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
723void 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
924int 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
945void 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}