elfinterp.c 10 KB

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