From 3ad229aec282fc1c984c608e6a598d300f6f2baf Mon Sep 17 00:00:00 2001 From: FirstName LastName Date: Mon, 11 Dec 2023 18:33:49 +0000 Subject: [PATCH] Deprecate SbMemoryMap APIs. - Deprecated SbMemoryMap, SbMemoryUnmap, SbMemoryProtect and SbMemoryFlush. b/302332972 Change-Id: I198963e11db32c14ecc35096691da00d6d690ddd --- starboard/CHANGELOG.md | 5 + starboard/elf_loader/exported_symbols.cc | 16 +- starboard/elf_loader/program_table.cc | 45 ++-- starboard/memory.h | 10 +- starboard/nplb/BUILD.gn | 1 + starboard/nplb/memory_map_test.cc | 4 + .../executable_memory_test.cc | 12 +- .../posix_compliance/posix_memory_map_test.cc | 241 ++++++++++++++++++ starboard/shared/posix/memory_map.cc | 4 + starboard/shared/posix/memory_protect.cc | 4 + starboard/shared/posix/memory_unmap.cc | 4 + starboard/shared/posix/page_internal.cc | 49 ++-- starboard/shared/posix/page_internal.h | 15 +- starboard/shared/win32/memory_flush.cc | 2 + starboard/shared/win32/memory_map.cc | 2 + starboard/shared/win32/memory_protect.cc | 3 + starboard/shared/win32/memory_unmap.cc | 2 + .../include/{time.h => posix_force_include.h} | 25 +- .../include/{stdlib.h => sys/mman.h} | 78 +++--- starboard/shared/win32/posix_emu/mman.cc | 109 ++++++++ .../api_leak_detector/api_leak_detector.py | 4 + starboard/win/shared/BUILD.gn | 1 + .../shared/platform_configuration/BUILD.gn | 7 +- third_party/icu/source/common/umapfile.cpp | 3 +- third_party/musl/BUILD.gn | 1 + third_party/musl/src/starboard/mman/mman.c | 61 +++++ .../src/base/platform/platform-starboard.cc | 33 ++- 27 files changed, 608 insertions(+), 133 deletions(-) create mode 100644 starboard/nplb/posix_compliance/posix_memory_map_test.cc rename starboard/shared/win32/posix_emu/include/{time.h => posix_force_include.h} (72%) rename starboard/shared/win32/posix_emu/include/{stdlib.h => sys/mman.h} (54%) create mode 100644 starboard/shared/win32/posix_emu/mman.cc create mode 100644 third_party/musl/src/starboard/mman/mman.c diff --git a/starboard/CHANGELOG.md b/starboard/CHANGELOG.md index a68060a68228..55a970a75d29 100644 --- a/starboard/CHANGELOG.md +++ b/starboard/CHANGELOG.md @@ -9,6 +9,11 @@ since the version previous to it. ## Version 16 +### Deprecated SbMemoryMap APIs and migrated to POSIX mmap +The memory mapping APIs `SbMemoryMap`, `SbMemoryUnmap`, `SbMemoryProtect` and +`SbMemoryFlush` are deprecated and the standard APIs `mmap`, `munmap`, +`mprotect`, `msync` from `` should be used instead. + ### Deprecated SbMemory allocation APIs and migrated to POSIX memory APIs The memory management APIs `SbMemoryAllocate`, `SbMemoryReallocate`, `SbMemoryCalloc`, `SbMemoryAllocateAligned`, `SbMemoryDeallocate`, diff --git a/starboard/elf_loader/exported_symbols.cc b/starboard/elf_loader/exported_symbols.cc index 5e69aa29a44e..194d326ea775 100644 --- a/starboard/elf_loader/exported_symbols.cc +++ b/starboard/elf_loader/exported_symbols.cc @@ -15,6 +15,7 @@ #include "starboard/elf_loader/exported_symbols.h" #include +#include #include #include "starboard/accessibility.h" @@ -201,12 +202,9 @@ ExportedSymbols::ExportedSymbols() { REGISTER_SYMBOL(SbMemoryDeallocate); REGISTER_SYMBOL(SbMemoryDeallocateAligned); REGISTER_SYMBOL(SbMemoryDeallocateNoReport); -#endif // SB_API_VERSION < 16 #if SB_CAN(MAP_EXECUTABLE_MEMORY) REGISTER_SYMBOL(SbMemoryFlush); #endif // SB_CAN(MAP_EXECUTABLE_MEMORY) - -#if SB_API_VERSION < 16 REGISTER_SYMBOL(SbMemoryFree); REGISTER_SYMBOL(SbMemoryFreeAligned); #endif // SB_API_VERSION < 16 @@ -214,10 +212,10 @@ ExportedSymbols::ExportedSymbols() { #if SB_API_VERSION < 15 REGISTER_SYMBOL(SbMemoryGetStackBounds); #endif - REGISTER_SYMBOL(SbMemoryMap); - REGISTER_SYMBOL(SbMemoryProtect); #if SB_API_VERSION < 16 + REGISTER_SYMBOL(SbMemoryMap); + REGISTER_SYMBOL(SbMemoryProtect); REGISTER_SYMBOL(SbMemoryReallocate); REGISTER_SYMBOL(SbMemoryReallocateUnchecked); #endif // SB_API_VERSION < 16 @@ -225,7 +223,11 @@ ExportedSymbols::ExportedSymbols() { #if SB_API_VERSION < 15 REGISTER_SYMBOL(SbMemorySetReporter); #endif + +#if SB_API_VERSION < 16 REGISTER_SYMBOL(SbMemoryUnmap); +#endif // SB_API_VERSION < 16 + REGISTER_SYMBOL(SbMicrophoneClose); REGISTER_SYMBOL(SbMicrophoneCreate); REGISTER_SYMBOL(SbMicrophoneDestroy); @@ -420,6 +422,10 @@ ExportedSymbols::ExportedSymbols() { // TODO: b/316603042 - Detect via NPLB and only add the wrapper if needed. map_["clock_gettime"] = reinterpret_cast(&__wrap_clock_gettime); map_["gettimeofday"] = reinterpret_cast(&__wrap_gettimeofday); + REGISTER_SYMBOL(mmap); + REGISTER_SYMBOL(mprotect); + REGISTER_SYMBOL(munmap); + REGISTER_SYMBOL(msync); #endif // SB_API_VERSION >= 16 } // NOLINT diff --git a/starboard/elf_loader/program_table.cc b/starboard/elf_loader/program_table.cc index 824a68f92902..56ddf44a3a29 100644 --- a/starboard/elf_loader/program_table.cc +++ b/starboard/elf_loader/program_table.cc @@ -14,6 +14,8 @@ #include "starboard/elf_loader/program_table.h" +#include + #include "starboard/common/log.h" #include "starboard/common/string.h" #include "starboard/elf_loader/evergreen_info.h" @@ -24,14 +26,12 @@ #define MAYBE_MAP_FLAG(x, from, to) (((x) & (from)) ? (to) : 0) #if SB_CAN(MAP_EXECUTABLE_MEMORY) -#define PFLAGS_TO_PROT(x) \ - (MAYBE_MAP_FLAG((x), PF_X, kSbMemoryMapProtectExec) | \ - MAYBE_MAP_FLAG((x), PF_R, kSbMemoryMapProtectRead) | \ - MAYBE_MAP_FLAG((x), PF_W, kSbMemoryMapProtectWrite)) +#define PFLAGS_TO_PROT(x) \ + (MAYBE_MAP_FLAG((x), PF_X, PROT_EXEC) | \ + MAYBE_MAP_FLAG((x), PF_R, PROT_READ) | \ + MAYBE_MAP_FLAG((x), PF_W, PROT_WRITE)) #endif -#define MAP_FAILED ((void*)-1) - namespace starboard { namespace elf_loader { @@ -92,7 +92,7 @@ bool ProgramTable::LoadProgramHeader(const Ehdr* elf_header, File* elf_file) { SB_DLOG(INFO) << "Allocated address=" << phdr_mmap_; } else { phdr_mmap_ = - SbMemoryMap(phdr_size_, kSbMemoryMapProtectWrite, "program_header"); + mmap(nullptr, phdr_size_, PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); if (!phdr_mmap_) { SB_LOG(ERROR) << "Failed to allocate memory"; return false; @@ -105,8 +105,7 @@ bool ProgramTable::LoadProgramHeader(const Ehdr* elf_header, File* elf_file) { << page_min; return false; } - bool mp_result = - SbMemoryProtect(phdr_mmap_, phdr_size_, kSbMemoryMapProtectRead); + bool mp_result = mprotect(phdr_mmap_, phdr_size_, PROT_READ) == 0; SB_DLOG(INFO) << "mp_result=" << mp_result; if (!mp_result) { SB_LOG(ERROR) << "Failed to protect program header"; @@ -205,8 +204,7 @@ bool ProgramTable::LoadSegments(File* elf_file) { } } else { SB_DLOG(INFO) << "Not using Memory Mapped Files"; - mp_ret = - SbMemoryProtect(seg_addr, file_length, kSbMemoryMapProtectWrite); + mp_ret = mprotect(seg_addr, file_length, PROT_WRITE) == 0; SB_DLOG(INFO) << "segment vaddress=" << seg_addr; if (!mp_ret) { @@ -221,7 +219,7 @@ bool ProgramTable::LoadSegments(File* elf_file) { return false; } } - mp_ret = SbMemoryProtect(seg_addr, file_length, prot_flags); + mp_ret = mprotect(seg_addr, file_length, prot_flags) == 0; SB_DLOG(INFO) << "mp_ret=" << mp_ret; if (!mp_ret) { SB_LOG(ERROR) << "Failed to protect segment"; @@ -251,9 +249,9 @@ bool ProgramTable::LoadSegments(File* elf_file) { // map for all extra pages. if (seg_page_end > seg_file_end) { #if SB_CAN(MAP_EXECUTABLE_MEMORY) - bool mprotect_fix = SbMemoryProtect(reinterpret_cast(seg_file_end), - seg_page_end - seg_file_end, - kSbMemoryMapProtectWrite); + bool mprotect_fix = + mprotect(reinterpret_cast(seg_file_end), + seg_page_end - seg_file_end, PROT_WRITE) == 0; SB_DLOG(INFO) << "mprotect_fix=" << mprotect_fix; if (!mprotect_fix) { SB_LOG(ERROR) << "Failed to unprotect end of segment"; @@ -266,9 +264,8 @@ bool ProgramTable::LoadSegments(File* elf_file) { memset(reinterpret_cast(seg_file_end), 0, seg_page_end - seg_file_end); #if SB_CAN(MAP_EXECUTABLE_MEMORY) - SbMemoryProtect(reinterpret_cast(seg_file_end), - seg_page_end - seg_file_end, - PFLAGS_TO_PROT(phdr->p_flags)); + mprotect(reinterpret_cast(seg_file_end), + seg_page_end - seg_file_end, PFLAGS_TO_PROT(phdr->p_flags)); SB_DLOG(INFO) << "mprotect_fix=" << mprotect_fix; if (!mprotect_fix) { SB_LOG(ERROR) << "Failed to protect end of segment"; @@ -360,9 +357,9 @@ int ProgramTable::AdjustMemoryProtectionOfReadOnlySegments( Addr seg_page_end = PAGE_END(phdr->p_vaddr + phdr->p_memsz) + base_memory_address_; #if SB_CAN(MAP_EXECUTABLE_MEMORY) - int ret = SbMemoryProtect(reinterpret_cast(seg_page_start), - seg_page_end - seg_page_start, - PFLAGS_TO_PROT(phdr->p_flags) | extra_prot_flags); + int ret = mprotect(reinterpret_cast(seg_page_start), + seg_page_end - seg_page_start, + PFLAGS_TO_PROT(phdr->p_flags) | extra_prot_flags); if (ret < 0) { return -1; } @@ -383,7 +380,7 @@ bool ProgramTable::ReserveLoadMemory() { SB_DLOG(INFO) << "Load size=" << load_size_; load_start_ = - SbMemoryMap(load_size_, kSbMemoryMapProtectReserved, "reserved_mem"); + mmap(nullptr, load_size_, PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0); if (load_start_ == MAP_FAILED) { SB_LOG(ERROR) << "Could not reserve " << load_size_ << " bytes of address space"; @@ -421,10 +418,10 @@ Addr ProgramTable::GetBaseMemoryAddress() { ProgramTable::~ProgramTable() { SetEvergreenInfo(NULL); if (load_start_) { - SbMemoryUnmap(load_start_, load_size_); + munmap(load_start_, load_size_); } if (phdr_mmap_) { - SbMemoryUnmap(phdr_mmap_, phdr_size_); + munmap(phdr_mmap_, phdr_size_); } } diff --git a/starboard/memory.h b/starboard/memory.h index bd4a8d39e4c2..8bcd2fabad36 100644 --- a/starboard/memory.h +++ b/starboard/memory.h @@ -50,8 +50,8 @@ extern "C" { #endif -#define SB_MEMORY_MAP_FAILED ((void*)-1) // NOLINT(readability/casting) - +// TODO: Remove the definition once the memory_mapped_file.h extension +// is deprecated. // The bitwise OR of these flags should be passed to SbMemoryMap to indicate // how the mapped memory can be used. typedef enum SbMemoryMapFlags { @@ -68,6 +68,9 @@ typedef enum SbMemoryMapFlags { } SbMemoryMapFlags; #if SB_API_VERSION < 16 + +#define SB_MEMORY_MAP_FAILED ((void*)-1) // NOLINT(readability/casting) + static SB_C_FORCE_INLINE void SbAbortIfAllocationFailed(size_t requested_bytes, void* address) { if (SB_UNLIKELY(requested_bytes > 0 && address == NULL)) { @@ -178,8 +181,6 @@ SB_DEPRECATED_EXTERNAL(SB_EXPORT void SbMemoryFree(void* memory)); // DO NOT CALL. Call SbMemoryDeallocateAligned(...) instead. SB_DEPRECATED_EXTERNAL(SB_EXPORT void SbMemoryFreeAligned(void* memory)); -#endif // SB_API_VERSION < 16 - // Allocates |size_bytes| worth of physical memory pages and maps them into // an available virtual region. This function returns |SB_MEMORY_MAP_FAILED| // on failure. |NULL| is a valid return value. @@ -219,6 +220,7 @@ SB_EXPORT bool SbMemoryProtect(void* virtual_address, // memory that has been written to and might be executed in the future. SB_EXPORT void SbMemoryFlush(void* virtual_address, int64_t size_bytes); #endif +#endif // SB_API_VERSION < 16 #if SB_API_VERSION < 15 diff --git a/starboard/nplb/BUILD.gn b/starboard/nplb/BUILD.gn index cfc2e867ebfb..b3583154f1f0 100644 --- a/starboard/nplb/BUILD.gn +++ b/starboard/nplb/BUILD.gn @@ -134,6 +134,7 @@ target(gtest_target_type, "nplb") { "player_test_util.cc", "player_test_util.h", "player_write_sample_test.cc", + "posix_compliance/posix_memory_map_test.cc", "random_helpers.cc", "recursive_mutex_test.cc", "rwlock_test.cc", diff --git a/starboard/nplb/memory_map_test.cc b/starboard/nplb/memory_map_test.cc index 10d2b9b1a5a2..134acc870095 100644 --- a/starboard/nplb/memory_map_test.cc +++ b/starboard/nplb/memory_map_test.cc @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +#if SB_API_VERSION < 16 + #include #include "starboard/common/memory.h" @@ -294,3 +296,5 @@ TEST(SbMemoryMapTest, CanChangeMemoryProtection) { } // namespace } // namespace nplb } // namespace starboard + +#endif // SB_API_VERSION < 16 diff --git a/starboard/nplb/nplb_evergreen_compat_tests/executable_memory_test.cc b/starboard/nplb/nplb_evergreen_compat_tests/executable_memory_test.cc index c2fab51a58ea..e8ce94ae8d3e 100644 --- a/starboard/nplb/nplb_evergreen_compat_tests/executable_memory_test.cc +++ b/starboard/nplb/nplb_evergreen_compat_tests/executable_memory_test.cc @@ -12,7 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "starboard/memory.h" +#include + #include "starboard/nplb/nplb_evergreen_compat_tests/checks.h" #include "testing/gtest/include/gtest/gtest.h" @@ -35,12 +36,11 @@ class ExecutableMemoryTest : public ::testing::Test { TEST_F(ExecutableMemoryTest, VerifyMemoryProtection) { void* memory = - SbMemoryMap(kSize, kSbMemoryMapProtectWrite, "evergreen_buffer"); - ASSERT_NE(SB_MEMORY_MAP_FAILED, memory); + mmap(nullptr, kSize, PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); + ASSERT_NE(MAP_FAILED, memory); memset(memory, 0, kSize); - ASSERT_TRUE(SbMemoryProtect( - memory, kSmallerSize, kSbMemoryMapProtectRead | kSbMemoryMapProtectExec)); - SbMemoryUnmap(memory, kSize); + ASSERT_EQ(mprotect(memory, kSmallerSize, PROT_READ | PROT_WRITE), 0); + munmap(memory, kSize); EXPECT_TRUE(true); } diff --git a/starboard/nplb/posix_compliance/posix_memory_map_test.cc b/starboard/nplb/posix_compliance/posix_memory_map_test.cc new file mode 100644 index 000000000000..07b6275e0d54 --- /dev/null +++ b/starboard/nplb/posix_compliance/posix_memory_map_test.cc @@ -0,0 +1,241 @@ +// Copyright 2016 The Cobalt Authors. All Rights Reserved. +// +// 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. + +#if SB_API_VERSION >= 16 + +#include +#include + +#include "starboard/common/memory.h" +#include "starboard/configuration_constants.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace starboard { +namespace nplb { +namespace { + +const size_t kSize = kSbMemoryPageSize * 8; +const void* kFailed = MAP_FAILED; + +TEST(PosixMemoryMapTest, AllocatesNormally) { + void* memory = mmap(nullptr, kSize, PROT_READ, MAP_PRIVATE | MAP_ANON, -1, 0); + ASSERT_NE(kFailed, memory); + EXPECT_EQ(munmap(memory, kSize), 0); +} + +TEST(PosixMemoryMapTest, AllocatesZero) { + void* memory = mmap(nullptr, 0, PROT_READ, MAP_PRIVATE | MAP_ANON, -1, 0); + ASSERT_EQ(kFailed, memory); + EXPECT_NE(munmap(memory, 0), 0); +} + +TEST(PosixMemoryMapTest, AllocatesOne) { + void* memory = mmap(nullptr, 1, PROT_READ, MAP_PRIVATE | MAP_ANON, -1, 0); + ASSERT_NE(kFailed, memory); + EXPECT_EQ(munmap(memory, 1), 0); +} + +TEST(PosixMemoryMapTest, AllocatesOnePage) { + void* memory = mmap(nullptr, kSbMemoryPageSize, PROT_READ, + MAP_PRIVATE | MAP_ANON, -1, 0); + ASSERT_NE(kFailed, memory); + EXPECT_EQ(munmap(memory, kSbMemoryPageSize), 0); +} + +TEST(PosixMemoryMapTest, CanReadWriteToResult) { + void* memory = + mmap(nullptr, kSize, PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); + ASSERT_NE(kFailed, memory); + char* data = static_cast(memory); + for (int i = 0; i < kSize; ++i) { + data[i] = static_cast(i); + } + + for (int i = 0; i < kSize; ++i) { + EXPECT_EQ(data[i], static_cast(i)); + } + + EXPECT_EQ(munmap(memory, kSize), 0); +} + +#if SB_CAN(MAP_EXECUTABLE_MEMORY) + +typedef int (*SumFunction)(int, int); +static int Sum(int x, int y) { + return x + y; +} +static int Sum2(int x, int y) { + return x + y + x; +} + +// Copy the contents of |Sum| into |memory|, returning an assertion result +// indicating whether the copy was successful, a function pointer to the +// possibly copied |Sum| function data and a function pointer to the selected +// original function.. Clients are expected to immediately call |ASSERT| on +// the assertion result. +std::tuple<::testing::AssertionResult, SumFunction, SumFunction> +CopySumFunctionIntoMemory(void* memory) { + // There's no reliable way to determine the size of the 'Sum' function. If we + // assume the function is at most a certain size, then we might try to read + // beyond mapped memory when copying it to the destination address. We can + // get a reasonable upper bound by assuming that the function's implementation + // does not cross a page boundary, and copy the memory from the beginning of + // the function to the end of the page that it is mapped to. + // + // However, since it's possible the function may cross the page boundary, we + // define two functions and use the one closest to the start of a page. There + // is no guarantee that the linker will place these definitions sequentially + // (although it likely will), so we can't use the address of 'Sum2' as the + // end of 'Sum'. + // + // To avoid the possibility that COMDAT folding will combine these two + // definitions into one, make sure they are different. + + // A function pointer can't be cast to void*, but uint8* seems to be okay. So + // cast to a uint* which will be implicitly casted to a void* below. + SumFunction original_function = ∑ + if (reinterpret_cast(&Sum2) % kSbMemoryPageSize < + reinterpret_cast(&Sum) % kSbMemoryPageSize) { + original_function = &Sum2; + } + + uint8_t* sum_function_start = reinterpret_cast(original_function); + + // MIPS16 instruction are kept odd addresses to differentiate between that and + // MIPS32 instructions. Most other instructions are aligned to at least even + // addresses, so this code should do nothing for those architectures. + // https://www.linux-mips.org/wiki/MIPS16 + ptrdiff_t sum_function_offset = + sum_function_start - + reinterpret_cast( + reinterpret_cast(sum_function_start) & ~0x1); + sum_function_start -= sum_function_offset; + + // Get the last address of the page that |sum_function_start| is on. + uint8_t* sum_function_page_end = reinterpret_cast( + (reinterpret_cast(sum_function_start) / kSbMemoryPageSize) * + kSbMemoryPageSize + + kSbMemoryPageSize); + if (!starboard::common::MemoryIsAligned(sum_function_page_end, + kSbMemoryPageSize)) { + return std::make_tuple(::testing::AssertionFailure() + << "Expected |Sum| page end (" + << static_cast(sum_function_page_end) + << ") to be aligned to " << kSbMemoryPageSize, + nullptr, nullptr); + } + if (sum_function_start >= sum_function_page_end) { + return std::make_tuple(::testing::AssertionFailure() + << "Expected |Sum| function page start (" + << static_cast(sum_function_start) + << ") to be less than |Sum| function page end (" + << static_cast(sum_function_page_end) + << ")", + nullptr, nullptr); + } + + size_t bytes_to_copy = sum_function_page_end - sum_function_start; + if (bytes_to_copy > kSbMemoryPageSize) { + return std::make_tuple( + ::testing::AssertionFailure() + << "Expected bytes required to copy |Sum| to be less than " + << kSbMemoryPageSize << ", Actual: " << bytes_to_copy, + nullptr, nullptr); + } + + memcpy(memory, sum_function_start, bytes_to_copy); + + SumFunction mapped_function = reinterpret_cast( + reinterpret_cast(memory) + sum_function_offset); + + return std::make_tuple(::testing::AssertionSuccess(), mapped_function, + original_function); +} +#endif // SB_CAN(MAP_EXECUTABLE_MEMORY) + +TEST(PosixMemoryMapTest, CanChangeMemoryProtection) { + int all_from_flags[] = { + PROT_NONE, + PROT_READ, + PROT_WRITE, + PROT_READ | PROT_WRITE, + }; + int all_to_flags[] = { + PROT_NONE, + PROT_READ, + PROT_WRITE, + PROT_READ | PROT_WRITE, +#if SB_CAN(MAP_EXECUTABLE_MEMORY) + PROT_EXEC, + PROT_READ | PROT_EXEC, +#endif + }; + + for (int from_flags : all_from_flags) { + for (int to_flags : all_to_flags) { + void* memory = + mmap(nullptr, kSize, from_flags, MAP_PRIVATE | MAP_ANON, -1, 0); + // If the platform does not support a particular protection flags + // configuration in the first place, then just give them a pass, knowing + // that that feature will be tested elsewhere. + if (memory == MAP_FAILED) { + continue; + } + +#if SB_CAN(MAP_EXECUTABLE_MEMORY) + // We can only test the ability to execute memory after changing + // protections if we have write permissions either now or then, because + // we have to actually put a valid function into the mapped memory. + SumFunction mapped_function = nullptr; + SumFunction original_function = nullptr; + if (from_flags & PROT_WRITE) { + auto copy_sum_function_result = CopySumFunctionIntoMemory(memory); + ASSERT_TRUE(std::get<0>(copy_sum_function_result)); + mapped_function = std::get<1>(copy_sum_function_result); + original_function = std::get<2>(copy_sum_function_result); + } +#endif + + if (mprotect(memory, kSize, to_flags) != 0) { + EXPECT_EQ(munmap(memory, kSize), 0); + continue; + } + +#if SB_CAN(MAP_EXECUTABLE_MEMORY) + if ((to_flags & PROT_EXEC) && mapped_function != nullptr) { + EXPECT_EQ(original_function(0xc0ba178, 0xbadf00d), + mapped_function(0xc0ba178, 0xbadf00d)); + } +#endif + + if (to_flags & PROT_READ) { + for (int i = 0; i < kSize; i++) { + volatile uint8_t force_read = static_cast(memory)[i]; + } + } + if (to_flags & PROT_WRITE) { + for (int i = 0; i < kSize; i++) { + static_cast(memory)[i] = 0xff; + } + } + + EXPECT_EQ(munmap(memory, kSize), 0); + } + } +} + +} // namespace +} // namespace nplb +} // namespace starboard +#endif // SB_API_VERSION >= 16 diff --git a/starboard/shared/posix/memory_map.cc b/starboard/shared/posix/memory_map.cc index 04c51c321d19..97d9e38a9c1e 100644 --- a/starboard/shared/posix/memory_map.cc +++ b/starboard/shared/posix/memory_map.cc @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +#if SB_API_VERSION < 16 + #include "starboard/memory.h" #include "starboard/shared/posix/page_internal.h" @@ -19,3 +21,5 @@ void* SbMemoryMap(int64_t size_bytes, int flags, const char* name) { void* memory = SbPageMap(size_bytes, flags, name); return memory; } + +#endif // SB_API_VERSION < 16 diff --git a/starboard/shared/posix/memory_protect.cc b/starboard/shared/posix/memory_protect.cc index 1d861fd35118..f1f544b1a55a 100644 --- a/starboard/shared/posix/memory_protect.cc +++ b/starboard/shared/posix/memory_protect.cc @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +#if SB_API_VERSION < 16 + #include "starboard/configuration.h" #include "starboard/memory.h" #include "starboard/shared/posix/page_internal.h" @@ -19,3 +21,5 @@ bool SbMemoryProtect(void* virtual_address, int64_t size_bytes, int flags) { return SbPageProtect(virtual_address, size_bytes, flags); } + +#endif // SB_API_VERSION < 16 diff --git a/starboard/shared/posix/memory_unmap.cc b/starboard/shared/posix/memory_unmap.cc index 96592dfd14bb..f539e17b355d 100644 --- a/starboard/shared/posix/memory_unmap.cc +++ b/starboard/shared/posix/memory_unmap.cc @@ -12,9 +12,13 @@ // See the License for the specific language governing permissions and // limitations under the License. +#if SB_API_VERSION < 16 + #include "starboard/memory.h" #include "starboard/shared/posix/page_internal.h" bool SbMemoryUnmap(void* virtual_address, int64_t size_bytes) { return SbPageUnmap(virtual_address, size_bytes); } + +#endif // SB_API_VERSION < 16 diff --git a/starboard/shared/posix/page_internal.cc b/starboard/shared/posix/page_internal.cc index 49cbb8a4bed5..4064f4afd10b 100644 --- a/starboard/shared/posix/page_internal.cc +++ b/starboard/shared/posix/page_internal.cc @@ -30,13 +30,6 @@ namespace { -int32_t s_tracked_page_count = 0; - -int32_t GetPageCount(size_t byte_count) { - return static_cast( - starboard::common::MemoryAlignToPageSize(byte_count) / kSbMemoryPageSize); -} - int SbMemoryMapFlagsToMmapProtect(int sb_flags) { bool flag_set = false; int mmap_protect = 0; @@ -63,6 +56,14 @@ int SbMemoryMapFlagsToMmapProtect(int sb_flags) { return mmap_protect; } +#if SB_API_VERSION < 16 +int32_t s_tracked_page_count = 0; + +int32_t GetPageCount(size_t byte_count) { + return static_cast( + starboard::common::MemoryAlignToPageSize(byte_count) / kSbMemoryPageSize); +} + void* SbPageMapUntracked(size_t size_bytes, int flags, const char* unused_name) { @@ -81,8 +82,11 @@ bool SbPageUnmapUntracked(void* ptr, size_t size_bytes) { return munmap(ptr, size_bytes) == 0; } +#endif // SB_API_VERSION < 16 + } // namespace +#if SB_API_VERSION < 16 void* SbPageMap(size_t size_bytes, int flags, const char* unused_name) { void* ret = SbPageMapUntracked(size_bytes, flags, NULL); if (ret != SB_MEMORY_MAP_FAILED) { @@ -92,6 +96,22 @@ void* SbPageMap(size_t size_bytes, int flags, const char* unused_name) { return ret; } +bool SbPageUnmap(void* ptr, size_t size_bytes) { + SbAtomicNoBarrier_Increment(&s_tracked_page_count, -GetPageCount(size_bytes)); + return SbPageUnmapUntracked(ptr, size_bytes); +} + +bool SbPageProtect(void* virtual_address, int64_t size_bytes, int flags) { + int mmap_protect = SbMemoryMapFlagsToMmapProtect(flags); + return mprotect(virtual_address, size_bytes, mmap_protect) == 0; +} + +size_t SbPageGetMappedBytes() { + return static_cast(SbAtomicNoBarrier_Load(&s_tracked_page_count) * + kSbMemoryPageSize); +} +#endif // SB_API_VERSION < 16 + void* SbPageMapFile(void* addr, const char* path, SbMemoryMapFlags flags, @@ -123,18 +143,3 @@ void* SbPageMapFile(void* addr, close(fd); return p; } - -bool SbPageUnmap(void* ptr, size_t size_bytes) { - SbAtomicNoBarrier_Increment(&s_tracked_page_count, -GetPageCount(size_bytes)); - return SbPageUnmapUntracked(ptr, size_bytes); -} - -bool SbPageProtect(void* virtual_address, int64_t size_bytes, int flags) { - int mmap_protect = SbMemoryMapFlagsToMmapProtect(flags); - return mprotect(virtual_address, size_bytes, mmap_protect) == 0; -} - -size_t SbPageGetMappedBytes() { - return static_cast(SbAtomicNoBarrier_Load(&s_tracked_page_count) * - kSbMemoryPageSize); -} diff --git a/starboard/shared/posix/page_internal.h b/starboard/shared/posix/page_internal.h index d653730e6e33..d65207405327 100644 --- a/starboard/shared/posix/page_internal.h +++ b/starboard/shared/posix/page_internal.h @@ -23,12 +23,6 @@ extern "C" { #endif -// Allocates |size_bytes| worth of physical memory pages and maps them into an -// available virtual region. On some platforms, |name| appears in the debugger -// and can be up to 32 bytes. Returns SB_MEMORY_MAP_FAILED on failure, as NULL -// is a valid return value. -void* SbPageMap(size_t size_bytes, int flags, const char* name); - // Memory maps a file to the specified |addr| starting with |file_offset| and // mapping |size| bytes. The |addr| should be reserved before calling. If // NULL |addr| is passed a new memory block would be allocated and the address @@ -40,6 +34,13 @@ void* SbPageMapFile(void* addr, int64_t file_offset, int64_t size); +#if SB_API_VERSION < 16 +// Allocates |size_bytes| worth of physical memory pages and maps them into an +// available virtual region. On some platforms, |name| appears in the debugger +// and can be up to 32 bytes. Returns SB_MEMORY_MAP_FAILED on failure, as NULL +// is a valid return value. +void* SbPageMap(size_t size_bytes, int flags, const char* name); + // Unmap |size_bytes| of physical pages starting from |virtual_address|, // returning true on success. After this, [virtual_address, virtual_address + // size_bytes) will not be read/writable. SbUnmap() can unmap multiple @@ -57,6 +58,8 @@ bool SbPageProtect(void* virtual_address, int64_t size_bytes, int flags); // always be a multiple of kSbMemoryPageSize. size_t SbPageGetMappedBytes(); +#endif // SB_API_VERSION < 16 + #ifdef __cplusplus } // extern "C" #endif diff --git a/starboard/shared/win32/memory_flush.cc b/starboard/shared/win32/memory_flush.cc index 297c01b42190..7beacede7acc 100644 --- a/starboard/shared/win32/memory_flush.cc +++ b/starboard/shared/win32/memory_flush.cc @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +#if SB_API_VERSION < 16 #include "starboard/common/log.h" #include "starboard/memory.h" @@ -28,3 +29,4 @@ void SbMemoryFlush(void* virtual_address, int64_t size_bytes) { // TODO: Enable the following implementation when xb1 can compile it. // FlushInstructionCache(GetCurrentProcess(), virtual_address, size_bytes); } +#endif // SB_API_VERSION < 16 diff --git a/starboard/shared/win32/memory_map.cc b/starboard/shared/win32/memory_map.cc index 529f8d13d658..3d4279a2a1d8 100644 --- a/starboard/shared/win32/memory_map.cc +++ b/starboard/shared/win32/memory_map.cc @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +#if SB_API_VERSION < 16 #include "starboard/memory.h" #include @@ -49,3 +50,4 @@ void* SbMemoryMap(int64_t size_bytes, int flags, const char* name) { protect); return memory; } +#endif // SB_API_VERSION < 16 diff --git a/starboard/shared/win32/memory_protect.cc b/starboard/shared/win32/memory_protect.cc index 8fd9b5d07c91..7f73cca1c302 100644 --- a/starboard/shared/win32/memory_protect.cc +++ b/starboard/shared/win32/memory_protect.cc @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +#if SB_API_VERSION < 16 #include "starboard/memory.h" #include @@ -56,3 +57,5 @@ bool SbMemoryProtect(void* virtual_address, int64_t size_bytes, int flags) { return VirtualProtectFromApp(virtual_address, size_bytes, new_protection, &old_protection) != 0; } + +#endif // SB_API_VERSION < 16 diff --git a/starboard/shared/win32/memory_unmap.cc b/starboard/shared/win32/memory_unmap.cc index 03868dbccf67..8b563555ed44 100644 --- a/starboard/shared/win32/memory_unmap.cc +++ b/starboard/shared/win32/memory_unmap.cc @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +#if SB_API_VERSION < 16 #include "starboard/memory.h" #include @@ -22,3 +23,4 @@ bool SbMemoryUnmap(void* virtual_address, int64_t size_bytes) { // to SbMemoryMap()". Because of that, we cannot use MEM_FREE here. return VirtualFree(virtual_address, size_bytes, MEM_DECOMMIT); } +#endif // SB_API_VERSION < 16 diff --git a/starboard/shared/win32/posix_emu/include/time.h b/starboard/shared/win32/posix_emu/include/posix_force_include.h similarity index 72% rename from starboard/shared/win32/posix_emu/include/time.h rename to starboard/shared/win32/posix_emu/include/posix_force_include.h index 605a5ded2b23..1724849fe058 100644 --- a/starboard/shared/win32/posix_emu/include/time.h +++ b/starboard/shared/win32/posix_emu/include/posix_force_include.h @@ -12,16 +12,19 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef STARBOARD_SHARED_WIN32_POSIX_EMU_INCLUDE_TIME_H_ -#define STARBOARD_SHARED_WIN32_POSIX_EMU_INCLUDE_TIME_H_ +#ifndef STARBOARD_SHARED_WIN32_POSIX_EMU_INCLUDE_POSIX_FORCE_INCLUDE_H_ +#define STARBOARD_SHARED_WIN32_POSIX_EMU_INCLUDE_POSIX_FORCE_INCLUDE_H_ + +// MSVC deprecated strdup() in favor of _strdup() +#define strdup _strdup +#define strcasecmp _stricmp +#define strncasecmp _strnicmp #if defined(STARBOARD) -#include // For struct timespec +#define free sb_free -#ifdef __cplusplus -extern "C" { -#endif +#include // For struct timespec // https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/time.h.html typedef int clockid_t; @@ -29,13 +32,17 @@ typedef int clockid_t; #define CLOCK_MONOTONIC 1 #define CLOCK_PROCESS_CPUTIME_ID 2 +#ifdef __cplusplus +extern "C" { +#endif + // https://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_gettime.html int clock_gettime(clockid_t clock_id, struct timespec* tp); +int posix_memalign(void** res, size_t alignment, size_t size); + #ifdef __cplusplus } #endif // __cplusplus - #endif // defined(STARBOARD) - -#endif // STARBOARD_SHARED_WIN32_POSIX_EMU_INCLUDE_TIME_H_ +#endif // STARBOARD_SHARED_WIN32_POSIX_EMU_INCLUDE_POSIX_FORCE_INCLUDE_H_ diff --git a/starboard/shared/win32/posix_emu/include/stdlib.h b/starboard/shared/win32/posix_emu/include/sys/mman.h similarity index 54% rename from starboard/shared/win32/posix_emu/include/stdlib.h rename to starboard/shared/win32/posix_emu/include/sys/mman.h index 8d7c27d98011..1a1c239a22bb 100644 --- a/starboard/shared/win32/posix_emu/include/stdlib.h +++ b/starboard/shared/win32/posix_emu/include/sys/mman.h @@ -1,36 +1,42 @@ -// Copyright 2023 The Cobalt Authors. All Rights Reserved. -// -// 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 STARBOARD_SHARED_WIN32_POSIX_EMU_INCLUDE_STDLIB_H_ -#define STARBOARD_SHARED_WIN32_POSIX_EMU_INCLUDE_STDLIB_H_ - -// MSVC deprecated strdup() in favor of _strdup() -#define strdup _strdup -#define strcasecmp _stricmp -#define strncasecmp _strnicmp - -#if defined(STARBOARD) -#define free sb_free - -#ifdef __cplusplus -extern "C" { -#endif - -int posix_memalign(void** res, size_t alignment, size_t size); - -#ifdef __cplusplus -} -#endif // __cplusplus -#endif // defined(STARBOARD) -#endif // STARBOARD_SHARED_WIN32_POSIX_EMU_INCLUDE_STDLIB_H_ +// Copyright 2023 The Cobalt Authors. All Rights Reserved. +// +// 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 STARBOARD_SHARED_WIN32_POSIX_EMU_INCLUDE_SYS_MMAN_H_ +#define STARBOARD_SHARED_WIN32_POSIX_EMU_INCLUDE_SYS_MMAN_H_ + +#include + +#define PROT_NONE 0 +#define PROT_READ 1 +#define PROT_WRITE 2 +#define PROT_EXEC 4 + +#define MAP_PRIVATE 0x02 +#define MAP_ANON 0x20 + +#define MAP_FAILED ((void*)-1) + +#ifdef __cplusplus +extern "C" { +#endif + +void* mmap(void*, size_t, int, int, int, off_t); +int munmap(void*, size_t); +int mprotect(void*, size_t, int); +int msync(void*, size_t, int); + +#ifdef __cplusplus +} +#endif +#endif // STARBOARD_SHARED_WIN32_POSIX_EMU_INCLUDE_SYS_MMAN_H_ diff --git a/starboard/shared/win32/posix_emu/mman.cc b/starboard/shared/win32/posix_emu/mman.cc new file mode 100644 index 000000000000..5bc59b82164b --- /dev/null +++ b/starboard/shared/win32/posix_emu/mman.cc @@ -0,0 +1,109 @@ +// Copyright 2023 The Cobalt Authors. All Rights Reserved. +// +// 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 +#include + +#include "starboard/configuration.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void* mmap(void* addr, size_t len, int prot, int flags, int fd, off_t off) { + if (addr != NULL) { + return MAP_FAILED; + } + if (fd != -1) { + return MAP_FAILED; + } + if (len == 0) { + return MAP_FAILED; + } + + ULONG allocation_type = MEM_RESERVE; + ULONG protect = PAGE_NOACCESS; + + if (prot & PROT_READ) { + protect = PAGE_READONLY; + allocation_type = MEM_COMMIT; + } + if (prot & PROT_WRITE) { + // Windows does not provide write only mode privileges + // are escalated to read/write. + protect = PAGE_READWRITE; + allocation_type = MEM_COMMIT; + } + + void* p = VirtualAllocFromApp(NULL, len, allocation_type, protect); + if (!p) { + return MAP_FAILED; + } + return p; +} + +int munmap(void* addr, size_t len) { + if (VirtualFree(addr, len, MEM_DECOMMIT)) { + return 0; + } + return -1; +} + +int msync(void* addr, size_t len, int flags) { + // TODO: Enable the following implementation when xb1 can compile it. + // FlushInstructionCache(GetCurrentProcess(), virtual_address, size_bytes); + return 0; +} + +int mprotect(void* addr, size_t len, int prot) { + ULONG new_protection = 0; + + if (prot == PROT_NONE) { + // After this call, the address will be in reserved state. + if (VirtualFree(addr, len, MEM_DECOMMIT)) { + return 0; + } + return -1; + } + + if (prot == PROT_READ) { + new_protection = PAGE_READONLY; + } else if (prot | PROT_WRITE) { + // Windows does not provide write only mode privileges + // are escalated to read/write. + new_protection = PAGE_READWRITE; + } + +#if SB_CAN(MAP_EXECUTABLE_MEMORY) + if (prot == PROT_EXEC) { + new_protection = PAGE_EXECUTE; + } else if (prot == (PROT_READ | PROT_EXEC)) { + new_protection = PAGE_EXECUTE_READ; + } +#endif + + ULONG old_protection; + // Changing protection from No-Access to others needs the memory to be + // committed first. Commit committed pages will not reset them to zero. + VirtualAllocFromApp(addr, len, MEM_COMMIT, PAGE_READONLY); + bool res = VirtualProtectFromApp(addr, len, new_protection, &old_protection); + if (res) { + return 0; + } + return -1; +} + +#ifdef __cplusplus +} +#endif diff --git a/starboard/tools/api_leak_detector/api_leak_detector.py b/starboard/tools/api_leak_detector/api_leak_detector.py index c1a558cc2043..a38869d9b5cc 100755 --- a/starboard/tools/api_leak_detector/api_leak_detector.py +++ b/starboard/tools/api_leak_detector/api_leak_detector.py @@ -97,6 +97,10 @@ 'strcasecmp', 'strncasecmp', 'time', + 'mmap', + 'munmap', + 'mprotect', + 'msync', ] diff --git a/starboard/win/shared/BUILD.gn b/starboard/win/shared/BUILD.gn index 97376937da70..45d12d709d25 100644 --- a/starboard/win/shared/BUILD.gn +++ b/starboard/win/shared/BUILD.gn @@ -233,6 +233,7 @@ static_library("starboard_platform") { "//starboard/shared/win32/mutex_destroy.cc", "//starboard/shared/win32/mutex_release.cc", "//starboard/shared/win32/once.cc", + "//starboard/shared/win32/posix_emu/mman.cc", "//starboard/shared/win32/posix_emu/posix_memalign.cc", "//starboard/shared/win32/posix_emu/time.cc", "//starboard/shared/win32/set_non_blocking_internal.cc", diff --git a/starboard/win/shared/platform_configuration/BUILD.gn b/starboard/win/shared/platform_configuration/BUILD.gn index 67563056a00a..b3b4e47a5fbf 100644 --- a/starboard/win/shared/platform_configuration/BUILD.gn +++ b/starboard/win/shared/platform_configuration/BUILD.gn @@ -42,9 +42,10 @@ config("platform_configuration") { ] cflags = [ - # Add POSIX emulation headers (note: sys/time.h cannot be force included) - "/FI ../../starboard/shared/win32/posix_emu/include/stdlib.h", - "/FI ../../starboard/shared/win32/posix_emu/include/time.h", + # Force include in every module + "/FI ../../starboard/shared/win32/posix_emu/include/posix_force_include.h", + + # Add POSIX emulation headers "/I../../starboard/shared/win32/posix_emu/include", ] diff --git a/third_party/icu/source/common/umapfile.cpp b/third_party/icu/source/common/umapfile.cpp index c084c8d7c060..cb8256d6d90b 100644 --- a/third_party/icu/source/common/umapfile.cpp +++ b/third_party/icu/source/common/umapfile.cpp @@ -102,6 +102,7 @@ typedef HANDLE MemoryMap; #elif MAP_IMPLEMENTATION==MAP_STARBOARD # include "starboard/file.h" # include "cmemory.h" +# include typedef void *MemoryMap; @@ -430,7 +431,7 @@ typedef HANDLE MemoryMap; uprv_free(pData->map); } else { size_t dataLen = (char *)pData->map - (char *)pData->mapAddr; - SbMemoryUnmap(pData->mapAddr, dataLen); + munmap(pData->mapAddr, dataLen); } pData->map = NULL; pData->mapAddr = NULL; diff --git a/third_party/musl/BUILD.gn b/third_party/musl/BUILD.gn index 6c4dd26842ba..84a48d175b06 100644 --- a/third_party/musl/BUILD.gn +++ b/third_party/musl/BUILD.gn @@ -380,6 +380,7 @@ static_library("c_internal") { "src/starboard/locale/uselocale.c", "src/starboard/malloc/malloc.c", "src/starboard/malloc/posix_memalign.c", + "src/starboard/mman/mman.c", "src/starboard/stdio/fflush.c", "src/starboard/stdio/fputc.c", "src/starboard/stdio/stderr.c", diff --git a/third_party/musl/src/starboard/mman/mman.c b/third_party/musl/src/starboard/mman/mman.c new file mode 100644 index 000000000000..c6e7dae152d5 --- /dev/null +++ b/third_party/musl/src/starboard/mman/mman.c @@ -0,0 +1,61 @@ +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if SB_API_VERSION < 16 +#include "starboard/memory.h" + +static SbMemoryMapFlags ToSbMemoryMapFlags(int prot) { + SbMemoryMapFlags sb_prot = kSbMemoryMapProtectReserved; + if (prot & PROT_READ) { + sb_prot |= kSbMemoryMapProtectRead; + } + if (prot & PROT_WRITE) { + sb_prot |= kSbMemoryMapProtectWrite; + } +#if SB_CAN(MAP_EXECUTABLE_MEMORY) + if (prot & PROT_EXEC) { + sb_prot |= kSbMemoryMapProtectExec; + } +#endif + + return sb_prot; +} + +void *mmap (void* addr, size_t len, int prot, int flags, int fd, off_t off) { + if (addr != NULL) { + return MAP_FAILED; + } + if (fd != -1) { + return MAP_FAILED; + } + void*p = SbMemoryMap(len , ToSbMemoryMapFlags(prot), "musl allocation"); + if (!p) { + return MAP_FAILED; + } + return p; +} + +int munmap (void* addr, size_t len) { + if (SbMemoryUnmap(addr, len)) { + return 0; + } + return -1; +} + +int mprotect (void* addr, size_t len, int prot) { + if (SbMemoryProtect(addr, len, ToSbMemoryMapFlags(prot))) { + return 0; + } + return -1; +} + +int msync (void * addr, size_t len, int flags) { + SbMemoryFlush(addr, len); + return 0; +} + +#endif // SB_API_VERSION < 16 diff --git a/third_party/v8/src/base/platform/platform-starboard.cc b/third_party/v8/src/base/platform/platform-starboard.cc index 37ecba21eec9..5b2eab34430b 100644 --- a/third_party/v8/src/base/platform/platform-starboard.cc +++ b/third_party/v8/src/base/platform/platform-starboard.cc @@ -18,10 +18,11 @@ #include "starboard/common/string.h" #include "starboard/configuration.h" #include "starboard/configuration_constants.h" -#include "starboard/memory.h" #include "starboard/time.h" #include "starboard/time_zone.h" +#include "sys/mman.h" + namespace v8 { namespace base { @@ -123,13 +124,13 @@ void OS::SetRandomMmapSeed(int64_t seed) { SB_NOTIMPLEMENTED(); } void* OS::GetRandomMmapAddr() { return nullptr; } void* Allocate(void* address, size_t size, OS::MemoryPermission access) { - SbMemoryMapFlags sb_flags; + int prot_flags; switch (access) { case OS::MemoryPermission::kNoAccess: - sb_flags = SbMemoryMapFlags(0); + prot_flags = PROT_NONE; break; case OS::MemoryPermission::kReadWrite: - sb_flags = SbMemoryMapFlags(kSbMemoryMapProtectReadWrite); + prot_flags = PROT_READ | PROT_WRITE; break; default: SB_LOG(ERROR) << "The requested memory allocation access is not" @@ -137,8 +138,8 @@ void* Allocate(void* address, size_t size, OS::MemoryPermission access) { << static_cast(access); return nullptr; } - void* result = SbMemoryMap(size, sb_flags, "v8::Base::Allocate"); - if (result == SB_MEMORY_MAP_FAILED) { + void* result = mmap(nullptr, size, prot_flags, MAP_PRIVATE | MAP_ANON, -1, 0); + if (result == MAP_FAILED) { return nullptr; } return result; @@ -181,38 +182,36 @@ void* OS::Allocate(void* address, size_t size, size_t alignment, // static bool OS::Free(void* address, const size_t size) { - return SbMemoryUnmap(address, size); + return munmap(address, size) == 0; } // static bool OS::Release(void* address, size_t size) { - return SbMemoryUnmap(address, size); + return munmap(address, size) == 0; } // static bool OS::SetPermissions(void* address, size_t size, MemoryPermission access) { - SbMemoryMapFlags new_protection; + int new_protection; switch (access) { case OS::MemoryPermission::kNoAccess: - new_protection = SbMemoryMapFlags(0); + new_protection = PROT_NONE; break; case OS::MemoryPermission::kRead: - new_protection = SbMemoryMapFlags(kSbMemoryMapProtectRead); + new_protection = PROT_READ; case OS::MemoryPermission::kReadWrite: - new_protection = SbMemoryMapFlags(kSbMemoryMapProtectReadWrite); + new_protection = PROT_READ | PROT_WRITE; break; case OS::MemoryPermission::kReadExecute: #if SB_CAN(MAP_EXECUTABLE_MEMORY) - new_protection = - SbMemoryMapFlags(kSbMemoryMapProtectRead | kSbMemoryMapProtectExec); + new_protection = PROT_READ | PROT_EXEC; #else UNREACHABLE(); #endif break; case OS::MemoryPermission::kReadWriteExecute: #if SB_CAN(MAP_EXECUTABLE_MEMORY) - new_protection = - SbMemoryMapFlags(kSbMemoryMapProtectRead | kSbMemoryMapProtectWrite| kSbMemoryMapProtectExec); + new_protection = PROT_READ| PROT_WRITE| PROT_EXEC; #else UNREACHABLE(); #endif @@ -222,7 +221,7 @@ bool OS::SetPermissions(void* address, size_t size, MemoryPermission access) { // All other types are not supported by Starboard. return false; } - return SbMemoryProtect(address, size, new_protection); + return mprotect(address, size, new_protection) == 0; } // static