summaryrefslogtreecommitdiffstats
path: root/xbmc/cores/DllLoader/coff.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'xbmc/cores/DllLoader/coff.cpp')
-rw-r--r--xbmc/cores/DllLoader/coff.cpp997
1 files changed, 997 insertions, 0 deletions
diff --git a/xbmc/cores/DllLoader/coff.cpp b/xbmc/cores/DllLoader/coff.cpp
new file mode 100644
index 0000000..6e330c9
--- /dev/null
+++ b/xbmc/cores/DllLoader/coff.cpp
@@ -0,0 +1,997 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "coff.h"
+#include "coffldr.h"
+
+//#define DUMPING_DATA 1
+
+#ifndef __GNUC__
+#pragma warning (disable:4806)
+#endif
+
+#include "utils/log.h"
+#define printf(format, ...) CLog::Log(LOGDEBUG, format , ##__VA_ARGS__)
+
+const char *DATA_DIR_NAME[16] =
+ {
+ "Export Table",
+ "Import Table",
+ "Resource Table",
+ "Exception Table",
+ "Certificate Table",
+ "Base Relocation Table",
+ "Debug",
+ "Architecture",
+ "Global Ptr",
+ "TLS Table",
+ "Load Config Table",
+ "Bound Import",
+ "IAT",
+ "Delay Import Descriptor",
+ "COM+ Runtime Header",
+ "Reserved"
+ };
+
+
+CoffLoader::CoffLoader()
+{
+ CoffFileHeader = 0;
+ OptionHeader = 0;
+ WindowsHeader = 0;
+ Directory = 0;
+ SectionHeader = 0;
+ SymTable = 0;
+ StringTable = 0;
+ SectionData = 0;
+
+ NumberOfSymbols = 0;
+ SizeOfStringTable = 0;
+ NumOfDirectories = 0;
+ NumOfSections = 0;
+ FileHeaderOffset = 0;
+ EntryAddress = 0;
+ hModule = NULL;
+}
+
+CoffLoader::~CoffLoader()
+{
+ if ( hModule )
+ {
+#ifdef TARGET_POSIX
+ free(hModule);
+#else
+ VirtualFree(hModule, 0, MEM_RELEASE);
+#endif
+ hModule = NULL;
+ }
+ if ( SymTable )
+ {
+ delete [] SymTable;
+ SymTable = 0;
+ }
+ if ( StringTable )
+ {
+ delete [] StringTable;
+ StringTable = 0;
+ }
+ if ( SectionData )
+ {
+ delete [] SectionData;
+ SectionData = 0;
+ }
+}
+
+// Has nothing to do with the coff loader itself
+// it can be used to parse the headers of a dll
+// already loaded into memory
+int CoffLoader::ParseHeaders(void* hModule)
+{
+ if (strncmp((char*)hModule, "MZ", 2) != 0)
+ return 0;
+
+ int* Offset = (int*)((char*)hModule+0x3c);
+ if (*Offset <= 0)
+ return 0;
+
+ if (strncmp((char*)hModule+*Offset, "PE\0\0", 4) != 0)
+ return 0;
+
+ FileHeaderOffset = *Offset + 4;
+
+ CoffFileHeader = (COFF_FileHeader_t *) ( (char*)hModule + FileHeaderOffset );
+ NumOfSections = CoffFileHeader->NumberOfSections;
+
+ OptionHeader = (OptionHeader_t *) ( (char*)CoffFileHeader + sizeof(COFF_FileHeader_t) );
+ WindowsHeader = (WindowsHeader_t *) ( (char*)OptionHeader + OPTHDR_SIZE );
+ EntryAddress = OptionHeader->Entry;
+ NumOfDirectories = WindowsHeader->NumDirectories;
+
+ Directory = (Image_Data_Directory_t *) ( (char*)WindowsHeader + WINHDR_SIZE);
+ SectionHeader = (SectionHeader_t *) ( (char*)Directory + sizeof(Image_Data_Directory_t) * NumOfDirectories);
+
+ if (CoffFileHeader->MachineType != IMAGE_FILE_MACHINE_I386)
+ return 0;
+
+#ifdef DUMPING_DATA
+ PrintFileHeader(CoffFileHeader);
+#endif
+
+ if ( CoffFileHeader->SizeOfOptionHeader == 0 ) //not an image file, object file maybe
+ return 0;
+
+ // process Option Header
+ if (OptionHeader->Magic == OPTMAGIC_PE32P)
+ {
+ printf("PE32+ not supported\n");
+ return 0;
+ }
+ else if (OptionHeader->Magic == OPTMAGIC_PE32)
+ {
+
+#ifdef DUMPING_DATA
+ PrintOptionHeader(OptionHeader);
+ PrintWindowsHeader(WindowsHeader);
+#endif
+
+ }
+ else
+ {
+ //add error message
+ return 0;
+ }
+
+#ifdef DUMPING_DATA
+ for (int DirCount = 0; DirCount < NumOfDirectories; DirCount++)
+ {
+ printf("Data Directory %02d: %s\n", DirCount + 1, DATA_DIR_NAME[DirCount]);
+ printf(" RVA: %08X\n", Directory[DirCount].RVA);
+ printf(" Size: %08X\n\n", Directory[DirCount].Size);
+ }
+#endif
+
+ return 1;
+
+}
+
+int CoffLoader::LoadCoffHModule(FILE *fp)
+{
+ //test file signatures
+ char Sig[4];
+ rewind(fp);
+ memset(Sig, 0, sizeof(Sig));
+ if (!fread(Sig, 1, 2, fp) || strncmp(Sig, "MZ", 2) != 0)
+ return 0;
+
+ if (fseek(fp, 0x3c, SEEK_SET) != 0)
+ return 0;
+
+ int Offset = 0;
+ if (!fread(&Offset, sizeof(int), 1, fp) || (Offset <= 0))
+ return 0;
+
+ if (fseek(fp, Offset, SEEK_SET) != 0)
+ return 0;
+
+ memset(Sig, 0, sizeof(Sig));
+ if (!fread(Sig, 1, 4, fp) || strncmp(Sig, "PE\0\0", 4) != 0)
+ return 0;
+
+ Offset += 4;
+ FileHeaderOffset = Offset;
+
+ // Load and process Header
+ if (fseek(fp, FileHeaderOffset + sizeof(COFF_FileHeader_t) + OPTHDR_SIZE, SEEK_SET)) //skip to winows headers
+ return 0;
+
+ WindowsHeader_t tempWindowsHeader;
+ size_t readcount = fread(&tempWindowsHeader, 1, WINHDR_SIZE, fp);
+ if (readcount != WINHDR_SIZE) //test file size error
+ return 0;
+
+ // alloc aligned memory
+#ifdef TARGET_POSIX
+ hModule = malloc(tempWindowsHeader.SizeOfImage);
+#elif defined TARGET_WINDOWS_STORE
+ hModule = VirtualAllocFromApp(GetCurrentProcess(), tempWindowsHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
+#else
+ hModule = VirtualAllocEx(GetCurrentProcess(), (PVOID)tempWindowsHeader.ImageBase, tempWindowsHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
+ if (hModule == NULL)
+ hModule = VirtualAlloc(GetCurrentProcess(), tempWindowsHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
+#endif
+ if (hModule == NULL)
+ return 0; //memory allocation fails
+
+ rewind(fp);
+ readcount = fread(hModule, 1, tempWindowsHeader.SizeOfHeaders, fp);
+ if (readcount != tempWindowsHeader.SizeOfHeaders) //file size error
+ return 0;
+
+ CoffFileHeader = (COFF_FileHeader_t *) ( (char*)hModule + FileHeaderOffset );
+ NumOfSections = CoffFileHeader->NumberOfSections;
+
+ OptionHeader = (OptionHeader_t *) ( (char*)CoffFileHeader + sizeof(COFF_FileHeader_t) );
+ WindowsHeader = (WindowsHeader_t *) ( (char*)OptionHeader + OPTHDR_SIZE );
+ EntryAddress = OptionHeader->Entry;
+ NumOfDirectories = WindowsHeader->NumDirectories;
+
+ Directory = (Image_Data_Directory_t *) ( (char*)WindowsHeader + WINHDR_SIZE);
+ SectionHeader = (SectionHeader_t *) ( (char*)Directory + sizeof(Image_Data_Directory_t) * NumOfDirectories);
+
+ if (CoffFileHeader->MachineType != IMAGE_FILE_MACHINE_I386)
+ return 0;
+
+#ifdef DUMPING_DATA
+ PrintFileHeader(CoffFileHeader);
+#endif
+
+ if ( CoffFileHeader->SizeOfOptionHeader == 0 ) //not an image file, object file maybe
+ return 0;
+
+ // process Option Header
+ if (OptionHeader->Magic == OPTMAGIC_PE32P)
+ {
+ printf("PE32+ not supported\n");
+ return 0;
+ }
+ else if (OptionHeader->Magic == OPTMAGIC_PE32)
+ {
+
+#ifdef DUMPING_DATA
+ PrintOptionHeader(OptionHeader);
+ PrintWindowsHeader(WindowsHeader);
+#endif
+
+ }
+ else
+ {
+ //add error message
+ return 0;
+ }
+
+#ifdef DUMPING_DATA
+ for (int DirCount = 0; DirCount < NumOfDirectories; DirCount++)
+ {
+ printf("Data Directory %02d: %s\n", DirCount + 1, DATA_DIR_NAME[DirCount]);
+ printf(" RVA: %08X\n", Directory[DirCount].RVA);
+ printf(" Size: %08X\n\n", Directory[DirCount].Size);
+ }
+#endif
+
+ return 1;
+
+}
+
+int CoffLoader::LoadSymTable(FILE *fp)
+{
+ int Offset = ftell(fp);
+ if (Offset < 0)
+ return 0;
+
+ if ( CoffFileHeader->PointerToSymbolTable == 0 )
+ return 1;
+
+ if (fseek(fp, CoffFileHeader->PointerToSymbolTable /* + CoffBeginOffset*/, SEEK_SET) != 0)
+ return 0;
+
+ SymbolTable_t *tmp = new SymbolTable_t[CoffFileHeader->NumberOfSymbols];
+ if (!tmp)
+ {
+ printf("Could not allocate memory for symbol table!\n");
+ return 0;
+ }
+ if (!fread((void *)tmp, CoffFileHeader->NumberOfSymbols, sizeof(SymbolTable_t), fp))
+ {
+ delete[] tmp;
+ return 0;
+ }
+ NumberOfSymbols = CoffFileHeader->NumberOfSymbols;
+ SymTable = tmp;
+ if (fseek(fp, Offset, SEEK_SET) != 0)
+ return 0;
+ return 1;
+}
+
+int CoffLoader::LoadStringTable(FILE *fp)
+{
+ int StringTableSize;
+ char *tmp = NULL;
+
+ int Offset = ftell(fp);
+ if (Offset < 0)
+ return 0;
+
+ if ( CoffFileHeader->PointerToSymbolTable == 0 )
+ return 1;
+
+ if (fseek(fp, CoffFileHeader->PointerToSymbolTable +
+ CoffFileHeader->NumberOfSymbols * sizeof(SymbolTable_t),
+ SEEK_SET) != 0)
+ return 0;
+
+ if (!fread(&StringTableSize, 1, sizeof(int), fp))
+ return 0;
+ StringTableSize -= 4;
+ if (StringTableSize != 0)
+ {
+ tmp = new char[StringTableSize];
+ if (tmp == NULL)
+ {
+ printf("Could not allocate memory for string table\n");
+ return 0;
+ }
+ if (!fread((void *)tmp, StringTableSize, sizeof(char), fp))
+ {
+ delete[] tmp;
+ return 0;
+ }
+ }
+ SizeOfStringTable = StringTableSize;
+ StringTable = tmp;
+ if (fseek(fp, Offset, SEEK_SET) != 0)
+ return 0;
+ return 1;
+}
+
+int CoffLoader::LoadSections(FILE *fp)
+{
+ NumOfSections = CoffFileHeader->NumberOfSections;
+
+ SectionData = new char * [NumOfSections];
+ if ( !SectionData )
+ return 0;
+
+ // Bobbin007: for debug dlls this check always fails
+
+ //////check VMA size!!!!!
+ //unsigned long vma_size = 0;
+ //for (int SctnCnt = 0; SctnCnt < NumOfSections; SctnCnt++)
+ //{
+ // SectionHeader_t *ScnHdr = (SectionHeader_t *)(SectionHeader + SctnCnt);
+ // vma_size = max(vma_size, ScnHdr->VirtualAddress + ScnHdr->SizeOfRawData);
+ // vma_size = max(vma_size, ScnHdr->VirtualAddress + ScnHdr->VirtualSize);
+ //}
+
+ //if (WindowsHeader->SizeOfImage < vma_size)
+ // return 0; //something wrong with file
+
+ for (int SctnCnt = 0; SctnCnt < NumOfSections; SctnCnt++)
+ {
+ SectionHeader_t *ScnHdr = SectionHeader + SctnCnt;
+ SectionData[SctnCnt] = ((char*)hModule + ScnHdr->VirtualAddress);
+
+ if (fseek(fp, ScnHdr->PtrToRawData, SEEK_SET) != 0)
+ return 0;
+
+ if (!fread(SectionData[SctnCnt], 1, ScnHdr->SizeOfRawData, fp))
+ return 0;
+
+#ifdef DUMPING_DATA
+ //debug blocks
+ char szBuf[128];
+ char namebuf[9];
+ for (int i = 0; i < 8; i++)
+ namebuf[i] = ScnHdr->Name[i];
+ namebuf[8] = '\0';
+ sprintf(szBuf, "Load code Sections %s Memory %p,Length %x\n", namebuf,
+ SectionData[SctnCnt], max(ScnHdr->VirtualSize, ScnHdr->SizeOfRawData));
+ OutputDebugString(szBuf);
+#endif
+
+ if ( ScnHdr->SizeOfRawData < ScnHdr->VirtualSize ) //initialize BSS data in the end of section
+ {
+ memset((char*)((long)(SectionData[SctnCnt]) + ScnHdr->SizeOfRawData), 0, ScnHdr->VirtualSize - ScnHdr->SizeOfRawData);
+ }
+
+ if (ScnHdr->Characteristics & IMAGE_SCN_CNT_BSS) //initialize whole .BSS section, pure .BSS is obsolete
+ {
+ memset(SectionData[SctnCnt], 0, ScnHdr->VirtualSize);
+ }
+
+#ifdef DUMPING_DATA
+ PrintSection(SectionHeader + SctnCnt, SectionData[SctnCnt]);
+#endif
+
+ }
+ return 1;
+}
+
+//FIXME: Add the Free Resources functions
+
+int CoffLoader::RVA2Section(unsigned long RVA)
+{
+ NumOfSections = CoffFileHeader->NumberOfSections;
+ for ( int i = 0; i < NumOfSections; i++)
+ {
+ if ( SectionHeader[i].VirtualAddress <= RVA )
+ {
+ if ( i + 1 != NumOfSections )
+ {
+ if ( RVA < SectionHeader[i + 1].VirtualAddress )
+ {
+ if ( SectionHeader[i].VirtualAddress + SectionHeader[i].VirtualSize <= RVA )
+ printf("Warning! Address outside of Section: %lx!\n", RVA);
+ // else
+ return i;
+ }
+ }
+ else
+ {
+ if ( SectionHeader[i].VirtualAddress + SectionHeader[i].VirtualSize <= RVA )
+ printf("Warning! Address outside of Section: %lx!\n", RVA);
+ // else
+ return i;
+ }
+ }
+ }
+ printf("RVA2Section lookup failure!\n");
+ return 0;
+}
+
+void* CoffLoader::RVA2Data(unsigned long RVA)
+{
+ int Sctn = RVA2Section(RVA);
+
+ if( RVA < SectionHeader[Sctn].VirtualAddress
+ || RVA >= SectionHeader[Sctn].VirtualAddress + SectionHeader[Sctn].VirtualSize)
+ {
+ // RVA2Section is lying, let's use base address of dll instead, only works if
+ // DLL has been loaded fully into memory, which we normally do
+ return (void*)(RVA + (unsigned long)hModule);
+ }
+ return SectionData[Sctn] + RVA - SectionHeader[Sctn].VirtualAddress;
+}
+
+unsigned long CoffLoader::Data2RVA(void* address)
+{
+ for ( int i = 0; i < CoffFileHeader->NumberOfSections; i++)
+ {
+ if(address >= SectionData[i] && address < SectionData[i] + SectionHeader[i].VirtualSize)
+ return (unsigned long)address - (unsigned long)SectionData[i] + SectionHeader[i].VirtualAddress;
+ }
+
+ // Section wasn't found, so use relative to main load of dll
+ return (unsigned long)address - (unsigned long)hModule;
+}
+
+char *CoffLoader::GetStringTblIndex(int index)
+{
+ char *table = StringTable;
+
+ while (index--)
+ table += strlen(table) + 1;
+ return table;
+}
+
+char *CoffLoader::GetStringTblOff(int Offset)
+{
+ return StringTable + Offset - 4;
+}
+
+char *CoffLoader::GetSymbolName(SymbolTable_t *sym)
+{
+ long long index = sym->Name.Offset;
+ int low = (int)(index & 0xFFFFFFFF);
+ int high = (int)((index >> 32) & 0xFFFFFFFF);
+
+ if (low == 0)
+ {
+ return GetStringTblOff(high);
+ }
+ else
+ {
+ static char shortname[9];
+ memset(shortname, 0, 9);
+ strncpy(shortname, (char *)sym->Name.ShortName, 8);
+ return shortname;
+ }
+}
+
+char *CoffLoader::GetSymbolName(int index)
+{
+ SymbolTable_t *sym = &(SymTable[index]);
+ return GetSymbolName(sym);
+}
+
+void CoffLoader::PrintStringTable(void)
+{
+ int size = SizeOfStringTable;
+ int index = 0;
+ char *table = StringTable;
+
+ printf("\nSTRING TABLE\n");
+ while (size)
+ {
+ printf("%2d: %s\n", index++, table);
+ size -= strlen(table) + 1;
+ table += strlen(table) + 1;
+ }
+ printf("\n");
+}
+
+
+void CoffLoader::PrintSymbolTable(void)
+{
+ int SymIndex;
+
+ printf("COFF SYMBOL TABLE\n");
+ for (SymIndex = 0; SymIndex < NumberOfSymbols; SymIndex++)
+ {
+ printf("%03X ", SymIndex);
+ printf("%08lX ", SymTable[SymIndex].Value);
+
+ if (SymTable[SymIndex].SectionNumber == IMAGE_SYM_ABSOLUTE)
+ printf("ABS ");
+ else if (SymTable[SymIndex].SectionNumber == IMAGE_SYM_DEBUG)
+ printf("DEBUG ");
+ else if (SymTable[SymIndex].SectionNumber == IMAGE_SYM_UNDEFINED)
+ printf("UNDEF ");
+ else
+ {
+ printf("SECT%d ", SymTable[SymIndex].SectionNumber);
+ if (SymTable[SymIndex].SectionNumber < 10)
+ printf(" ");
+ if (SymTable[SymIndex].SectionNumber < 100)
+ printf(" ");
+ }
+
+ if (SymTable[SymIndex].Type == 0)
+ printf("notype ");
+ else
+ {
+ printf("%X ", SymTable[SymIndex].Type);
+ if (SymTable[SymIndex].Type < 0x10)
+ printf(" ");
+ if (SymTable[SymIndex].Type < 0x100)
+ printf(" ");
+ if (SymTable[SymIndex].Type < 0x1000)
+ printf(" ");
+ }
+
+ if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_END_OF_FUNCTION)
+ printf("End of Function ");
+ if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_NULL)
+ printf("Null ");
+ if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_AUTOMATIC)
+ printf("Automatic ");
+ if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_EXTERNAL)
+ printf("External ");
+ if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_STATIC)
+ printf("Static ");
+ if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_REGISTER)
+ printf("Register ");
+ if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_EXTERNAL_DEF)
+ printf("External Def ");
+ if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_LABEL)
+ printf("Label ");
+ if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_UNDEFINED_LABEL)
+ printf("Undefined Label ");
+ if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_MEMBER_OF_STRUCT)
+ printf("Member Of Struct ");
+ if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_ARGUMENT)
+ printf("Argument ");
+ if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_STRUCT_TAG)
+ printf("Struct Tag ");
+ if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_MEMBER_OF_UNION)
+ printf("Member Of Union ");
+ if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_UNION_TAG)
+ printf("Union Tag ");
+ if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_TYPE_DEFINITION)
+ printf("Type Definition ");
+ if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_UNDEFINED_STATIC)
+ printf("Undefined Static ");
+ if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_ENUM_TAG)
+ printf("Enum Tag ");
+ if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_MEMBER_OF_ENUM)
+ printf("Member Of Enum ");
+ if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_REGISTER_PARAM)
+ printf("Register Param ");
+ if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_BIT_FIELD)
+ printf("Bit Field ");
+ if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_BLOCK)
+ printf("Block ");
+ if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_FUNCTION)
+ printf("Function ");
+ if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_END_OF_STRUCT)
+ printf("End Of Struct ");
+ if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_FILE)
+ printf("File ");
+ if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_SECTION)
+ printf("Section ");
+ if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_WEAK_EXTERNAL)
+ printf("Weak External ");
+
+ printf("| %s", GetSymbolName(SymIndex));
+
+ SymIndex += SymTable[SymIndex].NumberOfAuxSymbols;
+ printf("\n");
+ }
+ printf("\n");
+
+}
+
+void CoffLoader::PrintFileHeader(COFF_FileHeader_t *FileHeader)
+{
+ printf("COFF Header\n");
+ printf("------------------------------------------\n\n");
+
+ printf("MachineType: 0x%04X\n", FileHeader->MachineType);
+ printf("NumberOfSections: 0x%04X\n", FileHeader->NumberOfSections);
+ printf("TimeDateStamp: 0x%08lX\n",FileHeader->TimeDateStamp);
+ printf("PointerToSymbolTable: 0x%08lX\n",FileHeader->PointerToSymbolTable);
+ printf("NumberOfSymbols: 0x%08lX\n",FileHeader->NumberOfSymbols);
+ printf("SizeOfOptionHeader: 0x%04X\n", FileHeader->SizeOfOptionHeader);
+ printf("Characteristics: 0x%04X\n", FileHeader->Characteristics);
+
+ if (FileHeader->Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
+ printf(" IMAGE_FILE_RELOCS_STRIPPED\n");
+
+ if (FileHeader->Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE)
+ printf(" IMAGE_FILE_EXECUTABLE_IMAGE\n");
+
+ if (FileHeader->Characteristics & IMAGE_FILE_LINE_NUMS_STRIPPED)
+ printf(" IMAGE_FILE_LINE_NUMS_STRIPPED\n");
+
+ if (FileHeader->Characteristics & IMAGE_FILE_LOCAL_SYMS_STRIPPED)
+ printf(" IMAGE_FILE_LOCAL_SYMS_STRIPPED\n");
+
+ if (FileHeader->Characteristics & IMAGE_FILE_AGGRESSIVE_WS_TRIM)
+ printf(" IMAGE_FILE_AGGRESSIVE_WS_TRIM\n");
+
+ if (FileHeader->Characteristics & IMAGE_FILE_LARGE_ADDRESS_AWARE)
+ printf(" IMAGE_FILE_LARGE_ADDRESS_AWARE\n");
+
+ if (FileHeader->Characteristics & IMAGE_FILE_16BIT_MACHINE)
+ printf(" IMAGE_FILE_16BIT_MACHINE\n");
+
+ if (FileHeader->Characteristics & IMAGE_FILE_BYTES_REVERSED_LO)
+ printf(" IMAGE_FILE_BYTES_REVERSED_LO\n");
+
+ if (FileHeader->Characteristics & IMAGE_FILE_32BIT_MACHINE)
+ printf(" IMAGE_FILE_32BIT_MACHINE\n");
+
+ if (FileHeader->Characteristics & IMAGE_FILE_DEBUG_STRIPPED)
+ printf(" IMAGE_FILE_DEBUG_STRIPPED\n");
+
+ if (FileHeader->Characteristics & IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP)
+ printf(" IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP\n");
+
+ if (FileHeader->Characteristics & IMAGE_FILE_SYSTEM)
+ printf(" IMAGE_FILE_SYSTEM\n");
+
+ if (FileHeader->Characteristics & IMAGE_FILE_DLL)
+ printf(" IMAGE_FILE_DLL\n");
+
+ if (FileHeader->Characteristics & IMAGE_FILE_UP_SYSTEM_ONLY)
+ printf(" IMAGE_FILE_UP_SYSTEM_ONLY\n");
+
+ if (FileHeader->Characteristics & IMAGE_FILE_BYTES_REVERSED_HI)
+ printf(" IMAGE_FILE_BYTES_REVERSED_HI\n");
+
+ printf("\n");
+}
+
+void CoffLoader::PrintOptionHeader(OptionHeader_t *OptHdr)
+{
+ printf("Option Header\n");
+ printf("------------------------------------------\n\n");
+
+ printf("Magic: 0x%04X\n", OptHdr->Magic);
+ printf("Linker Major Ver: 0x%02X\n", VERSION_MAJOR(OptHdr->LinkVersion));
+ printf("Linker Minor Ver: 0x%02X\n", VERSION_MINOR(OptHdr->LinkVersion));
+ printf("Code Size: 0x%08lX\n", OptHdr->CodeSize);
+ printf("Data Size: 0x%08lX\n", OptHdr->DataSize);
+ printf("BSS Size: 0x%08lX\n", OptHdr->BssSize);
+ printf("Entry: 0x%08lX\n", OptHdr->Entry);
+ printf("Code Base: 0x%08lX\n", OptHdr->CodeBase);
+ printf("Data Base: 0x%08lX\n", OptHdr->DataBase);
+ printf("\n");
+}
+
+void CoffLoader::PrintWindowsHeader(WindowsHeader_t *WinHdr)
+{
+ printf("Windows Specific Option Header\n");
+ printf("------------------------------------------\n\n");
+
+ printf("Image Base: 0x%08lX\n", WinHdr->ImageBase);
+ printf("Section Alignment: 0x%08lX\n", WinHdr->SectionAlignment);
+ printf("File Alignment: 0x%08lX\n", WinHdr->FileAlignment);
+ printf("OS Version: %d.%08d\n", BIGVERSION_MAJOR(WinHdr->OSVer), BIGVERSION_MINOR(WinHdr->OSVer));
+ printf("Image Version: %d.%08d\n", BIGVERSION_MAJOR(WinHdr->ImgVer), BIGVERSION_MINOR(WinHdr->ImgVer));
+ printf("SubSystem Version: %d.%08d\n", BIGVERSION_MAJOR(WinHdr->SubSysVer), BIGVERSION_MINOR(WinHdr->SubSysVer));
+ printf("Size of Image: 0x%08lX\n", WinHdr->SizeOfImage);
+ printf("Size of Headers: 0x%08lX\n", WinHdr->SizeOfHeaders);
+ printf("Checksum: 0x%08lX\n", WinHdr->CheckSum);
+ printf("Subsystem: 0x%04X\n", WinHdr->Subsystem);
+ printf("DLL Flags: 0x%04X\n", WinHdr->DLLFlags);
+ printf("Sizeof Stack Resv: 0x%08lX\n", WinHdr->SizeOfStackReserve);
+ printf("Sizeof Stack Comm: 0x%08lX\n", WinHdr->SizeOfStackCommit);
+ printf("Sizeof Heap Resv: 0x%08lX\n", WinHdr->SizeOfHeapReserve);
+ printf("Sizeof Heap Comm: 0x%08lX\n", WinHdr->SizeOfHeapCommit);
+ printf("Loader Flags: 0x%08lX\n", WinHdr->LoaderFlags);
+ printf("Num Directories: %ld\n", WinHdr->NumDirectories);
+ printf("\n");
+}
+
+void CoffLoader::PrintSection(SectionHeader_t* ScnHdr, const char* data)
+{
+ char SectionName[9];
+
+ strncpy(SectionName, (char *)ScnHdr->Name, 8);
+ SectionName[8] = 0;
+ printf("Section: %s\n", SectionName);
+ printf("------------------------------------------\n\n");
+
+ printf("Virtual Size: 0x%08lX\n", ScnHdr->VirtualSize);
+ printf("Virtual Address: 0x%08lX\n", ScnHdr->VirtualAddress);
+ printf("Sizeof Raw Data: 0x%08lX\n", ScnHdr->SizeOfRawData);
+ printf("Ptr To Raw Data: 0x%08lX\n", ScnHdr->PtrToRawData);
+ printf("Ptr To Relocations: 0x%08lX\n", ScnHdr->PtrToRelocations);
+ printf("Ptr To Line Nums: 0x%08lX\n", ScnHdr->PtrToLineNums);
+ printf("Num Relocations: 0x%04X\n", ScnHdr->NumRelocations);
+ printf("Num Line Numbers: 0x%04X\n", ScnHdr->NumLineNumbers);
+ printf("Characteristics: 0x%08lX\n", ScnHdr->Characteristics);
+ if (ScnHdr->Characteristics & IMAGE_SCN_CNT_CODE)
+ printf(" IMAGE_SCN_CNT_CODE\n");
+ if (ScnHdr->Characteristics & IMAGE_SCN_CNT_DATA)
+ printf(" IMAGE_SCN_CNT_DATA\n");
+ if (ScnHdr->Characteristics & IMAGE_SCN_CNT_BSS)
+ printf(" IMAGE_SCN_CNT_BSS\n");
+ if (ScnHdr->Characteristics & IMAGE_SCN_LNK_INFO)
+ printf(" IMAGE_SCN_LNK_INFO\n");
+ if (ScnHdr->Characteristics & IMAGE_SCN_LNK_REMOVE)
+ printf(" IMAGE_SCN_LNK_REMOVE\n");
+ if (ScnHdr->Characteristics & IMAGE_SCN_LNK_COMDAT)
+ printf(" IMAGE_SCN_LNK_COMDAT\n");
+
+ if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_1BYTES)
+ printf(" IMAGE_SCN_ALIGN_1BYTES\n");
+ if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_2BYTES)
+ printf(" IMAGE_SCN_ALIGN_2BYTES\n");
+ if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_4BYTES)
+ printf(" IMAGE_SCN_ALIGN_4BYTES\n");
+ if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_8BYTES)
+ printf(" IMAGE_SCN_ALIGN_8BYTES\n");
+ if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_16BYTES)
+ printf(" IMAGE_SCN_ALIGN_16BYTES\n");
+ if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_32BYTES)
+ printf(" IMAGE_SCN_ALIGN_32BYTES\n");
+ if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_64BYTES)
+ printf(" IMAGE_SCN_ALIGN_64BYTES\n");
+ if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_128BYTES)
+ printf(" IMAGE_SCN_ALIGN_128BYTES\n");
+ if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_256BYTES)
+ printf(" IMAGE_SCN_ALIGN_256BYTES\n");
+ if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_512BYTES)
+ printf(" IMAGE_SCN_ALIGN_512BYTES\n");
+ if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_1024BYTES)
+ printf(" IMAGE_SCN_ALIGN_1024BYTES\n");
+ if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_2048BYTES)
+ printf(" IMAGE_SCN_ALIGN_2048BYTES\n");
+ if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_4096BYTES)
+ printf(" IMAGE_SCN_ALIGN_4096BYTES\n");
+ if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_8192BYTES)
+ printf(" IMAGE_SCN_ALIGN_8192BYTES\n");
+
+ if (ScnHdr->Characteristics & IMAGE_SCN_LNK_NRELOC_OVFL)
+ printf(" IMAGE_SCN_LNK_NRELOC_OVFL\n");
+ if (ScnHdr->Characteristics & IMAGE_SCN_MEM_DISCARDABLE)
+ printf(" IMAGE_SCN_MEM_DISCARDABLE\n");
+ if (ScnHdr->Characteristics & IMAGE_SCN_MEM_NOT_CACHED)
+ printf(" IMAGE_SCN_MEM_NOT_CACHED\n");
+ if (ScnHdr->Characteristics & IMAGE_SCN_MEM_NOT_PAGED)
+ printf(" IMAGE_SCN_MEM_NOT_PAGED\n");
+ if (ScnHdr->Characteristics & IMAGE_SCN_MEM_SHARED)
+ printf(" IMAGE_SCN_MEM_SHARED\n");
+ if (ScnHdr->Characteristics & IMAGE_SCN_MEM_EXECUTE)
+ printf(" IMAGE_SCN_MEM_EXECUTE\n");
+ if (ScnHdr->Characteristics & IMAGE_SCN_MEM_READ)
+ printf(" IMAGE_SCN_MEM_READ\n");
+ if (ScnHdr->Characteristics & IMAGE_SCN_MEM_WRITE)
+ printf(" IMAGE_SCN_MEM_WRITE\n");
+ printf("\n");
+
+ // Read the section Data, Relocations, & Line Nums
+ // Save the offset
+
+ if (ScnHdr->SizeOfRawData > 0)
+ {
+ unsigned int i;
+ // Print the Raw Data
+
+ printf("\nRAW DATA");
+ for (i = 0; i < ScnHdr->VirtualSize; i++)
+ {
+ if ((i % 16) == 0)
+ printf("\n %08X: ", i);
+ char ch = data[i];
+ printf("%02X ", (unsigned int)ch);
+ }
+ printf("\n\n");
+ }
+
+ /*
+ #if 0
+ if (ScnHdr->NumRelocations > 0)
+ {
+ // Print Section Relocations
+ ObjReloc_t ObjReloc;
+
+ fseek(fp, ScnHdr->PtrToRelocations/ * + CoffBeginOffset* /, SEEK_SET);
+ printf("RELOCATIONS\n");
+ printf(" Symbol Symbol\n");
+ printf(" Offset Type Index Name\n");
+ printf(" -------- -------- -------- ------\n");
+ for (int i = 0; i < ScnHdr->NumRelocations; i++)
+ {
+ fread(&ObjReloc, 1, sizeof(ObjReloc_t), fp);
+ printf(" %08X ", ObjReloc.VirtualAddress);
+
+ if (ObjReloc.Type == IMAGE_REL_I386_ABSOLUTE)
+ printf("ABSOLUTE ");
+ if (ObjReloc.Type == IMAGE_REL_I386_DIR16)
+ printf("DIR16 ");
+ if (ObjReloc.Type == IMAGE_REL_I386_REL16)
+ printf("REL16 ");
+ if (ObjReloc.Type == IMAGE_REL_I386_DIR32)
+ printf("DIR32 ");
+ if (ObjReloc.Type == IMAGE_REL_I386_DIR32NB)
+ printf("DIR32NB ");
+ if (ObjReloc.Type == IMAGE_REL_I386_SEG12)
+ printf("SEG12 ");
+ if (ObjReloc.Type == IMAGE_REL_I386_SECTION)
+ printf("SECTION ");
+ if (ObjReloc.Type == IMAGE_REL_I386_SECREL)
+ printf("SECREL ");
+ if (ObjReloc.Type == IMAGE_REL_I386_REL32)
+ printf("REL32 ");
+ printf("%8X ", ObjReloc.SymTableIndex);
+ printf("%s\n", GetSymbolName(ObjReloc.SymTableIndex));
+ }
+ printf("\n");
+ }
+
+ if (ScnHdr->NumLineNumbers > 0)
+ {
+ // Print The Line Number Info
+ LineNumbers_t LineNumber;
+ int LineCnt = 0;
+ int BaseLineNum = -1;
+
+ fseek(fp, ScnHdr->PtrToLineNums/ * + CoffBeginOffset* /, SEEK_SET);
+ printf("LINE NUMBERS");
+ for (int i = 0; i < ScnHdr->NumLineNumbers; i++)
+ {
+ int LNOffset = ftell(fp);
+
+ fread(&LineNumber, 1, sizeof(LineNumbers_t), fp);
+ if (LineNumber.LineNum == 0)
+ {
+ SymbolTable_t *Sym;
+ int SymIndex;
+
+ printf("\n");
+ SymIndex = LineNumber.Type.SymbolTableIndex;
+ Sym = &(SymTable[SymIndex]);
+ if (Sym->NumberOfAuxSymbols > 0)
+ {
+ Sym = &(SymTable[SymIndex+1]);
+ AuxFuncDef_t *FuncDef = (AuxFuncDef_t *)Sym;
+
+ if (FuncDef->PtrToLineNumber == LNOffset)
+ {
+ Sym = &(SymTable[FuncDef->TagIndex]);
+ if (Sym->NumberOfAuxSymbols > 0)
+ {
+ Sym = &(SymTable[FuncDef->TagIndex+1]);
+ AuxBfEf_t *Bf = (AuxBfEf_t *)Sym;
+ BaseLineNum = Bf->LineNumber;
+ }
+ }
+ }
+ printf(" Symbol Index: %8x ", SymIndex);
+ printf(" Base line number: %8d\n", BaseLineNum);
+ printf(" Symbol name = %s", GetSymbolName(SymIndex));
+ LineCnt = 0;
+ }
+ else
+ {
+ if ((LineCnt%4) == 0)
+ {
+ printf("\n ");
+ LineCnt = 0;
+ }
+ printf("%08X(%5d) ", LineNumber.Type.VirtualAddress,
+ LineNumber.LineNum + BaseLineNum);
+ LineCnt ++;
+ }
+ }
+ printf("\n");
+ }
+ #endif
+ */
+
+ printf("\n");
+}
+
+int CoffLoader::ParseCoff(FILE *fp)
+{
+ if ( !LoadCoffHModule(fp) )
+ {
+ printf("Failed to load/find COFF hModule header\n");
+ return 0;
+ }
+ if ( !LoadSymTable(fp) ||
+ !LoadStringTable(fp) ||
+ !LoadSections(fp) )
+ return 0;
+
+ PerformFixups();
+
+#ifdef DUMPING_DATA
+ PrintSymbolTable();
+ PrintStringTable();
+#endif
+ return 1;
+}
+
+void CoffLoader::PerformFixups(void)
+{
+ int FixupDataSize;
+ char *FixupData;
+ char *EndData;
+
+ EntryAddress = (unsigned long)RVA2Data(EntryAddress);
+
+ if( reinterpret_cast<void*>(WindowsHeader->ImageBase) == hModule )
+ return;
+
+ if ( !Directory )
+ return ;
+
+ if ( NumOfDirectories <= BASE_RELOCATION_TABLE )
+ return ;
+
+ if ( !Directory[BASE_RELOCATION_TABLE].Size )
+ return ;
+
+ FixupDataSize = Directory[BASE_RELOCATION_TABLE].Size;
+ FixupData = (char*)RVA2Data(Directory[BASE_RELOCATION_TABLE].RVA);
+ EndData = FixupData + FixupDataSize;
+
+ while (FixupData < EndData)
+ {
+ // Starting a new Fixup Block
+ unsigned long PageRVA = *((unsigned long*)FixupData);
+ FixupData += 4;
+ unsigned long BlockSize = *((unsigned long*)FixupData);
+ FixupData += 4;
+
+ BlockSize -= 8;
+ for (unsigned int i = 0; i < BlockSize / 2; i++)
+ {
+ unsigned short Fixup = *((unsigned short*)FixupData);
+ FixupData += 2;
+ int Type = (Fixup >> 12) & 0x0f;
+ Fixup &= 0xfff;
+ if (Type == IMAGE_REL_BASED_HIGHLOW)
+ {
+ unsigned long *Off = (unsigned long*)RVA2Data(Fixup + PageRVA);
+ *Off = (unsigned long)RVA2Data(*Off - WindowsHeader->ImageBase);
+ }
+ else if (Type == IMAGE_REL_BASED_ABSOLUTE)
+ {}
+ else
+ {
+ printf("Unsupported fixup type!!\n");
+ }
+ }
+ }
+}