elfinterp.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. /* vi: set sw=4 ts=4: */
  2. /* m68k ELF shared library loader suppport
  3. *
  4. * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
  5. * David Engel, Hongjiu Lu and Mitch D'Souza
  6. * Adapted to ELF/68k by Andreas Schwab.
  7. *
  8. * All rights reserved.
  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. #ifndef VERBOSE_DLINKER
  32. #define VERBOSE_DLINKER
  33. #endif
  34. #ifdef VERBOSE_DLINKER
  35. static const char *_dl_reltypes[] =
  36. {
  37. "R_68K_NONE",
  38. "R_68K_32", "R_68K_16", "R_68K_8",
  39. "R_68K_PC32", "R_68K_PC16", "R_68K_PC8",
  40. "R_68K_GOT32", "R_68K_GOT16", "R_68K_GOT8",
  41. "R_68K_GOT32O", "R_68K_GOT16O", "R_68K_GOT8O",
  42. "R_68K_PLT32", "R_68K_PLT16", "R_68K_PLT8",
  43. "R_68K_PLT32O", "R_68K_PLT16O", "R_68K_PLT8O",
  44. "R_68K_COPY", "R_68K_GLOB_DAT", "R_68K_JMP_SLOT", "R_68K_RELATIVE",
  45. "R_68K_NUM"
  46. };
  47. #endif
  48. /* Program to load an ELF binary on a linux system, and run it.
  49. References to symbols in sharable libraries can be resolved by either
  50. an ELF sharable library or a linux style of shared library. */
  51. /* Disclaimer: I have never seen any AT&T source code for SVr4, nor have
  52. I ever taken any courses on internals. This program was developed using
  53. information available through the book "UNIX SYSTEM V RELEASE 4,
  54. Programmers guide: Ansi C and Programming Support Tools", which did
  55. a more than adequate job of explaining everything required to get this
  56. working. */
  57. unsigned int _dl_linux_resolver (int dummy1, int dummy2,
  58. struct elf_resolve *tpnt, int reloc_entry)
  59. {
  60. int reloc_type;
  61. Elf32_Rela *this_reloc;
  62. char *strtab;
  63. Elf32_Sym *symtab;
  64. char *rel_addr;
  65. int symtab_index;
  66. char *new_addr;
  67. char **got_addr;
  68. unsigned int instr_addr;
  69. rel_addr = tpnt->loadaddr + tpnt->dynamic_info[DT_JMPREL];
  70. this_reloc = (Elf32_Rela *) (rel_addr + reloc_entry);
  71. reloc_type = ELF32_R_TYPE (this_reloc->r_info);
  72. symtab_index = ELF32_R_SYM (this_reloc->r_info);
  73. symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB]
  74. + tpnt->loadaddr);
  75. strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
  76. if (reloc_type != R_68K_JMP_SLOT)
  77. {
  78. _dl_dprintf (2, "%s: incorrect relocation type in jump relocations\n",
  79. _dl_progname);
  80. _dl_exit (1);
  81. }
  82. /* Address of jump instruction to fix up. */
  83. instr_addr = (int) this_reloc->r_offset + (int) tpnt->loadaddr;
  84. got_addr = (char **) instr_addr;
  85. #ifdef LD_DEBUG_SYMBOLS
  86. _dl_dprintf (2, "Resolving symbol %s\n",
  87. strtab + symtab[symtab_index].st_name);
  88. #endif
  89. /* Get the address of the GOT entry. */
  90. new_addr = _dl_find_hash (strtab + symtab[symtab_index].st_name,
  91. tpnt->symbol_scope, tpnt, resolver);
  92. if (!new_addr)
  93. {
  94. _dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
  95. _dl_progname, strtab + symtab[symtab_index].st_name);
  96. _dl_exit (1);
  97. }
  98. #ifdef LD_NEVER_FIXUP_SYMBOLS
  99. if ((unsigned int) got_addr < 0x40000000) {
  100. _dl_dprintf (2, "Calling library function: %s\n",
  101. strtab + symtab[symtab_index].st_name);
  102. } else {
  103. *got_addr = new_addr;
  104. }
  105. #else
  106. *got_addr = new_addr;
  107. #endif
  108. return (unsigned int) new_addr;
  109. }
  110. void
  111. _dl_parse_lazy_relocation_information (struct elf_resolve *tpnt,
  112. unsigned long rel_addr, unsigned long rel_size, int type)
  113. {
  114. int i;
  115. char *strtab;
  116. int reloc_type;
  117. int symtab_index;
  118. Elf32_Sym *symtab;
  119. Elf32_Rela *rpnt;
  120. unsigned int *reloc_addr;
  121. /* Now parse the relocation information. */
  122. rpnt = (Elf32_Rela *) (rel_addr + tpnt->loadaddr);
  123. rel_size = rel_size / sizeof (Elf32_Rela);
  124. symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB]
  125. + tpnt->loadaddr);
  126. strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
  127. for (i = 0; i < rel_size; i++, rpnt++)
  128. {
  129. reloc_addr = (int *) (tpnt->loadaddr + (int) rpnt->r_offset);
  130. reloc_type = ELF32_R_TYPE (rpnt->r_info);
  131. symtab_index = ELF32_R_SYM (rpnt->r_info);
  132. /* When the dynamic linker bootstrapped itself, it resolved some symbols.
  133. Make sure we do not do them again. */
  134. if (tpnt->libtype == program_interpreter
  135. && (!symtab_index
  136. || _dl_symbol (strtab + symtab[symtab_index].st_name)))
  137. continue;
  138. switch (reloc_type)
  139. {
  140. case R_68K_NONE:
  141. break;
  142. case R_68K_JMP_SLOT:
  143. *reloc_addr += (unsigned int) tpnt->loadaddr;
  144. break;
  145. default:
  146. _dl_dprintf (2, "%s: (LAZY) can't handle reloc type ", _dl_progname);
  147. #ifdef VERBOSE_DLINKER
  148. _dl_dprintf (2, "%s ", _dl_reltypes[reloc_type]);
  149. #endif
  150. if (symtab_index)
  151. _dl_dprintf (2, "'%s'", strtab + symtab[symtab_index].st_name);
  152. _dl_dprintf (2, "\n");
  153. _dl_exit (1);
  154. }
  155. }
  156. }
  157. int
  158. _dl_parse_relocation_information (struct elf_resolve *tpnt,
  159. unsigned long rel_addr, unsigned long rel_size, int type)
  160. {
  161. int i;
  162. char *strtab;
  163. int reloc_type;
  164. int goof = 0;
  165. Elf32_Sym *symtab;
  166. Elf32_Rela *rpnt;
  167. unsigned int *reloc_addr;
  168. unsigned int symbol_addr;
  169. int symtab_index;
  170. /* Now parse the relocation information */
  171. rpnt = (Elf32_Rela *) (rel_addr + tpnt->loadaddr);
  172. rel_size = rel_size / sizeof (Elf32_Rela);
  173. symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB]
  174. + tpnt->loadaddr);
  175. strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
  176. for (i = 0; i < rel_size; i++, rpnt++)
  177. {
  178. reloc_addr = (int *) (tpnt->loadaddr + (int) rpnt->r_offset);
  179. reloc_type = ELF32_R_TYPE (rpnt->r_info);
  180. symtab_index = ELF32_R_SYM (rpnt->r_info);
  181. symbol_addr = 0;
  182. if (tpnt->libtype == program_interpreter
  183. && (!symtab_index
  184. || _dl_symbol (strtab + symtab[symtab_index].st_name)))
  185. continue;
  186. if (symtab_index)
  187. {
  188. symbol_addr = (unsigned int)
  189. _dl_find_hash (strtab + symtab[symtab_index].st_name,
  190. tpnt->symbol_scope,
  191. reloc_type == R_68K_JMP_SLOT ? tpnt : NULL, symbolrel);
  192. /* We want to allow undefined references to weak symbols -
  193. this might have been intentional. We should not be
  194. linking local symbols here, so all bases should be
  195. covered. */
  196. if (!symbol_addr
  197. && ELF32_ST_BIND (symtab[symtab_index].st_info) == STB_GLOBAL)
  198. {
  199. _dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
  200. _dl_progname, strtab + symtab[symtab_index].st_name);
  201. goof++;
  202. }
  203. }
  204. switch (reloc_type)
  205. {
  206. case R_68K_NONE:
  207. break;
  208. case R_68K_8:
  209. *(char *) reloc_addr = symbol_addr + rpnt->r_addend;
  210. break;
  211. case R_68K_16:
  212. *(short *) reloc_addr = symbol_addr + rpnt->r_addend;
  213. break;
  214. case R_68K_32:
  215. *reloc_addr = symbol_addr + rpnt->r_addend;
  216. break;
  217. case R_68K_PC8:
  218. *(char *) reloc_addr = (symbol_addr + rpnt->r_addend
  219. - (unsigned int) reloc_addr);
  220. break;
  221. case R_68K_PC16:
  222. *(short *) reloc_addr = (symbol_addr + rpnt->r_addend
  223. - (unsigned int) reloc_addr);
  224. break;
  225. case R_68K_PC32:
  226. *reloc_addr = (symbol_addr + rpnt->r_addend
  227. - (unsigned int) reloc_addr);
  228. break;
  229. case R_68K_GLOB_DAT:
  230. case R_68K_JMP_SLOT:
  231. *reloc_addr = symbol_addr;
  232. break;
  233. case R_68K_RELATIVE:
  234. *reloc_addr = ((unsigned int) tpnt->loadaddr
  235. /* Compatibility kludge. */
  236. + (rpnt->r_addend ? : *reloc_addr));
  237. break;
  238. case R_68K_COPY:
  239. #if 0 /* Do this later. */
  240. _dl_dprintf (2, "Doing copy");
  241. if (symtab_index)
  242. _dl_dprintf (2, " for symbol %s",
  243. strtab + symtab[symtab_index].st_name);
  244. _dl_dprintf (2, "\n");
  245. _dl_memcpy ((void *) symtab[symtab_index].st_value,
  246. (void *) symbol_addr,
  247. symtab[symtab_index].st_size);
  248. #endif
  249. break;
  250. default:
  251. _dl_dprintf (2, "%s: can't handle reloc type ", _dl_progname);
  252. #ifdef VERBOSE_DLINKER
  253. _dl_dprintf (2, "%s ", _dl_reltypes[reloc_type]);
  254. #endif
  255. if (symtab_index)
  256. _dl_dprintf (2, "'%s'", strtab + symtab[symtab_index].st_name);
  257. _dl_dprintf (2, "\n");
  258. _dl_exit (1);
  259. }
  260. }
  261. return goof;
  262. }
  263. /* This is done as a separate step, because there are cases where
  264. information is first copied and later initialized. This results in
  265. the wrong information being copied. Someone at Sun was complaining about
  266. a bug in the handling of _COPY by SVr4, and this may in fact be what he
  267. was talking about. Sigh. */
  268. /* No, there are cases where the SVr4 linker fails to emit COPY relocs
  269. at all. */
  270. int
  271. _dl_parse_copy_information (struct dyn_elf *xpnt, unsigned long rel_addr,
  272. unsigned long rel_size, int type)
  273. {
  274. int i;
  275. char *strtab;
  276. int reloc_type;
  277. int goof = 0;
  278. Elf32_Sym *symtab;
  279. Elf32_Rela *rpnt;
  280. unsigned int *reloc_addr;
  281. unsigned int symbol_addr;
  282. struct elf_resolve *tpnt;
  283. int symtab_index;
  284. /* Now parse the relocation information */
  285. tpnt = xpnt->dyn;
  286. rpnt = (Elf32_Rela *) (rel_addr + tpnt->loadaddr);
  287. rel_size = rel_size / sizeof (Elf32_Rela);
  288. symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB]
  289. + tpnt->loadaddr);
  290. strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
  291. for (i = 0; i < rel_size; i++, rpnt++)
  292. {
  293. reloc_addr = (int *) (tpnt->loadaddr + (int) rpnt->r_offset);
  294. reloc_type = ELF32_R_TYPE (rpnt->r_info);
  295. if (reloc_type != R_68K_COPY)
  296. continue;
  297. symtab_index = ELF32_R_SYM (rpnt->r_info);
  298. symbol_addr = 0;
  299. if (tpnt->libtype == program_interpreter
  300. && (!symtab_index
  301. || _dl_symbol (strtab + symtab[symtab_index].st_name)))
  302. continue;
  303. if (symtab_index)
  304. {
  305. symbol_addr = (unsigned int)
  306. _dl_find_hash (strtab + symtab[symtab_index].st_name,
  307. xpnt->next, NULL, copyrel);
  308. if (!symbol_addr)
  309. {
  310. _dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
  311. _dl_progname, strtab + symtab[symtab_index].st_name);
  312. goof++;
  313. }
  314. }
  315. if (!goof)
  316. _dl_memcpy ((void *) symtab[symtab_index].st_value, (void *) symbol_addr,
  317. symtab[symtab_index].st_size);
  318. }
  319. return goof;
  320. }