diff --git a/assets/initrd.toml b/assets/initrd.toml index 2289e7b..c29a95a 100644 --- a/assets/initrd.toml +++ b/assets/initrd.toml @@ -15,6 +15,7 @@ source = "../assets/fonts/tamsyn8x16r.psf" [[files]] dest = "symbol_table.dat" source = "symbol_table.dat" +symbols = true [[files]] dest = "nulldrv1" diff --git a/modules.yaml b/modules.yaml index c29aaab..228c379 100644 --- a/modules.yaml +++ b/modules.yaml @@ -47,6 +47,7 @@ modules: - src/kernel/screen.cpp - src/kernel/serial.cpp - src/kernel/stack_cache.cpp + - src/kernel/symbol_table.cpp - src/kernel/syscall.cpp - src/kernel/syscall.s - src/kernel/syscalls/channel.cpp diff --git a/src/kernel/debug.cpp b/src/kernel/debug.cpp index 5025738..1b3b586 100644 --- a/src/kernel/debug.cpp +++ b/src/kernel/debug.cpp @@ -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; } } diff --git a/src/kernel/main.cpp b/src/kernel/main.cpp index 74423ab..8b988f3 100644 --- a/src/kernel/main.cpp +++ b/src/kernel/main.cpp @@ -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"); { diff --git a/src/kernel/symbol_table.cpp b/src/kernel/symbol_table.cpp new file mode 100644 index 0000000..1e927cd --- /dev/null +++ b/src/kernel/symbol_table.cpp @@ -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(m_data); + m_entries = *values++; + m_index = reinterpret_cast(values); + + for (size_t i = 0; i < m_entries; ++i) { + uint64_t offset = reinterpret_cast(m_index[i].name); + m_index[i].name = reinterpret_cast(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]; +} diff --git a/src/kernel/symbol_table.h b/src/kernel/symbol_table.h new file mode 100644 index 0000000..222fb1a --- /dev/null +++ b/src/kernel/symbol_table.h @@ -0,0 +1,34 @@ +#pragma once + +#include + +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; +}; diff --git a/src/libraries/initrd/include/initrd/headers.h b/src/libraries/initrd/include/initrd/headers.h index e89df99..0845275 100644 --- a/src/libraries/initrd/include/initrd/headers.h +++ b/src/libraries/initrd/include/initrd/headers.h @@ -21,7 +21,8 @@ struct disk_header enum class file_flags : uint16_t { - executable = 0x01 + executable = 0x01, + symbols = 0x02 }; struct file_header diff --git a/src/libraries/initrd/include/initrd/initrd.h b/src/libraries/initrd/include/initrd/initrd.h index ed8a676..c313947 100644 --- a/src/libraries/initrd/include/initrd/initrd.h +++ b/src/libraries/initrd/include/initrd/initrd.h @@ -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; diff --git a/src/libraries/initrd/initrd.cpp b/src/libraries/initrd/initrd.cpp index bfd2fd7..38d77f2 100644 --- a/src/libraries/initrd/initrd.cpp +++ b/src/libraries/initrd/initrd.cpp @@ -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) { diff --git a/src/tools/makerd/entry.cpp b/src/tools/makerd/entry.cpp index bede857..9fb4a4f 100644 --- a/src/tools/makerd/entry.cpp +++ b/src/tools/makerd/entry.cpp @@ -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(); diff --git a/src/tools/makerd/entry.h b/src/tools/makerd/entry.h index 58456e4..59f4083 100644 --- a/src/tools/makerd/entry.h +++ b/src/tools/makerd/entry.h @@ -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; }; diff --git a/src/tools/makerd/main.cpp b/src/tools/makerd/main.cpp index e95c690..4adef32 100644 --- a/src/tools/makerd/main.cpp +++ b/src/tools/makerd/main.cpp @@ -44,8 +44,9 @@ int main(int argc, char **argv) } auto exec = file->get_as("executable").value_or(false); + auto syms = file->get_as("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(&fheader), sizeof(fheader));