/branches/dynload/uspace/lib/rtld/include/module.h |
---|
50,14 → 50,20 |
/** Link to list of all modules in runtime environment */ |
link_t modules_link; |
/** Link to BFS queue. Only used when doing a BFS of the module graph */ |
link_t queue_link; |
/** Tag for modules already processed during a BFS */ |
bool bfs_tag; |
} module_t; |
void module_process_relocs(module_t *m); |
module_t *module_find(char *soname); |
module_t *module_load(char *soname); |
module_t *module_find(char *name); |
module_t *module_load(char *name); |
void module_load_deps(module_t *m); |
void modules_process_relocs(void); |
void modules_untag(void); |
#endif |
/branches/dynload/uspace/lib/rtld/module.c |
---|
69,20 → 69,29 |
} |
} |
/** Find module structure by soname. |
/** Find module structure by soname/pathname. |
* |
* Used primarily to see if a module has already been loaded. |
* Modules are compared according to their soname, i.e. possible |
* path components are ignored. |
*/ |
module_t *module_find(char *soname) |
module_t *module_find(char *name) |
{ |
link_t *head = &runtime_env.modules_head; |
link_t *cur; |
module_t *m; |
char *p, *soname; |
/* FIXME!! */ |
if (soname[0] == '.') return &runtime_env.rtld; |
/* |
* If name contains slashes, treat it as a pathname and |
* construct soname by chopping off the path. Otherwise |
* treat it as soname. |
*/ |
p = strrchr(name, '/'); |
soname = p ? (p + 1) : name; |
/* Traverse list of all modules. Not extremely fast, but simple */ |
for (cur = head->next; cur != head; cur = cur->next) { |
m = list_get_instance(cur, module_t, modules_link); |
if (strcmp(m->dyn.soname, soname) == 0) { |
97,9 → 106,9 |
/** Load a module. |
* |
* Currently this trivially tries to load '/<soname>'. |
* Currently this trivially tries to load '/<name>'. |
*/ |
module_t *module_load(char *soname) |
module_t *module_load(char *name) |
{ |
elf_info_t info; |
char name_buf[NAME_BUF_SIZE]; |
112,9 → 121,7 |
exit(1); |
} |
printf("Requested load of module '%s'\n", soname); |
if (strlen(soname) > NAME_BUF_SIZE - 2) { |
if (strlen(name) > NAME_BUF_SIZE - 2) { |
printf("soname too long. increase NAME_BUF_SIZE\n"); |
exit(1); |
} |
121,7 → 128,7 |
/* Prepend soname with slash */ |
name_buf[0] = '/'; |
strcpy(name_buf + 1, soname); |
strcpy(name_buf + 1, name); |
/* FIXME: need to vary bias / allocate address space */ |
m->bias = 0x20000; |
136,7 → 143,6 |
printf("parse dynamic section\n"); |
/* Parse ELF .dynamic section. Store info to m->dyn. */ |
dynamic_parse(info.dynamic, m->bias, &m->dyn); |
printf("...\n"); |
/* Insert into the list of loaded modules */ |
list_append(&m->modules_link, &runtime_env.modules_head); |
149,7 → 155,7 |
void module_load_deps(module_t *m) |
{ |
elf_dyn_t *dp; |
char *dep_soname; |
char *dep_name; |
module_t *dm; |
size_t n, i; |
181,12 → 187,12 |
while (dp->d_tag != DT_NULL) { |
if (dp->d_tag == DT_NEEDED) { |
dep_soname = m->dyn.str_tab + dp->d_un.d_val; |
printf("needed:'%s'\n", dep_soname); |
dep_name = m->dyn.str_tab + dp->d_un.d_val; |
dm = module_find(dep_soname); |
printf("%s needs %s\n", m->dyn.soname, dep_name); |
dm = module_find(dep_name); |
if (!dm) { |
dm = module_load(dep_soname); |
dm = module_load(dep_name); |
module_load_deps(dm); |
} |
214,5 → 220,20 |
} |
} |
/** Clear BFS tags of all modules. |
*/ |
void modules_untag(void) |
{ |
link_t *head = &runtime_env.modules_head; |
link_t *cur; |
module_t *m; |
for (cur = head->next; cur != head; cur = cur->next) { |
m = list_get_instance(cur, module_t, modules_link); |
m->bfs_tag = false; |
} |
} |
/** @} |
*/ |
/branches/dynload/uspace/lib/rtld/rtld.c |
---|
50,11 → 50,8 |
void _rtld_main(void) |
{ |
pcb_t *pcb; |
elf_info_t lib_info; |
static module_t prog; |
static module_t lib; |
module_t *rtld; |
int rc; |
printf("Hello, world! (from rtld)\n"); |
/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) |
/branches/dynload/uspace/lib/rtld/Makefile |
---|
38,10 → 38,9 |
include arch/$(ARCH)/Makefile.inc |
CFLAGS += -I../../app/iloader/include -Iinclude -fPIC -O0 -ggdb |
LFLAGS += -shared --no-undefined |
LFLAGS += -shared --no-undefined -soname rtld.so |
LIBS = $(LIBC_PREFIX)/libc.pic.a $(SOFTINT_PREFIX)/libsoftint.pic.a |
# LIBS = |
DEFS += -DRELEASE=\"$(RELEASE)\" |
ifdef REVISION |