From c75dbc0cbb7bcb40bcf9b0868ea2206829fd2f90 Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 13 Oct 2023 22:11:52 +0200 Subject: [PATCH] kernel: Lookup and print symbols for addresses in backtraces --- .gitignore | 1 + kernel/CMakeLists.txt | 3 ++ kernel/src/Symbols.cpp | 95 ++++++++++++++++++++++++++++++++++ kernel/src/Symbols.h | 9 ++++ kernel/src/arch/x86_64/CPU.cpp | 5 +- kernel/src/main.cpp | 3 ++ tools/generate-symbols.sh | 6 +-- 7 files changed, 115 insertions(+), 7 deletions(-) create mode 100644 kernel/src/Symbols.cpp create mode 100644 kernel/src/Symbols.h diff --git a/.gitignore b/.gitignore index 43437f04..0d2c2eac 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ Luna.iso toolchain/ build/ initrd/boot/moon +initrd/ksyms env-local.sh initrd/bin/** base/usr/bin/** diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 35571e8d..5ceff595 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -8,6 +8,7 @@ set(SOURCES src/Log.cpp src/Pledge.cpp src/cxxabi.cpp + src/Symbols.cpp src/video/Framebuffer.cpp src/video/TextConsole.cpp src/memory/MemoryManager.cpp @@ -150,4 +151,6 @@ target_include_directories(moon PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/gen) target_link_options(moon PRIVATE LINKER:-T ${CMAKE_CURRENT_LIST_DIR}/moon.ld -nostdlib -nodefaultlibs) +add_custom_command(TARGET moon POST_BUILD COMMAND ${LUNA_ROOT}/tools/generate-symbols.sh) + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/moon" DESTINATION ${LUNA_ROOT}/initrd/boot) diff --git a/kernel/src/Symbols.cpp b/kernel/src/Symbols.cpp new file mode 100644 index 00000000..e8f88fd0 --- /dev/null +++ b/kernel/src/Symbols.cpp @@ -0,0 +1,95 @@ +#include "Symbols.h" +#include "Log.h" +#include "arch/MMU.h" +#include "boot/bootboot.h" +#include "fs/InitRD.h" +#include +#include +#include + +extern const BOOTBOOT bootboot; + +static bool g_symbols_loaded = false; + +struct Symbol +{ + u64 address; + char symbol[256]; +}; + +Vector g_symbols; + +extern const u8 kernel_start; +extern const u8 kernel_end; + +static int sscanf(const char* str, const char* format, ...) +{ + va_list ap; + va_start(ap, format); + + int rc = scanf_impl(str, format, ap); + + va_end(ap); + + return rc; +} + +namespace Symbols +{ + Result load() + { + const u64 virtual_initrd_address = MMU::translate_physical_address(bootboot.initrd_ptr); + + TarStream stream; + stream.initialize((void*)virtual_initrd_address, bootboot.initrd_size); + + TarStream::Entry file; + while (TRY(stream.read_next_entry(file))) + { + if (file.name.view() == "ksyms") + { + char* string = strtok(const_cast((const char*)file.data()), "\n"); + if (!string) return {}; + + do { + Symbol symbol; + memset(symbol.symbol, 0, sizeof(symbol.symbol)); + + char unused; + int nread; + + sscanf(string, "%lx %c %n", &symbol.address, &unused, &nread); + strlcpy(symbol.symbol, string + nread, sizeof(symbol)); + + TRY(g_symbols.try_append(symbol)); + } while ((string = strtok(nullptr, "\n"))); + + kinfoln("Successfully loaded %zu kernel debug symbols", g_symbols.size()); + + g_symbols_loaded = true; + return {}; + } + } + + return {}; + } + + StringView lookup(u64 address) + { + if (!g_symbols_loaded) return StringView {}; + if (address < (u64)&kernel_start) return StringView {}; + if (address >= (u64)&kernel_end) return StringView {}; + + for (isize i = (isize)g_symbols.size() - 1; i >= 0; i--) + { + if (g_symbols[i].address < address) + { + usize index = i + 1; + if (index == g_symbols.size()) return StringView {}; + return StringView { g_symbols[index].symbol }; + } + } + + return StringView {}; + } +} diff --git a/kernel/src/Symbols.h b/kernel/src/Symbols.h new file mode 100644 index 00000000..1b993dce --- /dev/null +++ b/kernel/src/Symbols.h @@ -0,0 +1,9 @@ +#pragma once +#include +#include + +namespace Symbols +{ + Result load(); + StringView lookup(u64 address); +} diff --git a/kernel/src/arch/x86_64/CPU.cpp b/kernel/src/arch/x86_64/CPU.cpp index 116c0038..cd0d753f 100644 --- a/kernel/src/arch/x86_64/CPU.cpp +++ b/kernel/src/arch/x86_64/CPU.cpp @@ -1,5 +1,6 @@ #include "arch/CPU.h" #include "Log.h" +#include "Symbols.h" #include "api/Mouse.h" #include "arch/Keyboard.h" #include "arch/Timer.h" @@ -368,7 +369,7 @@ namespace CPU rbp, [](u64 instruction, void* arg) { int* ptr = (int*)arg; - kinfoln("#%d at %p", *ptr, (void*)instruction); + kinfoln("#%d at %p in %s", *ptr, (void*)instruction, Symbols::lookup(instruction).chars()); (*ptr)++; }, &frame_index); @@ -387,7 +388,7 @@ namespace CPU regs, [](u64 instruction, void* arg) { int* ptr = (int*)arg; - kinfoln("#%d at %p", *ptr, (void*)instruction); + kinfoln("#%d at %p in %s", *ptr, (void*)instruction, Symbols::lookup(instruction).chars()); (*ptr)++; }, &frame_index); diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 9724442e..49245b12 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -1,4 +1,5 @@ #include "Log.h" +#include "Symbols.h" #include "arch/CPU.h" #include "arch/Timer.h" #include "binfmt/BinaryFormat.h" @@ -53,6 +54,8 @@ void oom_thread() kinfoln("Current platform: %s", CPU::platform_string().chars()); kinfoln("Current processor: %s", CPU::identify().value_or("(unknown)"_sv).chars()); + Symbols::load(); + auto root = mark_critical(TmpFS::FileSystem::create(), "Failed to create initial ramfs"); mark_critical(VFS::mount_root(root), "Failed to mount the initial ramfs as the root filesystem"); mark_critical(InitRD::populate_vfs(), "Failed to load files from the initial ramdisk"); diff --git a/tools/generate-symbols.sh b/tools/generate-symbols.sh index 97d3c62e..b2d6dca4 100755 --- a/tools/generate-symbols.sh +++ b/tools/generate-symbols.sh @@ -6,8 +6,4 @@ source $(dirname $0)/env.sh cd $LUNA_ROOT -rm -f initrd/sys/moon.sym - -nm -C -n initrd/boot/moon | grep -vE \\.Lubsan_data | awk '{ if ($2 != "a") print; }' | uniq > initrd/sys/moon.sym - -chmod 400 initrd/sys/moon.sym \ No newline at end of file +nm -C -n $LUNA_BUILD_DIR/kernel/moon | grep -vE \\.Lubsan_data | awk '{ if ($2 != "a") print; }' | uniq > initrd/ksyms