elfinterp.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. /* Run an ELF binary on a linux system.
  2. Copyright (C) 1993, Eric Youngdale.
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 2, or (at your option)
  6. any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
  14. #ifndef VERBOSE_DLINKER
  15. #define VERBOSE_DLINKER
  16. #endif
  17. #ifdef VERBOSE_DLINKER
  18. static char *_dl_reltypes[] =
  19. { "R_ARM_NONE", "R_ARM_PC24", "R_ARM_ABS32", "R_ARM_REL32",
  20. "R_ARM_PC13", "R_ARM_ABS16", "R_ARM_ABS12", "R_ARM_THM_ABS5",
  21. "R_ARM_ABS8", "R_ARM_SBREL32", "R_ARM_THM_PC22", "R_ARM_THM_PC8",
  22. "R_ARM_AMP_VCALL9", "R_ARM_SWI24", "R_ARM_THM_SWI8", "R_ARM_XPC25",
  23. "R_ARM_THM_XPC22", "R_ARM_COPY", "R_ARM_GLOB_DAT", "R_ARM_JUMP_SLOT",
  24. "R_ARM_RELATIVE", "R_ARM_GOTOFF", "R_ARM_GOTPC", "R_ARM_GOT32",
  25. "R_ARM_PLT32", "R_ARM_ALU_PCREL_7_0", "R_ARM_ALU_PCREL_15_8",
  26. "R_ARM_ALU_PCREL_23_15", "R_ARM_LDR_SBREL_11_0", "R_ARM_ALU_SBREL_19_12",
  27. "R_ARM_ALU_SBREL_27_20", "R_ARM_GNU_VTENTRY", "R_ARM_GNU_VTINHERIT",
  28. "R_ARM_THM_PC11", "R_ARM_THM_PC9", "R_ARM_RXPC25", "R_ARM_RSBREL32",
  29. "R_ARM_THM_RPC22", "R_ARM_RREL32", "R_ARM_RABS22", "R_ARM_RPC24",
  30. "R_ARM_RBASE", "R_ARM_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 <errno.h>
  44. #include "elf.h"
  45. #include "hash.h"
  46. #include "syscall.h"
  47. #include "string.h"
  48. #include "sysdep.h"
  49. extern char *_dl_progname;
  50. extern int _dl_linux_resolve(void);
  51. unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
  52. {
  53. int reloc_type;
  54. Elf32_Rel *this_reloc;
  55. char *strtab;
  56. Elf32_Sym *symtab;
  57. Elf32_Rel *rel_addr;
  58. int symtab_index;
  59. char *new_addr;
  60. char **got_addr;
  61. unsigned long instr_addr;
  62. rel_addr = (Elf32_Rel *) (tpnt->dynamic_info[DT_JMPREL] + tpnt->loadaddr);
  63. this_reloc = rel_addr + (reloc_entry >> 3);
  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] + tpnt->loadaddr);
  67. strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
  68. if (reloc_type != R_ARM_JUMP_SLOT) {
  69. _dl_fdprintf(2, "%s: Incorrect relocation type in jump relocations\n",
  70. _dl_progname);
  71. _dl_exit(1);
  72. };
  73. /* Address of jump instruction to fix up */
  74. instr_addr = ((unsigned long) this_reloc->r_offset +
  75. (unsigned long) tpnt->loadaddr);
  76. got_addr = (char **) instr_addr;
  77. #ifdef DL_DEBUG
  78. _dl_fdprintf(2, "Resolving symbol %s\n",
  79. strtab + symtab[symtab_index].st_name);
  80. #endif
  81. /* Get the address of the GOT entry */
  82. new_addr = _dl_find_hash(strtab + symtab[symtab_index].st_name,
  83. tpnt->symbol_scope, (unsigned long) got_addr, tpnt, 0);
  84. if (!new_addr) {
  85. _dl_fdprintf(2, "%s: can't resolve symbol '%s'\n",
  86. _dl_progname, strtab + symtab[symtab_index].st_name);
  87. _dl_exit(1);
  88. };
  89. #ifdef DL_DEBUG
  90. if ((unsigned long) got_addr < 0x40000000) {
  91. _dl_fdprintf(2, "Calling library function: %s\n",
  92. strtab + symtab[symtab_index].st_name);
  93. } else {
  94. *got_addr = new_addr;
  95. }
  96. #else
  97. *got_addr = new_addr;
  98. #endif
  99. return (unsigned long) new_addr;
  100. }
  101. void _dl_parse_lazy_relocation_information(struct elf_resolve *tpnt,
  102. unsigned long rel_addr, unsigned long rel_size, int type)
  103. {
  104. int i;
  105. char *strtab;
  106. int reloc_type;
  107. int symtab_index;
  108. Elf32_Sym *symtab;
  109. Elf32_Rel *rpnt;
  110. unsigned long *reloc_addr;
  111. /* Now parse the relocation information */
  112. rpnt = (Elf32_Rel *) (rel_addr + tpnt->loadaddr);
  113. rel_size = rel_size / sizeof(Elf32_Rel);
  114. symtab =
  115. (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
  116. strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
  117. for (i = 0; i < rel_size; i++, rpnt++) {
  118. reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
  119. reloc_type = ELF32_R_TYPE(rpnt->r_info);
  120. symtab_index = ELF32_R_SYM(rpnt->r_info);
  121. /* When the dynamic linker bootstrapped itself, it resolved some symbols.
  122. Make sure we do not do them again */
  123. if (!symtab_index && tpnt->libtype == program_interpreter)
  124. continue;
  125. if (symtab_index && tpnt->libtype == program_interpreter &&
  126. _dl_symbol(strtab + symtab[symtab_index].st_name))
  127. continue;
  128. switch (reloc_type) {
  129. case R_ARM_NONE:
  130. break;
  131. case R_ARM_JUMP_SLOT:
  132. *reloc_addr += (unsigned long) tpnt->loadaddr;
  133. break;
  134. default:
  135. _dl_fdprintf(2, "%s: (LAZY) can't handle reloc type ",
  136. _dl_progname);
  137. #ifdef VERBOSE_DLINKER
  138. _dl_fdprintf(2, "%s ", _dl_reltypes[reloc_type]);
  139. #endif
  140. if (symtab_index)
  141. _dl_fdprintf(2, "'%s'\n", strtab + symtab[symtab_index].st_name);
  142. _dl_exit(1);
  143. };
  144. };
  145. }
  146. static unsigned long
  147. fix_bad_pc24 (unsigned long *const reloc_addr, unsigned long value)
  148. {
  149. static void *fix_page;
  150. static unsigned int fix_offset;
  151. unsigned int *fix_address;
  152. if (! fix_page)
  153. {
  154. fix_page = _dl_mmap (NULL, 4096 , PROT_READ | PROT_WRITE | PROT_EXEC,
  155. MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
  156. fix_offset = 0;
  157. }
  158. fix_address = (unsigned int *)(fix_page + fix_offset);
  159. fix_address[0] = 0xe51ff004; /* ldr pc, [pc, #-4] */
  160. fix_address[1] = value;
  161. fix_offset += 8;
  162. if (fix_offset >= 4096)
  163. fix_page = NULL;
  164. return (unsigned long)fix_address;
  165. }
  166. int _dl_parse_relocation_information(struct elf_resolve *tpnt,
  167. unsigned long rel_addr, unsigned long rel_size, int type)
  168. {
  169. int i;
  170. char *strtab;
  171. int reloc_type;
  172. int goof = 0;
  173. Elf32_Sym *symtab;
  174. Elf32_Rel *rpnt;
  175. unsigned long *reloc_addr;
  176. unsigned long symbol_addr;
  177. int symtab_index;
  178. /* Now parse the relocation information */
  179. rpnt = (Elf32_Rel *) (rel_addr + tpnt->loadaddr);
  180. rel_size = rel_size / sizeof(Elf32_Rel);
  181. symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
  182. strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
  183. for (i = 0; i < rel_size; i++, rpnt++) {
  184. reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
  185. reloc_type = ELF32_R_TYPE(rpnt->r_info);
  186. symtab_index = ELF32_R_SYM(rpnt->r_info);
  187. symbol_addr = 0;
  188. if (!symtab_index && tpnt->libtype == program_interpreter)
  189. continue;
  190. if (symtab_index) {
  191. if (tpnt->libtype == program_interpreter &&
  192. _dl_symbol(strtab + symtab[symtab_index].st_name))
  193. continue;
  194. symbol_addr = (unsigned long) _dl_find_hash(strtab + symtab[symtab_index].st_name,
  195. tpnt->symbol_scope, (unsigned long) reloc_addr,
  196. (reloc_type == R_ARM_JUMP_SLOT ? tpnt : NULL), 0);
  197. /*
  198. * We want to allow undefined references to weak symbols - this might
  199. * have been intentional. We should not be linking local symbols
  200. * here, so all bases should be covered.
  201. */
  202. if (!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) == STB_GLOBAL) {
  203. _dl_fdprintf(2, "%s: can't resolve symbol '%s'\n",
  204. _dl_progname, strtab + symtab[symtab_index].st_name);
  205. goof++;
  206. }
  207. }
  208. switch (reloc_type) {
  209. case R_ARM_NONE:
  210. break;
  211. case R_ARM_ABS32:
  212. *reloc_addr += symbol_addr;
  213. break;
  214. case R_ARM_PC24:
  215. {
  216. unsigned long addend;
  217. long newvalue, topbits;
  218. addend = *reloc_addr & 0x00ffffff;
  219. if (addend & 0x00800000) addend |= 0xff000000;
  220. newvalue = symbol_addr - (unsigned long)reloc_addr + (addend << 2);
  221. topbits = newvalue & 0xfe000000;
  222. if (topbits != 0xfe000000 && topbits != 0x00000000)
  223. {
  224. newvalue = fix_bad_pc24(reloc_addr, symbol_addr)
  225. - (unsigned long)reloc_addr + (addend << 2);
  226. topbits = newvalue & 0xfe000000;
  227. if (topbits != 0xfe000000 && topbits != 0x00000000)
  228. {
  229. _dl_fdprintf(2, "R_ARM_PC24 relocation out of range ");
  230. _dl_exit(1);
  231. }
  232. }
  233. newvalue >>= 2;
  234. symbol_addr = (*reloc_addr & 0xff000000) | (newvalue & 0x00ffffff);
  235. *reloc_addr = symbol_addr;
  236. break;
  237. }
  238. case R_ARM_GLOB_DAT:
  239. case R_ARM_JUMP_SLOT:
  240. *reloc_addr = symbol_addr;
  241. break;
  242. case R_ARM_RELATIVE:
  243. *reloc_addr += (unsigned long) tpnt->loadaddr;
  244. break;
  245. case R_ARM_COPY:
  246. #if 0
  247. /* Do this later */
  248. _dl_fdprintf(2, "Doing copy for symbol ");
  249. if (symtab_index) _dl_fdprintf(2, strtab + symtab[symtab_index].st_name);
  250. _dl_fdprintf(2, "\n");
  251. _dl_memcpy((void *) symtab[symtab_index].st_value,
  252. (void *) symbol_addr, symtab[symtab_index].st_size);
  253. #endif
  254. break;
  255. default:
  256. _dl_fdprintf(2, "%s: can't handle reloc type ", _dl_progname);
  257. #ifdef VERBOSE_DLINKER
  258. _dl_fdprintf(2, "%s ", _dl_reltypes[reloc_type]);
  259. #endif
  260. if (symtab_index)
  261. _dl_fdprintf(2, "'%s'\n", strtab + symtab[symtab_index].st_name);
  262. _dl_exit(1);
  263. };
  264. };
  265. return goof;
  266. }
  267. /* This is done as a separate step, because there are cases where
  268. information is first copied and later initialized. This results in
  269. the wrong information being copied. Someone at Sun was complaining about
  270. a bug in the handling of _COPY by SVr4, and this may in fact be what he
  271. was talking about. Sigh. */
  272. /* No, there are cases where the SVr4 linker fails to emit COPY relocs
  273. at all */
  274. int _dl_parse_copy_information(struct dyn_elf *xpnt, unsigned long rel_addr,
  275. unsigned long rel_size, int type)
  276. {
  277. int i;
  278. char *strtab;
  279. int reloc_type;
  280. int goof = 0;
  281. Elf32_Sym *symtab;
  282. Elf32_Rel *rpnt;
  283. unsigned long *reloc_addr;
  284. unsigned long symbol_addr;
  285. struct elf_resolve *tpnt;
  286. int symtab_index;
  287. /* Now parse the relocation information */
  288. tpnt = xpnt->dyn;
  289. rpnt = (Elf32_Rel *) (rel_addr + tpnt->loadaddr);
  290. rel_size = rel_size / sizeof(Elf32_Rel);
  291. symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
  292. strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
  293. for (i = 0; i < rel_size; i++, rpnt++) {
  294. reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
  295. reloc_type = ELF32_R_TYPE(rpnt->r_info);
  296. if (reloc_type != R_ARM_COPY)
  297. continue;
  298. symtab_index = ELF32_R_SYM(rpnt->r_info);
  299. symbol_addr = 0;
  300. if (!symtab_index && tpnt->libtype == program_interpreter)
  301. continue;
  302. if (symtab_index) {
  303. if (tpnt->libtype == program_interpreter &&
  304. _dl_symbol(strtab + symtab[symtab_index].st_name))
  305. continue;
  306. symbol_addr = (unsigned long) _dl_find_hash(strtab +
  307. symtab[symtab_index].st_name, xpnt->next,
  308. (unsigned long) reloc_addr, NULL, 1);
  309. if (!symbol_addr) {
  310. _dl_fdprintf(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((char *) symtab[symtab_index].st_value,
  317. (char *) symbol_addr, symtab[symtab_index].st_size);
  318. }
  319. };
  320. return goof;
  321. }