diff --git a/build.sh b/build.sh index 8faadeb..de1ffb9 100755 --- a/build.sh +++ b/build.sh @@ -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" diff --git a/elf_header.c b/elf_header.c new file mode 100644 index 0000000..53c054a --- /dev/null +++ b/elf_header.c @@ -0,0 +1,125 @@ +#include "elf_header.h" +#include +#include + +#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; +} \ No newline at end of file diff --git a/elf_header.h b/elf_header.h new file mode 100644 index 0000000..99b9e12 --- /dev/null +++ b/elf_header.h @@ -0,0 +1,58 @@ +#ifndef ELF_HEADER_H +#define ELF_HEADER_H + +#include +#include +#include +#include + +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 \ No newline at end of file diff --git a/main.c b/main.c index f503dfc..46e26e8 100644 --- a/main.c +++ b/main.c @@ -1,84 +1,87 @@ +#include #include +#include #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 -{ - 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 EIClass +// { +// ELFClassNone = 0, +// ELFClass32 = 1, +// ELFClass64 = 2 +// } EIClass; -typedef enum EIClass -{ - ELFClassNone = 0, - ELFClass32 = 1, - ELFClass64 = 2 -} EIClass; +// typedef enum EI_Data +// { +// ELFDataNone = 0, +// ELFDataLSB = 1, +// ELFDataMSB = 2 +// } EIData; -typedef enum EI_Data -{ - ELFDataNone = 0, - ELFDataLSB = 1, - ELFDataMSB = 2 -} EIData; +// 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 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 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; +// 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; int main(int argc, char** argv) { char* bytes; size_t size; + //int64_t entryAddress; if (argc != 2) { @@ -88,158 +91,165 @@ int main(int argc, char** argv) 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) - { - fprintf(stderr, "Failed to find ELF magic number in file header.\n"); + // if (strcmp(magic, "\x7f""ELF") != 0) + // { + // 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++) - { - printf("%02X ", bytes[i]); - } + // for(int i = 0; i < EI_NIDENT; i++) + // { + // printf("%02X ", bytes[i]); + // } - printf("\n"); + // printf("\n"); - switch(bytes[EI_CLASS]) - { - case ELFClass32: - printf("Class: 32-bit object\n"); - break; - case ELFClass64: - printf("Class: 64-bit object\n"); - break; - default: - printf("Class: Invalid\n"); - return 1; - } + // switch(bytes[EI_CLASS]) + // { + // case ELFClass32: + + // printf("Class: 32-bit object\n"); + // break; + // case ELFClass64: + // memcpy(&entryAddress, &bytes[0x18], sizeof(int64_t));//bytes[0x18]; + // printf("Class: 64-bit object\n"); + // break; + // default: + // printf("Class: Invalid\n"); + // return 1; + // } - switch(bytes[EI_DATA]) - { - case ELFDataLSB: - printf("Data: 2's complement, little endian.\n"); - break; - case ELFDataMSB: - printf("Data: 2's complement, big endian.\n"); - break; - default: - printf("Data: Unknown byte order\n"); - return 1; - } + // switch(bytes[EI_DATA]) + // { + // case ELFDataLSB: + // printf("Data: 2's complement, little endian.\n"); + // break; + // case ELFDataMSB: + // printf("Data: 2's complement, big endian.\n"); + // break; + // default: + // printf("Data: Unknown byte order\n"); + // return 1; + // } - if (bytes[EI_VERSION] == 1) printf("Version: 1 (Current)\n"); - else printf("Version: 0 (Invalid)\n"); + // if (bytes[EI_VERSION] == 1) printf("Version: 1 (Current)\n"); + // else printf("Version: 0 (Invalid)\n"); - printf("OS/ABI: "); + // printf("OS/ABI: "); - switch(bytes[EI_OSABI]) - { - case ELFOSABI_SYSTEMV: - printf("System V ABI\n"); - break; - case ELFOSABI_HPUX: - printf("Hewlett-Packard HP-UX ABI\n"); - break; - case ELFOSABI_NETBSD: - printf("NetBSD ABI\n"); - break; - case ELFOSABI_LINUX: - printf("GNU ABI\n"); - break; - case ELFOSABI_SOLARIS: - printf("Sun Solaris ABI\n"); - break; - case ELFOSABI_AIX: - printf("AIX ABI\n"); - break; - case ELFOSABI_IRIX: - printf("IRIX ABI\n"); - break; - case ELFOSABI_FREEBSD: - printf("FreeBSd ABI\n"); - break; - case ELFOSABI_TRU64: - printf("Compaq TRU64 UNIX ABI\n"); - break; - case ELFOSABI_MODESTO: - printf("Novell Modesto ABI\n"); - break; - case ELFOSABI_OPENBSD: - printf("OpenBSD ABI\n"); - break; - case ELFOSABI_OPENVMS: - printf("Open VMS ABI\n"); - break; - case ELFOSABI_NSK: - printf("Hewlett-Packard Non-Stop Kernel ABI\n"); - break; - case ELFOSABI_AROS: - printf("Amiga Research OS ABI\n"); - break; - case ELFOSABI_FENIXOS: - printf("The FenixOS highly scalable multi-core OS ABI\n"); - break; - case ELFOSABI_CLOUDABI: - printf("Nuxi CloudABI ABI\n"); - break; - case ELFOSABI_OPENVOS: - printf("Stratus Technologies OpenVOS ABI\n"); - break; - default: - printf("Reserved ABI (%d)\n", bytes[EI_ABIVERSION]); - break; - } + // switch(bytes[EI_OSABI]) + // { + // case ELFOSABI_SYSTEMV: + // printf("System V ABI\n"); + // break; + // case ELFOSABI_HPUX: + // printf("Hewlett-Packard HP-UX ABI\n"); + // break; + // case ELFOSABI_NETBSD: + // printf("NetBSD ABI\n"); + // break; + // case ELFOSABI_LINUX: + // printf("GNU ABI\n"); + // break; + // case ELFOSABI_SOLARIS: + // printf("Sun Solaris ABI\n"); + // break; + // case ELFOSABI_AIX: + // printf("AIX ABI\n"); + // break; + // case ELFOSABI_IRIX: + // printf("IRIX ABI\n"); + // break; + // case ELFOSABI_FREEBSD: + // printf("FreeBSd ABI\n"); + // break; + // case ELFOSABI_TRU64: + // printf("Compaq TRU64 UNIX ABI\n"); + // break; + // case ELFOSABI_MODESTO: + // printf("Novell Modesto ABI\n"); + // break; + // case ELFOSABI_OPENBSD: + // printf("OpenBSD ABI\n"); + // break; + // case ELFOSABI_OPENVMS: + // printf("Open VMS ABI\n"); + // break; + // case ELFOSABI_NSK: + // printf("Hewlett-Packard Non-Stop Kernel ABI\n"); + // break; + // case ELFOSABI_AROS: + // printf("Amiga Research OS ABI\n"); + // break; + // case ELFOSABI_FENIXOS: + // printf("The FenixOS highly scalable multi-core OS ABI\n"); + // break; + // case ELFOSABI_CLOUDABI: + // printf("Nuxi CloudABI ABI\n"); + // break; + // case ELFOSABI_OPENVOS: + // printf("Stratus Technologies OpenVOS ABI\n"); + // break; + // default: + // printf("Reserved ABI (%d)\n", bytes[EI_ABIVERSION]); + // 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]) - { - case ET_None: - printf("None\n"); - break; - case ET_Rel: - printf("Rel\n"); - break; - case ET_Exec: - printf("Exec\n"); - break; - case ET_Dyn: - printf("DYN (Position-Independent Executable file)\n"); - break; - case ET_Core: - printf("Core\n"); - break; - case ET_LOProc: - printf("LO\n"); - break; - case ET_HIProc: - printf("HI\n"); - break; - default: - fprintf(stderr, "Unknown file type\n"); - return 1; - } + // switch(bytes[EI_NIDENT] + bytes[EI_NIDENT + 1]) + // { + // case ET_None: + // printf("None\n"); + // break; + // case ET_Rel: + // printf("Rel\n"); + // break; + // case ET_Exec: + // printf("Exec\n"); + // break; + // case ET_Dyn: + // printf("DYN (Position-Independent Executable file)\n"); + // break; + // case ET_Core: + // printf("Core\n"); + // break; + // case ET_LOProc: + // printf("LO\n"); + // break; + // case ET_HIProc: + // printf("HI\n"); + // break; + // default: + // fprintf(stderr, "Unknown file type\n"); + // return 1; + // } - printf("Machine: "); + // printf("Machine: "); - switch (bytes[EI_NIDENT + 2] + bytes[EI_NIDENT + 3]) { - case EM_860: - printf("Intel 80860\n"); - break; - case EM_X86_64: - printf("AMD x86-64 architecture\n"); - break; - default: - fprintf(stderr, "Failed to identify machine type\n"); - return 1; - } + // switch (bytes[EI_NIDENT + 2] + bytes[EI_NIDENT + 3]) { + // case EM_860: + // printf("Intel 80860\n"); + // break; + // case EM_X86_64: + // printf("AMD x86-64 architecture\n"); + // break; + // default: + // fprintf(stderr, "Failed to identify machine type\n"); + // 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]); } \ No newline at end of file