mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 09:52:44 +00:00 
			
		
		
		
	AK: Make MappedFile heap-allocated and ref-counted
Let's adapt this class a bit better to how it's actually being used. Instead of having valid/invalid states and storing an error in case it's invalid, a MappedFile is now always valid, and the factory function that creates it will return an OSError if mapping fails.
This commit is contained in:
		
							parent
							
								
									70fce5c4c7
								
							
						
					
					
						commit
						2f3b901f7f
					
				
					 36 changed files with 184 additions and 199 deletions
				
			
		|  | @ -1,5 +1,5 @@ | ||||||
| /*
 | /*
 | ||||||
|  * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> |  * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org> | ||||||
|  * All rights reserved. |  * All rights reserved. | ||||||
|  * |  * | ||||||
|  * Redistribution and use in source and binary forms, with or without |  * Redistribution and use in source and binary forms, with or without | ||||||
|  | @ -25,6 +25,7 @@ | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #include <AK/MappedFile.h> | #include <AK/MappedFile.h> | ||||||
|  | #include <AK/ScopeGuard.h> | ||||||
| #include <AK/String.h> | #include <AK/String.h> | ||||||
| #include <fcntl.h> | #include <fcntl.h> | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
|  | @ -32,68 +33,43 @@ | ||||||
| #include <sys/stat.h> | #include <sys/stat.h> | ||||||
| #include <unistd.h> | #include <unistd.h> | ||||||
| 
 | 
 | ||||||
| //#define DEBUG_MAPPED_FILE
 |  | ||||||
| 
 |  | ||||||
| namespace AK { | namespace AK { | ||||||
| 
 | 
 | ||||||
| MappedFile::MappedFile(const StringView& file_name) | Result<NonnullRefPtr<MappedFile>, OSError> MappedFile::map(const StringView& path) | ||||||
| { | { | ||||||
|     int fd = open_with_path_length(file_name.characters_without_null_termination(), file_name.length(), O_RDONLY | O_CLOEXEC, 0); |     int fd = open_with_path_length(path.characters_without_null_termination(), path.length(), O_RDONLY | O_CLOEXEC, 0); | ||||||
|  |     if (fd < 0) | ||||||
|  |         return OSError(errno); | ||||||
| 
 | 
 | ||||||
|     if (fd == -1) { |     ScopeGuard fd_close_guard = [fd] { | ||||||
|         m_errno = errno; |         close(fd); | ||||||
|         perror("open"); |     }; | ||||||
|         return; |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     struct stat st; |     struct stat st; | ||||||
|     fstat(fd, &st); |     if (fstat(fd, &st) < 0) { | ||||||
|     m_size = st.st_size; |         auto saved_errno = errno; | ||||||
|     m_map = mmap(nullptr, m_size, PROT_READ, MAP_SHARED, fd, 0); |         return OSError(saved_errno); | ||||||
| 
 |  | ||||||
|     if (m_map == MAP_FAILED) { |  | ||||||
|         m_errno = errno; |  | ||||||
|         perror("mmap"); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| #ifdef DEBUG_MAPPED_FILE |     auto size = st.st_size; | ||||||
|     dbgln("MappedFile(\"{}\") := ( fd={}, m_size={}, m_map={} )", file_name, fd, m_size, m_map); |     auto* ptr = mmap(nullptr, size, PROT_READ, MAP_SHARED, fd, 0); | ||||||
| #endif |  | ||||||
| 
 | 
 | ||||||
|     close(fd); |     if (ptr == MAP_FAILED) | ||||||
|  |         return OSError(errno); | ||||||
|  | 
 | ||||||
|  |     return adopt(*new MappedFile(ptr, size)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | MappedFile::MappedFile(void* ptr, size_t size) | ||||||
|  |     : m_data(ptr) | ||||||
|  |     , m_size(size) | ||||||
|  | { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| MappedFile::~MappedFile() | MappedFile::~MappedFile() | ||||||
| { | { | ||||||
|     unmap(); |     auto rc = munmap(m_data, m_size); | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void MappedFile::unmap() |  | ||||||
| { |  | ||||||
|     if (!is_valid()) |  | ||||||
|         return; |  | ||||||
|     int rc = munmap(m_map, m_size); |  | ||||||
|     ASSERT(rc == 0); |     ASSERT(rc == 0); | ||||||
|     m_size = 0; |  | ||||||
|     m_map = (void*)-1; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| MappedFile::MappedFile(MappedFile&& other) |  | ||||||
|     : m_size(other.m_size) |  | ||||||
|     , m_map(other.m_map) |  | ||||||
| { |  | ||||||
|     other.m_size = 0; |  | ||||||
|     other.m_map = (void*)-1; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| MappedFile& MappedFile::operator=(MappedFile&& other) |  | ||||||
| { |  | ||||||
|     if (this == &other) |  | ||||||
|         return *this; |  | ||||||
|     unmap(); |  | ||||||
|     swap(m_size, other.m_size); |  | ||||||
|     swap(m_map, other.m_map); |  | ||||||
|     return *this; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -27,37 +27,33 @@ | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include <AK/Noncopyable.h> | #include <AK/Noncopyable.h> | ||||||
| #include <AK/StringView.h> | #include <AK/NonnullRefPtr.h> | ||||||
|  | #include <AK/OSError.h> | ||||||
|  | #include <AK/RefCounted.h> | ||||||
|  | #include <AK/Result.h> | ||||||
| 
 | 
 | ||||||
| namespace AK { | namespace AK { | ||||||
| 
 | 
 | ||||||
| class MappedFile { | class MappedFile : public RefCounted<MappedFile> { | ||||||
|     AK_MAKE_NONCOPYABLE(MappedFile); |     AK_MAKE_NONCOPYABLE(MappedFile); | ||||||
|  |     AK_MAKE_NONMOVABLE(MappedFile); | ||||||
| 
 | 
 | ||||||
| public: | public: | ||||||
|     MappedFile() { } |     static Result<NonnullRefPtr<MappedFile>, OSError> map(const StringView& path); | ||||||
|     explicit MappedFile(const StringView& file_name); |  | ||||||
|     MappedFile(MappedFile&&); |  | ||||||
|     ~MappedFile(); |     ~MappedFile(); | ||||||
| 
 | 
 | ||||||
|     MappedFile& operator=(MappedFile&&); |     void* data() { return m_data; } | ||||||
|  |     const void* data() const { return m_data; } | ||||||
| 
 | 
 | ||||||
|     bool is_valid() const { return m_map != (void*)-1; } |  | ||||||
|     int errno_if_invalid() const |  | ||||||
|     { |  | ||||||
|         ASSERT(!is_valid()); |  | ||||||
|         return m_errno; |  | ||||||
|     } |  | ||||||
|     void unmap(); |  | ||||||
| 
 |  | ||||||
|     void* data() { return m_map; } |  | ||||||
|     const void* data() const { return m_map; } |  | ||||||
|     size_t size() const { return m_size; } |     size_t size() const { return m_size; } | ||||||
| 
 | 
 | ||||||
|  |     ReadonlyBytes bytes() const { return { m_data, m_size }; } | ||||||
|  | 
 | ||||||
| private: | private: | ||||||
|  |     explicit MappedFile(void*, size_t); | ||||||
|  | 
 | ||||||
|  |     void* m_data { nullptr }; | ||||||
|     size_t m_size { 0 }; |     size_t m_size { 0 }; | ||||||
|     void* m_map { (void*)-1 }; |  | ||||||
|     int m_errno { 0 }; |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -79,22 +79,24 @@ String ManualModel::page_path(const GUI::ModelIndex& index) const | ||||||
|     return page->path(); |     return page->path(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Result<StringView, int> ManualModel::page_view(const String& path) const | Result<StringView, OSError> ManualModel::page_view(const String& path) const | ||||||
| { | { | ||||||
|     if (path.is_empty()) |     if (path.is_empty()) | ||||||
|         return StringView {}; |         return StringView {}; | ||||||
| 
 | 
 | ||||||
|     auto mapped_file = m_mapped_files.get(path); |     { | ||||||
|     if (mapped_file.has_value()) |         // Check if we've got it cached already.
 | ||||||
|         return StringView { (const char*)mapped_file.value()->data(), mapped_file.value()->size() }; |         auto mapped_file = m_mapped_files.get(path); | ||||||
|  |         if (mapped_file.has_value()) | ||||||
|  |             return StringView { mapped_file.value()->bytes() }; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     auto map = make<MappedFile>(path); |     auto file_or_error = MappedFile::map(path); | ||||||
|     if (!map->is_valid()) |     if (file_or_error.is_error()) | ||||||
|         return map->errno_if_invalid(); |         return file_or_error.error(); | ||||||
| 
 |  | ||||||
|     StringView view { (const char*)map->data(), map->size() }; |  | ||||||
|     m_mapped_files.set(path, move(map)); |  | ||||||
| 
 | 
 | ||||||
|  |     StringView view { file_or_error.value()->bytes() }; | ||||||
|  |     m_mapped_files.set(path, file_or_error.release_value()); | ||||||
|     return view; |     return view; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -45,7 +45,7 @@ public: | ||||||
| 
 | 
 | ||||||
|     String page_path(const GUI::ModelIndex&) const; |     String page_path(const GUI::ModelIndex&) const; | ||||||
|     String page_and_section(const GUI::ModelIndex&) const; |     String page_and_section(const GUI::ModelIndex&) const; | ||||||
|     Result<StringView, int> page_view(const String& path) const; |     Result<StringView, OSError> page_view(const String& path) const; | ||||||
| 
 | 
 | ||||||
|     void update_section_node_on_toggle(const GUI::ModelIndex&, const bool); |     void update_section_node_on_toggle(const GUI::ModelIndex&, const bool); | ||||||
|     virtual int row_count(const GUI::ModelIndex& = GUI::ModelIndex()) const override; |     virtual int row_count(const GUI::ModelIndex& = GUI::ModelIndex()) const override; | ||||||
|  | @ -62,5 +62,5 @@ private: | ||||||
|     GUI::Icon m_section_open_icon; |     GUI::Icon m_section_open_icon; | ||||||
|     GUI::Icon m_section_icon; |     GUI::Icon m_section_icon; | ||||||
|     GUI::Icon m_page_icon; |     GUI::Icon m_page_icon; | ||||||
|     mutable HashMap<String, OwnPtr<MappedFile>> m_mapped_files; |     mutable HashMap<String, NonnullRefPtr<MappedFile>> m_mapped_files; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | @ -159,7 +159,7 @@ int main(int argc, char* argv[]) | ||||||
| 
 | 
 | ||||||
|         auto source_result = model->page_view(path); |         auto source_result = model->page_view(path); | ||||||
|         if (source_result.is_error()) { |         if (source_result.is_error()) { | ||||||
|             GUI::MessageBox::show(window, strerror(source_result.error()), "Failed to open man page", GUI::MessageBox::Type::Error); |             GUI::MessageBox::show(window, source_result.error().string(), "Failed to open man page", GUI::MessageBox::Type::Error); | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -51,10 +51,10 @@ DisassemblyModel::DisassemblyModel(const Debug::DebugSession& debug_session, con | ||||||
|     const ELF::Image* elf = nullptr; |     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 file_or_error = MappedFile::map("/boot/Kernel"); | ||||||
|         if (!kernel_file->is_valid()) |         if (file_or_error.is_error()) | ||||||
|             return; |             return; | ||||||
|         kernel_elf = make<ELF::Image>((const u8*)kernel_file->data(), kernel_file->size()); |         kernel_elf = make<ELF::Image>(file_or_error.value()->bytes()); | ||||||
|         elf = kernel_elf.ptr(); |         elf = kernel_elf.ptr(); | ||||||
|     } else { |     } else { | ||||||
|         elf = &lib->debug_info->elf(); |         elf = &lib->debug_info->elf(); | ||||||
|  |  | ||||||
|  | @ -60,9 +60,10 @@ DisassemblyModel::DisassemblyModel(Profile& profile, ProfileNode& node) | ||||||
|     FlatPtr base_address = 0; |     FlatPtr base_address = 0; | ||||||
|     if (m_node.address() >= 0xc0000000) { |     if (m_node.address() >= 0xc0000000) { | ||||||
|         if (!m_kernel_file) { |         if (!m_kernel_file) { | ||||||
|             m_kernel_file = new MappedFile("/boot/Kernel"); |             auto file_or_error = MappedFile::map("/boot/Kernel"); | ||||||
|             if (!m_kernel_file->is_valid()) |             if (file_or_error.is_error()) | ||||||
|                 return; |                 return; | ||||||
|  |             m_kernel_file = file_or_error.release_value(); | ||||||
|         } |         } | ||||||
|         kernel_elf = make<ELF::Image>((const u8*)m_kernel_file->data(), m_kernel_file->size()); |         kernel_elf = make<ELF::Image>((const u8*)m_kernel_file->data(), m_kernel_file->size()); | ||||||
|         elf = kernel_elf.ptr(); |         elf = kernel_elf.ptr(); | ||||||
|  |  | ||||||
|  | @ -69,7 +69,7 @@ private: | ||||||
| 
 | 
 | ||||||
|     Profile& m_profile; |     Profile& m_profile; | ||||||
|     ProfileNode& m_node; |     ProfileNode& m_node; | ||||||
|     OwnPtr<MappedFile> m_kernel_file; |     RefPtr<MappedFile> m_kernel_file; | ||||||
| 
 | 
 | ||||||
|     Vector<InstructionData> m_instructions; |     Vector<InstructionData> m_instructions; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | @ -230,10 +230,10 @@ Result<NonnullOwnPtr<Profile>, String> Profile::load_from_perfcore_file(const St | ||||||
|     if (!coredump) |     if (!coredump) | ||||||
|         return String { "Could not open coredump" }; |         return String { "Could not open coredump" }; | ||||||
| 
 | 
 | ||||||
|     MappedFile kernel_elf_file("/boot/Kernel"); |     auto file_or_error = MappedFile::map("/boot/Kernel"); | ||||||
|     OwnPtr<ELF::Image> kernel_elf; |     OwnPtr<ELF::Image> kernel_elf; | ||||||
|     if (kernel_elf_file.is_valid()) |     if (!file_or_error.is_error()) | ||||||
|         kernel_elf = make<ELF::Image>(static_cast<const u8*>(kernel_elf_file.data()), kernel_elf_file.size()); |         kernel_elf = make<ELF::Image>(file_or_error.value()->bytes()); | ||||||
| 
 | 
 | ||||||
|     auto events_value = object.get("events"); |     auto events_value = object.get("events"); | ||||||
|     if (!events_value.is_array()) |     if (!events_value.is_array()) | ||||||
|  |  | ||||||
|  | @ -167,13 +167,14 @@ void Emulator::setup_stack(Vector<ELF::AuxiliaryValue> aux_vector) | ||||||
| 
 | 
 | ||||||
| bool Emulator::load_elf() | bool Emulator::load_elf() | ||||||
| { | { | ||||||
|     MappedFile mapped_executable(m_executable_path); |     auto file_or_error = MappedFile::map(m_executable_path); | ||||||
|     if (!mapped_executable.is_valid()) { |     if (file_or_error.is_error()) { | ||||||
|         reportln("Unable to map {}", m_executable_path); |         reportln("Unable to map {}: {}", m_executable_path, file_or_error.error()); | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     ELF::Image executable_elf((const u8*)mapped_executable.data(), mapped_executable.size()); |     auto elf_image_data = file_or_error.value()->bytes(); | ||||||
|  |     ELF::Image executable_elf(elf_image_data); | ||||||
| 
 | 
 | ||||||
|     if (!executable_elf.is_dynamic()) { |     if (!executable_elf.is_dynamic()) { | ||||||
|         // FIXME: Support static objects
 |         // FIXME: Support static objects
 | ||||||
|  | @ -181,7 +182,7 @@ bool Emulator::load_elf() | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     String interpreter_path; |     String interpreter_path; | ||||||
|     if (!ELF::validate_program_headers(*(Elf32_Ehdr*)mapped_executable.data(), mapped_executable.size(), (u8*)mapped_executable.data(), mapped_executable.size(), &interpreter_path)) { |     if (!ELF::validate_program_headers(*(const Elf32_Ehdr*)elf_image_data.data(), elf_image_data.size(), (const u8*)elf_image_data.data(), elf_image_data.size(), &interpreter_path)) { | ||||||
|         reportln("failed to validate ELF file"); |         reportln("failed to validate ELF file"); | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
|  | @ -189,9 +190,10 @@ bool Emulator::load_elf() | ||||||
|     ASSERT(!interpreter_path.is_null()); |     ASSERT(!interpreter_path.is_null()); | ||||||
|     dbgln("interpreter: {}", interpreter_path); |     dbgln("interpreter: {}", interpreter_path); | ||||||
| 
 | 
 | ||||||
|     auto interpreter_file = make<MappedFile>(interpreter_path); |     auto interpreter_file_or_error = MappedFile::map(interpreter_path); | ||||||
|     ASSERT(interpreter_file->is_valid()); |     ASSERT(!interpreter_file_or_error.is_error()); | ||||||
|     ELF::Image interpreter_image((const u8*)interpreter_file->data(), interpreter_file->size()); |     auto interpreter_image_data = interpreter_file_or_error.value()->bytes(); | ||||||
|  |     ELF::Image interpreter_image(interpreter_image_data); | ||||||
| 
 | 
 | ||||||
|     constexpr FlatPtr interpreter_load_offset = 0x08000000; |     constexpr FlatPtr interpreter_load_offset = 0x08000000; | ||||||
|     interpreter_image.for_each_program_header([&](const ELF::Image::ProgramHeader& program_header) { |     interpreter_image.for_each_program_header([&](const ELF::Image::ProgramHeader& program_header) { | ||||||
|  | @ -308,12 +310,12 @@ String Emulator::create_backtrace_line(FlatPtr address) | ||||||
|         lib_path = String::formatted("/usr/lib/{}", lib_path); |         lib_path = String::formatted("/usr/lib/{}", lib_path); | ||||||
| 
 | 
 | ||||||
|     if (!m_dynamic_library_cache.contains(lib_path)) { |     if (!m_dynamic_library_cache.contains(lib_path)) { | ||||||
|         MappedFile mapped_file { lib_path }; |         auto file_or_error = MappedFile::map(lib_path); | ||||||
|         if (!mapped_file.is_valid()) |         if (file_or_error.is_error()) | ||||||
|             return minimal; |             return minimal; | ||||||
| 
 | 
 | ||||||
|         auto debug_info = make<Debug::DebugInfo>(make<ELF::Image>((const u8*)mapped_file.data(), mapped_file.size())); |         auto debug_info = make<Debug::DebugInfo>(make<ELF::Image>(file_or_error.value()->bytes())); | ||||||
|         m_dynamic_library_cache.set(lib_path, CachedELF { move(mapped_file), move(debug_info) }); |         m_dynamic_library_cache.set(lib_path, CachedELF { file_or_error.release_value(), move(debug_info) }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     auto it = m_dynamic_library_cache.find(lib_path); |     auto it = m_dynamic_library_cache.find(lib_path); | ||||||
|  | @ -1765,11 +1767,11 @@ int Emulator::virt$beep() | ||||||
| 
 | 
 | ||||||
| bool Emulator::find_malloc_symbols(const MmapRegion& libc_text) | bool Emulator::find_malloc_symbols(const MmapRegion& libc_text) | ||||||
| { | { | ||||||
|     auto mapped_file = make<MappedFile>("/usr/lib/libc.so"); |     auto file_or_error = MappedFile::map("/usr/lib/libc.so"); | ||||||
|     if (!mapped_file->is_valid()) |     if (file_or_error.is_error()) | ||||||
|         return {}; |         return false; | ||||||
| 
 | 
 | ||||||
|     ELF::Image image((const u8*)mapped_file->data(), mapped_file->size()); |     ELF::Image image(file_or_error.value()->bytes()); | ||||||
|     auto malloc_symbol = image.find_demangled_function("malloc"); |     auto malloc_symbol = image.find_demangled_function("malloc"); | ||||||
|     auto free_symbol = image.find_demangled_function("free"); |     auto free_symbol = image.find_demangled_function("free"); | ||||||
|     auto realloc_symbol = image.find_demangled_function("realloc"); |     auto realloc_symbol = image.find_demangled_function("realloc"); | ||||||
|  |  | ||||||
|  | @ -207,7 +207,7 @@ private: | ||||||
|     Optional<size_t> m_loader_text_size; |     Optional<size_t> m_loader_text_size; | ||||||
| 
 | 
 | ||||||
|     struct CachedELF { |     struct CachedELF { | ||||||
|         MappedFile mapped_file; |         NonnullRefPtr<MappedFile> mapped_file; | ||||||
|         NonnullOwnPtr<Debug::DebugInfo> debug_info; |         NonnullOwnPtr<Debug::DebugInfo> debug_info; | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -57,11 +57,12 @@ static const ELFObjectInfo* object_info_for_region(const ELF::Core::MemoryRegion | ||||||
|     if (!Core::File::exists(path.characters())) |     if (!Core::File::exists(path.characters())) | ||||||
|         return nullptr; |         return nullptr; | ||||||
| 
 | 
 | ||||||
|     MappedFile object_file(path); |     auto file_or_error = MappedFile::map(path); | ||||||
|     if (!object_file.is_valid()) |     if (file_or_error.is_error()) | ||||||
|         return nullptr; |         return nullptr; | ||||||
| 
 | 
 | ||||||
|     auto info = make<ELFObjectInfo>(move(object_file), Debug::DebugInfo { make<ELF::Image>((const u8*)object_file.data(), object_file.size()) }); |     auto image = make<ELF::Image>(file_or_error.value()->bytes()); | ||||||
|  |     auto info = make<ELFObjectInfo>(file_or_error.release_value(), Debug::DebugInfo { move(image) }); | ||||||
|     auto* info_ptr = info.ptr(); |     auto* info_ptr = info.ptr(); | ||||||
|     s_debug_info_cache.set(path, move(info)); |     s_debug_info_cache.set(path, move(info)); | ||||||
|     return info_ptr; |     return info_ptr; | ||||||
|  |  | ||||||
|  | @ -33,13 +33,13 @@ | ||||||
| namespace CoreDump { | namespace CoreDump { | ||||||
| 
 | 
 | ||||||
| struct ELFObjectInfo { | struct ELFObjectInfo { | ||||||
|     ELFObjectInfo(MappedFile&& file, Debug::DebugInfo&& debug_info) |     ELFObjectInfo(NonnullRefPtr<MappedFile> file, Debug::DebugInfo&& debug_info) | ||||||
|         : file(move(file)) |         : file(move(file)) | ||||||
|         , debug_info(move(debug_info)) |         , debug_info(move(debug_info)) | ||||||
|     { |     { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     MappedFile file; |     NonnullRefPtr<MappedFile> file; | ||||||
|     Debug::DebugInfo debug_info; |     Debug::DebugInfo debug_info; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -35,15 +35,15 @@ namespace CoreDump { | ||||||
| 
 | 
 | ||||||
| OwnPtr<Reader> Reader::create(const String& path) | OwnPtr<Reader> Reader::create(const String& path) | ||||||
| { | { | ||||||
|     auto mapped_file = make<MappedFile>(path); |     auto file_or_error = MappedFile::map(path); | ||||||
|     if (!mapped_file->is_valid()) |     if (file_or_error.is_error()) | ||||||
|         return nullptr; |         return nullptr; | ||||||
|     return make<Reader>(move(mapped_file)); |     return adopt_own(*new Reader(file_or_error.release_value())); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Reader::Reader(OwnPtr<MappedFile>&& coredump_file) | Reader::Reader(NonnullRefPtr<MappedFile> coredump_file) | ||||||
|     : m_coredump_file(move(coredump_file)) |     : m_coredump_file(move(coredump_file)) | ||||||
|     , m_coredump_image((u8*)m_coredump_file->data(), m_coredump_file->size()) |     , m_coredump_image(m_coredump_file->bytes()) | ||||||
| { | { | ||||||
|     size_t index = 0; |     size_t index = 0; | ||||||
|     m_coredump_image.for_each_program_header([this, &index](auto pheader) { |     m_coredump_image.for_each_program_header([this, &index](auto pheader) { | ||||||
|  | @ -201,11 +201,11 @@ const Reader::LibraryData* Reader::library_containing(FlatPtr address) const | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (!cached_libs.contains(path)) { |     if (!cached_libs.contains(path)) { | ||||||
|         auto lib_file = make<MappedFile>(path); |         auto file_or_error = MappedFile::map(path); | ||||||
|         if (!lib_file->is_valid()) |         if (file_or_error.is_error()) | ||||||
|             return {}; |             return {}; | ||||||
|         auto image = ELF::Image((const u8*)lib_file->data(), lib_file->size()); |         auto image = ELF::Image(file_or_error.value()->bytes()); | ||||||
|         cached_libs.set(path, make<LibraryData>(name, region->region_start, move(lib_file), move(image))); |         cached_libs.set(path, make<LibraryData>(name, region->region_start, file_or_error.release_value(), move(image))); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     auto lib_data = cached_libs.get(path).value(); |     auto lib_data = cached_libs.get(path).value(); | ||||||
|  |  | ||||||
|  | @ -38,13 +38,12 @@ namespace CoreDump { | ||||||
| 
 | 
 | ||||||
| class Reader { | class Reader { | ||||||
|     AK_MAKE_NONCOPYABLE(Reader); |     AK_MAKE_NONCOPYABLE(Reader); | ||||||
|  |     AK_MAKE_NONMOVABLE(Reader); | ||||||
| 
 | 
 | ||||||
| public: | public: | ||||||
|     static OwnPtr<Reader> create(const String&); |     static OwnPtr<Reader> create(const String&); | ||||||
|     ~Reader(); |     ~Reader(); | ||||||
| 
 | 
 | ||||||
|     Reader(OwnPtr<MappedFile>&&); |  | ||||||
| 
 |  | ||||||
|     const ELF::Core::ProcessInfo& process_info() const; |     const ELF::Core::ProcessInfo& process_info() const; | ||||||
| 
 | 
 | ||||||
|     template<typename Func> |     template<typename Func> | ||||||
|  | @ -61,7 +60,7 @@ public: | ||||||
|     struct LibraryData { |     struct LibraryData { | ||||||
|         String name; |         String name; | ||||||
|         FlatPtr base_address { 0 }; |         FlatPtr base_address { 0 }; | ||||||
|         OwnPtr<MappedFile> file; |         NonnullRefPtr<MappedFile> file; | ||||||
|         ELF::Image lib_elf; |         ELF::Image lib_elf; | ||||||
|     }; |     }; | ||||||
|     const LibraryData* library_containing(FlatPtr address) const; |     const LibraryData* library_containing(FlatPtr address) const; | ||||||
|  | @ -70,6 +69,8 @@ public: | ||||||
|     const HashMap<String, String> metadata() const; |     const HashMap<String, String> metadata() const; | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|  |     Reader(NonnullRefPtr<MappedFile>); | ||||||
|  | 
 | ||||||
|     class NotesEntryIterator { |     class NotesEntryIterator { | ||||||
|     public: |     public: | ||||||
|         NotesEntryIterator(const u8* notes_data); |         NotesEntryIterator(const u8* notes_data); | ||||||
|  | @ -85,7 +86,7 @@ private: | ||||||
|         const u8* start { nullptr }; |         const u8* start { nullptr }; | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     OwnPtr<MappedFile> m_coredump_file; |     NonnullRefPtr<MappedFile> m_coredump_file; | ||||||
|     ELF::Image m_coredump_image; |     ELF::Image m_coredump_image; | ||||||
|     ssize_t m_notes_segment_index { -1 }; |     ssize_t m_notes_segment_index { -1 }; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | @ -42,13 +42,6 @@ DebugSession::DebugSession(pid_t pid, String source_root) | ||||||
| { | { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| MappedFile DebugSession::map_executable_for_process(pid_t pid) |  | ||||||
| { |  | ||||||
|     MappedFile executable(String::formatted("/proc/{}/exe", pid)); |  | ||||||
|     ASSERT(executable.is_valid()); |  | ||||||
|     return executable; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| DebugSession::~DebugSession() | DebugSession::~DebugSession() | ||||||
| { | { | ||||||
|     if (m_is_debuggee_dead) |     if (m_is_debuggee_dead) | ||||||
|  | @ -373,13 +366,13 @@ void DebugSession::update_loaded_libs() | ||||||
|         if (m_loaded_libraries.contains(lib_name)) |         if (m_loaded_libraries.contains(lib_name)) | ||||||
|             return IterationDecision::Continue; |             return IterationDecision::Continue; | ||||||
| 
 | 
 | ||||||
|         MappedFile lib_file(object_path.value()); |         auto file_or_error = MappedFile ::map(object_path.value()); | ||||||
|         if (!lib_file.is_valid()) |         if (file_or_error.is_error()) | ||||||
|             return IterationDecision::Continue; |             return IterationDecision::Continue; | ||||||
| 
 | 
 | ||||||
|         FlatPtr base_address = entry.as_object().get("address").as_u32(); |         FlatPtr base_address = entry.as_object().get("address").as_u32(); | ||||||
|         auto debug_info = make<DebugInfo>(make<ELF::Image>(reinterpret_cast<const u8*>(lib_file.data()), lib_file.size()), m_source_root, base_address); |         auto debug_info = make<DebugInfo>(make<ELF::Image>(file_or_error.value()->bytes()), m_source_root, base_address); | ||||||
|         auto lib = make<LoadedLibrary>(lib_name, move(lib_file), move(debug_info), base_address); |         auto lib = make<LoadedLibrary>(lib_name, file_or_error.release_value(), move(debug_info), base_address); | ||||||
|         m_loaded_libraries.set(lib_name, move(lib)); |         m_loaded_libraries.set(lib_name, move(lib)); | ||||||
| 
 | 
 | ||||||
|         return IterationDecision::Continue; |         return IterationDecision::Continue; | ||||||
|  |  | ||||||
|  | @ -134,11 +134,11 @@ public: | ||||||
| 
 | 
 | ||||||
|     struct LoadedLibrary { |     struct LoadedLibrary { | ||||||
|         String name; |         String name; | ||||||
|         MappedFile file; |         NonnullRefPtr<MappedFile> file; | ||||||
|         NonnullOwnPtr<DebugInfo> debug_info; |         NonnullOwnPtr<DebugInfo> debug_info; | ||||||
|         FlatPtr base_address; |         FlatPtr base_address; | ||||||
| 
 | 
 | ||||||
|         LoadedLibrary(const String& name, MappedFile&& file, NonnullOwnPtr<DebugInfo>&& debug_info, FlatPtr base_address) |         LoadedLibrary(const String& name, NonnullRefPtr<MappedFile> file, NonnullOwnPtr<DebugInfo>&& debug_info, FlatPtr base_address) | ||||||
|             : name(name) |             : name(name) | ||||||
|             , file(move(file)) |             , file(move(file)) | ||||||
|             , debug_info(move(debug_info)) |             , debug_info(move(debug_info)) | ||||||
|  | @ -175,8 +175,6 @@ private: | ||||||
|     // x86 breakpoint instruction "int3"
 |     // x86 breakpoint instruction "int3"
 | ||||||
|     static constexpr u8 BREAKPOINT_INSTRUCTION = 0xcc; |     static constexpr u8 BREAKPOINT_INSTRUCTION = 0xcc; | ||||||
| 
 | 
 | ||||||
|     static MappedFile map_executable_for_process(pid_t); |  | ||||||
| 
 |  | ||||||
|     void update_loaded_libs(); |     void update_loaded_libs(); | ||||||
| 
 | 
 | ||||||
|     int m_debuggee_pid { -1 }; |     int m_debuggee_pid { -1 }; | ||||||
|  |  | ||||||
|  | @ -36,14 +36,19 @@ | ||||||
| 
 | 
 | ||||||
| namespace ELF { | namespace ELF { | ||||||
| 
 | 
 | ||||||
| Image::Image(const u8* buffer, size_t size, bool verbose_logging) | Image::Image(ReadonlyBytes bytes, bool verbose_logging) | ||||||
|     : m_buffer(buffer) |     : m_buffer(bytes.data()) | ||||||
|     , m_size(size) |     , m_size(bytes.size()) | ||||||
|     , m_verbose_logging(verbose_logging) |     , m_verbose_logging(verbose_logging) | ||||||
| { | { | ||||||
|     parse(); |     parse(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | Image::Image(const u8* buffer, size_t size, bool verbose_logging) | ||||||
|  |     : Image(ReadonlyBytes { buffer, size }, verbose_logging) | ||||||
|  | { | ||||||
|  | } | ||||||
|  | 
 | ||||||
| Image::~Image() | Image::~Image() | ||||||
| { | { | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -37,7 +37,9 @@ namespace ELF { | ||||||
| 
 | 
 | ||||||
| class Image { | class Image { | ||||||
| public: | public: | ||||||
|  |     explicit Image(ReadonlyBytes, bool verbose_logging = true); | ||||||
|     explicit Image(const u8*, size_t, bool verbose_logging = true); |     explicit Image(const u8*, size_t, bool verbose_logging = true); | ||||||
|  | 
 | ||||||
|     ~Image(); |     ~Image(); | ||||||
|     void dump() const; |     void dump() const; | ||||||
|     bool is_valid() const { return m_valid; } |     bool is_valid() const { return m_valid; } | ||||||
|  |  | ||||||
|  | @ -150,12 +150,14 @@ Icon FileIconProvider::icon_for_executable(const String& path) | ||||||
|     // If the icon for an app isn't in the cache we attempt to load the file as an ELF image and extract
 |     // If the icon for an app isn't in the cache we attempt to load the file as an ELF image and extract
 | ||||||
|     // the serenity_app_icon_* sections which should contain the icons as raw PNG data. In the future it would
 |     // the serenity_app_icon_* sections which should contain the icons as raw PNG data. In the future it would
 | ||||||
|     // be better if the binary signalled the image format being used or we deduced it, e.g. using magic bytes.
 |     // be better if the binary signalled the image format being used or we deduced it, e.g. using magic bytes.
 | ||||||
|     auto mapped_file = make<MappedFile>(path); |     auto file_or_error = MappedFile::map(path); | ||||||
|     if (!mapped_file->is_valid()) { |     if (file_or_error.is_error()) { | ||||||
|         app_icon_cache.set(path, s_executable_icon); |         app_icon_cache.set(path, s_executable_icon); | ||||||
|         return s_executable_icon; |         return s_executable_icon; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     auto& mapped_file = file_or_error.value(); | ||||||
|  | 
 | ||||||
|     if (mapped_file->size() < SELFMAG) { |     if (mapped_file->size() < SELFMAG) { | ||||||
|         app_icon_cache.set(path, s_executable_icon); |         app_icon_cache.set(path, s_executable_icon); | ||||||
|         return s_executable_icon; |         return s_executable_icon; | ||||||
|  |  | ||||||
|  | @ -92,10 +92,11 @@ void ImageWidget::animate() | ||||||
| 
 | 
 | ||||||
| void ImageWidget::load_from_file(const StringView& path) | void ImageWidget::load_from_file(const StringView& path) | ||||||
| { | { | ||||||
|     MappedFile mapped_file(path); |     auto file_or_error = MappedFile::map(path); | ||||||
|     if (!mapped_file.is_valid()) |     if (file_or_error.is_error()) | ||||||
|         return; |         return; | ||||||
| 
 | 
 | ||||||
|  |     auto& mapped_file = *file_or_error.value(); | ||||||
|     m_image_decoder = Gfx::ImageDecoder::create((const u8*)mapped_file.data(), mapped_file.size()); |     m_image_decoder = Gfx::ImageDecoder::create((const u8*)mapped_file.data(), mapped_file.size()); | ||||||
|     auto bitmap = m_image_decoder->bitmap(); |     auto bitmap = m_image_decoder->bitmap(); | ||||||
|     ASSERT(bitmap); |     ASSERT(bitmap); | ||||||
|  |  | ||||||
|  | @ -179,10 +179,10 @@ static RefPtr<Bitmap> load_bmp_impl(const u8*, size_t); | ||||||
| 
 | 
 | ||||||
| RefPtr<Gfx::Bitmap> load_bmp(const StringView& path) | RefPtr<Gfx::Bitmap> load_bmp(const StringView& path) | ||||||
| { | { | ||||||
|     MappedFile mapped_file(path); |     auto file_or_error = MappedFile::map(path); | ||||||
|     if (!mapped_file.is_valid()) |     if (file_or_error.is_error()) | ||||||
|         return nullptr; |         return nullptr; | ||||||
|     auto bitmap = load_bmp_impl((const u8*)mapped_file.data(), mapped_file.size()); |     auto bitmap = load_bmp_impl((const u8*)file_or_error.value()->data(), file_or_error.value()->size()); | ||||||
|     if (bitmap) |     if (bitmap) | ||||||
|         bitmap->set_mmap_name(String::formatted("Gfx::Bitmap [{}] - Decoded BMP: {}", bitmap->size(), LexicalPath::canonicalized_path(path))); |         bitmap->set_mmap_name(String::formatted("Gfx::Bitmap [{}] - Decoded BMP: {}", bitmap->size(), LexicalPath::canonicalized_path(path))); | ||||||
|     return bitmap; |     return bitmap; | ||||||
|  |  | ||||||
|  | @ -27,7 +27,6 @@ | ||||||
| #include "BitmapFont.h" | #include "BitmapFont.h" | ||||||
| #include "Bitmap.h" | #include "Bitmap.h" | ||||||
| #include "Emoji.h" | #include "Emoji.h" | ||||||
| #include <AK/MappedFile.h> |  | ||||||
| #include <AK/StdLibExtras.h> | #include <AK/StdLibExtras.h> | ||||||
| #include <AK/StringBuilder.h> | #include <AK/StringBuilder.h> | ||||||
| #include <AK/Utf32View.h> | #include <AK/Utf32View.h> | ||||||
|  | @ -174,15 +173,15 @@ size_t BitmapFont::glyph_count_by_type(FontTypes type) | ||||||
| 
 | 
 | ||||||
| RefPtr<BitmapFont> BitmapFont::load_from_file(const StringView& path) | RefPtr<BitmapFont> BitmapFont::load_from_file(const StringView& path) | ||||||
| { | { | ||||||
|     MappedFile mapped_file(path); |     auto file_or_error = MappedFile::map(path); | ||||||
|     if (!mapped_file.is_valid()) |     if (file_or_error.is_error()) | ||||||
|         return nullptr; |         return nullptr; | ||||||
| 
 | 
 | ||||||
|     auto font = load_from_memory((const u8*)mapped_file.data()); |     auto font = load_from_memory((const u8*)file_or_error.value()->data()); | ||||||
|     if (!font) |     if (!font) | ||||||
|         return nullptr; |         return nullptr; | ||||||
| 
 | 
 | ||||||
|     font->m_mapped_file = move(mapped_file); |     font->m_mapped_file = file_or_error.release_value(); | ||||||
|     return font; |     return font; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -128,7 +128,7 @@ private: | ||||||
| 
 | 
 | ||||||
|     unsigned* m_rows { nullptr }; |     unsigned* m_rows { nullptr }; | ||||||
|     u8* m_glyph_widths { nullptr }; |     u8* m_glyph_widths { nullptr }; | ||||||
|     MappedFile m_mapped_file; |     RefPtr<MappedFile> m_mapped_file; | ||||||
| 
 | 
 | ||||||
|     u8 m_glyph_width { 0 }; |     u8 m_glyph_width { 0 }; | ||||||
|     u8 m_glyph_height { 0 }; |     u8 m_glyph_height { 0 }; | ||||||
|  |  | ||||||
|  | @ -107,10 +107,10 @@ struct GIFLoadingContext { | ||||||
| 
 | 
 | ||||||
| RefPtr<Gfx::Bitmap> load_gif(const StringView& path) | RefPtr<Gfx::Bitmap> load_gif(const StringView& path) | ||||||
| { | { | ||||||
|     MappedFile mapped_file(path); |     auto file_or_error = MappedFile::map(path); | ||||||
|     if (!mapped_file.is_valid()) |     if (file_or_error.is_error()) | ||||||
|         return nullptr; |         return nullptr; | ||||||
|     GIFImageDecoderPlugin gif_decoder((const u8*)mapped_file.data(), mapped_file.size()); |     GIFImageDecoderPlugin gif_decoder((const u8*)file_or_error.value()->data(), file_or_error.value()->size()); | ||||||
|     auto bitmap = gif_decoder.bitmap(); |     auto bitmap = gif_decoder.bitmap(); | ||||||
|     if (bitmap) |     if (bitmap) | ||||||
|         bitmap->set_mmap_name(String::formatted("Gfx::Bitmap [{}] - Decoded GIF: {}", bitmap->size(), LexicalPath::canonicalized_path(path))); |         bitmap->set_mmap_name(String::formatted("Gfx::Bitmap [{}] - Decoded GIF: {}", bitmap->size(), LexicalPath::canonicalized_path(path))); | ||||||
|  |  | ||||||
|  | @ -116,10 +116,10 @@ struct ICOLoadingContext { | ||||||
| 
 | 
 | ||||||
| RefPtr<Gfx::Bitmap> load_ico(const StringView& path) | RefPtr<Gfx::Bitmap> load_ico(const StringView& path) | ||||||
| { | { | ||||||
|     MappedFile mapped_file(path); |     auto file_or_error = MappedFile::map(path); | ||||||
|     if (!mapped_file.is_valid()) |     if (file_or_error.is_error()) | ||||||
|         return nullptr; |         return nullptr; | ||||||
|     ICOImageDecoderPlugin decoder((const u8*)mapped_file.data(), mapped_file.size()); |     ICOImageDecoderPlugin decoder((const u8*)file_or_error.value()->data(), file_or_error.value()->size()); | ||||||
|     auto bitmap = decoder.bitmap(); |     auto bitmap = decoder.bitmap(); | ||||||
|     if (bitmap) |     if (bitmap) | ||||||
|         bitmap->set_mmap_name(String::formatted("Gfx::Bitmap [{}] - Decoded ICO: {}", bitmap->size(), LexicalPath::canonicalized_path(path))); |         bitmap->set_mmap_name(String::formatted("Gfx::Bitmap [{}] - Decoded ICO: {}", bitmap->size(), LexicalPath::canonicalized_path(path))); | ||||||
|  |  | ||||||
|  | @ -1320,12 +1320,10 @@ static RefPtr<Gfx::Bitmap> load_jpg_impl(const u8* data, size_t data_size) | ||||||
| 
 | 
 | ||||||
| RefPtr<Gfx::Bitmap> load_jpg(const StringView& path) | RefPtr<Gfx::Bitmap> load_jpg(const StringView& path) | ||||||
| { | { | ||||||
|     MappedFile mapped_file(path); |     auto file_or_error = MappedFile::map(path); | ||||||
|     if (!mapped_file.is_valid()) { |     if (file_or_error.is_error()) | ||||||
|         return nullptr; |         return nullptr; | ||||||
|     } |     auto bitmap = load_jpg_impl((const u8*)file_or_error.value()->data(), file_or_error.value()->size()); | ||||||
| 
 |  | ||||||
|     auto bitmap = load_jpg_impl((const u8*)mapped_file.data(), mapped_file.size()); |  | ||||||
|     if (bitmap) |     if (bitmap) | ||||||
|         bitmap->set_mmap_name(String::formatted("Gfx::Bitmap [{}] - Decoded JPG: {}", bitmap->size(), LexicalPath::canonicalized_path(path))); |         bitmap->set_mmap_name(String::formatted("Gfx::Bitmap [{}] - Decoded JPG: {}", bitmap->size(), LexicalPath::canonicalized_path(path))); | ||||||
|     return bitmap; |     return bitmap; | ||||||
|  |  | ||||||
|  | @ -193,10 +193,10 @@ static bool process_chunk(Streamer&, PNGLoadingContext& context); | ||||||
| 
 | 
 | ||||||
| RefPtr<Gfx::Bitmap> load_png(const StringView& path) | RefPtr<Gfx::Bitmap> load_png(const StringView& path) | ||||||
| { | { | ||||||
|     MappedFile mapped_file(path); |     auto file_or_error = MappedFile::map(path); | ||||||
|     if (!mapped_file.is_valid()) |     if (file_or_error.is_error()) | ||||||
|         return nullptr; |         return nullptr; | ||||||
|     auto bitmap = load_png_impl((const u8*)mapped_file.data(), mapped_file.size()); |     auto bitmap = load_png_impl((const u8*)file_or_error.value()->data(), file_or_error.value()->size()); | ||||||
|     if (bitmap) |     if (bitmap) | ||||||
|         bitmap->set_mmap_name(String::formatted("Gfx::Bitmap [{}] - Decoded PNG: {}", bitmap->size(), LexicalPath::canonicalized_path(path))); |         bitmap->set_mmap_name(String::formatted("Gfx::Bitmap [{}] - Decoded PNG: {}", bitmap->size(), LexicalPath::canonicalized_path(path))); | ||||||
|     return bitmap; |     return bitmap; | ||||||
|  |  | ||||||
|  | @ -294,12 +294,10 @@ static RefPtr<Gfx::Bitmap> load_impl(const u8* data, size_t data_size) | ||||||
| template<typename TContext> | template<typename TContext> | ||||||
| static RefPtr<Gfx::Bitmap> load(const StringView& path) | static RefPtr<Gfx::Bitmap> load(const StringView& path) | ||||||
| { | { | ||||||
|     MappedFile mapped_file(path); |     auto file_or_error = MappedFile::map(path); | ||||||
|     if (!mapped_file.is_valid()) { |     if (file_or_error.is_error()) | ||||||
|         return nullptr; |         return nullptr; | ||||||
|     } |     auto bitmap = load_impl<TContext>((const u8*)file_or_error.value()->data(), file_or_error.value()->size()); | ||||||
| 
 |  | ||||||
|     auto bitmap = load_impl<TContext>((const u8*)mapped_file.data(), mapped_file.size()); |  | ||||||
|     if (bitmap) |     if (bitmap) | ||||||
|         bitmap->set_mmap_name(String::formatted("Gfx::Bitmap [{}] - Decoded {}: {}", |         bitmap->set_mmap_name(String::formatted("Gfx::Bitmap [{}] - Decoded {}: {}", | ||||||
|             bitmap->size(), |             bitmap->size(), | ||||||
|  |  | ||||||
|  | @ -34,7 +34,10 @@ namespace PCIDB { | ||||||
| 
 | 
 | ||||||
| RefPtr<Database> Database::open(const StringView& file_name) | RefPtr<Database> Database::open(const StringView& file_name) | ||||||
| { | { | ||||||
|     auto res = adopt(*new Database(file_name)); |     auto file_or_error = MappedFile::map(file_name); | ||||||
|  |     if (file_or_error.is_error()) | ||||||
|  |         return nullptr; | ||||||
|  |     auto res = adopt(*new Database(file_or_error.release_value())); | ||||||
|     if (res->init() != 0) |     if (res->init() != 0) | ||||||
|         return nullptr; |         return nullptr; | ||||||
|     return res; |     return res; | ||||||
|  | @ -131,10 +134,7 @@ int Database::init() | ||||||
|     if (m_ready) |     if (m_ready) | ||||||
|         return 0; |         return 0; | ||||||
| 
 | 
 | ||||||
|     if (!m_file.is_valid()) |     m_view = StringView { m_file->bytes() }; | ||||||
|         return -1; |  | ||||||
| 
 |  | ||||||
|     m_view = StringView((const char*)m_file.data(), m_file.size()); |  | ||||||
| 
 | 
 | ||||||
|     ParseMode mode = ParseMode::UnknownMode; |     ParseMode mode = ParseMode::UnknownMode; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -83,8 +83,10 @@ public: | ||||||
|     const StringView get_programming_interface(u8 class_id, u8 subclass_id, u8 programming_interface_id) const; |     const StringView get_programming_interface(u8 class_id, u8 subclass_id, u8 programming_interface_id) const; | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     Database(const StringView& file_name) |     explicit Database(NonnullRefPtr<MappedFile> file) | ||||||
|         : m_file(file_name) {}; |         : m_file(move(file)) | ||||||
|  |     { | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     int init(); |     int init(); | ||||||
| 
 | 
 | ||||||
|  | @ -94,7 +96,7 @@ private: | ||||||
|         ClassMode, |         ClassMode, | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     MappedFile m_file {}; |     NonnullRefPtr<MappedFile> m_file; | ||||||
|     StringView m_view {}; |     StringView m_view {}; | ||||||
|     HashMap<int, NonnullOwnPtr<Vendor>> m_vendors; |     HashMap<int, NonnullOwnPtr<Vendor>> m_vendors; | ||||||
|     HashMap<int, NonnullOwnPtr<Class>> m_classes; |     HashMap<int, NonnullOwnPtr<Class>> m_classes; | ||||||
|  |  | ||||||
|  | @ -162,8 +162,9 @@ static String folder_image_data() | ||||||
| { | { | ||||||
|     static String cache; |     static String cache; | ||||||
|     if (cache.is_empty()) { |     if (cache.is_empty()) { | ||||||
|         MappedFile image("/res/icons/16x16/filetype-folder.png"); |         auto file_or_error = MappedFile::map("/res/icons/16x16/filetype-folder.png"); | ||||||
|         cache = encode_base64({ image.data(), image.size() }); |         ASSERT(!file_or_error.is_error()); | ||||||
|  |         cache = encode_base64(file_or_error.value()->bytes()); | ||||||
|     } |     } | ||||||
|     return cache; |     return cache; | ||||||
| } | } | ||||||
|  | @ -172,8 +173,9 @@ static String file_image_data() | ||||||
| { | { | ||||||
|     static String cache; |     static String cache; | ||||||
|     if (cache.is_empty()) { |     if (cache.is_empty()) { | ||||||
|         MappedFile image("/res/icons/16x16/filetype-unknown.png"); |         auto file_or_error = MappedFile::map("/res/icons/16x16/filetype-unknown.png"); | ||||||
|         cache = encode_base64({ image.data(), image.size() }); |         ASSERT(!file_or_error.is_error()); | ||||||
|  |         cache = encode_base64(file_or_error.value()->bytes()); | ||||||
|     } |     } | ||||||
|     return cache; |     return cache; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -48,12 +48,14 @@ int main(int argc, char** argv) | ||||||
|     args_parser.add_positional_argument(path, "Path to i386 binary file", "path"); |     args_parser.add_positional_argument(path, "Path to i386 binary file", "path"); | ||||||
|     args_parser.parse(argc, argv); |     args_parser.parse(argc, argv); | ||||||
| 
 | 
 | ||||||
|     MappedFile file(path); |     auto file_or_error = MappedFile::map(path); | ||||||
|     if (!file.is_valid()) { |     if (file_or_error.is_error()) { | ||||||
|         // Already printed some error message.
 |         warnln("Could not map file: {}", file_or_error.error().string()); | ||||||
|         return 1; |         return 1; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     auto& file = *file_or_error.value(); | ||||||
|  | 
 | ||||||
|     struct Symbol { |     struct Symbol { | ||||||
|         size_t value; |         size_t value; | ||||||
|         size_t size; |         size_t size; | ||||||
|  |  | ||||||
|  | @ -90,7 +90,7 @@ static NonnullOwnPtr<HashMap<void*, X86::Instruction>> instrument_code() | ||||||
|             if (section.name() != ".text") |             if (section.name() != ".text") | ||||||
|                 return IterationDecision::Continue; |                 return IterationDecision::Continue; | ||||||
| 
 | 
 | ||||||
|             X86::SimpleInstructionStream stream((const u8*)((u32)lib.file.data() + section.offset()), section.size()); |             X86::SimpleInstructionStream stream((const u8*)((u32)lib.file->data() + section.offset()), section.size()); | ||||||
|             X86::Disassembler disassembler(stream); |             X86::Disassembler disassembler(stream); | ||||||
|             for (;;) { |             for (;;) { | ||||||
|                 auto offset = stream.offset(); |                 auto offset = stream.offset(); | ||||||
|  |  | ||||||
|  | @ -284,14 +284,15 @@ int main(int argc, char** argv) | ||||||
|         display_symbol_table = true; |         display_symbol_table = true; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     MappedFile mapped_executable(path); |     auto file_or_error = MappedFile::map(path); | ||||||
| 
 | 
 | ||||||
|     if (!mapped_executable.is_valid()) { |     if (file_or_error.is_error()) { | ||||||
|         fprintf(stderr, "Unable to map file %s\n", path); |         warnln("Unable to map file {}: {}", path, file_or_error.error()); | ||||||
|         return -1; |         return -1; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     ELF::Image executable_elf((const u8*)mapped_executable.data(), mapped_executable.size()); |     auto elf_image_data = file_or_error.value()->bytes(); | ||||||
|  |     ELF::Image executable_elf(elf_image_data); | ||||||
| 
 | 
 | ||||||
|     if (!executable_elf.is_valid()) { |     if (!executable_elf.is_valid()) { | ||||||
|         fprintf(stderr, "File is not a valid ELF object\n"); |         fprintf(stderr, "File is not a valid ELF object\n"); | ||||||
|  | @ -300,7 +301,7 @@ int main(int argc, char** argv) | ||||||
| 
 | 
 | ||||||
|     String interpreter_path; |     String interpreter_path; | ||||||
| 
 | 
 | ||||||
|     if (!ELF::validate_program_headers(*(Elf32_Ehdr*)mapped_executable.data(), mapped_executable.size(), (u8*)mapped_executable.data(), mapped_executable.size(), &interpreter_path)) { |     if (!ELF::validate_program_headers(*(const Elf32_Ehdr*)elf_image_data.data(), elf_image_data.size(), (const u8*)elf_image_data.data(), elf_image_data.size(), &interpreter_path)) { | ||||||
|         fprintf(stderr, "Invalid ELF headers\n"); |         fprintf(stderr, "Invalid ELF headers\n"); | ||||||
|         return -1; |         return -1; | ||||||
|     } |     } | ||||||
|  | @ -309,14 +310,14 @@ int main(int argc, char** argv) | ||||||
|         fprintf(stderr, "Warning: Dynamic ELF object has no interpreter path\n"); |         fprintf(stderr, "Warning: Dynamic ELF object has no interpreter path\n"); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     ELF::Image interpreter_image((const u8*)mapped_executable.data(), mapped_executable.size()); |     ELF::Image interpreter_image(elf_image_data); | ||||||
| 
 | 
 | ||||||
|     if (!interpreter_image.is_valid()) { |     if (!interpreter_image.is_valid()) { | ||||||
|         fprintf(stderr, "ELF image is invalid\n"); |         fprintf(stderr, "ELF image is invalid\n"); | ||||||
|         return -1; |         return -1; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     auto header = *reinterpret_cast<const Elf32_Ehdr*>(mapped_executable.data()); |     auto& header = *reinterpret_cast<const Elf32_Ehdr*>(elf_image_data.data()); | ||||||
| 
 | 
 | ||||||
|     if (display_elf_header) { |     if (display_elf_header) { | ||||||
|         printf("ELF header:\n"); |         printf("ELF header:\n"); | ||||||
|  |  | ||||||
|  | @ -181,9 +181,12 @@ int main(int argc, char** argv) | ||||||
|         return 1; |         return 1; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     MappedFile mapped_file { zip_file_path }; |     auto file_or_error = MappedFile ::map(zip_file_path); | ||||||
|     if (!mapped_file.is_valid()) |     if (file_or_error.is_error()) { | ||||||
|  |         warnln("Failed to open {}: {}", zip_file_path, file_or_error.error()); | ||||||
|         return 1; |         return 1; | ||||||
|  |     } | ||||||
|  |     auto& mapped_file = *file_or_error.value(); | ||||||
| 
 | 
 | ||||||
|     printf("Archive: %s\n", zip_file_path.characters()); |     printf("Archive: %s\n", zip_file_path.characters()); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling