13b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes/* 23b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes * Copyright (C) 2007 The Android Open Source Project 33b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes * 43b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License"); 53b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes * you may not use this file except in compliance with the License. 63b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes * You may obtain a copy of the License at 73b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes * 83b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes * http://www.apache.org/licenses/LICENSE-2.0 93b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes * 103b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes * Unless required by applicable law or agreed to in writing, software 113b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS, 123b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes * See the License for the specific language governing permissions and 143b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes * limitations under the License. 153b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes */ 163b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 175419b9474753d25dff947c7740532f86d130c0beElliott Hughes#include "linker.h" 185419b9474753d25dff947c7740532f86d130c0beElliott Hughes 193b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes#include <dlfcn.h> 203b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes#include <pthread.h> 213b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes#include <stdio.h> 225419b9474753d25dff947c7740532f86d130c0beElliott Hughes#include <stdlib.h> 23012cb4583a5f8564059142bb1900ea3a31e7cfa9Torne (Richard Coles)#include <android/dlext.h> 243b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 255419b9474753d25dff947c7740532f86d130c0beElliott Hughes#include <bionic/pthread_internal.h> 26eb847bc8666842a3cfc9c06e8458ad1abebebaf0Elliott Hughes#include "private/bionic_tls.h" 27eb847bc8666842a3cfc9c06e8458ad1abebebaf0Elliott Hughes#include "private/ScopedPthreadMutexLocker.h" 28eb847bc8666842a3cfc9c06e8458ad1abebebaf0Elliott Hughes#include "private/ThreadLocalBuffer.h" 293b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 303b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes/* This file hijacks the symbols stubbed out in libdl.so. */ 313b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 321728b2396591853345507a063ed6075dfd251706Elliott Hughesstatic pthread_mutex_t g_dl_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER; 333b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 345419b9474753d25dff947c7740532f86d130c0beElliott Hughesstatic const char* __bionic_set_dlerror(char* new_value) { 352a0b873065edb304fa2d1c54f8de663ea638b8abElliott Hughes char** dlerror_slot = &reinterpret_cast<char**>(__get_tls())[TLS_SLOT_DLERROR]; 363b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 375419b9474753d25dff947c7740532f86d130c0beElliott Hughes const char* old_value = *dlerror_slot; 385419b9474753d25dff947c7740532f86d130c0beElliott Hughes *dlerror_slot = new_value; 395419b9474753d25dff947c7740532f86d130c0beElliott Hughes return old_value; 405419b9474753d25dff947c7740532f86d130c0beElliott Hughes} 413b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 425419b9474753d25dff947c7740532f86d130c0beElliott Hughesstatic void __bionic_format_dlerror(const char* msg, const char* detail) { 435419b9474753d25dff947c7740532f86d130c0beElliott Hughes char* buffer = __get_thread()->dlerror_buffer; 445419b9474753d25dff947c7740532f86d130c0beElliott Hughes strlcpy(buffer, msg, __BIONIC_DLERROR_BUFFER_SIZE); 453b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes if (detail != NULL) { 465419b9474753d25dff947c7740532f86d130c0beElliott Hughes strlcat(buffer, ": ", __BIONIC_DLERROR_BUFFER_SIZE); 475419b9474753d25dff947c7740532f86d130c0beElliott Hughes strlcat(buffer, detail, __BIONIC_DLERROR_BUFFER_SIZE); 483b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes } 495419b9474753d25dff947c7740532f86d130c0beElliott Hughes 505419b9474753d25dff947c7740532f86d130c0beElliott Hughes __bionic_set_dlerror(buffer); 515419b9474753d25dff947c7740532f86d130c0beElliott Hughes} 525419b9474753d25dff947c7740532f86d130c0beElliott Hughes 535419b9474753d25dff947c7740532f86d130c0beElliott Hughesconst char* dlerror() { 545419b9474753d25dff947c7740532f86d130c0beElliott Hughes const char* old_value = __bionic_set_dlerror(NULL); 555419b9474753d25dff947c7740532f86d130c0beElliott Hughes return old_value; 563b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes} 573b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 58a4aafd156068ee174012f28cd894dbecf0e4ab90Elliott Hughesvoid android_get_LD_LIBRARY_PATH(char* buffer, size_t buffer_size) { 591728b2396591853345507a063ed6075dfd251706Elliott Hughes ScopedPthreadMutexLocker locker(&g_dl_mutex); 60a4aafd156068ee174012f28cd894dbecf0e4ab90Elliott Hughes do_android_get_LD_LIBRARY_PATH(buffer, buffer_size); 61a4aafd156068ee174012f28cd894dbecf0e4ab90Elliott Hughes} 62a4aafd156068ee174012f28cd894dbecf0e4ab90Elliott Hughes 63cade4c36e7c9c62db3f476a0f9cfc329bac9acb7Elliott Hughesvoid android_update_LD_LIBRARY_PATH(const char* ld_library_path) { 641728b2396591853345507a063ed6075dfd251706Elliott Hughes ScopedPthreadMutexLocker locker(&g_dl_mutex); 65cade4c36e7c9c62db3f476a0f9cfc329bac9acb7Elliott Hughes do_android_update_LD_LIBRARY_PATH(ld_library_path); 66cade4c36e7c9c62db3f476a0f9cfc329bac9acb7Elliott Hughes} 67cade4c36e7c9c62db3f476a0f9cfc329bac9acb7Elliott Hughes 681a586293400d0e1d73e6eb82f7dfe9d2d9ed3c4bElliott Hughesstatic void* dlopen_ext(const char* filename, int flags, const android_dlextinfo* extinfo) { 691728b2396591853345507a063ed6075dfd251706Elliott Hughes ScopedPthreadMutexLocker locker(&g_dl_mutex); 701a586293400d0e1d73e6eb82f7dfe9d2d9ed3c4bElliott Hughes soinfo* result = do_dlopen(filename, flags, extinfo); 713b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes if (result == NULL) { 72650be4e584eeab3591b9e273bfd6d169eea60853Elliott Hughes __bionic_format_dlerror("dlopen failed", linker_get_error_buffer()); 733b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes return NULL; 743b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes } 753b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes return result; 763b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes} 773b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 78b648a8a57ee42533a5bf127225a252f73ca2cbbcDmitriy Ivanovvoid* android_dlopen_ext(const char* filename, int flags, const android_dlextinfo* extinfo) { 791a586293400d0e1d73e6eb82f7dfe9d2d9ed3c4bElliott Hughes return dlopen_ext(filename, flags, extinfo); 80b648a8a57ee42533a5bf127225a252f73ca2cbbcDmitriy Ivanov} 81b648a8a57ee42533a5bf127225a252f73ca2cbbcDmitriy Ivanov 82012cb4583a5f8564059142bb1900ea3a31e7cfa9Torne (Richard Coles)void* dlopen(const char* filename, int flags) { 831a586293400d0e1d73e6eb82f7dfe9d2d9ed3c4bElliott Hughes return dlopen_ext(filename, flags, NULL); 84012cb4583a5f8564059142bb1900ea3a31e7cfa9Torne (Richard Coles)} 85012cb4583a5f8564059142bb1900ea3a31e7cfa9Torne (Richard Coles) 863b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughesvoid* dlsym(void* handle, const char* symbol) { 871728b2396591853345507a063ed6075dfd251706Elliott Hughes ScopedPthreadMutexLocker locker(&g_dl_mutex); 883b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 89ca1c80220e9b16fde7a761ca1c2c63dbe8071e0fDmitriy Ivanov#if !defined(__LP64__) 905419b9474753d25dff947c7740532f86d130c0beElliott Hughes if (handle == NULL) { 915419b9474753d25dff947c7740532f86d130c0beElliott Hughes __bionic_format_dlerror("dlsym library handle is null", NULL); 923b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes return NULL; 933b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes } 94ca1c80220e9b16fde7a761ca1c2c63dbe8071e0fDmitriy Ivanov#endif 95ca1c80220e9b16fde7a761ca1c2c63dbe8071e0fDmitriy Ivanov 965419b9474753d25dff947c7740532f86d130c0beElliott Hughes if (symbol == NULL) { 975419b9474753d25dff947c7740532f86d130c0beElliott Hughes __bionic_format_dlerror("dlsym symbol name is null", NULL); 983b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes return NULL; 993b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes } 1003b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 1013b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes soinfo* found = NULL; 1020266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes ElfW(Sym)* sym = NULL; 103acfc63760eef50cd451b80df8860d17bbab1ca33Colin Cross if (handle == RTLD_DEFAULT) { 1049419420919ea846bbad5510850c7aaec95021648Dmitriy Ivanov sym = dlsym_linear_lookup(symbol, &found, NULL); 105acfc63760eef50cd451b80df8860d17bbab1ca33Colin Cross } else if (handle == RTLD_NEXT) { 1069419420919ea846bbad5510850c7aaec95021648Dmitriy Ivanov void* caller_addr = __builtin_return_address(0); 1079419420919ea846bbad5510850c7aaec95021648Dmitriy Ivanov soinfo* si = find_containing_library(caller_addr); 1089419420919ea846bbad5510850c7aaec95021648Dmitriy Ivanov 1093b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes sym = NULL; 1109419420919ea846bbad5510850c7aaec95021648Dmitriy Ivanov if (si && si->next) { 1119419420919ea846bbad5510850c7aaec95021648Dmitriy Ivanov sym = dlsym_linear_lookup(symbol, &found, si->next); 1123b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes } 1133b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes } else { 1149419420919ea846bbad5510850c7aaec95021648Dmitriy Ivanov sym = dlsym_handle_lookup(reinterpret_cast<soinfo*>(handle), &found, symbol); 1153b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes } 1163b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 1179419420919ea846bbad5510850c7aaec95021648Dmitriy Ivanov if (sym != NULL) { 1189419420919ea846bbad5510850c7aaec95021648Dmitriy Ivanov unsigned bind = ELF_ST_BIND(sym->st_info); 1199419420919ea846bbad5510850c7aaec95021648Dmitriy Ivanov 1209419420919ea846bbad5510850c7aaec95021648Dmitriy Ivanov if ((bind == STB_GLOBAL || bind == STB_WEAK) && sym->st_shndx != 0) { 1219419420919ea846bbad5510850c7aaec95021648Dmitriy Ivanov return reinterpret_cast<void*>(sym->st_value + found->load_bias); 1229419420919ea846bbad5510850c7aaec95021648Dmitriy Ivanov } 1239419420919ea846bbad5510850c7aaec95021648Dmitriy Ivanov 1249419420919ea846bbad5510850c7aaec95021648Dmitriy Ivanov __bionic_format_dlerror("symbol found but not global", symbol); 1259419420919ea846bbad5510850c7aaec95021648Dmitriy Ivanov return NULL; 1263b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes } else { 1275419b9474753d25dff947c7740532f86d130c0beElliott Hughes __bionic_format_dlerror("undefined symbol", symbol); 1283b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes return NULL; 1293b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes } 1303b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes} 1313b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 1323b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughesint dladdr(const void* addr, Dl_info* info) { 1331728b2396591853345507a063ed6075dfd251706Elliott Hughes ScopedPthreadMutexLocker locker(&g_dl_mutex); 1343b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 1353b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes // Determine if this address can be found in any library currently mapped. 1363b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes soinfo* si = find_containing_library(addr); 1373b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes if (si == NULL) { 1383b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes return 0; 1393b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes } 1403b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 1413b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes memset(info, 0, sizeof(Dl_info)); 1423b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 1433b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes info->dli_fname = si->name; 1443b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes // Address at which the shared object is loaded. 145faf05bacd45719291b371f24b1b89543881b37f6Elliott Hughes info->dli_fbase = reinterpret_cast<void*>(si->base); 1463b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 1473b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes // Determine if any symbol in the library contains the specified address. 1480266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes ElfW(Sym)* sym = dladdr_find_symbol(si, addr); 1493b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes if (sym != NULL) { 1503b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes info->dli_sname = si->strtab + sym->st_name; 151faf05bacd45719291b371f24b1b89543881b37f6Elliott Hughes info->dli_saddr = reinterpret_cast<void*>(si->load_bias + sym->st_value); 1523b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes } 1533b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 1543b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes return 1; 1553b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes} 1563b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 1573b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughesint dlclose(void* handle) { 1581728b2396591853345507a063ed6075dfd251706Elliott Hughes ScopedPthreadMutexLocker locker(&g_dl_mutex); 159b648a8a57ee42533a5bf127225a252f73ca2cbbcDmitriy Ivanov do_dlclose(reinterpret_cast<soinfo*>(handle)); 160b648a8a57ee42533a5bf127225a252f73ca2cbbcDmitriy Ivanov // dlclose has no defined errors. 161b648a8a57ee42533a5bf127225a252f73ca2cbbcDmitriy Ivanov return 0; 1623b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes} 1633b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 1643b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes// name_offset: starting index of the name in libdl_info.strtab 1653b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes#define ELF32_SYM_INITIALIZER(name_offset, value, shndx) \ 1663b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes { name_offset, \ 1673b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes reinterpret_cast<Elf32_Addr>(reinterpret_cast<void*>(value)), \ 1683b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes /* st_size */ 0, \ 1693b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes (shndx == 0) ? 0 : (STB_GLOBAL << 4), \ 1703b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes /* st_other */ 0, \ 171c00f2cb587630d5e954c7f548749f1e3170b3cb1Elliott Hughes shndx, \ 172c00f2cb587630d5e954c7f548749f1e3170b3cb1Elliott Hughes } 173c00f2cb587630d5e954c7f548749f1e3170b3cb1Elliott Hughes 174c00f2cb587630d5e954c7f548749f1e3170b3cb1Elliott Hughes#define ELF64_SYM_INITIALIZER(name_offset, value, shndx) \ 175c00f2cb587630d5e954c7f548749f1e3170b3cb1Elliott Hughes { name_offset, \ 176c00f2cb587630d5e954c7f548749f1e3170b3cb1Elliott Hughes (shndx == 0) ? 0 : (STB_GLOBAL << 4), \ 177c00f2cb587630d5e954c7f548749f1e3170b3cb1Elliott Hughes /* st_other */ 0, \ 178c00f2cb587630d5e954c7f548749f1e3170b3cb1Elliott Hughes shndx, \ 179c00f2cb587630d5e954c7f548749f1e3170b3cb1Elliott Hughes reinterpret_cast<Elf64_Addr>(reinterpret_cast<void*>(value)), \ 180c00f2cb587630d5e954c7f548749f1e3170b3cb1Elliott Hughes /* st_size */ 0, \ 181c00f2cb587630d5e954c7f548749f1e3170b3cb1Elliott Hughes } 182c00f2cb587630d5e954c7f548749f1e3170b3cb1Elliott Hughes 183a4aafd156068ee174012f28cd894dbecf0e4ab90Elliott Hughes#if defined(__arm__) 184012cb4583a5f8564059142bb1900ea3a31e7cfa9Torne (Richard Coles) // 0000000 00011111 111112 22222222 2333333 3333444444444455555555556666666 6667777777777888888888899999 9999900000000001 1111111112222222222 333333333344444444445 185012cb4583a5f8564059142bb1900ea3a31e7cfa9Torne (Richard Coles) // 0123456 78901234 567890 12345678 9012345 6789012345678901234567890123456 7890123456789012345678901234 5678901234567890 1234567890123456789 012345678901234567890 186a4aafd156068ee174012f28cd894dbecf0e4ab90Elliott Hughes# define ANDROID_LIBDL_STRTAB \ 187012cb4583a5f8564059142bb1900ea3a31e7cfa9Torne (Richard Coles) "dlopen\0dlclose\0dlsym\0dlerror\0dladdr\0android_update_LD_LIBRARY_PATH\0android_get_LD_LIBRARY_PATH\0dl_iterate_phdr\0android_dlopen_ext\0dl_unwind_find_exidx\0" 188a4aafd156068ee174012f28cd894dbecf0e4ab90Elliott Hughes#elif defined(__aarch64__) || defined(__i386__) || defined(__mips__) || defined(__x86_64__) 189012cb4583a5f8564059142bb1900ea3a31e7cfa9Torne (Richard Coles) // 0000000 00011111 111112 22222222 2333333 3333444444444455555555556666666 6667777777777888888888899999 9999900000000001 1111111112222222222 190012cb4583a5f8564059142bb1900ea3a31e7cfa9Torne (Richard Coles) // 0123456 78901234 567890 12345678 9012345 6789012345678901234567890123456 7890123456789012345678901234 5678901234567890 1234567890123456789 191a4aafd156068ee174012f28cd894dbecf0e4ab90Elliott Hughes# define ANDROID_LIBDL_STRTAB \ 192012cb4583a5f8564059142bb1900ea3a31e7cfa9Torne (Richard Coles) "dlopen\0dlclose\0dlsym\0dlerror\0dladdr\0android_update_LD_LIBRARY_PATH\0android_get_LD_LIBRARY_PATH\0dl_iterate_phdr\0android_dlopen_ext\0" 193a4aafd156068ee174012f28cd894dbecf0e4ab90Elliott Hughes#else 1949918665a45095ad135576f005c0e5307feb366a1Chris Dearman# error Unsupported architecture. Only arm, arm64, mips, mips64, x86 and x86_64 are presently supported. 195a4aafd156068ee174012f28cd894dbecf0e4ab90Elliott Hughes#endif 196a4aafd156068ee174012f28cd894dbecf0e4ab90Elliott Hughes 1971728b2396591853345507a063ed6075dfd251706Elliott Hughesstatic ElfW(Sym) g_libdl_symtab[] = { 1983b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes // Total length of libdl_info.strtab, including trailing 0. 1993b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes // This is actually the STH_UNDEF entry. Technically, it's 2003b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes // supposed to have st_name == 0, but instead, it points to an index 2013b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes // in the strtab with a \0 to make iterating through the symtab easier. 2020266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes ELFW(SYM_INITIALIZER)(sizeof(ANDROID_LIBDL_STRTAB) - 1, NULL, 0), 2030266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes ELFW(SYM_INITIALIZER)( 0, &dlopen, 1), 2040266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes ELFW(SYM_INITIALIZER)( 7, &dlclose, 1), 2050266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes ELFW(SYM_INITIALIZER)( 15, &dlsym, 1), 2060266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes ELFW(SYM_INITIALIZER)( 21, &dlerror, 1), 2070266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes ELFW(SYM_INITIALIZER)( 29, &dladdr, 1), 2080266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes ELFW(SYM_INITIALIZER)( 36, &android_update_LD_LIBRARY_PATH, 1), 2090266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes ELFW(SYM_INITIALIZER)( 67, &android_get_LD_LIBRARY_PATH, 1), 2100266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes ELFW(SYM_INITIALIZER)( 95, &dl_iterate_phdr, 1), 211012cb4583a5f8564059142bb1900ea3a31e7cfa9Torne (Richard Coles) ELFW(SYM_INITIALIZER)(111, &android_dlopen_ext, 1), 2124eeb1f12a8b63afc0d0ad4d466b16fbffb21cd5aElliott Hughes#if defined(__arm__) 213012cb4583a5f8564059142bb1900ea3a31e7cfa9Torne (Richard Coles) ELFW(SYM_INITIALIZER)(130, &dl_unwind_find_exidx, 1), 2143b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes#endif 2153b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes}; 2163b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 21722d629211d72adaf46f3fc48f59540f8e5798b1eElliott Hughes// Fake out a hash table with a single bucket. 21822d629211d72adaf46f3fc48f59540f8e5798b1eElliott Hughes// 2191728b2396591853345507a063ed6075dfd251706Elliott Hughes// A search of the hash table will look through g_libdl_symtab starting with index 1, then 2201728b2396591853345507a063ed6075dfd251706Elliott Hughes// use g_libdl_chains to find the next index to look at. g_libdl_chains should be set up to 2211728b2396591853345507a063ed6075dfd251706Elliott Hughes// walk through every element in g_libdl_symtab, and then end with 0 (sentinel value). 22222d629211d72adaf46f3fc48f59540f8e5798b1eElliott Hughes// 2231728b2396591853345507a063ed6075dfd251706Elliott Hughes// That is, g_libdl_chains should look like { 0, 2, 3, ... N, 0 } where N is the number 2241728b2396591853345507a063ed6075dfd251706Elliott Hughes// of actual symbols, or nelems(g_libdl_symtab)-1 (since the first element of g_libdl_symtab is not 225a4aafd156068ee174012f28cd894dbecf0e4ab90Elliott Hughes// a real symbol). (See soinfo_elf_lookup().) 22622d629211d72adaf46f3fc48f59540f8e5798b1eElliott Hughes// 227a4aafd156068ee174012f28cd894dbecf0e4ab90Elliott Hughes// Note that adding any new symbols here requires stubbing them out in libdl. 2281728b2396591853345507a063ed6075dfd251706Elliott Hughesstatic unsigned g_libdl_buckets[1] = { 1 }; 2294eeb1f12a8b63afc0d0ad4d466b16fbffb21cd5aElliott Hughes#if defined(__arm__) 2301728b2396591853345507a063ed6075dfd251706Elliott Hughesstatic unsigned g_libdl_chains[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0 }; 23124053a461e7a20f34002262c1bb122023134989dChristopher Ferris#else 2321728b2396591853345507a063ed6075dfd251706Elliott Hughesstatic unsigned g_libdl_chains[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; 23324053a461e7a20f34002262c1bb122023134989dChristopher Ferris#endif 2343b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 235d59e50063ad708509f3ad83350be33f5612c4f54Dmitriy Ivanov// Defined as global because we do not yet have access 236d59e50063ad708509f3ad83350be33f5612c4f54Dmitriy Ivanov// to synchronization functions __cxa_guard_* needed 237d59e50063ad708509f3ad83350be33f5612c4f54Dmitriy Ivanov// to define statics inside functions. 238d59e50063ad708509f3ad83350be33f5612c4f54Dmitriy Ivanovstatic soinfo __libdl_info; 239c00f2cb587630d5e954c7f548749f1e3170b3cb1Elliott Hughes 240d59e50063ad708509f3ad83350be33f5612c4f54Dmitriy Ivanov// This is used by the dynamic linker. Every process gets these symbols for free. 241d59e50063ad708509f3ad83350be33f5612c4f54Dmitriy Ivanovsoinfo* get_libdl_info() { 242d59e50063ad708509f3ad83350be33f5612c4f54Dmitriy Ivanov if (__libdl_info.name[0] == '\0') { 243d59e50063ad708509f3ad83350be33f5612c4f54Dmitriy Ivanov // initialize 244d59e50063ad708509f3ad83350be33f5612c4f54Dmitriy Ivanov strncpy(__libdl_info.name, "libdl.so", sizeof(__libdl_info.name)); 245d59e50063ad708509f3ad83350be33f5612c4f54Dmitriy Ivanov __libdl_info.flags = FLAG_LINKED | FLAG_NEW_SOINFO; 246d59e50063ad708509f3ad83350be33f5612c4f54Dmitriy Ivanov __libdl_info.strtab = ANDROID_LIBDL_STRTAB; 247d59e50063ad708509f3ad83350be33f5612c4f54Dmitriy Ivanov __libdl_info.symtab = g_libdl_symtab; 248d59e50063ad708509f3ad83350be33f5612c4f54Dmitriy Ivanov __libdl_info.nbucket = sizeof(g_libdl_buckets)/sizeof(unsigned); 249d59e50063ad708509f3ad83350be33f5612c4f54Dmitriy Ivanov __libdl_info.nchain = sizeof(g_libdl_chains)/sizeof(unsigned); 250d59e50063ad708509f3ad83350be33f5612c4f54Dmitriy Ivanov __libdl_info.bucket = g_libdl_buckets; 251d59e50063ad708509f3ad83350be33f5612c4f54Dmitriy Ivanov __libdl_info.chain = g_libdl_chains; 252d59e50063ad708509f3ad83350be33f5612c4f54Dmitriy Ivanov __libdl_info.has_DT_SYMBOLIC = true; 253d59e50063ad708509f3ad83350be33f5612c4f54Dmitriy Ivanov } 2543b297c40794b23d50cb5240f9b03f6ef25fd98dbElliott Hughes 255d59e50063ad708509f3ad83350be33f5612c4f54Dmitriy Ivanov return &__libdl_info; 256d59e50063ad708509f3ad83350be33f5612c4f54Dmitriy Ivanov} 257