Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 2999 → Rev 3000

/branches/dynload/uspace/lib/rtld/symbol.c
117,36 → 117,83
*/
elf_symbol_t *symbol_def_find(char *name, module_t *origin, module_t **mod)
{
module_t *m;
elf_symbol_t *sym;
module_t *m, *dm;
elf_symbol_t *sym, *s;
link_t queue_head;
size_t i;
 
/* FIXME: support DT_SYMBOLIC */
//m = origin;
if (origin->dyn.symbolic) {
/*
* Origin module has a DT_SYMBOLIC flag.
* Try this module first
*/
s = def_find_in_module(name, origin);
if (s != NULL) {
/* Found */
*mod = origin;
return s;
}
}
 
/* Start in the executable program */
m = runtime_env.program;
/* Otherwise start in the executable program */
 
while (true) {
sym = def_find_in_module(name, m);
if (sym != NULL) {
/*
* Do a BFS using the queue_link and bfs_tag fields.
* Vertices (modules) are tagged the moment they are inserted
* into the queue. This prevents from visiting the same vertex
* more times in case of circular dependencies.
*/
 
/* Mark all vertices (modules) as unvisited */
modules_untag();
 
/* Insert root (the program) into the queue and tag it */
list_initialize(&queue_head);
runtime_env.program->bfs_tag = true;
list_append(&runtime_env.program->queue_link, &queue_head);
 
/* If the symbol is found, it will be stored in 'sym' */
sym = NULL;
 
/* While queue is not empty */
while (!list_empty(&queue_head)) {
/* Pop first element from the queue */
m = list_get_instance(queue_head.next, module_t, queue_link);
list_remove(&m->queue_link);
 
s = def_find_in_module(name, m);
if (s != NULL) {
/* Symbol found */
sym = s;
*mod = m;
return sym;
break;
}
 
if (m->n_deps < 1) break;
/*
* Insert m's untagged dependencies into the queue
* and tag them.
*/
for (i = 0; i < m->n_deps; ++i) {
dm = m->deps[i];
 
/* FIXME: support branching */
if (m->n_deps > 1) {
printf("error: BFS unimplemented\n");
exit(1);
if (dm->bfs_tag == false) {
dm->bfs_tag = true;
list_append(&dm->queue_link, &queue_head);
}
}
}
 
m = m->deps[0];
/* Empty the queue so that we leave it in a clean state */
while (!list_empty(&queue_head))
list_remove(queue_head.next);
 
if (!sym) {
printf("Error, symbol '%s' not found anywhere\n", name);
exit(1);
return NULL; /* Not found */
}
 
printf("Error, symbol '%s' not found anywhere\n", name);
exit(1);
return NULL; /* Not found */
return sym; /* Symbol found */
}
 
uintptr_t symbol_get_addr(elf_symbol_t *sym, module_t *m)