mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 14:42:44 +00:00 
			
		
		
		
	LibELF: Remove ELF::Loader and move everyone to ELF::Image
This commit gets rid of ELF::Loader entirely since its very ambiguous purpose was actually to load executables for the kernel, and that is now handled by the kernel itself. This patch includes some drive-by cleanup in LibDebug and CrashDaemon enabled by the fact that we no longer need to keep the ref-counted ELF::Loader around.
This commit is contained in:
		
							parent
							
								
									7551a66f73
								
							
						
					
					
						commit
						1e4c010643
					
				
					 24 changed files with 178 additions and 318 deletions
				
			
		|  | @ -30,9 +30,10 @@ | ||||||
| #include <AK/LogStream.h> | #include <AK/LogStream.h> | ||||||
| #include <AK/ScopeGuard.h> | #include <AK/ScopeGuard.h> | ||||||
| #include <LibCore/DirectoryWatcher.h> | #include <LibCore/DirectoryWatcher.h> | ||||||
|  | #include <LibCore/File.h> | ||||||
| #include <LibCoreDump/CoreDumpReader.h> | #include <LibCoreDump/CoreDumpReader.h> | ||||||
| #include <LibDebug/DebugInfo.h> | #include <LibDebug/DebugInfo.h> | ||||||
| #include <LibELF/Loader.h> | #include <LibELF/Image.h> | ||||||
| #include <fcntl.h> | #include <fcntl.h> | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
| #include <sys/stat.h> | #include <sys/stat.h> | ||||||
|  | @ -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(); |     return memory_region_name.substring_view(0, memory_region_name.find_first_of(":").value()).to_string(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| struct ElfObjectInfo : public RefCounted<ElfObjectInfo> { | struct ElfObjectInfo { | ||||||
| 
 |     ElfObjectInfo(MappedFile&& file, Debug::DebugInfo&& debug_info) | ||||||
|     ElfObjectInfo(MappedFile&& file, NonnullRefPtr<ELF::Loader>&& loader, Debug::DebugInfo&& debug_info) |  | ||||||
|         : file(move(file)) |         : file(move(file)) | ||||||
|         , loader(move(loader)) |  | ||||||
|         , debug_info(move(debug_info)) |         , debug_info(move(debug_info)) | ||||||
|     { |     { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     MappedFile file; |     MappedFile file; | ||||||
|     NonnullRefPtr<ELF::Loader> loader; |  | ||||||
|     Debug::DebugInfo debug_info; |     Debug::DebugInfo debug_info; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| // FIXME: This cache has to be invalidated when libraries/programs are re-compiled.
 | // 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.
 | // We can store the last-modified timestamp of the elf files in ElfObjectInfo to invalidate cache entries.
 | ||||||
| static HashMap<String, RefPtr<ElfObjectInfo>> s_debug_info_cache; | static HashMap<String, NonnullOwnPtr<ElfObjectInfo>> s_debug_info_cache; | ||||||
| 
 | 
 | ||||||
| static RefPtr<ElfObjectInfo> 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->region_name); | ||||||
| 
 |  | ||||||
|     auto name = object_name(region_name); |  | ||||||
| 
 | 
 | ||||||
|     String path; |     String path; | ||||||
|     if (name.contains(".so")) |     if (name.contains(".so")) | ||||||
|         path = String::format("/usr/lib/%s", name.characters()); |         path = String::formatted("/usr/lib/{}", name); | ||||||
|     else { |     else { | ||||||
|         path = name; |         path = name; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     auto cached_value = s_debug_info_cache.get(path); |     if (auto it = s_debug_info_cache.find(path); it != s_debug_info_cache.end()) | ||||||
|     if (cached_value.has_value()) |         return it->value.ptr(); | ||||||
|         return cached_value.value(); |  | ||||||
| 
 | 
 | ||||||
|     struct stat st; |     if (!Core::File::exists(path.characters())) | ||||||
|     if (stat(path.characters(), &st)) { |  | ||||||
|         return nullptr; |         return nullptr; | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     MappedFile object_file(path); |     MappedFile object_file(path); | ||||||
|     if (!object_file.is_valid()) |     if (!object_file.is_valid()) | ||||||
|         return nullptr; |         return nullptr; | ||||||
| 
 | 
 | ||||||
|     auto loader = ELF::Loader::create((const u8*)object_file.data(), object_file.size()); |     auto info = make<ElfObjectInfo>(move(object_file), Debug::DebugInfo { make<ELF::Image>((const u8*)object_file.data(), object_file.size()) }); | ||||||
|     Debug::DebugInfo debug_info(loader); |     auto* info_ptr = info.ptr(); | ||||||
| 
 |     s_debug_info_cache.set(path, move(info)); | ||||||
|     RefPtr<ElfObjectInfo> info = adopt(*new ElfObjectInfo( |     return info_ptr; | ||||||
|         move(object_file), |  | ||||||
|         move(loader), |  | ||||||
|         move(debug_info))); |  | ||||||
| 
 |  | ||||||
|     s_debug_info_cache.set(path, info); |  | ||||||
|     return info; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static String backtrace_line(const CoreDumpReader& coredump, FlatPtr eip) | static String backtrace_line(const CoreDumpReader& coredump, FlatPtr eip) | ||||||
| { | { | ||||||
|     auto* region = coredump.region_containing((FlatPtr)eip); |     auto* region = coredump.region_containing((FlatPtr)eip); | ||||||
|     if (!region) { |     if (!region) | ||||||
|         return String::format("%p: ???", eip); |         return String::format("%p: ???", eip); | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     StringView region_name { region->region_name }; |     if (StringView { region->region_name }.contains("Loader.so")) | ||||||
|     if (region_name.contains("Loader.so")) |  | ||||||
|         return {}; |         return {}; | ||||||
| 
 | 
 | ||||||
|     auto object_info = object_info_for_region(region); |     auto* object_info = object_info_for_region(region); | ||||||
|     if (object_info.is_null()) |     if (!object_info) | ||||||
|         return {}; |         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); |     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()) |     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); |         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) | static void backtrace(const String& coredump_path) | ||||||
|  |  | ||||||
|  | @ -28,7 +28,7 @@ | ||||||
| #include <AK/MappedFile.h> | #include <AK/MappedFile.h> | ||||||
| #include <AK/StringBuilder.h> | #include <AK/StringBuilder.h> | ||||||
| #include <LibDebug/DebugSession.h> | #include <LibDebug/DebugSession.h> | ||||||
| #include <LibELF/Loader.h> | #include <LibELF/Image.h> | ||||||
| #include <LibX86/Disassembler.h> | #include <LibX86/Disassembler.h> | ||||||
| #include <LibX86/ELFSymbolProvider.h> | #include <LibX86/ELFSymbolProvider.h> | ||||||
| #include <ctype.h> | #include <ctype.h> | ||||||
|  | @ -44,25 +44,27 @@ DisassemblyModel::DisassemblyModel(const Debug::DebugSession& debug_session, con | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     RefPtr<ELF::Loader> elf_loader; |     OwnPtr<ELF::Image> kernel_elf; | ||||||
|  |     const ELF::Image* elf = nullptr; | ||||||
| 
 | 
 | ||||||
|     if (containing_function.value().address_low >= 0xc0000000) { |     if (containing_function.value().address_low >= 0xc0000000) { | ||||||
|         auto kernel_file = make<MappedFile>("/boot/Kernel"); |         auto kernel_file = make<MappedFile>("/boot/Kernel"); | ||||||
|         if (!kernel_file->is_valid()) |         if (!kernel_file->is_valid()) | ||||||
|             return; |             return; | ||||||
|         elf_loader = ELF::Loader::create((const u8*)kernel_file->data(), kernel_file->size()); |         kernel_elf = make<ELF::Image>((const u8*)kernel_file->data(), kernel_file->size()); | ||||||
|  |         elf = kernel_elf.ptr(); | ||||||
|     } else { |     } 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()) |     if (!symbol.has_value()) | ||||||
|         return; |         return; | ||||||
|     ASSERT(symbol.has_value()); |     ASSERT(symbol.has_value()); | ||||||
| 
 | 
 | ||||||
|     auto view = symbol.value().raw_data(); |     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::SimpleInstructionStream stream((const u8*)view.characters_without_null_termination(), view.length()); | ||||||
|     X86::Disassembler disassembler(stream); |     X86::Disassembler disassembler(stream); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -27,7 +27,7 @@ | ||||||
| #include "DisassemblyModel.h" | #include "DisassemblyModel.h" | ||||||
| #include "Profile.h" | #include "Profile.h" | ||||||
| #include <AK/MappedFile.h> | #include <AK/MappedFile.h> | ||||||
| #include <LibELF/Loader.h> | #include <LibELF/Image.h> | ||||||
| #include <LibGUI/Painter.h> | #include <LibGUI/Painter.h> | ||||||
| #include <LibX86/Disassembler.h> | #include <LibX86/Disassembler.h> | ||||||
| #include <LibX86/ELFSymbolProvider.h> | #include <LibX86/ELFSymbolProvider.h> | ||||||
|  | @ -65,16 +65,16 @@ DisassemblyModel::DisassemblyModel(Profile& profile, ProfileNode& node) | ||||||
|     if (!m_file->is_valid()) |     if (!m_file->is_valid()) | ||||||
|         return; |         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()) |     if (!symbol.has_value()) | ||||||
|         return; |         return; | ||||||
|     ASSERT(symbol.has_value()); |     ASSERT(symbol.has_value()); | ||||||
| 
 | 
 | ||||||
|     auto view = symbol.value().raw_data(); |     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::SimpleInstructionStream stream((const u8*)view.characters_without_null_termination(), view.length()); | ||||||
|     X86::Disassembler disassembler(stream); |     X86::Disassembler disassembler(stream); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -33,7 +33,7 @@ | ||||||
| #include <AK/RefPtr.h> | #include <AK/RefPtr.h> | ||||||
| #include <LibCore/File.h> | #include <LibCore/File.h> | ||||||
| #include <LibCoreDump/CoreDumpReader.h> | #include <LibCoreDump/CoreDumpReader.h> | ||||||
| #include <LibELF/Loader.h> | #include <LibELF/Image.h> | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
| #include <sys/stat.h> | #include <sys/stat.h> | ||||||
| 
 | 
 | ||||||
|  | @ -58,7 +58,7 @@ static String object_name(StringView memory_region_name) | ||||||
| 
 | 
 | ||||||
| struct CachedLibData { | struct CachedLibData { | ||||||
|     OwnPtr<MappedFile> file; |     OwnPtr<MappedFile> file; | ||||||
|     NonnullRefPtr<ELF::Loader> lib_elf; |     ELF::Image lib_elf; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static String symbolicate(FlatPtr eip, const ELF::Core::MemoryRegionInfo* region, u32& offset) | 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<MappedFile>(path); |         auto lib_file = make<MappedFile>(path); | ||||||
|         if (!lib_file->is_valid()) |         if (!lib_file->is_valid()) | ||||||
|             return {}; |             return {}; | ||||||
|         auto loader = ELF::Loader::create((const u8*)lib_file->data(), lib_file->size()); |         auto image = ELF::Image((const u8*)lib_file->data(), lib_file->size()); | ||||||
|         cached_libs.set(path, make<CachedLibData>(move(lib_file), loader)); |         cached_libs.set(path, make<CachedLibData>(move(lib_file), move(image))); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     auto lib_data = cached_libs.get(path).value(); |     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) | static String symbolicate_from_coredump(CoreDumpReader& coredump, u32 ptr, [[maybe_unused]] u32& offset) | ||||||
|  | @ -288,9 +288,9 @@ OwnPtr<Profile> Profile::load_from_perfcore_file(const StringView& path) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     MappedFile kernel_elf_file("/boot/Kernel"); |     MappedFile kernel_elf_file("/boot/Kernel"); | ||||||
|     RefPtr<ELF::Loader> kernel_elf_loader; |     OwnPtr<ELF::Image> kernel_elf; | ||||||
|     if (kernel_elf_file.is_valid()) |     if (kernel_elf_file.is_valid()) | ||||||
|         kernel_elf_loader = ELF::Loader::create(static_cast<const u8*>(kernel_elf_file.data()), kernel_elf_file.size()); |         kernel_elf = make<ELF::Image>(static_cast<const u8*>(kernel_elf_file.data()), kernel_elf_file.size()); | ||||||
| 
 | 
 | ||||||
|     auto events_value = object.get("events"); |     auto events_value = object.get("events"); | ||||||
|     if (!events_value.is_array()) |     if (!events_value.is_array()) | ||||||
|  | @ -325,8 +325,8 @@ OwnPtr<Profile> Profile::load_from_perfcore_file(const StringView& path) | ||||||
|             String symbol; |             String symbol; | ||||||
| 
 | 
 | ||||||
|             if (ptr >= 0xc0000000) { |             if (ptr >= 0xc0000000) { | ||||||
|                 if (kernel_elf_loader) { |                 if (kernel_elf) { | ||||||
|                     symbol = kernel_elf_loader->symbolicate(ptr, &offset); |                     symbol = kernel_elf->symbolicate(ptr, &offset); | ||||||
|                 } else { |                 } else { | ||||||
|                     symbol = "??"; |                     symbol = "??"; | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|  | @ -309,14 +309,13 @@ String Emulator::create_backtrace_line(FlatPtr address) | ||||||
|         if (!mapped_file.is_valid()) |         if (!mapped_file.is_valid()) | ||||||
|             return minimal; |             return minimal; | ||||||
| 
 | 
 | ||||||
|         auto loader = ELF::Loader::create((const u8*)mapped_file.data(), mapped_file.size()); |         auto debug_info = make<Debug::DebugInfo>(make<ELF::Image>((const u8*)mapped_file.data(), mapped_file.size())); | ||||||
|         auto debug_info = make<Debug::DebugInfo>(loader); |         m_dynamic_library_cache.set(lib_path, CachedELF { move(mapped_file), move(debug_info) }); | ||||||
|         m_dynamic_library_cache.set(lib_path, CachedELF { move(mapped_file), move(loader), move(debug_info) }); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     auto it = m_dynamic_library_cache.find(lib_path); |     auto it = m_dynamic_library_cache.find(lib_path); | ||||||
|     auto& loader = *it->value.elf_loader; |     auto& elf = it->value.debug_info->elf(); | ||||||
|     String symbol = loader.symbolicate(address - region->base()); |     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()); |     auto line_without_source_info = String::format("=={%d}==    %p  [%s]: %s", getpid(), address, lib_name.characters(), symbol.characters()); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -34,7 +34,7 @@ | ||||||
| #include <AK/Types.h> | #include <AK/Types.h> | ||||||
| #include <LibDebug/DebugInfo.h> | #include <LibDebug/DebugInfo.h> | ||||||
| #include <LibELF/AuxiliaryVector.h> | #include <LibELF/AuxiliaryVector.h> | ||||||
| #include <LibELF/Loader.h> | #include <LibELF/Image.h> | ||||||
| #include <LibX86/Instruction.h> | #include <LibX86/Instruction.h> | ||||||
| #include <signal.h> | #include <signal.h> | ||||||
| #include <sys/types.h> | #include <sys/types.h> | ||||||
|  | @ -208,8 +208,7 @@ private: | ||||||
| 
 | 
 | ||||||
|     struct CachedELF { |     struct CachedELF { | ||||||
|         MappedFile mapped_file; |         MappedFile mapped_file; | ||||||
|         NonnullRefPtr<ELF::Loader> elf_loader; |         NonnullOwnPtr<Debug::DebugInfo> debug_info; | ||||||
|         OwnPtr<Debug::DebugInfo> debug_info; |  | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     HashMap<String, CachedELF> m_dynamic_library_cache; |     HashMap<String, CachedELF> m_dynamic_library_cache; | ||||||
|  |  | ||||||
|  | @ -32,7 +32,7 @@ | ||||||
| #include <AK/StringBuilder.h> | #include <AK/StringBuilder.h> | ||||||
| #include <LibCore/ArgsParser.h> | #include <LibCore/ArgsParser.h> | ||||||
| #include <LibCore/DirIterator.h> | #include <LibCore/DirIterator.h> | ||||||
| #include <LibELF/Loader.h> | #include <LibELF/Image.h> | ||||||
| #include <getopt.h> | #include <getopt.h> | ||||||
| #include <pthread.h> | #include <pthread.h> | ||||||
| #include <string.h> | #include <string.h> | ||||||
|  |  | ||||||
|  | @ -224,7 +224,6 @@ set(AK_SOURCES | ||||||
| 
 | 
 | ||||||
| set(ELF_SOURCES | set(ELF_SOURCES | ||||||
|     ../Libraries/LibELF/Image.cpp |     ../Libraries/LibELF/Image.cpp | ||||||
|     ../Libraries/LibELF/Loader.cpp |  | ||||||
|     ../Libraries/LibELF/Validation.cpp |     ../Libraries/LibELF/Validation.cpp | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -29,7 +29,7 @@ | ||||||
| #include <Kernel/KSyms.h> | #include <Kernel/KSyms.h> | ||||||
| #include <Kernel/Module.h> | #include <Kernel/Module.h> | ||||||
| #include <Kernel/Process.h> | #include <Kernel/Process.h> | ||||||
| #include <LibELF/Loader.h> | #include <LibELF/Image.h> | ||||||
| 
 | 
 | ||||||
| namespace Kernel { | namespace Kernel { | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -35,9 +35,9 @@ | ||||||
| 
 | 
 | ||||||
| namespace Debug { | namespace Debug { | ||||||
| 
 | 
 | ||||||
| DebugInfo::DebugInfo(NonnullRefPtr<const ELF::Loader> elf) | DebugInfo::DebugInfo(NonnullOwnPtr<const ELF::Image> elf) | ||||||
|     : m_elf(elf) |     : m_elf(move(elf)) | ||||||
|     , m_dwarf_info(Dwarf::DwarfInfo::create(m_elf)) |     , m_dwarf_info(*m_elf) | ||||||
| { | { | ||||||
|     prepare_variable_scopes(); |     prepare_variable_scopes(); | ||||||
|     prepare_lines(); |     prepare_lines(); | ||||||
|  | @ -45,7 +45,7 @@ DebugInfo::DebugInfo(NonnullRefPtr<const ELF::Loader> elf) | ||||||
| 
 | 
 | ||||||
| void DebugInfo::prepare_variable_scopes() | 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(); |         auto root = unit.root_die(); | ||||||
|         parse_scopes_impl(root); |         parse_scopes_impl(root); | ||||||
|     }); |     }); | ||||||
|  | @ -102,7 +102,7 @@ void DebugInfo::parse_scopes_impl(const Dwarf::DIE& die) | ||||||
| 
 | 
 | ||||||
| void DebugInfo::prepare_lines() | void DebugInfo::prepare_lines() | ||||||
| { | { | ||||||
|     auto section = m_elf->image().lookup_section(".debug_line"); |     auto section = elf().lookup_section(".debug_line"); | ||||||
|     if (section.is_undefined()) |     if (section.is_undefined()) | ||||||
|         return; |         return; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -33,14 +33,16 @@ | ||||||
| #include <LibDebug/Dwarf/DIE.h> | #include <LibDebug/Dwarf/DIE.h> | ||||||
| #include <LibDebug/Dwarf/DwarfInfo.h> | #include <LibDebug/Dwarf/DwarfInfo.h> | ||||||
| #include <LibDebug/Dwarf/LineProgram.h> | #include <LibDebug/Dwarf/LineProgram.h> | ||||||
| #include <LibELF/Loader.h> | #include <LibELF/Image.h> | ||||||
| #include <sys/arch/i386/regs.h> | #include <sys/arch/i386/regs.h> | ||||||
| 
 | 
 | ||||||
| namespace Debug { | namespace Debug { | ||||||
| 
 | 
 | ||||||
| class DebugInfo { | class DebugInfo { | ||||||
| public: | public: | ||||||
|     explicit DebugInfo(NonnullRefPtr<const ELF::Loader> elf); |     explicit DebugInfo(NonnullOwnPtr<const ELF::Image>); | ||||||
|  | 
 | ||||||
|  |     const ELF::Image& elf() const { return *m_elf; } | ||||||
| 
 | 
 | ||||||
|     struct SourcePosition { |     struct SourcePosition { | ||||||
|         FlyString file_path; |         FlyString file_path; | ||||||
|  | @ -117,8 +119,8 @@ private: | ||||||
|     void parse_scopes_impl(const Dwarf::DIE& die); |     void parse_scopes_impl(const Dwarf::DIE& die); | ||||||
|     OwnPtr<VariableInfo> create_variable_info(const Dwarf::DIE& variable_die, const PtraceRegisters&) const; |     OwnPtr<VariableInfo> create_variable_info(const Dwarf::DIE& variable_die, const PtraceRegisters&) const; | ||||||
| 
 | 
 | ||||||
|     NonnullRefPtr<const ELF::Loader> m_elf; |     NonnullOwnPtr<const ELF::Image> m_elf; | ||||||
|     NonnullRefPtr<Dwarf::DwarfInfo> m_dwarf_info; |     Dwarf::DwarfInfo m_dwarf_info; | ||||||
| 
 | 
 | ||||||
|     Vector<VariablesScope> m_scopes; |     Vector<VariablesScope> m_scopes; | ||||||
|     Vector<Dwarf::LineProgram::LineInfo> m_sorted_lines; |     Vector<Dwarf::LineProgram::LineInfo> m_sorted_lines; | ||||||
|  |  | ||||||
|  | @ -33,8 +33,7 @@ namespace Debug { | ||||||
| DebugSession::DebugSession(pid_t pid) | DebugSession::DebugSession(pid_t pid) | ||||||
|     : m_debuggee_pid(pid) |     : m_debuggee_pid(pid) | ||||||
|     , m_executable(map_executable_for_process(pid)) |     , m_executable(map_executable_for_process(pid)) | ||||||
|     , m_elf(ELF::Loader::create(reinterpret_cast<const u8*>(m_executable.data()), m_executable.size())) |     , m_debug_info(make<ELF::Image>(reinterpret_cast<const u8*>(m_executable.data()), m_executable.size())) | ||||||
|     , m_debug_info(m_elf) |  | ||||||
| { | { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -35,7 +35,6 @@ | ||||||
| #include <AK/String.h> | #include <AK/String.h> | ||||||
| #include <LibC/sys/arch/i386/regs.h> | #include <LibC/sys/arch/i386/regs.h> | ||||||
| #include <LibDebug/DebugInfo.h> | #include <LibDebug/DebugInfo.h> | ||||||
| #include <LibELF/Loader.h> |  | ||||||
| #include <signal.h> | #include <signal.h> | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
| #include <sys/ptrace.h> | #include <sys/ptrace.h> | ||||||
|  | @ -99,8 +98,7 @@ public: | ||||||
|     template<typename Callback> |     template<typename Callback> | ||||||
|     void run(Callback callback); |     void run(Callback callback); | ||||||
| 
 | 
 | ||||||
|     const ELF::Loader& elf() const { return *m_elf; } |     const ELF::Image& elf() const { return m_debug_info.elf(); } | ||||||
|     NonnullRefPtr<const ELF::Loader> elf_ref() const { return m_elf; } |  | ||||||
|     const MappedFile& executable() const { return m_executable; } |     const MappedFile& executable() const { return m_executable; } | ||||||
|     const DebugInfo& debug_info() const { return m_debug_info; } |     const DebugInfo& debug_info() const { return m_debug_info; } | ||||||
| 
 | 
 | ||||||
|  | @ -130,7 +128,6 @@ private: | ||||||
|     bool m_is_debuggee_dead { false }; |     bool m_is_debuggee_dead { false }; | ||||||
| 
 | 
 | ||||||
|     MappedFile m_executable; |     MappedFile m_executable; | ||||||
|     NonnullRefPtr<const ELF::Loader> m_elf; |  | ||||||
|     DebugInfo m_debug_info; |     DebugInfo m_debug_info; | ||||||
| 
 | 
 | ||||||
|     HashMap<void*, BreakPoint> m_breakpoints; |     HashMap<void*, BreakPoint> m_breakpoints; | ||||||
|  |  | ||||||
|  | @ -30,7 +30,7 @@ | ||||||
| 
 | 
 | ||||||
| namespace Debug::Dwarf { | namespace Debug::Dwarf { | ||||||
| 
 | 
 | ||||||
| DwarfInfo::DwarfInfo(NonnullRefPtr<const ELF::Loader> elf) | DwarfInfo::DwarfInfo(const ELF::Image& elf) | ||||||
|     : m_elf(elf) |     : m_elf(elf) | ||||||
| { | { | ||||||
|     m_debug_info_data = section_data(".debug_info"); |     m_debug_info_data = section_data(".debug_info"); | ||||||
|  | @ -42,7 +42,7 @@ DwarfInfo::DwarfInfo(NonnullRefPtr<const ELF::Loader> elf) | ||||||
| 
 | 
 | ||||||
| ReadonlyBytes DwarfInfo::section_data(const String& section_name) const | 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()) |     if (section.is_undefined()) | ||||||
|         return {}; |         return {}; | ||||||
|     return section.bytes(); |     return section.bytes(); | ||||||
|  |  | ||||||
|  | @ -32,13 +32,13 @@ | ||||||
| #include <AK/NonnullRefPtr.h> | #include <AK/NonnullRefPtr.h> | ||||||
| #include <AK/RefCounted.h> | #include <AK/RefCounted.h> | ||||||
| #include <AK/String.h> | #include <AK/String.h> | ||||||
| #include <LibELF/Loader.h> | #include <LibELF/Image.h> | ||||||
| 
 | 
 | ||||||
| namespace Debug::Dwarf { | namespace Debug::Dwarf { | ||||||
| 
 | 
 | ||||||
| class DwarfInfo : public RefCounted<DwarfInfo> { | class DwarfInfo { | ||||||
| public: | public: | ||||||
|     static NonnullRefPtr<DwarfInfo> create(NonnullRefPtr<const ELF::Loader> elf) { return adopt(*new DwarfInfo(move(elf))); } |     explicit DwarfInfo(const ELF::Image&); | ||||||
| 
 | 
 | ||||||
|     ReadonlyBytes debug_info_data() const { return m_debug_info_data; } |     ReadonlyBytes debug_info_data() const { return m_debug_info_data; } | ||||||
|     ReadonlyBytes abbreviation_data() const { return m_abbreviation_data; } |     ReadonlyBytes abbreviation_data() const { return m_abbreviation_data; } | ||||||
|  | @ -48,12 +48,11 @@ public: | ||||||
|     void for_each_compilation_unit(Callback) const; |     void for_each_compilation_unit(Callback) const; | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     explicit DwarfInfo(NonnullRefPtr<const ELF::Loader> elf); |  | ||||||
|     void populate_compilation_units(); |     void populate_compilation_units(); | ||||||
| 
 | 
 | ||||||
|     ReadonlyBytes section_data(const String& section_name) const; |     ReadonlyBytes section_data(const String& section_name) const; | ||||||
| 
 | 
 | ||||||
|     NonnullRefPtr<const ELF::Loader> m_elf; |     const ELF::Image& m_elf; | ||||||
|     ReadonlyBytes m_debug_info_data; |     ReadonlyBytes m_debug_info_data; | ||||||
|     ReadonlyBytes m_abbreviation_data; |     ReadonlyBytes m_abbreviation_data; | ||||||
|     ReadonlyBytes m_debug_strings_data; |     ReadonlyBytes m_debug_strings_data; | ||||||
|  |  | ||||||
|  | @ -26,6 +26,7 @@ | ||||||
| 
 | 
 | ||||||
| #include <AK/Demangle.h> | #include <AK/Demangle.h> | ||||||
| #include <AK/Memory.h> | #include <AK/Memory.h> | ||||||
|  | #include <AK/QuickSort.h> | ||||||
| #include <AK/StringBuilder.h> | #include <AK/StringBuilder.h> | ||||||
| #include <AK/StringView.h> | #include <AK/StringView.h> | ||||||
| #include <LibELF/Image.h> | #include <LibELF/Image.h> | ||||||
|  | @ -323,4 +324,84 @@ Optional<Image::Symbol> Image::find_demangled_function(const String& name) const | ||||||
|     return found; |     return found; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | Optional<Image::Symbol> 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
 | } // end namespace ELF
 | ||||||
|  |  | ||||||
|  | @ -210,6 +210,10 @@ public: | ||||||
| 
 | 
 | ||||||
|     Optional<Symbol> find_demangled_function(const String& name) const; |     Optional<Symbol> find_demangled_function(const String& name) const; | ||||||
| 
 | 
 | ||||||
|  |     bool has_symbols() const { return symbol_count(); } | ||||||
|  |     String symbolicate(u32 address, u32* offset = nullptr) const; | ||||||
|  |     Optional<Image::Symbol> find_symbol(u32 address, u32* offset = nullptr) const; | ||||||
|  | 
 | ||||||
| private: | private: | ||||||
|     const char* raw_data(unsigned offset) const; |     const char* raw_data(unsigned offset) const; | ||||||
|     const Elf32_Ehdr& header() const; |     const Elf32_Ehdr& header() const; | ||||||
|  | @ -227,6 +231,15 @@ private: | ||||||
|     bool m_valid { false }; |     bool m_valid { false }; | ||||||
|     unsigned m_symbol_table_section_index { 0 }; |     unsigned m_symbol_table_section_index { 0 }; | ||||||
|     unsigned m_string_table_section_index { 0 }; |     unsigned m_string_table_section_index { 0 }; | ||||||
|  | 
 | ||||||
|  |     struct SortedSymbol { | ||||||
|  |         u32 address; | ||||||
|  |         StringView name; | ||||||
|  |         String demangled_name; | ||||||
|  |         Optional<Image::Symbol> symbol; | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     mutable Vector<SortedSymbol> m_sorted_symbols; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| template<typename F> | template<typename F> | ||||||
|  |  | ||||||
|  | @ -1,128 +0,0 @@ | ||||||
| /*
 |  | ||||||
|  * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> |  | ||||||
|  * 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 <AK/Demangle.h> |  | ||||||
| #include <AK/Memory.h> |  | ||||||
| #include <AK/QuickSort.h> |  | ||||||
| 
 |  | ||||||
| //#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<Image::Symbol> 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
 |  | ||||||
|  | @ -1,85 +0,0 @@ | ||||||
| /*
 |  | ||||||
|  * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> |  | ||||||
|  * 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 <AK/Function.h> |  | ||||||
| #include <AK/HashMap.h> |  | ||||||
| #include <AK/NonnullRefPtr.h> |  | ||||||
| #include <AK/OwnPtr.h> |  | ||||||
| #include <AK/StringView.h> |  | ||||||
| #include <AK/Vector.h> |  | ||||||
| #include <LibELF/Image.h> |  | ||||||
| 
 |  | ||||||
| #ifdef KERNEL |  | ||||||
| #    include <Kernel/VirtualAddress.h> |  | ||||||
| namespace Kernel { |  | ||||||
| class Region; |  | ||||||
| } |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| namespace ELF { |  | ||||||
| 
 |  | ||||||
| class Loader : public RefCounted<Loader> { |  | ||||||
| public: |  | ||||||
|     static NonnullRefPtr<Loader> 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<Image::Symbol> 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<Image::Symbol> 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<Image::Symbol> symbol; |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     mutable Vector<SortedSymbol> m_sorted_symbols; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| } // end namespace ELF
 |  | ||||||
|  | @ -26,23 +26,23 @@ | ||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include <LibELF/Loader.h> | #include <LibELF/Image.h> | ||||||
| 
 | 
 | ||||||
| namespace X86 { | namespace X86 { | ||||||
| 
 | 
 | ||||||
| class ELFSymbolProvider final : public SymbolProvider { | class ELFSymbolProvider final : public SymbolProvider { | ||||||
| public: | public: | ||||||
|     ELFSymbolProvider(ELF::Loader& loader) |     ELFSymbolProvider(const ELF::Image& elf) | ||||||
|         : m_loader(loader) |         : m_elf(elf) | ||||||
|     { |     { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     virtual String symbolicate(FlatPtr address, u32* offset = nullptr) const override |     virtual String symbolicate(FlatPtr address, u32* offset = nullptr) const override | ||||||
|     { |     { | ||||||
|         return m_loader.symbolicate(address, offset); |         return m_elf.symbolicate(address, offset); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     ELF::Loader& m_loader; |     const ELF::Image& m_elf; | ||||||
| }; | }; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -24,12 +24,12 @@ | ||||||
|  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #include <LibELF/Loader.h> | #include <LibELF/Image.h> | ||||||
| #include <stddef.h> | #include <stddef.h> | ||||||
| #include <stdint.h> | #include <stdint.h> | ||||||
| 
 | 
 | ||||||
| extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) | 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; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -38,7 +38,6 @@ | ||||||
| #include <LibELF/DynamicLoader.h> | #include <LibELF/DynamicLoader.h> | ||||||
| #include <LibELF/DynamicObject.h> | #include <LibELF/DynamicObject.h> | ||||||
| #include <LibELF/Image.h> | #include <LibELF/Image.h> | ||||||
| #include <LibELF/Loader.h> |  | ||||||
| #include <LibELF/exec_elf.h> | #include <LibELF/exec_elf.h> | ||||||
| #include <dlfcn.h> | #include <dlfcn.h> | ||||||
| #include <string.h> | #include <string.h> | ||||||
|  |  | ||||||
|  | @ -29,7 +29,7 @@ | ||||||
| #include <AK/QuickSort.h> | #include <AK/QuickSort.h> | ||||||
| #include <AK/Vector.h> | #include <AK/Vector.h> | ||||||
| #include <LibCore/ArgsParser.h> | #include <LibCore/ArgsParser.h> | ||||||
| #include <LibELF/Loader.h> | #include <LibELF/Image.h> | ||||||
| #include <LibX86/Disassembler.h> | #include <LibX86/Disassembler.h> | ||||||
| #include <LibX86/ELFSymbolProvider.h> | #include <LibX86/ELFSymbolProvider.h> | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
|  | @ -70,14 +70,13 @@ int main(int argc, char** argv) | ||||||
|     size_t asm_size = file.size(); |     size_t asm_size = file.size(); | ||||||
|     size_t file_offset = 0; |     size_t file_offset = 0; | ||||||
|     Vector<Symbol>::Iterator current_symbol = symbols.begin(); |     Vector<Symbol>::Iterator current_symbol = symbols.begin(); | ||||||
|     RefPtr<ELF::Loader> elf; |  | ||||||
|     OwnPtr<X86::ELFSymbolProvider> symbol_provider; // nullptr for non-ELF disassembly.
 |     OwnPtr<X86::ELFSymbolProvider> symbol_provider; // nullptr for non-ELF disassembly.
 | ||||||
|  |     OwnPtr<ELF::Image> elf; | ||||||
|     if (asm_size >= 4 && strncmp((const char*)asm_data, "\u007fELF", 4) == 0) { |     if (asm_size >= 4 && strncmp((const char*)asm_data, "\u007fELF", 4) == 0) { | ||||||
|         NonnullRefPtr<ELF::Loader> elf_loader = ELF::Loader::create(asm_data, asm_size); |         elf = make<ELF::Image>(asm_data, asm_size); | ||||||
|         if (elf_loader->image().is_valid()) { |         if (elf->is_valid()) { | ||||||
|             elf = elf_loader; |  | ||||||
|             symbol_provider = make<X86::ELFSymbolProvider>(*elf); |             symbol_provider = make<X86::ELFSymbolProvider>(*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.
 |                 // FIXME: Disassemble all SHT_PROGBITS sections, not just .text.
 | ||||||
|                 if (section.name() != ".text") |                 if (section.name() != ".text") | ||||||
|                     return IterationDecision::Continue; |                     return IterationDecision::Continue; | ||||||
|  | @ -86,9 +85,9 @@ int main(int argc, char** argv) | ||||||
|                 file_offset = section.address(); |                 file_offset = section.address(); | ||||||
|                 return IterationDecision::Break; |                 return IterationDecision::Break; | ||||||
|             }); |             }); | ||||||
|             symbols.ensure_capacity(elf->image().symbol_count() + 1); |             symbols.ensure_capacity(elf->symbol_count() + 1); | ||||||
|             symbols.append({ 0, 0, StringView() }); // Sentinel.
 |             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() }); |                 symbols.append({ symbol.value(), symbol.size(), symbol.name() }); | ||||||
|                 return IterationDecision::Continue; |                 return IterationDecision::Continue; | ||||||
|             }); |             }); | ||||||
|  |  | ||||||
|  | @ -86,7 +86,7 @@ static NonnullOwnPtr<HashMap<void*, X86::Instruction>> instrument_code() | ||||||
| { | { | ||||||
|     [[maybe_unused]] auto r = demangle("foo"); // Required for linked with __cxa_demangle
 |     [[maybe_unused]] auto r = demangle("foo"); // Required for linked with __cxa_demangle
 | ||||||
|     auto instrumented = make<HashMap<void*, X86::Instruction>>(); |     auto instrumented = make<HashMap<void*, X86::Instruction>>(); | ||||||
|     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") |         if (section.name() != ".text") | ||||||
|             return IterationDecision::Continue; |             return IterationDecision::Continue; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling