elfinterp.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619
  1. /* vi: set sw=4 ts=4: */
  2. /* powerpc shared library loader suppport
  3. *
  4. * Copyright (C) 2001-2002, David A. Schleef
  5. * Copyright (C) 2003, Erik Andersen
  6. *
  7. * All rights reserved.
  8. *
  9. * Redistribution and use in source and binary forms, with or without
  10. * modification, are permitted provided that the following conditions
  11. * are met:
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. * 2. The name of the above contributors may not be
  15. * used to endorse or promote products derived from this software
  16. * without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
  19. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  20. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  21. * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE
  22. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  23. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  24. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  25. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  26. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  27. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  28. * SUCH DAMAGE.
  29. */
  30. #if defined (__SUPPORT_LD_DEBUG__)
  31. static const char *_dl_reltypes_tab[] =
  32. { "R_PPC_NONE", "R_PPC_ADDR32", "R_PPC_ADDR24", "R_PPC_ADDR16",
  33. "R_PPC_ADDR16_LO", "R_PPC_ADDR16_HI", "R_PPC_ADDR16_HA",
  34. "R_PPC_ADDR14", "R_PPC_ADDR14_BRTAKEN", "R_PPC_ADDR14_BRNTAKEN",
  35. "R_PPC_REL24", "R_PPC_REL14", "R_PPC_REL14_BRTAKEN",
  36. "R_PPC_REL14_BRNTAKEN", "R_PPC_GOT16", "R_PPC_GOT16_LO",
  37. "R_PPC_GOT16_HI", "R_PPC_GOT16_HA", "R_PPC_PLTREL24",
  38. "R_PPC_COPY", "R_PPC_GLOB_DAT", "R_PPC_JMP_SLOT", "R_PPC_RELATIVE",
  39. "R_PPC_LOCAL24PC", "R_PPC_UADDR32", "R_PPC_UADDR16", "R_PPC_REL32",
  40. "R_PPC_PLT32", "R_PPC_PLTREL32", "R_PPC_PLT16_LO", "R_PPC_PLT16_HI",
  41. "R_PPC_PLT16_HA", "R_PPC_SDAREL16", "R_PPC_SECTOFF",
  42. "R_PPC_SECTOFF_LO", "R_PPC_SECTOFF_HI", "R_PPC_SECTOFF_HA",
  43. };
  44. static const char *
  45. _dl_reltypes(int type)
  46. {
  47. static char buf[22];
  48. const char *str;
  49. if (type >= (int)(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\n\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
  73. void debug_reloc(Elf32_Sym *symtab,char *strtab, ELF_RELOC *rpnt)
  74. {
  75. if(_dl_debug_reloc)
  76. {
  77. int symtab_index;
  78. const char *sym;
  79. symtab_index = ELF32_R_SYM(rpnt->r_info);
  80. sym = symtab_index ? strtab + symtab[symtab_index].st_name : "sym=0x0";
  81. if(_dl_debug_symbols)
  82. _dl_dprintf(_dl_debug_file, "\n\t");
  83. else
  84. _dl_dprintf(_dl_debug_file, "\n%s\n\t", sym);
  85. #ifdef ELF_USES_RELOCA
  86. _dl_dprintf(_dl_debug_file, "%s\toffset=%x\taddend=%x",
  87. _dl_reltypes(ELF32_R_TYPE(rpnt->r_info)),
  88. rpnt->r_offset,
  89. rpnt->r_addend);
  90. #else
  91. _dl_dprintf(_dl_debug_file, "%s\toffset=%x\n",
  92. _dl_reltypes(ELF32_R_TYPE(rpnt->r_info)),
  93. rpnt->r_offset);
  94. #endif
  95. }
  96. }
  97. #endif
  98. extern int _dl_linux_resolve(void);
  99. void _dl_init_got(unsigned long *plt,struct elf_resolve *tpnt)
  100. {
  101. unsigned long target_addr = (unsigned long)_dl_linux_resolve;
  102. unsigned int n_plt_entries;
  103. unsigned long *tramp;
  104. unsigned long data_words;
  105. unsigned int rel_offset_words;
  106. //DPRINTF("init_got plt=%x, tpnt=%x\n", (unsigned long)plt,(unsigned long)tpnt);
  107. n_plt_entries = tpnt->dynamic_info[DT_PLTRELSZ] / sizeof(ELF_RELOC);
  108. //DPRINTF("n_plt_entries %d\n",n_plt_entries);
  109. rel_offset_words = PLT_DATA_START_WORDS(n_plt_entries);
  110. //DPRINTF("rel_offset_words %x\n",rel_offset_words);
  111. data_words = (unsigned long)(plt + rel_offset_words);
  112. //DPRINTF("data_words %x\n",data_words);
  113. tpnt->data_words = data_words;
  114. plt[PLT_LONGBRANCH_ENTRY_WORDS] = OPCODE_ADDIS_HI(11, 11, data_words);
  115. plt[PLT_LONGBRANCH_ENTRY_WORDS+1] = OPCODE_LWZ(11,data_words,11);
  116. plt[PLT_LONGBRANCH_ENTRY_WORDS+2] = OPCODE_MTCTR(11);
  117. plt[PLT_LONGBRANCH_ENTRY_WORDS+3] = OPCODE_BCTR();
  118. /* [4] */
  119. /* [5] */
  120. tramp = plt + PLT_TRAMPOLINE_ENTRY_WORDS;
  121. tramp[0] = OPCODE_ADDIS_HI(11,11,-data_words);
  122. tramp[1] = OPCODE_ADDI(11,11,-data_words);
  123. tramp[2] = OPCODE_SLWI(12,11,1);
  124. tramp[3] = OPCODE_ADD(11,12,11);
  125. tramp[4] = OPCODE_LI(12,target_addr);
  126. tramp[5] = OPCODE_ADDIS_HI(12,12,target_addr);
  127. tramp[6] = OPCODE_MTCTR(12);
  128. tramp[7] = OPCODE_LI(12,(unsigned long)tpnt);
  129. tramp[8] = OPCODE_ADDIS_HI(12,12,(unsigned long)tpnt);
  130. tramp[9] = OPCODE_BCTR();
  131. /* [16] unused */
  132. /* [17] unused */
  133. /* instructions were modified */
  134. PPC_DCBST(plt);
  135. PPC_DCBST(plt+4);
  136. PPC_DCBST(plt+8);
  137. PPC_DCBST(plt+12);
  138. PPC_DCBST(plt+16-1);
  139. PPC_SYNC;
  140. PPC_ICBI(plt);
  141. PPC_ICBI(plt+4); /* glibc thinks this is not needed */
  142. PPC_ICBI(plt+8); /* glibc thinks this is not needed */
  143. PPC_ICBI(plt+12); /* glibc thinks this is not needed */
  144. PPC_ICBI(plt+16-1);
  145. PPC_ISYNC;
  146. }
  147. unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
  148. {
  149. int reloc_type;
  150. ELF_RELOC *this_reloc;
  151. char *strtab;
  152. Elf32_Sym *symtab;
  153. ELF_RELOC *rel_addr;
  154. int symtab_index;
  155. char *symname;
  156. unsigned long insn_addr;
  157. unsigned long *insns;
  158. unsigned long new_addr;
  159. unsigned long delta;
  160. rel_addr = (ELF_RELOC *) (tpnt->dynamic_info[DT_JMPREL] + tpnt->loadaddr);
  161. this_reloc = (void *)rel_addr + reloc_entry;
  162. reloc_type = ELF32_R_TYPE(this_reloc->r_info);
  163. symtab_index = ELF32_R_SYM(this_reloc->r_info);
  164. symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
  165. strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
  166. symname = strtab + symtab[symtab_index].st_name;
  167. #if defined (__SUPPORT_LD_DEBUG__)
  168. debug_sym(symtab,strtab,symtab_index);
  169. debug_reloc(symtab,strtab,this_reloc);
  170. #endif
  171. if (reloc_type != R_PPC_JMP_SLOT) {
  172. _dl_dprintf(2, "%s: Incorrect relocation type in jump relocation\n", _dl_progname);
  173. _dl_exit(1);
  174. };
  175. /* Address of dump instruction to fix up */
  176. insn_addr = (unsigned long) tpnt->loadaddr +
  177. (unsigned long) this_reloc->r_offset;
  178. #if defined (__SUPPORT_LD_DEBUG__)
  179. if(_dl_debug_reloc && _dl_debug_detail)
  180. _dl_dprintf(_dl_debug_file, "\n\tResolving symbol %s %x --> ", symname, insn_addr);
  181. #endif
  182. /* Get the address of the GOT entry */
  183. new_addr = (unsigned long) _dl_find_hash(
  184. strtab + symtab[symtab_index].st_name,
  185. tpnt->symbol_scope, tpnt, resolver);
  186. if (!new_addr) {
  187. _dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
  188. _dl_progname, symname);
  189. _dl_exit(1);
  190. };
  191. #if defined (__SUPPORT_LD_DEBUG__)
  192. if(_dl_debug_reloc && _dl_debug_detail)
  193. _dl_dprintf(_dl_debug_file, "%x\n", new_addr);
  194. #endif
  195. insns = (unsigned long *)insn_addr;
  196. delta = new_addr - insn_addr;
  197. if(delta<<6>>6 == delta){
  198. insns[0] = OPCODE_B(delta);
  199. }else if (new_addr <= 0x01fffffc || new_addr >= 0xfe000000){
  200. insns[0] = OPCODE_BA (new_addr);
  201. }else{
  202. /* Warning: we don't handle double-sized PLT entries */
  203. unsigned long plt_addr;
  204. unsigned long *ptr;
  205. int index;
  206. plt_addr = (unsigned long)tpnt->dynamic_info[DT_PLTGOT] +
  207. (unsigned long)tpnt->loadaddr;
  208. delta = PLT_LONGBRANCH_ENTRY_WORDS*4 - (insn_addr-plt_addr+4);
  209. index = (insn_addr - plt_addr - PLT_INITIAL_ENTRY_WORDS*4)/8;
  210. ptr = (unsigned long *)tpnt->data_words;
  211. //DPRINTF("plt_addr=%x delta=%x index=%x ptr=%x\n", plt_addr, delta, index, ptr);
  212. insns += 1;
  213. ptr[index] = new_addr;
  214. PPC_SYNC;
  215. /* icache sync is not necessary, since this will be a data load */
  216. //PPC_DCBST(ptr+index);
  217. //PPC_SYNC;
  218. //PPC_ICBI(ptr+index);
  219. //PPC_ISYNC;
  220. insns[0] = OPCODE_B(delta);
  221. }
  222. /* instructions were modified */
  223. PPC_DCBST(insns);
  224. PPC_SYNC;
  225. PPC_ICBI(insns);
  226. PPC_ISYNC;
  227. return new_addr;
  228. }
  229. static int
  230. _dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,
  231. unsigned long rel_addr, unsigned long rel_size,
  232. int (*reloc_fnc) (struct elf_resolve *tpnt, struct dyn_elf *scope,
  233. ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab))
  234. {
  235. unsigned int i;
  236. char *strtab;
  237. Elf32_Sym *symtab;
  238. ELF_RELOC *rpnt;
  239. int symtab_index;
  240. /* Now parse the relocation information */
  241. rpnt = (ELF_RELOC *)(intptr_t) (rel_addr + tpnt->loadaddr);
  242. rel_size = rel_size / sizeof(ELF_RELOC);
  243. symtab = (Elf32_Sym *)(intptr_t) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
  244. strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
  245. for (i = 0; i < rel_size; i++, rpnt++) {
  246. int res;
  247. symtab_index = ELF32_R_SYM(rpnt->r_info);
  248. /* When the dynamic linker bootstrapped itself, it resolved some symbols.
  249. Make sure we do not do them again */
  250. if (!symtab_index && tpnt->libtype == program_interpreter)
  251. continue;
  252. if (symtab_index && tpnt->libtype == program_interpreter &&
  253. _dl_symbol(strtab + symtab[symtab_index].st_name))
  254. continue;
  255. #if defined (__SUPPORT_LD_DEBUG__)
  256. debug_sym(symtab,strtab,symtab_index);
  257. debug_reloc(symtab,strtab,rpnt);
  258. #endif
  259. res = reloc_fnc (tpnt, scope, rpnt, symtab, strtab);
  260. if (res==0) continue;
  261. _dl_dprintf(2, "\n%s: ",_dl_progname);
  262. if (symtab_index)
  263. _dl_dprintf(2, "symbol '%s': ", strtab + symtab[symtab_index].st_name);
  264. if (res <0)
  265. {
  266. int reloc_type = ELF32_R_TYPE(rpnt->r_info);
  267. #if defined (__SUPPORT_LD_DEBUG__)
  268. _dl_dprintf(2, "can't handle reloc type %s\n ", _dl_reltypes(reloc_type));
  269. #else
  270. _dl_dprintf(2, "can't handle reloc type %x\n", reloc_type);
  271. #endif
  272. _dl_exit(-res);
  273. }
  274. else if (res >0)
  275. {
  276. _dl_dprintf(2, "can't resolve symbol\n");
  277. return res;
  278. }
  279. }
  280. return 0;
  281. }
  282. static int
  283. _dl_do_lazy_reloc (struct elf_resolve *tpnt, struct dyn_elf *scope,
  284. ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
  285. {
  286. int reloc_type;
  287. unsigned long reloc_addr;
  288. #if defined (__SUPPORT_LD_DEBUG__)
  289. unsigned long old_val;
  290. #endif
  291. (void)scope;
  292. (void)symtab;
  293. (void)strtab;
  294. reloc_addr = (unsigned long)tpnt->loadaddr + (unsigned long) rpnt->r_offset;
  295. reloc_type = ELF32_R_TYPE(rpnt->r_info);
  296. #if defined (__SUPPORT_LD_DEBUG__)
  297. old_val = reloc_addr;
  298. #endif
  299. switch (reloc_type) {
  300. case R_PPC_NONE:
  301. return 0;
  302. break;
  303. case R_PPC_JMP_SLOT:
  304. {
  305. int index;
  306. unsigned long delta;
  307. unsigned long *plt;
  308. unsigned long *insns;
  309. plt = (unsigned long *)(tpnt->dynamic_info[DT_PLTGOT] + tpnt->loadaddr);
  310. delta = (unsigned long)(plt+PLT_TRAMPOLINE_ENTRY_WORDS+2) - (reloc_addr+4);
  311. index = (reloc_addr - (unsigned long)(plt+PLT_INITIAL_ENTRY_WORDS))
  312. /sizeof(unsigned long);
  313. index /= 2;
  314. //DPRINTF(" index %x delta %x\n",index,delta);
  315. insns = (unsigned long *)reloc_addr;
  316. insns[0] = OPCODE_LI(11,index*4);
  317. insns[1] = OPCODE_B(delta);
  318. break;
  319. }
  320. default:
  321. #if 0
  322. _dl_dprintf(2, "%s: (LAZY) can't handle reloc type ",
  323. _dl_progname);
  324. #if defined (__SUPPORT_LD_DEBUG__)
  325. _dl_dprintf(2, "%s ", _dl_reltypes[reloc_type]);
  326. #endif
  327. if (symtab_index)
  328. _dl_dprintf(2, "'%s'\n", strtab + symtab[symtab_index].st_name);
  329. #endif
  330. //_dl_exit(1);
  331. return -1;
  332. };
  333. /* instructions were modified */
  334. PPC_DCBST(reloc_addr);
  335. PPC_DCBST(reloc_addr+4);
  336. PPC_SYNC;
  337. PPC_ICBI(reloc_addr);
  338. PPC_ICBI(reloc_addr+4);
  339. PPC_ISYNC;
  340. #if defined (__SUPPORT_LD_DEBUG__)
  341. if(_dl_debug_reloc && _dl_debug_detail)
  342. _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x", old_val, reloc_addr);
  343. #endif
  344. return 0;
  345. }
  346. static int
  347. _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
  348. ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
  349. {
  350. int reloc_type;
  351. int symtab_index;
  352. char *symname;
  353. unsigned long *reloc_addr;
  354. unsigned long symbol_addr;
  355. #if defined (__SUPPORT_LD_DEBUG__)
  356. unsigned long old_val;
  357. #endif
  358. reloc_addr = (unsigned long *)(intptr_t) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
  359. reloc_type = ELF32_R_TYPE(rpnt->r_info);
  360. symtab_index = ELF32_R_SYM(rpnt->r_info);
  361. symbol_addr = 0;
  362. symname = strtab + symtab[symtab_index].st_name;
  363. if (symtab_index) {
  364. symbol_addr = (unsigned long) _dl_find_hash(symname, scope,
  365. (reloc_type == R_PPC_JMP_SLOT ? tpnt : NULL), symbolrel);
  366. /*
  367. * We want to allow undefined references to weak symbols - this might
  368. * have been intentional. We should not be linking local symbols
  369. * here, so all bases should be covered.
  370. */
  371. if (!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) == STB_GLOBAL) {
  372. #if defined (__SUPPORT_LD_DEBUG__)
  373. _dl_dprintf(2, "\tglobal symbol '%s' already defined in '%s'\n",
  374. symname, tpnt->libname);
  375. #endif
  376. return 0;
  377. }
  378. }
  379. #if defined (__SUPPORT_LD_DEBUG__)
  380. old_val = *reloc_addr;
  381. #endif
  382. switch (reloc_type) {
  383. case R_PPC_NONE:
  384. return 0;
  385. break;
  386. case R_PPC_REL24:
  387. #if 0
  388. {
  389. unsigned long delta = symbol_addr - (unsigned long)reloc_addr;
  390. if(delta<<6>>6 != delta){
  391. _dl_dprintf(2,"R_PPC_REL24: Reloc out of range\n");
  392. _dl_exit(1);
  393. }
  394. *reloc_addr &= 0xfc000003;
  395. *reloc_addr |= delta&0x03fffffc;
  396. }
  397. break;
  398. #else
  399. _dl_dprintf(2, "%s: symbol '%s' is type R_PPC_REL24\n\tCompile shared libraries with -fPIC!\n",
  400. _dl_progname, symname);
  401. _dl_exit(1);
  402. #endif
  403. case R_PPC_RELATIVE:
  404. *reloc_addr = (unsigned long)tpnt->loadaddr + (unsigned long)rpnt->r_addend;
  405. break;
  406. case R_PPC_ADDR32:
  407. case R_PPC_GLOB_DAT:
  408. *reloc_addr = symbol_addr + (unsigned long)rpnt->r_addend;
  409. break;
  410. case R_PPC_ADDR16_HA:
  411. /* XXX is this correct? */
  412. *(short *)reloc_addr += (symbol_addr+0x8000)>>16;
  413. break;
  414. case R_PPC_ADDR16_HI:
  415. *(short *)reloc_addr += symbol_addr>>16;
  416. break;
  417. case R_PPC_ADDR16_LO:
  418. *(short *)reloc_addr += symbol_addr;
  419. break;
  420. case R_PPC_JMP_SLOT:
  421. {
  422. unsigned long targ_addr = (unsigned long)*reloc_addr;
  423. unsigned long delta = targ_addr - (unsigned long)reloc_addr;
  424. if(delta<<6>>6 == delta){
  425. *reloc_addr = OPCODE_B(delta);
  426. }else if (targ_addr <= 0x01fffffc || targ_addr >= 0xfe000000){
  427. *reloc_addr = OPCODE_BA (targ_addr);
  428. }else{
  429. {
  430. int index;
  431. unsigned long delta2;
  432. unsigned long *plt, *ptr;
  433. plt = (unsigned long *)(tpnt->dynamic_info[DT_PLTGOT] + tpnt->loadaddr);
  434. delta2 = (unsigned long)(plt+PLT_LONGBRANCH_ENTRY_WORDS)
  435. - (unsigned long)(reloc_addr+1);
  436. index = ((unsigned long)reloc_addr -
  437. (unsigned long)(plt+PLT_INITIAL_ENTRY_WORDS))
  438. /sizeof(unsigned long);
  439. index /= 2;
  440. //DPRINTF(" index %x delta %x\n",index,delta2);
  441. ptr = (unsigned long *)tpnt->data_words;
  442. ptr[index] = targ_addr;
  443. reloc_addr[0] = OPCODE_LI(11,index*4);
  444. reloc_addr[1] = OPCODE_B(delta2);
  445. /* instructions were modified */
  446. PPC_DCBST(reloc_addr+1);
  447. PPC_SYNC;
  448. PPC_ICBI(reloc_addr+1);
  449. }
  450. }
  451. break;
  452. }
  453. case R_PPC_COPY:
  454. // handled later
  455. return 0;
  456. break;
  457. default:
  458. #if 0
  459. _dl_dprintf(2, "%s: can't handle reloc type ", _dl_progname);
  460. #if defined (__SUPPORT_LD_DEBUG__)
  461. _dl_dprintf(2, "%s ", _dl_reltypes[reloc_type]);
  462. #endif
  463. if (symtab_index)
  464. _dl_dprintf(2, "'%s'\n", strtab + symtab[symtab_index].st_name);
  465. #endif
  466. //_dl_exit(1);
  467. return -1;
  468. };
  469. /* instructions were modified */
  470. PPC_DCBST(reloc_addr);
  471. PPC_SYNC;
  472. PPC_ICBI(reloc_addr);
  473. PPC_ISYNC;
  474. #if defined (__SUPPORT_LD_DEBUG__)
  475. if(_dl_debug_reloc && _dl_debug_detail)
  476. _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x", old_val, *reloc_addr, reloc_addr);
  477. #endif
  478. return 0;
  479. }
  480. /* This is done as a separate step, because there are cases where
  481. information is first copied and later initialized. This results in
  482. the wrong information being copied. Someone at Sun was complaining about
  483. a bug in the handling of _COPY by SVr4, and this may in fact be what he
  484. was talking about. Sigh. */
  485. static int
  486. _dl_do_copy (struct elf_resolve *tpnt, struct dyn_elf *scope,
  487. ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
  488. {
  489. int reloc_type;
  490. int symtab_index;
  491. unsigned long *reloc_addr;
  492. unsigned long symbol_addr;
  493. int goof = 0;
  494. char *symname;
  495. reloc_addr = (unsigned long *)(intptr_t) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
  496. reloc_type = ELF32_R_TYPE(rpnt->r_info);
  497. if (reloc_type != R_PPC_COPY)
  498. return 0;
  499. symtab_index = ELF32_R_SYM(rpnt->r_info);
  500. symbol_addr = 0;
  501. symname = strtab + symtab[symtab_index].st_name;
  502. if (symtab_index) {
  503. symbol_addr = (unsigned long) _dl_find_hash(symname, scope, NULL, copyrel);
  504. if (!symbol_addr) goof++;
  505. }
  506. if (!goof) {
  507. #if defined (__SUPPORT_LD_DEBUG__)
  508. if(_dl_debug_move)
  509. _dl_dprintf(_dl_debug_file,"\n%s move %x bytes from %x to %x",
  510. symname, symtab[symtab_index].st_size,
  511. symbol_addr, symtab[symtab_index].st_value);
  512. #endif
  513. _dl_memcpy((char *) reloc_addr,
  514. (char *) (symbol_addr + (unsigned long)rpnt->r_addend), symtab[symtab_index].st_size);
  515. }
  516. return goof;
  517. }
  518. void _dl_parse_lazy_relocation_information(struct elf_resolve *tpnt,
  519. unsigned long rel_addr, unsigned long rel_size, int type)
  520. {
  521. (void) type;
  522. (void)_dl_parse(tpnt, NULL, rel_addr, rel_size, _dl_do_lazy_reloc);
  523. }
  524. int _dl_parse_relocation_information(struct elf_resolve *tpnt,
  525. unsigned long rel_addr, unsigned long rel_size, int type)
  526. {
  527. (void) type;
  528. return _dl_parse(tpnt, tpnt->symbol_scope, rel_addr, rel_size, _dl_do_reloc);
  529. }
  530. int _dl_parse_copy_information(struct dyn_elf *xpnt, unsigned long rel_addr,
  531. unsigned long rel_size, int type)
  532. {
  533. (void) type;
  534. return _dl_parse(xpnt->dyn, xpnt->next, rel_addr, rel_size, _dl_do_copy);
  535. }