elfinterp.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. /* vi: set sw=4 ts=4: */
  2. /* sparc ELF shared library loader suppport
  3. *
  4. * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
  5. * David Engel, Hongjiu Lu and Mitch D'Souza
  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[] = { "R_SPARC_NONE", "R_SPARC_8",
  32. "R_SPARC_16", "R_SPARC_32", "R_SPARC_DISP8", "R_SPARC_DISP16",
  33. "R_SPARC_DISP32", "R_SPARC_WDISP30", "R_SPARC_WDISP22",
  34. "R_SPARC_HI22", "R_SPARC_22", "R_SPARC_13", "R_SPARC_LO10",
  35. "R_SPARC_GOT10", "R_SPARC_GOT13", "R_SPARC_GOT22", "R_SPARC_PC10",
  36. "R_SPARC_PC22", "R_SPARC_WPLT30", "R_SPARC_COPY",
  37. "R_SPARC_GLOB_DAT", "R_SPARC_JMP_SLOT", "R_SPARC_RELATIVE",
  38. "R_SPARC_UA32"};
  39. #endif
  40. /* Program to load an ELF binary on a linux system, and run it.
  41. References to symbols in sharable libraries can be resolved by either
  42. an ELF sharable library or a linux style of shared library. */
  43. /* Disclaimer: I have never seen any AT&T source code for SVr4, nor have
  44. I ever taken any courses on internals. This program was developed using
  45. information available through the book "UNIX SYSTEM V RELEASE 4,
  46. Programmers guide: Ansi C and Programming Support Tools", which did
  47. a more than adequate job of explaining everything required to get this
  48. working. */
  49. extern _dl_linux_resolve(void);
  50. unsigned int _dl_linux_resolver(unsigned int reloc_entry, unsigned int * plt)
  51. {
  52. int reloc_type;
  53. Elf32_Rela * this_reloc;
  54. char * strtab;
  55. Elf32_Sym * symtab;
  56. Elf32_Rela * rel_addr;
  57. struct elf_resolve * tpnt;
  58. int symtab_index;
  59. char * new_addr;
  60. char ** got_addr;
  61. unsigned int instr_addr;
  62. tpnt = (struct elf_resolve *) plt[2];
  63. rel_addr = (Elf32_Rela *) (tpnt->dynamic_info[DT_JMPREL] +
  64. tpnt->loadaddr);
  65. /*
  66. * Generate the correct relocation index into the .rela.plt section.
  67. */
  68. reloc_entry = (reloc_entry >> 12) - 0xc;
  69. this_reloc = (Elf32_Rela *) ((char *) rel_addr + reloc_entry);
  70. reloc_type = ELF32_R_TYPE(this_reloc->r_info);
  71. symtab_index = ELF32_R_SYM(this_reloc->r_info);
  72. symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
  73. strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
  74. _dl_dprintf(2, "tpnt = %x\n", tpnt);
  75. _dl_dprintf(2, "reloc = %x\n", this_reloc);
  76. _dl_dprintf(2, "symtab = %x\n", symtab);
  77. _dl_dprintf(2, "strtab = %x\n", strtab);
  78. if (reloc_type != R_SPARC_JMP_SLOT) {
  79. _dl_dprintf(2, "%s: incorrect relocation type in jump relocations (%d)\n",
  80. _dl_progname, reloc_type);
  81. _dl_exit(30);
  82. };
  83. /* Address of jump instruction to fix up */
  84. instr_addr = ((int)this_reloc->r_offset + (int)tpnt->loadaddr);
  85. got_addr = (char **) instr_addr;
  86. _dl_dprintf(2, "symtab_index %d\n", symtab_index);
  87. #ifdef __SUPPORT_LD_DEBUG__
  88. if (_dl_debug_symbols) {
  89. _dl_dprintf(2, "Resolving symbol %s\n",
  90. strtab + symtab[symtab_index].st_name);
  91. }
  92. #endif
  93. /* Get the address of the GOT entry */
  94. new_addr = _dl_find_hash(strtab + symtab[symtab_index].st_name,
  95. tpnt->symbol_scope, tpnt, resolver);
  96. if(!new_addr) {
  97. _dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
  98. _dl_progname, strtab + symtab[symtab_index].st_name);
  99. _dl_exit(31);
  100. };
  101. #if defined (__SUPPORT_LD_DEBUG__)
  102. if ((unsigned long) got_addr < 0x40000000)
  103. {
  104. if (_dl_debug_bindings)
  105. {
  106. _dl_dprintf(_dl_debug_file, "\nresolve function: %s",
  107. strtab + symtab[symtab_index].st_name);
  108. if(_dl_debug_detail) _dl_dprintf(_dl_debug_file,
  109. "\tpatch %x ==> %x @ %x", *got_addr, new_addr, got_addr);
  110. }
  111. }
  112. if (!_dl_debug_nofixups) {
  113. got_addr[1] = (char *) (0x03000000 | (((unsigned int) new_addr >> 10) & 0x3fffff));
  114. got_addr[2] = (char *) (0x81c06000 | ((unsigned int) new_addr & 0x3ff));
  115. }
  116. #else
  117. got_addr[1] = (char *) (0x03000000 | (((unsigned int) new_addr >> 10) & 0x3fffff));
  118. got_addr[2] = (char *) (0x81c06000 | ((unsigned int) new_addr & 0x3ff));
  119. #endif
  120. _dl_dprintf(2, "Address = %x\n",new_addr);
  121. _dl_exit(32);
  122. return (unsigned int) new_addr;
  123. }
  124. void _dl_parse_lazy_relocation_information(struct elf_resolve * tpnt, int rel_addr,
  125. int rel_size, int type){
  126. int i;
  127. char * strtab;
  128. int reloc_type;
  129. int symtab_index;
  130. Elf32_Sym * symtab;
  131. Elf32_Rela * rpnt;
  132. unsigned int * reloc_addr;
  133. /* Now parse the relocation information */
  134. rpnt = (Elf32_Rela *) (rel_addr + tpnt->loadaddr);
  135. symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
  136. strtab = ( char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
  137. for(i=0; i< rel_size; i += sizeof(Elf32_Rela), rpnt++){
  138. reloc_addr = (int *) (tpnt->loadaddr + (int)rpnt->r_offset);
  139. reloc_type = ELF32_R_TYPE(rpnt->r_info);
  140. symtab_index = ELF32_R_SYM(rpnt->r_info);
  141. /* When the dynamic linker bootstrapped itself, it resolved some symbols.
  142. Make sure we do not do them again */
  143. if(!symtab_index && tpnt->libtype == program_interpreter) continue;
  144. if(symtab_index && tpnt->libtype == program_interpreter &&
  145. _dl_symbol(strtab + symtab[symtab_index].st_name))
  146. continue;
  147. switch(reloc_type){
  148. case R_SPARC_NONE:
  149. break;
  150. case R_SPARC_JMP_SLOT:
  151. break;
  152. default:
  153. _dl_dprintf(2, "%s: (LAZY) can't handle reloc type ", _dl_progname);
  154. #if defined (__SUPPORT_LD_DEBUG__)
  155. _dl_dprintf(2, "%s ", _dl_reltypes[reloc_type]);
  156. #endif
  157. if(symtab_index) _dl_dprintf(2, "'%s'\n",
  158. strtab + symtab[symtab_index].st_name);
  159. _dl_exit(33);
  160. };
  161. };
  162. }
  163. int _dl_parse_relocation_information(struct elf_resolve * tpnt, int rel_addr,
  164. int rel_size, int type){
  165. int i;
  166. char * strtab;
  167. int reloc_type;
  168. int goof = 0;
  169. Elf32_Sym * symtab;
  170. Elf32_Rela * rpnt;
  171. unsigned int * reloc_addr;
  172. unsigned int symbol_addr;
  173. int symtab_index;
  174. /* Now parse the relocation information */
  175. rpnt = (Elf32_Rela *) (rel_addr + tpnt->loadaddr);
  176. symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
  177. strtab = ( char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
  178. for(i=0; i< rel_size; i+= sizeof(Elf32_Rela), rpnt++){
  179. reloc_addr = (int *) (tpnt->loadaddr + (int)rpnt->r_offset);
  180. reloc_type = ELF32_R_TYPE(rpnt->r_info);
  181. symtab_index = ELF32_R_SYM(rpnt->r_info);
  182. symbol_addr = 0;
  183. if(!symtab_index && tpnt->libtype == program_interpreter) continue;
  184. if(symtab_index) {
  185. if(tpnt->libtype == program_interpreter &&
  186. _dl_symbol(strtab + symtab[symtab_index].st_name))
  187. continue;
  188. symbol_addr = (unsigned int)
  189. _dl_find_hash(strtab + symtab[symtab_index].st_name,
  190. tpnt->symbol_scope,
  191. (reloc_type == R_SPARC_JMP_SLOT ? tpnt : NULL), symbolrel);
  192. if(!symbol_addr &&
  193. ELF32_ST_BIND(symtab [symtab_index].st_info) == STB_GLOBAL) {
  194. _dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
  195. _dl_progname, strtab + symtab[symtab_index].st_name);
  196. goof++;
  197. };
  198. };
  199. switch(reloc_type){
  200. case R_SPARC_NONE:
  201. break;
  202. case R_SPARC_32:
  203. *reloc_addr = symbol_addr + rpnt->r_addend;
  204. break;
  205. case R_SPARC_DISP32:
  206. *reloc_addr = symbol_addr + rpnt->r_addend - (unsigned int) reloc_addr;
  207. break;
  208. case R_SPARC_GLOB_DAT:
  209. *reloc_addr = symbol_addr + rpnt->r_addend;
  210. break;
  211. case R_SPARC_JMP_SLOT:
  212. reloc_addr[1] = 0x03000000 | ((symbol_addr >> 10) & 0x3fffff);
  213. reloc_addr[2] = 0x81c06000 | (symbol_addr & 0x3ff);
  214. break;
  215. case R_SPARC_RELATIVE:
  216. *reloc_addr += (unsigned int) tpnt->loadaddr + rpnt->r_addend;
  217. break;
  218. case R_SPARC_HI22:
  219. if (!symbol_addr)
  220. symbol_addr = tpnt->loadaddr + rpnt->r_addend;
  221. else
  222. symbol_addr += rpnt->r_addend;
  223. *reloc_addr = (*reloc_addr & 0xffc00000)|(symbol_addr >> 10);
  224. break;
  225. case R_SPARC_LO10:
  226. if (!symbol_addr)
  227. symbol_addr = tpnt->loadaddr + rpnt->r_addend;
  228. else
  229. symbol_addr += rpnt->r_addend;
  230. *reloc_addr = (*reloc_addr & ~0x3ff)|(symbol_addr & 0x3ff);
  231. break;
  232. case R_SPARC_WDISP30:
  233. *reloc_addr = (*reloc_addr & 0xc0000000)|
  234. ((symbol_addr - (unsigned int) reloc_addr) >> 2);
  235. break;
  236. case R_SPARC_COPY:
  237. #if 0 /* This one is done later */
  238. _dl_dprintf(2, "Doing copy for symbol ");
  239. if(symtab_index) _dl_dprintf(2, strtab + symtab[symtab_index].st_name);
  240. _dl_dprintf(2, "\n");
  241. _dl_memcpy((void *) symtab[symtab_index].st_value,
  242. (void *) symbol_addr,
  243. symtab[symtab_index].st_size);
  244. #endif
  245. break;
  246. default:
  247. _dl_dprintf(2, "%s: can't handle reloc type ", _dl_progname);
  248. #if defined (__SUPPORT_LD_DEBUG__)
  249. _dl_dprintf(2, "%s ", _dl_reltypes[reloc_type]);
  250. #endif
  251. if (symtab_index)
  252. _dl_dprintf(2, "'%s'\n", strtab + symtab[symtab_index].st_name);
  253. _dl_exit(34);
  254. };
  255. };
  256. return goof;
  257. }
  258. /* This is done as a separate step, because there are cases where
  259. information is first copied and later initialized. This results in
  260. the wrong information being copied. Someone at Sun was complaining about
  261. a bug in the handling of _COPY by SVr4, and this may in fact be what he
  262. was talking about. Sigh. */
  263. /* No, there are cases where the SVr4 linker fails to emit COPY relocs
  264. at all */
  265. int _dl_parse_copy_information(struct dyn_elf * xpnt, int rel_addr,
  266. int rel_size, int type)
  267. {
  268. int i;
  269. char * strtab;
  270. int reloc_type;
  271. int goof = 0;
  272. Elf32_Sym * symtab;
  273. Elf32_Rela * rpnt;
  274. unsigned int * reloc_addr;
  275. unsigned int symbol_addr;
  276. struct elf_resolve *tpnt;
  277. int symtab_index;
  278. /* Now parse the relocation information */
  279. tpnt = xpnt->dyn;
  280. rpnt = (Elf32_Rela *) (rel_addr + tpnt->loadaddr);
  281. symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
  282. strtab = ( char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
  283. for(i=0; i< rel_size; i+= sizeof(Elf32_Rela), rpnt++){
  284. reloc_addr = (int *) (tpnt->loadaddr + (int)rpnt->r_offset);
  285. reloc_type = ELF32_R_TYPE(rpnt->r_info);
  286. if(reloc_type != R_SPARC_COPY) continue;
  287. symtab_index = ELF32_R_SYM(rpnt->r_info);
  288. symbol_addr = 0;
  289. if(!symtab_index && tpnt->libtype == program_interpreter) 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 int)
  295. _dl_find_hash(strtab + symtab[symtab_index].st_name,
  296. xpnt->next, NULL, copyrel);
  297. if(!symbol_addr) {
  298. _dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
  299. _dl_progname, strtab + symtab[symtab_index].st_name);
  300. goof++;
  301. };
  302. };
  303. if (!goof)
  304. _dl_memcpy((char *) symtab[symtab_index].st_value,
  305. (char *) symbol_addr,
  306. symtab[symtab_index].st_size);
  307. };
  308. return goof;
  309. }