elfinterp.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479
  1. #define DEBUG
  2. /* Run an ELF binary on a linux system.
  3. Copyright (C) 1993, Eric Youngdale.
  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. #ifndef VERBOSE_DLINKER
  16. #define VERBOSE_DLINKER
  17. #endif
  18. #ifdef VERBOSE_DLINKER
  19. static char *_dl_reltypes[] =
  20. { "R_PPC_NONE", "R_PPC_ADDR32", "R_PPC_ADDR24", "R_PPC_ADDR16",
  21. "R_PPC_ADDR16_LO", "R_PPC_ADDR16_HI", "R_PPC_ADDR16_HA",
  22. "R_PPC_ADDR14", "R_PPC_ADDR14_BRTAKEN", "R_PPC_ADDR14_BRNTAKEN",
  23. "R_PPC_REL24", "R_PPC_REL14", "R_PPC_REL14_BRTAKEN",
  24. "R_PPC_REL14_BRNTAKEN", "R_PPC_GOT16", "R_PPC_GOT16_LO",
  25. "R_PPC_GOT16_HI", "R_PPC_GOT16_HA", "R_PPC_PLTREL24",
  26. "R_PPC_COPY", "R_PPC_GLOB_DAT", "R_PPC_JMP_SLOT", "R_PPC_RELATIVE",
  27. "R_PPC_LOCAL24PC", "R_PPC_UADDR32", "R_PPC_UADDR16", "R_PPC_REL32",
  28. "R_PPC_PLT32", "R_PPC_PLTREL32", "R_PPC_PLT16_LO", "R_PPC_PLT16_HI",
  29. "R_PPC_PLT16_HA", "R_PPC_SDAREL16", "R_PPC_SECTOFF",
  30. "R_PPC_SECTOFF_LO", "R_PPC_SECTOFF_HI", "R_PPC_SECTOFF_HA",
  31. };
  32. #define N_RELTYPES (sizeof(_dl_reltypes)/sizeof(_dl_reltypes[0]))
  33. #endif
  34. /* Program to load an ELF binary on a linux system, and run it.
  35. References to symbols in sharable libraries can be resolved by either
  36. an ELF sharable library or a linux style of shared library. */
  37. /* Disclaimer: I have never seen any AT&T source code for SVr4, nor have
  38. I ever taken any courses on internals. This program was developed using
  39. information available through the book "UNIX SYSTEM V RELEASE 4,
  40. Programmers guide: Ansi C and Programming Support Tools", which did
  41. a more than adequate job of explaining everything required to get this
  42. working. */
  43. #include <sys/types.h>
  44. #include <errno.h>
  45. #include "sysdep.h"
  46. #include <elf.h>
  47. #include "linuxelf.h"
  48. #include "hash.h"
  49. #include "syscall.h"
  50. #include "string.h"
  51. extern char *_dl_progname;
  52. extern int _dl_linux_resolve(void);
  53. void _dl_init_got(unsigned long *plt,struct elf_resolve *tpnt)
  54. {
  55. int i;
  56. unsigned long target_addr = (unsigned long)_dl_linux_resolve;
  57. unsigned int n_plt_entries;
  58. unsigned long *tramp;
  59. unsigned long data_words;
  60. unsigned int rel_offset_words;
  61. unsigned int offset;
  62. _dl_dprintf(2,"init_got plt=%x, tpnt=%x\n",
  63. (unsigned long)plt,(unsigned long)tpnt);
  64. n_plt_entries = tpnt->dynamic_info[DT_PLTRELSZ] / sizeof(ELF_RELOC);
  65. _dl_dprintf(2,"n_plt_entries %d\n",n_plt_entries);
  66. rel_offset_words = PLT_DATA_START_WORDS(n_plt_entries);
  67. _dl_dprintf(2,"rel_offset_words %x\n",rel_offset_words);
  68. data_words = (unsigned long)(plt + rel_offset_words);
  69. _dl_dprintf(2,"data_words %x\n",data_words);
  70. //lpnt += PLT_INITIAL_ENTRY_WORDS;
  71. plt[PLT_LONGBRANCH_ENTRY_WORDS] = OPCODE_ADDIS_HI(11, 11, data_words);
  72. plt[PLT_LONGBRANCH_ENTRY_WORDS+1] = OPCODE_LWZ(11,data_words,11);
  73. plt[PLT_LONGBRANCH_ENTRY_WORDS+2] = OPCODE_MTCTR(11);
  74. plt[PLT_LONGBRANCH_ENTRY_WORDS+3] = OPCODE_BCTR();
  75. tramp = plt + PLT_TRAMPOLINE_ENTRY_WORDS;
  76. tramp[0] = OPCODE_ADDIS_HI(11,11,-data_words);
  77. tramp[1] = OPCODE_ADDI(11,11,-data_words);
  78. tramp[2] = OPCODE_SLWI(12,11,1);
  79. tramp[3] = OPCODE_ADD(11,12,11);
  80. tramp[4] = OPCODE_LI(12,target_addr);
  81. tramp[5] = OPCODE_ADDIS_HI(12,12,target_addr);
  82. tramp[6] = OPCODE_MTCTR(12);
  83. tramp[7] = OPCODE_LI(12,(unsigned long)tpnt);
  84. tramp[8] = OPCODE_ADDIS_HI(12,12,(unsigned long)tpnt);
  85. tramp[9] = OPCODE_BCTR();
  86. PPC_DCBST(plt);
  87. PPC_DCBST(plt+4);
  88. PPC_DCBST(plt+8);
  89. PPC_SYNC;
  90. PPC_ICBI(plt);
  91. PPC_ICBI(plt+4);
  92. PPC_ICBI(plt+8);
  93. PPC_ISYNC;
  94. }
  95. unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
  96. {
  97. int reloc_type;
  98. ELF_RELOC *this_reloc;
  99. char *strtab;
  100. Elf32_Sym *symtab;
  101. ELF_RELOC *rel_addr;
  102. int symtab_index;
  103. char *new_addr;
  104. char **got_addr;
  105. unsigned long instr_addr;
  106. _dl_dprintf(2,"linux_resolver tpnt=%x reloc_entry=%x\n",tpnt,reloc_entry);
  107. rel_addr = (ELF_RELOC *) (tpnt->dynamic_info[DT_JMPREL] + tpnt->loadaddr);
  108. this_reloc = (void *)rel_addr + reloc_entry;
  109. reloc_type = ELF32_R_TYPE(this_reloc->r_info);
  110. symtab_index = ELF32_R_SYM(this_reloc->r_info);
  111. symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
  112. strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
  113. if (reloc_type != R_PPC_JMP_SLOT) {
  114. _dl_dprintf(2, "%s: Incorrect relocation type [%s] in jump relocations\n",
  115. _dl_progname,
  116. (reloc_type<N_RELTYPES)?_dl_reltypes[reloc_type]:"unknown");
  117. _dl_exit(1);
  118. };
  119. /* Address of dump instruction to fix up */
  120. instr_addr = ((unsigned long) this_reloc->r_offset +
  121. (unsigned long) tpnt->loadaddr);
  122. got_addr = (char **) instr_addr;
  123. #ifdef DEBUG
  124. _dl_dprintf(2, "Resolving symbol %s %x --> ",
  125. strtab + symtab[symtab_index].st_name,
  126. instr_addr);
  127. #endif
  128. /* Get the address of the GOT entry */
  129. new_addr = _dl_find_hash(strtab + symtab[symtab_index].st_name,
  130. tpnt->symbol_scope, (unsigned long) got_addr, tpnt, 0);
  131. if (!new_addr) {
  132. _dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
  133. _dl_progname, strtab + symtab[symtab_index].st_name);
  134. _dl_exit(1);
  135. };
  136. #ifdef DEBUG
  137. _dl_dprintf(2, "%x\n", new_addr);
  138. #endif
  139. /* #define DEBUG_LIBRARY */
  140. #ifdef DEBUG_LIBRARY
  141. if ((unsigned long) got_addr < 0x40000000) {
  142. _dl_dprintf(2, "Calling library function: %s\n",
  143. strtab + symtab[symtab_index].st_name);
  144. } else {
  145. *got_addr = new_addr;
  146. }
  147. #else
  148. *got_addr = new_addr;
  149. #endif
  150. return (unsigned long) new_addr;
  151. }
  152. void _dl_parse_lazy_relocation_information(struct elf_resolve *tpnt,
  153. unsigned long rel_addr, unsigned long rel_size, int type)
  154. {
  155. int i;
  156. char *strtab;
  157. int reloc_type;
  158. int symtab_index;
  159. Elf32_Sym *symtab;
  160. ELF_RELOC *rpnt;
  161. unsigned long *reloc_addr;
  162. unsigned long *plt;
  163. int index;
  164. #ifdef DEBUG
  165. _dl_dprintf(2,"_dl_parse_lazy_relocation_information(tpnt=%x, rel_addr=%x, rel_size=%x, type=%d)\n",
  166. tpnt,rel_addr,rel_size,type);
  167. #endif
  168. /* Now parse the relocation information */
  169. rpnt = (ELF_RELOC *) (rel_addr + tpnt->loadaddr);
  170. rel_size = rel_size / sizeof(ELF_RELOC);
  171. symtab =
  172. (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
  173. strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
  174. plt = (unsigned long *)(tpnt->dynamic_info[DT_PLTGOT] + tpnt->loadaddr);
  175. for (i = 0; i < rel_size; i++, rpnt++) {
  176. reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
  177. reloc_type = ELF32_R_TYPE(rpnt->r_info);
  178. symtab_index = ELF32_R_SYM(rpnt->r_info);
  179. /* When the dynamic linker bootstrapped itself, it resolved some symbols.
  180. Make sure we do not do them again */
  181. if (!symtab_index && tpnt->libtype == program_interpreter)
  182. continue;
  183. if (symtab_index && tpnt->libtype == program_interpreter &&
  184. _dl_symbol(strtab + symtab[symtab_index].st_name))
  185. continue;
  186. #ifdef DEBUG
  187. _dl_dprintf(2, "L %x %s %s %x %x\n",
  188. reloc_addr, _dl_reltypes[reloc_type],
  189. symtab_index?strtab + symtab[symtab_index].st_name:"",0,0);
  190. #endif
  191. switch (reloc_type) {
  192. case R_PPC_NONE:
  193. break;
  194. case R_PPC_JMP_SLOT:
  195. {
  196. int delta;
  197. delta = (unsigned long)(plt+PLT_TRAMPOLINE_ENTRY_WORDS+2)
  198. - (unsigned long)(reloc_addr+1);
  199. index = ((unsigned long)reloc_addr -
  200. (unsigned long)(plt+PLT_INITIAL_ENTRY_WORDS))
  201. /sizeof(unsigned long);
  202. index /= 2;
  203. #ifdef DEBUG
  204. _dl_dprintf(2, " index %x delta %x\n",index,delta);
  205. #endif
  206. reloc_addr[0] = OPCODE_LI(11,index*4);
  207. reloc_addr[1] = OPCODE_B(delta);
  208. break;
  209. }
  210. default:
  211. _dl_dprintf(2, "%s: (LAZY) can't handle reloc type ",
  212. _dl_progname);
  213. #ifdef VERBOSE_DLINKER
  214. _dl_dprintf(2, "%s ", _dl_reltypes[reloc_type]);
  215. #endif
  216. if (symtab_index)
  217. _dl_dprintf(2, "'%s'\n", strtab + symtab[symtab_index].st_name);
  218. _dl_exit(1);
  219. };
  220. /* instructions were modified */
  221. PPC_DCBST(reloc_addr);
  222. PPC_SYNC;
  223. PPC_ICBI(reloc_addr);
  224. };
  225. }
  226. int _dl_parse_relocation_information(struct elf_resolve *tpnt,
  227. unsigned long rel_addr, unsigned long rel_size, int type)
  228. {
  229. int i;
  230. char *strtab;
  231. int reloc_type;
  232. int goof = 0;
  233. Elf32_Sym *symtab;
  234. ELF_RELOC *rpnt;
  235. unsigned long *reloc_addr;
  236. unsigned long symbol_addr;
  237. int symtab_index;
  238. unsigned long addend;
  239. unsigned long *plt;
  240. #ifdef DEBUG
  241. _dl_dprintf(2,"_dl_parse_relocation_information(tpnt=%x, rel_addr=%x, rel_size=%x, type=%d)\n",
  242. tpnt,rel_addr,rel_size,type);
  243. #endif
  244. /* Now parse the relocation information */
  245. rpnt = (ELF_RELOC *) (rel_addr + tpnt->loadaddr);
  246. rel_size = rel_size / sizeof(ELF_RELOC);
  247. symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
  248. strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
  249. plt = (unsigned long *)(tpnt->dynamic_info[DT_PLTGOT] + tpnt->loadaddr);
  250. for (i = 0; i < rel_size; i++, rpnt++) {
  251. reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
  252. reloc_type = ELF32_R_TYPE(rpnt->r_info);
  253. symtab_index = ELF32_R_SYM(rpnt->r_info);
  254. addend = rpnt->r_addend;
  255. symbol_addr = 0;
  256. if (!symtab_index && tpnt->libtype == program_interpreter)
  257. continue;
  258. if (symtab_index) {
  259. if (tpnt->libtype == program_interpreter &&
  260. _dl_symbol(strtab + symtab[symtab_index].st_name))
  261. continue;
  262. symbol_addr = (unsigned long) _dl_find_hash(strtab + symtab[symtab_index].st_name,
  263. tpnt->symbol_scope, (unsigned long) reloc_addr,
  264. (reloc_type == R_PPC_JMP_SLOT ? tpnt : NULL), 0);
  265. /*
  266. * We want to allow undefined references to weak symbols - this might
  267. * have been intentional. We should not be linking local symbols
  268. * here, so all bases should be covered.
  269. */
  270. if (!symbol_addr &&
  271. ELF32_ST_BIND(symtab[symtab_index].st_info) == STB_GLOBAL) {
  272. _dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
  273. _dl_progname, strtab + symtab[symtab_index].st_name);
  274. goof++;
  275. }
  276. }
  277. #ifdef DEBUG
  278. _dl_dprintf(2, " %x %s %s %x %x\n",
  279. reloc_addr, _dl_reltypes[reloc_type],
  280. symtab_index?strtab + symtab[symtab_index].st_name:"",
  281. symbol_addr, addend);
  282. #endif
  283. switch (reloc_type) {
  284. case R_PPC_NONE:
  285. break;
  286. case R_PPC_REL24:
  287. {
  288. int delta = symbol_addr - (unsigned long)reloc_addr;
  289. if(delta<<6>>6 != delta){
  290. _dl_dprintf(2,"R_PPC_REL24: Reloc out of range\n");
  291. _dl_exit(1);
  292. }
  293. *reloc_addr &= 0xfc000003;
  294. *reloc_addr |= delta&0x03fffffc;
  295. }
  296. break;
  297. case R_PPC_RELATIVE:
  298. *reloc_addr += (unsigned long)tpnt->loadaddr + addend;
  299. break;
  300. case R_PPC_ADDR32:
  301. *reloc_addr += symbol_addr;
  302. break;
  303. case R_PPC_ADDR16_HA:
  304. /* XXX is this correct? */
  305. *(short *)reloc_addr += (symbol_addr+0x8000)>>16;
  306. break;
  307. case R_PPC_ADDR16_HI:
  308. *(short *)reloc_addr += symbol_addr>>16;
  309. break;
  310. case R_PPC_ADDR16_LO:
  311. *(short *)reloc_addr += symbol_addr;
  312. break;
  313. case R_PPC_JMP_SLOT:
  314. {
  315. unsigned long targ_addr = (unsigned long)_dl_linux_resolve;
  316. int delta = targ_addr - (unsigned long)reloc_addr;
  317. if(delta<<6>>6 == delta){
  318. *reloc_addr = OPCODE_B(delta);
  319. }else if (targ_addr <= 0x01fffffc || targ_addr >= 0xfe000000){
  320. *reloc_addr = OPCODE_BA (targ_addr);
  321. }else{
  322. {
  323. int delta;
  324. int index;
  325. delta = (unsigned long)(plt+PLT_TRAMPOLINE_ENTRY_WORDS+2)
  326. - (unsigned long)(reloc_addr+1);
  327. index = ((unsigned long)reloc_addr -
  328. (unsigned long)(plt+PLT_INITIAL_ENTRY_WORDS))
  329. /sizeof(unsigned long);
  330. index /= 2;
  331. #ifdef DEBUG
  332. _dl_dprintf(2, " index %x delta %x\n",index,delta);
  333. #endif
  334. reloc_addr[0] = OPCODE_LI(11,index*4);
  335. reloc_addr[1] = OPCODE_B(delta);
  336. }
  337. }
  338. break;
  339. }
  340. default:
  341. _dl_dprintf(2, "%s: can't handle reloc type ", _dl_progname);
  342. #ifdef VERBOSE_DLINKER
  343. _dl_dprintf(2, "%s ", _dl_reltypes[reloc_type]);
  344. #endif
  345. if (symtab_index)
  346. _dl_dprintf(2, "'%s'\n", strtab + symtab[symtab_index].st_name);
  347. _dl_exit(1);
  348. };
  349. /* instructions were modified */
  350. PPC_DCBST(reloc_addr);
  351. PPC_SYNC;
  352. PPC_ICBI(reloc_addr);
  353. //_dl_dprintf(2,"reloc_addr %x: %x\n",reloc_addr,*reloc_addr);
  354. };
  355. return goof;
  356. }
  357. /* This is done as a separate step, because there are cases where
  358. information is first copied and later initialized. This results in
  359. the wrong information being copied. Someone at Sun was complaining about
  360. a bug in the handling of _COPY by SVr4, and this may in fact be what he
  361. was talking about. Sigh. */
  362. /* No, there are cases where the SVr4 linker fails to emit COPY relocs
  363. at all */
  364. int _dl_parse_copy_information(struct dyn_elf *xpnt, unsigned long rel_addr,
  365. unsigned long rel_size, int type)
  366. {
  367. int i;
  368. char *strtab;
  369. int reloc_type;
  370. int goof = 0;
  371. Elf32_Sym *symtab;
  372. ELF_RELOC *rpnt;
  373. unsigned long *reloc_addr;
  374. unsigned long symbol_addr;
  375. struct elf_resolve *tpnt;
  376. int symtab_index;
  377. _dl_dprintf(2,"parse_copy xpnt=%x rel_addr=%x rel_size=%x type=%d\n",
  378. (int)xpnt,rel_addr,rel_size,type);
  379. /* Now parse the relocation information */
  380. tpnt = xpnt->dyn;
  381. rpnt = (ELF_RELOC *) (rel_addr + tpnt->loadaddr);
  382. rel_size = rel_size / sizeof(ELF_RELOC);
  383. symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
  384. strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
  385. for (i = 0; i < rel_size; i++, rpnt++) {
  386. reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
  387. reloc_type = ELF32_R_TYPE(rpnt->r_info);
  388. if (reloc_type != R_386_COPY)
  389. continue;
  390. symtab_index = ELF32_R_SYM(rpnt->r_info);
  391. symbol_addr = 0;
  392. if (!symtab_index && tpnt->libtype == program_interpreter)
  393. continue;
  394. if (symtab_index) {
  395. if (tpnt->libtype == program_interpreter &&
  396. _dl_symbol(strtab + symtab[symtab_index].st_name))
  397. continue;
  398. symbol_addr = (unsigned long) _dl_find_hash(strtab +
  399. symtab[symtab_index].st_name, xpnt->next,
  400. (unsigned long) reloc_addr, NULL, 1);
  401. if (!symbol_addr) {
  402. _dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
  403. _dl_progname, strtab + symtab[symtab_index].st_name);
  404. goof++;
  405. };
  406. };
  407. if (!goof) {
  408. _dl_memcpy((char *) symtab[symtab_index].st_value,
  409. (char *) symbol_addr, symtab[symtab_index].st_size);
  410. }
  411. };
  412. return goof;
  413. }