mirror of
https://github.com/reactos/reactos.git
synced 2024-11-18 21:13:52 +00:00
226 lines
5.2 KiB
C
226 lines
5.2 KiB
C
/*
|
|
* Generates assembly definitions from the target headers.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdint.h>
|
|
|
|
#define IMAGE_FILE_MACHINE_I386 0x014c
|
|
#define IMAGE_FILE_MACHINE_AMD64 0x8664
|
|
#define IMAGE_FILE_MACHINE_ARMNT 0x01c4
|
|
|
|
#ifdef _MSC_VER
|
|
#define PRIx64 "I64x"
|
|
#else
|
|
#include <inttypes.h>
|
|
#define _stricmp strcasecmp
|
|
#endif
|
|
|
|
typedef struct
|
|
{
|
|
char Type;
|
|
char Name[55];
|
|
uint64_t Value;
|
|
} ASMGENDATA;
|
|
|
|
#define TYPE_END 0
|
|
#define TYPE_RAW 1
|
|
#define TYPE_CONSTANT 2
|
|
#define TYPE_HEADER 3
|
|
|
|
int main(int argc, char* argv[])
|
|
{
|
|
FILE *input, *output;
|
|
ASMGENDATA data;
|
|
int i, result = -1;
|
|
int ms_format = 0;
|
|
char header[20];
|
|
uint32_t e_lfanew, signature;
|
|
uint16_t Machine, NumberOfSections, SizeOfOptionalHeader;
|
|
typedef struct
|
|
{
|
|
char Name[8];
|
|
uint32_t VirtualSize;
|
|
uint32_t VirtualAddress;
|
|
uint32_t RawSize;
|
|
uint32_t RawAddress;
|
|
uint32_t RelocAddress;
|
|
uint32_t LineNumbers;
|
|
uint16_t RelocationsNumber;
|
|
uint16_t LineNumbersNumber;
|
|
uint32_t Characteristics;
|
|
} SECTION;
|
|
SECTION section;
|
|
|
|
if (argc >= 4 && _stricmp(argv[3], "-ms") == 0) ms_format = 1;
|
|
|
|
/* Open the input file */
|
|
input = fopen(argv[1], "rb");
|
|
if (!input)
|
|
{
|
|
fprintf(stderr, "Could not open input file '%s'\n", argv[1]);
|
|
return -1;
|
|
}
|
|
|
|
/* Open the output file */
|
|
output = fopen(argv[2], "w");
|
|
if (!output)
|
|
{
|
|
fclose(input);
|
|
fprintf(stderr, "Could not open output file '%s'\n", argv[2]);
|
|
return -1;
|
|
}
|
|
|
|
/* Read the DOS header */
|
|
if (fread(&header, 1, 2, input) != 2)
|
|
{
|
|
fprintf(stderr, "Error reading header.\n");
|
|
goto quit;
|
|
}
|
|
|
|
if (header[0] != 0x4d || header[1] != 0x5a)
|
|
{
|
|
fprintf(stderr, "Not a PE file.\n");
|
|
goto quit;
|
|
}
|
|
|
|
fseek(input, 0x3C, SEEK_SET);
|
|
if (fread(&e_lfanew, 1, 4, input) != 4)
|
|
{
|
|
fprintf(stderr, "Could not read e_lfanew.\n");
|
|
goto quit;
|
|
}
|
|
|
|
fseek(input, e_lfanew, SEEK_SET);
|
|
if (fread(&signature, 1, 4, input) != 4)
|
|
{
|
|
fprintf(stderr, "Could not read signature.\n");
|
|
goto quit;
|
|
}
|
|
|
|
/* Verify the PE signature */
|
|
if (signature != 0x4550)
|
|
{
|
|
fprintf(stderr, "Invalid signature: 0x%x.\n", signature);
|
|
goto quit;
|
|
}
|
|
|
|
/* Read Machine */
|
|
fseek(input, e_lfanew + 4, SEEK_SET);
|
|
if (fread(&Machine, 1, 2, input) != 2)
|
|
{
|
|
fprintf(stderr, "Could not read ExportDirectoryRVA.\n");
|
|
goto quit;
|
|
}
|
|
|
|
if ((Machine != IMAGE_FILE_MACHINE_I386) &&
|
|
(Machine != IMAGE_FILE_MACHINE_AMD64) &&
|
|
(Machine != IMAGE_FILE_MACHINE_ARMNT))
|
|
{
|
|
fprintf(stderr, "Invalid Machine: 0x%x.\n", Machine);
|
|
goto quit;
|
|
}
|
|
|
|
/* Read NumberOfSections */
|
|
if (fread(&NumberOfSections, 1, 2, input) != 2)
|
|
{
|
|
fprintf(stderr, "Could not read NumberOfSections.\n");
|
|
goto quit;
|
|
}
|
|
|
|
fseek(input, e_lfanew + 0x14, SEEK_SET);
|
|
if (fread(&SizeOfOptionalHeader, 1, 2, input) != 2)
|
|
{
|
|
fprintf(stderr, "Could not read SizeOfOptionalHeader.\n");
|
|
goto quit;
|
|
}
|
|
|
|
/* Read the section table */
|
|
fseek(input, e_lfanew + 0x18 + SizeOfOptionalHeader, SEEK_SET);
|
|
|
|
/* Search for the .asmdef section */
|
|
for (i = 0; i < NumberOfSections; i++)
|
|
{
|
|
if (fread(§ion, 1, sizeof(SECTION), input) != sizeof(SECTION))
|
|
{
|
|
fprintf(stderr, "Could not read section.\n");
|
|
goto quit;
|
|
}
|
|
|
|
if (strcmp(section.Name, ".asmdef") == 0)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i == NumberOfSections)
|
|
{
|
|
fprintf(stderr, "Could not find section.\n");
|
|
goto quit;
|
|
}
|
|
|
|
/* Read the section table */
|
|
fseek(input, section.RawAddress, SEEK_SET);
|
|
|
|
while (1)
|
|
{
|
|
/* Read one entry */
|
|
if (fread(&data, 1, sizeof(data), input) != sizeof(data))
|
|
{
|
|
fprintf(stderr, "Error reading input file.\n");
|
|
goto quit;
|
|
}
|
|
|
|
switch(data.Type)
|
|
{
|
|
case TYPE_END:
|
|
break;
|
|
|
|
case TYPE_RAW:
|
|
fprintf(output, "%s\n", data.Name);
|
|
continue;
|
|
|
|
case TYPE_CONSTANT:
|
|
if (ms_format)
|
|
{
|
|
if (Machine == IMAGE_FILE_MACHINE_ARMNT)
|
|
{
|
|
fprintf(output, "%s equ 0x%"PRIx64"\n", data.Name, data.Value);
|
|
}
|
|
else
|
|
{
|
|
fprintf(output, "%s equ 0%"PRIx64"h\n", data.Name, data.Value);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fprintf(output, "%s = 0x%"PRIx64"\n", data.Name, data.Value);
|
|
}
|
|
continue;
|
|
|
|
case TYPE_HEADER:
|
|
if (ms_format)
|
|
{
|
|
fprintf(output, "\n; %s\n", data.Name);
|
|
}
|
|
else
|
|
{
|
|
fprintf(output, "\n/* %s */\n", data.Name);
|
|
}
|
|
continue;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
result = 0;
|
|
|
|
quit:
|
|
/* Close files */
|
|
fclose(input);
|
|
fclose(output);
|
|
|
|
return result;
|
|
}
|