Files
elf-viewer/elf_header.c
T

135 lines
3.1 KiB
C

#include "elf_header.h"
#include "elf_osabi.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");
}
if (bytes[EI_HEADER_VERSION] == 1) printf("ELF File Version: Current (1)\n");
else printf("ELF File Version: Invalid (%d)\n", bytes[EI_HEADER_VERSION]);
char buffer[255];
GetELFOSABIString(bytes[EI_OSABI], buffer);
printf("OS ABI: %s\n", buffer);
// 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;
}