/branches/dynload/uspace/lib/rtld/include/dynamic.h |
---|
89,6 → 89,9 |
/* Assume for now that there's at most one needed library */ |
char *needed; |
/** Pointer to the module's dynamic section */ |
elf_dyn_t *dynamic; |
} dyn_info_t; |
void dynamic_parse(elf_dyn_t *dyn_ptr, size_t bias, dyn_info_t *info); |
/branches/dynload/uspace/lib/rtld/include/rtld.h |
---|
36,20 → 36,20 |
#define RTLD_H_ |
#include <sys/types.h> |
#include <libadt/list.h> |
#include <dynamic.h> |
#include <module.h> |
typedef struct { |
dyn_info_t dyn; |
size_t bias; |
} module_t; |
typedef struct { |
elf_dyn_t *rtld_dynamic; |
module_t rtld; |
module_t *program; |
module_t *libc; |
/** List of all loaded modules including rtld and the program */ |
link_t modules_head; |
} runtime_env_t; |
void _rtld_main(void); |
/branches/dynload/uspace/lib/rtld/include/symbol.h |
---|
38,7 → 38,7 |
#include <rtld.h> |
#include <elf.h> |
elf_symbol_t *symbol_def_find(char *name, module_t **m); |
elf_symbol_t *symbol_def_find(char *name, module_t *origin, module_t **m); |
uintptr_t symbol_get_addr(elf_symbol_t *sym, module_t *m); |
#endif |
/branches/dynload/uspace/lib/rtld/include/module.h |
---|
0,0 → 1,65 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup generic |
* @{ |
*/ |
/** @file |
*/ |
#ifndef MODULE_H_ |
#define MODULE_H_ |
#include <sys/types.h> |
#include <dynamic.h> |
#include <libadt/list.h> |
typedef struct module { |
dyn_info_t dyn; |
size_t bias; |
/** Array of pointers to directly dependent modules */ |
struct module **deps; |
/** Number of fields in deps */ |
size_t n_deps; |
/** Link to list of all modules in runtime environment */ |
link_t modules_link; |
} module_t; |
void module_process_relocs(module_t *m); |
module_t *module_find(char *soname); |
module_t *module_load(char *soname); |
void module_load_deps(module_t *m); |
void modules_process_relocs(void); |
#endif |
/** @} |
*/ |
/branches/dynload/uspace/lib/rtld/dynamic.c |
---|
94,6 → 94,10 |
info->soname = info->str_tab + soname_idx; |
info->rpath = info->str_tab + rpath_idx; |
/* This will be useful for parsing dependencies later */ |
info->dynamic = dyn_ptr; |
printf("str_tab=0x%x, soname_idx=0x%x, soname=0x%x\n", |
(uintptr_t)info->soname, soname_idx, (uintptr_t)info->soname); |
printf("soname='%s'\n", info->soname); |
/branches/dynload/uspace/lib/rtld/rtld.c |
---|
42,27 → 42,11 |
#include <dynamic.h> |
#include <pcb.h> |
#include <elf_load.h> |
#include <module.h> |
#include <arch.h> |
runtime_env_t runtime_env; |
void module_process_relocs(module_t *m) |
{ |
if (m->dyn.plt_rel == DT_REL) { |
if (m->dyn.rel != NULL) |
rel_table_process(m, m->dyn.rel, m->dyn.rel_sz); |
/* FIXME: this seems wrong */ |
if (m->dyn.jmp_rel != NULL) |
rel_table_process(m, m->dyn.jmp_rel, m->dyn.plt_rel_sz); |
} else { /* (m->dyn.plt_rel == DT_RELA) */ |
printf("table type DT_RELA\n"); |
if (m->dyn.rela != NULL) { |
printf("non-empty\n"); |
rela_table_process(m, m->dyn.rela, m->dyn.rela_sz); |
} |
} |
} |
void _rtld_main(void) |
{ |
pcb_t *pcb; |
73,13 → 57,17 |
int rc; |
printf("Hello, world! (from rtld)\n"); |
// getchar(); |
/* |
* First we need to process dynamic sections of the two modules |
* that have been already loaded, that is, of ourselves and of |
* the executable program. |
*/ |
/* rtld_dynamic and rtld->bias were filled out by the bootstrap code */ |
rtld = &runtime_env.rtld; |
printf("Parse rtld .dynamic section at 0x%x\n", runtime_env.rtld_dynamic); |
dynamic_parse(runtime_env.rtld_dynamic, rtld->bias, &rtld->dyn); |
// getchar(); |
pcb = __pcb_get(); |
printf("Parse program .dynamic section at 0x%x\n", pcb->dynamic); |
87,34 → 75,33 |
prog.bias = 0; |
prog.dyn.soname = "[program]"; |
printf("Program requested library '%s'\n", prog.dyn.needed); |
// getchar(); |
rc = elf_load_file("/libc.so.0", 0x20000, &lib_info); |
if (rc < 0) { |
printf("failed to load library\n"); |
return; |
} |
/* Initialize list of loaded modules */ |
list_initialize(&runtime_env.modules_head); |
list_append(&prog.modules_link, &runtime_env.modules_head); |
list_append(&rtld->modules_link, &runtime_env.modules_head); |
dynamic_parse(lib_info.dynamic, 0x20000, &lib.dyn); |
lib.bias = 0x20000; |
printf("lib.bias=0x%x\n", lib.bias); |
/* Pointer to program module. Used as root of the dependency graph */ |
runtime_env.program = &prog; |
runtime_env.libc = &lib; |
/* Parse program's relocation tables */ |
printf("Resolve references in program\n"); |
module_process_relocs(&prog); |
/* |
* Now we can continue with loading all other modules. |
*/ |
/* Parse lib's relocation tables */ |
printf("Resolve references in library\n"); |
module_process_relocs(&lib); |
printf("Load all program dependencies\n"); |
module_load_deps(&prog); |
printf("lib.bias=0x%x\n", lib.bias); |
/* |
* Now relocate/link all modules together. |
*/ |
/* Process relocations in all modules */ |
printf("Relocate all modules\n"); |
modules_process_relocs(); |
/* |
* Finally, run the main program. |
*/ |
printf("Run program.. (at 0x%x)\n", (uintptr_t)pcb->entry); |
getchar(); |
pcb->entry(); |
} |
/branches/dynload/uspace/lib/rtld/symbol.c |
---|
103,23 → 103,50 |
return sym; /* Found */ |
} |
elf_symbol_t *symbol_def_find(char *name, module_t **m) |
/** Find the definition of a symbol. |
* |
* By definition in System V ABI, if module origin has the flag DT_SYMBOLIC, |
* origin is searched first. Otherwise, or if the symbol hasn't been found, |
* the module dependency graph is searched breadth-first, beginning |
* from the executable program. |
* |
* @param name Name of the symbol to search for. |
* @param origin Module in which the dependency originates. |
* @param mod (output) Will be filled with a pointer to the module |
* that contains the symbol. |
*/ |
elf_symbol_t *symbol_def_find(char *name, module_t *origin, module_t **mod) |
{ |
module_t *m; |
elf_symbol_t *sym; |
sym = def_find_in_module(name, runtime_env.program); |
if (sym != NULL) { *m = runtime_env.program; return sym; } |
/* FIXME: support DT_SYMBOLIC */ |
//m = origin; |
sym = def_find_in_module(name, runtime_env.libc); |
if (sym != NULL) { *m = runtime_env.libc; return sym; } |
/* Start in the executable program */ |
m = runtime_env.program; |
sym = def_find_in_module(name, &runtime_env.rtld); |
if (sym != NULL) { *m = &runtime_env.rtld; return sym; } |
while (true) { |
sym = def_find_in_module(name, m); |
if (sym != NULL) { |
*mod = m; |
return sym; |
} |
printf("symbol found nowhere\n"); |
*m = NULL; |
return NULL; |
if (m->n_deps < 1) break; |
/* FIXME: support branching */ |
if (m->n_deps > 1) { |
printf("error: BFS unimplemented\n"); |
exit(1); |
} |
m = m->deps[0]; |
} |
printf("Error, symbol '%s' not found anywhere\n", name); |
exit(1); |
return NULL; /* Not found */ |
} |
uintptr_t symbol_get_addr(elf_symbol_t *sym, module_t *m) |
/branches/dynload/uspace/lib/rtld/module.c |
---|
0,0 → 1,218 |
/* |
* Copyright (c) 2008 Jiri Svoboda |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** @addtogroup rtld rtld |
* @brief |
* @{ |
*/ |
/** |
* @file |
*/ |
#include <stdio.h> |
#include <stdlib.h> |
#include <unistd.h> |
#include <fcntl.h> |
#include <libadt/list.h> |
#include <rtld.h> |
#include <dynamic.h> |
#include <pcb.h> |
#include <elf_load.h> |
#include <arch.h> |
#include <module.h> |
/** (Eagerly) process all relocation tables in a module. |
* |
* Currently works as if LD_BIND_NOW was specified. |
*/ |
void module_process_relocs(module_t *m) |
{ |
printf("module_process_relocs('%s')\n", m->dyn.soname); |
if (m->dyn.plt_rel == DT_REL) { |
if (m->dyn.rel != NULL) |
rel_table_process(m, m->dyn.rel, m->dyn.rel_sz); |
/* FIXME: this seems wrong */ |
if (m->dyn.jmp_rel != NULL) |
rel_table_process(m, m->dyn.jmp_rel, m->dyn.plt_rel_sz); |
} else { /* (m->dyn.plt_rel == DT_RELA) */ |
printf("table type DT_RELA\n"); |
if (m->dyn.rela != NULL) { |
printf("non-empty\n"); |
rela_table_process(m, m->dyn.rela, m->dyn.rela_sz); |
} |
} |
} |
/** Find module structure by soname. |
* |
* Used primarily to see if a module has already been loaded. |
*/ |
module_t *module_find(char *soname) |
{ |
link_t *head = &runtime_env.modules_head; |
link_t *cur; |
module_t *m; |
/* FIXME!! */ |
if (soname[0] == '.') return &runtime_env.rtld; |
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) { |
return m; /* Found */ |
} |
} |
return NULL; /* Not found */ |
} |
#define NAME_BUF_SIZE 64 |
/** Load a module. |
* |
* Currently this trivially tries to load '/<soname>'. |
*/ |
module_t *module_load(char *soname) |
{ |
elf_info_t info; |
char name_buf[NAME_BUF_SIZE]; |
module_t *m; |
int rc; |
m = malloc(sizeof(module_t)); |
if (!m) { |
printf("malloc failed\n"); |
exit(1); |
} |
printf("Requested load of module '%s'\n", soname); |
if (strlen(soname) > NAME_BUF_SIZE - 2) { |
printf("soname too long. increase NAME_BUF_SIZE\n"); |
exit(1); |
} |
/* Prepend soname with slash */ |
name_buf[0] = '/'; |
strcpy(name_buf + 1, soname); |
/* FIXME: need to vary bias / allocate address space */ |
m->bias = 0x20000; |
printf("filename:'%s'\n", name_buf); |
rc = elf_load_file(name_buf, m->bias, &info); |
if (rc < 0) { |
printf("Failed to load '%s'\n"); |
exit(1); |
} |
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); |
return m; |
} |
/** Load all modules on which m (transitively) depends. |
*/ |
void module_load_deps(module_t *m) |
{ |
elf_dyn_t *dp; |
char *dep_soname; |
module_t *dm; |
size_t n, i; |
/* Count direct dependencies */ |
dp = m->dyn.dynamic; |
n = 0; |
while (dp->d_tag != DT_NULL) { |
if (dp->d_tag == DT_NEEDED) ++n; |
++dp; |
} |
/* Create an array of pointers to direct dependencies */ |
m->n_deps = n; |
if (n > 0) |
m->deps = malloc(n * sizeof(module_t *)); |
else |
m->deps = NULL; |
if (!m->deps) { |
printf("malloc failed\n"); |
exit(1); |
} |
i = 0; /* Current dependency index */ |
dp = m->dyn.dynamic; |
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); |
dm = module_find(dep_soname); |
if (!dm) { |
dm = module_load(dep_soname); |
module_load_deps(dm); |
} |
/* Save into deps table */ |
m->deps[i++] = dm; |
} |
++dp; |
} |
} |
void modules_process_relocs(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); |
/* Skip rtld, since it has already been processed */ |
if (m != &runtime_env.rtld) { |
module_process_relocs(m); |
} |
} |
} |
/** @} |
*/ |
/branches/dynload/uspace/lib/rtld/Makefile |
---|
60,6 → 60,7 |
rtld.c \ |
elf_load.c \ |
dynamic.c \ |
module.c \ |
symbol.c |
GENERIC_OBJECTS := $(addsuffix .o,$(basename $(GENERIC_SOURCES))) |
/branches/dynload/uspace/lib/rtld/arch/ppc32/src/reloc.c |
---|
186,7 → 186,8 |
if (sym->st_name != 0) { |
printf("rel_type: %x, rel_offset: 0x%x\n", rel_type, r_offset); |
sym_def = symbol_def_find(str_tab + sym->st_name, &dest); |
sym_def = symbol_def_find(str_tab + sym->st_name, |
m, &dest); |
printf("dest name: '%s'\n", dest->dyn.soname); |
printf("dest bias: 0x%x\n", dest->bias); |
if (sym_def) { |
/branches/dynload/uspace/lib/rtld/arch/ia32/src/reloc.c |
---|
95,7 → 95,8 |
if (sym->st_name != 0) { |
// printf("rel_type: %x, rel_offset: 0x%x\n", rel_type, r_offset); |
sym_def = symbol_def_find(str_tab + sym->st_name, &dest); |
sym_def = symbol_def_find(str_tab + sym->st_name, |
m, &dest); |
// printf("dest name: '%s'\n", dest->dyn.soname); |
// printf("dest bias: 0x%x\n", dest->bias); |
if (sym_def) { |