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