elfinterp.c 17 KB

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