diff options
author | Daniel Bertalan <dani@danielbertalan.dev> | 2021-07-28 17:18:43 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-08-08 10:55:36 +0200 |
commit | c1d6637dc786be76721c31fb7712efb4735b8fce (patch) | |
tree | 9f358c20ab0ad176dd78f3457d35ed4e2c0fa9ba /Userland/DevTools | |
parent | 980f314a0303e0ecbf911d8daf666bb463012524 (diff) | |
download | serenity-c1d6637dc786be76721c31fb7712efb4735b8fce.zip |
UserspaceEmulator: Make symbolication work when .text isn't the first
... segment
This happens with binaries build with Clang or with a custom linker
script. If this is the case, offsets should be calculated not from the
base address of `.text`, but from the first section loaded for the
library.
This commit moves all UserspaceEmulator symbolication into a common
helper function and fixes a FIXME.
Diffstat (limited to 'Userland/DevTools')
-rw-r--r-- | Userland/DevTools/UserspaceEmulator/Emulator.cpp | 103 | ||||
-rw-r--r-- | Userland/DevTools/UserspaceEmulator/Emulator.h | 10 | ||||
-rw-r--r-- | Userland/DevTools/UserspaceEmulator/MmapRegion.h | 9 | ||||
-rw-r--r-- | Userland/DevTools/UserspaceEmulator/SoftMMU.h | 10 |
4 files changed, 77 insertions, 55 deletions
diff --git a/Userland/DevTools/UserspaceEmulator/Emulator.cpp b/Userland/DevTools/UserspaceEmulator/Emulator.cpp index 1c13d3a03d..76ba17fabe 100644 --- a/Userland/DevTools/UserspaceEmulator/Emulator.cpp +++ b/Userland/DevTools/UserspaceEmulator/Emulator.cpp @@ -276,19 +276,10 @@ void Emulator::handle_repl() auto saved_eip = m_cpu.eip(); m_cpu.save_base_eip(); auto insn = X86::Instruction::from_stream(m_cpu, true, true); - // FIXME: This does not respect inlineing + // FIXME: This does not respect inlining // another way of getting the current function is at need - if (auto const* region = load_library_from_address(m_cpu.base_eip())) { - auto separator_index = region->name().find(":").value(); - String lib_name = region->name().substring(0, separator_index); - String lib_path = lib_name; - if (region->name().contains(".so")) - lib_path = String::formatted("/usr/lib/{}", lib_path); - - auto it = m_dynamic_library_cache.find(lib_path); - auto& elf = it->value.debug_info->elf(); - String symbol = elf.symbolicate(m_cpu.base_eip() - region->base()); - outln("[{}]: {}", lib_name, symbol); + if (auto symbol = symbol_at(m_cpu.base_eip()); symbol.has_value()) { + outln("[{}]: {}", symbol->lib_name, symbol->symbol); } outln("==> {}", create_instruction_line(m_cpu.base_eip(), insn)); @@ -405,11 +396,11 @@ MmapRegion const* Emulator::load_library_from_address(FlatPtr address) auto const* region = find_text_region(address); if (!region) return {}; - auto separator_index = region->name().find(':'); - if (!separator_index.has_value()) + + String lib_name = region->lib_name(); + if (lib_name.is_null()) return {}; - String lib_name = region->name().substring(0, separator_index.value()); String lib_path = lib_name; if (region->name().contains(".so")) lib_path = String::formatted("/usr/lib/{}", lib_path); @@ -426,30 +417,49 @@ MmapRegion const* Emulator::load_library_from_address(FlatPtr address) return region; } -String Emulator::create_backtrace_line(FlatPtr address) +MmapRegion const* Emulator::first_region_for_object(StringView name) { - auto minimal = String::formatted("=={{{}}}== {:p}", getpid(), (void*)address); - auto const* region = load_library_from_address(address); - if (!region) - return minimal; - // FIXME: This is redundant - auto separator_index = region->name().find(":").value(); - String lib_name = region->name().substring(0, separator_index); - String lib_path = lib_name; - if (region->name().contains(".so")) - lib_path = String::formatted("/usr/lib/{}", lib_path); + MmapRegion* ret = nullptr; + mmu().for_each_region_of_type<MmapRegion>([&](auto& region) { + if (region.lib_name() == name) { + ret = ®ion; + return IterationDecision::Break; + } + return IterationDecision::Continue; + }); + return ret; +} - auto it = m_dynamic_library_cache.find(lib_path); - auto& elf = it->value.debug_info->elf(); - String symbol = elf.symbolicate(address - region->base()); +// FIXME: This disregards function inlining. +Optional<Emulator::SymbolInfo> Emulator::symbol_at(FlatPtr address) +{ + auto const* address_region = load_library_from_address(address); + if (!address_region) + return {}; + auto lib_name = address_region->lib_name(); + auto const* first_region = (lib_name.is_null() || lib_name.is_empty()) ? address_region : first_region_for_object(lib_name); + VERIFY(first_region); + auto lib_path = lib_name.contains(".so"sv) ? String::formatted("/usr/lib/{}", lib_name) : lib_name; - auto line_without_source_info = String::formatted("=={{{}}}== {:p} [{}]: {}", getpid(), (void*)address, lib_name, symbol); + auto it = m_dynamic_library_cache.find(lib_path); + auto const& elf = it->value.debug_info->elf(); + auto symbol = elf.symbolicate(address - first_region->base()); - auto source_position = it->value.debug_info->get_source_position(address - region->base()); - if (source_position.has_value()) - return String::formatted("=={{{}}}== {:p} [{}]: {} (\e[34;1m{}\e[0m:{})", getpid(), (void*)address, lib_name, symbol, LexicalPath::basename(source_position.value().file_path), source_position.value().line_number); + auto source_position = it->value.debug_info->get_source_position(address - first_region->base()); + return { { lib_name, symbol, source_position } }; +} - return line_without_source_info; +String Emulator::create_backtrace_line(FlatPtr address) +{ + auto maybe_symbol = symbol_at(address); + if (!maybe_symbol.has_value()) { + return String::formatted("=={{{}}}== {:p}", getpid(), address); + } else if (!maybe_symbol->source_position.has_value()) { + return String::formatted("=={{{}}}== {:p} [{}]: {}", getpid(), address, maybe_symbol->lib_name, maybe_symbol->symbol); + } else { + auto const& source_position = maybe_symbol->source_position.value(); + return String::formatted("=={{{}}}== {:p} [{}]: {} (\e[34;1m{}\e[0m:{})", getpid(), address, maybe_symbol->lib_name, maybe_symbol->symbol, LexicalPath::basename(source_position.file_path), source_position.line_number); + } } void Emulator::dump_backtrace(Vector<FlatPtr> const& backtrace) @@ -486,26 +496,11 @@ void Emulator::emit_profile_event(AK::OutputStream& output, StringView event_nam String Emulator::create_instruction_line(FlatPtr address, X86::Instruction insn) { - auto minimal = String::formatted("{:p}: {}", (void*)address, insn.to_string(address)); - auto const* region = load_library_from_address(address); - if (!region) - return minimal; - // FIXME: This is redundant - auto separator_index = region->name().find(":").value(); - String lib_name = region->name().substring(0, separator_index); - String lib_path = lib_name; - if (region->name().contains(".so")) - lib_path = String::formatted("/usr/lib/{}", lib_path); - - auto it = m_dynamic_library_cache.find(lib_path); - auto& elf = it->value.debug_info->elf(); - String symbol = elf.symbolicate(address - region->base()); - - auto source_position = it->value.debug_info->get_source_position(address - region->base()); - if (!source_position.has_value()) - return minimal; - - return String::formatted("{:p}: {} \e[34;1m{}\e[0m:{}", (void*)address, insn.to_string(address), LexicalPath::basename(source_position.value().file_path), source_position.value().line_number); + auto symbol = symbol_at(address); + if (!symbol.has_value() || !symbol->source_position.has_value()) + return String::formatted("{:p}: {}", address, insn.to_string(address)); + else + return String::formatted("{:p}: {} \e[34;1m{}\e[0m:{}", address, insn.to_string(address), LexicalPath::basename(symbol->source_position->file_path), symbol->source_position.value().line_number); } static void emulator_signal_handler(int signum) diff --git a/Userland/DevTools/UserspaceEmulator/Emulator.h b/Userland/DevTools/UserspaceEmulator/Emulator.h index faafbd34b3..74662c91cf 100644 --- a/Userland/DevTools/UserspaceEmulator/Emulator.h +++ b/Userland/DevTools/UserspaceEmulator/Emulator.h @@ -79,6 +79,14 @@ public: pause(); } + struct SymbolInfo { + String lib_name; + String symbol; + Optional<Debug::DebugInfo::SourcePosition> source_position; + }; + + Optional<SymbolInfo> symbol_at(FlatPtr address); + void dump_regions() const; private: @@ -211,7 +219,7 @@ private: void dispatch_one_pending_signal(); MmapRegion const* find_text_region(FlatPtr address); MmapRegion const* load_library_from_address(FlatPtr address); - String symbol_at(FlatPtr address); + MmapRegion const* first_region_for_object(StringView name); String create_backtrace_line(FlatPtr address); String create_instruction_line(FlatPtr address, X86::Instruction insn); diff --git a/Userland/DevTools/UserspaceEmulator/MmapRegion.h b/Userland/DevTools/UserspaceEmulator/MmapRegion.h index c535c80aea..b39eaeee1b 100644 --- a/Userland/DevTools/UserspaceEmulator/MmapRegion.h +++ b/Userland/DevTools/UserspaceEmulator/MmapRegion.h @@ -52,6 +52,15 @@ public: void set_malloc_metadata(Badge<MallocTracer>, NonnullOwnPtr<MallocRegionMetadata> metadata) { m_malloc_metadata = move(metadata); } const String& name() const { return m_name; } + String lib_name() const + { + if (m_name.contains("Loader.so"sv)) + return "Loader.so"; + auto const maybe_separator = m_name.find(':'); + if (!maybe_separator.has_value()) + return {}; + return m_name.substring(0, *maybe_separator); + } void set_name(String name) { m_name = move(name); } private: diff --git a/Userland/DevTools/UserspaceEmulator/SoftMMU.h b/Userland/DevTools/UserspaceEmulator/SoftMMU.h index 8767fe2d87..c46e1c8e86 100644 --- a/Userland/DevTools/UserspaceEmulator/SoftMMU.h +++ b/Userland/DevTools/UserspaceEmulator/SoftMMU.h @@ -71,6 +71,16 @@ public: } } + template<typename Type, typename Callback> + void for_each_region_of_type(Callback callback) + { + return for_each_region([callback](auto& region) { + if (!is<Type>(region)) + return IterationDecision::Continue; + return callback(static_cast<Type&>(region)); + }); + } + template<typename Callback> void for_regions_in(X86::LogicalAddress address, size_t size, Callback callback) { |