Add kernel symbol support.
This commit is contained in:
parent
834789d006
commit
2525de507c
|
@ -122,6 +122,7 @@ serialterminal.o \
|
||||||
signal.o \
|
signal.o \
|
||||||
sound.o \
|
sound.o \
|
||||||
string.o \
|
string.o \
|
||||||
|
symbol.o \
|
||||||
syscall.o \
|
syscall.o \
|
||||||
textbuffer.o \
|
textbuffer.o \
|
||||||
textterminal.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_W = (1<<1);
|
||||||
const uint32_t PF_R = (1<<2);
|
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
|
// Reads the elf file into the current address space and returns the
|
||||||
// entry address of the program, or 0 upon failure.
|
// entry address of the program, or 0 upon failure.
|
||||||
addr_t Construct(Process* process, const void* file, size_t filelen);
|
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/string.h>
|
||||||
#include <sortix/kernel/user-timer.h>
|
#include <sortix/kernel/user-timer.h>
|
||||||
#include <sortix/kernel/signal.h>
|
#include <sortix/kernel/signal.h>
|
||||||
|
#include <sortix/kernel/symbol.h>
|
||||||
#include <sortix/kernel/process.h>
|
#include <sortix/kernel/process.h>
|
||||||
#include <sortix/kernel/thread.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.
|
// Initialize the kernel heap.
|
||||||
_init_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).
|
// Initialize the interrupt worker (before scheduling is enabled).
|
||||||
Interrupt::InitWorker();
|
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