diff --git a/AK/String.cpp b/AK/String.cpp index 5bd3a98da2..78176780cb 100644 --- a/AK/String.cpp +++ b/AK/String.cpp @@ -317,6 +317,18 @@ bool String::contains(const String& needle) const return strstr(characters(), needle.characters()); } +Optional String::index_of(const String& needle) const +{ + if (is_null() || needle.is_null()) + return {}; + + const char* self_characters = characters(); + const char* result = strstr(self_characters, needle.characters()); + if (!result) + return {}; + return Optional { result - self_characters }; +} + bool String::equals_ignoring_case(const StringView& other) const { return StringUtils::equals_ignoring_case(view(), other); diff --git a/AK/String.h b/AK/String.h index e184476186..bf5ac828ce 100644 --- a/AK/String.h +++ b/AK/String.h @@ -117,6 +117,7 @@ public: bool equals_ignoring_case(const StringView&) const; bool contains(const String&) const; + Optional index_of(const String&) const; Vector split_limit(char separator, size_t limit, bool keep_empty = false) const; Vector split(char separator, bool keep_empty = false) const; diff --git a/Applications/Debugger/DebugSession.cpp b/Applications/Debugger/DebugSession.cpp index 86c59e8196..14e673cc5e 100644 --- a/Applications/Debugger/DebugSession.cpp +++ b/Applications/Debugger/DebugSession.cpp @@ -30,8 +30,8 @@ DebugSession::DebugSession(int pid) : m_debugee_pid(pid) - , m_executable(make(String::format("/proc/%d/exe", pid))) - , m_elf_image(make(reinterpret_cast(m_executable->data()), m_executable->size())) + , m_executable(String::format("/proc/%d/exe", pid)) + , m_elf(reinterpret_cast(m_executable.data()), m_executable.size()) { } @@ -176,8 +176,3 @@ void DebugSession::continue_debugee() ASSERT_NOT_REACHED(); } } - -VirtualAddress DebugSession::get_entry_point() const -{ - return m_elf_image->entry(); -} diff --git a/Applications/Debugger/DebugSession.h b/Applications/Debugger/DebugSession.h index 9ac7774f20..2b683c6ecd 100644 --- a/Applications/Debugger/DebugSession.h +++ b/Applications/Debugger/DebugSession.h @@ -26,13 +26,14 @@ #pragma once +#include #include #include #include #include #include #include -#include +#include #include #include #include @@ -69,7 +70,7 @@ public: template void run(Callback callback); - VirtualAddress get_entry_point() const; + const ELF::Loader& elf() const { return m_elf; } enum DebugDecision { Continue, @@ -90,8 +91,8 @@ private: int m_debugee_pid { -1 }; bool m_is_debugee_dead { false }; - NonnullOwnPtr m_executable; - NonnullOwnPtr m_elf_image; + MappedFile m_executable; + ELF::Loader m_elf; HashMap m_breakpoints; }; diff --git a/Applications/Debugger/main.cpp b/Applications/Debugger/main.cpp index 94fbe0ffcb..eeb09ffa99 100644 --- a/Applications/Debugger/main.cpp +++ b/Applications/Debugger/main.cpp @@ -27,6 +27,7 @@ #include "DebugSession.h" #include #include +#include #include #include #include @@ -137,14 +138,28 @@ bool handle_breakpoint_command(const String& command) if (parts.size() != 2) return false; - u32 breakpoint_address = strtoul(parts[1].characters(), nullptr, 16); - if (errno != 0) + auto argument = parts[1]; + if (argument.is_empty()) return false; + + u32 breakpoint_address = 0; + + if ((argument[0] >= '0' && argument[0] <= '9')) { + breakpoint_address = strtoul(argument.characters(), nullptr, 16); + } else { + auto symbol = g_debug_session->elf().find_demangled_function(argument); + if (!symbol.has_value()) { + printf("symbol %s not found\n", parts[1].characters()); + return false; + } + breakpoint_address = reinterpret_cast(symbol.value().value()); + } bool success = g_debug_session->insert_breakpoint(reinterpret_cast(breakpoint_address)); if (!success) { - fprintf(stderr, "coult not insert breakpoint at: 0x%x\n", breakpoint_address); + fprintf(stderr, "coult not insert breakpoint at: %08x\n", breakpoint_address); return false; } + printf("breakpoint insterted at: %08x\n", breakpoint_address); return true; } @@ -153,8 +168,8 @@ void print_help() printf("Options:\n" "cont - Continue execution\n" "regs - Print registers\n" - "dis - Print disassembly\n" - "bp
- Insert a breakpoint\n"); + "dis [number of instructions] - Print disassembly\n" + "bp
- Insert a breakpoint\n"); } int main(int argc, char** argv) @@ -185,7 +200,7 @@ int main(int argc, char** argv) sa.sa_handler = handle_sigint; sigaction(SIGINT, &sa, nullptr); - bool rc = g_debug_session->insert_breakpoint(g_debug_session->get_entry_point().as_ptr()); + bool rc = g_debug_session->insert_breakpoint(g_debug_session->elf().entry().as_ptr()); ASSERT(rc); g_debug_session->run([&](DebugSession::DebugBreakReason reason, Optional optional_regs) { diff --git a/Libraries/LibELF/Loader.cpp b/Libraries/LibELF/Loader.cpp index 39a50a9fb2..ba3be75fd3 100644 --- a/Libraries/LibELF/Loader.cpp +++ b/Libraries/LibELF/Loader.cpp @@ -136,13 +136,13 @@ bool Loader::layout() return !failed; } -char* Loader::symbol_ptr(const char* name) +char* Loader::symbol_ptr(const char* name) const { char* found_ptr = nullptr; m_image.for_each_symbol([&](const Image::Symbol symbol) { if (symbol.type() != STT_FUNC) return IterationDecision::Continue; - if (symbol.name() == name) + if (symbol.name() != name) return IterationDecision::Continue; if (m_image.is_executable()) found_ptr = (char*)(size_t)symbol.value(); @@ -153,6 +153,25 @@ char* Loader::symbol_ptr(const char* name) return found_ptr; } +Optional Loader::find_demangled_function(const String& name) const +{ + Optional found; + m_image.for_each_symbol([&](const Image::Symbol symbol) { + if (symbol.type() != STT_FUNC) + return IterationDecision::Continue; + auto demangled = demangle(symbol.name()); + auto index_of_paren = demangled.index_of("("); + if (index_of_paren.has_value()) { + demangled = demangled.substring(0, index_of_paren.value()); + } + if (demangled != name) + return IterationDecision::Continue; + found = symbol; + return IterationDecision::Break; + }); + return found; +} + #ifndef KERNEL Optional Loader::find_symbol(u32 address, u32* out_offset) const { @@ -160,7 +179,7 @@ Optional Loader::find_symbol(u32 address, u32* out_offset) const return {}; SortedSymbol* sorted_symbols = nullptr; -#ifdef KERNEL +# ifdef KERNEL if (!m_sorted_symbols_region) { m_sorted_symbols_region = MM.allocate_kernel_region(PAGE_ROUND_UP(m_symbol_count * sizeof(SortedSymbol)), "Sorted symbols", Kernel::Region::Access::Read | Kernel::Region::Access::Write); sorted_symbols = (SortedSymbol*)m_sorted_symbols_region->vaddr().as_ptr(); @@ -175,7 +194,7 @@ Optional Loader::find_symbol(u32 address, u32* out_offset) const } else { sorted_symbols = (SortedSymbol*)m_sorted_symbols_region->vaddr().as_ptr(); } -#else +# else if (m_sorted_symbols.is_empty()) { m_sorted_symbols.ensure_capacity(m_symbol_count); m_image.for_each_symbol([this](auto& symbol) { @@ -187,7 +206,7 @@ Optional Loader::find_symbol(u32 address, u32* out_offset) const }); } sorted_symbols = m_sorted_symbols.data(); -#endif +# endif for (size_t i = 0; i < m_symbol_count; ++i) { if (sorted_symbols[i].address > address) { diff --git a/Libraries/LibELF/Loader.h b/Libraries/LibELF/Loader.h index 394ceeafab..e7539be0b0 100644 --- a/Libraries/LibELF/Loader.h +++ b/Libraries/LibELF/Loader.h @@ -52,9 +52,13 @@ public: Function alloc_section_hook; Function tls_section_hook; Function map_section_hook; - VirtualAddress entry() const { return m_image.entry(); } #endif - char* symbol_ptr(const char* name); + VirtualAddress entry() const + { + return m_image.entry(); + } + char* symbol_ptr(const char* name) const; + Optional find_demangled_function(const String& name) const; bool has_symbols() const { return m_symbol_count; }