rtld.c (df618d033c1d50bde6516eb2d1867745590cb695) rtld.c (d3980376e8c139e07958914c5184ab37463e4818)
1/*-
2 * Copyright 1996, 1997, 1998, 1999 John D. Polstra.
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 * 1. Redistributions of source code must retain the above copyright

--- 38 unchanged lines hidden (view full) ---

47#include <stdio.h>
48#include <stdlib.h>
49#include <string.h>
50#include <unistd.h>
51
52#include "debug.h"
53#include "rtld.h"
54
1/*-
2 * Copyright 1996, 1997, 1998, 1999 John D. Polstra.
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 * 1. Redistributions of source code must retain the above copyright

--- 38 unchanged lines hidden (view full) ---

47#include <stdio.h>
48#include <stdlib.h>
49#include <string.h>
50#include <unistd.h>
51
52#include "debug.h"
53#include "rtld.h"
54
55/*
56 * Debugging support.
57 */
58
59#define assert(cond) ((cond) ? (void) 0 :\
60 (msg("oops: " __XSTRING(__LINE__) "\n"), abort()))
61#define msg(s) (write(1, s, strlen(s)))
62#define trace() msg("trace: " __XSTRING(__LINE__) "\n");
63
64#define END_SYM "_end"
65#define PATH_RTLD "/usr/libexec/ld-elf.so.1"
66
67/* Types. */
68typedef void (*func_ptr_type)();
69
55#define END_SYM "_end"
56#define PATH_RTLD "/usr/libexec/ld-elf.so.1"
57
58/* Types. */
59typedef void (*func_ptr_type)();
60
61typedef struct Struct_LockInfo {
62 void *context; /* Client context for creating locks */
63 void *thelock; /* The one big lock */
64 /* Methods */
65 void (*rlock_acquire)(void *lock);
66 void (*wlock_acquire)(void *lock);
67 void (*lock_release)(void *lock);
68 void (*lock_destroy)(void *lock);
69 void (*context_destroy)(void *context);
70} LockInfo;
71
70/*
71 * Function declarations.
72 */
73static const char *basename(const char *);
74static void call_fini_functions(Obj_Entry *);
75static void call_init_functions(Obj_Entry *);
76static void die(void);
77static void digest_dynamic(Obj_Entry *);

--- 5 unchanged lines hidden (view full) ---

83static void init_dag1(Obj_Entry *root, Obj_Entry *obj);
84static void init_rtld(caddr_t);
85static bool is_exported(const Elf_Sym *);
86static void linkmap_add(Obj_Entry *);
87static void linkmap_delete(Obj_Entry *);
88static int load_needed_objects(Obj_Entry *);
89static int load_preload_objects(void);
90static Obj_Entry *load_object(char *);
72/*
73 * Function declarations.
74 */
75static const char *basename(const char *);
76static void call_fini_functions(Obj_Entry *);
77static void call_init_functions(Obj_Entry *);
78static void die(void);
79static void digest_dynamic(Obj_Entry *);

--- 5 unchanged lines hidden (view full) ---

85static void init_dag1(Obj_Entry *root, Obj_Entry *obj);
86static void init_rtld(caddr_t);
87static bool is_exported(const Elf_Sym *);
88static void linkmap_add(Obj_Entry *);
89static void linkmap_delete(Obj_Entry *);
90static int load_needed_objects(Obj_Entry *);
91static int load_preload_objects(void);
92static Obj_Entry *load_object(char *);
93static void lock_nop(void *);
91static Obj_Entry *obj_from_addr(const void *);
92static void objlist_add(Objlist *, Obj_Entry *);
93static Objlist_Entry *objlist_find(Objlist *, const Obj_Entry *);
94static void objlist_remove(Objlist *, Obj_Entry *);
95static int relocate_objects(Obj_Entry *, bool);
96static void rtld_exit(void);
97static char *search_library_path(const char *, const char *);
98static void set_program_var(const char *, const void *);

--- 24 unchanged lines hidden (view full) ---

123static Obj_Entry obj_rtld; /* The dynamic linker shared object */
124static unsigned long curmark; /* Current mark value */
125
126static Objlist list_global = /* Objects dlopened with RTLD_GLOBAL */
127 STAILQ_HEAD_INITIALIZER(list_global);
128static Objlist list_main = /* Objects loaded at program startup */
129 STAILQ_HEAD_INITIALIZER(list_main);
130
94static Obj_Entry *obj_from_addr(const void *);
95static void objlist_add(Objlist *, Obj_Entry *);
96static Objlist_Entry *objlist_find(Objlist *, const Obj_Entry *);
97static void objlist_remove(Objlist *, Obj_Entry *);
98static int relocate_objects(Obj_Entry *, bool);
99static void rtld_exit(void);
100static char *search_library_path(const char *, const char *);
101static void set_program_var(const char *, const void *);

--- 24 unchanged lines hidden (view full) ---

126static Obj_Entry obj_rtld; /* The dynamic linker shared object */
127static unsigned long curmark; /* Current mark value */
128
129static Objlist list_global = /* Objects dlopened with RTLD_GLOBAL */
130 STAILQ_HEAD_INITIALIZER(list_global);
131static Objlist list_main = /* Objects loaded at program startup */
132 STAILQ_HEAD_INITIALIZER(list_main);
133
134static LockInfo lockinfo;
135
131static Elf_Sym sym_zero; /* For resolving undefined weak refs. */
132
133#define GDB_STATE(s) r_debug.r_state = s; r_debug_state();
134
135extern Elf_Dyn _DYNAMIC;
136#pragma weak _DYNAMIC
137
138/*
139 * These are the functions the dynamic linker exports to application
140 * programs. They are the only symbols the dynamic linker is willing
141 * to export from itself.
142 */
143static func_ptr_type exports[] = {
144 (func_ptr_type) &_rtld_error,
145 (func_ptr_type) &dlclose,
146 (func_ptr_type) &dlerror,
147 (func_ptr_type) &dlopen,
148 (func_ptr_type) &dlsym,
149 (func_ptr_type) &dladdr,
136static Elf_Sym sym_zero; /* For resolving undefined weak refs. */
137
138#define GDB_STATE(s) r_debug.r_state = s; r_debug_state();
139
140extern Elf_Dyn _DYNAMIC;
141#pragma weak _DYNAMIC
142
143/*
144 * These are the functions the dynamic linker exports to application
145 * programs. They are the only symbols the dynamic linker is willing
146 * to export from itself.
147 */
148static func_ptr_type exports[] = {
149 (func_ptr_type) &_rtld_error,
150 (func_ptr_type) &dlclose,
151 (func_ptr_type) &dlerror,
152 (func_ptr_type) &dlopen,
153 (func_ptr_type) &dlsym,
154 (func_ptr_type) &dladdr,
155 (func_ptr_type) &dllockinit,
150 NULL
151};
152
153/*
154 * Global declarations normally provided by crt1. The dynamic linker is
155 * not build with crt1, so we have to provide them ourselves.
156 */
157char *__progname;
158char **environ;
159
156 NULL
157};
158
159/*
160 * Global declarations normally provided by crt1. The dynamic linker is
161 * not build with crt1, so we have to provide them ourselves.
162 */
163char *__progname;
164char **environ;
165
166static __inline void
167rlock_acquire(void)
168{
169 lockinfo.rlock_acquire(lockinfo.thelock);
170}
171
172static __inline void
173wlock_acquire(void)
174{
175 lockinfo.wlock_acquire(lockinfo.thelock);
176}
177
178static __inline void
179lock_release(void)
180{
181 lockinfo.lock_release(lockinfo.thelock);
182}
183
160/*
161 * Main entry point for dynamic linking. The first argument is the
162 * stack pointer. The stack is expected to be laid out as described
163 * in the SVR4 ABI specification, Intel 386 Processor Supplement.
164 * Specifically, the stack pointer points to a word containing
165 * ARGC. Following that in the stack is a null-terminated sequence
166 * of pointers to argument strings. Then comes a null-terminated
167 * sequence of pointers to environment strings. Finally, there is a

--- 149 unchanged lines hidden (view full) ---

317 dbg("doing copy relocations");
318 if (do_copy_relocations(obj_main) == -1)
319 die();
320
321 dbg("initializing key program variables");
322 set_program_var("__progname", argv[0] != NULL ? basename(argv[0]) : "");
323 set_program_var("environ", env);
324
184/*
185 * Main entry point for dynamic linking. The first argument is the
186 * stack pointer. The stack is expected to be laid out as described
187 * in the SVR4 ABI specification, Intel 386 Processor Supplement.
188 * Specifically, the stack pointer points to a word containing
189 * ARGC. Following that in the stack is a null-terminated sequence
190 * of pointers to argument strings. Then comes a null-terminated
191 * sequence of pointers to environment strings. Finally, there is a

--- 149 unchanged lines hidden (view full) ---

341 dbg("doing copy relocations");
342 if (do_copy_relocations(obj_main) == -1)
343 die();
344
345 dbg("initializing key program variables");
346 set_program_var("__progname", argv[0] != NULL ? basename(argv[0]) : "");
347 set_program_var("environ", env);
348
349 dbg("initializing default locks");
350 dllockinit(NULL, NULL, NULL, NULL, NULL, NULL, NULL);
351
325 r_debug_state(); /* say hello to gdb! */
326
327 dbg("calling _init functions");
328 call_init_functions(obj_main->next);
329
330 dbg("transferring control to program entry point = %p", obj_main->entry);
331
332 /* Return the exit procedure and the program entry point. */

--- 6 unchanged lines hidden (view full) ---

339_rtld_bind(Obj_Entry *obj, Elf_Word reloff)
340{
341 const Elf_Rel *rel;
342 const Elf_Sym *def;
343 const Obj_Entry *defobj;
344 Elf_Addr *where;
345 Elf_Addr target;
346
352 r_debug_state(); /* say hello to gdb! */
353
354 dbg("calling _init functions");
355 call_init_functions(obj_main->next);
356
357 dbg("transferring control to program entry point = %p", obj_main->entry);
358
359 /* Return the exit procedure and the program entry point. */

--- 6 unchanged lines hidden (view full) ---

366_rtld_bind(Obj_Entry *obj, Elf_Word reloff)
367{
368 const Elf_Rel *rel;
369 const Elf_Sym *def;
370 const Obj_Entry *defobj;
371 Elf_Addr *where;
372 Elf_Addr target;
373
374 wlock_acquire();
347 if (obj->pltrel)
348 rel = (const Elf_Rel *) ((caddr_t) obj->pltrel + reloff);
349 else
350 rel = (const Elf_Rel *) ((caddr_t) obj->pltrela + reloff);
351
352 where = (Elf_Addr *) (obj->relocbase + rel->r_offset);
353 def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, true);
354 if (def == NULL)
355 die();
356
357 target = (Elf_Addr)(defobj->relocbase + def->st_value);
358
359 dbg("\"%s\" in \"%s\" ==> %p in \"%s\"",
360 defobj->strtab + def->st_name, basename(obj->path),
361 (void *)target, basename(defobj->path));
362
363 reloc_jmpslot(where, target);
375 if (obj->pltrel)
376 rel = (const Elf_Rel *) ((caddr_t) obj->pltrel + reloff);
377 else
378 rel = (const Elf_Rel *) ((caddr_t) obj->pltrela + reloff);
379
380 where = (Elf_Addr *) (obj->relocbase + rel->r_offset);
381 def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, true);
382 if (def == NULL)
383 die();
384
385 target = (Elf_Addr)(defobj->relocbase + def->st_value);
386
387 dbg("\"%s\" in \"%s\" ==> %p in \"%s\"",
388 defobj->strtab + def->st_name, basename(obj->path),
389 (void *)target, basename(defobj->path));
390
391 reloc_jmpslot(where, target);
392 lock_release();
364 return target;
365}
366
367/*
368 * Error reporting function. Use it like printf. If formats the message
369 * into a buffer, and sets things up so that the next call to dlerror()
370 * will return the message.
371 */

--- 681 unchanged lines hidden (view full) ---

1053 dbg(" WARNING: %s has impure text", obj->path);
1054 } else
1055 free(path);
1056
1057 obj->refcount++;
1058 return obj;
1059}
1060
393 return target;
394}
395
396/*
397 * Error reporting function. Use it like printf. If formats the message
398 * into a buffer, and sets things up so that the next call to dlerror()
399 * will return the message.
400 */

--- 681 unchanged lines hidden (view full) ---

1082 dbg(" WARNING: %s has impure text", obj->path);
1083 } else
1084 free(path);
1085
1086 obj->refcount++;
1087 return obj;
1088}
1089
1090static void
1091lock_nop(void *lock)
1092{
1093}
1094
1061static Obj_Entry *
1062obj_from_addr(const void *addr)
1063{
1064 unsigned long endhash;
1065 Obj_Entry *obj;
1066
1067 endhash = elf_hash(END_SYM);
1068 for (obj = obj_list; obj != NULL; obj = obj->next) {

--- 149 unchanged lines hidden (view full) ---

1218 }
1219
1220 return NULL;
1221}
1222
1223int
1224dlclose(void *handle)
1225{
1095static Obj_Entry *
1096obj_from_addr(const void *addr)
1097{
1098 unsigned long endhash;
1099 Obj_Entry *obj;
1100
1101 endhash = elf_hash(END_SYM);
1102 for (obj = obj_list; obj != NULL; obj = obj->next) {

--- 149 unchanged lines hidden (view full) ---

1252 }
1253
1254 return NULL;
1255}
1256
1257int
1258dlclose(void *handle)
1259{
1226 Obj_Entry *root = dlcheck(handle);
1260 Obj_Entry *root;
1227
1261
1228 if (root == NULL)
1262 wlock_acquire();
1263 root = dlcheck(handle);
1264 if (root == NULL) {
1265 lock_release();
1229 return -1;
1266 return -1;
1267 }
1230
1231 GDB_STATE(RT_DELETE);
1232 unload_object(root, true);
1233 root->dl_refcount--;
1234 GDB_STATE(RT_CONSISTENT);
1235
1268
1269 GDB_STATE(RT_DELETE);
1270 unload_object(root, true);
1271 root->dl_refcount--;
1272 GDB_STATE(RT_CONSISTENT);
1273
1274 lock_release();
1236 return 0;
1237}
1238
1239const char *
1240dlerror(void)
1241{
1242 char *msg = error_message;
1243 error_message = NULL;
1244 return msg;
1245}
1246
1275 return 0;
1276}
1277
1278const char *
1279dlerror(void)
1280{
1281 char *msg = error_message;
1282 error_message = NULL;
1283 return msg;
1284}
1285
1286void
1287dllockinit(void *context,
1288 void *(*lock_create)(void *context),
1289 void (*rlock_acquire)(void *lock),
1290 void (*wlock_acquire)(void *lock),
1291 void (*lock_release)(void *lock),
1292 void (*lock_destroy)(void *lock),
1293 void (*context_destroy)(void *context))
1294{
1295 /* NULL arguments mean reset to the built-in locks. */
1296 if (lock_create == NULL) {
1297 context = NULL;
1298 lock_create = lockdflt_create;
1299 rlock_acquire = wlock_acquire = lockdflt_acquire;
1300 lock_release = lockdflt_release;
1301 lock_destroy = lockdflt_destroy;
1302 context_destroy = NULL;
1303 }
1304
1305 /* Temporarily set locking methods to no-ops. */
1306 lockinfo.rlock_acquire = lock_nop;
1307 lockinfo.wlock_acquire = lock_nop;
1308 lockinfo.lock_release = lock_nop;
1309
1310 /* Release any existing locks and context. */
1311 if (lockinfo.lock_destroy != NULL)
1312 lockinfo.lock_destroy(lockinfo.thelock);
1313 if (lockinfo.context_destroy != NULL)
1314 lockinfo.context_destroy(lockinfo.context);
1315
1316 /*
1317 * Allocate the locks we will need and call all the new locking
1318 * methods, to accomplish any needed lazy binding for the methods
1319 * themselves.
1320 */
1321 lockinfo.thelock = lock_create(lockinfo.context);
1322 rlock_acquire(lockinfo.thelock);
1323 lock_release(lockinfo.thelock);
1324 wlock_acquire(lockinfo.thelock);
1325 lock_release(lockinfo.thelock);
1326
1327 /* Record the new method information. */
1328 lockinfo.context = context;
1329 lockinfo.rlock_acquire = rlock_acquire;
1330 lockinfo.wlock_acquire = wlock_acquire;
1331 lockinfo.lock_release = lock_release;
1332 lockinfo.lock_destroy = lock_destroy;
1333 lockinfo.context_destroy = context_destroy;
1334}
1335
1247void *
1248dlopen(const char *name, int mode)
1249{
1336void *
1337dlopen(const char *name, int mode)
1338{
1250 Obj_Entry **old_obj_tail = obj_tail;
1251 Obj_Entry *obj = NULL;
1339 Obj_Entry **old_obj_tail;
1340 Obj_Entry *obj;
1252
1341
1342 wlock_acquire();
1253 GDB_STATE(RT_ADD);
1254
1343 GDB_STATE(RT_ADD);
1344
1345 old_obj_tail = obj_tail;
1346 obj = NULL;
1255 if (name == NULL) {
1256 obj = obj_main;
1257 obj->refcount++;
1258 } else {
1259 char *path = find_library(name, obj_main);
1260 if (path != NULL)
1261 obj = load_object(path);
1262 }

--- 12 unchanged lines hidden (view full) ---

1275 obj->dl_refcount--;
1276 obj = NULL;
1277 } else
1278 call_init_functions(obj);
1279 }
1280 }
1281
1282 GDB_STATE(RT_CONSISTENT);
1347 if (name == NULL) {
1348 obj = obj_main;
1349 obj->refcount++;
1350 } else {
1351 char *path = find_library(name, obj_main);
1352 if (path != NULL)
1353 obj = load_object(path);
1354 }

--- 12 unchanged lines hidden (view full) ---

1367 obj->dl_refcount--;
1368 obj = NULL;
1369 } else
1370 call_init_functions(obj);
1371 }
1372 }
1373
1374 GDB_STATE(RT_CONSISTENT);
1283
1375 lock_release();
1284 return obj;
1285}
1286
1287void *
1288dlsym(void *handle, const char *name)
1289{
1290 const Obj_Entry *obj;
1291 unsigned long hash;
1292 const Elf_Sym *def;
1293 const Obj_Entry *defobj;
1294
1295 hash = elf_hash(name);
1296 def = NULL;
1297 defobj = NULL;
1298
1376 return obj;
1377}
1378
1379void *
1380dlsym(void *handle, const char *name)
1381{
1382 const Obj_Entry *obj;
1383 unsigned long hash;
1384 const Elf_Sym *def;
1385 const Obj_Entry *defobj;
1386
1387 hash = elf_hash(name);
1388 def = NULL;
1389 defobj = NULL;
1390
1391 wlock_acquire();
1299 if (handle == NULL || handle == RTLD_NEXT) {
1300 void *retaddr;
1301
1302 retaddr = __builtin_return_address(0); /* __GNUC__ only */
1303 if ((obj = obj_from_addr(retaddr)) == NULL) {
1304 _rtld_error("Cannot determine caller's shared object");
1392 if (handle == NULL || handle == RTLD_NEXT) {
1393 void *retaddr;
1394
1395 retaddr = __builtin_return_address(0); /* __GNUC__ only */
1396 if ((obj = obj_from_addr(retaddr)) == NULL) {
1397 _rtld_error("Cannot determine caller's shared object");
1398 lock_release();
1305 return NULL;
1306 }
1307 if (handle == NULL) { /* Just the caller's shared object. */
1308 def = symlook_obj(name, hash, obj, true);
1309 defobj = obj;
1310 } else { /* All the shared objects after the caller's */
1311 while ((obj = obj->next) != NULL) {
1312 if ((def = symlook_obj(name, hash, obj, true)) != NULL) {
1313 defobj = obj;
1314 break;
1315 }
1316 }
1317 }
1318 } else {
1399 return NULL;
1400 }
1401 if (handle == NULL) { /* Just the caller's shared object. */
1402 def = symlook_obj(name, hash, obj, true);
1403 defobj = obj;
1404 } else { /* All the shared objects after the caller's */
1405 while ((obj = obj->next) != NULL) {
1406 if ((def = symlook_obj(name, hash, obj, true)) != NULL) {
1407 defobj = obj;
1408 break;
1409 }
1410 }
1411 }
1412 } else {
1319 if ((obj = dlcheck(handle)) == NULL)
1413 if ((obj = dlcheck(handle)) == NULL) {
1414 lock_release();
1320 return NULL;
1415 return NULL;
1416 }
1321
1322 if (obj->mainprog) {
1323 /* Search main program and all libraries loaded by it. */
1324 curmark++;
1325 def = symlook_list(name, hash, &list_main, &defobj, true);
1326 } else {
1327 /*
1328 * XXX - This isn't correct. The search should include the whole
1329 * DAG rooted at the given object.
1330 */
1331 def = symlook_obj(name, hash, obj, true);
1332 defobj = obj;
1333 }
1334 }
1335
1417
1418 if (obj->mainprog) {
1419 /* Search main program and all libraries loaded by it. */
1420 curmark++;
1421 def = symlook_list(name, hash, &list_main, &defobj, true);
1422 } else {
1423 /*
1424 * XXX - This isn't correct. The search should include the whole
1425 * DAG rooted at the given object.
1426 */
1427 def = symlook_obj(name, hash, obj, true);
1428 defobj = obj;
1429 }
1430 }
1431
1336 if (def != NULL)
1432 if (def != NULL) {
1433 lock_release();
1337 return defobj->relocbase + def->st_value;
1434 return defobj->relocbase + def->st_value;
1435 }
1338
1339 _rtld_error("Undefined symbol \"%s\"", name);
1436
1437 _rtld_error("Undefined symbol \"%s\"", name);
1438 lock_release();
1340 return NULL;
1341}
1342
1343int
1344dladdr(const void *addr, Dl_info *info)
1345{
1346 const Obj_Entry *obj;
1347 const Elf_Sym *def;
1348 void *symbol_addr;
1349 unsigned long symoffset;
1350
1439 return NULL;
1440}
1441
1442int
1443dladdr(const void *addr, Dl_info *info)
1444{
1445 const Obj_Entry *obj;
1446 const Elf_Sym *def;
1447 void *symbol_addr;
1448 unsigned long symoffset;
1449
1450 wlock_acquire();
1351 obj = obj_from_addr(addr);
1352 if (obj == NULL) {
1353 _rtld_error("No shared object contains address");
1451 obj = obj_from_addr(addr);
1452 if (obj == NULL) {
1453 _rtld_error("No shared object contains address");
1454 lock_release();
1354 return 0;
1355 }
1356 info->dli_fname = obj->path;
1357 info->dli_fbase = obj->mapbase;
1358 info->dli_saddr = (void *)0;
1359 info->dli_sname = NULL;
1360
1361 /*

--- 22 unchanged lines hidden (view full) ---

1384 /* Update our idea of the nearest symbol. */
1385 info->dli_sname = obj->strtab + def->st_name;
1386 info->dli_saddr = symbol_addr;
1387
1388 /* Exact match? */
1389 if (info->dli_saddr == addr)
1390 break;
1391 }
1455 return 0;
1456 }
1457 info->dli_fname = obj->path;
1458 info->dli_fbase = obj->mapbase;
1459 info->dli_saddr = (void *)0;
1460 info->dli_sname = NULL;
1461
1462 /*

--- 22 unchanged lines hidden (view full) ---

1485 /* Update our idea of the nearest symbol. */
1486 info->dli_sname = obj->strtab + def->st_name;
1487 info->dli_saddr = symbol_addr;
1488
1489 /* Exact match? */
1490 if (info->dli_saddr == addr)
1491 break;
1492 }
1493 lock_release();
1392 return 1;
1393}
1394
1395static void
1396linkmap_add(Obj_Entry *obj)
1397{
1398 struct link_map *l = &obj->linkmap;
1399 struct link_map *prev;

--- 303 unchanged lines hidden ---
1494 return 1;
1495}
1496
1497static void
1498linkmap_add(Obj_Entry *obj)
1499{
1500 struct link_map *l = &obj->linkmap;
1501 struct link_map *prev;

--- 303 unchanged lines hidden ---