xref: /reactos/sdk/tools/obj2bin/obj2bin.c (revision cdf90707)
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