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 "malloc_translation.h"
18
19 #include <malloc.h>
20 #include <stdio.h>
21
22 #include "berberis/guest_abi/function_wrappers.h"
23 #include "berberis/guest_abi/guest_params.h"
24 #include "berberis/guest_state/guest_state.h"
25
26 using MallocIterateCallback = void (*)(uintptr_t base, size_t size, void* arg);
27
28 // malloc_iterate is not declared in any public bionic headers.
29 extern "C" int malloc_iterate(uintptr_t base, size_t size,
30 MallocIterateCallback callback, void* arg);
31
32 namespace berberis {
33
34 // int native_bridge_malloc_info(int options, int fd);
DoCustomTrampoline_native_bridge_malloc_info_helper(HostCode,ProcessState * state)35 void DoCustomTrampoline_native_bridge_malloc_info_helper(HostCode /*callee*/,
36 ProcessState* state) {
37 // Note: we couldn't handle malloc_info here. It has the following prototype:
38 // int malloc_info(int options, FILE *stream);
39 // And it's really hard to deal with Guest type FILE on host.
40 // Instead we call fileno(stream) in guest code and pass fd to
41 // native_bridge_malloc_info.
42 using NativeBridgeMallocInfo = int (*)(int options, int fd);
43 auto [options, fd] = GuestParamsValues<NativeBridgeMallocInfo>(state);
44 FILE* fp = fdopen(dup(fd), "w"); // fdopen "w" doesn't truncate fd!
45 CHECK(fp);
46 auto&& [ret] = GuestReturnReference<NativeBridgeMallocInfo>(state);
47 ret = malloc_info(options, fp);
48 fclose(fp);
49 }
50
51 // struct mallinfo mallinfo(void);
52 // Using custom trampoline to handle struct return type.
DoCustomTrampoline_native_bridge_mallinfo(HostCode,ProcessState * state)53 void DoCustomTrampoline_native_bridge_mallinfo(HostCode /* callee */,
54 ProcessState* state) {
55 auto&& [ret] = GuestReturnReference<decltype(mallinfo)>(state);
56 ret = mallinfo();
57 }
58
59 // Using custom trampoline to handle callback.
DoCustomTrampoline_native_bridge_malloc_iterate(HostCode,ProcessState * state)60 void DoCustomTrampoline_native_bridge_malloc_iterate(HostCode /* callee */,
61 ProcessState* state) {
62 auto [base, size, guest_callback, arg] =
63 GuestParamsValues<decltype(malloc_iterate)>(state);
64 auto callback = WrapGuestFunction(guest_callback, "MallocIterateCallback");
65 auto&& [ret] = GuestReturnReference<decltype(malloc_iterate)>(state);
66 ret = malloc_iterate(base, size, callback, arg);
67 }
68
69 } // namespace berberis
70