1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <typedefs.h> 5 #include <pecoff.h> 6 7 static 8 void 9 Usage(void) 10 { 11 printf("Converts a coff object file into a raw binary file.\n" 12 "Syntax: obj2bin <source file> <dest file> <base address>\n"); 13 } 14 15 static 16 int 17 RelocateSection( 18 char *pData, 19 IMAGE_SECTION_HEADER *pSectionHeader, 20 PIMAGE_SYMBOL pSymbols, 21 unsigned int iOffset) 22 { 23 unsigned int i, nOffset; 24 PIMAGE_RELOCATION pReloc; 25 char *pSection; 26 WORD *p16; 27 DWORD *p32; 28 29 pSection = pData + pSectionHeader->PointerToRawData; 30 31 /* Calculate pointer to relocation table */ 32 pReloc = (PIMAGE_RELOCATION)(pData + pSectionHeader->PointerToRelocations); 33 34 /* Loop all relocations */ 35 for (i = 0; i < pSectionHeader->NumberOfRelocations; i++) 36 { 37 nOffset = pReloc->VirtualAddress - pSectionHeader->VirtualAddress; 38 39 if (nOffset > pSectionHeader->SizeOfRawData) continue; 40 41 switch (pReloc->Type) 42 { 43 case IMAGE_REL_I386_ABSOLUTE: 44 case 16: 45 p16 = (void*)(pSection + nOffset); 46 *p16 += (WORD)(pSymbols[pReloc->SymbolTableIndex].Value + iOffset); 47 break; 48 49 case IMAGE_REL_I386_REL16: 50 p16 = (void*)(pSection + nOffset); 51 *p16 += (WORD)(pSymbols[pReloc->SymbolTableIndex].Value + iOffset); 52 break; 53 54 case IMAGE_REL_I386_DIR32: 55 p32 = (void*)(pSection + nOffset); 56 *p32 += (DWORD)(pSymbols[pReloc->SymbolTableIndex].Value + iOffset); 57 break; 58 59 default: 60 printf("Unknown relocation type %u, address 0x%x\n", 61 pReloc->Type, (unsigned)pReloc->VirtualAddress); 62 return 0; 63 } 64 65 pReloc++; 66 } 67 68 return 1; 69 } 70 71 int main(int argc, char *argv[]) 72 { 73 char *pszSourceFile; 74 char *pszDestFile; 75 unsigned long nFileSize, nBaseAddress; 76 FILE *pSourceFile, *pDestFile; 77 IMAGE_FILE_HEADER *pFileHeader; 78 IMAGE_SECTION_HEADER *pSectionHeader; 79 unsigned int i; 80 char *pData; 81 PIMAGE_SYMBOL pSymbols; 82 83 if ((argc != 4) || (strcmp(argv[1], "--help") == 0)) 84 { 85 Usage(); 86 return -1; 87 } 88 89 pszSourceFile = argv[1]; 90 pszDestFile = argv[2]; 91 nBaseAddress = strtol(argv[3], 0, 16); 92 93 pSourceFile = fopen(pszSourceFile, "rb"); 94 if (!pSourceFile) 95 { 96 fprintf(stderr, "Couldn't open source file '%s'\n", pszSourceFile); 97 return -2; 98 } 99 100 /* Get file size */ 101 fseek(pSourceFile, 0, SEEK_END); 102 nFileSize = ftell(pSourceFile); 103 rewind(pSourceFile); 104 105 /* Allocate memory for the file */ 106 pData = malloc(nFileSize); 107 if (!pData) 108 { 109 fclose(pSourceFile); 110 fprintf(stderr, "Failed to allocate %lu bytes\n", nFileSize); 111 return -3; 112 } 113 114 /* Read the whole source file */ 115 if (!fread(pData, nFileSize, 1, pSourceFile)) 116 { 117 free(pData); 118 fclose(pSourceFile); 119 fprintf(stderr, "Failed to read %lu bytes from source file\n", nFileSize); 120 return -4; 121 } 122 123 /* Close source file */ 124 fclose(pSourceFile); 125 126 /* Open the destination file */ 127 pDestFile = fopen(pszDestFile, "wb"); 128 if (!pDestFile) 129 { 130 free(pData); 131 fprintf(stderr, "Couldn't open destination file '%s'\n", pszDestFile); 132 return -5; 133 } 134 135 /* Calculate table pointers */ 136 pFileHeader = (IMAGE_FILE_HEADER*)pData; 137 pSymbols = (void*)(pData + pFileHeader->PointerToSymbolTable); 138 pSectionHeader = (void*)(((char*)(pFileHeader + 1)) + pFileHeader->SizeOfOptionalHeader); 139 140 /* Loop all sections */ 141 for (i = 0; i < pFileHeader->NumberOfSections; i++) 142 { 143 /* Check if this is '.text' section */ 144 if ((strcmp((char*)pSectionHeader->Name, ".text") == 0) && 145 (pSectionHeader->SizeOfRawData != 0)) 146 { 147 if (!RelocateSection(pData, 148 pSectionHeader, 149 pSymbols, 150 nBaseAddress)) 151 { 152 free(pData); 153 fclose(pDestFile); 154 return -7; 155 } 156 157 /* Write the section to the destination file */ 158 if (!fwrite(pData + pSectionHeader->PointerToRawData, 159 pSectionHeader->SizeOfRawData, 1, pDestFile)) 160 { 161 free(pData); 162 fclose(pDestFile); 163 fprintf(stderr, "Failed to write %u bytes to destination file\n", 164 (unsigned int)pSectionHeader->SizeOfRawData); 165 return -6; 166 } 167 168 nBaseAddress += pSectionHeader->SizeOfRawData; 169 } 170 171 pSectionHeader++; 172 } 173 174 free(pData); 175 fclose(pDestFile); 176 177 return 0; 178 } 179