diff --git a/Kernel/ELF/ELFImage.h b/Kernel/ELF/ELFImage.h index 7ad336fa9d..4574f4d0fd 100644 --- a/Kernel/ELF/ELFImage.h +++ b/Kernel/ELF/ELFImage.h @@ -212,7 +212,7 @@ template inline void ELFImage::for_each_symbol(F func) const { for (unsigned i = 0; i < symbol_count(); ++i) { - if (!func(symbol(i))) + if (func(symbol(i)) == IterationDecision::Abort) break; } } diff --git a/Kernel/ELF/ELFLoader.cpp b/Kernel/ELF/ELFLoader.cpp index 10544be44d..85a863b761 100644 --- a/Kernel/ELF/ELFLoader.cpp +++ b/Kernel/ELF/ELFLoader.cpp @@ -1,5 +1,6 @@ #include "ELFLoader.h" #include +#include //#define ELFLOADER_DEBUG //#define SUPPORT_RELOCATIONS @@ -162,9 +163,9 @@ char* ELFLoader::symbol_ptr(const char* name) char* found_ptr = nullptr; m_image.for_each_symbol([&] (const ELFImage::Symbol symbol) { if (symbol.type() != STT_FUNC) - return true; + return IterationDecision::Continue; if (strcmp(symbol.name(), name)) - return true; + return IterationDecision::Continue; if (m_image.is_executable()) found_ptr = (char*)symbol.value(); #ifdef SUPPORT_RELOCATIONS @@ -173,7 +174,31 @@ char* ELFLoader::symbol_ptr(const char* name) #endif else ASSERT_NOT_REACHED(); - return false; + return IterationDecision::Abort; }); return found_ptr; } + +String ELFLoader::symbolicate(dword address) const +{ + if (m_sorted_symbols.is_empty()) { + m_sorted_symbols.ensure_capacity(m_image.symbol_count()); + m_image.for_each_symbol([this] (auto& symbol) { + m_sorted_symbols.append({ symbol.value(), symbol.name() }); + return IterationDecision::Continue; + }); + quick_sort(m_sorted_symbols.begin(), m_sorted_symbols.end(), [] (auto& a, auto& b) { + return a.address < b.address; + }); + } + + for (int i = 0; i < m_sorted_symbols.size(); ++i) { + if (m_sorted_symbols[i].address > address) { + if (i == 0) + return "!!"; + auto& symbol = m_sorted_symbols[i - 1]; + return String::format("%s +%u", symbol.name, address - symbol.address); + } + } + return "??"; +} diff --git a/Kernel/ELF/ELFLoader.h b/Kernel/ELF/ELFLoader.h index 25f47bce45..957185b76e 100644 --- a/Kernel/ELF/ELFLoader.h +++ b/Kernel/ELF/ELFLoader.h @@ -18,6 +18,8 @@ public: char* symbol_ptr(const char* name); LinearAddress entry() const { return m_image.entry(); } + String symbolicate(dword address) const; + private: bool layout(); bool perform_relocations(); @@ -39,5 +41,11 @@ private: ELFImage m_image; HashMap m_sections; + + struct SortedSymbol { + dword address; + const char* name; + }; + mutable Vector m_sorted_symbols; }; diff --git a/Kernel/KSyms.cpp b/Kernel/KSyms.cpp index 16c4fc538f..1dc7830a3b 100644 --- a/Kernel/KSyms.cpp +++ b/Kernel/KSyms.cpp @@ -2,6 +2,7 @@ #include "Process.h" #include "Scheduler.h" #include +#include static KSym* s_ksyms; dword ksym_lowest_address; @@ -114,7 +115,11 @@ static void load_ksyms_from_data(const ByteBuffer& buffer) if (!symbol.address) break; if (!symbol.ksym) { - dbgprintf("%p\n", symbol.address); + if (current->process().elf_loader()) { + dbgprintf("%p %s\n", symbol.address, current->process().elf_loader()->symbolicate(symbol.address).characters()); + } else { + dbgprintf("%p (no ELF loader for process)\n", symbol.address); + } continue; } unsigned offset = symbol.address - symbol.ksym->address; diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index 98be49edf6..c6e8ea4949 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -327,19 +327,20 @@ int Process::do_exec(String path, Vector arguments, Vector envir bool success = region->page_in(); ASSERT(success); } + OwnPtr loader; { // Okay, here comes the sleight of hand, pay close attention.. auto old_regions = move(m_regions); m_regions.append(*region); - ELFLoader loader(region->laddr().as_ptr()); - loader.map_section_hook = [&] (LinearAddress laddr, size_t size, size_t alignment, size_t offset_in_image, bool is_readable, bool is_writable, const String& name) { + loader = make(region->laddr().as_ptr()); + loader->map_section_hook = [&] (LinearAddress laddr, size_t size, size_t alignment, size_t offset_in_image, bool is_readable, bool is_writable, const String& name) { ASSERT(size); ASSERT(alignment == PAGE_SIZE); size = ceil_div(size, PAGE_SIZE) * PAGE_SIZE; (void) allocate_region_with_vmo(laddr, size, vmo.copy_ref(), offset_in_image, String(name), is_readable, is_writable); return laddr.as_ptr(); }; - loader.alloc_section_hook = [&] (LinearAddress laddr, size_t size, size_t alignment, bool is_readable, bool is_writable, const String& name) { + loader->alloc_section_hook = [&] (LinearAddress laddr, size_t size, size_t alignment, bool is_readable, bool is_writable, const String& name) { ASSERT(size); ASSERT(alignment == PAGE_SIZE); size += laddr.get() & 0xfff; @@ -348,8 +349,8 @@ int Process::do_exec(String path, Vector arguments, Vector envir (void) allocate_region(laddr, size, String(name), is_readable, is_writable); return laddr.as_ptr(); }; - bool success = loader.load(); - if (!success || !loader.entry().get()) { + bool success = loader->load(); + if (!success || !loader->entry().get()) { m_page_directory = move(old_page_directory); // FIXME: RAII this somehow instead. ASSERT(¤t->process() == this); @@ -359,9 +360,11 @@ int Process::do_exec(String path, Vector arguments, Vector envir return -ENOEXEC; } - entry_eip = loader.entry().get(); + entry_eip = loader->entry().get(); } + m_elf_loader = move(loader); + current->m_kernel_stack_for_signal_handler_region = nullptr; current->m_signal_stack_user_region = nullptr; current->set_default_signal_dispositions(); diff --git a/Kernel/Process.h b/Kernel/Process.h index 613c003ff7..a158ccd460 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -14,6 +14,7 @@ #include #include +class ELFLoader; class FileDescriptor; class PageDirectory; class Region; @@ -248,6 +249,8 @@ public: unsigned syscall_count() const { return m_syscall_count; } void did_syscall() { ++m_syscall_count; } + const ELFLoader* elf_loader() const { return m_elf_loader.ptr(); } + private: friend class MemoryManager; friend class Scheduler; @@ -327,6 +330,7 @@ private: unsigned m_syscall_count { 0 }; RetainPtr m_tracer; + OwnPtr m_elf_loader; Lock m_big_lock { "Process" }; };