Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 2998 → Rev 2999

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