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