Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/generic/rtld/symbol.c

    r9d58539 rd2bb25e7  
    3939
    4040#include <elf/elf.h>
     41#include <rtld/module.h>
    4142#include <rtld/rtld.h>
    4243#include <rtld/rtld_debug.h>
     
    114115 *                      that contains the symbol.
    115116 */
    116 elf_symbol_t *symbol_bfs_find(const char *name, module_t *start, module_t **mod)
     117elf_symbol_t *symbol_bfs_find(const char *name, module_t *start,
     118    module_t **mod)
    117119{
    118120        module_t *m, *dm;
     
    129131
    130132        /* Mark all vertices (modules) as unvisited */ 
    131         modules_untag();
     133        modules_untag(start->rtld);
    132134
    133135        /* Insert root (the program) into the queue and tag it */
     
    145147                list_remove(&m->queue_link);
    146148
     149                /* If ssf_noroot is specified, do not look in start module */
    147150                s = def_find_in_module(name, m);
    148151                if (s != NULL) {
     
    179182
    180183
    181 /** Find the definition of a symbol..
     184/** Find the definition of a symbol.
    182185 *
    183186 * By definition in System V ABI, if module origin has the flag DT_SYMBOLIC,
    184  * origin is searched first. Otherwise, or if the symbol hasn't been found,
    185  * the module dependency graph is searched breadth-first, beginning
    186  * from the executable program.
     187 * origin is searched first. Otherwise, search global modules in the default
     188 * order.
    187189 *
    188190 * @param name          Name of the symbol to search for.
    189191 * @param origin        Module in which the dependency originates.
     192 * @param flags         @c ssf_none or @c ssf_noexec to not look for the symbol
     193 *                      in the executable program.
    190194 * @param mod           (output) Will be filled with a pointer to the module
    191195 *                      that contains the symbol.
    192196 */
    193 elf_symbol_t *symbol_def_find(const char *name, module_t *origin, module_t **mod)
     197elf_symbol_t *symbol_def_find(const char *name, module_t *origin,
     198    symbol_search_flags_t flags, module_t **mod)
    194199{
    195200        elf_symbol_t *s;
    196201
    197         if (origin->dyn.symbolic) {
    198                 /*
     202        DPRINTF("symbol_def_find('%s', origin='%s'\n",
     203            name, origin->dyn.soname);
     204        if (origin->dyn.symbolic && (!origin->exec || (flags & ssf_noexec) == 0)) {
     205                DPRINTF("symbolic->find '%s' in module '%s'\n", name, origin->dyn.soname);
     206                /*
    199207                 * Origin module has a DT_SYMBOLIC flag.
    200208                 * Try this module first
    201209                 */
    202                  s = def_find_in_module(name, origin);
    203                  if (s != NULL) {
     210                s = def_find_in_module(name, origin);
     211                if (s != NULL) {
    204212                        /* Found */
    205213                        *mod = origin;
    206214                        return s;
    207                  }
     215                }
    208216        }
    209217
    210218        /* Not DT_SYMBOLIC or no match. Now try other locations. */
    211219
    212         if (runtime_env->program) {
    213                 /* Program is dynamic -- start with program as root. */
    214                 return symbol_bfs_find(name, runtime_env->program, mod);
    215         } else {
    216                 /* Program is static -- start with @a origin as root. */
    217                 return symbol_bfs_find(name, origin, mod);
    218         }
    219 }
    220 
    221 void *symbol_get_addr(elf_symbol_t *sym, module_t *m)
    222 {
    223         if (sym->st_shndx == SHN_ABS) {
     220        list_foreach(origin->rtld->modules, modules_link, module_t, m) {
     221                DPRINTF("module '%s' local?\n", m->dyn.soname);
     222                if (!m->local && (!m->exec || (flags & ssf_noexec) == 0)) {
     223                        DPRINTF("!local->find '%s' in module '%s'\n", name, m->dyn.soname);
     224                        s = def_find_in_module(name, m);
     225                        if (s != NULL) {
     226                                /* Found */
     227                                *mod = m;
     228                                return s;
     229                        }
     230                }
     231        }
     232
     233        /* Finally, try origin. */
     234
     235        DPRINTF("try finding '%s' in origin '%s'\n", name,
     236            origin->dyn.soname);
     237
     238        if (!origin->exec || (flags & ssf_noexec) == 0) {
     239                s = def_find_in_module(name, origin);
     240                if (s != NULL) {
     241                        /* Found */
     242                        *mod = origin;
     243                        return s;
     244                }
     245        }
     246
     247        DPRINTF("'%s' not found\n", name);
     248        return NULL;
     249}
     250
     251/** Get symbol address.
     252 *
     253 * @param sym Symbol
     254 * @param m Module contaning the symbol
     255 * @param tcb TCB of the thread whose thread-local variable instance should
     256 *            be returned. If @a tcb is @c NULL then @c NULL is returned for
     257 *            thread-local variables.
     258 *
     259 * @return Symbol address
     260 */
     261void *symbol_get_addr(elf_symbol_t *sym, module_t *m, tcb_t *tcb)
     262{
     263        if (ELF_ST_TYPE(sym->st_info) == STT_TLS) {
     264                if (tcb == NULL)
     265                        return NULL;
     266                return rtld_tls_get_addr(m->rtld, tcb, m->id, sym->st_value);
     267        } else if (sym->st_shndx == SHN_ABS) {
    224268                /* Do not add bias to absolute symbols */
    225269                return (void *) sym->st_value;
Note: See TracChangeset for help on using the changeset viewer.