diff --git a/sortix/Makefile b/sortix/Makefile index 0d8041f5..f89ba975 100644 --- a/sortix/Makefile +++ b/sortix/Makefile @@ -122,6 +122,7 @@ serialterminal.o \ signal.o \ sound.o \ string.o \ +symbol.o \ syscall.o \ textbuffer.o \ textterminal.o \ diff --git a/sortix/elf.h b/sortix/elf.h index fbd3ffc5..033c88aa 100644 --- a/sortix/elf.h +++ b/sortix/elf.h @@ -166,6 +166,26 @@ namespace Sortix const uint32_t PF_W = (1<<1); const uint32_t PF_R = (1<<2); + struct Symbol32 + { + uint32_t st_name; + uint32_t st_value; + uint32_t st_size; + uint8_t st_info; + uint8_t st_other; + uint16_t st_shndx; + }; + + 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; + }; + // Reads the elf file into the current address space and returns the // entry address of the program, or 0 upon failure. addr_t Construct(Process* process, const void* file, size_t filelen); diff --git a/sortix/include/sortix/kernel/symbol.h b/sortix/include/sortix/kernel/symbol.h new file mode 100644 index 00000000..30376dae --- /dev/null +++ b/sortix/include/sortix/kernel/symbol.h @@ -0,0 +1,49 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2013. + + This file is part of Sortix. + + Sortix is free software: you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation, either version 3 of the License, or (at your option) any later + version. + + Sortix is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + details. + + You should have received a copy of the GNU General Public License along with + Sortix. If not, see . + + sortix/kernel/symbol.h + Symbol table declarations. + +*******************************************************************************/ + +#ifndef INCLUDE_SORTIX_KERNEL_SYMBOL_H +#define INCLUDE_SORTIX_KERNEL_SYMBOL_H + +namespace Sortix { + +struct Symbol +{ + uintptr_t address; + size_t size; + const char* name; +}; + +void SetKernelSymbolTable(Symbol* table, size_t length); +const Symbol* GetKernelSymbolTable(size_t* length = NULL); +const Symbol* GetKernelSymbol(uintptr_t address); + +static inline const char* GetKernelSymbolName(uintptr_t address) +{ + const Symbol* symbol = GetKernelSymbol(address); + return symbol ? symbol->name : NULL; +} + +} // namespace Sortix + +#endif diff --git a/sortix/kernel.cpp b/sortix/kernel.cpp index f00453d6..eed2153e 100644 --- a/sortix/kernel.cpp +++ b/sortix/kernel.cpp @@ -49,6 +49,7 @@ #include #include #include +#include #include #include @@ -243,6 +244,114 @@ extern "C" void KernelInit(unsigned long magic, multiboot_info_t* bootinfo) // Initialize the kernel heap. _init_heap(); + // Load the kernel symbols if provided by the bootloader. + do if ( bootinfo->flags & MULTIBOOT_INFO_ELF_SHDR ) + { + // On i386 and x86_64 we identity map the first 4 MiB memory, if the + // debugging sections are outside that region, we can't access them + // directly and we'll have to memory map some physical memory. + // TODO: Correctly handle the memory being outside 4 MiB. You need to + // teach the memory management code to reserve these ranges for + // a while until we have used them and add additional complexity + // in this code. + #define BELOW_4MIB(addr, length) ((addr) + (length) <= 4*1024*1024) + + // Find and the verify the section table. + multiboot_elf_section_header_table_t* elf_sec = &bootinfo->u.elf_sec; + if ( !BELOW_4MIB(elf_sec->addr, elf_sec->size) ) + { + Log::PrintF("Warning: the section table was loaded inappropriately by the boot loader, kernel debugging symbols will not be available.\n"); + break; + } + + #define SECTION(num) ((ELF::SectionHeader32*) ((uintptr_t) elf_sec->addr + (uintptr_t) elf_sec->size * (uintptr_t) (num))) + + // Verify the section name section. + ELF::SectionHeader32* section_string_section = SECTION(elf_sec->shndx); + if ( !BELOW_4MIB(section_string_section->addr, section_string_section->size) ) + { + Log::PrintF("Warning: the section string table was loaded inappropriately by the boot loader, kernel debugging symbols will not be available.\n"); + break; + } + + if ( !section_string_section ) + break; + + const char* section_string_table = (const char*) (uintptr_t) section_string_section->addr; + + // Find the symbol table. + ELF::SectionHeader32* symbol_table_section = NULL; + for ( unsigned i = 0; i < elf_sec->num && !symbol_table_section; i++ ) + { + ELF::SectionHeader32* section = SECTION(i); + if ( !strcmp(section_string_table + section->name, ".symtab") ) + symbol_table_section = section; + } + + if ( !symbol_table_section ) + break; + + if ( !BELOW_4MIB(symbol_table_section->addr, symbol_table_section->size) ) + { + Log::PrintF("Warning: the symbol table was loaded inappropriately by the boot loader, kernel debugging symbols will not be available.\n"); + break; + } + + // Find the symbol string table. + ELF::SectionHeader32* string_table_section = NULL; + for ( unsigned i = 0; i < elf_sec->num && !string_table_section; i++ ) + { + ELF::SectionHeader32* section = SECTION(i); + if ( !strcmp(section_string_table + section->name, ".strtab") ) + string_table_section = section; + } + + if ( !string_table_section ) + break; + + if ( !BELOW_4MIB(string_table_section->addr, string_table_section->size) ) + { + Log::PrintF("Warning: the symbol string table was loaded inappropriately by the boot loader, kernel debugging symbols will not be available.\n"); + break; + } + + // Duplicate the data structures and convert them to the kernel symbol + // table format and register it for later debugging. + const char* elf_string_table = (const char*) (uintptr_t) string_table_section->addr; + size_t elf_string_table_size = string_table_section->size; + ELF::Symbol32* elf_symbols = (ELF::Symbol32*) (uintptr_t) symbol_table_section->addr; + size_t elf_symbol_count = symbol_table_section->size / sizeof(ELF::Symbol32); + + if ( !elf_symbol_count || elf_symbol_count == 1 /* null symbol */) + break; + + char* string_table = new char[elf_string_table_size]; + if ( !string_table ) + { + Log::PrintF("Warning: unable to allocate the kernel symbol string table, kernel debugging symbols will not be available.\n"); + break; + } + memcpy(string_table, elf_string_table, elf_string_table_size); + + Symbol* symbols = new Symbol[elf_symbol_count-1]; + if ( !symbols ) + { + Log::PrintF("Warning: unable to allocate the kernel symbol table, kernel debugging symbols will not be available.\n"); + delete[] string_table; + break; + } + + // Copy all entires except the leading null entry. + for ( size_t i = 1; i < elf_symbol_count; i++ ) + { + symbols[i-1].address = elf_symbols[i].st_value; + symbols[i-1].size = elf_symbols[i].st_size; + symbols[i-1].name = string_table + elf_symbols[i].st_name; + } + + SetKernelSymbolTable(symbols, elf_symbol_count-1); + } while ( false ); + // Initialize the interrupt worker (before scheduling is enabled). Interrupt::InitWorker(); diff --git a/sortix/symbol.cpp b/sortix/symbol.cpp new file mode 100644 index 00000000..289a7db4 --- /dev/null +++ b/sortix/symbol.cpp @@ -0,0 +1,65 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2013. + + This file is part of Sortix. + + Sortix is free software: you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation, either version 3 of the License, or (at your option) any later + version. + + Sortix is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + details. + + You should have received a copy of the GNU General Public License along with + Sortix. If not, see . + + symbol.cpp + Symbol table access. + +*******************************************************************************/ + +#include +#include + +#include + +namespace Sortix { + +Symbol* kernel_symbol_table; +size_t kernel_symbol_table_length; + +void SetKernelSymbolTable(Symbol* table, size_t length) +{ + kernel_symbol_table = table; + kernel_symbol_table_length = length; +} + +const Symbol* GetKernelSymbolTable(size_t* length) +{ + if ( length ) + *length = kernel_symbol_table_length; + return kernel_symbol_table; +} + +static bool MatchesSymbol(const Symbol* symbol, uintptr_t address) +{ + return symbol->address <= address && + address <= symbol->address + symbol->size; +} + +const Symbol* GetKernelSymbol(uintptr_t address) +{ + for ( size_t i = 0; i < kernel_symbol_table_length; i++ ) + { + const Symbol* symbol = kernel_symbol_table + i; + if ( MatchesSymbol(symbol, address) ) + return symbol; + } + return NULL; +} + +} // namespace Sortix