[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:
@@ -5,6 +5,7 @@
|
||||
#include "objects/process.h"
|
||||
#include "objects/thread.h"
|
||||
#include "page_manager.h"
|
||||
#include "symbol_table.h"
|
||||
|
||||
size_t __counter_syscall_enter = 0;
|
||||
size_t __counter_syscall_sysret = 0;
|
||||
@@ -59,14 +60,26 @@ void
|
||||
print_stacktrace(int skip)
|
||||
{
|
||||
console *cons = console::get();
|
||||
symbol_table *syms = symbol_table::get();
|
||||
|
||||
frame *fp = nullptr;
|
||||
int fi = -skip;
|
||||
__asm__ __volatile__ ( "mov %%rbp, %0" : "=r" (fp) );
|
||||
|
||||
while (fp && fp->return_addr) {
|
||||
if (fi++ >= 0)
|
||||
cons->printf(" frame %2d: %lx\n", fi-1, fp->return_addr);
|
||||
if (fi++ >= 0) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "page_manager.h"
|
||||
#include "scheduler.h"
|
||||
#include "serial.h"
|
||||
#include "symbol_table.h"
|
||||
#include "syscall.h"
|
||||
|
||||
extern "C" {
|
||||
@@ -121,8 +122,11 @@ kernel_main(args::header *header)
|
||||
|
||||
initrd::disk &ird = initrds.emplace(mod.location);
|
||||
log::info(logs::boot, "initrd loaded with %d files.", ird.files().count());
|
||||
for (auto &f : ird.files())
|
||||
log::info(logs::boot, " %s%s (%d bytes).", f.executable() ? "*" : "", f.name(), f.size());
|
||||
for (auto &f : ird.files()) {
|
||||
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 &f : ird.files()) {
|
||||
if (f.executable())
|
||||
if (f.executable()) {
|
||||
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 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
|
||||
{
|
||||
executable = 0x01
|
||||
executable = 0x01,
|
||||
symbols = 0x02
|
||||
};
|
||||
|
||||
struct file_header
|
||||
|
||||
@@ -36,6 +36,9 @@ public:
|
||||
/// Whether this file is an executable
|
||||
bool executable() const;
|
||||
|
||||
/// Whether this file is a symbol table
|
||||
bool symbols() const;
|
||||
|
||||
private:
|
||||
const file_header *m_header;
|
||||
void const *m_data;
|
||||
|
||||
@@ -22,6 +22,11 @@ file::executable() const {
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
#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_out(out),
|
||||
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_size = m_file.tellg();
|
||||
|
||||
@@ -5,13 +5,18 @@
|
||||
class entry
|
||||
{
|
||||
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 & out() const { return m_out; }
|
||||
inline const std::ifstream & file() const { return m_file; }
|
||||
|
||||
inline bool executable() const { return m_exec; }
|
||||
inline bool symbols() const { return m_syms; }
|
||||
inline size_t size() const { return m_size; }
|
||||
inline bool good() const { return m_file.good(); }
|
||||
|
||||
@@ -21,5 +26,6 @@ private:
|
||||
std::ifstream m_file;
|
||||
size_t m_size;
|
||||
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 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();
|
||||
|
||||
if (!e.good()) {
|
||||
@@ -96,6 +97,9 @@ int main(int argc, char **argv)
|
||||
if (e.executable())
|
||||
fheader.flags |= initrd::file_flags::executable;
|
||||
|
||||
if (e.symbols())
|
||||
fheader.flags |= initrd::file_flags::symbols;
|
||||
|
||||
out.write(
|
||||
reinterpret_cast<const char *>(&fheader),
|
||||
sizeof(fheader));
|
||||
|
||||
Reference in New Issue
Block a user