Started to break out the parsing of the file's bytes into seperate files.

This commit is contained in:
2024-04-09 22:47:40 -05:00
parent f8374cb026
commit b40418d357
4 changed files with 400 additions and 207 deletions
+1 -1
View File
@@ -1,2 +1,2 @@
gcc -o main.o main.c gcc -o main.o elf_header.c main.c -g -Wall -DDEBUG -Wpedantic -Wextra -Wunused-result -std=c99 -pedantic-errors
./main.o "$1" ./main.o "$1"
+125
View File
@@ -0,0 +1,125 @@
#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;
}
+58
View File
@@ -0,0 +1,58 @@
#ifndef ELF_HEADER_H
#define ELF_HEADER_H
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
typedef struct elf_header ELFHeader;
ELFHeader* ParseObjectFile(const char* bytes, size_t size);
typedef enum ELFType{
ET_None = 0, //No file type
ET_Rel = 1, //Relocatable file
ET_Exec = 2, //Executable file
ET_Dyn = 3, //Shared object file
ET_Core = 4, //Core file
ET_LOProc = 0xff00, //Processor
ET_HIProc = 0xffff //Specific
} ELFType;
typedef enum ELFMachine
{
EM_None = 0,
EM_M32 = 1, //AT&T WE 32100
EM_Sparc = 2,
EM_386 = 3,
EM_68k = 4,
EM_88k = 5,
EM_860 = 7,
EM_MIPS = 8,
EM_X86_64 = 62
} ELFMachine;
typedef enum ELFOSABI
{
ELFOSABI_SYSTEMV = 0,
ELFOSABI_HPUX = 1,
ELFOSABI_NETBSD = 2,
ELFOSABI_GNU = 3,
ELFOSABI_LINUX = 3,
ELFOSABI_SOLARIS = 6,
ELFOSABI_AIX,
ELFOSABI_IRIX,
ELFOSABI_FREEBSD,
ELFOSABI_TRU64,
ELFOSABI_MODESTO,
ELFOSABI_OPENBSD,
ELFOSABI_OPENVMS,
ELFOSABI_NSK,
ELFOSABI_AROS,
ELFOSABI_FENIXOS,
ELFOSABI_CLOUDABI,
ELFOSABI_OPENVOS
} ELFOSABI;
#endif
+216 -206
View File
@@ -1,84 +1,87 @@
#include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include "futil.c" #include "futil.c"
#include "elf_header.h"
// 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_VERSION = 6,
// EI_OSABI = 7,
// EI_ABIVERSION = 8,
// EI_PAD = 9,
// EI_NIDENT = 16 //End of reserved 16 bytes for the header.
// } EIdent;
typedef enum EIdent // typedef enum EIClass
{ // {
EI_MAG0 = 0, //Magic number position zero - three. // ELFClassNone = 0,
EI_MAG1 = 1, // ELFClass32 = 1,
EI_MAG2 = 2, // ELFClass64 = 2
EI_MAG3 = 3, // } EIClass;
EI_CLASS = 4,
EI_DATA = 5,
EI_VERSION = 6,
EI_OSABI = 7,
EI_ABIVERSION = 8,
EI_PAD = 9,
EI_NIDENT = 16 //End of reserved 16 bytes for the header.
} EIdent;
typedef enum EIClass // typedef enum EI_Data
{ // {
ELFClassNone = 0, // ELFDataNone = 0,
ELFClass32 = 1, // ELFDataLSB = 1,
ELFClass64 = 2 // ELFDataMSB = 2
} EIClass; // } EIData;
typedef enum EI_Data // typedef enum ELFType{
{ // ET_None = 0, //No file type
ELFDataNone = 0, // ET_Rel = 1, //Relocatable file
ELFDataLSB = 1, // ET_Exec = 2, //Executable file
ELFDataMSB = 2 // ET_Dyn = 3, //Shared object file
} EIData; // ET_Core = 4, //Core file
// ET_LOProc = 0xff00, //Processor
// ET_HIProc = 0xffff //Specific
// } ELFType;
typedef enum ELFType{ // typedef enum ELFMachine
ET_None = 0, //No file type // {
ET_Rel = 1, //Relocatable file // EM_None = 0,
ET_Exec = 2, //Executable file // EM_M32 = 1, //AT&T WE 32100
ET_Dyn = 3, //Shared object file // EM_Sparc = 2,
ET_Core = 4, //Core file // EM_386 = 3,
ET_LOProc = 0xff00, //Processor // EM_68k = 4,
ET_HIProc = 0xffff //Specific // EM_88k = 5,
} ELFType; // EM_860 = 7,
// EM_MIPS = 8,
// EM_X86_64 = 62
// } ELFMachine;
typedef enum ELFMachine // typedef enum ELFOSABI
{ // {
EM_None = 0, // ELFOSABI_SYSTEMV = 0,
EM_M32 = 1, //AT&T WE 32100 // ELFOSABI_HPUX = 1,
EM_Sparc = 2, // ELFOSABI_NETBSD = 2,
EM_386 = 3, // ELFOSABI_GNU = 3,
EM_68k = 4, // ELFOSABI_LINUX = 3,
EM_88k = 5, // ELFOSABI_SOLARIS = 6,
EM_860 = 7, // ELFOSABI_AIX,
EM_MIPS = 8, // ELFOSABI_IRIX,
EM_X86_64 = 62 // ELFOSABI_FREEBSD,
} ELFMachine; // ELFOSABI_TRU64,
// ELFOSABI_MODESTO,
typedef enum ELFOSABI // ELFOSABI_OPENBSD,
{ // ELFOSABI_OPENVMS,
ELFOSABI_SYSTEMV = 0, // ELFOSABI_NSK,
ELFOSABI_HPUX = 1, // ELFOSABI_AROS,
ELFOSABI_NETBSD = 2, // ELFOSABI_FENIXOS,
ELFOSABI_GNU = 3, // ELFOSABI_CLOUDABI,
ELFOSABI_LINUX = 3, // ELFOSABI_OPENVOS
ELFOSABI_SOLARIS = 6, // } ELFOSABI;
ELFOSABI_AIX,
ELFOSABI_IRIX,
ELFOSABI_FREEBSD,
ELFOSABI_TRU64,
ELFOSABI_MODESTO,
ELFOSABI_OPENBSD,
ELFOSABI_OPENVMS,
ELFOSABI_NSK,
ELFOSABI_AROS,
ELFOSABI_FENIXOS,
ELFOSABI_CLOUDABI,
ELFOSABI_OPENVOS
} ELFOSABI;
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
char* bytes; char* bytes;
size_t size; size_t size;
//int64_t entryAddress;
if (argc != 2) if (argc != 2)
{ {
@@ -88,158 +91,165 @@ int main(int argc, char** argv)
if (!ReadAllString(argv[1], &bytes, &size)) return 0; if (!ReadAllString(argv[1], &bytes, &size)) return 0;
char magic[5] = { bytes[EI_MAG0], bytes[EI_MAG1], bytes[EI_MAG2], bytes[EI_MAG3], '\0' }; ParseObjectFile(bytes, size);
// char magic[5] = { bytes[EI_MAG0], bytes[EI_MAG1], bytes[EI_MAG2], bytes[EI_MAG3], '\0' };
if (strcmp(magic, "\x7f""ELF") != 0) // if (strcmp(magic, "\x7f""ELF") != 0)
{ // {
fprintf(stderr, "Failed to find ELF magic number in file header.\n"); // fprintf(stderr, "Failed to find ELF magic number in file header.\n");
return 0; // return 0;
} // }
printf("Magic: "); // printf("Magic: ");
for(int i = 0; i < EI_NIDENT; i++) // for(int i = 0; i < EI_NIDENT; i++)
{ // {
printf("%02X ", bytes[i]); // printf("%02X ", bytes[i]);
} // }
printf("\n"); // printf("\n");
switch(bytes[EI_CLASS]) // switch(bytes[EI_CLASS])
{ // {
case ELFClass32: // case ELFClass32:
printf("Class: 32-bit object\n");
break; // printf("Class: 32-bit object\n");
case ELFClass64: // break;
printf("Class: 64-bit object\n"); // case ELFClass64:
break; // memcpy(&entryAddress, &bytes[0x18], sizeof(int64_t));//bytes[0x18];
default: // printf("Class: 64-bit object\n");
printf("Class: Invalid\n"); // break;
return 1; // default:
} // printf("Class: Invalid\n");
// return 1;
// }
switch(bytes[EI_DATA]) // switch(bytes[EI_DATA])
{ // {
case ELFDataLSB: // case ELFDataLSB:
printf("Data: 2's complement, little endian.\n"); // printf("Data: 2's complement, little endian.\n");
break; // break;
case ELFDataMSB: // case ELFDataMSB:
printf("Data: 2's complement, big endian.\n"); // printf("Data: 2's complement, big endian.\n");
break; // break;
default: // default:
printf("Data: Unknown byte order\n"); // printf("Data: Unknown byte order\n");
return 1; // return 1;
} // }
if (bytes[EI_VERSION] == 1) printf("Version: 1 (Current)\n"); // if (bytes[EI_VERSION] == 1) printf("Version: 1 (Current)\n");
else printf("Version: 0 (Invalid)\n"); // else printf("Version: 0 (Invalid)\n");
printf("OS/ABI: "); // printf("OS/ABI: ");
switch(bytes[EI_OSABI]) // switch(bytes[EI_OSABI])
{ // {
case ELFOSABI_SYSTEMV: // case ELFOSABI_SYSTEMV:
printf("System V ABI\n"); // printf("System V ABI\n");
break; // break;
case ELFOSABI_HPUX: // case ELFOSABI_HPUX:
printf("Hewlett-Packard HP-UX ABI\n"); // printf("Hewlett-Packard HP-UX ABI\n");
break; // break;
case ELFOSABI_NETBSD: // case ELFOSABI_NETBSD:
printf("NetBSD ABI\n"); // printf("NetBSD ABI\n");
break; // break;
case ELFOSABI_LINUX: // case ELFOSABI_LINUX:
printf("GNU ABI\n"); // printf("GNU ABI\n");
break; // break;
case ELFOSABI_SOLARIS: // case ELFOSABI_SOLARIS:
printf("Sun Solaris ABI\n"); // printf("Sun Solaris ABI\n");
break; // break;
case ELFOSABI_AIX: // case ELFOSABI_AIX:
printf("AIX ABI\n"); // printf("AIX ABI\n");
break; // break;
case ELFOSABI_IRIX: // case ELFOSABI_IRIX:
printf("IRIX ABI\n"); // printf("IRIX ABI\n");
break; // break;
case ELFOSABI_FREEBSD: // case ELFOSABI_FREEBSD:
printf("FreeBSd ABI\n"); // printf("FreeBSd ABI\n");
break; // break;
case ELFOSABI_TRU64: // case ELFOSABI_TRU64:
printf("Compaq TRU64 UNIX ABI\n"); // printf("Compaq TRU64 UNIX ABI\n");
break; // break;
case ELFOSABI_MODESTO: // case ELFOSABI_MODESTO:
printf("Novell Modesto ABI\n"); // printf("Novell Modesto ABI\n");
break; // break;
case ELFOSABI_OPENBSD: // case ELFOSABI_OPENBSD:
printf("OpenBSD ABI\n"); // printf("OpenBSD ABI\n");
break; // break;
case ELFOSABI_OPENVMS: // case ELFOSABI_OPENVMS:
printf("Open VMS ABI\n"); // printf("Open VMS ABI\n");
break; // break;
case ELFOSABI_NSK: // case ELFOSABI_NSK:
printf("Hewlett-Packard Non-Stop Kernel ABI\n"); // printf("Hewlett-Packard Non-Stop Kernel ABI\n");
break; // break;
case ELFOSABI_AROS: // case ELFOSABI_AROS:
printf("Amiga Research OS ABI\n"); // printf("Amiga Research OS ABI\n");
break; // break;
case ELFOSABI_FENIXOS: // case ELFOSABI_FENIXOS:
printf("The FenixOS highly scalable multi-core OS ABI\n"); // printf("The FenixOS highly scalable multi-core OS ABI\n");
break; // break;
case ELFOSABI_CLOUDABI: // case ELFOSABI_CLOUDABI:
printf("Nuxi CloudABI ABI\n"); // printf("Nuxi CloudABI ABI\n");
break; // break;
case ELFOSABI_OPENVOS: // case ELFOSABI_OPENVOS:
printf("Stratus Technologies OpenVOS ABI\n"); // printf("Stratus Technologies OpenVOS ABI\n");
break; // break;
default: // default:
printf("Reserved ABI (%d)\n", bytes[EI_ABIVERSION]); // printf("Reserved ABI (%d)\n", bytes[EI_ABIVERSION]);
break; // break;
} // }
printf("ABI Version: %d\n", bytes[EI_ABIVERSION]); // printf("ABI Version: %d\n", bytes[EI_ABIVERSION]);
printf("Type: "); // printf("Type: ");
switch(bytes[EI_NIDENT] + bytes[EI_NIDENT + 1]) // switch(bytes[EI_NIDENT] + bytes[EI_NIDENT + 1])
{ // {
case ET_None: // case ET_None:
printf("None\n"); // printf("None\n");
break; // break;
case ET_Rel: // case ET_Rel:
printf("Rel\n"); // printf("Rel\n");
break; // break;
case ET_Exec: // case ET_Exec:
printf("Exec\n"); // printf("Exec\n");
break; // break;
case ET_Dyn: // case ET_Dyn:
printf("DYN (Position-Independent Executable file)\n"); // printf("DYN (Position-Independent Executable file)\n");
break; // break;
case ET_Core: // case ET_Core:
printf("Core\n"); // printf("Core\n");
break; // break;
case ET_LOProc: // case ET_LOProc:
printf("LO\n"); // printf("LO\n");
break; // break;
case ET_HIProc: // case ET_HIProc:
printf("HI\n"); // printf("HI\n");
break; // break;
default: // default:
fprintf(stderr, "Unknown file type\n"); // fprintf(stderr, "Unknown file type\n");
return 1; // return 1;
} // }
printf("Machine: "); // printf("Machine: ");
switch (bytes[EI_NIDENT + 2] + bytes[EI_NIDENT + 3]) { // switch (bytes[EI_NIDENT + 2] + bytes[EI_NIDENT + 3]) {
case EM_860: // case EM_860:
printf("Intel 80860\n"); // printf("Intel 80860\n");
break; // break;
case EM_X86_64: // case EM_X86_64:
printf("AMD x86-64 architecture\n"); // printf("AMD x86-64 architecture\n");
break; // break;
default: // default:
fprintf(stderr, "Failed to identify machine type\n"); // fprintf(stderr, "Failed to identify machine type\n");
return 1; // return 1;
} // }
// printf("Version: %#04x\n", bytes[EI_NIDENT + 4] + bytes[EI_NIDENT + 5]);
// printf("Entry point address: %#06lX\n", entryAddress);
printf("Read %ld bytes from file '%s'\n", size, argv[1]); printf("Read %ld bytes from file '%s'\n", size, argv[1]);
} }