Move ScopedReadMmap to ext/base It's going to acquire another user in a future commit. Also: * Use nullptr in ptr_ to represent failure. * Remove the virtual destructor: we don't need a vtable here. * Make the class non copiable and non movable. * Avoid logging in the implementation (logging is enhanced outside). * Rename to ScopedMmap, in case we want to use iti for writing in the future. * Instead of passing a filename to the constructor, create a function that accepts a filename and a length. * Support mapping a whole file. It's going to be used in a future commit. Change-Id: I2aacf9d5eac1ca21150486d53cbe1a6daff5b74b
diff --git a/Android.bp b/Android.bp index 4541d4c..dc3f8de 100644 --- a/Android.bp +++ b/Android.bp
@@ -9826,6 +9826,7 @@ "src/base/paged_memory.cc", "src/base/periodic_task.cc", "src/base/pipe.cc", + "src/base/scoped_mmap.cc", "src/base/status.cc", "src/base/string_splitter.cc", "src/base/string_utils.cc", @@ -9915,6 +9916,7 @@ "src/base/paged_memory_unittest.cc", "src/base/periodic_task_unittest.cc", "src/base/scoped_file_unittest.cc", + "src/base/scoped_mmap_unittest.cc", "src/base/small_vector_unittest.cc", "src/base/status_or_unittest.cc", "src/base/status_unittest.cc", @@ -10540,8 +10542,6 @@ "src/profiling/symbolizer/filesystem_posix.cc", "src/profiling/symbolizer/filesystem_windows.cc", "src/profiling/symbolizer/local_symbolizer.cc", - "src/profiling/symbolizer/scoped_read_mmap_posix.cc", - "src/profiling/symbolizer/scoped_read_mmap_windows.cc", "src/profiling/symbolizer/subprocess_posix.cc", "src/profiling/symbolizer/subprocess_windows.cc", "src/profiling/symbolizer/symbolizer.cc",
diff --git a/BUILD b/BUILD index 1e7c962..8e771b0 100644 --- a/BUILD +++ b/BUILD
@@ -599,6 +599,7 @@ "include/perfetto/ext/base/pipe.h", "include/perfetto/ext/base/platform.h", "include/perfetto/ext/base/scoped_file.h", + "include/perfetto/ext/base/scoped_mmap.h", "include/perfetto/ext/base/small_set.h", "include/perfetto/ext/base/small_vector.h", "include/perfetto/ext/base/status_or.h", @@ -1031,6 +1032,7 @@ "src/base/paged_memory.cc", "src/base/periodic_task.cc", "src/base/pipe.cc", + "src/base/scoped_mmap.cc", "src/base/status.cc", "src/base/string_splitter.cc", "src/base/string_utils.cc", @@ -1232,9 +1234,6 @@ "src/profiling/symbolizer/filesystem_windows.cc", "src/profiling/symbolizer/local_symbolizer.cc", "src/profiling/symbolizer/local_symbolizer.h", - "src/profiling/symbolizer/scoped_read_mmap.h", - "src/profiling/symbolizer/scoped_read_mmap_posix.cc", - "src/profiling/symbolizer/scoped_read_mmap_windows.cc", "src/profiling/symbolizer/subprocess.h", "src/profiling/symbolizer/subprocess_posix.cc", "src/profiling/symbolizer/subprocess_windows.cc",
diff --git a/include/perfetto/ext/base/BUILD.gn b/include/perfetto/ext/base/BUILD.gn index 6e38737..2418346 100644 --- a/include/perfetto/ext/base/BUILD.gn +++ b/include/perfetto/ext/base/BUILD.gn
@@ -37,6 +37,7 @@ "pipe.h", "platform.h", "scoped_file.h", + "scoped_mmap.h", "small_set.h", "small_vector.h", "status_or.h",
diff --git a/include/perfetto/ext/base/scoped_mmap.h b/include/perfetto/ext/base/scoped_mmap.h new file mode 100644 index 0000000..1af620b --- /dev/null +++ b/include/perfetto/ext/base/scoped_mmap.h
@@ -0,0 +1,75 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INCLUDE_PERFETTO_EXT_BASE_SCOPED_MMAP_H_ +#define INCLUDE_PERFETTO_EXT_BASE_SCOPED_MMAP_H_ + +#include <cstddef> + +#include "perfetto/base/build_config.h" +#include "perfetto/ext/base/scoped_file.h" + +namespace perfetto::base { + +// RAII wrapper that holds ownership of an mmap()d area and of a file. Calls +// unmap() and close() on destruction. +class ScopedMmap { + public: + // Creates a memory mapping for the first `length` bytes of `file`. + static ScopedMmap FromHandle(base::ScopedPlatformHandle file, size_t length); + + ScopedMmap() {} + ~ScopedMmap(); + ScopedMmap(ScopedMmap&& other) noexcept; + + ScopedMmap& operator=(ScopedMmap&& other) noexcept; + + // Returns a pointer to the mapped memory area. Only valid if `IsValid()` is + // true. + void* data() const { return ptr_; } + + // Returns true if this object contains a successfully mapped area. + bool IsValid() const { return ptr_ != nullptr; } + + // Returns the length of the mapped area. + size_t length() const { return length_; } + + // Unmaps the area and closes the file. Returns false if this held a mmap()d + // area and unmapping failed. In any case, after this method, `IsValid()` will + // return false. + bool reset() noexcept; + + private: + ScopedMmap(const ScopedMmap&) = delete; + ScopedMmap& operator=(const ScopedMmap&) = delete; + + size_t length_ = 0; + void* ptr_ = nullptr; + ScopedPlatformHandle file_; +#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) + ScopedPlatformHandle map_; +#endif +}; + +// Tries to open `fname` and maps its first `length` bytes in memory. +ScopedMmap ReadMmapFilePart(const char* fname, size_t length); + +// Tries to open `fname` and maps the whole file into memory. +ScopedMmap ReadMmapWholeFile(const char* fname); + +} // namespace perfetto::base + +#endif // INCLUDE_PERFETTO_EXT_BASE_SCOPED_MMAP_H_
diff --git a/src/base/BUILD.gn b/src/base/BUILD.gn index bb2e11b..d8d00a7 100644 --- a/src/base/BUILD.gn +++ b/src/base/BUILD.gn
@@ -46,6 +46,7 @@ "paged_memory.cc", "periodic_task.cc", "pipe.cc", + "scoped_mmap.cc", "status.cc", "string_splitter.cc", "string_utils.cc", @@ -201,6 +202,7 @@ "paged_memory_unittest.cc", "periodic_task_unittest.cc", "scoped_file_unittest.cc", + "scoped_mmap_unittest.cc", "small_vector_unittest.cc", "status_or_unittest.cc", "status_unittest.cc",
diff --git a/src/base/file_utils.cc b/src/base/file_utils.cc index 65fcc46..db0105c 100644 --- a/src/base/file_utils.cc +++ b/src/base/file_utils.cc
@@ -410,8 +410,7 @@ std::optional<size_t> GetFileSize(const std::string& file_path) { #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) - // This does not use base::OpenFile because to avoid getting an exclusive - // lock. + // This does not use base::OpenFile to avoid getting an exclusive lock. HANDLE file = CreateFileA(file_path.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
diff --git a/src/base/scoped_mmap.cc b/src/base/scoped_mmap.cc new file mode 100644 index 0000000..c12d33b --- /dev/null +++ b/src/base/scoped_mmap.cc
@@ -0,0 +1,180 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "perfetto/ext/base/scoped_mmap.h" + +#include <utility> + +#include "perfetto/ext/base/file_utils.h" +#include "perfetto/ext/base/scoped_file.h" + +#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \ + PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \ + PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE) +#include <sys/mman.h> +#include <unistd.h> +#elif PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) +#include <Windows.h> +#endif + +namespace perfetto::base { +namespace { + +ScopedPlatformHandle OpenFileForMmap(const char* fname) { +#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \ + PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \ + PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE) + return OpenFile(fname, O_RDONLY); +#elif PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) + // This does not use base::OpenFile to avoid getting an exclusive lock. + return ScopedPlatformHandle(CreateFileA(fname, GENERIC_READ, FILE_SHARE_READ, + nullptr, OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, nullptr)); +#else + // mmap is not supported. Do not even open the file. + base::ignore_result(fname); + return ScopedPlatformHandle(); +#endif +} + +std::optional<size_t> GetPlatformHandleFileSize(PlatformHandle file) { +#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \ + PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \ + PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE) + off_t file_size_offset = lseek(file, 0, SEEK_END); + if (file_size_offset <= 0) { + return std::nullopt; + } + + lseek(file, 0, SEEK_SET); + + size_t file_size = static_cast<size_t>(file_size_offset); + if (static_cast<off_t>(file_size) != file_size_offset) { + return std::nullopt; + } + return file_size; +#elif PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) + LARGE_INTEGER fs; + fs.QuadPart = 0; + if (!GetFileSizeEx(file, &fs)) { + return std::nullopt; + } + + size_t file_size = static_cast<size_t>(fs.QuadPart); + if (static_cast<decltype(fs.QuadPart)>(file_size) != fs.QuadPart) { + return std::nullopt; + } + return file_size; +#else + // mmap is not supported. This does not matter. + base::ignore_result(file); + return std::nullopt; +#endif +} + +} // namespace + +ScopedMmap::ScopedMmap(ScopedMmap&& other) noexcept { + *this = std::move(other); +} + +ScopedMmap& ScopedMmap::operator=(ScopedMmap&& other) noexcept { + reset(); + std::swap(ptr_, other.ptr_); + std::swap(length_, other.length_); + std::swap(file_, other.file_); +#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) + std::swap(map_, other.map_); +#endif + return *this; +} + +ScopedMmap::~ScopedMmap() { + reset(); +} + +// static +ScopedMmap ScopedMmap::FromHandle(base::ScopedPlatformHandle file, + size_t length) { + ScopedMmap ret; + if (!file) { + return ret; + } +#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \ + PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \ + PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE) + void* ptr = mmap(nullptr, length, PROT_READ, MAP_PRIVATE, *file, 0); + if (ptr != MAP_FAILED) { + ret.ptr_ = ptr; + ret.length_ = length; + ret.file_ = std::move(file); + } +#elif PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) + ScopedPlatformHandle map( + CreateFileMapping(*file, nullptr, PAGE_READONLY, 0, 0, nullptr)); + if (!map) { + return ret; + } + void* ptr = MapViewOfFile(*map, FILE_MAP_READ, 0, 0, length); + if (ptr != nullptr) { + ret.ptr_ = ptr; + ret.length_ = length; + ret.file_ = std::move(file); + ret.map_ = std::move(map); + } +#else + base::ignore_result(length); +#endif + return ret; +} + +bool ScopedMmap::reset() noexcept { + bool ret = true; +#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \ + PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \ + PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE) + if (ptr_ != nullptr) { + ret = munmap(ptr_, length_) == 0; + } +#elif PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) + if (ptr_ != nullptr) { + ret = UnmapViewOfFile(ptr_); + } + map_.reset(); +#endif + ptr_ = nullptr; + length_ = 0; + file_.reset(); + return ret; +} + +ScopedMmap ReadMmapFilePart(const char* fname, size_t length) { + return ScopedMmap::FromHandle(OpenFileForMmap(fname), length); +} + +ScopedMmap ReadMmapWholeFile(const char* fname) { + ScopedPlatformHandle file = OpenFileForMmap(fname); + if (!file) { + return ScopedMmap(); + } + std::optional<size_t> file_size = GetPlatformHandleFileSize(file.get()); + if (!file_size.has_value()) { + return ScopedMmap(); + } + return ScopedMmap::FromHandle(std::move(file), *file_size); +} + +} // namespace perfetto::base
diff --git a/src/base/scoped_mmap_unittest.cc b/src/base/scoped_mmap_unittest.cc new file mode 100644 index 0000000..2c6b004 --- /dev/null +++ b/src/base/scoped_mmap_unittest.cc
@@ -0,0 +1,87 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "perfetto/ext/base/scoped_mmap.h" + +#include "src/base/test/tmp_dir_tree.h" +#include "test/gtest_and_gmock.h" + +namespace perfetto::base { +namespace { + +class ScopedMmapTest : public ::testing::Test { + void SetUp() override { +#if !PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) && \ + !PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) && \ + !PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE) && \ + !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) + GTEST_SKIP() << "mmap not supported"; +#endif + } +}; + +TEST_F(ScopedMmapTest, WholeNonExistingFile) { + base::TmpDirTree tmp; + + ScopedMmap mapped = ReadMmapWholeFile(tmp.AbsolutePath("f1.txt").c_str()); + + EXPECT_FALSE(mapped.IsValid()); +} + +TEST_F(ScopedMmapTest, PartNonExistingFile) { + base::TmpDirTree tmp; + + ScopedMmap mapped = ReadMmapFilePart(tmp.AbsolutePath("f1.txt").c_str(), 4); + + EXPECT_FALSE(mapped.IsValid()); +} + +TEST_F(ScopedMmapTest, WholeOneByteFile) { + base::TmpDirTree tmp; + tmp.AddFile("f1.txt", "c"); + + ScopedMmap mapped = ReadMmapWholeFile(tmp.AbsolutePath("f1.txt").c_str()); + + ASSERT_TRUE(mapped.IsValid()); + ASSERT_NE(mapped.data(), nullptr); + ASSERT_EQ(mapped.length(), 1u); + EXPECT_EQ(*static_cast<char*>(mapped.data()), 'c'); +} + +TEST_F(ScopedMmapTest, PartThreeBytes) { + base::TmpDirTree tmp; + tmp.AddFile("f1.txt", "ccccc"); + + ScopedMmap mapped = ReadMmapFilePart(tmp.AbsolutePath("f1.txt").c_str(), 3); + + ASSERT_TRUE(mapped.IsValid()); + ASSERT_NE(mapped.data(), nullptr); + ASSERT_EQ(mapped.length(), 3u); +} + +TEST_F(ScopedMmapTest, Reset) { + base::TmpDirTree tmp; + tmp.AddFile("f1.txt", "ccccc"); + ScopedMmap mapped = ReadMmapWholeFile(tmp.AbsolutePath("f1.txt").c_str()); + ASSERT_TRUE(mapped.IsValid()); + + EXPECT_TRUE(mapped.reset()); + + EXPECT_FALSE(mapped.IsValid()); +} + +} // namespace +} // namespace perfetto::base
diff --git a/src/profiling/symbolizer/BUILD.gn b/src/profiling/symbolizer/BUILD.gn index c81dbb1..722d1cf 100644 --- a/src/profiling/symbolizer/BUILD.gn +++ b/src/profiling/symbolizer/BUILD.gn
@@ -29,9 +29,6 @@ "filesystem_windows.cc", "local_symbolizer.cc", "local_symbolizer.h", - "scoped_read_mmap.h", - "scoped_read_mmap_posix.cc", - "scoped_read_mmap_windows.cc", "subprocess.h", "subprocess_posix.cc", "subprocess_windows.cc",
diff --git a/src/profiling/symbolizer/local_symbolizer.cc b/src/profiling/symbolizer/local_symbolizer.cc index 9ade8b4..eee5076 100644 --- a/src/profiling/symbolizer/local_symbolizer.cc +++ b/src/profiling/symbolizer/local_symbolizer.cc
@@ -30,10 +30,10 @@ #include "perfetto/base/logging.h" #include "perfetto/ext/base/file_utils.h" #include "perfetto/ext/base/scoped_file.h" +#include "perfetto/ext/base/scoped_mmap.h" #include "perfetto/ext/base/string_utils.h" #include "src/profiling/symbolizer/elf.h" #include "src/profiling/symbolizer/filesystem.h" -#include "src/profiling/symbolizer/scoped_read_mmap.h" namespace perfetto { namespace profiling { @@ -222,12 +222,12 @@ static_assert(EI_CLASS > EI_MAG3, "mem[EI_MAG?] accesses are in range."); if (size <= EI_CLASS) return std::nullopt; - ScopedReadMmap map(fname, size); + base::ScopedMmap map = base::ReadMmapFilePart(fname, size); if (!map.IsValid()) { - PERFETTO_PLOG("mmap"); + PERFETTO_PLOG("Failed to mmap %s", fname); return std::nullopt; } - char* mem = static_cast<char*>(*map); + char* mem = static_cast<char*>(map.data()); if (!IsElf(mem, size)) return std::nullopt;
diff --git a/src/profiling/symbolizer/scoped_read_mmap.h b/src/profiling/symbolizer/scoped_read_mmap.h deleted file mode 100644 index 69a028a..0000000 --- a/src/profiling/symbolizer/scoped_read_mmap.h +++ /dev/null
@@ -1,48 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef SRC_PROFILING_SYMBOLIZER_SCOPED_READ_MMAP_H_ -#define SRC_PROFILING_SYMBOLIZER_SCOPED_READ_MMAP_H_ - -#include "perfetto/ext/base/scoped_file.h" - -namespace perfetto { -namespace profiling { - -class ScopedReadMmap { - public: - ScopedReadMmap(const char* fname, size_t length); - virtual ~ScopedReadMmap(); - - void* operator*() { return ptr_; } - - bool IsValid(); - - private: - size_t length_; - void* ptr_; -#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) - void* file_ = nullptr; - void* map_ = nullptr; -#else - base::ScopedFile fd_; -#endif -}; - -} // namespace profiling -} // namespace perfetto - -#endif // SRC_PROFILING_SYMBOLIZER_SCOPED_READ_MMAP_H_
diff --git a/src/profiling/symbolizer/scoped_read_mmap_posix.cc b/src/profiling/symbolizer/scoped_read_mmap_posix.cc deleted file mode 100644 index f6c3276..0000000 --- a/src/profiling/symbolizer/scoped_read_mmap_posix.cc +++ /dev/null
@@ -1,50 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "src/profiling/symbolizer/scoped_read_mmap.h" - -#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) - -#include "perfetto/base/logging.h" -#include "perfetto/ext/base/file_utils.h" - -#include <sys/mman.h> - -namespace perfetto { -namespace profiling { - -ScopedReadMmap::ScopedReadMmap(const char* fname, size_t length) - : length_(length), fd_(base::OpenFile(fname, O_RDONLY)) { - if (!fd_) { - PERFETTO_PLOG("Failed to open %s", fname); - return; - } - ptr_ = mmap(nullptr, length, PROT_READ, MAP_PRIVATE, *fd_, 0); -} - -ScopedReadMmap::~ScopedReadMmap() { - if (ptr_ != MAP_FAILED) - munmap(ptr_, length_); -} - -bool ScopedReadMmap::IsValid() { - return ptr_ != MAP_FAILED; -} - -} // namespace profiling -} // namespace perfetto - -#endif // !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
diff --git a/src/profiling/symbolizer/scoped_read_mmap_windows.cc b/src/profiling/symbolizer/scoped_read_mmap_windows.cc deleted file mode 100644 index d56d913..0000000 --- a/src/profiling/symbolizer/scoped_read_mmap_windows.cc +++ /dev/null
@@ -1,65 +0,0 @@ - -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "src/profiling/symbolizer/scoped_read_mmap.h" - -#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) - -#include <Windows.h> - -namespace perfetto { -namespace profiling { - -ScopedReadMmap::ScopedReadMmap(const char* fName, size_t length) - : length_(length), ptr_(nullptr) { - file_ = CreateFileA(fName, GENERIC_READ, FILE_SHARE_READ, nullptr, - OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); - if (file_ == INVALID_HANDLE_VALUE) { - PERFETTO_DLOG("Failed to open file: %s", fName); - return; - } - map_ = CreateFileMapping(file_, nullptr, PAGE_READONLY, 0, 0, nullptr); - if (map_ == INVALID_HANDLE_VALUE) { - PERFETTO_DLOG("Failed to mmap file"); - return; - } - ptr_ = MapViewOfFile(map_, FILE_MAP_READ, 0, 0, length_); - if (ptr_ == nullptr) { - PERFETTO_DLOG("Failed to map view of file"); - } -} - -ScopedReadMmap::~ScopedReadMmap() { - if (ptr_ != nullptr) { - UnmapViewOfFile(ptr_); - } - if (map_ != nullptr && map_ != INVALID_HANDLE_VALUE) { - CloseHandle(map_); - } - if (file_ != nullptr && file_ != INVALID_HANDLE_VALUE) { - CloseHandle(file_); - } -} - -bool ScopedReadMmap::IsValid() { - return ptr_ != nullptr; -} - -} // namespace profiling -} // namespace perfetto - -#endif // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)