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:
Andreas Kling 2021-01-10 15:55:54 +01:00
parent 70fce5c4c7
commit 2f3b901f7f
Notes: sideshowbarker 2024-07-18 23:57:45 +09:00
36 changed files with 184 additions and 199 deletions

View file

@ -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.
*
* Redistribution and use in source and binary forms, with or without
@ -25,6 +25,7 @@
*/
#include <AK/MappedFile.h>
#include <AK/ScopeGuard.h>
#include <AK/String.h>
#include <fcntl.h>
#include <stdio.h>
@ -32,68 +33,43 @@
#include <sys/stat.h>
#include <unistd.h>
//#define DEBUG_MAPPED_FILE
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) {
m_errno = errno;
perror("open");
return;
}
ScopeGuard fd_close_guard = [fd] {
close(fd);
};
struct stat st;
fstat(fd, &st);
m_size = st.st_size;
m_map = mmap(nullptr, m_size, PROT_READ, MAP_SHARED, fd, 0);
if (m_map == MAP_FAILED) {
m_errno = errno;
perror("mmap");
if (fstat(fd, &st) < 0) {
auto saved_errno = errno;
return OSError(saved_errno);
}
#ifdef DEBUG_MAPPED_FILE
dbgln("MappedFile(\"{}\") := ( fd={}, m_size={}, m_map={} )", file_name, fd, m_size, m_map);
#endif
auto size = st.st_size;
auto* ptr = mmap(nullptr, size, PROT_READ, MAP_SHARED, fd, 0);
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()
{
unmap();
}
void MappedFile::unmap()
{
if (!is_valid())
return;
int rc = munmap(m_map, m_size);
auto rc = munmap(m_data, m_size);
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;
}
}

View file

@ -27,37 +27,33 @@
#pragma once
#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 {
class MappedFile {
class MappedFile : public RefCounted<MappedFile> {
AK_MAKE_NONCOPYABLE(MappedFile);
AK_MAKE_NONMOVABLE(MappedFile);
public:
MappedFile() { }
explicit MappedFile(const StringView& file_name);
MappedFile(MappedFile&&);
static Result<NonnullRefPtr<MappedFile>, OSError> map(const StringView& path);
~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; }
ReadonlyBytes bytes() const { return { m_data, m_size }; }
private:
explicit MappedFile(void*, size_t);
void* m_data { nullptr };
size_t m_size { 0 };
void* m_map { (void*)-1 };
int m_errno { 0 };
};
}

View file

@ -79,22 +79,24 @@ String ManualModel::page_path(const GUI::ModelIndex& index) const
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())
return StringView {};
auto mapped_file = m_mapped_files.get(path);
if (mapped_file.has_value())
return StringView { (const char*)mapped_file.value()->data(), mapped_file.value()->size() };
{
// Check if we've got it cached already.
auto mapped_file = m_mapped_files.get(path);
if (mapped_file.has_value())
return StringView { mapped_file.value()->bytes() };
}
auto map = make<MappedFile>(path);
if (!map->is_valid())
return map->errno_if_invalid();
StringView view { (const char*)map->data(), map->size() };
m_mapped_files.set(path, move(map));
auto file_or_error = MappedFile::map(path);
if (file_or_error.is_error())
return file_or_error.error();
StringView view { file_or_error.value()->bytes() };
m_mapped_files.set(path, file_or_error.release_value());
return view;
}

View file

@ -45,7 +45,7 @@ public:
String page_path(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);
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_icon;
GUI::Icon m_page_icon;
mutable HashMap<String, OwnPtr<MappedFile>> m_mapped_files;
mutable HashMap<String, NonnullRefPtr<MappedFile>> m_mapped_files;
};

View file

@ -159,7 +159,7 @@ int main(int argc, char* argv[])
auto source_result = model->page_view(path);
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;
}

View file

@ -51,10 +51,10 @@ DisassemblyModel::DisassemblyModel(const Debug::DebugSession& debug_session, con
const ELF::Image* elf = nullptr;
if (containing_function.value().address_low >= 0xc0000000) {
auto kernel_file = make<MappedFile>("/boot/Kernel");
if (!kernel_file->is_valid())
auto file_or_error = MappedFile::map("/boot/Kernel");
if (file_or_error.is_error())
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();
} else {
elf = &lib->debug_info->elf();

View file

@ -60,9 +60,10 @@ DisassemblyModel::DisassemblyModel(Profile& profile, ProfileNode& node)
FlatPtr base_address = 0;
if (m_node.address() >= 0xc0000000) {
if (!m_kernel_file) {
m_kernel_file = new MappedFile("/boot/Kernel");
if (!m_kernel_file->is_valid())
auto file_or_error = MappedFile::map("/boot/Kernel");
if (file_or_error.is_error())
return;
m_kernel_file = file_or_error.release_value();
}
kernel_elf = make<ELF::Image>((const u8*)m_kernel_file->data(), m_kernel_file->size());
elf = kernel_elf.ptr();

View file

@ -69,7 +69,7 @@ private:
Profile& m_profile;
ProfileNode& m_node;
OwnPtr<MappedFile> m_kernel_file;
RefPtr<MappedFile> m_kernel_file;
Vector<InstructionData> m_instructions;
};

View file

@ -230,10 +230,10 @@ Result<NonnullOwnPtr<Profile>, String> Profile::load_from_perfcore_file(const St
if (!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;
if (kernel_elf_file.is_valid())
kernel_elf = make<ELF::Image>(static_cast<const u8*>(kernel_elf_file.data()), kernel_elf_file.size());
if (!file_or_error.is_error())
kernel_elf = make<ELF::Image>(file_or_error.value()->bytes());
auto events_value = object.get("events");
if (!events_value.is_array())

View file

@ -167,13 +167,14 @@ void Emulator::setup_stack(Vector<ELF::AuxiliaryValue> aux_vector)
bool Emulator::load_elf()
{
MappedFile mapped_executable(m_executable_path);
if (!mapped_executable.is_valid()) {
reportln("Unable to map {}", m_executable_path);
auto file_or_error = MappedFile::map(m_executable_path);
if (file_or_error.is_error()) {
reportln("Unable to map {}: {}", m_executable_path, file_or_error.error());
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()) {
// FIXME: Support static objects
@ -181,7 +182,7 @@ bool Emulator::load_elf()
}
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");
return false;
}
@ -189,9 +190,10 @@ bool Emulator::load_elf()
ASSERT(!interpreter_path.is_null());
dbgln("interpreter: {}", interpreter_path);
auto interpreter_file = make<MappedFile>(interpreter_path);
ASSERT(interpreter_file->is_valid());
ELF::Image interpreter_image((const u8*)interpreter_file->data(), interpreter_file->size());
auto interpreter_file_or_error = MappedFile::map(interpreter_path);
ASSERT(!interpreter_file_or_error.is_error());
auto interpreter_image_data = interpreter_file_or_error.value()->bytes();
ELF::Image interpreter_image(interpreter_image_data);
constexpr FlatPtr interpreter_load_offset = 0x08000000;
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);
if (!m_dynamic_library_cache.contains(lib_path)) {
MappedFile mapped_file { lib_path };
if (!mapped_file.is_valid())
auto file_or_error = MappedFile::map(lib_path);
if (file_or_error.is_error())
return minimal;
auto debug_info = make<Debug::DebugInfo>(make<ELF::Image>((const u8*)mapped_file.data(), mapped_file.size()));
m_dynamic_library_cache.set(lib_path, CachedELF { move(mapped_file), move(debug_info) });
auto debug_info = make<Debug::DebugInfo>(make<ELF::Image>(file_or_error.value()->bytes()));
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);
@ -1765,11 +1767,11 @@ int Emulator::virt$beep()
bool Emulator::find_malloc_symbols(const MmapRegion& libc_text)
{
auto mapped_file = make<MappedFile>("/usr/lib/libc.so");
if (!mapped_file->is_valid())
return {};
auto file_or_error = MappedFile::map("/usr/lib/libc.so");
if (file_or_error.is_error())
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 free_symbol = image.find_demangled_function("free");
auto realloc_symbol = image.find_demangled_function("realloc");

View file

@ -207,7 +207,7 @@ private:
Optional<size_t> m_loader_text_size;
struct CachedELF {
MappedFile mapped_file;
NonnullRefPtr<MappedFile> mapped_file;
NonnullOwnPtr<Debug::DebugInfo> debug_info;
};

View file

@ -57,11 +57,12 @@ static const ELFObjectInfo* object_info_for_region(const ELF::Core::MemoryRegion
if (!Core::File::exists(path.characters()))
return nullptr;
MappedFile object_file(path);
if (!object_file.is_valid())
auto file_or_error = MappedFile::map(path);
if (file_or_error.is_error())
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();
s_debug_info_cache.set(path, move(info));
return info_ptr;

View file

@ -33,13 +33,13 @@
namespace CoreDump {
struct ELFObjectInfo {
ELFObjectInfo(MappedFile&& file, Debug::DebugInfo&& debug_info)
ELFObjectInfo(NonnullRefPtr<MappedFile> file, Debug::DebugInfo&& debug_info)
: file(move(file))
, debug_info(move(debug_info))
{
}
MappedFile file;
NonnullRefPtr<MappedFile> file;
Debug::DebugInfo debug_info;
};

View file

@ -35,15 +35,15 @@ namespace CoreDump {
OwnPtr<Reader> Reader::create(const String& path)
{
auto mapped_file = make<MappedFile>(path);
if (!mapped_file->is_valid())
auto file_or_error = MappedFile::map(path);
if (file_or_error.is_error())
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_image((u8*)m_coredump_file->data(), m_coredump_file->size())
, m_coredump_image(m_coredump_file->bytes())
{
size_t index = 0;
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)) {
auto lib_file = make<MappedFile>(path);
if (!lib_file->is_valid())
auto file_or_error = MappedFile::map(path);
if (file_or_error.is_error())
return {};
auto image = ELF::Image((const u8*)lib_file->data(), lib_file->size());
cached_libs.set(path, make<LibraryData>(name, region->region_start, move(lib_file), move(image)));
auto image = ELF::Image(file_or_error.value()->bytes());
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();

View file

@ -38,13 +38,12 @@ namespace CoreDump {
class Reader {
AK_MAKE_NONCOPYABLE(Reader);
AK_MAKE_NONMOVABLE(Reader);
public:
static OwnPtr<Reader> create(const String&);
~Reader();
Reader(OwnPtr<MappedFile>&&);
const ELF::Core::ProcessInfo& process_info() const;
template<typename Func>
@ -61,7 +60,7 @@ public:
struct LibraryData {
String name;
FlatPtr base_address { 0 };
OwnPtr<MappedFile> file;
NonnullRefPtr<MappedFile> file;
ELF::Image lib_elf;
};
const LibraryData* library_containing(FlatPtr address) const;
@ -70,6 +69,8 @@ public:
const HashMap<String, String> metadata() const;
private:
Reader(NonnullRefPtr<MappedFile>);
class NotesEntryIterator {
public:
NotesEntryIterator(const u8* notes_data);
@ -85,7 +86,7 @@ private:
const u8* start { nullptr };
};
OwnPtr<MappedFile> m_coredump_file;
NonnullRefPtr<MappedFile> m_coredump_file;
ELF::Image m_coredump_image;
ssize_t m_notes_segment_index { -1 };
};

View file

@ -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()
{
if (m_is_debuggee_dead)
@ -373,13 +366,13 @@ void DebugSession::update_loaded_libs()
if (m_loaded_libraries.contains(lib_name))
return IterationDecision::Continue;
MappedFile lib_file(object_path.value());
if (!lib_file.is_valid())
auto file_or_error = MappedFile ::map(object_path.value());
if (file_or_error.is_error())
return IterationDecision::Continue;
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 lib = make<LoadedLibrary>(lib_name, move(lib_file), move(debug_info), 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, file_or_error.release_value(), move(debug_info), base_address);
m_loaded_libraries.set(lib_name, move(lib));
return IterationDecision::Continue;

View file

@ -134,11 +134,11 @@ public:
struct LoadedLibrary {
String name;
MappedFile file;
NonnullRefPtr<MappedFile> file;
NonnullOwnPtr<DebugInfo> debug_info;
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)
, file(move(file))
, debug_info(move(debug_info))
@ -175,8 +175,6 @@ private:
// x86 breakpoint instruction "int3"
static constexpr u8 BREAKPOINT_INSTRUCTION = 0xcc;
static MappedFile map_executable_for_process(pid_t);
void update_loaded_libs();
int m_debuggee_pid { -1 };

View file

@ -36,14 +36,19 @@
namespace ELF {
Image::Image(const u8* buffer, size_t size, bool verbose_logging)
: m_buffer(buffer)
, m_size(size)
Image::Image(ReadonlyBytes bytes, bool verbose_logging)
: m_buffer(bytes.data())
, m_size(bytes.size())
, m_verbose_logging(verbose_logging)
{
parse();
}
Image::Image(const u8* buffer, size_t size, bool verbose_logging)
: Image(ReadonlyBytes { buffer, size }, verbose_logging)
{
}
Image::~Image()
{
}

View file

@ -37,7 +37,9 @@ namespace ELF {
class Image {
public:
explicit Image(ReadonlyBytes, bool verbose_logging = true);
explicit Image(const u8*, size_t, bool verbose_logging = true);
~Image();
void dump() const;
bool is_valid() const { return m_valid; }

View file

@ -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
// 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.
auto mapped_file = make<MappedFile>(path);
if (!mapped_file->is_valid()) {
auto file_or_error = MappedFile::map(path);
if (file_or_error.is_error()) {
app_icon_cache.set(path, s_executable_icon);
return s_executable_icon;
}
auto& mapped_file = file_or_error.value();
if (mapped_file->size() < SELFMAG) {
app_icon_cache.set(path, s_executable_icon);
return s_executable_icon;

View file

@ -92,10 +92,11 @@ void ImageWidget::animate()
void ImageWidget::load_from_file(const StringView& path)
{
MappedFile mapped_file(path);
if (!mapped_file.is_valid())
auto file_or_error = MappedFile::map(path);
if (file_or_error.is_error())
return;
auto& mapped_file = *file_or_error.value();
m_image_decoder = Gfx::ImageDecoder::create((const u8*)mapped_file.data(), mapped_file.size());
auto bitmap = m_image_decoder->bitmap();
ASSERT(bitmap);

View file

@ -179,10 +179,10 @@ static RefPtr<Bitmap> load_bmp_impl(const u8*, size_t);
RefPtr<Gfx::Bitmap> load_bmp(const StringView& path)
{
MappedFile mapped_file(path);
if (!mapped_file.is_valid())
auto file_or_error = MappedFile::map(path);
if (file_or_error.is_error())
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)
bitmap->set_mmap_name(String::formatted("Gfx::Bitmap [{}] - Decoded BMP: {}", bitmap->size(), LexicalPath::canonicalized_path(path)));
return bitmap;

View file

@ -27,7 +27,6 @@
#include "BitmapFont.h"
#include "Bitmap.h"
#include "Emoji.h"
#include <AK/MappedFile.h>
#include <AK/StdLibExtras.h>
#include <AK/StringBuilder.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)
{
MappedFile mapped_file(path);
if (!mapped_file.is_valid())
auto file_or_error = MappedFile::map(path);
if (file_or_error.is_error())
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)
return nullptr;
font->m_mapped_file = move(mapped_file);
font->m_mapped_file = file_or_error.release_value();
return font;
}

View file

@ -128,7 +128,7 @@ private:
unsigned* m_rows { nullptr };
u8* m_glyph_widths { nullptr };
MappedFile m_mapped_file;
RefPtr<MappedFile> m_mapped_file;
u8 m_glyph_width { 0 };
u8 m_glyph_height { 0 };

View file

@ -107,10 +107,10 @@ struct GIFLoadingContext {
RefPtr<Gfx::Bitmap> load_gif(const StringView& path)
{
MappedFile mapped_file(path);
if (!mapped_file.is_valid())
auto file_or_error = MappedFile::map(path);
if (file_or_error.is_error())
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();
if (bitmap)
bitmap->set_mmap_name(String::formatted("Gfx::Bitmap [{}] - Decoded GIF: {}", bitmap->size(), LexicalPath::canonicalized_path(path)));

View file

@ -116,10 +116,10 @@ struct ICOLoadingContext {
RefPtr<Gfx::Bitmap> load_ico(const StringView& path)
{
MappedFile mapped_file(path);
if (!mapped_file.is_valid())
auto file_or_error = MappedFile::map(path);
if (file_or_error.is_error())
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();
if (bitmap)
bitmap->set_mmap_name(String::formatted("Gfx::Bitmap [{}] - Decoded ICO: {}", bitmap->size(), LexicalPath::canonicalized_path(path)));

View file

@ -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)
{
MappedFile mapped_file(path);
if (!mapped_file.is_valid()) {
auto file_or_error = MappedFile::map(path);
if (file_or_error.is_error())
return nullptr;
}
auto bitmap = load_jpg_impl((const u8*)mapped_file.data(), mapped_file.size());
auto bitmap = load_jpg_impl((const u8*)file_or_error.value()->data(), file_or_error.value()->size());
if (bitmap)
bitmap->set_mmap_name(String::formatted("Gfx::Bitmap [{}] - Decoded JPG: {}", bitmap->size(), LexicalPath::canonicalized_path(path)));
return bitmap;

View file

@ -193,10 +193,10 @@ static bool process_chunk(Streamer&, PNGLoadingContext& context);
RefPtr<Gfx::Bitmap> load_png(const StringView& path)
{
MappedFile mapped_file(path);
if (!mapped_file.is_valid())
auto file_or_error = MappedFile::map(path);
if (file_or_error.is_error())
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)
bitmap->set_mmap_name(String::formatted("Gfx::Bitmap [{}] - Decoded PNG: {}", bitmap->size(), LexicalPath::canonicalized_path(path)));
return bitmap;

View file

@ -294,12 +294,10 @@ static RefPtr<Gfx::Bitmap> load_impl(const u8* data, size_t data_size)
template<typename TContext>
static RefPtr<Gfx::Bitmap> load(const StringView& path)
{
MappedFile mapped_file(path);
if (!mapped_file.is_valid()) {
auto file_or_error = MappedFile::map(path);
if (file_or_error.is_error())
return nullptr;
}
auto bitmap = load_impl<TContext>((const u8*)mapped_file.data(), mapped_file.size());
auto bitmap = load_impl<TContext>((const u8*)file_or_error.value()->data(), file_or_error.value()->size());
if (bitmap)
bitmap->set_mmap_name(String::formatted("Gfx::Bitmap [{}] - Decoded {}: {}",
bitmap->size(),

View file

@ -34,7 +34,10 @@ namespace PCIDB {
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)
return nullptr;
return res;
@ -131,10 +134,7 @@ int Database::init()
if (m_ready)
return 0;
if (!m_file.is_valid())
return -1;
m_view = StringView((const char*)m_file.data(), m_file.size());
m_view = StringView { m_file->bytes() };
ParseMode mode = ParseMode::UnknownMode;

View file

@ -83,8 +83,10 @@ public:
const StringView get_programming_interface(u8 class_id, u8 subclass_id, u8 programming_interface_id) const;
private:
Database(const StringView& file_name)
: m_file(file_name) {};
explicit Database(NonnullRefPtr<MappedFile> file)
: m_file(move(file))
{
}
int init();
@ -94,7 +96,7 @@ private:
ClassMode,
};
MappedFile m_file {};
NonnullRefPtr<MappedFile> m_file;
StringView m_view {};
HashMap<int, NonnullOwnPtr<Vendor>> m_vendors;
HashMap<int, NonnullOwnPtr<Class>> m_classes;

View file

@ -162,8 +162,9 @@ static String folder_image_data()
{
static String cache;
if (cache.is_empty()) {
MappedFile image("/res/icons/16x16/filetype-folder.png");
cache = encode_base64({ image.data(), image.size() });
auto file_or_error = MappedFile::map("/res/icons/16x16/filetype-folder.png");
ASSERT(!file_or_error.is_error());
cache = encode_base64(file_or_error.value()->bytes());
}
return cache;
}
@ -172,8 +173,9 @@ static String file_image_data()
{
static String cache;
if (cache.is_empty()) {
MappedFile image("/res/icons/16x16/filetype-unknown.png");
cache = encode_base64({ image.data(), image.size() });
auto file_or_error = MappedFile::map("/res/icons/16x16/filetype-unknown.png");
ASSERT(!file_or_error.is_error());
cache = encode_base64(file_or_error.value()->bytes());
}
return cache;
}

View file

@ -48,12 +48,14 @@ int main(int argc, char** argv)
args_parser.add_positional_argument(path, "Path to i386 binary file", "path");
args_parser.parse(argc, argv);
MappedFile file(path);
if (!file.is_valid()) {
// Already printed some error message.
auto file_or_error = MappedFile::map(path);
if (file_or_error.is_error()) {
warnln("Could not map file: {}", file_or_error.error().string());
return 1;
}
auto& file = *file_or_error.value();
struct Symbol {
size_t value;
size_t size;

View file

@ -90,7 +90,7 @@ static NonnullOwnPtr<HashMap<void*, X86::Instruction>> instrument_code()
if (section.name() != ".text")
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);
for (;;) {
auto offset = stream.offset();

View file

@ -284,14 +284,15 @@ int main(int argc, char** argv)
display_symbol_table = true;
}
MappedFile mapped_executable(path);
auto file_or_error = MappedFile::map(path);
if (!mapped_executable.is_valid()) {
fprintf(stderr, "Unable to map file %s\n", path);
if (file_or_error.is_error()) {
warnln("Unable to map file {}: {}", path, file_or_error.error());
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()) {
fprintf(stderr, "File is not a valid ELF object\n");
@ -300,7 +301,7 @@ int main(int argc, char** argv)
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");
return -1;
}
@ -309,14 +310,14 @@ int main(int argc, char** argv)
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()) {
fprintf(stderr, "ELF image is invalid\n");
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) {
printf("ELF header:\n");

View file

@ -181,9 +181,12 @@ int main(int argc, char** argv)
return 1;
}
MappedFile mapped_file { zip_file_path };
if (!mapped_file.is_valid())
auto file_or_error = MappedFile ::map(zip_file_path);
if (file_or_error.is_error()) {
warnln("Failed to open {}: {}", zip_file_path, file_or_error.error());
return 1;
}
auto& mapped_file = *file_or_error.value();
printf("Archive: %s\n", zip_file_path.characters());