Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 2999 → Rev 3000

/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