elfinterp.c 17 KB

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