From f888e03924f99402ed733f0f4ff9c05d9a80fb43 Mon Sep 17 00:00:00 2001 From: Garritt McCune Date: Tue, 2 Apr 2024 20:37:18 -0500 Subject: [PATCH] Added a bunch of enums for the ELF header. --- .gitignore | 1 + build.sh | 2 + futil.c | 64 +++++++++++++++ main.c | 223 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 289 insertions(+), 1 deletion(-) create mode 100755 build.sh create mode 100644 futil.c diff --git a/.gitignore b/.gitignore index 9c1e36a..4f48cc0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ *.o bin/* +.vscode/* diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..8faadeb --- /dev/null +++ b/build.sh @@ -0,0 +1,2 @@ +gcc -o main.o main.c +./main.o "$1" diff --git a/futil.c b/futil.c new file mode 100644 index 0000000..55374f2 --- /dev/null +++ b/futil.c @@ -0,0 +1,64 @@ +#include +#include +#include +#include + +#ifndef FUTIL_READ_SIZE +#define FUTIL_READ_SIZE 2097152 //Default here is 2MiB +#endif + +//Reference: https://stackoverflow.com/a/44894946 +int ReadAllString(const char* path, char** content_ptr, size_t* bytes_read) { + if (!path || !content_ptr || !bytes_read) return 0; + + FILE *file = fopen(path, "rb"); + + if (!file) { + fprintf(stderr, "Failed to open '%s'. %s.\n", path, strerror(errno)); + return 0; + } + + char *content = NULL, *temp = NULL; + size_t used = 0, capacity = 0, read = 0; + + while(1) { + if (used + FUTIL_READ_SIZE + 1 > capacity) { + capacity = used + FUTIL_READ_SIZE + 1; + + temp = realloc(content, capacity); + + if (!temp) { + fprintf(stderr, "Failed to realloc space for file contents. %s.\n", strerror(errno)); + free(content); + fclose(file); + return 0; + } + + content = temp; + } + + read = fread(content + used, 1, FUTIL_READ_SIZE, file); + + if (read == 0) break; + + used += read; + } + + fclose(file); + //Shrink the buffer to fit just the contents of the buffer. + temp = realloc(content, used + 1); + + if (!temp) { + fprintf(stderr, "Failed to realloc to only hold the file contents. %s.\n", strerror(errno)); + free(content); + return 0; + } + + content = temp; + content[used] = '\0'; + + *content_ptr = content; + *bytes_read = used; + + return 1; +} \ No newline at end of file diff --git a/main.c b/main.c index c4b8e9e..f7fef22 100644 --- a/main.c +++ b/main.c @@ -1,6 +1,227 @@ #include +#include "futil.c" + +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 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 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 +} ELFMachine; + +typedef enum ELFOSABI +{ + ELFOSABI_NONE = 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) { - printf("Hello, world!\n"); + char* bytes; + size_t size; + + if (argc != 2) + { + printf("No argcs\n"); + 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' }; + + if (strcmp(magic, "\x7f""ELF") != 0) + { + fprintf(stderr, "Failed to find ELF magic number in file header.\n"); + + return 0; + } + else printf("Magic ELF number found!\n"); + + switch(bytes[EI_CLASS]) + { + case ELFClass32: + printf("32-bit object detected\n"); + break; + case ELFClass64: + printf("64-bit object detected\n"); + break; + default: + printf("Invalid class type detected\n"); + return 1; + } + + switch(bytes[EI_DATA]) + { + case ELFDataLSB: + printf("2's complement, little endian.\n"); + break; + case ELFDataMSB: + printf("2's complement, big endian.\n"); + break; + default: + printf("Unknown byte order\n"); + return 1; + } + + if (bytes[EI_VERSION] == 1) printf("Version: current\n"); + else printf("Invalid version number\n"); + + switch(bytes[EI_OSABI]) + { + case ELFOSABI_NONE: + printf("No extension or unspecified OS 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]); + + switch(bytes[EI_NIDENT] + bytes[EI_NIDENT + 1]) + { + case ET_None: + printf("No file type\n"); + break; + case ET_Rel: + printf("Rel\n"); + break; + case ET_Exec: + printf("Exec\n"); + break; + case ET_Dyn: + printf("File type is 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 + 2] + bytes[EI_NIDENT + 3]) { + case EM_860: + printf("Intel 80860\n"); + break; + default: + fprintf(stderr, "Failed to identify machine type\n"); + return 1; + } + + printf("Read %ld bytes from file '%s'\n", size, argv[1]); } \ No newline at end of file