From 4b218387e78d34a11f946c7a1de4ca1ce168479a Mon Sep 17 00:00:00 2001 From: Kevin Lange Date: Fri, 29 Apr 2011 12:43:09 -0500 Subject: [PATCH] [sys] Various. --- kernel/core/syscall.c | 1 + loader/ld.c | 189 ++++++++++++++++++++++++++++++++++++++++++ util/readelf.c | 10 +++ 3 files changed, 200 insertions(+) create mode 100644 loader/ld.c diff --git a/kernel/core/syscall.c b/kernel/core/syscall.c index 61810d2b..a5f5326c 100644 --- a/kernel/core/syscall.c +++ b/kernel/core/syscall.c @@ -67,6 +67,7 @@ static int write(int fd, char * ptr, int len) { if (fd == 1 || fd == 2) { for (int i = 0; i < len; ++i) { ansi_put(ptr[i]); + serial_send(ptr[i]); } return len; } diff --git a/loader/ld.c b/loader/ld.c new file mode 100644 index 00000000..2192b045 --- /dev/null +++ b/loader/ld.c @@ -0,0 +1,189 @@ +/* + * ToAruOS Loader + * (C) 2011 Kevin Lange + */ + +#include +#include +#include + +/* The Master ELF Header */ +#include "../kernel/include/elf.h" + +/** + * Show usage for the readelf application. + * @param argc Argument count (unused) + * @param argv Arguments to binary + */ +void usage(int argc, char ** argv) { + /* Show usage */ + printf("%s [filename]\n", argv[0]); + printf("Loads a /static/ binary into memory and executes it.\n"); + exit(1); +} + +/** + * Application entry point. + * @returns 0 on sucess, 1 on failure + */ +int main(int argc, char ** argv) { + /* Process arguments */ + if (argc < 2) usage(argc,argv); + + FILE * binary; /**< File pointer for requested executable */ + size_t binary_size; /**< Size of the file */ + char * binary_buf; /**< Buffer to store the binary in memory */ + Elf32_Header * header; /**< ELF header */ + char * string_table[5]; /**< Room for some string tables */ + + /* Open the requested binary */ + binary = fopen(argv[1], "r"); + + /* Hack because we don't have seek/tell */ + char garbage[3]; + binary_size = 0; + while (fread((void *)&garbage, 1, 1, binary) != 0) { + ++binary_size; + } + printf("Binary is %u bytes.\n", binary_size); + fclose(binary); + binary = fopen(argv[1], "r"); + + /* Read the binary into a buffer */ + binary_buf = malloc(binary_size); + fread((void *)binary_buf, binary_size, 1, binary); + + /* Let's start considering this guy an elf, 'eh? */ + header = (Elf32_Header *)binary_buf; + + /* Verify the magic */ + if ( header->e_ident[0] != ELFMAG0 || + header->e_ident[1] != ELFMAG1 || + header->e_ident[2] != ELFMAG2 || + header->e_ident[3] != ELFMAG3) { + printf("Header magic is wrong!\n"); + printf("Are you sure this is a 32-bit ELF binary or object file?\n"); + return 1; + } + + /* Let's print out some of the header information, shall we? */ + printf("\033[1mELF Header\033[0m\n"); + + /* File type */ + printf("[Type %d] ", header->e_type); + switch (header->e_type) { + case ET_NONE: + printf("No file type.\n"); + break; + case ET_REL: + printf("Relocatable file.\n"); + break; + case ET_EXEC: + printf("Executable file.\n"); + break; + case ET_DYN: + printf("Shared object file.\n"); + break; + case ET_CORE: + printf("Core file.\n"); + break; + default: + printf("(Unknown file type)\n"); + break; + } + + /* Machine Type */ + switch (header->e_machine) { + case EM_386: + printf("Intel x86\n"); + break; + default: + printf("Unknown machine: %d\n", header->e_machine); + break; + } + + /* Version == EV_CURRENT? */ + if (header->e_version == EV_CURRENT) { + printf("ELF version is 1, as it should be.\n"); + } + + /* Entry point in memory */ + printf("Binary entry point in virtual memory is at 0x%x\n", header->e_entry); + + /* Program header table offset */ + printf("Program header table is at +0x%x and one entry is 0x%x bytes.\n" + "There are %d total program headers.\n", + header->e_phoff, header->e_phentsize, header->e_phnum); + + /* Section header table offset */ + printf("Section header table is at +0x%x and one entry is 0x%x bytes.\n" + "There are %d total section headers.\n", + header->e_shoff, header->e_shentsize, header->e_shnum); + + /* Read the program headers */ + printf("\033[1mProgram Headers\033[0m\n"); + for (uint32_t x = 0; x < header->e_phentsize * header->e_phnum; x += header->e_phentsize) { + if (header->e_phoff + x > binary_size) { + printf("Tried to read beyond the end of the file.\n"); + return 1; + } + /* Grab the program header */ + Elf32_Phdr * phdr = (Elf32_Phdr *)((uintptr_t)binary_buf + (header->e_phoff + x)); + + /* Print the header type */ + switch (phdr->p_type) { + case PT_LOAD: + printf("[Loadable Segment]\n"); + break; + case PT_DYNAMIC: + printf("[Dynamic Loading Information]\n"); + break; + case PT_INTERP: + printf("[Interpreter Path]\n"); + break; + default: + printf("[Unused Segement]\n"); + break; + } + } + + /* Find the (hopefully two) string tables */ + printf("\033[1mString Tables\033[0m\n"); + uint32_t i = 0; + for (uint32_t x = 0; x < header->e_shentsize * header->e_shnum; x += header->e_shentsize) { + if (header->e_shoff + x > binary_size) { + printf("Tried to read beyond the end of the file.\n"); + return 1; + } + Elf32_Shdr * shdr = (Elf32_Shdr *)((uintptr_t)binary_buf + (header->e_shoff + x)); + if (shdr->sh_type != SHT_STRTAB) continue; + string_table[i] = (char *)((uintptr_t)binary_buf + shdr->sh_offset); + printf("Found a string table at 0x%x\n", shdr->sh_offset); + ++i; + if (i == 5) break; + } + + /* Read the section headers */ + printf("\033[1mSection Headers\033[0m\n"); + for (uint32_t x = 0; x < header->e_shentsize * header->e_shnum; x += header->e_shentsize) { + if (header->e_shoff + x > binary_size) { + printf("Tried to read beyond the end of the file.\n"); + return 1; + } + Elf32_Shdr * shdr = (Elf32_Shdr *)((uintptr_t)binary_buf + (header->e_shoff + x)); + + printf("[%d] %s\n", shdr->sh_type, (char *)((uintptr_t)string_table[0] + shdr->sh_name)); + printf("Section starts at 0x%x and is 0x%x bytes long.\n", shdr->sh_offset, shdr->sh_size); + if (shdr->sh_addr) { + printf("It should be loaded at 0x%x.\n", shdr->sh_addr); + } + } + + return 0; +} + +/* + * vim:noexpandtab + * vim:tabstop=4 + * vim:shiftwidth=4 + */ diff --git a/util/readelf.c b/util/readelf.c index 85d82710..da8171d9 100644 --- a/util/readelf.c +++ b/util/readelf.c @@ -40,6 +40,7 @@ int main(int argc, char ** argv) { /* Open the requested binary */ binary = fopen(argv[1], "r"); +#if 0 /* Jump to the end so we can get the size */ fseek(binary, 0, SEEK_END); binary_size = ftell(binary); @@ -50,6 +51,15 @@ int main(int argc, char ** argv) { printf("Oh no! I don't quite like the size of this binary.\n"); return 1; } +#endif + char garbage[3]; + binary_size = 0; + while (fread((void *)&garbage, 1, 1, binary) != 0) { + ++binary_size; + } + printf("Binary is %d bytes.\n", binary_size); + fclose(binary); + binary = fopen(argv[1], "r"); /* Read the binary into a buffer */ binary_buf = malloc(binary_size);