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