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
451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic pthread_mutex_t dl_lock = PTHREAD_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 {
631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        ret->refcount++;
641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    }
651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    pthread_mutex_unlock(&dl_lock);
661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    return ret;
671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectconst char *dlerror(void)
701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
712e85579c34047c305caf15fb0ebe02bf3d001d0eDima Zavin    const char *tmp = dl_err_str;
722e85579c34047c305caf15fb0ebe02bf3d001d0eDima Zavin    dl_err_str = NULL;
732e85579c34047c305caf15fb0ebe02bf3d001d0eDima Zavin    return (const char *)tmp;
741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectvoid *dlsym(void *handle, const char *symbol)
771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
789ea64da6c511e8f9f4edae4c10c20879957631abIliyan Malchev    soinfo *found;
791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    Elf32_Sym *sym;
801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    unsigned bind;
811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    pthread_mutex_lock(&dl_lock);
832e85579c34047c305caf15fb0ebe02bf3d001d0eDima Zavin
841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    if(unlikely(handle == 0)) {
852e85579c34047c305caf15fb0ebe02bf3d001d0eDima Zavin        set_dlerror(DL_ERR_INVALID_LIBRARY_HANDLE);
861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        goto err;
871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    }
881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    if(unlikely(symbol == 0)) {
892e85579c34047c305caf15fb0ebe02bf3d001d0eDima Zavin        set_dlerror(DL_ERR_BAD_SYMBOL_NAME);
901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        goto err;
911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    }
922e85579c34047c305caf15fb0ebe02bf3d001d0eDima Zavin
931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    if(handle == RTLD_DEFAULT) {
941698d9ebfc7e27271852a1fdf305a2ac37b3ebe4Matt Fischer        sym = lookup(symbol, &found, NULL);
951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    } else if(handle == RTLD_NEXT) {
961698d9ebfc7e27271852a1fdf305a2ac37b3ebe4Matt Fischer        void *ret_addr = __builtin_return_address(0);
971698d9ebfc7e27271852a1fdf305a2ac37b3ebe4Matt Fischer        soinfo *si = find_containing_library(ret_addr);
981698d9ebfc7e27271852a1fdf305a2ac37b3ebe4Matt Fischer
991698d9ebfc7e27271852a1fdf305a2ac37b3ebe4Matt Fischer        sym = NULL;
1001698d9ebfc7e27271852a1fdf305a2ac37b3ebe4Matt Fischer        if(si && si->next) {
1011698d9ebfc7e27271852a1fdf305a2ac37b3ebe4Matt Fischer            sym = lookup(symbol, &found, si->next);
1021698d9ebfc7e27271852a1fdf305a2ac37b3ebe4Matt Fischer        }
1031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    } else {
1049ea64da6c511e8f9f4edae4c10c20879957631abIliyan Malchev        found = (soinfo*)handle;
1059ea64da6c511e8f9f4edae4c10c20879957631abIliyan Malchev        sym = lookup_in_library(found, symbol);
1061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    }
1071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    if(likely(sym != 0)) {
1091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        bind = ELF32_ST_BIND(sym->st_info);
1102e85579c34047c305caf15fb0ebe02bf3d001d0eDima Zavin
1111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if(likely((bind == STB_GLOBAL) && (sym->st_shndx != 0))) {
1129ea64da6c511e8f9f4edae4c10c20879957631abIliyan Malchev            unsigned ret = sym->st_value + found->base;
1131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            pthread_mutex_unlock(&dl_lock);
1141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return (void*)ret;
1151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        }
1161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1172e85579c34047c305caf15fb0ebe02bf3d001d0eDima Zavin        set_dlerror(DL_ERR_SYMBOL_NOT_GLOBAL);
1181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    }
1192e85579c34047c305caf15fb0ebe02bf3d001d0eDima Zavin    else
1202e85579c34047c305caf15fb0ebe02bf3d001d0eDima Zavin        set_dlerror(DL_ERR_SYMBOL_NOT_FOUND);
1211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projecterr:
1231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    pthread_mutex_unlock(&dl_lock);
1241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    return 0;
1251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
1261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
127bda5da074eab4bdf374e1f4a19d480c62c72f5ffMathias Agopianint dladdr(const void *addr, Dl_info *info)
128e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer{
129e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer    int ret = 0;
130e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer
131e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer    pthread_mutex_lock(&dl_lock);
132e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer
133e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer    /* Determine if this address can be found in any library currently mapped */
134e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer    soinfo *si = find_containing_library(addr);
135e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer
136e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer    if(si) {
137e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer        memset(info, 0, sizeof(Dl_info));
138e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer
139e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer        info->dli_fname = si->name;
140e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer        info->dli_fbase = (void*)si->base;
141e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer
142e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer        /* Determine if any symbol in the library contains the specified address */
143e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer        Elf32_Sym *sym = find_containing_symbol(addr, si);
144e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer
145e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer        if(sym != NULL) {
146e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer            info->dli_sname = si->strtab + sym->st_name;
147e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer            info->dli_saddr = (void*)(si->base + sym->st_value);
148e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer        }
149e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer
150e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer        ret = 1;
151e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer    }
152e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer
153e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer    pthread_mutex_unlock(&dl_lock);
154e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer
155e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer    return ret;
156e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer}
157e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer
1581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint dlclose(void *handle)
1591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
1601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    pthread_mutex_lock(&dl_lock);
1611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    (void)unload_library((soinfo*)handle);
1621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    pthread_mutex_unlock(&dl_lock);
1631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    return 0;
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
1721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#elif defined(ANDROID_X86_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"
1771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
178ad13c57298e57d33c130fb03a2c6494da573408cShin-ichiro KAWASAKI#elif defined(ANDROID_SH_LINKER)
179e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer//                     0000000 00011111 111112 22222222 2333333 3333444444444455
180e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer//                     0123456 78901234 567890 12345678 9012345 6789012345678901
181ad13c57298e57d33c130fb03a2c6494da573408cShin-ichiro KAWASAKI#define ANDROID_LIBDL_STRTAB \
182e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer                      "dlopen\0dlclose\0dlsym\0dlerror\0dladdr\0dl_iterate_phdr\0"
183ad13c57298e57d33c130fb03a2c6494da573408cShin-ichiro KAWASAKI
1841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#else /* !defined(ANDROID_ARM_LINKER) && !defined(ANDROID_X86_LINKER) */
1851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#error Unsupported architecture. Only ARM and x86 are presently supported.
1861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
1871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic Elf32_Sym libdl_symtab[] = {
1901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project      // total length of libdl_info.strtab, including trailing 0
1911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project      // This is actually the the STH_UNDEF entry. Technically, it's
1921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project      // supposed to have st_name == 0, but instead, it points to an index
1931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project      // in the strtab with a \0 to make iterating through the symtab easier.
1941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    { st_name: sizeof(ANDROID_LIBDL_STRTAB) - 1,
1951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    },
1961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    { st_name: 0,   // starting index of the name in libdl_info.strtab
1971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project      st_value: (Elf32_Addr) &dlopen,
1981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project      st_info: STB_GLOBAL << 4,
1991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project      st_shndx: 1,
2001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    },
2011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    { st_name: 7,
2021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project      st_value: (Elf32_Addr) &dlclose,
2031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project      st_info: STB_GLOBAL << 4,
2041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project      st_shndx: 1,
2051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    },
2061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    { st_name: 15,
2071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project      st_value: (Elf32_Addr) &dlsym,
2081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project      st_info: STB_GLOBAL << 4,
2091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project      st_shndx: 1,
2101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    },
2111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    { st_name: 21,
2121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project      st_value: (Elf32_Addr) &dlerror,
2131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project      st_info: STB_GLOBAL << 4,
2141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project      st_shndx: 1,
2151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    },
2161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    { st_name: 29,
217e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer      st_value: (Elf32_Addr) &dladdr,
218e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer      st_info: STB_GLOBAL << 4,
219e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer      st_shndx: 1,
220e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer    },
221e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer#ifdef ANDROID_ARM_LINKER
222e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer    { st_name: 36,
2231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project      st_value: (Elf32_Addr) &dl_unwind_find_exidx,
2241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project      st_info: STB_GLOBAL << 4,
2251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project      st_shndx: 1,
2261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    },
2271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#elif defined(ANDROID_X86_LINKER)
228e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer    { st_name: 36,
2291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project      st_value: (Elf32_Addr) &dl_iterate_phdr,
2301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project      st_info: STB_GLOBAL << 4,
231ad13c57298e57d33c130fb03a2c6494da573408cShin-ichiro KAWASAKI      st_shndx: 1,
232ad13c57298e57d33c130fb03a2c6494da573408cShin-ichiro KAWASAKI    },
233ad13c57298e57d33c130fb03a2c6494da573408cShin-ichiro KAWASAKI#elif defined(ANDROID_SH_LINKER)
234e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer    { st_name: 36,
235ad13c57298e57d33c130fb03a2c6494da573408cShin-ichiro KAWASAKI      st_value: (Elf32_Addr) &dl_iterate_phdr,
236ad13c57298e57d33c130fb03a2c6494da573408cShin-ichiro KAWASAKI      st_info: STB_GLOBAL << 4,
2371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project      st_shndx: 1,
2381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    },
2391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
2401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project};
2411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* Fake out a hash table with a single bucket.
2431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * A search of the hash table will look through
2441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * libdl_symtab starting with index [1], then
2451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * use libdl_chains to find the next index to
2461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * look at.  libdl_chains should be set up to
2471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * walk through every element in libdl_symtab,
2481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * and then end with 0 (sentinel value).
2491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
2501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * I.e., libdl_chains should look like
2511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * { 0, 2, 3, ... N, 0 } where N is the number
2521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * of actual symbols, or nelems(libdl_symtab)-1
2531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * (since the first element of libdl_symtab is not
2541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * a real symbol).
2551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
2561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * (see _elf_lookup())
2571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
2581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Note that adding any new symbols here requires
2591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * stubbing them out in libdl.
2601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
2611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic unsigned libdl_buckets[1] = { 1 };
262e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischerstatic unsigned libdl_chains[7] = { 0, 2, 3, 4, 5, 6, 0 };
2631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectsoinfo libdl_info = {
2651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    name: "libdl.so",
2661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    flags: FLAG_LINKED,
2671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    strtab: ANDROID_LIBDL_STRTAB,
2691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    symtab: libdl_symtab,
2701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    nbucket: 1,
272e2a8b1fd19fb3a8ead2ba28ddba27be19fa978b5Matt Fischer    nchain: 7,
2731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    bucket: libdl_buckets,
2741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    chain: libdl_chains,
2751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project};
2761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
277