Add kernel symbol support.
This commit is contained in:
parent
834789d006
commit
2525de507c
|
@ -122,6 +122,7 @@ serialterminal.o \
|
|||
signal.o \
|
||||
sound.o \
|
||||
string.o \
|
||||
symbol.o \
|
||||
syscall.o \
|
||||
textbuffer.o \
|
||||
textterminal.o \
|
||||
|
|
20
sortix/elf.h
20
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);
|
||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
|
@ -49,6 +49,7 @@
|
|||
#include <sortix/kernel/string.h>
|
||||
#include <sortix/kernel/user-timer.h>
|
||||
#include <sortix/kernel/signal.h>
|
||||
#include <sortix/kernel/symbol.h>
|
||||
#include <sortix/kernel/process.h>
|
||||
#include <sortix/kernel/thread.h>
|
||||
|
||||
|
@ -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();
|
||||
|
||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
symbol.cpp
|
||||
Symbol table access.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <sortix/kernel/symbol.h>
|
||||
|
||||
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
|
Loading…
Reference in New Issue