diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:28:13 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:28:13 -0800 |
commit | 1767f908af327fa388b1c66883760ad851267013 (patch) | |
tree | 4b825dc642cb6eb9a060e54bf8d69288fbee4904 /linker/dlfcn.c | |
parent | a799b53f10e5a6fd51fef4436cfb7ec99836a516 (diff) | |
download | bionic-1767f908af327fa388b1c66883760ad851267013.zip bionic-1767f908af327fa388b1c66883760ad851267013.tar.gz bionic-1767f908af327fa388b1c66883760ad851267013.tar.bz2 |
auto import from //depot/cupcake/@135843
Diffstat (limited to 'linker/dlfcn.c')
-rw-r--r-- | linker/dlfcn.c | 212 |
1 files changed, 0 insertions, 212 deletions
diff --git a/linker/dlfcn.c b/linker/dlfcn.c deleted file mode 100644 index cd73d11..0000000 --- a/linker/dlfcn.c +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright (C) 2007 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 <dlfcn.h> -#include <pthread.h> -#include "linker.h" - -/* This file hijacks the symbols stubbed out in libdl.so. */ - -#define DL_SUCCESS 0 -#define DL_ERR_CANNOT_FIND_LIBRARY 1 -#define DL_ERR_INVALID_LIBRARY_HANDLE 2 -#define DL_ERR_BAD_SYMBOL_NAME 3 -#define DL_ERR_SYMBOL_NOT_FOUND 4 -#define DL_ERR_SYMBOL_NOT_GLOBAL 5 - -static const char *dl_errors[] = { - [DL_SUCCESS] = NULL, - [DL_ERR_CANNOT_FIND_LIBRARY] = "Cannot find library", - [DL_ERR_INVALID_LIBRARY_HANDLE] = "Invalid library handle", - [DL_ERR_BAD_SYMBOL_NAME] = "Invalid symbol name", - [DL_ERR_SYMBOL_NOT_FOUND] = "Symbol not found", - [DL_ERR_SYMBOL_NOT_GLOBAL] = "Symbol is not global", -}; - -static int dl_last_err = DL_SUCCESS; - -#define likely(expr) __builtin_expect (expr, 1) -#define unlikely(expr) __builtin_expect (expr, 0) - -static pthread_mutex_t dl_lock = PTHREAD_MUTEX_INITIALIZER; - -void *dlopen(const char *filename, int flag) -{ - soinfo *ret; - - pthread_mutex_lock(&dl_lock); - ret = find_library(filename); - if (unlikely(ret == NULL)) { - dl_last_err = DL_ERR_CANNOT_FIND_LIBRARY; - } else { - ret->refcount++; - } - pthread_mutex_unlock(&dl_lock); - return ret; -} - -const char *dlerror(void) -{ - const char *err = dl_errors[dl_last_err]; - dl_last_err = DL_SUCCESS; - return err; -} - -void *dlsym(void *handle, const char *symbol) -{ - unsigned base; - Elf32_Sym *sym; - unsigned bind; - - pthread_mutex_lock(&dl_lock); - - if(unlikely(handle == 0)) { - dl_last_err = DL_ERR_INVALID_LIBRARY_HANDLE; - goto err; - } - if(unlikely(symbol == 0)) { - dl_last_err = DL_ERR_BAD_SYMBOL_NAME; - goto err; - } - - if(handle == RTLD_DEFAULT) { - sym = lookup(symbol, &base); - } else if(handle == RTLD_NEXT) { - sym = lookup(symbol, &base); - } else { - sym = lookup_in_library((soinfo*) handle, symbol); - base = ((soinfo*) handle)->base; - } - - if(likely(sym != 0)) { - bind = ELF32_ST_BIND(sym->st_info); - - if(likely((bind == STB_GLOBAL) && (sym->st_shndx != 0))) { - unsigned ret = sym->st_value + base; - pthread_mutex_unlock(&dl_lock); - return (void*)ret; - } - - dl_last_err = DL_ERR_SYMBOL_NOT_GLOBAL; - } - else dl_last_err = DL_ERR_SYMBOL_NOT_FOUND; - -err: - pthread_mutex_unlock(&dl_lock); - return 0; -} - -int dlclose(void *handle) -{ - pthread_mutex_lock(&dl_lock); - (void)unload_library((soinfo*)handle); - pthread_mutex_unlock(&dl_lock); - return 0; -} - -#if defined(ANDROID_ARM_LINKER) -// 0000000 00011111 111112 22222222 233333333334444444444 -// 0123456 78901234 567890 12345678 901234567890123456789 -#define ANDROID_LIBDL_STRTAB \ - "dlopen\0dlclose\0dlsym\0dlerror\0dl_unwind_find_exidx\0" - -#elif defined(ANDROID_X86_LINKER) -// 0000000 00011111 111112 22222222 2333333333344444 -// 0123456 78901234 567890 12345678 9012345678901234 -#define ANDROID_LIBDL_STRTAB \ - "dlopen\0dlclose\0dlsym\0dlerror\0dl_iterate_phdr\0" - -#else /* !defined(ANDROID_ARM_LINKER) && !defined(ANDROID_X86_LINKER) */ -#error Unsupported architecture. Only ARM and x86 are presently supported. -#endif - - -static Elf32_Sym libdl_symtab[] = { - // total length of libdl_info.strtab, including trailing 0 - // This is actually the the STH_UNDEF entry. Technically, it's - // supposed to have st_name == 0, but instead, it points to an index - // in the strtab with a \0 to make iterating through the symtab easier. - { st_name: sizeof(ANDROID_LIBDL_STRTAB) - 1, - }, - { st_name: 0, // starting index of the name in libdl_info.strtab - st_value: (Elf32_Addr) &dlopen, - st_info: STB_GLOBAL << 4, - st_shndx: 1, - }, - { st_name: 7, - st_value: (Elf32_Addr) &dlclose, - st_info: STB_GLOBAL << 4, - st_shndx: 1, - }, - { st_name: 15, - st_value: (Elf32_Addr) &dlsym, - st_info: STB_GLOBAL << 4, - st_shndx: 1, - }, - { st_name: 21, - st_value: (Elf32_Addr) &dlerror, - st_info: STB_GLOBAL << 4, - st_shndx: 1, - }, -#ifdef ANDROID_ARM_LINKER - { st_name: 29, - st_value: (Elf32_Addr) &dl_unwind_find_exidx, - st_info: STB_GLOBAL << 4, - st_shndx: 1, - }, -#elif defined(ANDROID_X86_LINKER) - { st_name: 29, - st_value: (Elf32_Addr) &dl_iterate_phdr, - st_info: STB_GLOBAL << 4, - st_shndx: 1, - }, -#endif -}; - -/* Fake out a hash table with a single bucket. - * A search of the hash table will look through - * libdl_symtab starting with index [1], then - * use libdl_chains to find the next index to - * look at. libdl_chains should be set up to - * walk through every element in libdl_symtab, - * and then end with 0 (sentinel value). - * - * I.e., libdl_chains should look like - * { 0, 2, 3, ... N, 0 } where N is the number - * of actual symbols, or nelems(libdl_symtab)-1 - * (since the first element of libdl_symtab is not - * a real symbol). - * - * (see _elf_lookup()) - * - * Note that adding any new symbols here requires - * stubbing them out in libdl. - */ -static unsigned libdl_buckets[1] = { 1 }; -static unsigned libdl_chains[6] = { 0, 2, 3, 4, 5, 0 }; - -soinfo libdl_info = { - name: "libdl.so", - flags: FLAG_LINKED, - - strtab: ANDROID_LIBDL_STRTAB, - symtab: libdl_symtab, - - nbucket: 1, - nchain: 6, - bucket: libdl_buckets, - chain: libdl_chains, -}; - |