libdl.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * Program to load an ELF binary on a linux system, and run it
  4. * after resolving ELF shared library symbols
  5. *
  6. * Copyright (C) 2000-2004 by Erik Andersen <andersen@codpoet.org>
  7. * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
  8. * David Engel, Hongjiu Lu and Mitch D'Souza
  9. *
  10. * Redistribution and use in source and binary forms, with or without
  11. * modification, are permitted provided that the following conditions
  12. * are met:
  13. * 1. Redistributions of source code must retain the above copyright
  14. * notice, this list of conditions and the following disclaimer.
  15. * 2. The name of the above contributors may not be
  16. * used to endorse or promote products derived from this software
  17. * without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
  20. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  21. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  22. * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE
  23. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  24. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  25. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  26. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  27. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  28. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  29. * SUCH DAMAGE.
  30. */
  31. #include <ldso.h>
  32. #if defined (__LIBDL_SHARED__)
  33. /* When libdl is loaded as a shared library, we need to load in
  34. * and use a pile of symbols from ldso... */
  35. extern void _dl_dprintf(int, const char *, ...) __attribute__ ((__weak__));
  36. extern char *_dl_find_hash(const char *, struct dyn_elf *, int)
  37. __attribute__ ((__weak__));
  38. extern struct elf_resolve * _dl_load_shared_library(int, struct dyn_elf **,
  39. struct elf_resolve *, char *, int) __attribute__ ((__weak__));
  40. extern struct elf_resolve * _dl_check_if_named_library_is_loaded(const char *, int)
  41. __attribute__ ((__weak__));
  42. extern int _dl_fixup(struct dyn_elf *rpnt, int lazy)
  43. __attribute__ ((__weak__));
  44. extern int _dl_errno __attribute__ ((__weak__));
  45. extern struct dyn_elf *_dl_symbol_tables __attribute__ ((__weak__));
  46. extern struct dyn_elf *_dl_handles __attribute__ ((__weak__));
  47. extern struct elf_resolve *_dl_loaded_modules __attribute__ ((__weak__));
  48. extern struct r_debug *_dl_debug_addr __attribute__ ((__weak__));
  49. extern unsigned long _dl_error_number __attribute__ ((__weak__));
  50. extern void *(*_dl_malloc_function)(size_t) __attribute__ ((__weak__));
  51. #ifdef USE_CACHE
  52. int _dl_map_cache(void) __attribute__ ((__weak__));
  53. int _dl_unmap_cache(void) __attribute__ ((__weak__));
  54. #endif
  55. #ifdef __mips__
  56. extern void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt)
  57. __attribute__ ((__weak__));
  58. #endif
  59. #ifdef __SUPPORT_LD_DEBUG__
  60. extern char *_dl_debug __attribute__ ((__weak__));
  61. extern char *_dl_debug_symbols __attribute__ ((__weak__));
  62. extern char *_dl_debug_move __attribute__ ((__weak__));
  63. extern char *_dl_debug_reloc __attribute__ ((__weak__));
  64. extern char *_dl_debug_detail __attribute__ ((__weak__));
  65. extern char *_dl_debug_nofixups __attribute__ ((__weak__));
  66. extern char *_dl_debug_bindings __attribute__ ((__weak__));
  67. extern int _dl_debug_file __attribute__ ((__weak__));
  68. #endif
  69. #else /* __LIBDL_SHARED__ */
  70. /* When libdl is linked as a static library, we need to replace all
  71. * the symbols that otherwise would have been loaded in from ldso... */
  72. #ifdef __SUPPORT_LD_DEBUG__
  73. char *_dl_debug = 0;
  74. char *_dl_debug_symbols = 0;
  75. char *_dl_debug_move = 0;
  76. char *_dl_debug_reloc = 0;
  77. char *_dl_debug_detail = 0;
  78. char *_dl_debug_nofixups = 0;
  79. char *_dl_debug_bindings = 0;
  80. int _dl_debug_file = 2;
  81. #endif
  82. char *_dl_library_path = 0;
  83. char *_dl_ldsopath = 0;
  84. struct r_debug *_dl_debug_addr = NULL;
  85. static unsigned char *_dl_malloc_addr, *_dl_mmap_zero;
  86. void *(*_dl_malloc_function) (size_t size);
  87. int _dl_errno = 0;
  88. int _dl_fixup(struct dyn_elf *rpnt, int lazy);
  89. #include "../ldso/dl-progname.h" /* Pull in the name of ld.so */
  90. #include "../ldso/dl-hash.c"
  91. #define _dl_trace_loaded_objects 0
  92. #include "../ldso/dl-elf.c"
  93. #endif
  94. static int do_dlclose(void *, int need_fini);
  95. static const char *dl_error_names[] = {
  96. "",
  97. "File not found",
  98. "Unable to open /dev/zero",
  99. "Not an ELF file",
  100. #if defined (__i386__)
  101. "Not i386 binary",
  102. #elif defined (__sparc__)
  103. "Not sparc binary",
  104. #elif defined (__mc68000__)
  105. "Not m68k binary",
  106. #else
  107. "Unrecognized binary type",
  108. #endif
  109. "Not an ELF shared library",
  110. "Unable to mmap file",
  111. "No dynamic section",
  112. #ifdef ELF_USES_RELOCA
  113. "Unable to process REL relocs",
  114. #else
  115. "Unable to process RELA relocs",
  116. #endif
  117. "Bad handle",
  118. "Unable to resolve symbol"
  119. };
  120. static void __attribute__ ((destructor)) dl_cleanup(void)
  121. {
  122. struct dyn_elf *d;
  123. for (d = _dl_handles; d; d = d->next_handle)
  124. if (d->dyn->libtype == loaded_file && d->dyn->dynamic_info[DT_FINI]) {
  125. (* ((int (*)(void)) (d->dyn->loadaddr + d->dyn->dynamic_info[DT_FINI]))) ();
  126. d->dyn->dynamic_info[DT_FINI] = 0;
  127. }
  128. }
  129. void *_dlopen(const char *libname, int flag)
  130. {
  131. struct elf_resolve *tpnt, *tfrom, *tcurr;
  132. struct dyn_elf *dyn_chain, *rpnt = NULL;
  133. struct dyn_elf *dpnt;
  134. static int dl_init = 0;
  135. ElfW(Addr) from;
  136. struct elf_resolve *tpnt1;
  137. void (*dl_brk) (void);
  138. /* A bit of sanity checking... */
  139. if (!(flag & (RTLD_LAZY|RTLD_NOW))) {
  140. _dl_error_number = LD_BAD_HANDLE;
  141. return NULL;
  142. }
  143. from = (ElfW(Addr)) __builtin_return_address(0);
  144. /* Have the dynamic linker use the regular malloc function now */
  145. if (!dl_init) {
  146. dl_init++;
  147. _dl_malloc_function = malloc;
  148. }
  149. /* Cover the trivial case first */
  150. if (!libname)
  151. return _dl_symbol_tables;
  152. _dl_map_cache();
  153. /*
  154. * Try and locate the module we were called from - we
  155. * need this so that we get the correct RPATH. Note that
  156. * this is the current behavior under Solaris, but the
  157. * ABI+ specifies that we should only use the RPATH from
  158. * the application. Thus this may go away at some time
  159. * in the future.
  160. */
  161. tfrom = NULL;
  162. for (dpnt = _dl_symbol_tables; dpnt; dpnt = dpnt->next) {
  163. tpnt = dpnt->dyn;
  164. if (tpnt->loadaddr < from
  165. && (tfrom == NULL || tfrom->loadaddr < tpnt->loadaddr))
  166. tfrom = tpnt;
  167. }
  168. /* Try to load the specified library */
  169. #ifdef __SUPPORT_LD_DEBUG__
  170. if(_dl_debug)
  171. _dl_dprintf(_dl_debug_file, "Trying to dlopen '%s'\n", (char*)libname);
  172. #endif
  173. if (!(tpnt = _dl_check_if_named_library_is_loaded((char *)libname, 0)))
  174. tpnt = _dl_load_shared_library(0, &rpnt, tfrom, (char*)libname, 0);
  175. if (tpnt == NULL) {
  176. _dl_unmap_cache();
  177. return NULL;
  178. }
  179. dyn_chain = (struct dyn_elf *) malloc(sizeof(struct dyn_elf));
  180. _dl_memset(dyn_chain, 0, sizeof(struct dyn_elf));
  181. dyn_chain->dyn = tpnt;
  182. dyn_chain->flags = flag;
  183. if (!tpnt->symbol_scope)
  184. tpnt->symbol_scope = dyn_chain;
  185. dyn_chain->next_handle = _dl_handles;
  186. _dl_handles = rpnt = dyn_chain;
  187. if (tpnt->init_flag & INIT_FUNCS_CALLED) {
  188. /* If the init and fini stuff has already been run, that means
  189. * the dlopen'd library has already been loaded, and nothing
  190. * further needs to be done. */
  191. return (void *) dyn_chain;
  192. }
  193. #ifdef __SUPPORT_LD_DEBUG__
  194. if(_dl_debug)
  195. _dl_dprintf(_dl_debug_file, "Looking for needed libraries\n");
  196. #endif
  197. for (tcurr = tpnt; tcurr; tcurr = tcurr->next)
  198. {
  199. Elf32_Dyn *dpnt;
  200. char *lpntstr;
  201. for (dpnt = (Elf32_Dyn *) tcurr->dynamic_addr; dpnt->d_tag; dpnt++) {
  202. if (dpnt->d_tag == DT_NEEDED) {
  203. char *name;
  204. lpntstr = (char*) (tcurr->loadaddr + tcurr->dynamic_info[DT_STRTAB] +
  205. dpnt->d_un.d_val);
  206. name = _dl_get_last_path_component(lpntstr);
  207. if ((tpnt1 = _dl_check_if_named_library_is_loaded(name, 0)))
  208. continue;
  209. #ifdef __SUPPORT_LD_DEBUG__
  210. if(_dl_debug)
  211. _dl_dprintf(_dl_debug_file, "Trying to load '%s', needed by '%s'\n",
  212. lpntstr, tcurr->libname);
  213. #endif
  214. if (!(tpnt1 = _dl_load_shared_library(0, &rpnt, tcurr, lpntstr, 0))) {
  215. goto oops;
  216. }
  217. rpnt->next = (struct dyn_elf *) malloc(sizeof(struct dyn_elf));
  218. _dl_memset (rpnt->next, 0, sizeof (struct dyn_elf));
  219. rpnt = rpnt->next;
  220. if (!tpnt1->symbol_scope) tpnt1->symbol_scope = rpnt;
  221. rpnt->dyn = tpnt1;
  222. }
  223. }
  224. }
  225. /*
  226. * OK, now attach the entire chain at the end
  227. */
  228. rpnt->next = _dl_symbol_tables;
  229. #ifdef __mips__
  230. /*
  231. * Relocation of the GOT entries for MIPS have to be done
  232. * after all the libraries have been loaded.
  233. */
  234. _dl_perform_mips_global_got_relocations(tpnt);
  235. #endif
  236. #ifdef __SUPPORT_LD_DEBUG__
  237. if(_dl_debug)
  238. _dl_dprintf(_dl_debug_file, "Beginning dlopen relocation fixups\n");
  239. #endif
  240. /*
  241. * OK, now all of the kids are tucked into bed in their proper addresses.
  242. * Now we go through and look for REL and RELA records that indicate fixups
  243. * to the GOT tables. We need to do this in reverse order so that COPY
  244. * directives work correctly */
  245. if (_dl_fixup(dyn_chain, dyn_chain->flags))
  246. goto oops;
  247. /* TODO: Should we set the protections of all pages back to R/O now ? */
  248. /* Notify the debugger we have added some objects. */
  249. if (_dl_debug_addr) {
  250. dl_brk = (void (*)(void)) _dl_debug_addr->r_brk;
  251. if (dl_brk != NULL) {
  252. _dl_debug_addr->r_state = RT_ADD;
  253. (*dl_brk) ();
  254. _dl_debug_addr->r_state = RT_CONSISTENT;
  255. (*dl_brk) ();
  256. }
  257. }
  258. #if 0 //def __SUPPORT_LD_DEBUG__
  259. if(_dl_debug)
  260. _dlinfo();
  261. #endif
  262. #if defined (__LIBDL_SHARED__)
  263. /* Find the last library so we can run things in the right order */
  264. for (tpnt = dyn_chain->dyn; tpnt->next!=NULL; tpnt = tpnt->next)
  265. ;
  266. /* Run the ctors and set up the dtors */
  267. for (; tpnt != dyn_chain->dyn->prev; tpnt=tpnt->prev)
  268. {
  269. /* Apparently crt1 for the application is responsible for handling this.
  270. * We only need to run the init/fini for shared libraries
  271. */
  272. if (tpnt->libtype == program_interpreter)
  273. continue;
  274. if (tpnt->libtype == elf_executable)
  275. continue;
  276. if (tpnt->init_flag & INIT_FUNCS_CALLED)
  277. continue;
  278. tpnt->init_flag |= INIT_FUNCS_CALLED;
  279. if (tpnt->dynamic_info[DT_INIT]) {
  280. void (*dl_elf_func) (void);
  281. dl_elf_func = (void (*)(void)) (tpnt->loadaddr + tpnt->dynamic_info[DT_INIT]);
  282. if (dl_elf_func && *dl_elf_func != NULL) {
  283. #ifdef __SUPPORT_LD_DEBUG__
  284. if(_dl_debug)
  285. _dl_dprintf(2, "running ctors for library %s at '%x'\n", tpnt->libname, dl_elf_func);
  286. #endif
  287. (*dl_elf_func) ();
  288. }
  289. }
  290. if (tpnt->dynamic_info[DT_FINI]) {
  291. void (*dl_elf_func) (void);
  292. dl_elf_func = (void (*)(void)) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI]);
  293. if (dl_elf_func && *dl_elf_func != NULL) {
  294. #ifdef __SUPPORT_LD_DEBUG__
  295. if(_dl_debug)
  296. _dl_dprintf(2, "setting up dtors for library %s at '%x'\n", tpnt->libname, dl_elf_func);
  297. #endif
  298. atexit(dl_elf_func);
  299. }
  300. }
  301. }
  302. #endif
  303. return (void *) dyn_chain;
  304. oops:
  305. /* Something went wrong. Clean up and return NULL. */
  306. _dl_unmap_cache();
  307. do_dlclose(dyn_chain, 0);
  308. return NULL;
  309. }
  310. weak_alias(_dlopen, dlopen);
  311. void *_dlsym(void *vhandle, const char *name)
  312. {
  313. struct elf_resolve *tpnt, *tfrom;
  314. struct dyn_elf *handle;
  315. ElfW(Addr) from;
  316. struct dyn_elf *rpnt;
  317. void *ret;
  318. handle = (struct dyn_elf *) vhandle;
  319. /* First of all verify that we have a real handle
  320. of some kind. Return NULL if not a valid handle. */
  321. if (handle == NULL)
  322. handle = _dl_symbol_tables;
  323. else if (handle != RTLD_NEXT && handle != _dl_symbol_tables) {
  324. for (rpnt = _dl_handles; rpnt; rpnt = rpnt->next_handle)
  325. if (rpnt == handle)
  326. break;
  327. if (!rpnt) {
  328. _dl_error_number = LD_BAD_HANDLE;
  329. return NULL;
  330. }
  331. } else if (handle == RTLD_NEXT) {
  332. /*
  333. * Try and locate the module we were called from - we
  334. * need this so that we know where to start searching
  335. * from. We never pass RTLD_NEXT down into the actual
  336. * dynamic loader itself, as it doesn't know
  337. * how to properly treat it.
  338. */
  339. from = (ElfW(Addr)) __builtin_return_address(0);
  340. tfrom = NULL;
  341. for (rpnt = _dl_symbol_tables; rpnt; rpnt = rpnt->next) {
  342. tpnt = rpnt->dyn;
  343. if (tpnt->loadaddr < from
  344. && (tfrom == NULL || tfrom->loadaddr < tpnt->loadaddr)) {
  345. tfrom = tpnt;
  346. handle = rpnt->next;
  347. }
  348. }
  349. }
  350. ret = _dl_find_hash((char*)name, handle, 0);
  351. /*
  352. * Nothing found.
  353. */
  354. if (!ret)
  355. _dl_error_number = LD_NO_SYMBOL;
  356. return ret;
  357. }
  358. weak_alias(_dlsym, dlsym);
  359. static int do_dlclose(void *vhandle, int need_fini)
  360. {
  361. struct dyn_elf *rpnt, *rpnt1;
  362. struct dyn_elf *spnt, *spnt1;
  363. ElfW(Phdr) *ppnt;
  364. struct elf_resolve *tpnt;
  365. int (*dl_elf_fini) (void);
  366. void (*dl_brk) (void);
  367. struct dyn_elf *handle;
  368. unsigned int end;
  369. int i = 0;
  370. handle = (struct dyn_elf *) vhandle;
  371. rpnt1 = NULL;
  372. for (rpnt = _dl_handles; rpnt; rpnt = rpnt->next_handle) {
  373. if (rpnt == handle) {
  374. break;
  375. }
  376. rpnt1 = rpnt;
  377. }
  378. if (!rpnt) {
  379. _dl_error_number = LD_BAD_HANDLE;
  380. return 1;
  381. }
  382. /* OK, this is a valid handle - now close out the file.
  383. * We check if we need to call fini () on the handle. */
  384. spnt = need_fini ? handle : handle->next;
  385. for (; spnt; spnt = spnt1) {
  386. spnt1 = spnt->next;
  387. /* We appended the module list to the end - when we get back here,
  388. quit. The access counts were not adjusted to account for being here. */
  389. if (spnt == _dl_symbol_tables)
  390. break;
  391. if (spnt->dyn->usage_count == 1
  392. && spnt->dyn->libtype == loaded_file) {
  393. tpnt = spnt->dyn;
  394. /* Apparently crt1 for the application is responsible for handling this.
  395. * We only need to run the init/fini for shared libraries
  396. */
  397. if (tpnt->dynamic_info[DT_FINI]) {
  398. dl_elf_fini = (int (*)(void)) (tpnt->loadaddr +
  399. tpnt->dynamic_info[DT_FINI]);
  400. (*dl_elf_fini) ();
  401. }
  402. }
  403. }
  404. if (rpnt1)
  405. rpnt1->next_handle = rpnt->next_handle;
  406. else
  407. _dl_handles = rpnt->next_handle;
  408. /* OK, this is a valid handle - now close out the file */
  409. for (rpnt = handle; rpnt; rpnt = rpnt1) {
  410. rpnt1 = rpnt->next;
  411. /* We appended the module list to the end - when we get back here,
  412. quit. The access counts were not adjusted to account for being here. */
  413. if (rpnt == _dl_symbol_tables)
  414. break;
  415. rpnt->dyn->usage_count--;
  416. if (rpnt->dyn->usage_count == 0
  417. && rpnt->dyn->libtype == loaded_file) {
  418. tpnt = rpnt->dyn;
  419. /* Apparently crt1 for the application is responsible for handling this.
  420. * We only need to run the init/fini for shared libraries
  421. */
  422. #if 0
  423. /* We have to do this above, before we start closing objects.
  424. * Otherwise when the needed symbols for _fini handling are
  425. * resolved a coredump would occur. Rob Ryan (robr@cmu.edu)*/
  426. if (tpnt->dynamic_info[DT_FINI]) {
  427. dl_elf_fini = (int (*)(void)) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI]);
  428. (*dl_elf_fini) ();
  429. }
  430. #endif
  431. end = 0;
  432. for (i = 0, ppnt = rpnt->dyn->ppnt;
  433. i < rpnt->dyn->n_phent; ppnt++, i++) {
  434. if (ppnt->p_type != PT_LOAD)
  435. continue;
  436. if (end < ppnt->p_vaddr + ppnt->p_memsz)
  437. end = ppnt->p_vaddr + ppnt->p_memsz;
  438. }
  439. _dl_munmap((void*)rpnt->dyn->loadaddr, end);
  440. /* Next, remove rpnt->dyn from the loaded_module list */
  441. if (_dl_loaded_modules == rpnt->dyn) {
  442. _dl_loaded_modules = rpnt->dyn->next;
  443. if (_dl_loaded_modules)
  444. _dl_loaded_modules->prev = 0;
  445. } else
  446. for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next)
  447. if (tpnt->next == rpnt->dyn) {
  448. tpnt->next = tpnt->next->next;
  449. if (tpnt->next)
  450. tpnt->next->prev = tpnt;
  451. break;
  452. }
  453. free(rpnt->dyn->libname);
  454. free(rpnt->dyn);
  455. }
  456. free(rpnt);
  457. }
  458. if (_dl_debug_addr) {
  459. dl_brk = (void (*)(void)) _dl_debug_addr->r_brk;
  460. if (dl_brk != NULL) {
  461. _dl_debug_addr->r_state = RT_DELETE;
  462. (*dl_brk) ();
  463. _dl_debug_addr->r_state = RT_CONSISTENT;
  464. (*dl_brk) ();
  465. }
  466. }
  467. return 0;
  468. }
  469. int _dlclose(void *vhandle)
  470. {
  471. return do_dlclose(vhandle, 1);
  472. }
  473. weak_alias(_dlclose, dlclose);
  474. const char *_dlerror(void)
  475. {
  476. const char *retval;
  477. if (!_dl_error_number)
  478. return NULL;
  479. retval = dl_error_names[_dl_error_number];
  480. _dl_error_number = 0;
  481. return retval;
  482. }
  483. weak_alias(_dlerror, dlerror);
  484. /*
  485. * Dump information to stderrr about the current loaded modules
  486. */
  487. static char *type[] = { "Lib", "Exe", "Int", "Mod" };
  488. void _dlinfo(void)
  489. {
  490. struct elf_resolve *tpnt;
  491. struct dyn_elf *rpnt, *hpnt;
  492. _dl_dprintf(2, "List of loaded modules\n");
  493. /* First start with a complete list of all of the loaded files. */
  494. for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
  495. _dl_dprintf(2, "\t%x %x %x %s %d %s\n",
  496. (unsigned) tpnt->loadaddr, (unsigned) tpnt,
  497. (unsigned) tpnt->symbol_scope,
  498. type[tpnt->libtype],
  499. tpnt->usage_count, tpnt->libname);
  500. }
  501. /* Next dump the module list for the application itself */
  502. _dl_dprintf(2, "\nModules for application (%x):\n",
  503. (unsigned) _dl_symbol_tables);
  504. for (rpnt = _dl_symbol_tables; rpnt; rpnt = rpnt->next)
  505. _dl_dprintf(2, "\t%x %s\n", (unsigned) rpnt->dyn, rpnt->dyn->libname);
  506. for (hpnt = _dl_handles; hpnt; hpnt = hpnt->next_handle) {
  507. _dl_dprintf(2, "Modules for handle %x\n", (unsigned) hpnt);
  508. for (rpnt = hpnt; rpnt; rpnt = rpnt->next)
  509. _dl_dprintf(2, "\t%x %s\n", (unsigned) rpnt->dyn,
  510. rpnt->dyn->libname);
  511. }
  512. }
  513. weak_alias(_dlinfo, dlinfo);
  514. int _dladdr(void *__address, Dl_info * __dlip)
  515. {
  516. struct elf_resolve *pelf;
  517. struct elf_resolve *rpnt;
  518. _dl_map_cache();
  519. /*
  520. * Try and locate the module address is in
  521. */
  522. pelf = NULL;
  523. #if 0
  524. _dl_dprintf(2, "dladdr( %x, %x )\n", __address, __dlip);
  525. #endif
  526. for (rpnt = _dl_loaded_modules; rpnt; rpnt = rpnt->next) {
  527. struct elf_resolve *tpnt;
  528. tpnt = rpnt;
  529. #if 0
  530. _dl_dprintf(2, "Module \"%s\" at %x\n",
  531. tpnt->libname, tpnt->loadaddr);
  532. #endif
  533. if (tpnt->loadaddr < (ElfW(Addr)) __address
  534. && (pelf == NULL || pelf->loadaddr < tpnt->loadaddr)) {
  535. pelf = tpnt;
  536. }
  537. }
  538. if (!pelf) {
  539. return 0;
  540. }
  541. /*
  542. * Try and locate the symbol of address
  543. */
  544. {
  545. char *strtab;
  546. Elf32_Sym *symtab;
  547. int hn, si;
  548. int sf;
  549. int sn = 0;
  550. ElfW(Addr) sa;
  551. sa = 0;
  552. symtab = (Elf32_Sym *) (pelf->dynamic_info[DT_SYMTAB] + pelf->loadaddr);
  553. strtab = (char *) (pelf->dynamic_info[DT_STRTAB] + pelf->loadaddr);
  554. sf = 0;
  555. for (hn = 0; hn < pelf->nbucket; hn++) {
  556. for (si = pelf->elf_buckets[hn]; si; si = pelf->chains[si]) {
  557. ElfW(Addr) symbol_addr;
  558. symbol_addr = pelf->loadaddr + symtab[si].st_value;
  559. if (symbol_addr <= (ElfW(Addr))__address && (!sf || sa < symbol_addr)) {
  560. sa = symbol_addr;
  561. sn = si;
  562. sf = 1;
  563. }
  564. #if 0
  565. _dl_dprintf(2, "Symbol \"%s\" at %x\n",
  566. strtab + symtab[si].st_name, symbol_addr);
  567. #endif
  568. }
  569. }
  570. if (sf) {
  571. __dlip->dli_fname = pelf->libname;
  572. __dlip->dli_fbase = (void *)pelf->loadaddr;
  573. __dlip->dli_sname = strtab + symtab[sn].st_name;
  574. __dlip->dli_saddr = (void *)sa;
  575. }
  576. return 1;
  577. }
  578. }
  579. weak_alias(_dladdr, dladdr);