diff --git a/sortix/elf.cpp b/sortix/elf.cpp index 3e92ee03..480112bf 100644 --- a/sortix/elf.cpp +++ b/sortix/elf.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include "elf.h" @@ -60,7 +61,11 @@ static int ToProgramSectionType(int flags) } } -addr_t Construct32(Process* process, const void* file, size_t filelen) +// TODO: This code doesn't respect that the size of program headers and section +// headers may vary depending on the ELF header and that using a simple +// table indexation isn't enough. + +addr_t Construct32(Process* process, const uint8_t* file, size_t filelen) { if ( filelen < sizeof(Header32) ) return 0; @@ -145,10 +150,71 @@ addr_t Construct32(Process* process, const void* file, size_t filelen) memset(memdest + pht->filesize, 0, pht->memorysize - pht->filesize); } + // Find the location of the section headers. + addr_t shtblpos = (addr_t) file + header->sectionheaderoffset; + const SectionHeader32* shtbl = (const SectionHeader32*) shtblpos; + + const SectionHeader32* section_names_section = shtbl + header->sectionheaderstringindex; + const char* section_names = (const char*) (file + section_names_section->offset); + + // Find the string table. + const SectionHeader32* string_table_section = NULL; + for ( size_t i = 0; i < header->numsectionheaderentries; i++ ) + if ( !strcmp(section_names + shtbl[i].name, ".strtab") ) + { + string_table_section = shtbl + i; + break; + } + + // Find the symbol table. + const SectionHeader32* symbol_table_section = NULL; + for ( size_t i = 0; i < header->numsectionheaderentries; i++ ) + if ( !strcmp(section_names + shtbl[i].name, ".symtab") ) + { + symbol_table_section = shtbl + i; + break; + } + + if ( !string_table_section || !symbol_table_section ) + return entry; + + // Prepare copying debug information. + const char* elf_string_table = (const char*) (file + string_table_section->offset); + size_t elf_string_table_size = string_table_section->size; + const Symbol32* elf_symbols = (const Symbol32*) (file + symbol_table_section->offset); + size_t elf_symbol_count = symbol_table_section->size / sizeof(Symbol32); + + // Duplicate the string table. + char* string_table = new char[elf_string_table_size]; + if ( !string_table ) + return entry; + memcpy(string_table, elf_string_table, elf_string_table_size); + + // Duplicate the symbol table. + Symbol* symbol_table = new Symbol[elf_symbol_count-1]; + if ( !symbol_table ) + { + delete[] string_table; + return entry; + } + + // Copy all entires except the leading null entry. + for ( size_t i = 1; i < elf_symbol_count; i++ ) + { + symbol_table[i-1].address = elf_symbols[i].st_value; + symbol_table[i-1].size = elf_symbols[i].st_size; + symbol_table[i-1].name = string_table + elf_symbols[i].st_name; + } + + process->string_table = string_table; + process->string_table_length = elf_string_table_size; + process->symbol_table = symbol_table; + process->symbol_table_length = elf_symbol_count-1; + return entry; } -addr_t Construct64(Process* process, const void* file, size_t filelen) +addr_t Construct64(Process* process, const uint8_t* file, size_t filelen) { #ifndef PLATFORM_X64 (void) process; @@ -241,6 +307,67 @@ addr_t Construct64(Process* process, const void* file, size_t filelen) memset(memdest + pht->filesize, 0, pht->memorysize - pht->filesize); } + // Find the location of the section headers. + addr_t shtblpos = (addr_t) file + header->sectionheaderoffset; + const SectionHeader64* shtbl = (const SectionHeader64*) shtblpos; + + const SectionHeader64* section_names_section = shtbl + header->sectionheaderstringindex; + const char* section_names = (const char*) (file + section_names_section->offset); + + // Find the string table. + const SectionHeader64* string_table_section = NULL; + for ( size_t i = 0; i < header->numsectionheaderentries; i++ ) + if ( !strcmp(section_names + shtbl[i].name, ".strtab") ) + { + string_table_section = shtbl + i; + break; + } + + // Find the symbol table. + const SectionHeader64* symbol_table_section = NULL; + for ( size_t i = 0; i < header->numsectionheaderentries; i++ ) + if ( !strcmp(section_names + shtbl[i].name, ".symtab") ) + { + symbol_table_section = shtbl + i; + break; + } + + if ( !string_table_section || !symbol_table_section ) + return entry; + + // Prepare copying debug information. + const char* elf_string_table = (const char*) (file + string_table_section->offset); + size_t elf_string_table_size = string_table_section->size; + const Symbol64* elf_symbols = (const Symbol64*) (file + symbol_table_section->offset); + size_t elf_symbol_count = symbol_table_section->size / sizeof(Symbol64); + + // Duplicate the string table. + char* string_table = new char[elf_string_table_size]; + if ( !string_table ) + return entry; + memcpy(string_table, elf_string_table, elf_string_table_size); + + // Duplicate the symbol table. + Symbol* symbol_table = new Symbol[elf_symbol_count-1]; + if ( !symbol_table ) + { + delete[] string_table; + return entry; + } + + // Copy all entires except the leading null entry. + for ( size_t i = 1; i < elf_symbol_count; i++ ) + { + symbol_table[i-1].address = elf_symbols[i].st_value; + symbol_table[i-1].size = elf_symbols[i].st_size; + symbol_table[i-1].name = string_table + elf_symbols[i].st_name; + } + + process->string_table = string_table; + process->string_table_length = elf_string_table_size; + process->symbol_table = symbol_table; + process->symbol_table_length = elf_symbol_count-1; + return entry; #endif } @@ -258,8 +385,8 @@ addr_t Construct(Process* process, const void* file, size_t filelen) switch ( header->fileclass ) { - case CLASS32: return Construct32(process, file, filelen); - case CLASS64: return Construct64(process, file, filelen); + case CLASS32: return Construct32(process, (const uint8_t*) file, filelen); + case CLASS64: return Construct64(process, (const uint8_t*) file, filelen); default: return 0; } diff --git a/sortix/elf.h b/sortix/elf.h index ed24448e..b3710495 100644 --- a/sortix/elf.h +++ b/sortix/elf.h @@ -178,12 +178,12 @@ struct Symbol32 struct Symbol64 { - uint32_t st_name; - uint8_t st_info; - uint8_t st_other; - uint16_t st_shndx; - uint64_t st_value; - uint64_t st_size; + uint32_t st_name; + uint8_t st_info; + uint8_t st_other; + uint16_t st_shndx; + uint64_t st_value; + uint64_t st_size; }; // Reads the elf file into the current address space and returns the entry diff --git a/sortix/include/sortix/kernel/process.h b/sortix/include/sortix/kernel/process.h index 276a22a7..91d0837f 100644 --- a/sortix/include/sortix/kernel/process.h +++ b/sortix/include/sortix/kernel/process.h @@ -48,6 +48,7 @@ struct ProcessSegment; struct ProcessTimer; struct ioctx_struct; typedef struct ioctx_struct ioctx_t; +struct Symbol; const int SEG_NONE = 0; const int SEG_TEXT = 1; @@ -88,6 +89,10 @@ private: static pid_t AllocatePID(); public: + char* string_table; + size_t string_table_length; + Symbol* symbol_table; + size_t symbol_table_length; char* program_image_path; addr_t addrspace; pid_t pid; diff --git a/sortix/process.cpp b/sortix/process.cpp index b4c9d2e2..941c0a55 100644 --- a/sortix/process.cpp +++ b/sortix/process.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -107,6 +108,10 @@ namespace Sortix Process::Process() { + string_table = NULL; + string_table_length = 0; + symbol_table = NULL; + symbol_table_length = 0; addrspace = 0; segments = NULL; parent = NULL; @@ -139,6 +144,8 @@ namespace Sortix Process::~Process() { + delete[] string_table; + delete[] symbol_table; if ( alarm_timer.IsAttached() ) alarm_timer.Detach(); if ( program_image_path ) @@ -280,6 +287,10 @@ namespace Sortix curthread); addrspace = 0; + // Unload the process symbol and string tables. + delete[] symbol_table; symbol_table = NULL; + delete[] string_table; string_table = NULL; + // Init is nice and will gladly raise our orphaned children and zombies. Process* init = Scheduler::GetInitProcess(); assert(init); @@ -618,6 +629,28 @@ namespace Sortix if ( !(clone->program_image_path = String::Clone(program_image_path)) ) failure = false; + if ( string_table && (clone->string_table = new char[string_table_length]) ) + { + memcpy(clone->string_table, string_table, string_table_length); + clone->string_table_length = string_table_length; + } + + if ( clone->string_table && symbol_table && + (clone->symbol_table = new Symbol[symbol_table_length]) ) + { + for ( size_t i = 0; i < symbol_table_length; i++ ) + { + clone->symbol_table[i].address = symbol_table[i].address; + clone->symbol_table[i].size = symbol_table[i].size; + clone->symbol_table[i].name = + (const char*)((uintptr_t) symbol_table[i].name - + (uintptr_t) string_table + + (uintptr_t) clone->string_table); + } + clone->symbol_table_length = symbol_table_length; + } + + if ( pid == 1) assert(dtable->Get(1)); @@ -640,6 +673,11 @@ namespace Sortix { // TODO: Delete all threads and their stacks. + string_table_length = 0; + symbol_table_length = 0; + delete[] string_table; string_table = NULL; + delete[] symbol_table; symbol_table = NULL; + DeleteTimers(); ResetAddressSpace();