11dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
21dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
31dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
41dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
51dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * you may not use this file except in compliance with the License.
61dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * You may obtain a copy of the License at
71dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
81dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
91dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * See the License for the specific language governing permissions and
141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * limitations under the License.
151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <dlfcn.h>
171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <pthread.h>
182e85579c34047c305caf15fb0ebe02bf3d001d0eDima Zavin#include <stdio.h>
191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "linker.h"
205c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner#include "linker_format.h"
211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* This file hijacks the symbols stubbed out in libdl.so. */
231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define DL_SUCCESS                    0
252e85579c34047c305caf15fb0ebe02bf3d001d0eDima Zavin#define DL_ERR_CANNOT_LOAD_LIBRARY    1
261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define DL_ERR_INVALID_LIBRARY_HANDLE 2
271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define DL_ERR_BAD_SYMBOL_NAME        3
281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define DL_ERR_SYMBOL_NOT_FOUND       4
291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define DL_ERR_SYMBOL_NOT_GLOBAL      5
301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
312e85579c34047c305caf15fb0ebe02bf3d001d0eDima Zavinstatic char dl_err_buf[1024];
322e85579c34047c305caf15fb0ebe02bf3d001d0eDima Zavinstatic const char *dl_err_str;
332e85579c34047c305caf15fb0ebe02bf3d001d0eDima Zavin
341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const char *dl_errors[] = {
352e85579c34047c305caf15fb0ebe02bf3d001d0eDima Zavin    [DL_ERR_CANNOT_LOAD_LIBRARY] = "Cannot load library",
361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    [DL_ERR_INVALID_LIBRARY_HANDLE] = "Invalid library handle",
371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    [DL_ERR_BAD_SYMBOL_NAME] = "Invalid symbol name",
381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    [DL_ERR_SYMBOL_NOT_FOUND] = "Symbol not found",
391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    [DL_ERR_SYMBOL_NOT_GLOBAL] = "Symbol is not global",
401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project};
411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define likely(expr)   __builtin_expect (expr, 1)
431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define unlikely(expr) __builtin_expect (expr, 0)
441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
45e19d702b8e330cef87e0983733c427b5f7842144Pavel Chupinpthread_mutex_t dl_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER;
461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
472e85579c34047c305caf15fb0ebe02bf3d001d0eDima Zavinstatic void set_dlerror(int err)
482e85579c34047c305caf15fb0ebe02bf3d001d0eDima Zavin{
495c734644eebf8d01be1e86cbe20a111a5c5a2738David 'Digit' Turner    format_buffer(dl_err_buf, sizeof(dl_err_buf), "%s: %s", dl_errors[err],
502e85579c34047c305caf15fb0ebe02bf3d001d0eDima Zavin             linker_get_error());
512e85579c34047c305caf15fb0ebe02bf3d001d0eDima Zavin    dl_err_str = (const char *)&dl_err_buf[0];
522e85579c34047c305caf15fb0ebe02bf3d001d0eDima Zavin};
532e85579c34047c305caf15fb0ebe02bf3d001d0eDima Zavin
542e85579c34047c305caf15fb0ebe02bf3d001d0eDima Zavinvoid *dlopen(const char *filename, int flag)
551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    soinfo *ret;
571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    pthread_mutex_lock(&dl_lock);
591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    ret = find_library(filename);
601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    if (unlikely(ret == NULL)) {
612e85579c34047c305caf15fb0ebe02bf3d001d0eDima Zavin        set_dlerror(DL_ERR_CANNOT_LOAD_LIBRARY);
621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    } else {
6316084168111cd7d2ac8a6b92e6fa6df5696928a5David 'Digit' Turner        soinfo_call_constructors(ret);
641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        ret->refcount++;
651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    }
661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    pthread_mutex_unlock(&dl_lock);
671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    return ret;
681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectconst char *dlerror(void)
711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
722e85579c34047c305caf15fb0ebe02bf3d001d0eDima Zavin    const char *tmp = dl_err_str;
732e85579c34047c305caf15fb0ebe02bf3d001d0eDima Zavin    dl_err_str = NULL;
742e85579c34047c305caf15fb0ebe02bf3d001d0eDima Zavin    return (const char *)tmp;
751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectvoid *dlsym(void *handle, const char *symbol)
781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
799ea64da6c511e8f9f4edae4c10c20879957631abIliyan Malchev    soinfo *found;
801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    Elf32_Sym *sym;
811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    unsigned bind;
821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    pthread_mutex_lock(&dl_lock);
842e85579c34047c305caf15fb0ebe02bf3d001d0eDima Zavin
85bedfe38b8ba512dd6236c00e8b4a9b01c2bd1281Elliott Hughes    if(unlikely(handle == 0)) {
862e85579c34047c305caf15fb0ebe02bf3d001d0eDima Zavin        set_dlerror(DL_ERR_INVALID_LIBRARY_HANDLE);
871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        goto err;
881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    }
891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    if(unlikely(symbol == 0)) {
902e85579c34047c305caf15fb0ebe02bf3d001d0eDima Zavin        set_dlerror(DL_ERR_BAD_SYMBOL_NAME);
911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        goto err;
921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    }
932e85579c34047c305caf15fb0ebe02bf3d001d0eDima Zavin
941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    if(handle == RTLD_DEFAULT) {
951698d9ebfc7e27271852a1fdf305a2ac37b3ebe4Matt Fischer        sym = lookup(symbol, &found, NULL);
961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    } else if(handle == RTLD_NEXT) {
971698d9ebfc7e27271852a1fdf305a2ac37b3ebe4Matt Fischer        void *ret_addr = __builtin_return_address(0);
981698d9ebfc7e27271852a1fdf305a2ac37b3ebe4Matt Fischer        soinfo *si = find_containing_library(ret_addr);
991698d9ebfc7e27271852a1fdf305a2ac37b3ebe4Matt Fischer
1001698d9ebfc7e27271852a1fdf305a2ac37b3ebe4Matt Fischer        sym = NULL;
1011698d9ebfc7e27271852a1fdf305a2ac37b3ebe4Matt Fischer        if(si && si->next) {
1021698d9ebfc7e27271852a1fdf305a2ac37b3ebe4Matt Fischer            sym = lookup(symbol, &found, si->next);
1031698d9ebfc7e27271852a1fdf305a2ac37b3ebe4Matt Fischer        }
1041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    } else {
1059ea64da6c511e8f9f4edae4c10c20879957631abIliyan Malchev        found = (soinfo*)handle;
10616084168111cd7d2ac8a6b92e6fa6df5696928a5David 'Digit' Turner        sym = soinfo_lookup(found, symbol);
1071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    }
1081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    if(likely(sym != 0)) {
1101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        bind = ELF32_ST_BIND(sym->st_info);
1112e85579c34047c305caf15fb0ebe02bf3d001d0eDima Zavin
1121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if(likely((bind == STB_GLOBAL) && (sym->st_shndx != 0))) {
1139ea64da6c511e8f9f4edae4c10c20879957631abIliyan Malchev            unsigned ret = sym->st_value + found->base;
1141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            pthread_mutex_unlock(&dl_lock);
1151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return (void*)ret;
1161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        }
1171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1182e85579c34047c305caf15fb0ebe02bf3d001d0eDima Zavin        set_dlerror(DL_ERR_SYMBOL_NOT_GLOBAL);
1191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    }
1202e85579c34047c305caf15fb0ebe02bf3d001d0eDima Zavin    else
1212e85579c34047c305caf15fb0ebe02bf3d001d0eDima Zavin        set_dlerror(DL_ERR_SYMBOL_NOT_FOUND);
1221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projecterr:
1241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    pthread_mutex_unlock(&dl_lock);
1251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    return 0;
1261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
1271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
128bda5da074eab4bdf374e1f4a19d480c62c72f5ffMathias Agopianint dladdr(const void *addr, Dl_info *info)
129e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer{
130e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer    int ret = 0;
131e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer
132e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer    pthread_mutex_lock(&dl_lock);
133e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer
134e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer    /* Determine if this address can be found in any library currently mapped */
135e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer    soinfo *si = find_containing_library(addr);
136e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer
137e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer    if(si) {
138e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer        memset(info, 0, sizeof(Dl_info));
139e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer
140e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer        info->dli_fname = si->name;
141e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer        info->dli_fbase = (void*)si->base;
142e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer
143e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer        /* Determine if any symbol in the library contains the specified address */
14416084168111cd7d2ac8a6b92e6fa6df5696928a5David 'Digit' Turner        Elf32_Sym *sym = soinfo_find_symbol(si, addr);
145e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer
146e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer        if(sym != NULL) {
147e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer            info->dli_sname = si->strtab + sym->st_name;
148e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer            info->dli_saddr = (void*)(si->base + sym->st_value);
149e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer        }
150e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer
151e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer        ret = 1;
152e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer    }
153e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer
154e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer    pthread_mutex_unlock(&dl_lock);
155e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer
156e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer    return ret;
157e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer}
158e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer
159bedfe38b8ba512dd6236c00e8b4a9b01c2bd1281Elliott Hughesint dlclose(void* handle) {
1601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    pthread_mutex_lock(&dl_lock);
161bedfe38b8ba512dd6236c00e8b4a9b01c2bd1281Elliott Hughes    int result = soinfo_unload((soinfo*)handle);
1621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    pthread_mutex_unlock(&dl_lock);
163bedfe38b8ba512dd6236c00e8b4a9b01c2bd1281Elliott Hughes    return result;
1641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
1651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#if defined(ANDROID_ARM_LINKER)
167e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer//                     0000000 00011111 111112 22222222 2333333 333344444444445555555
168e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer//                     0123456 78901234 567890 12345678 9012345 678901234567890123456
1691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define ANDROID_LIBDL_STRTAB \
170e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer                      "dlopen\0dlclose\0dlsym\0dlerror\0dladdr\0dl_unwind_find_exidx\0"
1711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
172d7daacb46372132ae3f0121647074936c304b572Raghu Gandham#elif defined(ANDROID_X86_LINKER) || defined(ANDROID_MIPS_LINKER)
173e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer//                     0000000 00011111 111112 22222222 2333333 3333444444444455
174e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer//                     0123456 78901234 567890 12345678 9012345 6789012345678901
1751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define ANDROID_LIBDL_STRTAB \
176e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer                      "dlopen\0dlclose\0dlsym\0dlerror\0dladdr\0dl_iterate_phdr\0"
177177a77067b6d3326dbcf88fd93d0664e48e27f9fDavid 'Digit' Turner#else
178d7daacb46372132ae3f0121647074936c304b572Raghu Gandham#error Unsupported architecture. Only ARM, MIPS, and x86 are presently supported.
1791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
1801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic Elf32_Sym libdl_symtab[] = {
1831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project      // total length of libdl_info.strtab, including trailing 0
1841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project      // This is actually the the STH_UNDEF entry. Technically, it's
1851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project      // supposed to have st_name == 0, but instead, it points to an index
1861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project      // in the strtab with a \0 to make iterating through the symtab easier.
1871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    { st_name: sizeof(ANDROID_LIBDL_STRTAB) - 1,
1881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    },
1891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    { st_name: 0,   // starting index of the name in libdl_info.strtab
1901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project      st_value: (Elf32_Addr) &dlopen,
1911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project      st_info: STB_GLOBAL << 4,
1921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project      st_shndx: 1,
1931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    },
1941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    { st_name: 7,
1951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project      st_value: (Elf32_Addr) &dlclose,
1961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project      st_info: STB_GLOBAL << 4,
1971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project      st_shndx: 1,
1981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    },
1991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    { st_name: 15,
2001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project      st_value: (Elf32_Addr) &dlsym,
2011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project      st_info: STB_GLOBAL << 4,
2021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project      st_shndx: 1,
2031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    },
2041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    { st_name: 21,
2051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project      st_value: (Elf32_Addr) &dlerror,
2061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project      st_info: STB_GLOBAL << 4,
2071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project      st_shndx: 1,
2081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    },
2091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    { st_name: 29,
210e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer      st_value: (Elf32_Addr) &dladdr,
211e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer      st_info: STB_GLOBAL << 4,
212e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer      st_shndx: 1,
213e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer    },
214e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer#ifdef ANDROID_ARM_LINKER
215e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer    { st_name: 36,
2161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project      st_value: (Elf32_Addr) &dl_unwind_find_exidx,
2171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project      st_info: STB_GLOBAL << 4,
2181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project      st_shndx: 1,
2191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    },
220d7daacb46372132ae3f0121647074936c304b572Raghu Gandham#elif defined(ANDROID_X86_LINKER) || defined(ANDROID_MIPS_LINKER)
221e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer    { st_name: 36,
2221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project      st_value: (Elf32_Addr) &dl_iterate_phdr,
2231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project      st_info: STB_GLOBAL << 4,
2241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project      st_shndx: 1,
2251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    },
2261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
2271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project};
2281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* Fake out a hash table with a single bucket.
2301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * A search of the hash table will look through
2311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * libdl_symtab starting with index [1], then
2321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * use libdl_chains to find the next index to
2331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * look at.  libdl_chains should be set up to
2341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * walk through every element in libdl_symtab,
2351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * and then end with 0 (sentinel value).
2361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
2371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * I.e., libdl_chains should look like
2381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * { 0, 2, 3, ... N, 0 } where N is the number
2391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * of actual symbols, or nelems(libdl_symtab)-1
2401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * (since the first element of libdl_symtab is not
2411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * a real symbol).
2421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
2431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * (see _elf_lookup())
2441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
2451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Note that adding any new symbols here requires
2461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * stubbing them out in libdl.
2471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
2481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic unsigned libdl_buckets[1] = { 1 };
249e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischerstatic unsigned libdl_chains[7] = { 0, 2, 3, 4, 5, 6, 0 };
2501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectsoinfo libdl_info = {
2521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    name: "libdl.so",
2531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    flags: FLAG_LINKED,
2541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    strtab: ANDROID_LIBDL_STRTAB,
2561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    symtab: libdl_symtab,
2571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    nbucket: 1,
259e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer    nchain: 7,
2601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    bucket: libdl_buckets,
2611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    chain: libdl_chains,
2621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project};
263