From c9118b84b77bdbc2c66f7dd394244aa53019789e Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Tue, 27 Jul 2021 17:01:29 +0200 Subject: [PATCH] LibCoreDump: Make symbolication work when .text isn't the first segment This can happen with binaries built with Clang or with a custom linker script. --- Userland/Libraries/LibCoreDump/Backtrace.cpp | 10 +++++++--- Userland/Libraries/LibCoreDump/Reader.cpp | 13 +++++++++++++ Userland/Libraries/LibCoreDump/Reader.h | 1 + 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/Userland/Libraries/LibCoreDump/Backtrace.cpp b/Userland/Libraries/LibCoreDump/Backtrace.cpp index 9ce5c64695..68f20e7467 100644 --- a/Userland/Libraries/LibCoreDump/Backtrace.cpp +++ b/Userland/Libraries/LibCoreDump/Backtrace.cpp @@ -79,14 +79,18 @@ Backtrace::~Backtrace() void Backtrace::add_entry(const Reader& coredump, FlatPtr ip) { - auto* region = coredump.region_containing((FlatPtr)ip); - if (!region) { + auto* ip_region = coredump.region_containing((FlatPtr)ip); + if (!ip_region) { m_entries.append({ ip, {}, {}, {} }); return; } - auto object_name = region->object_name(); + auto object_name = ip_region->object_name(); if (object_name == "Loader.so") return; + // We need to find the first region for the object, just in case + // the PT_LOAD header for the .text segment isn't the first one + // in the object file. + auto region = coredump.first_region_for_object(object_name); auto* object_info = object_info_for_region(*region); if (!object_info) return; diff --git a/Userland/Libraries/LibCoreDump/Reader.cpp b/Userland/Libraries/LibCoreDump/Reader.cpp index da4a67b92d..2698a1e859 100644 --- a/Userland/Libraries/LibCoreDump/Reader.cpp +++ b/Userland/Libraries/LibCoreDump/Reader.cpp @@ -137,6 +137,19 @@ const JsonObject Reader::process_info() const // FIXME: Maybe just cache this on the Reader instance after first access. } +ELF::Core::MemoryRegionInfo const* Reader::first_region_for_object(StringView object_name) const +{ + ELF::Core::MemoryRegionInfo const* ret = nullptr; + for_each_memory_region_info([&ret, &object_name](auto& region_info) { + if (region_info.object_name() == object_name) { + ret = ®ion_info; + return IterationDecision::Break; + } + return IterationDecision::Continue; + }); + return ret; +} + const ELF::Core::MemoryRegionInfo* Reader::region_containing(FlatPtr address) const { const ELF::Core::MemoryRegionInfo* ret = nullptr; diff --git a/Userland/Libraries/LibCoreDump/Reader.h b/Userland/Libraries/LibCoreDump/Reader.h index 2e6116b7b9..fbfbde3537 100644 --- a/Userland/Libraries/LibCoreDump/Reader.h +++ b/Userland/Libraries/LibCoreDump/Reader.h @@ -32,6 +32,7 @@ public: const ELF::Image& image() const { return m_coredump_image; } Optional peek_memory(FlatPtr address) const; + ELF::Core::MemoryRegionInfo const* first_region_for_object(StringView object_name) const; const ELF::Core::MemoryRegionInfo* region_containing(FlatPtr address) const; struct LibraryData {