Skip to content

Commit

Permalink
Refactor ABI wrappers to not rely on --wrap
Browse files Browse the repository at this point in the history
b/330648201
  • Loading branch information
gbournou committed Mar 25, 2024
1 parent 60884cb commit fd69425
Show file tree
Hide file tree
Showing 18 changed files with 535 additions and 319 deletions.
16 changes: 16 additions & 0 deletions starboard/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ group("default") {
}

group("starboard_group") {
deps = []
public_deps = [
":starboard_headers_only",
"//starboard/client_porting/cwrappers",
Expand All @@ -106,6 +107,21 @@ group("starboard_group") {
"//third_party/llvm-project/libcxxabi:cxxabi",
"//third_party/musl:c",
]

if (!sb_is_evergreen) {
# For modular builds, we need to wrap any POSIX APIs that may not be ABI
# equivalent across the Cobalt toolchain and the platform toolchain. For
# non-Evergreen builds, this is done via the below wrapper implementations
# of the API functions, which will simply call a renamed version of the
# function that will be implemented in the Starboard shared library. The
# same behavior is achieved in Evergreen via exported_symbols.cc remapping
# the functions to the same renamed version. In both cases, implementation
# of these renamed functions will handle translating data types across the
# ABI boundary and be compiled into the Starboard shared library in
# //starboard/build/config/starboard_target_type.gni.
deps += [ "//starboard/shared/modular:cobalt_layer_posix_abi_wrappers" ]
}

if (sb_is_evergreen) {
public_deps += [ "//starboard/elf_loader:sabi_string" ]
} else {
Expand Down
31 changes: 0 additions & 31 deletions starboard/build/config/modular/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -168,37 +168,6 @@ config("modular") {

defines += [ "THREAD_SANITIZER" ]
}

# Wrap underlying POSIX implementations to be cross-compatible with
# musl-based types that are used in modular builds. Evergreen builds use
# a different map-based wrapping of these POSIX APIs.
# Note that the corresponding implementations of these wrappers need to be
# compiled into the Starboard shared library, which is handled in
# //starboard/build/config/starboard_target_type.gni.
if (!sb_is_evergreen && current_toolchain == cobalt_toolchain) {
ldflags += [
"-Wl,--wrap=clock_gettime",
"-Wl,--wrap=gettimeofday",
"-Wl,--wrap=time",
"-Wl,--wrap=gmtime_r",
"-Wl,--wrap=mmap",
"-Wl,--wrap=pthread_mutex_destroy",
"-Wl,--wrap=pthread_mutex_init",
"-Wl,--wrap=pthread_mutex_lock",
"-Wl,--wrap=pthread_mutex_unlock",
"-Wl,--wrap=pthread_mutex_trylock",
"-Wl,--wrap=pthread_cond_broadcast",
"-Wl,--wrap=pthread_cond_destroy",
"-Wl,--wrap=pthread_cond_init",
"-Wl,--wrap=pthread_cond_signal",
"-Wl,--wrap=pthread_cond_timedwait",
"-Wl,--wrap=pthread_cond_wait",
"-Wl,--wrap=pthread_condattr_destroy",
"-Wl,--wrap=pthread_condattr_getclock",
"-Wl,--wrap=pthread_condattr_init",
"-Wl,--wrap=pthread_condattr_setclock",
]
}
}

config("speed") {
Expand Down
5 changes: 3 additions & 2 deletions starboard/build/config/starboard_target_type.gni
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,10 @@ template("starboard_platform_target") {
public_deps += [ "//$starboard_path:starboard_platform" ]
}
if (sb_is_modular) {
# For modular builds (including Evergreen), include POSIX wrappers that
# For modular builds (including Evergreen), include POSIX ABI wrappers that
# handle cross-compatibility with musl-based Cobalt code.
public_deps += [ "//starboard/shared/modular:posix_wrappers" ]
public_deps +=
[ "//starboard/shared/modular:starboard_layer_posix_abi_wrappers" ]
}
}
}
4 changes: 2 additions & 2 deletions starboard/elf_loader/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ static_library("elf_loader") {
":evergreen_info",
"//starboard:starboard_group",
"//starboard/common",
"//starboard/shared/modular:posix_wrappers",
"//starboard/shared/modular:starboard_layer_posix_abi_wrappers",
"//third_party/lz4_lib:lz4",
]
}
Expand All @@ -81,7 +81,7 @@ if (sb_is_evergreen_compatible && current_toolchain == starboard_toolchain) {
":evergreen_info",
"//starboard:starboard_group",
"//starboard/common",
"//starboard/shared/modular:posix_wrappers",
"//starboard/shared/modular:starboard_layer_posix_abi_wrappers",
"//third_party/crashpad/wrapper",
]
}
Expand Down
48 changes: 25 additions & 23 deletions starboard/elf_loader/exported_symbols.cc
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@
#include "starboard/once.h"
#include "starboard/player.h"
#if SB_API_VERSION >= 16
#include "starboard/shared/modular/posix_mmap_wrappers.h"
#include "starboard/shared/modular/posix_pthread_wrappers.h"
#include "starboard/shared/modular/posix_time_wrappers.h"
#include "starboard/shared/modular/starboard_layer_posix_mmap_abi_wrappers.h"
#include "starboard/shared/modular/starboard_layer_posix_pthread_abi_wrappers.h"
#include "starboard/shared/modular/starboard_layer_posix_time_abi_wrappers.h"
#endif // SB_API_VERSION >= 16
#include "starboard/socket.h"
#include "starboard/socket_waiter.h"
Expand Down Expand Up @@ -453,41 +453,43 @@ ExportedSymbols::ExportedSymbols() {
// Platform-specific types with musl-based types. These wrappers are defined
// in //starboard/shared/modular.
// TODO: b/316603042 - Detect via NPLB and only add the wrapper if needed.
map_["clock_gettime"] = reinterpret_cast<const void*>(&__wrap_clock_gettime);
map_["gettimeofday"] = reinterpret_cast<const void*>(&__wrap_gettimeofday);
map_["gmtime_r"] = reinterpret_cast<const void*>(&__wrap_gmtime_r);
map_["mmap"] = reinterpret_cast<const void*>(&__wrap_mmap);
map_["clock_gettime"] =
reinterpret_cast<const void*>(&__abi_wrap_clock_gettime);
map_["gettimeofday"] =
reinterpret_cast<const void*>(&__abi_wrap_gettimeofday);
map_["gmtime_r"] = reinterpret_cast<const void*>(&__abi_wrap_gmtime_r);
map_["mmap"] = reinterpret_cast<const void*>(&__abi_wrap_mmap);
map_["pthread_cond_broadcast"] =
reinterpret_cast<const void*>(&__wrap_pthread_cond_broadcast);
reinterpret_cast<const void*>(&__abi_wrap_pthread_cond_broadcast);
map_["pthread_cond_destroy"] =
reinterpret_cast<const void*>(&__wrap_pthread_cond_destroy);
reinterpret_cast<const void*>(&__abi_wrap_pthread_cond_destroy);
map_["pthread_cond_init"] =
reinterpret_cast<const void*>(&__wrap_pthread_cond_init);
reinterpret_cast<const void*>(&__abi_wrap_pthread_cond_init);
map_["pthread_cond_signal"] =
reinterpret_cast<const void*>(&__wrap_pthread_cond_signal);
reinterpret_cast<const void*>(&__abi_wrap_pthread_cond_signal);
map_["pthread_cond_timedwait"] =
reinterpret_cast<const void*>(&__wrap_pthread_cond_timedwait);
reinterpret_cast<const void*>(&__abi_wrap_pthread_cond_timedwait);
map_["pthread_cond_wait"] =
reinterpret_cast<const void*>(&__wrap_pthread_cond_wait);
reinterpret_cast<const void*>(&__abi_wrap_pthread_cond_wait);
map_["pthread_condattr_destroy"] =
reinterpret_cast<const void*>(&__wrap_pthread_condattr_destroy);
reinterpret_cast<const void*>(&__abi_wrap_pthread_condattr_destroy);
map_["pthread_condattr_getclock"] =
reinterpret_cast<const void*>(&__wrap_pthread_condattr_getclock);
reinterpret_cast<const void*>(&__abi_wrap_pthread_condattr_getclock);
map_["pthread_condattr_init"] =
reinterpret_cast<const void*>(&__wrap_pthread_condattr_init);
reinterpret_cast<const void*>(&__abi_wrap_pthread_condattr_init);
map_["pthread_condattr_setclock"] =
reinterpret_cast<const void*>(&__wrap_pthread_condattr_setclock);
reinterpret_cast<const void*>(&__abi_wrap_pthread_condattr_setclock);
map_["pthread_mutex_destroy"] =
reinterpret_cast<const void*>(&__wrap_pthread_mutex_destroy);
reinterpret_cast<const void*>(&__abi_wrap_pthread_mutex_destroy);
map_["pthread_mutex_init"] =
reinterpret_cast<const void*>(&__wrap_pthread_mutex_init);
reinterpret_cast<const void*>(&__abi_wrap_pthread_mutex_init);
map_["pthread_mutex_lock"] =
reinterpret_cast<const void*>(&__wrap_pthread_mutex_lock);
reinterpret_cast<const void*>(&__abi_wrap_pthread_mutex_lock);
map_["pthread_mutex_unlock"] =
reinterpret_cast<const void*>(&__wrap_pthread_mutex_unlock);
reinterpret_cast<const void*>(&__abi_wrap_pthread_mutex_unlock);
map_["pthread_mutex_trylock"] =
reinterpret_cast<const void*>(&__wrap_pthread_mutex_trylock);
map_["time"] = reinterpret_cast<const void*>(&__wrap_time);
reinterpret_cast<const void*>(&__abi_wrap_pthread_mutex_trylock);
map_["time"] = reinterpret_cast<const void*>(&__abi_wrap_time);

#if defined(_MSC_VER)
// MSVC provides a template with the same name.
Expand Down
25 changes: 18 additions & 7 deletions starboard/shared/modular/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,28 @@

# TODO: b/315170518 - Revert to static library after fixing
# symbol visibility issues for windows based modular platform builds.
source_set("posix_wrappers") {
source_set("starboard_layer_posix_abi_wrappers") {
sources = [
"posix_mmap_wrappers.cc",
"posix_mmap_wrappers.h",
"posix_pthread_wrappers.cc",
"posix_pthread_wrappers.h",
"posix_time_wrappers.cc",
"posix_time_wrappers.h",
"starboard_layer_posix_mmap_abi_wrappers.cc",
"starboard_layer_posix_mmap_abi_wrappers.h",
"starboard_layer_posix_pthread_abi_wrappers.cc",
"starboard_layer_posix_pthread_abi_wrappers.h",
"starboard_layer_posix_time_abi_wrappers.cc",
"starboard_layer_posix_time_abi_wrappers.h",
]

configs += [ "//starboard/build/config:starboard_implementation" ]

deps = [ "//starboard:starboard_headers_only" ]
}

if (sb_is_modular && !sb_is_evergreen &&
current_toolchain == cobalt_toolchain) {
source_set("cobalt_layer_posix_abi_wrappers") {
sources = [
"cobalt_layer_posix_mmap_abi_wrappers.cc",
"cobalt_layer_posix_pthread_abi_wrappers.cc",
"cobalt_layer_posix_time_abi_wrappers.cc",
]
}
}
52 changes: 52 additions & 0 deletions starboard/shared/modular/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Starboard Modular ABI Wrappers

This directory contains code that will handle translations of data types across
ABI boundaries.

These wrappers are used in modular builds (including Evergreen). They are needed
to handle dealing with differences in platform-specific toolchain types and
musl-based types. For example, the `struct timespec` and `struct timeval` types
may contain differently sized member fields and when the caller is Cobalt code
compiled with musl it will provide argument data that needs to be adjusted when
passed to platform-specific system libraries.

To do this adjustment across compilation toolchains, there are 2 sets of files
in this directory that will be compiled in either the Cobalt toolchain or the
Starboard plaform-specific toolchain:

* `cobalt_layer_posix_XYZ_abi_wrappers.cc` - these are compiled only in the
Cobalt toolchain for modular builds (excluding Evergreen). The logic in
these files simply defines the API we want to wrap and re-calls an external
function named `__abi_wrap_XYZ` using the exact same parameter and return
value types. This is simply to get the libcobalt.so to not link against
the glibc implementations and instead rely on an external implementation
that will be defined in libstarboard.so. Similar logic is done specifically
for Evergreen in exported_symbols.cc, since we have a custom ELF loader in
that case to handle remapping the functions.
* `starboard_layer_posix_XYZ_abi_wrappers.{h,cc}` - these are compiled only
in the Starboard platform-specific toolchain for modular builds (including
Evergreen). The header files define corresponding musl-compatible types
(copying definitions provided in //third_party/musl/include/alltypes.h.in)
for the cases where data types are not guaranteed to match across ABI
boundaries. These files then define the implementation of the
`__abi_wrap_XYZ` functions, which will be called from the Cobalt layer.
Since these functions are being implemented/compiled in the Starboard
layer, they will rely on the platform-specific toolchain to get the
platform-specific type definitions from the system headers (e.g. <time.h>).
The implementations will handle doing data type conversions across the
ABI boundary (both for parameters and return types).


To help illustrate how this works, we can use the POSIX function `clock_gettime`
as an example. When we build modularly, the following table shows how the
symbols would look using a tool like `nm`:

```
libstarboard.so:
U clock_gettime@GLIBC_2.17 (undefined reference to platform library)
T __abi_wrap_clock_gettime (concrete definition of ABI wrapper function)
libcobalt.so
U __abi_wrap_clock_gettime (undefined reference to the Starboard wrapper)
t clock_gettime (concrete definition that calls __abi_wrap_*)
```
33 changes: 33 additions & 0 deletions starboard/shared/modular/cobalt_layer_posix_mmap_abi_wrappers.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright 2024 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 <sys/mman.h>

extern "C" {

void* __abi_wrap_mmap(void* addr,
size_t len,
int prot,
int flags,
int fildes,
off_t off);

void* mmap(void* addr, size_t len, int prot, int flags, int fildes, off_t off) {
return __abi_wrap_mmap(addr, len, prot, flags, fildes, off);
}
}

#endif // SB_API_VERSION >= 16
Loading

0 comments on commit fd69425

Please sign in to comment.