elfinterp.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. /*
  2. * Copyright (C) 2017 Hangzhou C-SKY Microsystems co.,ltd.
  3. *
  4. * Licensed under the LGPL v2.1 or later, see the file COPYING.LIB
  5. * in this tarball.
  6. */
  7. #include "ldso.h"
  8. unsigned long
  9. _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
  10. {
  11. ELF_RELOC *this_reloc;
  12. int symtab_index;
  13. //char *rel_tab;
  14. Elf32_Sym *sym_tab;
  15. char *str_tab;
  16. char *sym_name;
  17. char *sym_addr;
  18. char **reloc_addr;
  19. this_reloc = (ELF_RELOC *)tpnt->dynamic_info[DT_JMPREL];
  20. this_reloc += reloc_entry;
  21. //this_reloc = (ELF_RELOC *)(intptr_t)(rel_tab + reloc_entry);
  22. symtab_index = ELF32_R_SYM(this_reloc->r_info);
  23. sym_tab = (Elf32_Sym *)(intptr_t)tpnt->dynamic_info[DT_SYMTAB];
  24. str_tab = (char *)tpnt->dynamic_info[DT_STRTAB];
  25. sym_name = str_tab + sym_tab[symtab_index].st_name;
  26. reloc_addr = (char **)((unsigned long)this_reloc->r_offset +
  27. (unsigned long)tpnt->loadaddr);
  28. sym_addr = _dl_find_hash(sym_name, &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
  29. if (unlikely(!sym_addr)) {
  30. _dl_dprintf(2, "%s: 1can't resolve symbol '%s' in lib '%s'.\n", _dl_progname, sym_name, tpnt->libname);
  31. _dl_exit(1);
  32. }
  33. *reloc_addr = sym_addr;
  34. return (unsigned long)sym_addr;
  35. }
  36. static int
  37. _dl_parse(struct elf_resolve *tpnt, struct r_scope_elem*scope,
  38. unsigned long rel_addr, unsigned long rel_size,
  39. int (*reloc_fnc)(struct elf_resolve *tpnt, struct r_scope_elem*scope,
  40. ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab))
  41. {
  42. unsigned int i;
  43. char *strtab;
  44. Elf32_Sym *symtab;
  45. ELF_RELOC *rpnt;
  46. int symtab_index;
  47. /* Parse the relocation information. */
  48. rpnt = (ELF_RELOC *)(intptr_t)rel_addr;
  49. rel_size /= sizeof(ELF_RELOC);
  50. symtab = (Elf32_Sym *)(intptr_t)tpnt->dynamic_info[DT_SYMTAB];
  51. strtab = (char *)tpnt->dynamic_info[DT_STRTAB];
  52. for (i = 0; i < rel_size; i++, rpnt++) {
  53. int res;
  54. symtab_index = ELF32_R_SYM(rpnt->r_info);
  55. debug_sym(symtab, strtab, symtab_index);
  56. debug_reloc(symtab, strtab, rpnt);
  57. res = reloc_fnc(tpnt, scope, rpnt, symtab, strtab);
  58. if (res == 0)
  59. continue;
  60. _dl_dprintf(2, "\n%s: ", _dl_progname);
  61. if (symtab_index)
  62. _dl_dprintf(2, "symbol '%s': ",
  63. strtab + symtab[symtab_index].st_name);
  64. if (unlikely(res < 0)) {
  65. int reloc_type = ELF32_R_TYPE(rpnt->r_info);
  66. _dl_dprintf(2, "2can't handle reloc type %x in lib '%s'\n",
  67. reloc_type, tpnt->libname);
  68. return res;
  69. } else if (unlikely(res > 0)) {
  70. _dl_dprintf(2, "3can't resolve symbol in lib '%s'.\n", tpnt->libname);
  71. return res;
  72. }
  73. }
  74. return 0;
  75. }
  76. static int
  77. _dl_do_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
  78. ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
  79. {
  80. int reloc_type;
  81. int symtab_index;
  82. char *symname;
  83. unsigned long *reloc_addr;
  84. unsigned long symbol_addr;
  85. struct symbol_ref sym_ref;
  86. #if defined (__SUPPORT_LD_DEBUG__)
  87. unsigned long old_val;
  88. #endif
  89. #if defined USE_TLS && USE_TLS
  90. struct elf_resolve *tls_tpnt = NULL;
  91. #endif
  92. #if defined(__CSKYABIV2__)
  93. unsigned int insn_opcode = 0x0;
  94. unsigned short *opcode16_addr;
  95. #endif
  96. reloc_addr = (unsigned long *)(intptr_t)(tpnt->loadaddr + (unsigned long)rpnt->r_offset);
  97. #if defined(__CSKYABIV2__)
  98. opcode16_addr = (unsigned short *)reloc_addr;
  99. #endif
  100. reloc_type = ELF32_R_TYPE(rpnt->r_info);
  101. if (reloc_type == R_CKCORE_NONE)
  102. return 0;
  103. symtab_index = ELF32_R_SYM(rpnt->r_info);
  104. symbol_addr = 0;
  105. sym_ref.sym = &symtab[symtab_index];
  106. sym_ref.tpnt = NULL;
  107. symname = strtab + symtab[symtab_index].st_name;
  108. if (symtab_index) {
  109. symbol_addr = (unsigned long)_dl_find_hash(symname, scope, tpnt,
  110. elf_machine_type_class(reloc_type), &sym_ref);
  111. /*
  112. * We want to allow undefined references to weak symbols - this
  113. * might have been intentional. We should not be linking local
  114. * symbols here, so all bases should be covered.
  115. */
  116. // if (unlikely(!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK))
  117. if (!symbol_addr && (ELF_ST_TYPE(symtab[symtab_index].st_info) != STT_TLS)
  118. && (ELF_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK))
  119. return 1;
  120. #if defined USE_TLS && USE_TLS
  121. tls_tpnt = sym_ref.tpnt;
  122. #endif
  123. }else{
  124. /*
  125. * Relocs against STN_UNDEF are usually treated as using a
  126. * symbol value of zero, and using the module containing the
  127. * reloc itself.
  128. */
  129. symbol_addr = symtab[symtab_index].st_name;
  130. #if defined USE_TLS && USE_TLS
  131. tls_tpnt = tpnt;
  132. #endif
  133. }
  134. #if defined (__SUPPORT_LD_DEBUG__)
  135. old_val = *reloc_addr;
  136. #endif
  137. switch (reloc_type) { /* need modify */
  138. case R_CKCORE_NONE:
  139. case R_CKCORE_PCRELJSR_IMM11BY2:
  140. break;
  141. case R_CKCORE_ADDR32:
  142. *reloc_addr = symbol_addr + rpnt->r_addend;
  143. break;
  144. case R_CKCORE_GLOB_DAT:
  145. case R_CKCORE_JUMP_SLOT:
  146. *reloc_addr = symbol_addr;
  147. break;
  148. case R_CKCORE_RELATIVE:
  149. *reloc_addr = (unsigned long)tpnt->loadaddr + rpnt->r_addend;
  150. break;
  151. #if defined(__CSKYABIV2__)
  152. case R_CKCORE_ADDR_HI16:
  153. insn_opcode = (*opcode16_addr << 16) | (*(opcode16_addr + 1));
  154. insn_opcode = (insn_opcode & 0xffff0000)
  155. | (((symbol_addr + rpnt->r_addend) >> 16) & 0xffff);
  156. *(opcode16_addr++) = (unsigned short)(insn_opcode >> 16);
  157. *opcode16_addr = (unsigned short)(insn_opcode & 0xffff);
  158. break;
  159. case R_CKCORE_ADDR_LO16:
  160. insn_opcode = (*opcode16_addr << 16) | (*(opcode16_addr + 1));
  161. insn_opcode = (insn_opcode & 0xffff0000)
  162. | ((symbol_addr + rpnt->r_addend) & 0xffff);
  163. *(opcode16_addr++) = (unsigned short)(insn_opcode >> 16);
  164. *opcode16_addr = (unsigned short)(insn_opcode & 0xffff);
  165. break;
  166. case R_CKCORE_PCREL_IMM26BY2:
  167. {
  168. unsigned int offset = ((symbol_addr + rpnt->r_addend -
  169. (unsigned int)reloc_addr) >> 1);
  170. insn_opcode = (*opcode16_addr << 16) | (*(opcode16_addr + 1));
  171. if (offset > 0x3ffffff){
  172. _dl_dprintf(2, "%s:The reloc R_CKCORE_PCREL_IMM26BY2 cannot reach the symbol '%s'.\n", _dl_progname, symname);
  173. _dl_exit(1);
  174. }
  175. insn_opcode = (insn_opcode & ~0x3ffffff) | offset;
  176. *(opcode16_addr++) = (unsigned short)(insn_opcode >> 16);
  177. *opcode16_addr = (unsigned short)(insn_opcode & 0xffff);
  178. break;
  179. }
  180. case R_CKCORE_PCREL_JSR_IMM26BY2:
  181. break;
  182. #endif
  183. case R_CKCORE_COPY:
  184. if (symbol_addr) {
  185. #if defined (__SUPPORT_LD_DEBUG__)
  186. if (_dl_debug_move)
  187. _dl_dprintf(_dl_debug_file,
  188. "\n%s move %d bytes from %x to %x",
  189. symname, symtab[symtab_index].st_size,
  190. symbol_addr, reloc_addr);
  191. #endif
  192. _dl_memcpy((char *)reloc_addr,
  193. (char *)symbol_addr,
  194. symtab[symtab_index].st_size);
  195. }
  196. break;
  197. #if defined USE_TLS && USE_TLS
  198. case R_CKCORE_TLS_DTPMOD32:
  199. *reloc_addr = tls_tpnt->l_tls_modid;
  200. break;
  201. case R_CKCORE_TLS_DTPOFF32:
  202. *reloc_addr += symbol_addr;
  203. break;
  204. case R_CKCORE_TLS_TPOFF32:
  205. CHECK_STATIC_TLS ((struct link_map *) tls_tpnt);
  206. *reloc_addr += tls_tpnt->l_tls_offset + symbol_addr;
  207. break;
  208. #endif
  209. default:
  210. return -1;
  211. }
  212. #if defined (__SUPPORT_LD_DEBUG__)
  213. if (_dl_debug_reloc && _dl_debug_detail)
  214. _dl_dprintf(_dl_debug_file, "\n\tpatched: %x ==> %x @ %x",
  215. old_val, *reloc_addr, reloc_addr);
  216. #endif
  217. return 0;
  218. }
  219. static int
  220. _dl_do_lazy_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
  221. ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
  222. {
  223. int reloc_type;
  224. unsigned long *reloc_addr;
  225. #if defined (__SUPPORT_LD_DEBUG__)
  226. unsigned long old_val;
  227. #endif
  228. reloc_addr = (unsigned long *)(intptr_t)(tpnt->loadaddr + (unsigned long)rpnt->r_offset);
  229. reloc_type = ELF32_R_TYPE(rpnt->r_info);
  230. #if defined (__SUPPORT_LD_DEBUG__)
  231. old_val = *reloc_addr;
  232. #endif
  233. switch (reloc_type) {
  234. case R_CKCORE_NONE:
  235. case R_CKCORE_PCRELJSR_IMM11BY2:
  236. break;
  237. case R_CKCORE_JUMP_SLOT:
  238. *reloc_addr = (unsigned long)tpnt->loadaddr + rpnt->r_addend;
  239. break;
  240. default:
  241. return -1;
  242. }
  243. #if defined (__SUPPORT_LD_DEBUG__)
  244. if (_dl_debug_reloc && _dl_debug_detail)
  245. _dl_dprintf(_dl_debug_file, "\n\tpatched: %x ==> %x @ %x",
  246. old_val, *reloc_addr, reloc_addr);
  247. #endif
  248. return 0;
  249. }
  250. void
  251. _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
  252. unsigned long rel_addr,
  253. unsigned long rel_size)
  254. {
  255. (void)_dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc);
  256. }
  257. int
  258. _dl_parse_relocation_information(struct dyn_elf *rpnt,
  259. struct r_scope_elem *scope,
  260. unsigned long rel_addr,
  261. unsigned long rel_size)
  262. {
  263. return _dl_parse(rpnt->dyn, scope, rel_addr, rel_size, _dl_do_reloc);
  264. }