Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions base/allocator/dispatcher/tls.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

#include <sys/mman.h>

#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_LINUX)
#if BUILDFLAG(IS_ANDROID) || (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_STARBOARD))
#include <sys/prctl.h>
#endif

Expand All @@ -22,7 +22,7 @@ namespace base::allocator::dispatcher::internal {
void* MMapAllocator::AllocateMemory(size_t size_in_bytes) {
void* const mmap_res = mmap(nullptr, size_in_bytes, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_LINUX)
#if BUILDFLAG(IS_ANDROID) || (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_STARBOARD))
#if defined(PR_SET_VMA) && defined(PR_SET_VMA_ANON_NAME)
if (mmap_res != MAP_FAILED) {
// Allow the anonymous memory region allocated by mmap(MAP_ANONYMOUS) to
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
#include <Security/Security.h>
#include <mach/mach.h>
#endif
#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_LINUX)
#if BUILDFLAG(IS_ANDROID) || (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_STARBOARD))
#include <sys/prctl.h>
#endif
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
Expand All @@ -62,7 +62,7 @@ namespace partition_alloc::internal {

namespace {

#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_LINUX)
#if BUILDFLAG(IS_ANDROID) || (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_STARBOARD))
#if defined(PR_SET_VMA) && defined(PR_SET_VMA_ANON_NAME)
const char* PageTagToName(PageTag tag) {
// Important: All the names should be string literals. As per prctl.h in
Expand All @@ -86,7 +86,7 @@ const char* PageTagToName(PageTag tag) {
}
}
#endif
#endif // BUILDFLAG(IS_ANDROID)
#endif // BUILDFLAG(IS_ANDROID) || (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_STARBOARD))

#if BUILDFLAG(IS_MAC)
// Tests whether the version of macOS supports the MAP_JIT flag and if the
Expand Down Expand Up @@ -197,7 +197,7 @@ uintptr_t SystemAllocPagesInternal(uintptr_t hint,
ret = nullptr;
}

#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_LINUX)
#if BUILDFLAG(IS_ANDROID) || (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_STARBOARD))
#if defined(PR_SET_VMA) && defined(PR_SET_VMA_ANON_NAME)
// On Android and Linux, anonymous mappings can have a name attached to them.
// This is useful for debugging, and double-checking memory attribution.
Expand Down
4 changes: 2 additions & 2 deletions base/memory/madv_free_discardable_memory_posix.cc
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
#include "base/tracing_buildflags.h"
#include "build/build_config.h"

#if BUILDFLAG(IS_ANDROID)
#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_STARBOARD)
#include <sys/prctl.h>
#endif

Expand All @@ -47,7 +47,7 @@ void* AllocatePages(size_t size_in_pages) {
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
PCHECK(data != MAP_FAILED);

#if BUILDFLAG(IS_ANDROID)
#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_STARBOARD)
prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, data, length,
"madv-free-discardable");
#endif
Expand Down
4 changes: 2 additions & 2 deletions base/metrics/persistent_memory_allocator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
#include <winbase.h>
#elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
#include <sys/mman.h>
#if BUILDFLAG(IS_ANDROID)
#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_STARBOARD)
#include <sys/prctl.h>
#endif
#endif
Expand Down Expand Up @@ -992,7 +992,7 @@ LocalPersistentMemoryAllocator::AllocateLocalMemory(size_t size,
address = ::mmap(nullptr, size, PROT_READ | PROT_WRITE,
MAP_ANON | MAP_SHARED, -1, 0);
if (address != MAP_FAILED) {
#if BUILDFLAG(IS_ANDROID)
#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_STARBOARD)
// Allow the anonymous memory region allocated by mmap(MAP_ANON) to be
// identified in /proc/$PID/smaps. This helps improve visibility into
// Chrome's memory usage on Android.
Expand Down
3 changes: 3 additions & 0 deletions starboard/elf_loader/exported_symbols.cc
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
#include "starboard/shared/modular/starboard_layer_posix_mmap_abi_wrappers.h"
#include "starboard/shared/modular/starboard_layer_posix_pipe2_abi_wrappers.h"
#include "starboard/shared/modular/starboard_layer_posix_poll_abi_wrappers.h"
#include "starboard/shared/modular/starboard_layer_posix_prctl_abi_wrappers.h"
#include "starboard/shared/modular/starboard_layer_posix_pthread_abi_wrappers.h"
#include "starboard/shared/modular/starboard_layer_posix_semaphore_abi_wrappers.h"
#include "starboard/shared/modular/starboard_layer_posix_signal_abi_wrappers.h"
Expand Down Expand Up @@ -230,6 +231,7 @@ ExportedSymbols::ExportedSymbols() {

// POSIX APIs
REGISTER_SYMBOL(aligned_alloc);
REGISTER_SYMBOL(atexit);
REGISTER_SYMBOL(calloc);
REGISTER_SYMBOL(close);
REGISTER_SYMBOL(fdatasync);
Expand Down Expand Up @@ -348,6 +350,7 @@ ExportedSymbols::ExportedSymbols() {
REGISTER_WRAPPER(pathconf);
REGISTER_WRAPPER(pipe2);
REGISTER_WRAPPER(poll);
REGISTER_WRAPPER(prctl);
REGISTER_WRAPPER(pthread_attr_init);
REGISTER_WRAPPER(pthread_attr_destroy);
REGISTER_WRAPPER(pthread_attr_getdetachstate);
Expand Down
1 change: 1 addition & 0 deletions starboard/nplb/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ test("nplb") {
"posix_compliance/posix_pipe_test.cc",
"posix_compliance/posix_poll_test.cc",
"posix_compliance/posix_posix_memory_allocate_aligned_test.cc",
"posix_compliance/posix_prctl_test.cc",
"posix_compliance/posix_process_test.cc",
"posix_compliance/posix_rand_r_test.cc",
"posix_compliance/posix_rand_test.cc",
Expand Down
153 changes: 153 additions & 0 deletions starboard/nplb/posix_compliance/posix_prctl_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
// Copyright 2025 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 "starboard/shared/modular/starboard_layer_posix_prctl_abi_wrappers.h"

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/prctl.h>
#include <unistd.h>

#include "starboard/common/log.h"
#include "testing/gtest/include/gtest/gtest.h"

// From third_party/musl/include/sys/prctl.h
#ifndef PR_SET_VMA
#define PR_SET_VMA 0x53564d41
#endif
#ifndef PR_SET_VMA_ANON_NAME
#define PR_SET_VMA_ANON_NAME 0
#endif

namespace {

const char kVmaName[] = "TestVmaName";

// Checks /proc/self/maps to see if the memory mapping containing |addr| has
// the specified |name|. This is the expected outcome when the kernel supports
// PR_SET_VMA_ANON_NAME.
bool VmaIsNamed(void* addr, const char* name) {
FILE* fp = fopen("/proc/self/maps", "r");
if (!fp) {
// If we can't open /proc/self/maps, we can't verify.
// Assume it's not named and let the fallback check proceed.
return false;
}

char line[1024];
bool found = false;
unsigned long target_addr = (unsigned long)addr;

while (fgets(line, sizeof(line), fp)) {
unsigned long start, end;
if (sscanf(line, "%lx-%lx", &start, &end) != 2) {
continue;
}
if (target_addr >= start && target_addr < end) {
if (strstr(line, name)) {
found = true;
}
// We found the mapping containing our address, so we can stop.
// If it's not named here, it's not named.
break;
}
}

fclose(fp);
return found;
}

// Checks for the existence and content of the fallback file. This is the
// expected outcome when the kernel does NOT support PR_SET_VMA_ANON_NAME.
bool FallbackFileIsCorrect(unsigned long start,
unsigned long size,
const char* name) {
char file_path[256];
snprintf(file_path, sizeof(file_path), "/tmp/cobalt_vma_tags_%d.txt",
getpid());

FILE* fp = fopen(file_path, "r");
if (!fp) {
return false;
}

char line[1024];
bool found = false;
while (fgets(line, sizeof(line), fp)) {
unsigned long file_start, file_end;
char file_name[256];
// The format is "0x%lx 0x%lx %s\n"
if (sscanf(line, "0x%lx 0x%lx %s", &file_start, &file_end, file_name) ==
3) {
if (file_start == start && file_end == start + size &&
strcmp(file_name, name) == 0) {
found = true;
break;
}
}
}

fclose(fp);
return found;
}

// This test verifies that __abi_wrap_prctl with PR_SET_VMA and
// PR_SET_VMA_ANON_NAME correctly names a VMA region, either by calling the
// underlying prctl syscall or by using the fallback mechanism of writing to a
// file.
TEST(PosixPrctlTest, SetVmaAnonName) {
const size_t kMapSize = 4096;
void* p = malloc(kMapSize);
ASSERT_NE(p, nullptr);

// Ensure we have a clean state by deleting any leftover fallback file.
char file_path[256];
snprintf(file_path, sizeof(file_path), "/tmp/cobalt_vma_tags_%d.txt",
getpid());
unlink(file_path);

int result =
__abi_wrap_prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, (unsigned long)p,
kMapSize, (unsigned long)kVmaName);

// The wrapper should return 0 on success, for both the prctl call and the
// fallback.
EXPECT_EQ(result, 0);

bool vma_is_named = VmaIsNamed(p, kVmaName);
bool fallback_file_is_correct =
FallbackFileIsCorrect((unsigned long)p, kMapSize, kVmaName);

// We expect one of the two mechanisms to have worked.
EXPECT_TRUE(vma_is_named || fallback_file_is_correct)
<< "VMA name was not set via prctl and fallback file was not created or "
"is incorrect.";

if (vma_is_named) {
SB_LOG(INFO) << "VMA naming with PR_SET_VMA_ANON_NAME is supported by the "
"kernel.";
}
if (fallback_file_is_correct) {
SB_LOG(INFO) << "VMA naming with PR_SET_VMA_ANON_NAME is NOT supported by "
"the kernel, fallback was used.";
}

free(p);
// Clean up the fallback file if it was created.
unlink(file_path);
}

} // namespace
4 changes: 4 additions & 0 deletions starboard/shared/modular/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ if ((sb_is_modular || sb_is_evergreen_compatible) &&
"starboard_layer_posix_pipe2_abi_wrappers.h",
"starboard_layer_posix_poll_abi_wrappers.cc",
"starboard_layer_posix_poll_abi_wrappers.h",
"starboard_layer_posix_prctl_abi_wrappers.cc",
"starboard_layer_posix_prctl_abi_wrappers.h",
"starboard_layer_posix_pthread_abi_wrappers.cc",
"starboard_layer_posix_pthread_abi_wrappers.h",
"starboard_layer_posix_semaphore_abi_wrappers.cc",
Expand Down Expand Up @@ -61,6 +63,7 @@ if ((sb_is_modular || sb_is_evergreen_compatible) &&

deps = [
"//starboard:starboard_headers_only",
"//starboard/common",
"//starboard/common:common_headers_only",
]
}
Expand All @@ -78,6 +81,7 @@ if (is_cobalt_hermetic_build && !sb_is_evergreen &&
"cobalt_layer_posix_mmap_abi_wrappers.cc",
"cobalt_layer_posix_pipe2_abi_wrappers.cc",
"cobalt_layer_posix_poll_abi_wrappers.cc",
"cobalt_layer_posix_prctl_abi_wrappers.cc",
"cobalt_layer_posix_pthread_abi_wrappers.cc",
"cobalt_layer_posix_semaphore_abi_wrappers.cc",
"cobalt_layer_posix_signal_abi_wrappers.cc",
Expand Down
37 changes: 37 additions & 0 deletions starboard/shared/modular/cobalt_layer_posix_prctl_abi_wrappers.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright 2025 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 <stdarg.h>
#include <sys/prctl.h>

extern "C" {

int __abi_wrap_prctl(int option,
unsigned long arg2,
unsigned long arg3,
unsigned long arg4,
unsigned long arg5);

int prctl(int option, ...) {
va_list args;
va_start(args, option);
long arg2 = va_arg(args, long);
long arg3 = va_arg(args, long);
long arg4 = va_arg(args, long);
long arg5 = va_arg(args, long);
va_end(args);
return __abi_wrap_prctl(option, arg2, arg3, arg4, arg5);
}

} // extern "C"
Loading
Loading