1 /*
2 * Copyright (C) 2023 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 
17 #include <android/file_descriptor_jni.h>
18 #include <jni.h>
19 
20 #include "berberis/base/logging.h"
21 #include "berberis/guest_abi/function_wrappers.h"
22 #include "berberis/guest_abi/guest_params.h"
23 #include "berberis/jni/jni_trampolines.h"
24 #include "berberis/proxy_loader/proxy_library_builder.h"
25 
26 namespace berberis {
27 
28 namespace {
29 
30 // jobject AFileDescriptor_create(JNIEnv* env);
DoCustomTrampoline_AFileDescriptor_create(HostCode,ProcessState * state)31 void DoCustomTrampoline_AFileDescriptor_create(HostCode /* callee */, ProcessState* state) {
32   auto [guest_env] = GuestParamsValues<decltype(AFileDescriptor_create)>(state);
33   auto&& [ret] = GuestReturnReference<decltype(AFileDescriptor_create)>(state);
34   ret = AFileDescriptor_create(ToHostJNIEnv(guest_env));
35 }
36 
37 // int AFileDescriptor_getFd(JNIEnv* env, jobject fileDescriptor);
DoCustomTrampoline_AFileDescriptor_getFd(HostCode,ProcessState * state)38 void DoCustomTrampoline_AFileDescriptor_getFd(HostCode /* callee */, ProcessState* state) {
39   auto [guest_env, fileDescriptor] = GuestParamsValues<decltype(AFileDescriptor_getFd)>(state);
40   auto&& [ret] = GuestReturnReference<decltype(AFileDescriptor_getFd)>(state);
41   ret = AFileDescriptor_getFd(ToHostJNIEnv(guest_env), fileDescriptor);
42 }
43 
44 // void AFileDescriptor_setFd(JNIEnv* env, jobject fileDescriptor, int fd);
DoCustomTrampoline_AFileDescriptor_setFd(HostCode,ProcessState * state)45 void DoCustomTrampoline_AFileDescriptor_setFd(HostCode /* callee */, ProcessState* state) {
46   auto [guest_env, fileDescriptor, fd] = GuestParamsValues<decltype(AFileDescriptor_setFd)>(state);
47   AFileDescriptor_setFd(ToHostJNIEnv(guest_env), fileDescriptor, fd);
48 }
49 
50 // jint JNI_CreateJavaVM(JavaVM**, JNIEnv**, void*);
DoCustomTrampoline_JNI_CreateJavaVM(HostCode,ProcessState * state)51 void DoCustomTrampoline_JNI_CreateJavaVM(HostCode /* callee */, ProcessState* state) {
52   auto [guest_vm, guest_env, init_info] = GuestParamsValues<decltype(JNI_CreateJavaVM)>(state);
53   auto&& [ret] = GuestReturnReference<decltype(JNI_CreateJavaVM)>(state);
54   JavaVM* host_vm;
55   JNIEnv* host_env;
56 
57   ret = JNI_CreateJavaVM(&host_vm, &host_env, init_info);
58   // Android only supports a single runtime, this is already running so no more
59   // can be created. Thus we don't need to convert the returned objects to guest.
60   CHECK(ret == JNI_ERR);
61 }
62 
63 // jint JNI_GetCreatedJavaVMs(JavaVM**, jsize, jsize*);
DoCustomTrampoline_JNI_GetCreatedJavaVMs(HostCode,ProcessState * state)64 void DoCustomTrampoline_JNI_GetCreatedJavaVMs(HostCode /* callee */, ProcessState* state) {
65   auto [guest_vm, input_size, output_size] =
66       GuestParamsValues<decltype(JNI_GetCreatedJavaVMs)>(state);
67   auto&& [ret] = GuestReturnReference<decltype(JNI_GetCreatedJavaVMs)>(state);
68 
69   // There could be only one VM in Android.
70   JavaVM* host_vm;
71   ret = JNI_GetCreatedJavaVMs(&host_vm, 1, output_size);
72 
73   if (ret == JNI_ERR) {
74     return;
75   }
76 
77   CHECK(*output_size == 1u);
78   *ToHostAddr<GuestType<JavaVM*>>(ToGuestAddr(guest_vm)) = ToGuestJavaVM(host_vm);
79 }
80 
81 #if defined(NATIVE_BRIDGE_GUEST_ARCH_ARM) && defined(__i386__)
82 
83 #include "trampolines_arm_to_x86-inl.h"  // generated file NOLINT [build/include]
84 
85 #elif defined(NATIVE_BRIDGE_GUEST_ARCH_ARM64) && defined(__x86_64__)
86 
87 #include "trampolines_arm64_to_x86_64-inl.h"  // generated file NOLINT [build/include]
88 
89 #elif defined(NATIVE_BRIDGE_GUEST_ARCH_RISCV64) && defined(__x86_64__)
90 
91 #include "trampolines_riscv64_to_x86_64-inl.h"  // generated file NOLINT [build/include]
92 
93 #else
94 
95 #error "Unknown guest/host arch combination"
96 
97 #endif
98 
99 DEFINE_INIT_PROXY_LIBRARY("libnativehelper.so")
100 
101 }  // namespace
102 
103 }  // namespace berberis
104