elfinterp.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  1. /* vi: set sw=4 ts=4: */
  2. /* ARM ELF shared library loader suppport
  3. *
  4. * Copyright (C) 2001-2002, Erik Andersen
  5. *
  6. * All rights reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * 2. The name of the above contributors may not be
  14. * used to endorse or promote products derived from this software
  15. * without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
  18. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20. * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE
  21. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  23. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27. * SUCH DAMAGE.
  28. */
  29. #if defined (SUPPORT_LD_DEBUG) || defined (LD_DEBUG_SYMBOLS)
  30. static const char *_dl_reltypes_tab[] =
  31. [0] "R_ARM_NONE", "R_ARM_PC24", "R_ARM_ABS32", "R_ARM_REL32",
  32. [4] "R_ARM_PC13", "R_ARM_ABS16", "R_ARM_ABS12", "R_ARM_THM_ABS5",
  33. [8] "R_ARM_ABS8", "R_ARM_SBREL32","R_ARM_THM_PC22", "R_ARM_THM_PC8",
  34. [12] "R_ARM_AMP_VCALL9", "R_ARM_SWI24", "R_ARM_THM_SWI8", "R_ARM_XPC25",
  35. [16] "R_ARM_THM_XPC22",
  36. [20] "R_ARM_COPY", "R_ARM_GLOB_DAT","R_ARM_JUMP_SLOT", "R_ARM_RELATIVE",
  37. [24] "R_ARM_GOTOFF", "R_ARM_GOTPC", "R_ARM_GOT32", "R_ARM_PLT32",
  38. [32] "R_ARM_ALU_PCREL_7_0","R_ARM_ALU_PCREL_15_8","R_ARM_ALU_PCREL_23_15","R_ARM_LDR_SBREL_11_0",
  39. [36] "R_ARM_ALU_SBREL_19_12","R_ARM_ALU_SBREL_27_20",
  40. [100] "R_ARM_GNU_VTENTRY","R_ARM_GNU_VTINHERIT","R_ARM_THM_PC11","R_ARM_THM_PC9",
  41. [249] "R_ARM_RXPC25", "R_ARM_RSBREL32", "R_ARM_THM_RPC22", "R_ARM_RREL32",
  42. [253] "R_ARM_RABS22", "R_ARM_RPC24", "R_ARM_RBASE",
  43. };
  44. static const char *
  45. _dl_reltypes(int type)
  46. {
  47. static char buf[22];
  48. const char *str;
  49. if (type >= (sizeof (_dl_reltypes_tab)/sizeof(_dl_reltypes_tab[0])) ||
  50. NULL == (str = _dl_reltypes_tab[type]))
  51. {
  52. str =_dl_simple_ltoa( buf, (unsigned long)(type));
  53. }
  54. return str;
  55. }
  56. static
  57. void debug_sym(Elf32_Sym *symtab,char *strtab,int symtab_index)
  58. {
  59. if(_dl_debug_symbols)
  60. {
  61. if(symtab_index){
  62. _dl_dprintf(_dl_debug_file, "\n%s\tvalue=%x\tsize=%x\tinfo=%x\tother=%x\tshndx=%x",
  63. strtab + symtab[symtab_index].st_name,
  64. symtab[symtab_index].st_value,
  65. symtab[symtab_index].st_size,
  66. symtab[symtab_index].st_info,
  67. symtab[symtab_index].st_other,
  68. symtab[symtab_index].st_shndx);
  69. }
  70. }
  71. }
  72. static void debug_reloc(Elf32_Sym *symtab,char *strtab, ELF_RELOC *rpnt)
  73. {
  74. if(_dl_debug_reloc)
  75. {
  76. int symtab_index;
  77. const char *sym;
  78. symtab_index = ELF32_R_SYM(rpnt->r_info);
  79. sym = symtab_index ? strtab + symtab[symtab_index].st_name : "sym=0x0";
  80. #ifdef ELF_USES_RELOCA
  81. _dl_dprintf(_dl_debug_file, "\n%s\toffset=%x\taddend=%x %s",
  82. _dl_reltypes(ELF32_R_TYPE(rpnt->r_info)),
  83. rpnt->r_offset,
  84. rpnt->r_addend,
  85. sym);
  86. #else
  87. _dl_dprintf(_dl_debug_file, "\n%s\toffset=%x %s",
  88. _dl_reltypes(ELF32_R_TYPE(rpnt->r_info)),
  89. rpnt->r_offset,
  90. sym);
  91. #endif
  92. }
  93. }
  94. #endif
  95. /* Program to load an ELF binary on a linux system, and run it.
  96. References to symbols in sharable libraries can be resolved by either
  97. an ELF sharable library or a linux style of shared library. */
  98. /* Disclaimer: I have never seen any AT&T source code for SVr4, nor have
  99. I ever taken any courses on internals. This program was developed using
  100. information available through the book "UNIX SYSTEM V RELEASE 4,
  101. Programmers guide: Ansi C and Programming Support Tools", which did
  102. a more than adequate job of explaining everything required to get this
  103. working. */
  104. extern int _dl_linux_resolve(void);
  105. unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
  106. {
  107. int reloc_type;
  108. ELF_RELOC *this_reloc;
  109. char *strtab;
  110. Elf32_Sym *symtab;
  111. ELF_RELOC *rel_addr;
  112. int symtab_index;
  113. char *new_addr;
  114. char **got_addr;
  115. unsigned long instr_addr;
  116. rel_addr = (ELF_RELOC *) (tpnt->dynamic_info[DT_JMPREL] + tpnt->loadaddr);
  117. this_reloc = rel_addr + (reloc_entry >> 3);
  118. reloc_type = ELF32_R_TYPE(this_reloc->r_info);
  119. symtab_index = ELF32_R_SYM(this_reloc->r_info);
  120. symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
  121. strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
  122. if (reloc_type != R_ARM_JUMP_SLOT) {
  123. _dl_dprintf(2, "%s: Incorrect relocation type in jump relocations\n",
  124. _dl_progname);
  125. _dl_exit(1);
  126. };
  127. /* Address of jump instruction to fix up */
  128. instr_addr = ((unsigned long) this_reloc->r_offset +
  129. (unsigned long) tpnt->loadaddr);
  130. got_addr = (char **) instr_addr;
  131. /* Get the address of the GOT entry */
  132. new_addr = _dl_find_hash(strtab + symtab[symtab_index].st_name,
  133. tpnt->symbol_scope, tpnt, resolver);
  134. if (!new_addr) {
  135. _dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
  136. _dl_progname, strtab + symtab[symtab_index].st_name);
  137. _dl_exit(1);
  138. };
  139. #if defined (SUPPORT_LD_DEBUG) || defined (LD_NEVER_FIXUP_SYMBOLS)
  140. if ((unsigned long) got_addr < 0x40000000)
  141. {
  142. #ifndef SUPPORT_LD_DEBUG
  143. if (_dl_debug_bindings)
  144. {
  145. _dl_dprintf(_dl_debug_file, "\nresolve function: %s",
  146. strtab + symtab[symtab_index].st_name);
  147. if(_dl_debug_detail) _dl_dprintf(_dl_debug_file, "\tpatch %x ==> %x @ %x", *got_addr, new_addr, got_addr);
  148. }
  149. #endif
  150. #ifndef LD_NEVER_FIXUP_SYMBOLS
  151. *got_addr = new_addr;
  152. #endif
  153. } else {
  154. *got_addr = new_addr;
  155. }
  156. #else
  157. *got_addr = new_addr;
  158. #endif
  159. return (unsigned long) new_addr;
  160. }
  161. static int
  162. _dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,
  163. unsigned long rel_addr, unsigned long rel_size,
  164. int (*reloc_fnc) (struct elf_resolve *tpnt, struct dyn_elf *scope,
  165. ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab))
  166. {
  167. int i;
  168. char *strtab;
  169. int goof = 0;
  170. Elf32_Sym *symtab;
  171. ELF_RELOC *rpnt;
  172. int symtab_index;
  173. /* Now parse the relocation information */
  174. rpnt = (ELF_RELOC *) (rel_addr + tpnt->loadaddr);
  175. rel_size = rel_size / sizeof(ELF_RELOC);
  176. symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
  177. strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
  178. for (i = 0; i < rel_size; i++, rpnt++) {
  179. int res;
  180. symtab_index = ELF32_R_SYM(rpnt->r_info);
  181. /* When the dynamic linker bootstrapped itself, it resolved some symbols.
  182. Make sure we do not do them again */
  183. if (!symtab_index && tpnt->libtype == program_interpreter)
  184. continue;
  185. if (symtab_index && tpnt->libtype == program_interpreter &&
  186. _dl_symbol(strtab + symtab[symtab_index].st_name))
  187. continue;
  188. #if defined (SUPPORT_LD_DEBUG) || defined (LD_DEBUG_SYMBOLS)
  189. debug_sym(symtab,strtab,symtab_index);
  190. debug_reloc(symtab,strtab,rpnt);
  191. #endif
  192. res = reloc_fnc (tpnt, scope, rpnt, symtab, strtab);
  193. if (res==0) continue;
  194. _dl_dprintf(2, "\n%s: ",_dl_progname);
  195. if (symtab_index)
  196. _dl_dprintf(2, "symbol '%s': ", strtab + symtab[symtab_index].st_name);
  197. if (res <0)
  198. {
  199. int reloc_type = ELF32_R_TYPE(rpnt->r_info);
  200. #if defined (SUPPORT_LD_DEBUG)
  201. _dl_dprintf(2, "can't handle reloc type %s\n ", _dl_reltypes(reloc_type));
  202. #else
  203. _dl_dprintf(2, "can't handle reloc type %x\n", reloc_type);
  204. #endif
  205. _dl_exit(-res);
  206. }
  207. else if (res >0)
  208. {
  209. _dl_dprintf(2, "can't resolve symbol '%s'\n");
  210. goof += res;
  211. }
  212. }
  213. return goof;
  214. }
  215. static unsigned long
  216. fix_bad_pc24 (unsigned long *const reloc_addr, unsigned long value)
  217. {
  218. static void *fix_page;
  219. static unsigned int fix_offset;
  220. unsigned int *fix_address;
  221. if (! fix_page)
  222. {
  223. fix_page = _dl_mmap (NULL, 4096 , PROT_READ | PROT_WRITE | PROT_EXEC,
  224. MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
  225. fix_offset = 0;
  226. }
  227. fix_address = (unsigned int *)(fix_page + fix_offset);
  228. fix_address[0] = 0xe51ff004; /* ldr pc, [pc, #-4] */
  229. fix_address[1] = value;
  230. fix_offset += 8;
  231. if (fix_offset >= 4096)
  232. fix_page = NULL;
  233. return (unsigned long)fix_address;
  234. }
  235. static int
  236. _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
  237. ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
  238. {
  239. int reloc_type;
  240. int symtab_index;
  241. unsigned long *reloc_addr;
  242. unsigned long symbol_addr;
  243. int goof = 0;
  244. reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
  245. reloc_type = ELF32_R_TYPE(rpnt->r_info);
  246. symtab_index = ELF32_R_SYM(rpnt->r_info);
  247. symbol_addr = 0;
  248. if (symtab_index) {
  249. symbol_addr = (unsigned long) _dl_find_hash(strtab + symtab[symtab_index].st_name,
  250. scope, (reloc_type == R_ARM_JUMP_SLOT ? tpnt : NULL), symbolrel);
  251. /*
  252. * We want to allow undefined references to weak symbols - this might
  253. * have been intentional. We should not be linking local symbols
  254. * here, so all bases should be covered.
  255. */
  256. if (!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) == STB_GLOBAL) {
  257. goof++;
  258. }
  259. }
  260. #if defined (SUPPORT_LD_DEBUG)
  261. {
  262. unsigned long old_val = *reloc_addr;
  263. #endif
  264. switch (reloc_type) {
  265. case R_ARM_NONE:
  266. break;
  267. case R_ARM_ABS32:
  268. *reloc_addr += symbol_addr;
  269. break;
  270. case R_ARM_PC24:
  271. {
  272. unsigned long addend;
  273. long newvalue, topbits;
  274. addend = *reloc_addr & 0x00ffffff;
  275. if (addend & 0x00800000) addend |= 0xff000000;
  276. newvalue = symbol_addr - (unsigned long)reloc_addr + (addend << 2);
  277. topbits = newvalue & 0xfe000000;
  278. if (topbits != 0xfe000000 && topbits != 0x00000000)
  279. {
  280. newvalue = fix_bad_pc24(reloc_addr, symbol_addr)
  281. - (unsigned long)reloc_addr + (addend << 2);
  282. topbits = newvalue & 0xfe000000;
  283. if (topbits != 0xfe000000 && topbits != 0x00000000)
  284. {
  285. _dl_dprintf(2,"symbol '%s': R_ARM_PC24 relocation out of range.",
  286. symtab[symtab_index].st_name);
  287. _dl_exit(1);
  288. }
  289. }
  290. newvalue >>= 2;
  291. symbol_addr = (*reloc_addr & 0xff000000) | (newvalue & 0x00ffffff);
  292. *reloc_addr = symbol_addr;
  293. break;
  294. }
  295. case R_ARM_GLOB_DAT:
  296. case R_ARM_JUMP_SLOT:
  297. *reloc_addr = symbol_addr;
  298. break;
  299. case R_ARM_RELATIVE:
  300. *reloc_addr += (unsigned long) tpnt->loadaddr;
  301. break;
  302. case R_ARM_COPY:
  303. #if 0
  304. /* Do this later */
  305. _dl_dprintf(2, "Doing copy for symbol ");
  306. if (symtab_index) _dl_dprintf(2, strtab + symtab[symtab_index].st_name);
  307. _dl_dprintf(2, "\n");
  308. _dl_memcpy((void *) symtab[symtab_index].st_value,
  309. (void *) symbol_addr, symtab[symtab_index].st_size);
  310. #endif
  311. break;
  312. default:
  313. return -1; /*call _dl_exit(1) */
  314. }
  315. #if defined (SUPPORT_LD_DEBUG)
  316. if(_dl_debug_reloc && _dl_debug_detail)
  317. _dl_dprintf(_dl_debug_file, "\tpatch: %x ==> %x @ %x", old_val, *reloc_addr, reloc_addr);
  318. }
  319. #endif
  320. return goof;
  321. }
  322. static int
  323. _dl_do_lazy_reloc (struct elf_resolve *tpnt, struct dyn_elf *scope,
  324. ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
  325. {
  326. int reloc_type;
  327. unsigned long *reloc_addr;
  328. reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
  329. reloc_type = ELF32_R_TYPE(rpnt->r_info);
  330. #if defined (SUPPORT_LD_DEBUG)
  331. {
  332. unsigned long old_val = *reloc_addr;
  333. #endif
  334. switch (reloc_type) {
  335. case R_ARM_NONE:
  336. break;
  337. case R_ARM_JUMP_SLOT:
  338. *reloc_addr += (unsigned long) tpnt->loadaddr;
  339. break;
  340. default:
  341. return -1; /*call _dl_exit(1) */
  342. }
  343. #if defined (SUPPORT_LD_DEBUG)
  344. if(_dl_debug_reloc && _dl_debug_detail)
  345. _dl_dprintf(_dl_debug_file, "\tpatch: %x ==> %x @ %x", old_val, *reloc_addr, reloc_addr);
  346. }
  347. #endif
  348. return 0;
  349. }
  350. /* This is done as a separate step, because there are cases where
  351. information is first copied and later initialized. This results in
  352. the wrong information being copied. Someone at Sun was complaining about
  353. a bug in the handling of _COPY by SVr4, and this may in fact be what he
  354. was talking about. Sigh. */
  355. /* No, there are cases where the SVr4 linker fails to emit COPY relocs
  356. at all */
  357. static int
  358. _dl_do_copy (struct elf_resolve *tpnt, struct dyn_elf *scope,
  359. ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
  360. {
  361. int reloc_type;
  362. int symtab_index;
  363. unsigned long *reloc_addr;
  364. unsigned long symbol_addr;
  365. int goof = 0;
  366. reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
  367. reloc_type = ELF32_R_TYPE(rpnt->r_info);
  368. if (reloc_type != R_ARM_COPY)
  369. return 0;
  370. symtab_index = ELF32_R_SYM(rpnt->r_info);
  371. symbol_addr = 0;
  372. if (symtab_index) {
  373. symbol_addr = (unsigned long) _dl_find_hash(strtab +
  374. symtab[symtab_index].st_name, scope,
  375. NULL, copyrel);
  376. if (!symbol_addr) goof++;
  377. }
  378. if (!goof) {
  379. #if defined (SUPPORT_LD_DEBUG)
  380. if(_dl_debug_move)
  381. _dl_dprintf(_dl_debug_file,"\n%s move %x bytes from %x to %x",
  382. strtab + symtab[symtab_index].st_name,
  383. symtab[symtab_index].st_size,
  384. symbol_addr, symtab[symtab_index].st_value);
  385. #endif
  386. _dl_memcpy((char *) symtab[symtab_index].st_value,
  387. (char *) symbol_addr, symtab[symtab_index].st_size);
  388. }
  389. return goof;
  390. }
  391. void _dl_parse_lazy_relocation_information(struct elf_resolve *tpnt,
  392. unsigned long rel_addr, unsigned long rel_size, int type)
  393. {
  394. (void)_dl_parse(tpnt, NULL, rel_addr, rel_size, _dl_do_lazy_reloc);
  395. }
  396. int _dl_parse_relocation_information(struct elf_resolve *tpnt,
  397. unsigned long rel_addr, unsigned long rel_size, int type)
  398. {
  399. return _dl_parse(tpnt, tpnt->symbol_scope, rel_addr, rel_size, _dl_do_reloc);
  400. }
  401. int _dl_parse_copy_information(struct dyn_elf *xpnt, unsigned long rel_addr,
  402. unsigned long rel_size, int type)
  403. {
  404. return _dl_parse(xpnt->dyn, xpnt->next, rel_addr, rel_size, _dl_do_copy);
  405. }