elfinterp.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577
  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. #ifdef DEBUG
  44. static void debug_sym(Elf32_Sym *symtab,char *strtab,int symtab_index);
  45. static void debug_reloc(ELF_RELOC *rpnt);
  46. #define DPRINTF(fmt,args...) _dl_dprintf(2,fmt,args)
  47. #else
  48. #define debug_sym(a,b,c)
  49. #define debug_reloc(a)
  50. #define DPRINTF(fmt,args...)
  51. #endif
  52. extern int _dl_linux_resolve(void);
  53. void _dl_init_got(unsigned long *plt,struct elf_resolve *tpnt)
  54. {
  55. unsigned long target_addr = (unsigned long)_dl_linux_resolve;
  56. unsigned int n_plt_entries;
  57. unsigned long *tramp;
  58. unsigned long data_words;
  59. unsigned int rel_offset_words;
  60. DPRINTF("init_got plt=%x, tpnt=%x\n",
  61. (unsigned long)plt,(unsigned long)tpnt);
  62. n_plt_entries = tpnt->dynamic_info[DT_PLTRELSZ] / sizeof(ELF_RELOC);
  63. DPRINTF("n_plt_entries %d\n",n_plt_entries);
  64. rel_offset_words = PLT_DATA_START_WORDS(n_plt_entries);
  65. DPRINTF("rel_offset_words %x\n",rel_offset_words);
  66. data_words = (unsigned long)(plt + rel_offset_words);
  67. DPRINTF("data_words %x\n",data_words);
  68. tpnt->data_words = data_words;
  69. plt[PLT_LONGBRANCH_ENTRY_WORDS] = OPCODE_ADDIS_HI(11, 11, data_words);
  70. plt[PLT_LONGBRANCH_ENTRY_WORDS+1] = OPCODE_LWZ(11,data_words,11);
  71. plt[PLT_LONGBRANCH_ENTRY_WORDS+2] = OPCODE_MTCTR(11);
  72. plt[PLT_LONGBRANCH_ENTRY_WORDS+3] = OPCODE_BCTR();
  73. /* [4] */
  74. /* [5] */
  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. /* [16] unused */
  87. /* [17] unused */
  88. /* instructions were modified */
  89. PPC_DCBST(plt);
  90. PPC_DCBST(plt+4);
  91. PPC_DCBST(plt+8);
  92. PPC_SYNC;
  93. PPC_ICBI(plt);
  94. PPC_ICBI(plt+4);
  95. PPC_ICBI(plt+8);
  96. PPC_ISYNC;
  97. }
  98. unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
  99. {
  100. int reloc_type;
  101. ELF_RELOC *this_reloc;
  102. char *strtab;
  103. Elf32_Sym *symtab;
  104. ELF_RELOC *rel_addr;
  105. int symtab_index;
  106. unsigned long insn_addr;
  107. unsigned long *insns;
  108. unsigned long targ_addr;
  109. int delta;
  110. //DPRINTF("linux_resolver tpnt=%x reloc_entry=%x\n", tpnt, reloc_entry);
  111. rel_addr = (ELF_RELOC *) (tpnt->dynamic_info[DT_JMPREL] + tpnt->loadaddr);
  112. this_reloc = (void *)rel_addr + reloc_entry;
  113. reloc_type = ELF32_R_TYPE(this_reloc->r_info);
  114. symtab_index = ELF32_R_SYM(this_reloc->r_info);
  115. symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
  116. strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
  117. //debug_reloc(this_reloc);
  118. if (reloc_type != R_PPC_JMP_SLOT) {
  119. _dl_dprintf(2, "%s: Incorrect relocation type [%s] in jump relocations\n",
  120. _dl_progname,
  121. (reloc_type<N_RELTYPES)?_dl_reltypes[reloc_type]:"unknown");
  122. _dl_exit(1);
  123. };
  124. /* Address of dump instruction to fix up */
  125. insn_addr = (unsigned long) tpnt->loadaddr +
  126. (unsigned long) this_reloc->r_offset;
  127. DPRINTF("Resolving symbol %s %x --> ",
  128. strtab + symtab[symtab_index].st_name,
  129. insn_addr);
  130. /* Get the address of the GOT entry */
  131. targ_addr = (unsigned long) _dl_find_hash(
  132. strtab + symtab[symtab_index].st_name,
  133. tpnt->symbol_scope, insn_addr, tpnt, 0);
  134. if (!targ_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. DPRINTF("%x\n", targ_addr);
  140. insns = (unsigned long *)insn_addr;
  141. delta = targ_addr - insn_addr;
  142. if(delta<<6>>6 == delta){
  143. insns[0] = OPCODE_B(delta);
  144. }else if (targ_addr <= 0x01fffffc || targ_addr >= 0xfe000000){
  145. insns[0] = OPCODE_BA (targ_addr);
  146. }else{
  147. /* Warning: we don't handle double-sized PLT entries */
  148. int num_plt_entries;
  149. unsigned long plt_addr;
  150. unsigned long lbranch_addr;
  151. unsigned long *ptr;
  152. int index;
  153. plt_addr = (unsigned long)tpnt->dynamic_info[DT_PLTGOT] +
  154. (unsigned long)tpnt->loadaddr;
  155. lbranch_addr = plt_addr + PLT_LONGBRANCH_ENTRY_WORDS*4;
  156. delta = lbranch_addr - insn_addr;
  157. index = (insn_addr - plt_addr - PLT_INITIAL_ENTRY_WORDS*4)/8;
  158. ptr = (unsigned long *)tpnt->data_words;
  159. DPRINTF("plt_addr=%x delta=%x index=%x ptr=%x\n",
  160. plt_addr, delta, index, ptr);
  161. ptr[index] = targ_addr;
  162. /* icache sync is not necessary, since this will be a data load */
  163. //PPC_DCBST(ptr+index);
  164. //PPC_SYNC;
  165. //PPC_ICBI(ptr+index);
  166. //PPC_ISYNC;
  167. insns[1] = OPCODE_B(delta - 4);
  168. }
  169. /* instructions were modified */
  170. PPC_DCBST(insn_addr);
  171. PPC_SYNC;
  172. PPC_ICBI(insn_addr);
  173. PPC_ISYNC;
  174. return targ_addr;
  175. }
  176. void _dl_parse_lazy_relocation_information(struct elf_resolve *tpnt,
  177. unsigned long rel_addr, unsigned long rel_size, int type)
  178. {
  179. int i;
  180. char *strtab;
  181. int reloc_type;
  182. int symtab_index;
  183. Elf32_Sym *symtab;
  184. ELF_RELOC *rpnt;
  185. unsigned long reloc_addr;
  186. unsigned long *insns;
  187. unsigned long *plt;
  188. int index;
  189. DPRINTF("_dl_parse_lazy_relocation_information(tpnt=%x, rel_addr=%x, rel_size=%x, type=%d)\n",
  190. tpnt,rel_addr,rel_size,type);
  191. /* Now parse the relocation information */
  192. rpnt = (ELF_RELOC *) (rel_addr + tpnt->loadaddr);
  193. rel_size = rel_size / sizeof(ELF_RELOC);
  194. symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
  195. strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
  196. plt = (unsigned long *)(tpnt->dynamic_info[DT_PLTGOT] + tpnt->loadaddr);
  197. for (i = 0; i < rel_size; i++, rpnt++) {
  198. reloc_addr = (unsigned long)tpnt->loadaddr +
  199. (unsigned long) rpnt->r_offset;
  200. reloc_type = ELF32_R_TYPE(rpnt->r_info);
  201. symtab_index = ELF32_R_SYM(rpnt->r_info);
  202. /* When the dynamic linker bootstrapped itself, it resolved some symbols.
  203. Make sure we do not do them again */
  204. if (!symtab_index && tpnt->libtype == program_interpreter)
  205. continue;
  206. if (symtab_index && tpnt->libtype == program_interpreter &&
  207. _dl_symbol(strtab + symtab[symtab_index].st_name))
  208. continue;
  209. DPRINTF("L %x %s %s %x %x\n",
  210. reloc_addr, _dl_reltypes[reloc_type],
  211. symtab_index?strtab + symtab[symtab_index].st_name:"",0,0);
  212. switch (reloc_type) {
  213. case R_PPC_NONE:
  214. break;
  215. case R_PPC_JMP_SLOT:
  216. {
  217. int delta;
  218. delta = (unsigned long)(plt+PLT_TRAMPOLINE_ENTRY_WORDS+2)
  219. - (reloc_addr+4);
  220. index = (reloc_addr -
  221. (unsigned long)(plt+PLT_INITIAL_ENTRY_WORDS))
  222. /sizeof(unsigned long);
  223. index /= 2;
  224. DPRINTF(" index %x delta %x\n",index,delta);
  225. insns = (unsigned long *)reloc_addr;
  226. insns[0] = OPCODE_LI(11,index*4);
  227. insns[1] = OPCODE_B(delta);
  228. break;
  229. }
  230. default:
  231. _dl_dprintf(2, "%s: (LAZY) can't handle reloc type ",
  232. _dl_progname);
  233. #ifdef VERBOSE_DLINKER
  234. _dl_dprintf(2, "%s ", _dl_reltypes[reloc_type]);
  235. #endif
  236. if (symtab_index)
  237. _dl_dprintf(2, "'%s'\n", strtab + symtab[symtab_index].st_name);
  238. _dl_exit(1);
  239. };
  240. /* instructions were modified */
  241. PPC_DCBST(reloc_addr);
  242. PPC_SYNC;
  243. PPC_ICBI(reloc_addr);
  244. };
  245. }
  246. int _dl_parse_relocation_information(struct elf_resolve *tpnt,
  247. unsigned long rel_addr, unsigned long rel_size, int type)
  248. {
  249. int i;
  250. char *strtab;
  251. int reloc_type;
  252. int goof = 0;
  253. Elf32_Sym *symtab;
  254. ELF_RELOC *rpnt;
  255. unsigned long *reloc_addr;
  256. unsigned long symbol_addr;
  257. int symtab_index;
  258. unsigned long addend;
  259. unsigned long *plt;
  260. DPRINTF("_dl_parse_relocation_information(tpnt=%x, rel_addr=%x, rel_size=%x, type=%d)\n",
  261. tpnt,rel_addr,rel_size,type);
  262. /* Now parse the relocation information */
  263. rpnt = (ELF_RELOC *) (rel_addr + tpnt->loadaddr);
  264. rel_size = rel_size / sizeof(ELF_RELOC);
  265. symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
  266. strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
  267. plt = (unsigned long *)(tpnt->dynamic_info[DT_PLTGOT] + tpnt->loadaddr);
  268. for (i = 0; i < rel_size; i++, rpnt++) {
  269. debug_reloc(rpnt);
  270. reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
  271. reloc_type = ELF32_R_TYPE(rpnt->r_info);
  272. symtab_index = ELF32_R_SYM(rpnt->r_info);
  273. addend = rpnt->r_addend;
  274. symbol_addr = 0;
  275. if (!symtab_index && tpnt->libtype == program_interpreter)
  276. continue;
  277. if (symtab_index) {
  278. if (tpnt->libtype == program_interpreter &&
  279. _dl_symbol(strtab + symtab[symtab_index].st_name))
  280. continue;
  281. symbol_addr = (unsigned long) _dl_find_hash(strtab + symtab[symtab_index].st_name,
  282. tpnt->symbol_scope, (unsigned long) reloc_addr,
  283. (reloc_type == R_PPC_JMP_SLOT ? tpnt : NULL), 0);
  284. /*
  285. * We want to allow undefined references to weak symbols - this might
  286. * have been intentional. We should not be linking local symbols
  287. * here, so all bases should be covered.
  288. */
  289. if (!symbol_addr &&
  290. ELF32_ST_BIND(symtab[symtab_index].st_info) == STB_GLOBAL) {
  291. _dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
  292. _dl_progname, strtab + symtab[symtab_index].st_name);
  293. goof++;
  294. }
  295. }
  296. debug_sym(symtab,strtab,symtab_index);
  297. switch (reloc_type) {
  298. case R_PPC_NONE:
  299. break;
  300. case R_PPC_REL24:
  301. {
  302. int delta = symbol_addr - (unsigned long)reloc_addr;
  303. if(delta<<6>>6 != delta){
  304. _dl_dprintf(2,"R_PPC_REL24: Reloc out of range\n");
  305. _dl_exit(1);
  306. }
  307. *reloc_addr &= 0xfc000003;
  308. *reloc_addr |= delta&0x03fffffc;
  309. }
  310. break;
  311. case R_PPC_RELATIVE:
  312. *reloc_addr = (unsigned long)tpnt->loadaddr + addend;
  313. break;
  314. case R_PPC_ADDR32:
  315. *reloc_addr += symbol_addr;
  316. break;
  317. case R_PPC_ADDR16_HA:
  318. /* XXX is this correct? */
  319. *(short *)reloc_addr += (symbol_addr+0x8000)>>16;
  320. break;
  321. case R_PPC_ADDR16_HI:
  322. *(short *)reloc_addr += symbol_addr>>16;
  323. break;
  324. case R_PPC_ADDR16_LO:
  325. *(short *)reloc_addr += symbol_addr;
  326. break;
  327. case R_PPC_JMP_SLOT:
  328. {
  329. unsigned long targ_addr = (unsigned long)_dl_linux_resolve;
  330. int delta = targ_addr - (unsigned long)reloc_addr;
  331. if(delta<<6>>6 == delta){
  332. *reloc_addr = OPCODE_B(delta);
  333. }else if (targ_addr <= 0x01fffffc || targ_addr >= 0xfe000000){
  334. *reloc_addr = OPCODE_BA (targ_addr);
  335. }else{
  336. {
  337. int delta;
  338. int index;
  339. delta = (unsigned long)(plt+PLT_TRAMPOLINE_ENTRY_WORDS+2)
  340. - (unsigned long)(reloc_addr+1);
  341. index = ((unsigned long)reloc_addr -
  342. (unsigned long)(plt+PLT_INITIAL_ENTRY_WORDS))
  343. /sizeof(unsigned long);
  344. index /= 2;
  345. DPRINTF(" index %x delta %x\n",index,delta);
  346. reloc_addr[0] = OPCODE_LI(11,index*4);
  347. reloc_addr[1] = OPCODE_B(delta);
  348. }
  349. }
  350. break;
  351. }
  352. case R_PPC_GLOB_DAT:
  353. *reloc_addr += symbol_addr;
  354. break;
  355. case R_PPC_COPY:
  356. // handled later
  357. break;
  358. default:
  359. _dl_dprintf(2, "%s: can't handle reloc type ", _dl_progname);
  360. #ifdef VERBOSE_DLINKER
  361. _dl_dprintf(2, "%s ", _dl_reltypes[reloc_type]);
  362. #endif
  363. if (symtab_index)
  364. _dl_dprintf(2, "'%s'\n", strtab + symtab[symtab_index].st_name);
  365. _dl_exit(1);
  366. };
  367. /* instructions were modified */
  368. PPC_DCBST(reloc_addr);
  369. PPC_SYNC;
  370. PPC_ICBI(reloc_addr);
  371. DPRINTF("reloc_addr %x: %x\n",reloc_addr,*reloc_addr);
  372. };
  373. return goof;
  374. }
  375. /* This is done as a separate step, because there are cases where
  376. information is first copied and later initialized. This results in
  377. the wrong information being copied. Someone at Sun was complaining about
  378. a bug in the handling of _COPY by SVr4, and this may in fact be what he
  379. was talking about. Sigh. */
  380. /* No, there are cases where the SVr4 linker fails to emit COPY relocs
  381. at all */
  382. int _dl_parse_copy_information(struct dyn_elf *xpnt, unsigned long rel_addr,
  383. unsigned long rel_size, int type)
  384. {
  385. int i;
  386. char *strtab;
  387. int reloc_type;
  388. int goof = 0;
  389. Elf32_Sym *symtab;
  390. ELF_RELOC *rpnt;
  391. unsigned long *reloc_addr;
  392. unsigned long symbol_addr;
  393. struct elf_resolve *tpnt;
  394. int symtab_index;
  395. DPRINTF("parse_copy xpnt=%x rel_addr=%x rel_size=%x type=%d\n",
  396. (int)xpnt,rel_addr,rel_size,type);
  397. /* Now parse the relocation information */
  398. tpnt = xpnt->dyn;
  399. rpnt = (ELF_RELOC *) (rel_addr + tpnt->loadaddr);
  400. rel_size = rel_size / sizeof(ELF_RELOC);
  401. symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
  402. strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
  403. for (i = 0; i < rel_size; i++, rpnt++) {
  404. reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
  405. reloc_type = ELF32_R_TYPE(rpnt->r_info);
  406. if (reloc_type != R_PPC_COPY)
  407. continue;
  408. debug_reloc(rpnt);
  409. symtab_index = ELF32_R_SYM(rpnt->r_info);
  410. symbol_addr = 0;
  411. if (!symtab_index && tpnt->libtype == program_interpreter)
  412. continue;
  413. if (symtab_index) {
  414. if (tpnt->libtype == program_interpreter &&
  415. _dl_symbol(strtab + symtab[symtab_index].st_name))
  416. continue;
  417. symbol_addr = (unsigned long) _dl_find_hash(strtab +
  418. symtab[symtab_index].st_name, xpnt->next,
  419. (unsigned long) reloc_addr, NULL, 1);
  420. if (!symbol_addr) {
  421. _dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
  422. _dl_progname, strtab + symtab[symtab_index].st_name);
  423. goof++;
  424. };
  425. };
  426. debug_sym(symtab,strtab,symtab_index);
  427. DPRINTF("copy: to=%x from=%x size=%x\n",
  428. symtab[symtab_index].st_value,
  429. symbol_addr, symtab[symtab_index].st_size);
  430. if (!goof) {
  431. _dl_memcpy((char *) symtab[symtab_index].st_value,
  432. (char *) symbol_addr,
  433. symtab[symtab_index].st_size);
  434. }
  435. };
  436. return goof;
  437. }
  438. #ifdef unused
  439. static void fixup_jmpslot(unsigned long reloc_addr, unsigned long targ_addr)
  440. {
  441. int delta = targ_addr - reloc_addr;
  442. int index;
  443. if(delta<<6>>6 == delta){
  444. *reloc_addr = OPCODE_B(delta);
  445. }else if (targ_addr <= 0x01fffffc || targ_addr >= 0xfe000000){
  446. *reloc_addr = OPCODE_BA (targ_addr);
  447. }else{
  448. delta = (unsigned long)(plt+PLT_TRAMPOLINE_ENTRY_WORDS+2)
  449. - (unsigned long)(reloc_addr+1);
  450. index = ((unsigned long)reloc_addr -
  451. (unsigned long)(plt+PLT_INITIAL_ENTRY_WORDS))
  452. /sizeof(unsigned long);
  453. index /= 2;
  454. DPRINTF(" index %x delta %x\n",index,delta);
  455. reloc_addr[0] = OPCODE_LI(11,index*4);
  456. reloc_addr[1] = OPCODE_B(delta);
  457. }
  458. }
  459. #endif
  460. #ifdef DEBUG
  461. static void debug_sym(Elf32_Sym *symtab,char *strtab,int symtab_index)
  462. {
  463. if(symtab_index){
  464. _dl_dprintf(2, "sym: name=%s value=%x size=%x info=%x other=%x shndx=%x\n",
  465. strtab + symtab[symtab_index].st_name,
  466. symtab[symtab_index].st_value,
  467. symtab[symtab_index].st_size,
  468. symtab[symtab_index].st_info,
  469. symtab[symtab_index].st_other,
  470. symtab[symtab_index].st_shndx);
  471. }else{
  472. _dl_dprintf(2, "sym: null\n");
  473. }
  474. }
  475. static void debug_reloc(ELF_RELOC *rpnt)
  476. {
  477. _dl_dprintf(2, "reloc: offset=%x type=%x sym=%x addend=%x\n",
  478. rpnt->r_offset,
  479. ELF32_R_TYPE(rpnt->r_info),
  480. ELF32_R_SYM(rpnt->r_info),
  481. rpnt->r_addend);
  482. }
  483. #endif