88c6e95d724b499bc9d16d35a65568ca47d438e8
[reactos.git] / reactos / tools / obj2bin / obj2bin.c
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 void
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_DIR32:
50 p32 = (void*)(pSection + nOffset);
51 *p32 += (DWORD)(pSymbols[pReloc->SymbolTableIndex].Value + iOffset);
52 break;
53
54 default:
55 printf("Unknown relocatation type %d, address 0x%lx\n",
56 pReloc->Type, pReloc->VirtualAddress);
57 }
58
59 pReloc++;
60 }
61 }
62
63 int main(int argc, char *argv[])
64 {
65 char *pszSourceFile;
66 char *pszDestFile;
67 unsigned long nFileSize, nBaseAddress;
68 FILE *pSourceFile, *pDestFile;
69 IMAGE_FILE_HEADER *pFileHeader;
70 IMAGE_SECTION_HEADER *pSectionHeader;
71 unsigned int i;
72 char *pData;
73 PIMAGE_SYMBOL pSymbols;
74
75 if ((argc != 4) || (strcmp(argv[1], "--help") == 0))
76 {
77 Usage();
78 return -1;
79 }
80
81 pszSourceFile = argv[1];
82 pszDestFile = argv[2];
83 nBaseAddress = strtol(argv[3], 0, 16);
84
85 pSourceFile = fopen(pszSourceFile, "rb");
86 if (!pSourceFile)
87 {
88 fprintf(stderr, "Couldn't open source file '%s'\n", pszSourceFile);
89 return -2;
90 }
91
92 /* Get file size */
93 fseek(pSourceFile, 0, SEEK_END);
94 nFileSize = ftell(pSourceFile);
95 rewind(pSourceFile);
96
97 /* Allocate memory for the file */
98 pData = malloc(nFileSize);
99 if (!pData)
100 {
101 fclose(pSourceFile);
102 fprintf(stderr, "Failed to allocate %ld bytes\n", nFileSize);
103 return -3;
104 }
105
106 /* Read the whole source file */
107 if (!fread(pData, nFileSize, 1, pSourceFile))
108 {
109 free(pData);
110 fclose(pSourceFile);
111 fprintf(stderr, "Failed to read %ld bytes from source file\n", nFileSize);
112 return -4;
113 }
114
115 /* Close source file */
116 fclose(pSourceFile);
117
118 /* Open the destination file */
119 pDestFile = fopen(pszDestFile, "wb");
120 if (!pDestFile)
121 {
122 free(pData);
123 fprintf(stderr, "Couldn't open destination file '%s'\n", pszDestFile);
124 return -5;
125 }
126
127 /* Calculate table pointers */
128 pFileHeader = (IMAGE_FILE_HEADER*)pData;
129 pSymbols = (void*)(pData + pFileHeader->PointerToSymbolTable);
130 pSectionHeader = (void*)(((char*)(pFileHeader + 1)) + pFileHeader->SizeOfOptionalHeader);
131
132 /* Loop all sections */
133 for (i = 0; i < pFileHeader->NumberOfSections; i++)
134 {
135 /* Check if this is '.text' section */
136 if ((strcmp((char*)pSectionHeader->Name, ".text") == 0) &&
137 (pSectionHeader->SizeOfRawData != 0))
138 {
139 RelocateSection(pData,
140 pSectionHeader,
141 pSymbols,
142 nBaseAddress);
143
144 /* Write the section to the destination file */
145 if (!fwrite(pData + pSectionHeader->PointerToRawData,
146 pSectionHeader->SizeOfRawData, 1, pDestFile))
147 {
148 free(pData);
149 fclose(pDestFile);
150 fprintf(stderr, "Failed to write %ld bytes to destination file\n",
151 pSectionHeader->SizeOfRawData);
152 return -6;
153 }
154
155 nBaseAddress += pSectionHeader->SizeOfRawData;
156 }
157
158 pSectionHeader++;
159 }
160
161 free(pData);
162 fclose(pDestFile);
163
164 return 0;
165 }