elfinterp.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  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 <sys/types.h>
  43. #include "elf.h"
  44. #include "hash.h"
  45. #include "syscall.h"
  46. #include "string.h"
  47. #include "sysdep.h"
  48. extern char *_dl_progname;
  49. unsigned int
  50. _dl_linux_resolver (int dummy1, int dummy2,
  51. struct elf_resolve *tpnt, int reloc_entry)
  52. {
  53. int reloc_type;
  54. Elf32_Rela *this_reloc;
  55. char *strtab;
  56. Elf32_Sym *symtab;
  57. char *rel_addr;
  58. int symtab_index;
  59. char *new_addr;
  60. char **got_addr;
  61. unsigned int instr_addr;
  62. rel_addr = tpnt->loadaddr + tpnt->dynamic_info[DT_JMPREL];
  63. this_reloc = (Elf32_Rela *) (rel_addr + reloc_entry);
  64. reloc_type = ELF32_R_TYPE (this_reloc->r_info);
  65. symtab_index = ELF32_R_SYM (this_reloc->r_info);
  66. symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB]
  67. + tpnt->loadaddr);
  68. strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
  69. if (reloc_type != R_68K_JMP_SLOT)
  70. {
  71. _dl_dprintf (2, "%s: incorrect relocation type in jump relocations\n",
  72. _dl_progname);
  73. _dl_exit (1);
  74. }
  75. /* Address of jump instruction to fix up. */
  76. instr_addr = (int) this_reloc->r_offset + (int) tpnt->loadaddr;
  77. got_addr = (char **) instr_addr;
  78. #ifdef DEBUG
  79. _dl_dprintf (2, "Resolving symbol %s\n",
  80. strtab + symtab[symtab_index].st_name);
  81. #endif
  82. /* Get the address of the GOT entry. */
  83. new_addr = _dl_find_hash (strtab + symtab[symtab_index].st_name,
  84. tpnt->symbol_scope, (int) got_addr, tpnt, 0);
  85. if (!new_addr)
  86. {
  87. _dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
  88. _dl_progname, strtab + symtab[symtab_index].st_name);
  89. _dl_exit (1);
  90. }
  91. /* #define DEBUG_LIBRARY */
  92. #ifdef DEBUG_LIBRARY
  93. if ((unsigned int) got_addr < 0x40000000)
  94. _dl_dprintf (2, "Calling library function: %s\n",
  95. strtab + symtab[symtab_index].st_name);
  96. else
  97. #endif
  98. *got_addr = new_addr;
  99. return (unsigned int) new_addr;
  100. }
  101. void
  102. _dl_parse_lazy_relocation_information (struct elf_resolve *tpnt,
  103. unsigned long rel_addr, unsigned long rel_size, int type)
  104. {
  105. int i;
  106. char *strtab;
  107. int reloc_type;
  108. int symtab_index;
  109. Elf32_Sym *symtab;
  110. Elf32_Rela *rpnt;
  111. unsigned int *reloc_addr;
  112. /* Now parse the relocation information. */
  113. rpnt = (Elf32_Rela *) (rel_addr + tpnt->loadaddr);
  114. rel_size = rel_size / sizeof (Elf32_Rela);
  115. symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB]
  116. + tpnt->loadaddr);
  117. strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
  118. for (i = 0; i < rel_size; i++, rpnt++)
  119. {
  120. reloc_addr = (int *) (tpnt->loadaddr + (int) rpnt->r_offset);
  121. reloc_type = ELF32_R_TYPE (rpnt->r_info);
  122. symtab_index = ELF32_R_SYM (rpnt->r_info);
  123. /* When the dynamic linker bootstrapped itself, it resolved some symbols.
  124. Make sure we do not do them again. */
  125. if (tpnt->libtype == program_interpreter
  126. && (!symtab_index
  127. || _dl_symbol (strtab + symtab[symtab_index].st_name)))
  128. continue;
  129. switch (reloc_type)
  130. {
  131. case R_68K_NONE:
  132. break;
  133. case R_68K_JMP_SLOT:
  134. *reloc_addr += (unsigned int) tpnt->loadaddr;
  135. break;
  136. default:
  137. _dl_dprintf (2, "%s: (LAZY) can't handle reloc type ", _dl_progname);
  138. #ifdef VERBOSE_DLINKER
  139. _dl_dprintf (2, "%s ", _dl_reltypes[reloc_type]);
  140. #endif
  141. if (symtab_index)
  142. _dl_dprintf (2, "'%s'", strtab + symtab[symtab_index].st_name);
  143. _dl_dprintf (2, "\n");
  144. _dl_exit (1);
  145. }
  146. }
  147. }
  148. int
  149. _dl_parse_relocation_information (struct elf_resolve *tpnt,
  150. unsigned long rel_addr, unsigned long rel_size, int type)
  151. {
  152. int i;
  153. char *strtab;
  154. int reloc_type;
  155. int goof = 0;
  156. Elf32_Sym *symtab;
  157. Elf32_Rela *rpnt;
  158. unsigned int *reloc_addr;
  159. unsigned int symbol_addr;
  160. int symtab_index;
  161. /* Now parse the relocation information */
  162. rpnt = (Elf32_Rela *) (rel_addr + tpnt->loadaddr);
  163. rel_size = rel_size / sizeof (Elf32_Rela);
  164. symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB]
  165. + tpnt->loadaddr);
  166. strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
  167. for (i = 0; i < rel_size; i++, rpnt++)
  168. {
  169. reloc_addr = (int *) (tpnt->loadaddr + (int) rpnt->r_offset);
  170. reloc_type = ELF32_R_TYPE (rpnt->r_info);
  171. symtab_index = ELF32_R_SYM (rpnt->r_info);
  172. symbol_addr = 0;
  173. if (tpnt->libtype == program_interpreter
  174. && (!symtab_index
  175. || _dl_symbol (strtab + symtab[symtab_index].st_name)))
  176. continue;
  177. if (symtab_index)
  178. {
  179. symbol_addr = (unsigned int)
  180. _dl_find_hash (strtab + symtab[symtab_index].st_name,
  181. tpnt->symbol_scope, (int) reloc_addr,
  182. reloc_type == R_68K_JMP_SLOT ? tpnt : NULL, 0);
  183. /* We want to allow undefined references to weak symbols -
  184. this might have been intentional. We should not be
  185. linking local symbols here, so all bases should be
  186. covered. */
  187. if (!symbol_addr
  188. && ELF32_ST_BIND (symtab[symtab_index].st_info) == STB_GLOBAL)
  189. {
  190. _dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
  191. _dl_progname, strtab + symtab[symtab_index].st_name);
  192. goof++;
  193. }
  194. }
  195. switch (reloc_type)
  196. {
  197. case R_68K_NONE:
  198. break;
  199. case R_68K_8:
  200. *(char *) reloc_addr = symbol_addr + rpnt->r_addend;
  201. break;
  202. case R_68K_16:
  203. *(short *) reloc_addr = symbol_addr + rpnt->r_addend;
  204. break;
  205. case R_68K_32:
  206. *reloc_addr = symbol_addr + rpnt->r_addend;
  207. break;
  208. case R_68K_PC8:
  209. *(char *) reloc_addr = (symbol_addr + rpnt->r_addend
  210. - (unsigned int) reloc_addr);
  211. break;
  212. case R_68K_PC16:
  213. *(short *) reloc_addr = (symbol_addr + rpnt->r_addend
  214. - (unsigned int) reloc_addr);
  215. break;
  216. case R_68K_PC32:
  217. *reloc_addr = (symbol_addr + rpnt->r_addend
  218. - (unsigned int) reloc_addr);
  219. break;
  220. case R_68K_GLOB_DAT:
  221. case R_68K_JMP_SLOT:
  222. *reloc_addr = symbol_addr;
  223. break;
  224. case R_68K_RELATIVE:
  225. *reloc_addr = ((unsigned int) tpnt->loadaddr
  226. /* Compatibility kludge. */
  227. + (rpnt->r_addend ? : *reloc_addr));
  228. break;
  229. case R_68K_COPY:
  230. #if 0 /* Do this later. */
  231. _dl_dprintf (2, "Doing copy");
  232. if (symtab_index)
  233. _dl_dprintf (2, " for symbol %s",
  234. strtab + symtab[symtab_index].st_name);
  235. _dl_dprintf (2, "\n");
  236. _dl_memcpy ((void *) symtab[symtab_index].st_value,
  237. (void *) symbol_addr,
  238. symtab[symtab_index].st_size);
  239. #endif
  240. break;
  241. default:
  242. _dl_dprintf (2, "%s: can't handle reloc type ", _dl_progname);
  243. #ifdef VERBOSE_DLINKER
  244. _dl_dprintf (2, "%s ", _dl_reltypes[reloc_type]);
  245. #endif
  246. if (symtab_index)
  247. _dl_dprintf (2, "'%s'", strtab + symtab[symtab_index].st_name);
  248. _dl_dprintf (2, "\n");
  249. _dl_exit (1);
  250. }
  251. }
  252. return goof;
  253. }
  254. /* This is done as a separate step, because there are cases where
  255. information is first copied and later initialized. This results in
  256. the wrong information being copied. Someone at Sun was complaining about
  257. a bug in the handling of _COPY by SVr4, and this may in fact be what he
  258. was talking about. Sigh. */
  259. /* No, there are cases where the SVr4 linker fails to emit COPY relocs
  260. at all. */
  261. int
  262. _dl_parse_copy_information (struct dyn_elf *xpnt, unsigned long rel_addr,
  263. unsigned long rel_size, int type)
  264. {
  265. int i;
  266. char *strtab;
  267. int reloc_type;
  268. int goof = 0;
  269. Elf32_Sym *symtab;
  270. Elf32_Rela *rpnt;
  271. unsigned int *reloc_addr;
  272. unsigned int symbol_addr;
  273. struct elf_resolve *tpnt;
  274. int symtab_index;
  275. /* Now parse the relocation information */
  276. tpnt = xpnt->dyn;
  277. rpnt = (Elf32_Rela *) (rel_addr + tpnt->loadaddr);
  278. rel_size = rel_size / sizeof (Elf32_Rela);
  279. symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB]
  280. + tpnt->loadaddr);
  281. strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
  282. for (i = 0; i < rel_size; i++, rpnt++)
  283. {
  284. reloc_addr = (int *) (tpnt->loadaddr + (int) rpnt->r_offset);
  285. reloc_type = ELF32_R_TYPE (rpnt->r_info);
  286. if (reloc_type != R_68K_COPY)
  287. continue;
  288. symtab_index = ELF32_R_SYM (rpnt->r_info);
  289. symbol_addr = 0;
  290. if (tpnt->libtype == program_interpreter
  291. && (!symtab_index
  292. || _dl_symbol (strtab + symtab[symtab_index].st_name)))
  293. continue;
  294. if (symtab_index)
  295. {
  296. symbol_addr = (unsigned int)
  297. _dl_find_hash (strtab + symtab[symtab_index].st_name,
  298. xpnt->next, (int) reloc_addr, NULL, 1);
  299. if (!symbol_addr)
  300. {
  301. _dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
  302. _dl_progname, strtab + symtab[symtab_index].st_name);
  303. goof++;
  304. }
  305. }
  306. if (!goof)
  307. _dl_memcpy ((void *) symtab[symtab_index].st_value, (void *) symbol_addr,
  308. symtab[symtab_index].st_size);
  309. }
  310. return goof;
  311. }