blob: 2075e0547eedce36a9f077d5f109f35ec76cf04e [file] [log] [blame]
// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "dump-file-mmap.h"
#include <sys/mman.h>
namespace zxdump::internal {
// The returned view is valid for the life of the Mmap.
fit::result<Error, ByteView> DumpFile::Mmap::ReadPermanent(FileRange where) {
auto result = ReadEphemeral(where);
if (result.is_ok()) {
const size_t bytes_read = result.value().size();
read_limit_ = std::max(read_limit_, where.offset + bytes_read);
}
return result;
}
// The returned view is only guaranteed valid until the next call. In
// fact, it stays valid possibly for the life of the Mmap and at
// least until shrink_to_fit is called.
fit::result<Error, ByteView> DumpFile::Mmap::ReadEphemeral(FileRange where) {
ByteView data{reinterpret_cast<std::byte*>(data_), size_};
data = data.subspan(where.offset, std::min(data.size() - where.offset, where.size));
if (data.empty()) {
return TruncatedDump();
}
return fit::ok(data);
}
// This never allows EOF since the size is always known and reading past
// EOF should never be attempted.
fit::result<Error, ByteView> DumpFile::Mmap::ReadProbe(FileRange where) {
return ReadEphemeral(where);
}
fit::result<Error, Buffer<>> DumpFile::Mmap::ReadMemory(FileRange where) {
auto result = ReadPermanent(where);
if (result.is_error()) {
return result.take_error();
}
Buffer<> buffer;
buffer.data_ = result.value();
// There is nothing to own, so this doesn't set the impl_ pointer at all.
return fit::ok(std::move(buffer));
}
// All the data that will be read has been read.
void DumpFile::Mmap::shrink_to_fit() {
const size_t page_size = static_cast<size_t>(sysconf(_SC_PAGESIZE));
const size_t last_page = size_ & -page_size;
if (read_limit_ <= last_page) {
// Unmap the file pages we never looked at with ReadPermanent.
const size_t limit_page = (read_limit_ + page_size - 1) & -page_size;
const size_t trim = last_page + page_size - limit_page;
munmap(static_cast<std::byte*>(data_) + limit_page, trim);
size_ = limit_page;
}
}
DumpFile::Mmap::~Mmap() {
if (size_ > 0) {
munmap(data_, size_);
}
}
} // namespace zxdump::internal