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) |