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