elfinterp.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. /* Run an ELF binary on a linux system.
  2. Copyright (C) 1993, Eric Youngdale.
  3. Copyright (C) 1995, Andreas Schwab.
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2, or (at your option)
  7. any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
  15. /* Adapted to ELF/68k by Andreas Schwab. */
  16. #ifndef VERBOSE_DLINKER
  17. #define VERBOSE_DLINKER
  18. #endif
  19. #ifdef VERBOSE_DLINKER
  20. static char *_dl_reltypes[] =
  21. {
  22. "R_68K_NONE",
  23. "R_68K_32", "R_68K_16", "R_68K_8",
  24. "R_68K_PC32", "R_68K_PC16", "R_68K_PC8",
  25. "R_68K_GOT32", "R_68K_GOT16", "R_68K_GOT8",
  26. "R_68K_GOT32O", "R_68K_GOT16O", "R_68K_GOT8O",
  27. "R_68K_PLT32", "R_68K_PLT16", "R_68K_PLT8",
  28. "R_68K_PLT32O", "R_68K_PLT16O", "R_68K_PLT8O",
  29. "R_68K_COPY", "R_68K_GLOB_DAT", "R_68K_JMP_SLOT", "R_68K_RELATIVE",
  30. "R_68K_NUM"
  31. };
  32. #endif
  33. /* Program to load an ELF binary on a linux system, and run it.
  34. References to symbols in sharable libraries can be resolved by either
  35. an ELF sharable library or a linux style of shared library. */
  36. /* Disclaimer: I have never seen any AT&T source code for SVr4, nor have
  37. I ever taken any courses on internals. This program was developed using
  38. information available through the book "UNIX SYSTEM V RELEASE 4,
  39. Programmers guide: Ansi C and Programming Support Tools", which did
  40. a more than adequate job of explaining everything required to get this
  41. working. */
  42. #include <linux/types.h>
  43. #include <linux/errno.h>
  44. #include <linux/unistd.h>
  45. /*#include <stdlib.h>*/
  46. #include "string.h"
  47. #include <linux/unistd.h>
  48. #include <linux/fcntl.h>
  49. #include <linux/elf.h>
  50. #include "hash.h"
  51. #include "linuxelf.h"
  52. #include "sysdep.h"
  53. #include "../syscall.h"
  54. #include "../string.h"
  55. extern char *_dl_progname;
  56. unsigned int
  57. _dl_linux_resolver (int dummy1, int dummy2,
  58. struct elf_resolve *tpnt, int reloc_entry)
  59. {
  60. int reloc_type;
  61. struct elf32_rela *this_reloc;
  62. char *strtab;
  63. struct 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 = (struct 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 = (struct 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_fdprintf (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 DEBUG
  86. _dl_fdprintf (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, (int) got_addr, tpnt, 0);
  92. if (!new_addr)
  93. {
  94. _dl_fdprintf (2, "%s: can't resolve symbol '%s'\n",
  95. _dl_progname, strtab + symtab[symtab_index].st_name);
  96. _dl_exit (1);
  97. }
  98. /* #define DEBUG_LIBRARY */
  99. #ifdef DEBUG_LIBRARY
  100. if ((unsigned int) got_addr < 0x40000000)
  101. _dl_fdprintf (2, "Calling library function: %s\n",
  102. strtab + symtab[symtab_index].st_name);
  103. else
  104. #endif
  105. *got_addr = new_addr;
  106. return (unsigned int) new_addr;
  107. }
  108. void
  109. _dl_parse_lazy_relocation_information (struct elf_resolve *tpnt, int rel_addr,
  110. int rel_size, int type)
  111. {
  112. int i;
  113. char *strtab;
  114. int reloc_type;
  115. int symtab_index;
  116. struct elf32_sym *symtab;
  117. struct elf32_rela *rpnt;
  118. unsigned int *reloc_addr;
  119. /* Now parse the relocation information. */
  120. rpnt = (struct elf32_rela *) (rel_addr + tpnt->loadaddr);
  121. rel_size = rel_size / sizeof (struct elf32_rela);
  122. symtab = (struct elf32_sym *) (tpnt->dynamic_info[DT_SYMTAB]
  123. + tpnt->loadaddr);
  124. strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
  125. for (i = 0; i < rel_size; i++, rpnt++)
  126. {
  127. reloc_addr = (int *) (tpnt->loadaddr + (int) rpnt->r_offset);
  128. reloc_type = ELF32_R_TYPE (rpnt->r_info);
  129. symtab_index = ELF32_R_SYM (rpnt->r_info);
  130. /* When the dynamic linker bootstrapped itself, it resolved some symbols.
  131. Make sure we do not do them again. */
  132. if (tpnt->libtype == program_interpreter
  133. && (!symtab_index
  134. || _dl_symbol (strtab + symtab[symtab_index].st_name)))
  135. continue;
  136. switch (reloc_type)
  137. {
  138. case R_68K_NONE:
  139. break;
  140. case R_68K_JMP_SLOT:
  141. *reloc_addr += (unsigned int) tpnt->loadaddr;
  142. break;
  143. default:
  144. _dl_fdprintf (2, "%s: (LAZY) can't handle reloc type ", _dl_progname);
  145. #ifdef VERBOSE_DLINKER
  146. _dl_fdprintf (2, "%s ", _dl_reltypes[reloc_type]);
  147. #endif
  148. if (symtab_index)
  149. _dl_fdprintf (2, "'%s'", strtab + symtab[symtab_index].st_name);
  150. _dl_fdprintf (2, "\n");
  151. _dl_exit (1);
  152. }
  153. }
  154. }
  155. int
  156. _dl_parse_relocation_information (struct elf_resolve *tpnt, int rel_addr,
  157. int rel_size, int type)
  158. {
  159. int i;
  160. char *strtab;
  161. int reloc_type;
  162. int goof = 0;
  163. struct elf32_sym *symtab;
  164. struct elf32_rela *rpnt;
  165. unsigned int *reloc_addr;
  166. unsigned int symbol_addr;
  167. int symtab_index;
  168. /* Now parse the relocation information */
  169. rpnt = (struct elf32_rela *) (rel_addr + tpnt->loadaddr);
  170. rel_size = rel_size / sizeof (struct elf32_rela);
  171. symtab = (struct elf32_sym *) (tpnt->dynamic_info[DT_SYMTAB]
  172. + tpnt->loadaddr);
  173. strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
  174. for (i = 0; i < rel_size; i++, rpnt++)
  175. {
  176. reloc_addr = (int *) (tpnt->loadaddr + (int) rpnt->r_offset);
  177. reloc_type = ELF32_R_TYPE (rpnt->r_info);
  178. symtab_index = ELF32_R_SYM (rpnt->r_info);
  179. symbol_addr = 0;
  180. if (tpnt->libtype == program_interpreter
  181. && (!symtab_index
  182. || _dl_symbol (strtab + symtab[symtab_index].st_name)))
  183. continue;
  184. if (symtab_index)
  185. {
  186. symbol_addr = (unsigned int)
  187. _dl_find_hash (strtab + symtab[symtab_index].st_name,
  188. tpnt->symbol_scope, (int) reloc_addr,
  189. reloc_type == R_68K_JMP_SLOT ? tpnt : NULL, 0);
  190. /* We want to allow undefined references to weak symbols -
  191. this might have been intentional. We should not be
  192. linking local symbols here, so all bases should be
  193. covered. */
  194. if (!symbol_addr
  195. && ELF32_ST_BIND (symtab[symtab_index].st_info) == STB_GLOBAL)
  196. {
  197. _dl_fdprintf (2, "%s: can't resolve symbol '%s'\n",
  198. _dl_progname, strtab + symtab[symtab_index].st_name);
  199. goof++;
  200. }
  201. }
  202. switch (reloc_type)
  203. {
  204. case R_68K_NONE:
  205. break;
  206. case R_68K_8:
  207. *(char *) reloc_addr = symbol_addr + rpnt->r_addend;
  208. break;
  209. case R_68K_16:
  210. *(short *) reloc_addr = symbol_addr + rpnt->r_addend;
  211. break;
  212. case R_68K_32:
  213. *reloc_addr = symbol_addr + rpnt->r_addend;
  214. break;
  215. case R_68K_PC8:
  216. *(char *) reloc_addr = (symbol_addr + rpnt->r_addend
  217. - (unsigned int) reloc_addr);
  218. break;
  219. case R_68K_PC16:
  220. *(short *) reloc_addr = (symbol_addr + rpnt->r_addend
  221. - (unsigned int) reloc_addr);
  222. break;
  223. case R_68K_PC32:
  224. *reloc_addr = (symbol_addr + rpnt->r_addend
  225. - (unsigned int) reloc_addr);
  226. break;
  227. case R_68K_GLOB_DAT:
  228. case R_68K_JMP_SLOT:
  229. *reloc_addr = symbol_addr;
  230. break;
  231. case R_68K_RELATIVE:
  232. *reloc_addr = ((unsigned int) tpnt->loadaddr
  233. /* Compatibility kludge. */
  234. + (rpnt->r_addend ? : *reloc_addr));
  235. break;
  236. case R_68K_COPY:
  237. #if 0 /* Do this later. */
  238. _dl_fdprintf (2, "Doing copy");
  239. if (symtab_index)
  240. _dl_fdprintf (2, " for symbol %s",
  241. strtab + symtab[symtab_index].st_name);
  242. _dl_fdprintf (2, "\n");
  243. _dl_memcpy ((void *) symtab[symtab_index].st_value,
  244. (void *) symbol_addr,
  245. symtab[symtab_index].st_size);
  246. #endif
  247. break;
  248. default:
  249. _dl_fdprintf (2, "%s: can't handle reloc type ", _dl_progname);
  250. #ifdef VERBOSE_DLINKER
  251. _dl_fdprintf (2, "%s ", _dl_reltypes[reloc_type]);
  252. #endif
  253. if (symtab_index)
  254. _dl_fdprintf (2, "'%s'", strtab + symtab[symtab_index].st_name);
  255. _dl_fdprintf (2, "\n");
  256. _dl_exit (1);
  257. }
  258. }
  259. return goof;
  260. }
  261. /* This is done as a separate step, because there are cases where
  262. information is first copied and later initialized. This results in
  263. the wrong information being copied. Someone at Sun was complaining about
  264. a bug in the handling of _COPY by SVr4, and this may in fact be what he
  265. was talking about. Sigh. */
  266. /* No, there are cases where the SVr4 linker fails to emit COPY relocs
  267. at all. */
  268. int
  269. _dl_parse_copy_information (struct dyn_elf *xpnt, int rel_addr,
  270. int rel_size, int type)
  271. {
  272. int i;
  273. char *strtab;
  274. int reloc_type;
  275. int goof = 0;
  276. struct elf32_sym *symtab;
  277. struct elf32_rela *rpnt;
  278. unsigned int *reloc_addr;
  279. unsigned int symbol_addr;
  280. struct elf_resolve *tpnt;
  281. int symtab_index;
  282. /* Now parse the relocation information */
  283. tpnt = xpnt->dyn;
  284. rpnt = (struct elf32_rela *) (rel_addr + tpnt->loadaddr);
  285. rel_size = rel_size / sizeof (struct elf32_rela);
  286. symtab = (struct elf32_sym *) (tpnt->dynamic_info[DT_SYMTAB]
  287. + tpnt->loadaddr);
  288. strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
  289. for (i = 0; i < rel_size; i++, rpnt++)
  290. {
  291. reloc_addr = (int *) (tpnt->loadaddr + (int) rpnt->r_offset);
  292. reloc_type = ELF32_R_TYPE (rpnt->r_info);
  293. if (reloc_type != R_68K_COPY)
  294. continue;
  295. symtab_index = ELF32_R_SYM (rpnt->r_info);
  296. symbol_addr = 0;
  297. if (tpnt->libtype == program_interpreter
  298. && (!symtab_index
  299. || _dl_symbol (strtab + symtab[symtab_index].st_name)))
  300. continue;
  301. if (symtab_index)
  302. {
  303. symbol_addr = (unsigned int)
  304. _dl_find_hash (strtab + symtab[symtab_index].st_name,
  305. xpnt->next, (int) reloc_addr, NULL, 1);
  306. if (!symbol_addr)
  307. {
  308. _dl_fdprintf (2, "%s: can't resolve symbol '%s'\n",
  309. _dl_progname, strtab + symtab[symtab_index].st_name);
  310. goof++;
  311. }
  312. }
  313. if (!goof)
  314. _dl_memcpy ((void *) symtab[symtab_index].st_value, (void *) symbol_addr,
  315. symtab[symtab_index].st_size);
  316. }
  317. return goof;
  318. }