dlfcn.cpp revision 06016f226efe7aff2736643cb8e719c513948ecc
13b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes/*
23b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes * Copyright (C) 2007 The Android Open Source Project
3bcc4da9b752f0def46d63ed7b31f3f49cc2435adDimitry Ivanov * All rights reserved.
43b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes *
5bcc4da9b752f0def46d63ed7b31f3f49cc2435adDimitry Ivanov * Redistribution and use in source and binary forms, with or without
6bcc4da9b752f0def46d63ed7b31f3f49cc2435adDimitry Ivanov * modification, are permitted provided that the following conditions
7bcc4da9b752f0def46d63ed7b31f3f49cc2435adDimitry Ivanov * are met:
8bcc4da9b752f0def46d63ed7b31f3f49cc2435adDimitry Ivanov *  * Redistributions of source code must retain the above copyright
9bcc4da9b752f0def46d63ed7b31f3f49cc2435adDimitry Ivanov *    notice, this list of conditions and the following disclaimer.
10bcc4da9b752f0def46d63ed7b31f3f49cc2435adDimitry Ivanov *  * Redistributions in binary form must reproduce the above copyright
11bcc4da9b752f0def46d63ed7b31f3f49cc2435adDimitry Ivanov *    notice, this list of conditions and the following disclaimer in
12bcc4da9b752f0def46d63ed7b31f3f49cc2435adDimitry Ivanov *    the documentation and/or other materials provided with the
13bcc4da9b752f0def46d63ed7b31f3f49cc2435adDimitry Ivanov *    distribution.
143b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes *
15bcc4da9b752f0def46d63ed7b31f3f49cc2435adDimitry Ivanov * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16bcc4da9b752f0def46d63ed7b31f3f49cc2435adDimitry Ivanov * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17bcc4da9b752f0def46d63ed7b31f3f49cc2435adDimitry Ivanov * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18bcc4da9b752f0def46d63ed7b31f3f49cc2435adDimitry Ivanov * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19bcc4da9b752f0def46d63ed7b31f3f49cc2435adDimitry Ivanov * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20bcc4da9b752f0def46d63ed7b31f3f49cc2435adDimitry Ivanov * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21bcc4da9b752f0def46d63ed7b31f3f49cc2435adDimitry Ivanov * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22bcc4da9b752f0def46d63ed7b31f3f49cc2435adDimitry Ivanov * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23bcc4da9b752f0def46d63ed7b31f3f49cc2435adDimitry Ivanov * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24bcc4da9b752f0def46d63ed7b31f3f49cc2435adDimitry Ivanov * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25bcc4da9b752f0def46d63ed7b31f3f49cc2435adDimitry Ivanov * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26bcc4da9b752f0def46d63ed7b31f3f49cc2435adDimitry Ivanov * SUCH DAMAGE.
273b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes */
283b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes
295419b9474753d25dff947c7740532f86d130c0beElliott Hughes#include "linker.h"
300a3637d3eb2424d8e825ad1825f843450a888406Evgenii Stepanov#include "linker_cfi.h"
3148ec288d40d272e6fe5e68c4c0a9778b55e24f8aDimitry Ivanov#include "linker_globals.h"
32769b33fadf45a039741f932672ac2c4f901d7d4aDimitry Ivanov#include "linker_dlwarning.h"
335419b9474753d25dff947c7740532f86d130c0beElliott Hughes
343b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes#include <pthread.h>
353b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes#include <stdio.h>
365419b9474753d25dff947c7740532f86d130c0beElliott Hughes#include <stdlib.h>
3705fc1d7050d5451aea08dc5f504d2670287b2d43Elliott Hughes#include <string.h>
381913352c6b3501893dfb45189754970f9dc6e7bbDmitriy Ivanov#include <android/api-level.h>
393b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes
405419b9474753d25dff947c7740532f86d130c0beElliott Hughes#include <bionic/pthread_internal.h>
41eb847bc8666842a3cfc9c06e8458ad1abebebaf0Elliott Hughes#include "private/bionic_tls.h"
42eb847bc8666842a3cfc9c06e8458ad1abebebaf0Elliott Hughes#include "private/ScopedPthreadMutexLocker.h"
433b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes
447abea57ba599b9b114031ae33699b5d7fba8cc97dimitry#define __LINKER_PUBLIC__ __attribute__((visibility("default")))
457abea57ba599b9b114031ae33699b5d7fba8cc97dimitry
467abea57ba599b9b114031ae33699b5d7fba8cc97dimitryextern "C" {
477abea57ba599b9b114031ae33699b5d7fba8cc97dimitry
487abea57ba599b9b114031ae33699b5d7fba8cc97dimitryandroid_namespace_t* __loader_android_create_namespace(const char* name,
497abea57ba599b9b114031ae33699b5d7fba8cc97dimitry                                                       const char* ld_library_path,
507abea57ba599b9b114031ae33699b5d7fba8cc97dimitry                                                       const char* default_library_path,
517abea57ba599b9b114031ae33699b5d7fba8cc97dimitry                                                       uint64_t type,
527abea57ba599b9b114031ae33699b5d7fba8cc97dimitry                                                       const char* permitted_when_isolated_path,
537abea57ba599b9b114031ae33699b5d7fba8cc97dimitry                                                       android_namespace_t* parent_namespace,
547abea57ba599b9b114031ae33699b5d7fba8cc97dimitry                                                       const void* caller_addr) __LINKER_PUBLIC__;
557abea57ba599b9b114031ae33699b5d7fba8cc97dimitryvoid* __loader_android_dlopen_ext(const char* filename,
567abea57ba599b9b114031ae33699b5d7fba8cc97dimitry                           int flags,
577abea57ba599b9b114031ae33699b5d7fba8cc97dimitry                           const android_dlextinfo* extinfo,
587abea57ba599b9b114031ae33699b5d7fba8cc97dimitry                           const void* caller_addr) __LINKER_PUBLIC__;
597abea57ba599b9b114031ae33699b5d7fba8cc97dimitryvoid __loader_android_dlwarning(void* obj, void (*f)(void*, const char*)) __LINKER_PUBLIC__;
607abea57ba599b9b114031ae33699b5d7fba8cc97dimitryuint32_t __loader_android_get_application_target_sdk_version() __LINKER_PUBLIC__;
617abea57ba599b9b114031ae33699b5d7fba8cc97dimitryvoid __loader_android_get_LD_LIBRARY_PATH(char* buffer, size_t buffer_size) __LINKER_PUBLIC__;
627abea57ba599b9b114031ae33699b5d7fba8cc97dimitryandroid_namespace_t* __loader_android_get_exported_namespace(const char* name) __LINKER_PUBLIC__;
637abea57ba599b9b114031ae33699b5d7fba8cc97dimitrybool __loader_android_init_anonymous_namespace(const char* shared_libs_sonames,
647abea57ba599b9b114031ae33699b5d7fba8cc97dimitry                                               const char* library_search_path) __LINKER_PUBLIC__;
657abea57ba599b9b114031ae33699b5d7fba8cc97dimitrybool __loader_android_link_namespaces(android_namespace_t* namespace_from,
667abea57ba599b9b114031ae33699b5d7fba8cc97dimitry                                      android_namespace_t* namespace_to,
677abea57ba599b9b114031ae33699b5d7fba8cc97dimitry                                      const char* shared_libs_sonames) __LINKER_PUBLIC__;
687abea57ba599b9b114031ae33699b5d7fba8cc97dimitryvoid __loader_android_set_application_target_sdk_version(uint32_t target) __LINKER_PUBLIC__;
697abea57ba599b9b114031ae33699b5d7fba8cc97dimitryvoid __loader_android_update_LD_LIBRARY_PATH(const char* ld_library_path) __LINKER_PUBLIC__;
707abea57ba599b9b114031ae33699b5d7fba8cc97dimitryvoid __loader_cfi_fail(uint64_t CallSiteTypeId,
717abea57ba599b9b114031ae33699b5d7fba8cc97dimitry                       void* Ptr,
727abea57ba599b9b114031ae33699b5d7fba8cc97dimitry                       void *DiagData,
737abea57ba599b9b114031ae33699b5d7fba8cc97dimitry                       void *CallerPc) __LINKER_PUBLIC__;
747abea57ba599b9b114031ae33699b5d7fba8cc97dimitryint __loader_dl_iterate_phdr(int (*cb)(dl_phdr_info* info, size_t size, void* data),
757abea57ba599b9b114031ae33699b5d7fba8cc97dimitry                             void* data) __LINKER_PUBLIC__;
767abea57ba599b9b114031ae33699b5d7fba8cc97dimitryint __loader_dladdr(const void* addr, Dl_info* info) __LINKER_PUBLIC__;
777abea57ba599b9b114031ae33699b5d7fba8cc97dimitryint __loader_dlclose(void* handle) __LINKER_PUBLIC__;
787abea57ba599b9b114031ae33699b5d7fba8cc97dimitrychar* __loader_dlerror() __LINKER_PUBLIC__;
797abea57ba599b9b114031ae33699b5d7fba8cc97dimitryvoid* __loader_dlopen(const char* filename, int flags, const void* caller_addr) __LINKER_PUBLIC__;
807abea57ba599b9b114031ae33699b5d7fba8cc97dimitryvoid* __loader_dlsym(void* handle, const char* symbol, const void* caller_addr) __LINKER_PUBLIC__;
817abea57ba599b9b114031ae33699b5d7fba8cc97dimitryvoid* __loader_dlvsym(void* handle,
827abea57ba599b9b114031ae33699b5d7fba8cc97dimitry                      const char* symbol,
837abea57ba599b9b114031ae33699b5d7fba8cc97dimitry                      const char* version,
847abea57ba599b9b114031ae33699b5d7fba8cc97dimitry                      const void* caller_addr) __LINKER_PUBLIC__;
8506016f226efe7aff2736643cb8e719c513948eccdimitryvoid __loader_add_thread_local_dtor(void* dso_handle) __LINKER_PUBLIC__;
8606016f226efe7aff2736643cb8e719c513948eccdimitryvoid __loader_remove_thread_local_dtor(void* dso_handle) __LINKER_PUBLIC__;
877abea57ba599b9b114031ae33699b5d7fba8cc97dimitry#if defined(__arm__)
887abea57ba599b9b114031ae33699b5d7fba8cc97dimitry_Unwind_Ptr __loader_dl_unwind_find_exidx(_Unwind_Ptr pc, int* pcount) __LINKER_PUBLIC__;
897abea57ba599b9b114031ae33699b5d7fba8cc97dimitry#endif
907abea57ba599b9b114031ae33699b5d7fba8cc97dimitry}
917abea57ba599b9b114031ae33699b5d7fba8cc97dimitry
92212e0e38248860b151b28877225629a988d95b58Elliott Hughesstatic pthread_mutex_t g_dl_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
933b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes
945e071a18ce88d93fcffaebb9e0f62524ae504908Elliott Hughesstatic char* __bionic_set_dlerror(char* new_value) {
952a0b873065edb304fa2d1c54f8de663ea638b8abElliott Hughes  char** dlerror_slot = &reinterpret_cast<char**>(__get_tls())[TLS_SLOT_DLERROR];
963b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes
975e071a18ce88d93fcffaebb9e0f62524ae504908Elliott Hughes  char* old_value = *dlerror_slot;
985419b9474753d25dff947c7740532f86d130c0beElliott Hughes  *dlerror_slot = new_value;
99295082b3af2042e52ce44aa75c90755ac97bc4aaElliott Hughes  if (new_value != nullptr) LD_LOG(kLogErrors, "dlerror set to \"%s\"", new_value);
1005419b9474753d25dff947c7740532f86d130c0beElliott Hughes  return old_value;
1015419b9474753d25dff947c7740532f86d130c0beElliott Hughes}
1023b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes
1035419b9474753d25dff947c7740532f86d130c0beElliott Hughesstatic void __bionic_format_dlerror(const char* msg, const char* detail) {
1045419b9474753d25dff947c7740532f86d130c0beElliott Hughes  char* buffer = __get_thread()->dlerror_buffer;
1055419b9474753d25dff947c7740532f86d130c0beElliott Hughes  strlcpy(buffer, msg, __BIONIC_DLERROR_BUFFER_SIZE);
106851135bf9941b3813adb9b4f43d76e040c4ba157Dmitriy Ivanov  if (detail != nullptr) {
1075419b9474753d25dff947c7740532f86d130c0beElliott Hughes    strlcat(buffer, ": ", __BIONIC_DLERROR_BUFFER_SIZE);
1085419b9474753d25dff947c7740532f86d130c0beElliott Hughes    strlcat(buffer, detail, __BIONIC_DLERROR_BUFFER_SIZE);
1093b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes  }
1105419b9474753d25dff947c7740532f86d130c0beElliott Hughes
1115419b9474753d25dff947c7740532f86d130c0beElliott Hughes  __bionic_set_dlerror(buffer);
1125419b9474753d25dff947c7740532f86d130c0beElliott Hughes}
1135419b9474753d25dff947c7740532f86d130c0beElliott Hughes
1147abea57ba599b9b114031ae33699b5d7fba8cc97dimitrychar* __loader_dlerror() {
1155e071a18ce88d93fcffaebb9e0f62524ae504908Elliott Hughes  char* old_value = __bionic_set_dlerror(nullptr);
1165419b9474753d25dff947c7740532f86d130c0beElliott Hughes  return old_value;
1173b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes}
1183b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes
1197abea57ba599b9b114031ae33699b5d7fba8cc97dimitryvoid __loader_android_get_LD_LIBRARY_PATH(char* buffer, size_t buffer_size) {
1201728b2396591853345507a063ed6075dfd251706Elliott Hughes  ScopedPthreadMutexLocker locker(&g_dl_mutex);
121a4aafd156068ee174012f28cd894dbecf0e4ab90Elliott Hughes  do_android_get_LD_LIBRARY_PATH(buffer, buffer_size);
122a4aafd156068ee174012f28cd894dbecf0e4ab90Elliott Hughes}
123a4aafd156068ee174012f28cd894dbecf0e4ab90Elliott Hughes
1247abea57ba599b9b114031ae33699b5d7fba8cc97dimitryvoid __loader_android_update_LD_LIBRARY_PATH(const char* ld_library_path) {
1251728b2396591853345507a063ed6075dfd251706Elliott Hughes  ScopedPthreadMutexLocker locker(&g_dl_mutex);
126cade4c36e7c9c62db3f476a0f9cfc329bac9acb7Elliott Hughes  do_android_update_LD_LIBRARY_PATH(ld_library_path);
127cade4c36e7c9c62db3f476a0f9cfc329bac9acb7Elliott Hughes}
128cade4c36e7c9c62db3f476a0f9cfc329bac9acb7Elliott Hughes
129d9e427cf41893377dcdd0650ba20ff7cf7d72209Dimitry Ivanovstatic void* dlopen_ext(const char* filename,
130d9e427cf41893377dcdd0650ba20ff7cf7d72209Dimitry Ivanov                        int flags,
131d9e427cf41893377dcdd0650ba20ff7cf7d72209Dimitry Ivanov                        const android_dlextinfo* extinfo,
132d9e427cf41893377dcdd0650ba20ff7cf7d72209Dimitry Ivanov                        const void* caller_addr) {
1331728b2396591853345507a063ed6075dfd251706Elliott Hughes  ScopedPthreadMutexLocker locker(&g_dl_mutex);
134b996d60493a2e501655f23523b31fe34a63edd5cDimitry Ivanov  g_linker_logger.ResetState();
135d88e1f350111b3dfd71c6492321f0503cb5540dbDimitry Ivanov  void* result = do_dlopen(filename, flags, extinfo, caller_addr);
136851135bf9941b3813adb9b4f43d76e040c4ba157Dmitriy Ivanov  if (result == nullptr) {
137650be4e584eeab3591b9e273bfd6d169eea60853Elliott Hughes    __bionic_format_dlerror("dlopen failed", linker_get_error_buffer());
138851135bf9941b3813adb9b4f43d76e040c4ba157Dmitriy Ivanov    return nullptr;
1393b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes  }
1403b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes  return result;
1413b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes}
1423b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes
1437abea57ba599b9b114031ae33699b5d7fba8cc97dimitryvoid* __loader_android_dlopen_ext(const char* filename,
144d9e427cf41893377dcdd0650ba20ff7cf7d72209Dimitry Ivanov                           int flags,
145d9e427cf41893377dcdd0650ba20ff7cf7d72209Dimitry Ivanov                           const android_dlextinfo* extinfo,
146d9e427cf41893377dcdd0650ba20ff7cf7d72209Dimitry Ivanov                           const void* caller_addr) {
147e5cfafe3446a33b0c77416061d598bf76d580ee0Dmitriy Ivanov  return dlopen_ext(filename, flags, extinfo, caller_addr);
148b648a8a57ee42533a5bf127225a252f73ca2cbbcDmitriy Ivanov}
149b648a8a57ee42533a5bf127225a252f73ca2cbbcDmitriy Ivanov
1507abea57ba599b9b114031ae33699b5d7fba8cc97dimitryvoid* __loader_dlopen(const char* filename, int flags, const void* caller_addr) {
151e5cfafe3446a33b0c77416061d598bf76d580ee0Dmitriy Ivanov  return dlopen_ext(filename, flags, nullptr, caller_addr);
152012cb4583a5f8564059142bb1900ea3a31e7cfa9Torne (Richard Coles)}
153012cb4583a5f8564059142bb1900ea3a31e7cfa9Torne (Richard Coles)
154d9e427cf41893377dcdd0650ba20ff7cf7d72209Dimitry Ivanovvoid* dlsym_impl(void* handle, const char* symbol, const char* version, const void* caller_addr) {
1551728b2396591853345507a063ed6075dfd251706Elliott Hughes  ScopedPthreadMutexLocker locker(&g_dl_mutex);
156b996d60493a2e501655f23523b31fe34a63edd5cDimitry Ivanov  g_linker_logger.ResetState();
1574a2c5aa30ceea2aaf8dcaee2feb4879978af4fceDimitry Ivanov  void* result;
1589cf99cbad89c8495828788ce693a99ced434f66fDimitry Ivanov  if (!do_dlsym(handle, symbol, version, caller_addr, &result)) {
1594a2c5aa30ceea2aaf8dcaee2feb4879978af4fceDimitry Ivanov    __bionic_format_dlerror(linker_get_error_buffer(), nullptr);
160851135bf9941b3813adb9b4f43d76e040c4ba157Dmitriy Ivanov    return nullptr;
1613b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes  }
1623b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes
1634a2c5aa30ceea2aaf8dcaee2feb4879978af4fceDimitry Ivanov  return result;
1643b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes}
1653b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes
1667abea57ba599b9b114031ae33699b5d7fba8cc97dimitryvoid* __loader_dlsym(void* handle, const char* symbol, const void* caller_addr) {
1679cf99cbad89c8495828788ce693a99ced434f66fDimitry Ivanov  return dlsym_impl(handle, symbol, nullptr, caller_addr);
1689cf99cbad89c8495828788ce693a99ced434f66fDimitry Ivanov}
1699cf99cbad89c8495828788ce693a99ced434f66fDimitry Ivanov
1707abea57ba599b9b114031ae33699b5d7fba8cc97dimitryvoid* __loader_dlvsym(void* handle, const char* symbol, const char* version, const void* caller_addr) {
1719cf99cbad89c8495828788ce693a99ced434f66fDimitry Ivanov  return dlsym_impl(handle, symbol, version, caller_addr);
1729cf99cbad89c8495828788ce693a99ced434f66fDimitry Ivanov}
1739cf99cbad89c8495828788ce693a99ced434f66fDimitry Ivanov
1747abea57ba599b9b114031ae33699b5d7fba8cc97dimitryint __loader_dladdr(const void* addr, Dl_info* info) {
1751728b2396591853345507a063ed6075dfd251706Elliott Hughes  ScopedPthreadMutexLocker locker(&g_dl_mutex);
1764a2c5aa30ceea2aaf8dcaee2feb4879978af4fceDimitry Ivanov  return do_dladdr(addr, info);
1773b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes}
1783b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes
1797abea57ba599b9b114031ae33699b5d7fba8cc97dimitryint __loader_dlclose(void* handle) {
1801728b2396591853345507a063ed6075dfd251706Elliott Hughes  ScopedPthreadMutexLocker locker(&g_dl_mutex);
181d88e1f350111b3dfd71c6492321f0503cb5540dbDimitry Ivanov  int result = do_dlclose(handle);
182d88e1f350111b3dfd71c6492321f0503cb5540dbDimitry Ivanov  if (result != 0) {
183d88e1f350111b3dfd71c6492321f0503cb5540dbDimitry Ivanov    __bionic_format_dlerror("dlclose failed", linker_get_error_buffer());
184d88e1f350111b3dfd71c6492321f0503cb5540dbDimitry Ivanov  }
185d88e1f350111b3dfd71c6492321f0503cb5540dbDimitry Ivanov  return result;
1863b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes}
1873b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes
1887abea57ba599b9b114031ae33699b5d7fba8cc97dimitryint __loader_dl_iterate_phdr(int (*cb)(dl_phdr_info* info, size_t size, void* data), void* data) {
1897271caf93db6897cdbcfca169441045bb52de61bDmitriy Ivanov  ScopedPthreadMutexLocker locker(&g_dl_mutex);
1907271caf93db6897cdbcfca169441045bb52de61bDmitriy Ivanov  return do_dl_iterate_phdr(cb, data);
1917271caf93db6897cdbcfca169441045bb52de61bDmitriy Ivanov}
1927271caf93db6897cdbcfca169441045bb52de61bDmitriy Ivanov
1937abea57ba599b9b114031ae33699b5d7fba8cc97dimitry// This function is needed by libgcc.a
1947abea57ba599b9b114031ae33699b5d7fba8cc97dimitryint dl_iterate_phdr(int (*cb)(dl_phdr_info* info, size_t size, void* data), void* data) {
1957abea57ba599b9b114031ae33699b5d7fba8cc97dimitry  return __loader_dl_iterate_phdr(cb, data);
1967abea57ba599b9b114031ae33699b5d7fba8cc97dimitry}
1977abea57ba599b9b114031ae33699b5d7fba8cc97dimitry
198d9e427cf41893377dcdd0650ba20ff7cf7d72209Dimitry Ivanov#if defined(__arm__)
1997abea57ba599b9b114031ae33699b5d7fba8cc97dimitry_Unwind_Ptr __loader_dl_unwind_find_exidx(_Unwind_Ptr pc, int* pcount) {
200d9e427cf41893377dcdd0650ba20ff7cf7d72209Dimitry Ivanov  ScopedPthreadMutexLocker locker(&g_dl_mutex);
201d9e427cf41893377dcdd0650ba20ff7cf7d72209Dimitry Ivanov  return do_dl_unwind_find_exidx(pc, pcount);
202d9e427cf41893377dcdd0650ba20ff7cf7d72209Dimitry Ivanov}
203d9e427cf41893377dcdd0650ba20ff7cf7d72209Dimitry Ivanov#endif
204d9e427cf41893377dcdd0650ba20ff7cf7d72209Dimitry Ivanov
2057abea57ba599b9b114031ae33699b5d7fba8cc97dimitryvoid __loader_android_set_application_target_sdk_version(uint32_t target) {
206d974e8804689058714dc4fe9adcb57ee9a6996a8Dmitriy Ivanov  // lock to avoid modification in the middle of dlopen.
207d974e8804689058714dc4fe9adcb57ee9a6996a8Dmitriy Ivanov  ScopedPthreadMutexLocker locker(&g_dl_mutex);
20879fd668bb4ddb22432eeda2ebd8d10359013d9a8Dmitriy Ivanov  set_application_target_sdk_version(target);
20979fd668bb4ddb22432eeda2ebd8d10359013d9a8Dmitriy Ivanov}
21079fd668bb4ddb22432eeda2ebd8d10359013d9a8Dmitriy Ivanov
2117abea57ba599b9b114031ae33699b5d7fba8cc97dimitryuint32_t __loader_android_get_application_target_sdk_version() {
21279fd668bb4ddb22432eeda2ebd8d10359013d9a8Dmitriy Ivanov  return get_application_target_sdk_version();
21379fd668bb4ddb22432eeda2ebd8d10359013d9a8Dmitriy Ivanov}
21479fd668bb4ddb22432eeda2ebd8d10359013d9a8Dmitriy Ivanov
2157abea57ba599b9b114031ae33699b5d7fba8cc97dimitryvoid __loader_android_dlwarning(void* obj, void (*f)(void*, const char*)) {
216769b33fadf45a039741f932672ac2c4f901d7d4aDimitry Ivanov  ScopedPthreadMutexLocker locker(&g_dl_mutex);
217769b33fadf45a039741f932672ac2c4f901d7d4aDimitry Ivanov  get_dlwarning(obj, f);
218769b33fadf45a039741f932672ac2c4f901d7d4aDimitry Ivanov}
219769b33fadf45a039741f932672ac2c4f901d7d4aDimitry Ivanov
2207abea57ba599b9b114031ae33699b5d7fba8cc97dimitrybool __loader_android_init_anonymous_namespace(const char* shared_libs_sonames,
2217abea57ba599b9b114031ae33699b5d7fba8cc97dimitry                                               const char* library_search_path) {
22242d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov  ScopedPthreadMutexLocker locker(&g_dl_mutex);
2237a34b9d57a762ca7cd6b8d6b9f9fb45c2b991da7Dimitry Ivanov  bool success = init_anonymous_namespace(shared_libs_sonames, library_search_path);
22442d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov  if (!success) {
2257a34b9d57a762ca7cd6b8d6b9f9fb45c2b991da7Dimitry Ivanov    __bionic_format_dlerror("android_init_anonymous_namespace failed", linker_get_error_buffer());
22642d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov  }
22742d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov
22842d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov  return success;
22942d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov}
23042d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov
2317abea57ba599b9b114031ae33699b5d7fba8cc97dimitryandroid_namespace_t* __loader_android_create_namespace(const char* name,
232d9e427cf41893377dcdd0650ba20ff7cf7d72209Dimitry Ivanov                                                const char* ld_library_path,
233d9e427cf41893377dcdd0650ba20ff7cf7d72209Dimitry Ivanov                                                const char* default_library_path,
234d9e427cf41893377dcdd0650ba20ff7cf7d72209Dimitry Ivanov                                                uint64_t type,
235d9e427cf41893377dcdd0650ba20ff7cf7d72209Dimitry Ivanov                                                const char* permitted_when_isolated_path,
236d9e427cf41893377dcdd0650ba20ff7cf7d72209Dimitry Ivanov                                                android_namespace_t* parent_namespace,
237d9e427cf41893377dcdd0650ba20ff7cf7d72209Dimitry Ivanov                                                const void* caller_addr) {
23842d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov  ScopedPthreadMutexLocker locker(&g_dl_mutex);
23942d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov
240fc2da53440383fe1026e0eb287d643b577c2707dDimitry Ivanov  android_namespace_t* result = create_namespace(caller_addr,
241fc2da53440383fe1026e0eb287d643b577c2707dDimitry Ivanov                                                 name,
242fc2da53440383fe1026e0eb287d643b577c2707dDimitry Ivanov                                                 ld_library_path,
243fc2da53440383fe1026e0eb287d643b577c2707dDimitry Ivanov                                                 default_library_path,
244fc2da53440383fe1026e0eb287d643b577c2707dDimitry Ivanov                                                 type,
245fc2da53440383fe1026e0eb287d643b577c2707dDimitry Ivanov                                                 permitted_when_isolated_path,
246fc2da53440383fe1026e0eb287d643b577c2707dDimitry Ivanov                                                 parent_namespace);
24742d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov
24842d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov  if (result == nullptr) {
24942d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov    __bionic_format_dlerror("android_create_namespace failed", linker_get_error_buffer());
25042d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov  }
25142d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov
25242d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov  return result;
25342d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov}
25442d5fcb9f494eb45de3b6bf759f4a18076e84728Dmitriy Ivanov
2557abea57ba599b9b114031ae33699b5d7fba8cc97dimitrybool __loader_android_link_namespaces(android_namespace_t* namespace_from,
2567abea57ba599b9b114031ae33699b5d7fba8cc97dimitry                                      android_namespace_t* namespace_to,
2577abea57ba599b9b114031ae33699b5d7fba8cc97dimitry                                      const char* shared_libs_sonames) {
2587a34b9d57a762ca7cd6b8d6b9f9fb45c2b991da7Dimitry Ivanov  ScopedPthreadMutexLocker locker(&g_dl_mutex);
2597a34b9d57a762ca7cd6b8d6b9f9fb45c2b991da7Dimitry Ivanov
2607a34b9d57a762ca7cd6b8d6b9f9fb45c2b991da7Dimitry Ivanov  bool success = link_namespaces(namespace_from, namespace_to, shared_libs_sonames);
2617a34b9d57a762ca7cd6b8d6b9f9fb45c2b991da7Dimitry Ivanov
2627a34b9d57a762ca7cd6b8d6b9f9fb45c2b991da7Dimitry Ivanov  if (!success) {
2637a34b9d57a762ca7cd6b8d6b9f9fb45c2b991da7Dimitry Ivanov    __bionic_format_dlerror("android_link_namespaces failed", linker_get_error_buffer());
2647a34b9d57a762ca7cd6b8d6b9f9fb45c2b991da7Dimitry Ivanov  }
2657a34b9d57a762ca7cd6b8d6b9f9fb45c2b991da7Dimitry Ivanov
2667a34b9d57a762ca7cd6b8d6b9f9fb45c2b991da7Dimitry Ivanov  return success;
2677a34b9d57a762ca7cd6b8d6b9f9fb45c2b991da7Dimitry Ivanov}
2687a34b9d57a762ca7cd6b8d6b9f9fb45c2b991da7Dimitry Ivanov
2697abea57ba599b9b114031ae33699b5d7fba8cc97dimitryandroid_namespace_t* __loader_android_get_exported_namespace(const char* name) {
27001de74e76d1131b5c5b0120d07e8f468ac5f8facJiyong Park  return get_exported_namespace(name);
27101de74e76d1131b5c5b0120d07e8f468ac5f8facJiyong Park}
27201de74e76d1131b5c5b0120d07e8f468ac5f8facJiyong Park
2737abea57ba599b9b114031ae33699b5d7fba8cc97dimitryvoid __loader_cfi_fail(uint64_t CallSiteTypeId, void* Ptr, void *DiagData, void *CallerPc) {
2740a3637d3eb2424d8e825ad1825f843450a888406Evgenii Stepanov  CFIShadowWriter::CfiFail(CallSiteTypeId, Ptr, DiagData, CallerPc);
2750a3637d3eb2424d8e825ad1825f843450a888406Evgenii Stepanov}
2760a3637d3eb2424d8e825ad1825f843450a888406Evgenii Stepanov
27706016f226efe7aff2736643cb8e719c513948eccdimitryvoid __loader_add_thread_local_dtor(void* dso_handle) {
27806016f226efe7aff2736643cb8e719c513948eccdimitry  ScopedPthreadMutexLocker locker(&g_dl_mutex);
27906016f226efe7aff2736643cb8e719c513948eccdimitry  increment_dso_handle_reference_counter(dso_handle);
28006016f226efe7aff2736643cb8e719c513948eccdimitry}
28106016f226efe7aff2736643cb8e719c513948eccdimitry
28206016f226efe7aff2736643cb8e719c513948eccdimitryvoid __loader_remove_thread_local_dtor(void* dso_handle) {
28306016f226efe7aff2736643cb8e719c513948eccdimitry  ScopedPthreadMutexLocker locker(&g_dl_mutex);
28406016f226efe7aff2736643cb8e719c513948eccdimitry  decrement_dso_handle_reference_counter(dso_handle);
28506016f226efe7aff2736643cb8e719c513948eccdimitry}
28606016f226efe7aff2736643cb8e719c513948eccdimitry
287aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanovstatic uint8_t __libdl_info_buf[sizeof(soinfo)] __attribute__((aligned(8)));
288aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanovstatic soinfo* __libdl_info = nullptr;
289c00f2cb587630d5e954c7f548749f1e3170b3cb1Elliott Hughes
290d59e50063ad708509f3ad83350be33f5612c4f54Dmitriy Ivanov// This is used by the dynamic linker. Every process gets these symbols for free.
2917abea57ba599b9b114031ae33699b5d7fba8cc97dimitrysoinfo* get_libdl_info(const char* linker_path,
2927abea57ba599b9b114031ae33699b5d7fba8cc97dimitry                       const soinfo& linker_si,
2937abea57ba599b9b114031ae33699b5d7fba8cc97dimitry                       const link_map& linker_map) {
2947abea57ba599b9b114031ae33699b5d7fba8cc97dimitry  CHECK((linker_si.flags_ & FLAG_GNU_HASH) != 0);
2957abea57ba599b9b114031ae33699b5d7fba8cc97dimitry
296aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov  if (__libdl_info == nullptr) {
297d9e427cf41893377dcdd0650ba20ff7cf7d72209Dimitry Ivanov    __libdl_info = new (__libdl_info_buf) soinfo(&g_default_namespace, linker_path, nullptr, 0, 0);
2987abea57ba599b9b114031ae33699b5d7fba8cc97dimitry    __libdl_info->flags_ |= (FLAG_LINKED | FLAG_GNU_HASH);
2997abea57ba599b9b114031ae33699b5d7fba8cc97dimitry    __libdl_info->strtab_ = linker_si.strtab_;
3007abea57ba599b9b114031ae33699b5d7fba8cc97dimitry    __libdl_info->symtab_ = linker_si.symtab_;
3017abea57ba599b9b114031ae33699b5d7fba8cc97dimitry    __libdl_info->load_bias = linker_si.load_bias;
3027abea57ba599b9b114031ae33699b5d7fba8cc97dimitry
3037abea57ba599b9b114031ae33699b5d7fba8cc97dimitry    __libdl_info->gnu_nbucket_ = linker_si.gnu_nbucket_;
3047abea57ba599b9b114031ae33699b5d7fba8cc97dimitry    __libdl_info->gnu_maskwords_ = linker_si.gnu_maskwords_;
3057abea57ba599b9b114031ae33699b5d7fba8cc97dimitry    __libdl_info->gnu_shift2_ = linker_si.gnu_shift2_;
3067abea57ba599b9b114031ae33699b5d7fba8cc97dimitry    __libdl_info->gnu_bloom_filter_ = linker_si.gnu_bloom_filter_;
3077abea57ba599b9b114031ae33699b5d7fba8cc97dimitry    __libdl_info->gnu_bucket_ = linker_si.gnu_bucket_;
3087abea57ba599b9b114031ae33699b5d7fba8cc97dimitry    __libdl_info->gnu_chain_ = linker_si.gnu_chain_;
3097abea57ba599b9b114031ae33699b5d7fba8cc97dimitry
310aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov    __libdl_info->ref_count_ = 1;
3117abea57ba599b9b114031ae33699b5d7fba8cc97dimitry    __libdl_info->strtab_size_ = linker_si.strtab_size_;
312aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov    __libdl_info->local_group_root_ = __libdl_info;
3138e8c2c001380ad98f2e239c0c840dad80ebec35cdimitry    __libdl_info->soname_ = linker_si.soname_;
3141913352c6b3501893dfb45189754970f9dc6e7bbDmitriy Ivanov    __libdl_info->target_sdk_version_ = __ANDROID_API__;
315d88e1f350111b3dfd71c6492321f0503cb5540dbDimitry Ivanov    __libdl_info->generate_handle();
316cd510cbed9dc1e1b65b9d34676fdf6d85101f22cDimitry Ivanov    __libdl_info->link_map_head.l_addr = linker_map.l_addr;
317cd510cbed9dc1e1b65b9d34676fdf6d85101f22cDimitry Ivanov    __libdl_info->link_map_head.l_name = linker_map.l_name;
318cd510cbed9dc1e1b65b9d34676fdf6d85101f22cDimitry Ivanov    __libdl_info->link_map_head.l_ld = linker_map.l_ld;
319747d30ebf368be8c4ec0455324bdac53204eb179Mike Frysinger#if defined(__work_around_b_24465209__)
320aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov    strlcpy(__libdl_info->old_name_, __libdl_info->soname_, sizeof(__libdl_info->old_name_));
321aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov#endif
322d59e50063ad708509f3ad83350be33f5612c4f54Dmitriy Ivanov  }
3233b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes
324aae859cc3ca127d890e853cbf12b731e05624a22Dmitriy Ivanov  return __libdl_info;
325d59e50063ad708509f3ad83350be33f5612c4f54Dmitriy Ivanov}
326