#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include "../pecoff.h"
+#include <typedefs.h>
+#include <pecoff.h>
static
void
Usage(void)
{
printf("Converts a coff object file into a raw binary file.\n"
- "Syntax: obj2bin <source file> <dest file>\n");
+ "Syntax: obj2bin <source file> <dest file> <base address>\n");
+}
+
+static
+void
+RelocateSection(
+ char *pData,
+ IMAGE_SECTION_HEADER *pSectionHeader,
+ PIMAGE_SYMBOL pSymbols,
+ unsigned int iOffset)
+{
+ unsigned int i, nOffset;
+ PIMAGE_RELOCATION pReloc;
+ char *pSection;
+ WORD *p16;
+ DWORD *p32;
+
+ pSection = pData + pSectionHeader->PointerToRawData;
+
+ /* Calculate pointer to relocation table */
+ pReloc = (PIMAGE_RELOCATION)(pData + pSectionHeader->PointerToRelocations);
+
+ /* Loop all relocations */
+ for (i = 0; i < pSectionHeader->NumberOfRelocations; i++)
+ {
+ nOffset = pReloc->VirtualAddress - pSectionHeader->VirtualAddress;
+
+ if (nOffset > pSectionHeader->SizeOfRawData) continue;
+
+ switch (pReloc->Type)
+ {
+ case IMAGE_REL_I386_ABSOLUTE:
+ case 16:
+ p16 = (void*)(pSection + nOffset);
+ *p16 += (WORD)(pSymbols[pReloc->SymbolTableIndex].Value + iOffset);
+ break;
+
+ case IMAGE_REL_I386_DIR32:
+ p32 = (void*)(pSection + nOffset);
+ *p32 += (DWORD)(pSymbols[pReloc->SymbolTableIndex].Value + iOffset);
+ break;
+
+ default:
+ printf("Unknown relocation type %u, address 0x%x\n",
+ pReloc->Type, (unsigned)pReloc->VirtualAddress);
+ }
+
+ pReloc++;
+ }
}
int main(int argc, char *argv[])
{
char *pszSourceFile;
char *pszDestFile;
+ unsigned long nFileSize, nBaseAddress;
FILE *pSourceFile, *pDestFile;
- IMAGE_FILE_HEADER FileHeader;
- IMAGE_SECTION_HEADER SectionHeader;
+ IMAGE_FILE_HEADER *pFileHeader;
+ IMAGE_SECTION_HEADER *pSectionHeader;
unsigned int i;
- size_t nSize;
- void *pData;
+ char *pData;
+ PIMAGE_SYMBOL pSymbols;
- if ((argc != 3) || (strcmp(argv[1], "--help") == 0)) Usage();
+ if ((argc != 4) || (strcmp(argv[1], "--help") == 0))
+ {
+ Usage();
+ return -1;
+ }
pszSourceFile = argv[1];
pszDestFile = argv[2];
+ nBaseAddress = strtol(argv[3], 0, 16);
pSourceFile = fopen(pszSourceFile, "rb");
if (!pSourceFile)
{
fprintf(stderr, "Couldn't open source file '%s'\n", pszSourceFile);
- return -1;
- }
-
- pDestFile = fopen(pszDestFile, "wb");
- if (!pszDestFile)
- {
- fprintf(stderr, "Couldn't open dest file '%s'\n", pszDestFile);
return -2;
}
- /* Load the coff header */
- nSize = fread(&FileHeader, 1, sizeof(FileHeader), pSourceFile);
- if (nSize != sizeof(FileHeader))
+ /* Get file size */
+ fseek(pSourceFile, 0, SEEK_END);
+ nFileSize = ftell(pSourceFile);
+ rewind(pSourceFile);
+
+ /* Allocate memory for the file */
+ pData = malloc(nFileSize);
+ if (!pData)
{
- fprintf(stderr, "Failed to read source file\n");
+ fclose(pSourceFile);
+ fprintf(stderr, "Failed to allocate %lu bytes\n", nFileSize);
return -3;
}
- /* Jump to section headers (skip optional header) */
- if (fseek(pSourceFile, FileHeader.SizeOfOptionalHeader, SEEK_CUR))
+ /* Read the whole source file */
+ if (!fread(pData, nFileSize, 1, pSourceFile))
{
- fprintf(stderr, "Failed to set file pointer\n");
+ free(pData);
+ fclose(pSourceFile);
+ fprintf(stderr, "Failed to read %lu bytes from source file\n", nFileSize);
return -4;
}
- /* Loop all sections */
- for (i = 0; i < FileHeader.NumberOfSections; i++)
- {
- /* Read section header */
- nSize = fread(&SectionHeader, 1, sizeof(SectionHeader), pSourceFile);
- if (nSize != sizeof(SectionHeader))
- {
- fprintf(stderr, "Failed to read section %ld file\n", i);
- return -5;
- }
-
- /* Check if this is '.text' section */
- if (strcmp(SectionHeader.Name, ".text") == 0) break;
- }
+ /* Close source file */
+ fclose(pSourceFile);
- if (i == FileHeader.NumberOfSections)
+ /* Open the destination file */
+ pDestFile = fopen(pszDestFile, "wb");
+ if (!pDestFile)
{
- fprintf(stderr, "No .text section found\n");
- return -6;
+ free(pData);
+ fprintf(stderr, "Couldn't open destination file '%s'\n", pszDestFile);
+ return -5;
}
- /* Move file pointer to the start of the section*/
- if (fseek(pSourceFile, SectionHeader.PointerToRawData, SEEK_SET))
- {
- fprintf(stderr, "Failed to set file pointer\n");
- return -7;
- }
+ /* Calculate table pointers */
+ pFileHeader = (IMAGE_FILE_HEADER*)pData;
+ pSymbols = (void*)(pData + pFileHeader->PointerToSymbolTable);
+ pSectionHeader = (void*)(((char*)(pFileHeader + 1)) + pFileHeader->SizeOfOptionalHeader);
- /* Allocate memory for the section */
- pData = malloc(SectionHeader.SizeOfRawData);
- if (!pData)
- {
- fprintf(stderr, "Failed to allocate %ld bytes\n", SectionHeader.SizeOfRawData);
- return -8;
- }
-
- /* Read section data */
- if (!fread(pData, SectionHeader.SizeOfRawData, 1, pSourceFile))
+ /* Loop all sections */
+ for (i = 0; i < pFileHeader->NumberOfSections; i++)
{
- fprintf(stderr, "Failed to read section %ld file\n", i);
- return -5;
- }
+ /* Check if this is '.text' section */
+ if ((strcmp((char*)pSectionHeader->Name, ".text") == 0) &&
+ (pSectionHeader->SizeOfRawData != 0))
+ {
+ RelocateSection(pData,
+ pSectionHeader,
+ pSymbols,
+ nBaseAddress);
+
+ /* Write the section to the destination file */
+ if (!fwrite(pData + pSectionHeader->PointerToRawData,
+ pSectionHeader->SizeOfRawData, 1, pDestFile))
+ {
+ free(pData);
+ fclose(pDestFile);
+ fprintf(stderr, "Failed to write %u bytes to destination file\n",
+ (unsigned int)pSectionHeader->SizeOfRawData);
+ return -6;
+ }
+
+ nBaseAddress += pSectionHeader->SizeOfRawData;
+ }
- /* Write the section to the destination file */
- if (!fwrite(pData, SectionHeader.SizeOfRawData, 1, pDestFile))
- {
- fprintf(stderr, "Failed to write data\n");
- return -9;
+ pSectionHeader++;
}
+ free(pData);
fclose(pDestFile);
- fclose(pSourceFile);
return 0;
}
-