blob: 0e4a0996b88d0e3d4beebff92b3780f9047e0e31 [file] [log] [blame]
/*
* Copyright (C) 2018 The Android Open Source Project
*
* 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 <unistd.h>
#include "native_bridge_support/vdso/vdso.h"
extern "C" void __loader_add_thread_local_dtor(void* dso_handle) __attribute__((weak));
extern "C" void __loader_remove_thread_local_dtor(void* dso_handle) __attribute__((weak));
struct WrappedArg {
typedef void (*thread_atexit_fn_t)(void*);
thread_atexit_fn_t fn;
void* arg;
void* dso_handle;
};
static void WrappedFn(void* arg) {
WrappedArg* wrapped_arg = static_cast<WrappedArg*>(arg);
WrappedArg::thread_atexit_fn_t origin_fn = wrapped_arg->fn;
void* origin_arg = wrapped_arg->arg;
void* dso_handle = wrapped_arg->dso_handle;
delete wrapped_arg;
origin_fn(origin_arg);
if (__loader_remove_thread_local_dtor != nullptr) {
__loader_remove_thread_local_dtor(dso_handle);
}
}
extern "C" int __cxa_thread_atexit_impl(void (*func)(void*), void* arg, void* dso_handle) {
WrappedArg* wrapped_arg = new WrappedArg();
wrapped_arg->fn = func;
wrapped_arg->arg = arg;
wrapped_arg->dso_handle = dso_handle;
if (__loader_add_thread_local_dtor != nullptr) {
__loader_add_thread_local_dtor(dso_handle);
}
typedef decltype(__cxa_thread_atexit_impl)* fn_t;
static fn_t __host_cxa_thread_atexit_impl = reinterpret_cast<fn_t>(
native_bridge_find_proxy_library_symbol("libc.so", "__cxa_thread_atexit_impl"));
return __host_cxa_thread_atexit_impl(WrappedFn, wrapped_arg, dso_handle);
}