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