diff --git a/Applications/CrashDaemon/main.cpp b/Applications/CrashDaemon/main.cpp index a8a90f220bc..eca299c191d 100644 --- a/Applications/CrashDaemon/main.cpp +++ b/Applications/CrashDaemon/main.cpp @@ -30,9 +30,10 @@ #include #include #include +#include #include #include -#include +#include #include #include #include @@ -63,78 +64,62 @@ static String object_name(StringView memory_region_name) return memory_region_name.substring_view(0, memory_region_name.find_first_of(":").value()).to_string(); } -struct ElfObjectInfo : public RefCounted { - - ElfObjectInfo(MappedFile&& file, NonnullRefPtr&& loader, Debug::DebugInfo&& debug_info) +struct ElfObjectInfo { + ElfObjectInfo(MappedFile&& file, Debug::DebugInfo&& debug_info) : file(move(file)) - , loader(move(loader)) , debug_info(move(debug_info)) { } MappedFile file; - NonnullRefPtr loader; Debug::DebugInfo debug_info; }; // FIXME: This cache has to be invalidated when libraries/programs are re-compiled. // We can store the last-modified timestamp of the elf files in ElfObjectInfo to invalidate cache entries. -static HashMap> s_debug_info_cache; +static HashMap> s_debug_info_cache; -static RefPtr object_info_for_region(const ELF::Core::MemoryRegionInfo* region) +static const ElfObjectInfo* object_info_for_region(const ELF::Core::MemoryRegionInfo* region) { - StringView region_name { region->region_name }; - - auto name = object_name(region_name); + auto name = object_name(region->region_name); String path; if (name.contains(".so")) - path = String::format("/usr/lib/%s", name.characters()); + path = String::formatted("/usr/lib/{}", name); else { path = name; } - auto cached_value = s_debug_info_cache.get(path); - if (cached_value.has_value()) - return cached_value.value(); + if (auto it = s_debug_info_cache.find(path); it != s_debug_info_cache.end()) + return it->value.ptr(); - struct stat st; - if (stat(path.characters(), &st)) { + if (!Core::File::exists(path.characters())) return nullptr; - } MappedFile object_file(path); if (!object_file.is_valid()) return nullptr; - auto loader = ELF::Loader::create((const u8*)object_file.data(), object_file.size()); - Debug::DebugInfo debug_info(loader); - - RefPtr info = adopt(*new ElfObjectInfo( - move(object_file), - move(loader), - move(debug_info))); - - s_debug_info_cache.set(path, info); - return info; + auto info = make(move(object_file), Debug::DebugInfo { make((const u8*)object_file.data(), object_file.size()) }); + auto* info_ptr = info.ptr(); + s_debug_info_cache.set(path, move(info)); + return info_ptr; } static String backtrace_line(const CoreDumpReader& coredump, FlatPtr eip) { auto* region = coredump.region_containing((FlatPtr)eip); - if (!region) { + if (!region) return String::format("%p: ???", eip); - } - StringView region_name { region->region_name }; - if (region_name.contains("Loader.so")) + if (StringView { region->region_name }.contains("Loader.so")) return {}; - auto object_info = object_info_for_region(region); - if (object_info.is_null()) + auto* object_info = object_info_for_region(region); + if (!object_info) return {}; - auto func_name = object_info->loader->symbolicate(eip - region->region_start); + auto func_name = object_info->debug_info.elf().symbolicate(eip - region->region_start); auto source_position = object_info->debug_info.get_source_position(eip - region->region_start); @@ -142,7 +127,7 @@ static String backtrace_line(const CoreDumpReader& coredump, FlatPtr eip) if (source_position.has_value()) source_position_string = String::format(" (\033[34;1m%s\033[0m:%u)", LexicalPath(source_position.value().file_path).basename().characters(), source_position.value().line_number); - return String::format("%p: [%s] %s%s", eip, object_name(region_name).characters(), func_name.is_null() ? "???" : func_name.characters(), source_position_string.characters()); + return String::format("%p: [%s] %s%s", eip, object_name(region->region_name).characters(), func_name.is_null() ? "???" : func_name.characters(), source_position_string.characters()); } static void backtrace(const String& coredump_path) diff --git a/DevTools/HackStudio/Debugger/DisassemblyModel.cpp b/DevTools/HackStudio/Debugger/DisassemblyModel.cpp index ae0b72a8f9c..394abdd13ff 100644 --- a/DevTools/HackStudio/Debugger/DisassemblyModel.cpp +++ b/DevTools/HackStudio/Debugger/DisassemblyModel.cpp @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include #include #include @@ -44,25 +44,27 @@ DisassemblyModel::DisassemblyModel(const Debug::DebugSession& debug_session, con return; } - RefPtr elf_loader; + OwnPtr kernel_elf; + const ELF::Image* elf = nullptr; if (containing_function.value().address_low >= 0xc0000000) { auto kernel_file = make("/boot/Kernel"); if (!kernel_file->is_valid()) return; - elf_loader = ELF::Loader::create((const u8*)kernel_file->data(), kernel_file->size()); + kernel_elf = make((const u8*)kernel_file->data(), kernel_file->size()); + elf = kernel_elf.ptr(); } else { - elf_loader = debug_session.elf(); + elf = &debug_session.elf(); } - auto symbol = elf_loader->find_symbol(containing_function.value().address_low); + auto symbol = elf->find_symbol(containing_function.value().address_low); if (!symbol.has_value()) return; ASSERT(symbol.has_value()); auto view = symbol.value().raw_data(); - X86::ELFSymbolProvider symbol_provider(*elf_loader); + X86::ELFSymbolProvider symbol_provider(*elf); X86::SimpleInstructionStream stream((const u8*)view.characters_without_null_termination(), view.length()); X86::Disassembler disassembler(stream); diff --git a/DevTools/Profiler/DisassemblyModel.cpp b/DevTools/Profiler/DisassemblyModel.cpp index 9526db156ec..d45b165c2e4 100644 --- a/DevTools/Profiler/DisassemblyModel.cpp +++ b/DevTools/Profiler/DisassemblyModel.cpp @@ -27,7 +27,7 @@ #include "DisassemblyModel.h" #include "Profile.h" #include -#include +#include #include #include #include @@ -65,16 +65,16 @@ DisassemblyModel::DisassemblyModel(Profile& profile, ProfileNode& node) if (!m_file->is_valid()) return; - auto elf_loader = ELF::Loader::create((const u8*)m_file->data(), m_file->size()); + auto elf = ELF::Image((const u8*)m_file->data(), m_file->size()); - auto symbol = elf_loader->find_symbol(node.address()); + auto symbol = elf.find_symbol(node.address()); if (!symbol.has_value()) return; ASSERT(symbol.has_value()); auto view = symbol.value().raw_data(); - X86::ELFSymbolProvider symbol_provider(*elf_loader); + X86::ELFSymbolProvider symbol_provider(elf); X86::SimpleInstructionStream stream((const u8*)view.characters_without_null_termination(), view.length()); X86::Disassembler disassembler(stream); diff --git a/DevTools/Profiler/Profile.cpp b/DevTools/Profiler/Profile.cpp index 594d434d2f0..7449c6697ec 100644 --- a/DevTools/Profiler/Profile.cpp +++ b/DevTools/Profiler/Profile.cpp @@ -33,7 +33,7 @@ #include #include #include -#include +#include #include #include @@ -58,7 +58,7 @@ static String object_name(StringView memory_region_name) struct CachedLibData { OwnPtr file; - NonnullRefPtr lib_elf; + ELF::Image lib_elf; }; static String symbolicate(FlatPtr eip, const ELF::Core::MemoryRegionInfo* region, u32& offset) @@ -86,13 +86,13 @@ static String symbolicate(FlatPtr eip, const ELF::Core::MemoryRegionInfo* region auto lib_file = make(path); if (!lib_file->is_valid()) return {}; - auto loader = ELF::Loader::create((const u8*)lib_file->data(), lib_file->size()); - cached_libs.set(path, make(move(lib_file), loader)); + auto image = ELF::Image((const u8*)lib_file->data(), lib_file->size()); + cached_libs.set(path, make(move(lib_file), move(image))); } auto lib_data = cached_libs.get(path).value(); - return String::format("[%s] %s", name.characters(), lib_data->lib_elf->symbolicate(eip - region->region_start, &offset).characters()); + return String::format("[%s] %s", name.characters(), lib_data->lib_elf.symbolicate(eip - region->region_start, &offset).characters()); } static String symbolicate_from_coredump(CoreDumpReader& coredump, u32 ptr, [[maybe_unused]] u32& offset) @@ -288,9 +288,9 @@ OwnPtr Profile::load_from_perfcore_file(const StringView& path) } MappedFile kernel_elf_file("/boot/Kernel"); - RefPtr kernel_elf_loader; + OwnPtr kernel_elf; if (kernel_elf_file.is_valid()) - kernel_elf_loader = ELF::Loader::create(static_cast(kernel_elf_file.data()), kernel_elf_file.size()); + kernel_elf = make(static_cast(kernel_elf_file.data()), kernel_elf_file.size()); auto events_value = object.get("events"); if (!events_value.is_array()) @@ -325,8 +325,8 @@ OwnPtr Profile::load_from_perfcore_file(const StringView& path) String symbol; if (ptr >= 0xc0000000) { - if (kernel_elf_loader) { - symbol = kernel_elf_loader->symbolicate(ptr, &offset); + if (kernel_elf) { + symbol = kernel_elf->symbolicate(ptr, &offset); } else { symbol = "??"; } diff --git a/DevTools/UserspaceEmulator/Emulator.cpp b/DevTools/UserspaceEmulator/Emulator.cpp index 0436fbebd41..eacafb9e531 100644 --- a/DevTools/UserspaceEmulator/Emulator.cpp +++ b/DevTools/UserspaceEmulator/Emulator.cpp @@ -309,14 +309,13 @@ String Emulator::create_backtrace_line(FlatPtr address) if (!mapped_file.is_valid()) return minimal; - auto loader = ELF::Loader::create((const u8*)mapped_file.data(), mapped_file.size()); - auto debug_info = make(loader); - m_dynamic_library_cache.set(lib_path, CachedELF { move(mapped_file), move(loader), move(debug_info) }); + auto debug_info = make(make((const u8*)mapped_file.data(), mapped_file.size())); + m_dynamic_library_cache.set(lib_path, CachedELF { move(mapped_file), move(debug_info) }); } auto it = m_dynamic_library_cache.find(lib_path); - auto& loader = *it->value.elf_loader; - String symbol = loader.symbolicate(address - region->base()); + auto& elf = it->value.debug_info->elf(); + String symbol = elf.symbolicate(address - region->base()); auto line_without_source_info = String::format("=={%d}== %p [%s]: %s", getpid(), address, lib_name.characters(), symbol.characters()); diff --git a/DevTools/UserspaceEmulator/Emulator.h b/DevTools/UserspaceEmulator/Emulator.h index 2dfe223ce4e..5e37caa1e63 100644 --- a/DevTools/UserspaceEmulator/Emulator.h +++ b/DevTools/UserspaceEmulator/Emulator.h @@ -34,7 +34,7 @@ #include #include #include -#include +#include #include #include #include @@ -208,8 +208,7 @@ private: struct CachedELF { MappedFile mapped_file; - NonnullRefPtr elf_loader; - OwnPtr debug_info; + NonnullOwnPtr debug_info; }; HashMap m_dynamic_library_cache; diff --git a/DevTools/UserspaceEmulator/main.cpp b/DevTools/UserspaceEmulator/main.cpp index ec6c320d940..432c9a4a752 100644 --- a/DevTools/UserspaceEmulator/main.cpp +++ b/DevTools/UserspaceEmulator/main.cpp @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/Kernel/CMakeLists.txt b/Kernel/CMakeLists.txt index c5497e7303d..8ac692e8404 100644 --- a/Kernel/CMakeLists.txt +++ b/Kernel/CMakeLists.txt @@ -224,7 +224,6 @@ set(AK_SOURCES set(ELF_SOURCES ../Libraries/LibELF/Image.cpp - ../Libraries/LibELF/Loader.cpp ../Libraries/LibELF/Validation.cpp ) diff --git a/Kernel/Syscalls/module.cpp b/Kernel/Syscalls/module.cpp index bc402e226dd..0bcb75a2dee 100644 --- a/Kernel/Syscalls/module.cpp +++ b/Kernel/Syscalls/module.cpp @@ -29,7 +29,7 @@ #include #include #include -#include +#include namespace Kernel { diff --git a/Libraries/LibDebug/DebugInfo.cpp b/Libraries/LibDebug/DebugInfo.cpp index 6ceb72b4558..10204f23d30 100644 --- a/Libraries/LibDebug/DebugInfo.cpp +++ b/Libraries/LibDebug/DebugInfo.cpp @@ -35,9 +35,9 @@ namespace Debug { -DebugInfo::DebugInfo(NonnullRefPtr elf) - : m_elf(elf) - , m_dwarf_info(Dwarf::DwarfInfo::create(m_elf)) +DebugInfo::DebugInfo(NonnullOwnPtr elf) + : m_elf(move(elf)) + , m_dwarf_info(*m_elf) { prepare_variable_scopes(); prepare_lines(); @@ -45,7 +45,7 @@ DebugInfo::DebugInfo(NonnullRefPtr elf) void DebugInfo::prepare_variable_scopes() { - m_dwarf_info->for_each_compilation_unit([&](const Dwarf::CompilationUnit& unit) { + m_dwarf_info.for_each_compilation_unit([&](const Dwarf::CompilationUnit& unit) { auto root = unit.root_die(); parse_scopes_impl(root); }); @@ -102,7 +102,7 @@ void DebugInfo::parse_scopes_impl(const Dwarf::DIE& die) void DebugInfo::prepare_lines() { - auto section = m_elf->image().lookup_section(".debug_line"); + auto section = elf().lookup_section(".debug_line"); if (section.is_undefined()) return; diff --git a/Libraries/LibDebug/DebugInfo.h b/Libraries/LibDebug/DebugInfo.h index cb4fe30b8a1..bcb5db3cbcc 100644 --- a/Libraries/LibDebug/DebugInfo.h +++ b/Libraries/LibDebug/DebugInfo.h @@ -33,14 +33,16 @@ #include #include #include -#include +#include #include namespace Debug { class DebugInfo { public: - explicit DebugInfo(NonnullRefPtr elf); + explicit DebugInfo(NonnullOwnPtr); + + const ELF::Image& elf() const { return *m_elf; } struct SourcePosition { FlyString file_path; @@ -117,8 +119,8 @@ private: void parse_scopes_impl(const Dwarf::DIE& die); OwnPtr create_variable_info(const Dwarf::DIE& variable_die, const PtraceRegisters&) const; - NonnullRefPtr m_elf; - NonnullRefPtr m_dwarf_info; + NonnullOwnPtr m_elf; + Dwarf::DwarfInfo m_dwarf_info; Vector m_scopes; Vector m_sorted_lines; diff --git a/Libraries/LibDebug/DebugSession.cpp b/Libraries/LibDebug/DebugSession.cpp index 42f1ced66eb..27fb35edc9c 100644 --- a/Libraries/LibDebug/DebugSession.cpp +++ b/Libraries/LibDebug/DebugSession.cpp @@ -33,8 +33,7 @@ namespace Debug { DebugSession::DebugSession(pid_t pid) : m_debuggee_pid(pid) , m_executable(map_executable_for_process(pid)) - , m_elf(ELF::Loader::create(reinterpret_cast(m_executable.data()), m_executable.size())) - , m_debug_info(m_elf) + , m_debug_info(make(reinterpret_cast(m_executable.data()), m_executable.size())) { } diff --git a/Libraries/LibDebug/DebugSession.h b/Libraries/LibDebug/DebugSession.h index 6912eb59dcf..ff0c90fab50 100644 --- a/Libraries/LibDebug/DebugSession.h +++ b/Libraries/LibDebug/DebugSession.h @@ -35,7 +35,6 @@ #include #include #include -#include #include #include #include @@ -99,8 +98,7 @@ public: template void run(Callback callback); - const ELF::Loader& elf() const { return *m_elf; } - NonnullRefPtr elf_ref() const { return m_elf; } + const ELF::Image& elf() const { return m_debug_info.elf(); } const MappedFile& executable() const { return m_executable; } const DebugInfo& debug_info() const { return m_debug_info; } @@ -130,7 +128,6 @@ private: bool m_is_debuggee_dead { false }; MappedFile m_executable; - NonnullRefPtr m_elf; DebugInfo m_debug_info; HashMap m_breakpoints; diff --git a/Libraries/LibDebug/Dwarf/DwarfInfo.cpp b/Libraries/LibDebug/Dwarf/DwarfInfo.cpp index c1bd4a39c65..09717cfc715 100644 --- a/Libraries/LibDebug/Dwarf/DwarfInfo.cpp +++ b/Libraries/LibDebug/Dwarf/DwarfInfo.cpp @@ -30,7 +30,7 @@ namespace Debug::Dwarf { -DwarfInfo::DwarfInfo(NonnullRefPtr elf) +DwarfInfo::DwarfInfo(const ELF::Image& elf) : m_elf(elf) { m_debug_info_data = section_data(".debug_info"); @@ -42,7 +42,7 @@ DwarfInfo::DwarfInfo(NonnullRefPtr elf) ReadonlyBytes DwarfInfo::section_data(const String& section_name) const { - auto section = m_elf->image().lookup_section(section_name); + auto section = m_elf.lookup_section(section_name); if (section.is_undefined()) return {}; return section.bytes(); diff --git a/Libraries/LibDebug/Dwarf/DwarfInfo.h b/Libraries/LibDebug/Dwarf/DwarfInfo.h index 0a0222a78b4..59496e0e3b4 100644 --- a/Libraries/LibDebug/Dwarf/DwarfInfo.h +++ b/Libraries/LibDebug/Dwarf/DwarfInfo.h @@ -32,13 +32,13 @@ #include #include #include -#include +#include namespace Debug::Dwarf { -class DwarfInfo : public RefCounted { +class DwarfInfo { public: - static NonnullRefPtr create(NonnullRefPtr elf) { return adopt(*new DwarfInfo(move(elf))); } + explicit DwarfInfo(const ELF::Image&); ReadonlyBytes debug_info_data() const { return m_debug_info_data; } ReadonlyBytes abbreviation_data() const { return m_abbreviation_data; } @@ -48,12 +48,11 @@ public: void for_each_compilation_unit(Callback) const; private: - explicit DwarfInfo(NonnullRefPtr elf); void populate_compilation_units(); ReadonlyBytes section_data(const String& section_name) const; - NonnullRefPtr m_elf; + const ELF::Image& m_elf; ReadonlyBytes m_debug_info_data; ReadonlyBytes m_abbreviation_data; ReadonlyBytes m_debug_strings_data; diff --git a/Libraries/LibELF/Image.cpp b/Libraries/LibELF/Image.cpp index 085cb97aa3f..f455a7d98be 100644 --- a/Libraries/LibELF/Image.cpp +++ b/Libraries/LibELF/Image.cpp @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -323,4 +324,84 @@ Optional Image::find_demangled_function(const String& name) const return found; } +Optional Image::find_symbol(u32 address, u32* out_offset) const +{ + auto symbol_count = this->symbol_count(); + if (!symbol_count) + return {}; + + SortedSymbol* sorted_symbols = nullptr; + if (m_sorted_symbols.is_empty()) { + m_sorted_symbols.ensure_capacity(symbol_count); + for_each_symbol([this](auto& symbol) { + m_sorted_symbols.append({ symbol.value(), symbol.name(), {}, symbol }); + return IterationDecision::Continue; + }); + quick_sort(m_sorted_symbols, [](auto& a, auto& b) { + return a.address < b.address; + }); + } + sorted_symbols = m_sorted_symbols.data(); + + for (size_t i = 0; i < symbol_count; ++i) { + if (sorted_symbols[i].address > address) { + if (i == 0) + return {}; + auto& symbol = sorted_symbols[i - 1]; + if (out_offset) + *out_offset = address - symbol.address; + return symbol.symbol; + } + } + return {}; +} + +String Image::symbolicate(u32 address, u32* out_offset) const +{ + auto symbol_count = this->symbol_count(); + if (!symbol_count) { + if (out_offset) + *out_offset = 0; + return "??"; + } + SortedSymbol* sorted_symbols = nullptr; + + if (m_sorted_symbols.is_empty()) { + m_sorted_symbols.ensure_capacity(symbol_count); + for_each_symbol([this](auto& symbol) { + m_sorted_symbols.append({ symbol.value(), symbol.name(), {}, {} }); + return IterationDecision::Continue; + }); + quick_sort(m_sorted_symbols, [](auto& a, auto& b) { + return a.address < b.address; + }); + } + sorted_symbols = m_sorted_symbols.data(); + + for (size_t i = 0; i < symbol_count; ++i) { + if (sorted_symbols[i].address > address) { + if (i == 0) { + if (out_offset) + *out_offset = 0; + return "!!"; + } + auto& symbol = sorted_symbols[i - 1]; + + auto& demangled_name = symbol.demangled_name; + if (demangled_name.is_null()) { + demangled_name = demangle(symbol.name); + } + + if (out_offset) { + *out_offset = address - symbol.address; + return demangled_name; + } + return String::format("%s +%u", demangled_name.characters(), address - symbol.address); + } + } + if (out_offset) + *out_offset = 0; + return "??"; +} + } // end namespace ELF diff --git a/Libraries/LibELF/Image.h b/Libraries/LibELF/Image.h index 4cb941c0190..eb444ab4122 100644 --- a/Libraries/LibELF/Image.h +++ b/Libraries/LibELF/Image.h @@ -210,6 +210,10 @@ public: Optional find_demangled_function(const String& name) const; + bool has_symbols() const { return symbol_count(); } + String symbolicate(u32 address, u32* offset = nullptr) const; + Optional find_symbol(u32 address, u32* offset = nullptr) const; + private: const char* raw_data(unsigned offset) const; const Elf32_Ehdr& header() const; @@ -227,6 +231,15 @@ private: bool m_valid { false }; unsigned m_symbol_table_section_index { 0 }; unsigned m_string_table_section_index { 0 }; + + struct SortedSymbol { + u32 address; + StringView name; + String demangled_name; + Optional symbol; + }; + + mutable Vector m_sorted_symbols; }; template diff --git a/Libraries/LibELF/Loader.cpp b/Libraries/LibELF/Loader.cpp deleted file mode 100644 index 4b0bd25279f..00000000000 --- a/Libraries/LibELF/Loader.cpp +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (c) 2018-2020, Andreas Kling - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "Loader.h" -#include -#include -#include - -//#define Loader_DEBUG - -namespace ELF { - -Loader::Loader(const u8* buffer, size_t size, String&&, bool verbose_logging) - : m_image(buffer, size, verbose_logging) -{ - if (m_image.is_valid()) - m_symbol_count = m_image.symbol_count(); -} - -Loader::~Loader() -{ -} - -#ifndef KERNEL -Optional Loader::find_symbol(u32 address, u32* out_offset) const -{ - if (!m_symbol_count) - return {}; - - SortedSymbol* sorted_symbols = nullptr; - if (m_sorted_symbols.is_empty()) { - m_sorted_symbols.ensure_capacity(m_symbol_count); - m_image.for_each_symbol([this](auto& symbol) { - m_sorted_symbols.append({ symbol.value(), symbol.name(), {}, symbol }); - return IterationDecision::Continue; - }); - quick_sort(m_sorted_symbols, [](auto& a, auto& b) { - return a.address < b.address; - }); - } - sorted_symbols = m_sorted_symbols.data(); - - for (size_t i = 0; i < m_symbol_count; ++i) { - if (sorted_symbols[i].address > address) { - if (i == 0) - return {}; - auto& symbol = sorted_symbols[i - 1]; - if (out_offset) - *out_offset = address - symbol.address; - return symbol.symbol; - } - } - return {}; -} - -String Loader::symbolicate(u32 address, u32* out_offset) const -{ - if (!m_symbol_count) { - if (out_offset) - *out_offset = 0; - return "??"; - } - SortedSymbol* sorted_symbols = nullptr; - - if (m_sorted_symbols.is_empty()) { - m_sorted_symbols.ensure_capacity(m_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, [](auto& a, auto& b) { - return a.address < b.address; - }); - } - sorted_symbols = m_sorted_symbols.data(); - - for (size_t i = 0; i < m_symbol_count; ++i) { - if (sorted_symbols[i].address > address) { - if (i == 0) { - if (out_offset) - *out_offset = 0; - return "!!"; - } - auto& symbol = sorted_symbols[i - 1]; - - auto& demangled_name = symbol.demangled_name; - if (demangled_name.is_null()) { - demangled_name = demangle(symbol.name); - } - - if (out_offset) { - *out_offset = address - symbol.address; - return demangled_name; - } - return String::format("%s +%u", demangled_name.characters(), address - symbol.address); - } - } - if (out_offset) - *out_offset = 0; - return "??"; -} - -#endif - -} // end namespace ELF diff --git a/Libraries/LibELF/Loader.h b/Libraries/LibELF/Loader.h deleted file mode 100644 index afa6c391a50..00000000000 --- a/Libraries/LibELF/Loader.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2018-2020, Andreas Kling - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -#ifdef KERNEL -# include -namespace Kernel { -class Region; -} -#endif - -namespace ELF { - -class Loader : public RefCounted { -public: - static NonnullRefPtr create(const u8* data, size_t size, String&& name = String::empty(), bool verbose_logging = true) { return adopt(*new Loader(data, size, move(name), verbose_logging)); } - ~Loader(); - - VirtualAddress entry() const - { - return m_image.entry(); - } - const Image& image() const { return m_image; } - Optional find_demangled_function(const String& name) const - { - return m_image.find_demangled_function(name); - } - - bool has_symbols() const { return m_symbol_count; } - - String symbolicate(u32 address, u32* offset = nullptr) const; - Optional find_symbol(u32 address, u32* offset = nullptr) const; - -private: - explicit Loader(const u8*, size_t, String&& name, bool verbose_logging); - - bool layout(); - - Image m_image; - - size_t m_symbol_count { 0 }; - - struct SortedSymbol { - u32 address; - StringView name; - String demangled_name; - Optional symbol; - }; - - mutable Vector m_sorted_symbols; -}; - -} // end namespace ELF diff --git a/Libraries/LibX86/ELFSymbolProvider.h b/Libraries/LibX86/ELFSymbolProvider.h index 3a9b94a40c8..f208cec0a08 100644 --- a/Libraries/LibX86/ELFSymbolProvider.h +++ b/Libraries/LibX86/ELFSymbolProvider.h @@ -26,23 +26,23 @@ #pragma once -#include +#include namespace X86 { class ELFSymbolProvider final : public SymbolProvider { public: - ELFSymbolProvider(ELF::Loader& loader) - : m_loader(loader) + ELFSymbolProvider(const ELF::Image& elf) + : m_elf(elf) { } virtual String symbolicate(FlatPtr address, u32* offset = nullptr) const override { - return m_loader.symbolicate(address, offset); + return m_elf.symbolicate(address, offset); } private: - ELF::Loader& m_loader; + const ELF::Image& m_elf; }; } diff --git a/Meta/Lagom/Fuzzers/FuzzELF.cpp b/Meta/Lagom/Fuzzers/FuzzELF.cpp index b87467dfb6e..cda7018238e 100644 --- a/Meta/Lagom/Fuzzers/FuzzELF.cpp +++ b/Meta/Lagom/Fuzzers/FuzzELF.cpp @@ -24,12 +24,12 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include +#include #include #include extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - ELF::Loader::create(data, size, /*name=*/ {}, /*verbose_logging=*/false); + ELF::Image elf(data, size, /*verbose_logging=*/false); return 0; } diff --git a/Userland/DynamicLoader/main.cpp b/Userland/DynamicLoader/main.cpp index 5c9049f1ef2..6eb7a872165 100644 --- a/Userland/DynamicLoader/main.cpp +++ b/Userland/DynamicLoader/main.cpp @@ -38,7 +38,6 @@ #include #include #include -#include #include #include #include diff --git a/Userland/disasm.cpp b/Userland/disasm.cpp index 6d3a82d0474..4189499000b 100644 --- a/Userland/disasm.cpp +++ b/Userland/disasm.cpp @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include #include @@ -70,14 +70,13 @@ int main(int argc, char** argv) size_t asm_size = file.size(); size_t file_offset = 0; Vector::Iterator current_symbol = symbols.begin(); - RefPtr elf; OwnPtr symbol_provider; // nullptr for non-ELF disassembly. + OwnPtr elf; if (asm_size >= 4 && strncmp((const char*)asm_data, "\u007fELF", 4) == 0) { - NonnullRefPtr elf_loader = ELF::Loader::create(asm_data, asm_size); - if (elf_loader->image().is_valid()) { - elf = elf_loader; + elf = make(asm_data, asm_size); + if (elf->is_valid()) { symbol_provider = make(*elf); - elf->image().for_each_section_of_type(SHT_PROGBITS, [&](const ELF::Image::Section& section) { + elf->for_each_section_of_type(SHT_PROGBITS, [&](const ELF::Image::Section& section) { // FIXME: Disassemble all SHT_PROGBITS sections, not just .text. if (section.name() != ".text") return IterationDecision::Continue; @@ -86,9 +85,9 @@ int main(int argc, char** argv) file_offset = section.address(); return IterationDecision::Break; }); - symbols.ensure_capacity(elf->image().symbol_count() + 1); + symbols.ensure_capacity(elf->symbol_count() + 1); symbols.append({ 0, 0, StringView() }); // Sentinel. - elf->image().for_each_symbol([&](const ELF::Image::Symbol& symbol) { + elf->for_each_symbol([&](const ELF::Image::Symbol& symbol) { symbols.append({ symbol.value(), symbol.size(), symbol.name() }); return IterationDecision::Continue; }); diff --git a/Userland/functrace.cpp b/Userland/functrace.cpp index 972b4941201..44888fb66e0 100644 --- a/Userland/functrace.cpp +++ b/Userland/functrace.cpp @@ -86,7 +86,7 @@ static NonnullOwnPtr> instrument_code() { [[maybe_unused]] auto r = demangle("foo"); // Required for linked with __cxa_demangle auto instrumented = make>(); - g_debug_session->elf().image().for_each_section_of_type(SHT_PROGBITS, [&](const ELF::Image::Section& section) { + g_debug_session->elf().for_each_section_of_type(SHT_PROGBITS, [&](const ELF::Image::Section& section) { if (section.name() != ".text") return IterationDecision::Continue;