dl-startup.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565
  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. /*
  32. * The main trick with this program is that initially, we ourselves are not
  33. * dynamicly linked. This means that we cannot access any global variables or
  34. * call any functions. No globals initially, since the Global Offset Table
  35. * (GOT) is initialized by the linker assuming a virtual address of 0, and no
  36. * function calls initially since the Procedure Linkage Table (PLT) is not yet
  37. * initialized.
  38. *
  39. * There are additional initial restrictions - we cannot use large switch
  40. * statements, since the compiler generates tables of addresses and jumps
  41. * through them. We cannot use normal syscall stubs, because these all
  42. * reference the errno global variable which is not yet initialized. We _can_
  43. * use all of the local stack variables that we want. We _can_ use inline
  44. * functions, because these do not transfer control to a new address, but they
  45. * must be static so that they are not exported from the modules.
  46. *
  47. * Life is further complicated by the fact that initially we do not want to do
  48. * a complete dynamic linking. We want to allow the user to supply new
  49. * functions to override symbols (i.e. weak symbols and/or LD_PRELOAD). So
  50. * initially, we only perform relocations for variables that start with "_dl_"
  51. * since ANSI specifies that the user is not supposed to redefine any of these
  52. * variables.
  53. *
  54. * Fortunately, the linker itself leaves a few clues lying around, and when the
  55. * kernel starts the image, there are a few further clues. First of all, there
  56. * is Auxiliary Vector Table information sitting on which is provided to us by
  57. * the kernel, and which includes information about the load address that the
  58. * program interpreter was loaded at, the number of sections, the address the
  59. * application was loaded at and so forth. Here this information is stored in
  60. * the array auxvt. For details see linux/fs/binfmt_elf.c where it calls
  61. * NEW_AUX_ENT() a bunch of time....
  62. *
  63. * Next, we need to find the GOT. On most arches there is a register pointing
  64. * to the GOT, but just in case (and for new ports) I've added some (slow) C
  65. * code to locate the GOT for you.
  66. *
  67. * This code was originally written for SVr4, and there the kernel would load
  68. * all text pages R/O, so they needed to call mprotect a zillion times to mark
  69. * all text pages as writable so dynamic linking would succeed. Then when they
  70. * were done, they would change the protections for all the pages back again.
  71. * Well, under Linux everything is loaded writable (since Linux does copy on
  72. * write anyways) so all the mprotect stuff has been disabled.
  73. *
  74. * Initially, we do not have access to _dl_malloc since we can't yet make
  75. * function calls, so we mmap one page to use as scratch space. Later on, when
  76. * we can call _dl_malloc we reuse this this memory. This is also beneficial,
  77. * since we do not want to use the same memory pool as malloc anyway - esp if
  78. * the user redefines malloc to do something funky.
  79. *
  80. * Our first task is to perform a minimal linking so that we can call other
  81. * portions of the dynamic linker. Once we have done this, we then build the
  82. * list of modules that the application requires, using LD_LIBRARY_PATH if this
  83. * is not a suid program (/usr/lib otherwise). Once this is done, we can do
  84. * the dynamic linking as required, and we must omit the things we did to get
  85. * the dynamic linker up and running in the first place. After we have done
  86. * this, we just have a few housekeeping chores and we can transfer control to
  87. * the user's application.
  88. */
  89. #include "ldso.h"
  90. /* This is a poor man's malloc, used prior to resolving our internal poor man's malloc */
  91. #define LD_MALLOC(SIZE) ((void *) (malloc_buffer += SIZE, malloc_buffer - SIZE)) ; REALIGN();
  92. /* Make sure that the malloc buffer is aligned on 4 byte boundary. For 64 bit
  93. * platforms we may need to increase this to 8, but this is good enough for
  94. * now. This is typically called after LD_MALLOC. */
  95. #define REALIGN() malloc_buffer = (char *) (((unsigned long) malloc_buffer + 3) & ~(3))
  96. /* Pull in all the arch specific stuff */
  97. #include "dl-startup.h"
  98. /* Static declarations */
  99. int (*_dl_elf_main) (int, char **, char **);
  100. /* When we enter this piece of code, the program stack looks like this:
  101. argc argument counter (integer)
  102. argv[0] program name (pointer)
  103. argv[1...N] program args (pointers)
  104. argv[argc-1] end of args (integer)
  105. NULL
  106. env[0...N] environment variables (pointers)
  107. NULL
  108. auxvt[0...N] Auxiliary Vector Table elements (mixed types)
  109. */
  110. DL_BOOT(unsigned long args)
  111. {
  112. unsigned int argc;
  113. char **argv, **envp;
  114. unsigned long load_addr;
  115. unsigned long *got;
  116. unsigned long *aux_dat;
  117. int goof = 0;
  118. ElfW(Ehdr) *header;
  119. struct elf_resolve *tpnt;
  120. struct elf_resolve *app_tpnt;
  121. Elf32_auxv_t auxvt[AT_EGID + 1];
  122. unsigned char *malloc_buffer, *mmap_zero;
  123. Elf32_Dyn *dpnt;
  124. unsigned long *hash_addr;
  125. struct r_debug *debug_addr = NULL;
  126. int indx;
  127. #if defined(__i386__)
  128. int status = 0;
  129. #endif
  130. /* WARNING! -- we cannot make _any_ funtion calls until we have
  131. * taken care of fixing up our own relocations. Making static
  132. * inline calls is ok, but _no_ function calls. Not yet
  133. * anyways. */
  134. /* First obtain the information on the stack that tells us more about
  135. what binary is loaded, where it is loaded, etc, etc */
  136. GET_ARGV(aux_dat, args);
  137. #if defined (__arm__) || defined (__mips__) || defined (__cris__)
  138. aux_dat += 1;
  139. #endif
  140. argc = *(aux_dat - 1);
  141. argv = (char **) aux_dat;
  142. aux_dat += argc; /* Skip over the argv pointers */
  143. aux_dat++; /* Skip over NULL at end of argv */
  144. envp = (char **) aux_dat;
  145. while (*aux_dat)
  146. aux_dat++; /* Skip over the envp pointers */
  147. aux_dat++; /* Skip over NULL at end of envp */
  148. /* Place -1 here as a checkpoint. We later check if it was changed
  149. * when we read in the auxvt */
  150. auxvt[AT_UID].a_type = -1;
  151. /* The junk on the stack immediately following the environment is
  152. * the Auxiliary Vector Table. Read out the elements of the auxvt,
  153. * sort and store them in auxvt for later use. */
  154. while (*aux_dat) {
  155. Elf32_auxv_t *auxv_entry = (Elf32_auxv_t *) aux_dat;
  156. if (auxv_entry->a_type <= AT_EGID) {
  157. _dl_memcpy(&(auxvt[auxv_entry->a_type]), auxv_entry, sizeof(Elf32_auxv_t));
  158. }
  159. aux_dat += 2;
  160. }
  161. /* locate the ELF header. We need this done as soon as possible
  162. * (esp since SEND_STDERR() needs this on some platforms... */
  163. load_addr = auxvt[AT_BASE].a_un.a_val;
  164. header = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_ptr;
  165. /* Check the ELF header to make sure everything looks ok. */
  166. if (!header || header->e_ident[EI_CLASS] != ELFCLASS32 ||
  167. header->e_ident[EI_VERSION] != EV_CURRENT
  168. /* Do not use an inline _dl_strncmp here or some arches
  169. * will blow chunks, i.e. those that need to relocate all
  170. * string constants... */
  171. || header->e_ident[EI_MAG0] != ELFMAG0
  172. || header->e_ident[EI_MAG1] != ELFMAG1
  173. || header->e_ident[EI_MAG2] != ELFMAG2
  174. || header->e_ident[EI_MAG3] != ELFMAG3)
  175. {
  176. SEND_STDERR("Invalid ELF header\n");
  177. _dl_exit(0);
  178. }
  179. #ifdef __SUPPORT_LD_DEBUG_EARLY__
  180. SEND_STDERR("ELF header=");
  181. SEND_ADDRESS_STDERR(load_addr, 1);
  182. #endif
  183. /* Locate the global offset table. Since this code must be PIC
  184. * we can take advantage of the magic offset register, if we
  185. * happen to know what that is for this architecture. If not,
  186. * we can always read stuff out of the ELF file to find it... */
  187. #if defined(__i386__)
  188. __asm__("\tmovl %%ebx,%0\n\t":"=a"(got));
  189. #elif defined(__m68k__)
  190. __asm__("movel %%a5,%0":"=g"(got));
  191. #elif defined(__sparc__)
  192. __asm__("\tmov %%l7,%0\n\t":"=r"(got));
  193. #elif defined(__arm__)
  194. __asm__("\tmov %0, r10\n\t":"=r"(got));
  195. #elif defined(__powerpc__)
  196. __asm__("\tbl _GLOBAL_OFFSET_TABLE_-4@local\n\t":"=l"(got));
  197. #elif defined(__mips__)
  198. __asm__("\tmove %0, $28\n\tsubu %0,%0,0x7ff0\n\t":"=r"(got));
  199. #elif defined(__sh__) && !defined(__SH5__)
  200. __asm__(
  201. " mov.l 1f, %0\n"
  202. " mova 1f, r0\n"
  203. " bra 2f\n"
  204. " add r0, %0\n"
  205. " .balign 4\n"
  206. "1: .long _GLOBAL_OFFSET_TABLE_\n"
  207. "2:" : "=r" (got) : : "r0");
  208. #elif defined(__cris__)
  209. __asm__("\tmove.d $pc,%0\n\tsub.d .:GOTOFF,%0\n\t":"=r"(got));
  210. #else
  211. /* Do things the slow way in C */
  212. {
  213. unsigned long tx_reloc;
  214. Elf32_Dyn *dynamic = NULL;
  215. Elf32_Shdr *shdr;
  216. Elf32_Phdr *pt_load;
  217. #ifdef __SUPPORT_LD_DEBUG_EARLY__
  218. SEND_STDERR("Finding the GOT using C code to read the ELF file\n");
  219. #endif
  220. /* Find where the dynamic linking information section is hiding */
  221. shdr = (Elf32_Shdr *) (header->e_shoff + (char *) header);
  222. for (indx = header->e_shnum; --indx >= 0; ++shdr) {
  223. if (shdr->sh_type == SHT_DYNAMIC) {
  224. goto found_dynamic;
  225. }
  226. }
  227. SEND_STDERR("missing dynamic linking information section \n");
  228. _dl_exit(0);
  229. found_dynamic:
  230. dynamic = (Elf32_Dyn *) (shdr->sh_offset + (char *) header);
  231. /* Find where PT_LOAD is hiding */
  232. pt_load = (Elf32_Phdr *) (header->e_phoff + (char *) header);
  233. for (indx = header->e_phnum; --indx >= 0; ++pt_load) {
  234. if (pt_load->p_type == PT_LOAD) {
  235. goto found_pt_load;
  236. }
  237. }
  238. SEND_STDERR("missing loadable program segment\n");
  239. _dl_exit(0);
  240. found_pt_load:
  241. /* Now (finally) find where DT_PLTGOT is hiding */
  242. tx_reloc = pt_load->p_vaddr - pt_load->p_offset;
  243. for (; DT_NULL != dynamic->d_tag; ++dynamic) {
  244. if (dynamic->d_tag == DT_PLTGOT) {
  245. goto found_got;
  246. }
  247. }
  248. SEND_STDERR("missing global offset table\n");
  249. _dl_exit(0);
  250. found_got:
  251. got = (unsigned long *) (dynamic->d_un.d_val - tx_reloc +
  252. (char *) header);
  253. }
  254. #endif
  255. /* Now, finally, fix up the location of the dynamic stuff */
  256. dpnt = (Elf32_Dyn *) (*got + load_addr);
  257. #ifdef __SUPPORT_LD_DEBUG_EARLY__
  258. SEND_STDERR("First Dynamic section entry=");
  259. SEND_ADDRESS_STDERR(dpnt, 1);
  260. #endif
  261. /* Call mmap to get a page of writable memory that can be used
  262. * for _dl_malloc throughout the shared lib loader. */
  263. mmap_zero = malloc_buffer = _dl_mmap((void *) 0, PAGE_SIZE,
  264. PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
  265. if (_dl_mmap_check_error(mmap_zero)) {
  266. SEND_STDERR("dl_boot: mmap of a spare page failed!\n");
  267. _dl_exit(13);
  268. }
  269. tpnt = LD_MALLOC(sizeof(struct elf_resolve));
  270. _dl_memset(tpnt, 0, sizeof(struct elf_resolve));
  271. app_tpnt = LD_MALLOC(sizeof(struct elf_resolve));
  272. _dl_memset(app_tpnt, 0, sizeof(struct elf_resolve));
  273. /* Find the runtime load address of the main executable, this may be
  274. * different from what the ELF header says for ET_DYN/PIE executables.
  275. */
  276. {
  277. int i;
  278. ElfW(Phdr) *ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_ptr;
  279. for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++)
  280. if (ppnt->p_type == PT_PHDR) {
  281. app_tpnt->loadaddr = (ElfW(Addr)) (auxvt[AT_PHDR].a_un.a_val - ppnt->p_vaddr);
  282. break;
  283. }
  284. #ifdef __SUPPORT_LD_DEBUG_EARLY__
  285. if (app_tpnt->loadaddr) {
  286. SEND_STDERR("Position Independent Executable: app_tpnt->loadaddr=");
  287. SEND_ADDRESS_STDERR(app_tpnt->loadaddr, 1);
  288. }
  289. #endif
  290. }
  291. /*
  292. * This is used by gdb to locate the chain of shared libraries that are currently loaded.
  293. */
  294. debug_addr = LD_MALLOC(sizeof(struct r_debug));
  295. _dl_memset(debug_addr, 0, sizeof(struct r_debug));
  296. /* OK, that was easy. Next scan the DYNAMIC section of the image.
  297. We are only doing ourself right now - we will have to do the rest later */
  298. #ifdef __SUPPORT_LD_DEBUG_EARLY__
  299. SEND_STDERR("scanning DYNAMIC section\n");
  300. #endif
  301. while (dpnt->d_tag) {
  302. #if defined(__mips__)
  303. if (dpnt->d_tag == DT_MIPS_GOTSYM)
  304. tpnt->mips_gotsym = (unsigned long) dpnt->d_un.d_val;
  305. if (dpnt->d_tag == DT_MIPS_LOCAL_GOTNO)
  306. tpnt->mips_local_gotno = (unsigned long) dpnt->d_un.d_val;
  307. if (dpnt->d_tag == DT_MIPS_SYMTABNO)
  308. tpnt->mips_symtabno = (unsigned long) dpnt->d_un.d_val;
  309. #endif
  310. if (dpnt->d_tag < 24) {
  311. tpnt->dynamic_info[dpnt->d_tag] = dpnt->d_un.d_val;
  312. if (dpnt->d_tag == DT_TEXTREL) {
  313. tpnt->dynamic_info[DT_TEXTREL] = 1;
  314. }
  315. }
  316. dpnt++;
  317. }
  318. {
  319. ElfW(Phdr) *ppnt;
  320. int i;
  321. ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_ptr;
  322. for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++)
  323. if (ppnt->p_type == PT_DYNAMIC) {
  324. dpnt = (Elf32_Dyn *) (ppnt->p_vaddr + app_tpnt->loadaddr);
  325. while (dpnt->d_tag) {
  326. #if defined(__mips__)
  327. if (dpnt->d_tag == DT_MIPS_GOTSYM)
  328. app_tpnt->mips_gotsym =
  329. (unsigned long) dpnt->d_un.d_val;
  330. if (dpnt->d_tag == DT_MIPS_LOCAL_GOTNO)
  331. app_tpnt->mips_local_gotno =
  332. (unsigned long) dpnt->d_un.d_val;
  333. if (dpnt->d_tag == DT_MIPS_SYMTABNO)
  334. app_tpnt->mips_symtabno =
  335. (unsigned long) dpnt->d_un.d_val;
  336. if (dpnt->d_tag > DT_JMPREL) {
  337. dpnt++;
  338. continue;
  339. }
  340. app_tpnt->dynamic_info[dpnt->d_tag] = dpnt->d_un.d_val;
  341. #warning "Debugging threads on mips won't work till someone fixes this..."
  342. #if 0
  343. if (dpnt->d_tag == DT_DEBUG) {
  344. dpnt->d_un.d_val = (unsigned long) debug_addr;
  345. }
  346. #endif
  347. #else
  348. if (dpnt->d_tag > DT_JMPREL) {
  349. dpnt++;
  350. continue;
  351. }
  352. app_tpnt->dynamic_info[dpnt->d_tag] = dpnt->d_un.d_val;
  353. if (dpnt->d_tag == DT_DEBUG) {
  354. dpnt->d_un.d_val = (unsigned long) debug_addr;
  355. }
  356. #endif
  357. if (dpnt->d_tag == DT_TEXTREL)
  358. app_tpnt->dynamic_info[DT_TEXTREL] = 1;
  359. dpnt++;
  360. }
  361. }
  362. }
  363. #ifdef __SUPPORT_LD_DEBUG_EARLY__
  364. SEND_STDERR("done scanning DYNAMIC section\n");
  365. #endif
  366. /* Get some more of the information that we will need to dynamicly link
  367. this module to itself */
  368. hash_addr = (unsigned long *) (tpnt->dynamic_info[DT_HASH] + load_addr);
  369. tpnt->nbucket = *hash_addr++;
  370. tpnt->nchain = *hash_addr++;
  371. tpnt->elf_buckets = hash_addr;
  372. hash_addr += tpnt->nbucket;
  373. #ifdef __SUPPORT_LD_DEBUG_EARLY__
  374. SEND_STDERR("done grabbing link information\n");
  375. #endif
  376. #ifndef FORCE_SHAREABLE_TEXT_SEGMENTS
  377. /* Ugly, ugly. We need to call mprotect to change the protection of
  378. the text pages so that we can do the dynamic linking. We can set the
  379. protection back again once we are done */
  380. {
  381. ElfW(Phdr) *ppnt;
  382. int i;
  383. #ifdef __SUPPORT_LD_DEBUG_EARLY__
  384. SEND_STDERR("calling mprotect on the shared library/dynamic linker\n");
  385. #endif
  386. /* First cover the shared library/dynamic linker. */
  387. if (tpnt->dynamic_info[DT_TEXTREL]) {
  388. header = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_ptr;
  389. ppnt = (ElfW(Phdr) *) ((int)auxvt[AT_BASE].a_un.a_ptr +
  390. header->e_phoff);
  391. for (i = 0; i < header->e_phnum; i++, ppnt++) {
  392. if (ppnt->p_type == PT_LOAD && !(ppnt->p_flags & PF_W)) {
  393. _dl_mprotect((void *) (load_addr + (ppnt->p_vaddr & PAGE_ALIGN)),
  394. (ppnt->p_vaddr & ADDR_ALIGN) + (unsigned long) ppnt->p_filesz,
  395. PROT_READ | PROT_WRITE | PROT_EXEC);
  396. }
  397. }
  398. }
  399. #ifdef __SUPPORT_LD_DEBUG_EARLY__
  400. SEND_STDERR("calling mprotect on the application program\n");
  401. #endif
  402. /* Now cover the application program. */
  403. if (app_tpnt->dynamic_info[DT_TEXTREL]) {
  404. ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_ptr;
  405. for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++) {
  406. if (ppnt->p_type == PT_LOAD && !(ppnt->p_flags & PF_W))
  407. _dl_mprotect((void *) ((ppnt->p_vaddr + app_tpnt->loadaddr) & PAGE_ALIGN),
  408. ((ppnt->p_vaddr + app_tpnt->loadaddr) & ADDR_ALIGN) +
  409. (unsigned long) ppnt->p_filesz,
  410. PROT_READ | PROT_WRITE | PROT_EXEC);
  411. }
  412. }
  413. }
  414. #endif
  415. #if defined(__mips__)
  416. #ifdef __SUPPORT_LD_DEBUG_EARLY__
  417. SEND_STDERR("About to do MIPS specific GOT bootstrap\n");
  418. #endif
  419. /* For MIPS we have to do stuff to the GOT before we do relocations. */
  420. PERFORM_BOOTSTRAP_GOT(got);
  421. #endif
  422. /* OK, now do the relocations. We do not do a lazy binding here, so
  423. that once we are done, we have considerably more flexibility. */
  424. #ifdef __SUPPORT_LD_DEBUG_EARLY__
  425. SEND_STDERR("About to do library loader relocations\n");
  426. #endif
  427. goof = 0;
  428. for (indx = 0; indx < 2; indx++) {
  429. unsigned int i;
  430. ELF_RELOC *rpnt;
  431. unsigned long *reloc_addr;
  432. unsigned long symbol_addr;
  433. int symtab_index;
  434. unsigned long rel_addr, rel_size;
  435. rel_addr = (indx ? tpnt->dynamic_info[DT_JMPREL] : tpnt->
  436. dynamic_info[DT_RELOC_TABLE_ADDR]);
  437. rel_size = (indx ? tpnt->dynamic_info[DT_PLTRELSZ] : tpnt->
  438. dynamic_info[DT_RELOC_TABLE_SIZE]);
  439. if (!rel_addr)
  440. continue;
  441. /* Now parse the relocation information */
  442. rpnt = (ELF_RELOC *) (rel_addr + load_addr);
  443. for (i = 0; i < rel_size; i += sizeof(ELF_RELOC), rpnt++) {
  444. reloc_addr = (unsigned long *) (load_addr + (unsigned long) rpnt->r_offset);
  445. symtab_index = ELF32_R_SYM(rpnt->r_info);
  446. symbol_addr = 0;
  447. if (symtab_index) {
  448. char *strtab;
  449. char *symname;
  450. Elf32_Sym *symtab;
  451. symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + load_addr);
  452. strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + load_addr);
  453. symname = strtab + symtab[symtab_index].st_name;
  454. /* We only do a partial dynamic linking right now. The user
  455. is not supposed to define any symbols that start with a
  456. '_dl', so we can do this with confidence. */
  457. if (!symname || !_dl_symbol(symname)) {
  458. continue;
  459. }
  460. symbol_addr = load_addr + symtab[symtab_index].st_value;
  461. if (!symbol_addr) {
  462. /* This will segfault - you cannot call a function until
  463. * we have finished the relocations.
  464. */
  465. SEND_STDERR("ELF dynamic loader - unable to self-bootstrap - symbol ");
  466. SEND_STDERR(symname);
  467. SEND_STDERR(" undefined.\n");
  468. goof++;
  469. }
  470. #ifdef __SUPPORT_LD_DEBUG_EARLY__
  471. SEND_STDERR("relocating symbol: ");
  472. SEND_STDERR(symname);
  473. SEND_STDERR("\n");
  474. #endif
  475. PERFORM_BOOTSTRAP_RELOC(rpnt, reloc_addr, symbol_addr, load_addr, &symtab[symtab_index]);
  476. } else {
  477. /* Use this machine-specific macro to perform the actual relocation. */
  478. PERFORM_BOOTSTRAP_RELOC(rpnt, reloc_addr, symbol_addr, load_addr, NULL);
  479. }
  480. }
  481. }
  482. if (goof) {
  483. _dl_exit(14);
  484. }
  485. #ifdef __SUPPORT_LD_DEBUG_EARLY__
  486. /* Wahoo!!! */
  487. SEND_STDERR("Done relocating library loader, so we can now\n"
  488. "\tuse globals and make function calls!\n");
  489. #endif
  490. /* Now we have done the mandatory linking of some things. We are now
  491. free to start using global variables, since these things have all been
  492. fixed up by now. Still no function calls outside of this library ,
  493. since the dynamic resolver is not yet ready. */
  494. _dl_get_ready_to_run(tpnt, app_tpnt, load_addr, hash_addr,
  495. auxvt, envp, debug_addr, malloc_buffer, mmap_zero, argv);
  496. /* Transfer control to the application. */
  497. #ifdef __SUPPORT_LD_DEBUG_EARLY__
  498. SEND_STDERR("transfering control to application\n");
  499. #endif
  500. _dl_elf_main = (int (*)(int, char **, char **)) auxvt[AT_ENTRY].a_un.a_fcn;
  501. START();
  502. }