125 lines
2.9 KiB
C
125 lines
2.9 KiB
C
#include "elf_header.h"
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#define ELF_IDENTITIFCATION_MAX_SIZE 16
|
|
#define ELF_CLASS_TYPE32 1
|
|
#define ELF_CLASS_TYPE64 2
|
|
|
|
#define ELF_BYTE_ORDER_LSB 1
|
|
#define ELF_BYTE_ORDER_MSB 2
|
|
|
|
typedef enum EIdent
|
|
{
|
|
EI_MAG0 = 0, //Magic number position zero - three.
|
|
EI_MAG1 = 1,
|
|
EI_MAG2 = 2,
|
|
EI_MAG3 = 3,
|
|
EI_CLASS = 4,
|
|
EI_DATA = 5,
|
|
EI_HEADER_VERSION = 6,
|
|
EI_OSABI = 7,
|
|
EI_ABIVERSION = 8,
|
|
EI_PAD = 9,
|
|
EI_NIDENT = ELF_IDENTITIFCATION_MAX_SIZE - 1, //End of reserved 16 bytes for the header.
|
|
EI_TYPE = EI_NIDENT + 1,
|
|
EI_MACHINE = EI_TYPE + 2,
|
|
EI_OBJECT_FILE_VERSION = EI_MACHINE + 2,
|
|
EI_ENTRY_ADDRESS_POINT = EI_OBJECT_FILE_VERSION + 4
|
|
} ELFIdentOffsets;
|
|
|
|
struct elf_header {
|
|
unsigned char Identitication[ELF_IDENTITIFCATION_MAX_SIZE];
|
|
uint32_t FileType;
|
|
uint32_t ISA;
|
|
uint32_t ELFVersion;
|
|
uint64_t EntryAddress;
|
|
uint64_t ProgramHeaderOffset;
|
|
uint64_t SectionHeaderOffset;
|
|
uint32_t Flags;
|
|
};
|
|
|
|
struct elf_header* CreateELFHeader(void);
|
|
int ELFMagicNumberValid(const unsigned char* ident);
|
|
void ELFPrintMagic(const struct elf_header* header);
|
|
|
|
struct elf_header* ParseObjectFile(const char* bytes, size_t count) {
|
|
if (count < 0x40) return NULL;
|
|
|
|
struct elf_header* header = CreateELFHeader();
|
|
|
|
memcpy(header, bytes, ELF_IDENTITIFCATION_MAX_SIZE);
|
|
|
|
if (!ELFMagicNumberValid(header->Identitication))
|
|
{
|
|
fprintf(stderr, "Failed to find ELF magic number in file header.\n");
|
|
ELFPrintMagic(header);
|
|
printf("\n");
|
|
|
|
return NULL;
|
|
}
|
|
|
|
switch(bytes[EI_CLASS])
|
|
{
|
|
case ELF_CLASS_TYPE32:
|
|
memcpy(&header->EntryAddress, &bytes[EI_ENTRY_ADDRESS_POINT], sizeof(int32_t));
|
|
break;
|
|
case ELF_CLASS_TYPE64:
|
|
memcpy(&header->EntryAddress, &bytes[EI_ENTRY_ADDRESS_POINT], sizeof(int64_t));
|
|
break;
|
|
default:
|
|
header->EntryAddress = -1;
|
|
}
|
|
|
|
switch(bytes[EI_DATA])
|
|
{
|
|
case ELF_BYTE_ORDER_LSB:
|
|
printf("Data: 2's complement, little endian.\n");
|
|
break;
|
|
case ELF_BYTE_ORDER_MSB:
|
|
printf("Data: 2's complement, big endian.\n");
|
|
break;
|
|
default:
|
|
printf("Data: Unknown byte order\n");
|
|
}
|
|
|
|
// int64_t entryAddress;
|
|
|
|
// memcpy(&entryAddress, &bytes[EI_ENTRY_ADDRESS_POINT], sizeof(int64_t));
|
|
|
|
// printf("Entry point address: %#06lx\n", entryAddress);
|
|
|
|
return header;
|
|
}
|
|
|
|
int ELFMagicNumberValid(const unsigned char* ident) {
|
|
char magic[5] = { ident[EI_MAG0], ident[EI_MAG1], ident[EI_MAG2], ident[EI_MAG3], '\0' };
|
|
|
|
return strcmp(magic, "\x7f""ELF") == 0;
|
|
}
|
|
|
|
void ELFPrintMagic(const struct elf_header* header) {
|
|
if (!header) return;
|
|
|
|
printf("Magic: ");
|
|
|
|
for(int i = 0; i < ELF_IDENTITIFCATION_MAX_SIZE; i++)
|
|
{
|
|
printf("%02X ", header->Identitication[i]);
|
|
}
|
|
|
|
printf("\n");
|
|
}
|
|
|
|
struct elf_header* CreateELFHeader(void) {
|
|
struct elf_header* header = calloc(sizeof(struct elf_header), 1);
|
|
|
|
if (!header)
|
|
{
|
|
fprintf(stderr, "Failed to calloc\n");
|
|
|
|
exit(1);
|
|
}
|
|
|
|
return header;
|
|
} |