source: mainline/uspace/lib/c/generic/rtld/module.c@ 1d6dd2a

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 1d6dd2a was 1d6dd2a, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 7 years ago

Remove unnecessary includes from <stdio.h>.

  • Property mode set to 100644
File size: 8.5 KB
RevLine 
[1ea99cc]1/*
2 * Copyright (c) 2008 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup rtld rtld
30 * @brief
31 * @{
32 */
33/**
34 * @file
35 */
36
[bfdb5af1]37#include <adt/list.h>
38#include <elf/elf_load.h>
[6adb775f]39#include <errno.h>
[bfdb5af1]40#include <loader/pcb.h>
[1ea99cc]41#include <stdio.h>
42#include <stdlib.h>
[1d6dd2a]43#include <str.h>
[1ea99cc]44
[8a1fb09]45#include <rtld/rtld.h>
46#include <rtld/rtld_debug.h>
47#include <rtld/dynamic.h>
48#include <rtld/rtld_arch.h>
49#include <rtld/module.h>
[1ea99cc]50
[153c7a29]51/** Create module for static executable.
52 *
53 * @param rtld Run-time dynamic linker
54 * @param rmodule Place to store pointer to new module or @c NULL
55 * @return EOK on success, ENOMEM if out of memory
56 */
[b7fd2a0]57errno_t module_create_static_exec(rtld_t *rtld, module_t **rmodule)
[153c7a29]58{
59 module_t *module;
60
61 module = calloc(1, sizeof(module_t));
62 if (module == NULL)
63 return ENOMEM;
64
65 module->id = rtld_get_next_id(rtld);
66 module->dyn.soname = "[program]";
67
68 module->rtld = rtld;
69 module->exec = true;
70 module->local = true;
71
72 module->tdata = &_tdata_start;
73 module->tdata_size = &_tdata_end - &_tdata_start;
74 module->tbss_size = &_tbss_end - &_tbss_start;
75 module->tls_align = (uintptr_t)&_tls_alignment;
76
77 list_append(&module->modules_link, &rtld->modules);
78
79 if (rmodule != NULL)
80 *rmodule = module;
81 return EOK;
82}
83
[1ea99cc]84/** (Eagerly) process all relocation tables in a module.
85 *
86 * Currently works as if LD_BIND_NOW was specified.
87 */
88void module_process_relocs(module_t *m)
89{
90 DPRINTF("module_process_relocs('%s')\n", m->dyn.soname);
91
92 /* Do not relocate twice. */
93 if (m->relocated) return;
94
95 module_process_pre_arch(m);
96
[634e020]97 /* jmp_rel table */
98 if (m->dyn.jmp_rel != NULL) {
99 DPRINTF("jmp_rel table\n");
100 if (m->dyn.plt_rel == DT_REL) {
101 DPRINTF("jmp_rel table type DT_REL\n");
[1ea99cc]102 rel_table_process(m, m->dyn.jmp_rel, m->dyn.plt_rel_sz);
[634e020]103 } else {
104 assert(m->dyn.plt_rel == DT_RELA);
105 DPRINTF("jmp_rel table type DT_RELA\n");
106 rela_table_process(m, m->dyn.jmp_rel, m->dyn.plt_rel_sz);
[1ea99cc]107 }
[634e020]108 }
109
110 /* rel table */
111 if (m->dyn.rel != NULL) {
112 DPRINTF("rel table\n");
113 rel_table_process(m, m->dyn.rel, m->dyn.rel_sz);
114 }
115
116 /* rela table */
117 if (m->dyn.rela != NULL) {
118 DPRINTF("rela table\n");
119 rela_table_process(m, m->dyn.rela, m->dyn.rela_sz);
[1ea99cc]120 }
121
122 m->relocated = true;
123}
124
125/** Find module structure by soname/pathname.
126 *
127 * Used primarily to see if a module has already been loaded.
128 * Modules are compared according to their soname, i.e. possible
129 * path components are ignored.
130 */
[17341d4]131module_t *module_find(rtld_t *rtld, const char *name)
[1ea99cc]132{
[04803bf]133 const char *p, *soname;
[1ea99cc]134
[a6dffb8]135 DPRINTF("module_find('%s')\n", name);
136
[1ea99cc]137 /*
138 * If name contains slashes, treat it as a pathname and
139 * construct soname by chopping off the path. Otherwise
140 * treat it as soname.
141 */
142 p = str_rchr(name, '/');
143 soname = p ? (p + 1) : name;
144
145 /* Traverse list of all modules. Not extremely fast, but simple */
[17341d4]146 list_foreach(rtld->modules, modules_link, module_t, m) {
[4b63316]147 DPRINTF("m = %p\n", m);
[1ea99cc]148 if (str_cmp(m->dyn.soname, soname) == 0) {
149 return m; /* Found */
150 }
151 }
[58563585]152
[1ea99cc]153 return NULL; /* Not found */
154}
155
156#define NAME_BUF_SIZE 64
157
158/** Load a module.
159 *
160 * Currently this trivially tries to load '/<name>'.
161 */
[5035ba05]162module_t *module_load(rtld_t *rtld, const char *name, mlflags_t flags)
[1ea99cc]163{
[17341d4]164 elf_finfo_t info;
[1ea99cc]165 char name_buf[NAME_BUF_SIZE];
166 module_t *m;
167 int rc;
[58563585]168
[6adb775f]169 m = calloc(1, sizeof(module_t));
170 if (m == NULL) {
[1ea99cc]171 printf("malloc failed\n");
172 exit(1);
173 }
[58563585]174
[17341d4]175 m->rtld = rtld;
[6adb775f]176 m->id = rtld_get_next_id(rtld);
[17341d4]177
[5035ba05]178 if ((flags & mlf_local) != 0)
179 m->local = true;
[17341d4]180
[1ea99cc]181 if (str_size(name) > NAME_BUF_SIZE - 2) {
182 printf("soname too long. increase NAME_BUF_SIZE\n");
183 exit(1);
184 }
185
186 /* Prepend soname with '/lib/' */
187 str_cpy(name_buf, NAME_BUF_SIZE, "/lib/");
188 str_cpy(name_buf + 5, NAME_BUF_SIZE - 5, name);
189
190 /* FIXME: need to real allocation of address space */
[17341d4]191 m->bias = rtld->next_bias;
192 rtld->next_bias += 0x100000;
[1ea99cc]193
194 DPRINTF("filename:'%s'\n", name_buf);
[33f86a3]195 DPRINTF("load '%s' at 0x%zx\n", name_buf, m->bias);
[1ea99cc]196
[bb9ec2d]197 rc = elf_load_file_name(name_buf, m->bias, ELDF_RW, &info);
[1ea99cc]198 if (rc != EE_OK) {
199 printf("Failed to load '%s'\n", name_buf);
200 exit(1);
201 }
202
203 if (info.dynamic == NULL) {
204 printf("Error: '%s' is not a dynamically-linked object.\n",
205 name_buf);
206 exit(1);
207 }
208
209 /* Pending relocation. */
210 m->relocated = false;
211
212 DPRINTF("parse dynamic section\n");
213 /* Parse ELF .dynamic section. Store info to m->dyn. */
214 dynamic_parse(info.dynamic, m->bias, &m->dyn);
215
216 /* Insert into the list of loaded modules */
[17341d4]217 list_append(&m->modules_link, &rtld->modules);
[58563585]218
[6adb775f]219 /* Copy TLS info */
220 m->tdata = info.tls.tdata;
221 m->tdata_size = info.tls.tdata_size;
222 m->tbss_size = info.tls.tbss_size;
[29405ac]223 m->tls_align = info.tls.tls_align;
[58563585]224
[153c7a29]225 DPRINTF("tdata at %p size %zu, tbss size %zu\n",
[6adb775f]226 m->tdata, m->tdata_size, m->tbss_size);
227
[1ea99cc]228 return m;
229}
230
231/** Load all modules on which m (transitively) depends.
232 */
[5035ba05]233void module_load_deps(module_t *m, mlflags_t flags)
[1ea99cc]234{
235 elf_dyn_t *dp;
236 char *dep_name;
237 module_t *dm;
238 size_t n, i;
239
[a6dffb8]240 DPRINTF("module_load_deps('%s')\n", m->dyn.soname);
241
[1ea99cc]242 /* Count direct dependencies */
243
244 dp = m->dyn.dynamic;
245 n = 0;
246
247 while (dp->d_tag != DT_NULL) {
248 if (dp->d_tag == DT_NEEDED) ++n;
249 ++dp;
250 }
251
252 /* Create an array of pointers to direct dependencies */
253
254 m->n_deps = n;
255
256 if (n == 0) {
257 /* There are no dependencies, so we are done. */
258 m->deps = NULL;
259 return;
260 }
261
262 m->deps = malloc(n * sizeof(module_t *));
263 if (!m->deps) {
264 printf("malloc failed\n");
265 exit(1);
266 }
267
268 i = 0; /* Current dependency index */
269 dp = m->dyn.dynamic;
270
271 while (dp->d_tag != DT_NULL) {
272 if (dp->d_tag == DT_NEEDED) {
273 dep_name = m->dyn.str_tab + dp->d_un.d_val;
274
275 DPRINTF("%s needs %s\n", m->dyn.soname, dep_name);
[17341d4]276 dm = module_find(m->rtld, dep_name);
[1ea99cc]277 if (!dm) {
[5035ba05]278 dm = module_load(m->rtld, dep_name, flags);
279 module_load_deps(dm, flags);
[1ea99cc]280 }
281
282 /* Save into deps table */
283 m->deps[i++] = dm;
284 }
285 ++dp;
286 }
287}
288
[6adb775f]289/** Find module structure by ID. */
290module_t *module_by_id(rtld_t *rtld, unsigned long id)
291{
292 list_foreach(rtld->modules, modules_link, module_t, m) {
293 if (m->id == id)
294 return m;
295 }
296
297 return NULL;
298}
299
[1ea99cc]300/** Process relocations in modules.
301 *
302 * Processes relocations in @a start and all its dependencies.
303 * Modules that have already been relocated are unaffected.
304 *
305 * @param start The module where to start from.
306 */
[17341d4]307void modules_process_relocs(rtld_t *rtld, module_t *start)
[1ea99cc]308{
[17341d4]309 list_foreach(rtld->modules, modules_link, module_t, m) {
310 /* Skip rtld module, since it has already been processed */
311 if (m != &rtld->rtld) {
[1ea99cc]312 module_process_relocs(m);
313 }
314 }
315}
316
[6adb775f]317void modules_process_tls(rtld_t *rtld)
318{
[29405ac]319#ifdef CONFIG_TLS_VARIANT_1
[6adb775f]320 list_foreach(rtld->modules, modules_link, module_t, m) {
321 m->ioffs = rtld->tls_size;
[bab0f42]322 list_append(&m->imodules_link, &rtmd->imodules);
[6adb775f]323 rtld->tls_size += m->tdata_size + m->tbss_size;
324 }
[29405ac]325#else /* CONFIG_TLS_VARIANT_2 */
326 size_t offs;
327
328 list_foreach(rtld->modules, modules_link, module_t, m) {
329 rtld->tls_size += m->tdata_size + m->tbss_size;
330 }
331
332 offs = 0;
333 list_foreach(rtld->modules, modules_link, module_t, m) {
334 offs += m->tdata_size + m->tbss_size;
335 m->ioffs = rtld->tls_size - offs;
[bab0f42]336 list_append(&m->imodules_link, &rtld->imodules);
[29405ac]337 }
338#endif
[6adb775f]339}
340
[1ea99cc]341/** Clear BFS tags of all modules.
342 */
[17341d4]343void modules_untag(rtld_t *rtld)
[1ea99cc]344{
[17341d4]345 list_foreach(rtld->modules, modules_link, module_t, m) {
[1ea99cc]346 m->bfs_tag = false;
347 }
348}
349
350/** @}
351 */
Note: See TracBrowser for help on using the repository browser.