module.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2008 Jiri Svoboda
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  * - Redistributions in binary form must reproduce the above copyright
00012  *   notice, this list of conditions and the following disclaimer in the
00013  *   documentation and/or other materials provided with the distribution.
00014  * - The name of the author may not be used to endorse or promote products
00015  *   derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00019  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00020  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00022  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00023  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00024  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00026  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  */
00028 
00037 #include <stdio.h>
00038 #include <stdlib.h>
00039 #include <unistd.h>
00040 #include <fcntl.h>
00041 #include <adt/list.h>
00042 #include <loader/pcb.h>
00043 
00044 #include <rtld/rtld.h>
00045 #include <rtld/rtld_debug.h>
00046 #include <rtld/dynamic.h>
00047 #include <rtld/rtld_arch.h>
00048 #include <rtld/module.h>
00049 #include <elf_load.h>
00050 
00055 void module_process_relocs(module_t *m)
00056 {
00057         DPRINTF("module_process_relocs('%s')\n", m->dyn.soname);
00058 
00059         /* Do not relocate twice. */
00060         if (m->relocated) return;
00061 
00062         module_process_pre_arch(m);
00063 
00064         if (m->dyn.plt_rel == DT_REL) {
00065                 DPRINTF("table type DT_REL\n");
00066                 if (m->dyn.rel != NULL) {
00067                         DPRINTF("non-empty\n");
00068                         rel_table_process(m, m->dyn.rel, m->dyn.rel_sz);
00069                 }
00070                 /* FIXME: this seems wrong */
00071                 if (m->dyn.jmp_rel != NULL) {
00072                 DPRINTF("table type jmp-rel\n");
00073                         DPRINTF("non-empty\n");
00074                         rel_table_process(m, m->dyn.jmp_rel, m->dyn.plt_rel_sz);
00075                 }
00076         } else { /* (m->dyn.plt_rel == DT_RELA) */
00077                 DPRINTF("table type DT_RELA\n");
00078                 if (m->dyn.rela != NULL) {
00079                         DPRINTF("non-empty\n");
00080                         rela_table_process(m, m->dyn.rela, m->dyn.rela_sz);
00081                 }
00082         }
00083 
00084         m->relocated = true;
00085 }
00086 
00093 module_t *module_find(const char *name)
00094 {
00095         link_t *head = &runtime_env->modules_head;
00096 
00097         link_t *cur;
00098         module_t *m;
00099         const char *p, *soname;
00100 
00101         DPRINTF("module_find('%s')\n", name);
00102 
00103         /*
00104          * If name contains slashes, treat it as a pathname and
00105          * construct soname by chopping off the path. Otherwise
00106          * treat it as soname.
00107          */
00108         p = str_rchr(name, '/');
00109         soname = p ? (p + 1) : name;
00110 
00111         /* Traverse list of all modules. Not extremely fast, but simple */
00112         DPRINTF("head = %p\n", head);
00113         for (cur = head->next; cur != head; cur = cur->next) {
00114                 DPRINTF("cur = %p\n", cur);
00115                 m = list_get_instance(cur, module_t, modules_link);
00116                 if (str_cmp(m->dyn.soname, soname) == 0) {
00117                         return m; /* Found */
00118                 }
00119         }
00120         
00121         return NULL; /* Not found */
00122 }
00123 
00124 #define NAME_BUF_SIZE 64
00125 
00130 module_t *module_load(const char *name)
00131 {
00132         elf_info_t info;
00133         char name_buf[NAME_BUF_SIZE];
00134         module_t *m;
00135         int rc;
00136         
00137         m = malloc(sizeof(module_t));
00138         if (!m) {
00139                 printf("malloc failed\n");
00140                 exit(1);
00141         }
00142 
00143         if (str_size(name) > NAME_BUF_SIZE - 2) {
00144                 printf("soname too long. increase NAME_BUF_SIZE\n");
00145                 exit(1);
00146         }
00147 
00148         /* Prepend soname with '/lib/' */
00149         str_cpy(name_buf, NAME_BUF_SIZE, "/lib/");
00150         str_cpy(name_buf + 5, NAME_BUF_SIZE - 5, name);
00151 
00152         /* FIXME: need to real allocation of address space */
00153         m->bias = runtime_env->next_bias;
00154         runtime_env->next_bias += 0x100000;
00155 
00156         DPRINTF("filename:'%s'\n", name_buf);
00157         DPRINTF("load '%s' at 0x%x\n", name_buf, m->bias);
00158 
00159         rc = elf_load_file(name_buf, m->bias, ELDF_RW, &info);
00160         if (rc != EE_OK) {
00161                 printf("Failed to load '%s'\n", name_buf);
00162                 exit(1);
00163         }
00164 
00165         if (info.dynamic == NULL) {
00166                 printf("Error: '%s' is not a dynamically-linked object.\n",
00167                     name_buf);
00168                 exit(1);
00169         }
00170 
00171         /* Pending relocation. */
00172         m->relocated = false;
00173 
00174         DPRINTF("parse dynamic section\n");
00175         /* Parse ELF .dynamic section. Store info to m->dyn. */
00176         dynamic_parse(info.dynamic, m->bias, &m->dyn);
00177 
00178         /* Insert into the list of loaded modules */
00179         list_append(&m->modules_link, &runtime_env->modules_head);
00180 
00181         return m;
00182 }
00183 
00186 void module_load_deps(module_t *m)
00187 {
00188         elf_dyn_t *dp;
00189         char *dep_name;
00190         module_t *dm;
00191         size_t n, i;
00192 
00193         DPRINTF("module_load_deps('%s')\n", m->dyn.soname);
00194 
00195         /* Count direct dependencies */
00196         
00197         dp = m->dyn.dynamic;
00198         n = 0;
00199 
00200         while (dp->d_tag != DT_NULL) {
00201                 if (dp->d_tag == DT_NEEDED) ++n;
00202                 ++dp;
00203         }
00204 
00205         /* Create an array of pointers to direct dependencies */
00206 
00207         m->n_deps = n;
00208 
00209         if (n == 0) {
00210                 /* There are no dependencies, so we are done. */
00211                 m->deps = NULL;
00212                 return;
00213         }
00214 
00215         m->deps = malloc(n * sizeof(module_t *));
00216         if (!m->deps) {
00217                 printf("malloc failed\n");
00218                 exit(1);
00219         }
00220 
00221         i = 0; /* Current dependency index */
00222         dp = m->dyn.dynamic;
00223 
00224         while (dp->d_tag != DT_NULL) {
00225                 if (dp->d_tag == DT_NEEDED) {
00226                         dep_name = m->dyn.str_tab + dp->d_un.d_val;
00227 
00228                         DPRINTF("%s needs %s\n", m->dyn.soname, dep_name);
00229                         dm = module_find(dep_name);
00230                         if (!dm) {
00231                                 dm = module_load(dep_name);
00232                                 module_load_deps(dm);
00233                         }
00234 
00235                         /* Save into deps table */
00236                         m->deps[i++] = dm;
00237                 }
00238                 ++dp;
00239         }
00240 }
00241 
00249 void modules_process_relocs(module_t *start)
00250 {
00251         link_t *head = &runtime_env->modules_head;
00252 
00253         link_t *cur;
00254         module_t *m;
00255 
00256         for (cur = head->next; cur != head; cur = cur->next) {
00257                 m = list_get_instance(cur, module_t, modules_link);
00258 
00259                 /* Skip rtld, since it has already been processed */
00260                 if (m != &runtime_env->rtld) {
00261                         module_process_relocs(m);
00262                 }
00263         }
00264 }
00265 
00268 void modules_untag(void)
00269 {
00270         link_t *head = &runtime_env->modules_head;
00271 
00272         link_t *cur;
00273         module_t *m;
00274 
00275         for (cur = head->next; cur != head; cur = cur->next) {
00276                 m = list_get_instance(cur, module_t, modules_link);
00277                 m->bfs_tag = false;
00278         }
00279 }
00280 

Generated on Thu Jun 2 07:45:46 2011 for HelenOS/USB by  doxygen 1.4.7