mirror of
https://github.com/justinian/jsix.git
synced 2025-12-09 16:04:32 -08:00
[kernel] Use symbol table in stack traces
Now using the symbol table built by build_symbol_table.py in the kernel when printing stack traces.
This commit is contained in:
@@ -15,6 +15,7 @@ source = "../assets/fonts/tamsyn8x16r.psf"
|
|||||||
[[files]]
|
[[files]]
|
||||||
dest = "symbol_table.dat"
|
dest = "symbol_table.dat"
|
||||||
source = "symbol_table.dat"
|
source = "symbol_table.dat"
|
||||||
|
symbols = true
|
||||||
|
|
||||||
[[files]]
|
[[files]]
|
||||||
dest = "nulldrv1"
|
dest = "nulldrv1"
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ modules:
|
|||||||
- src/kernel/screen.cpp
|
- src/kernel/screen.cpp
|
||||||
- src/kernel/serial.cpp
|
- src/kernel/serial.cpp
|
||||||
- src/kernel/stack_cache.cpp
|
- src/kernel/stack_cache.cpp
|
||||||
|
- src/kernel/symbol_table.cpp
|
||||||
- src/kernel/syscall.cpp
|
- src/kernel/syscall.cpp
|
||||||
- src/kernel/syscall.s
|
- src/kernel/syscall.s
|
||||||
- src/kernel/syscalls/channel.cpp
|
- src/kernel/syscalls/channel.cpp
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include "objects/process.h"
|
#include "objects/process.h"
|
||||||
#include "objects/thread.h"
|
#include "objects/thread.h"
|
||||||
#include "page_manager.h"
|
#include "page_manager.h"
|
||||||
|
#include "symbol_table.h"
|
||||||
|
|
||||||
size_t __counter_syscall_enter = 0;
|
size_t __counter_syscall_enter = 0;
|
||||||
size_t __counter_syscall_sysret = 0;
|
size_t __counter_syscall_sysret = 0;
|
||||||
@@ -59,14 +60,26 @@ void
|
|||||||
print_stacktrace(int skip)
|
print_stacktrace(int skip)
|
||||||
{
|
{
|
||||||
console *cons = console::get();
|
console *cons = console::get();
|
||||||
|
symbol_table *syms = symbol_table::get();
|
||||||
|
|
||||||
frame *fp = nullptr;
|
frame *fp = nullptr;
|
||||||
int fi = -skip;
|
int fi = -skip;
|
||||||
__asm__ __volatile__ ( "mov %%rbp, %0" : "=r" (fp) );
|
__asm__ __volatile__ ( "mov %%rbp, %0" : "=r" (fp) );
|
||||||
|
|
||||||
while (fp && fp->return_addr) {
|
while (fp && fp->return_addr) {
|
||||||
if (fi++ >= 0)
|
if (fi++ >= 0) {
|
||||||
cons->printf(" frame %2d: %lx\n", fi-1, fp->return_addr);
|
const symbol_table::entry *e = syms ? syms->find_symbol(fp->return_addr) : nullptr;
|
||||||
|
const char *name = e ? e->name : "";
|
||||||
|
cons->printf(" frame %2d:", fi-1);
|
||||||
|
|
||||||
|
cons->set_color(5);
|
||||||
|
cons->printf(" %016llx", fp->return_addr);
|
||||||
|
cons->set_color();
|
||||||
|
|
||||||
|
cons->set_color(6);
|
||||||
|
cons->printf(" %s\n", name);
|
||||||
|
cons->set_color();
|
||||||
|
}
|
||||||
fp = fp->prev;
|
fp = fp->prev;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
#include "page_manager.h"
|
#include "page_manager.h"
|
||||||
#include "scheduler.h"
|
#include "scheduler.h"
|
||||||
#include "serial.h"
|
#include "serial.h"
|
||||||
|
#include "symbol_table.h"
|
||||||
#include "syscall.h"
|
#include "syscall.h"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -121,8 +122,11 @@ kernel_main(args::header *header)
|
|||||||
|
|
||||||
initrd::disk &ird = initrds.emplace(mod.location);
|
initrd::disk &ird = initrds.emplace(mod.location);
|
||||||
log::info(logs::boot, "initrd loaded with %d files.", ird.files().count());
|
log::info(logs::boot, "initrd loaded with %d files.", ird.files().count());
|
||||||
for (auto &f : ird.files())
|
for (auto &f : ird.files()) {
|
||||||
log::info(logs::boot, " %s%s (%d bytes).", f.executable() ? "*" : "", f.name(), f.size());
|
char type = f.executable() ? '*' :
|
||||||
|
f.symbols() ? '+' : ' ';
|
||||||
|
log::info(logs::boot, " %c%s (%d bytes).", type, f.name(), f.size());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -180,14 +184,16 @@ kernel_main(args::header *header)
|
|||||||
|
|
||||||
for (auto &ird : initrds) {
|
for (auto &ird : initrds) {
|
||||||
for (auto &f : ird.files()) {
|
for (auto &f : ird.files()) {
|
||||||
if (f.executable())
|
if (f.executable()) {
|
||||||
sched->load_process(f.name(), f.data(), f.size());
|
sched->load_process(f.name(), f.data(), f.size());
|
||||||
|
} else if (f.symbols()) {
|
||||||
|
new symbol_table {f.data(), f.size()};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log::info(logs::objs, "Testing object system:");
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
log::info(logs::objs, "Testing object system:");
|
||||||
test_observer obs1("event");
|
test_observer obs1("event");
|
||||||
test_observer obs2("no handles");
|
test_observer obs2("no handles");
|
||||||
{
|
{
|
||||||
|
|||||||
49
src/kernel/symbol_table.cpp
Normal file
49
src/kernel/symbol_table.cpp
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
#include "kutil/assert.h"
|
||||||
|
#include "kutil/memory.h"
|
||||||
|
|
||||||
|
#include "log.h"
|
||||||
|
#include "symbol_table.h"
|
||||||
|
|
||||||
|
symbol_table * symbol_table::s_instance = nullptr;
|
||||||
|
|
||||||
|
symbol_table::symbol_table(const void *data, size_t size)
|
||||||
|
{
|
||||||
|
m_data = kutil::kalloc(size);
|
||||||
|
kassert(m_data, "Failed to allocate for symbol table");
|
||||||
|
kutil::memcpy(m_data, data, size);
|
||||||
|
|
||||||
|
uint64_t *values = reinterpret_cast<uint64_t*>(m_data);
|
||||||
|
m_entries = *values++;
|
||||||
|
m_index = reinterpret_cast<entry*>(values);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < m_entries; ++i) {
|
||||||
|
uint64_t offset = reinterpret_cast<uint64_t>(m_index[i].name);
|
||||||
|
m_index[i].name = reinterpret_cast<char*>(m_data) + offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!s_instance)
|
||||||
|
s_instance = this;
|
||||||
|
|
||||||
|
log::info(logs::boot, "Loaded %d symbol table entries at %llx", m_entries, m_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
symbol_table::~symbol_table()
|
||||||
|
{
|
||||||
|
kutil::kfree(m_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
const symbol_table::entry *
|
||||||
|
symbol_table::find_symbol(uintptr_t addr) const
|
||||||
|
{
|
||||||
|
if (!m_entries)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
// TODO: binary search
|
||||||
|
for (size_t i = 0; i < m_entries; ++i) {
|
||||||
|
if (m_index[i].address > addr) {
|
||||||
|
return i ? &m_index[i - 1] : nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &m_index[m_entries - 1];
|
||||||
|
}
|
||||||
34
src/kernel/symbol_table.h
Normal file
34
src/kernel/symbol_table.h
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
class symbol_table
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct entry
|
||||||
|
{
|
||||||
|
uintptr_t address;
|
||||||
|
char *name;
|
||||||
|
};
|
||||||
|
|
||||||
|
static symbol_table * get() { return s_instance; }
|
||||||
|
|
||||||
|
/// Constructor.
|
||||||
|
/// \arg data Pointer to the start of the symbol_table data.
|
||||||
|
/// \arg size Size of the data, in bytes
|
||||||
|
symbol_table(const void *data, size_t size);
|
||||||
|
|
||||||
|
~symbol_table();
|
||||||
|
|
||||||
|
/// Find the closest symbol address before the given address
|
||||||
|
/// \args addr Address to search for
|
||||||
|
/// \returns Actual address of the symbol
|
||||||
|
const entry * find_symbol(uintptr_t addr) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
size_t m_entries;
|
||||||
|
entry *m_index;
|
||||||
|
void *m_data;
|
||||||
|
|
||||||
|
static symbol_table *s_instance;
|
||||||
|
};
|
||||||
@@ -21,7 +21,8 @@ struct disk_header
|
|||||||
|
|
||||||
enum class file_flags : uint16_t
|
enum class file_flags : uint16_t
|
||||||
{
|
{
|
||||||
executable = 0x01
|
executable = 0x01,
|
||||||
|
symbols = 0x02
|
||||||
};
|
};
|
||||||
|
|
||||||
struct file_header
|
struct file_header
|
||||||
|
|||||||
@@ -36,6 +36,9 @@ public:
|
|||||||
/// Whether this file is an executable
|
/// Whether this file is an executable
|
||||||
bool executable() const;
|
bool executable() const;
|
||||||
|
|
||||||
|
/// Whether this file is a symbol table
|
||||||
|
bool symbols() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const file_header *m_header;
|
const file_header *m_header;
|
||||||
void const *m_data;
|
void const *m_data;
|
||||||
|
|||||||
@@ -22,6 +22,11 @@ file::executable() const {
|
|||||||
return bitfield_has(m_header->flags, file_flags::executable);
|
return bitfield_has(m_header->flags, file_flags::executable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
file::symbols() const {
|
||||||
|
return bitfield_has(m_header->flags, file_flags::symbols);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
disk::disk(const void *start)
|
disk::disk(const void *start)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
#include "entry.h"
|
#include "entry.h"
|
||||||
|
|
||||||
entry::entry(const std::string &in, const std::string &out, bool executable) :
|
entry::entry(const std::string &in, const std::string &out,
|
||||||
|
bool executable, bool symbols) :
|
||||||
m_in(in),
|
m_in(in),
|
||||||
m_out(out),
|
m_out(out),
|
||||||
m_file(in, std::ios_base::binary),
|
m_file(in, std::ios_base::binary),
|
||||||
m_exec(executable)
|
m_exec(executable),
|
||||||
|
m_syms(symbols)
|
||||||
{
|
{
|
||||||
m_file.seekg(0, std::ios_base::end);
|
m_file.seekg(0, std::ios_base::end);
|
||||||
m_size = m_file.tellg();
|
m_size = m_file.tellg();
|
||||||
|
|||||||
@@ -5,13 +5,18 @@
|
|||||||
class entry
|
class entry
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
entry(const std::string &in, const std::string &out, bool executable = false);
|
entry(
|
||||||
|
const std::string &in,
|
||||||
|
const std::string &out,
|
||||||
|
bool executable = false,
|
||||||
|
bool symbols = false);
|
||||||
|
|
||||||
inline const std::string & in() const { return m_in; }
|
inline const std::string & in() const { return m_in; }
|
||||||
inline const std::string & out() const { return m_out; }
|
inline const std::string & out() const { return m_out; }
|
||||||
inline const std::ifstream & file() const { return m_file; }
|
inline const std::ifstream & file() const { return m_file; }
|
||||||
|
|
||||||
inline bool executable() const { return m_exec; }
|
inline bool executable() const { return m_exec; }
|
||||||
|
inline bool symbols() const { return m_syms; }
|
||||||
inline size_t size() const { return m_size; }
|
inline size_t size() const { return m_size; }
|
||||||
inline bool good() const { return m_file.good(); }
|
inline bool good() const { return m_file.good(); }
|
||||||
|
|
||||||
@@ -21,5 +26,6 @@ private:
|
|||||||
std::ifstream m_file;
|
std::ifstream m_file;
|
||||||
size_t m_size;
|
size_t m_size;
|
||||||
bool m_exec;
|
bool m_exec;
|
||||||
|
bool m_syms;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -44,8 +44,9 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto exec = file->get_as<bool>("executable").value_or(false);
|
auto exec = file->get_as<bool>("executable").value_or(false);
|
||||||
|
auto syms = file->get_as<bool>("symbols").value_or(false);
|
||||||
|
|
||||||
entries.emplace_back(*source, *dest, exec);
|
entries.emplace_back(*source, *dest, exec, syms);
|
||||||
const entry &e = entries.back();
|
const entry &e = entries.back();
|
||||||
|
|
||||||
if (!e.good()) {
|
if (!e.good()) {
|
||||||
@@ -96,6 +97,9 @@ int main(int argc, char **argv)
|
|||||||
if (e.executable())
|
if (e.executable())
|
||||||
fheader.flags |= initrd::file_flags::executable;
|
fheader.flags |= initrd::file_flags::executable;
|
||||||
|
|
||||||
|
if (e.symbols())
|
||||||
|
fheader.flags |= initrd::file_flags::symbols;
|
||||||
|
|
||||||
out.write(
|
out.write(
|
||||||
reinterpret_cast<const char *>(&fheader),
|
reinterpret_cast<const char *>(&fheader),
|
||||||
sizeof(fheader));
|
sizeof(fheader));
|
||||||
|
|||||||
Reference in New Issue
Block a user