Reactos
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <typedefs.h>
5#include <pecoff.h>
6
7static
8void
9Usage(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
15static
16int
17RelocateSection(
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
71int 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}