elfinterp.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  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. #if defined (__SUPPORT_LD_DEBUG__)
  67. _dl_dprintf(2, "2can't handle reloc type '%s' in lib '%s'\n",
  68. _dl_reltypes(reloc_type), tpnt->libname);
  69. #else
  70. _dl_dprintf(2, "3can't handle reloc type %x in lib '%s'\n",
  71. reloc_type, tpnt->libname);
  72. #endif
  73. return res;
  74. } else if (unlikely(res > 0)) {
  75. _dl_dprintf(2, "4can't resolve symbol in lib '%s'.\n", tpnt->libname);
  76. return res;
  77. }
  78. }
  79. return 0;
  80. }
  81. static int
  82. _dl_do_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
  83. ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
  84. {
  85. int reloc_type;
  86. int symtab_index;
  87. char *symname;
  88. unsigned long *reloc_addr;
  89. unsigned long symbol_addr;
  90. struct symbol_ref sym_ref;
  91. #if defined (__SUPPORT_LD_DEBUG__)
  92. unsigned long old_val;
  93. #endif
  94. #if defined USE_TLS && USE_TLS
  95. struct elf_resolve *tls_tpnt = NULL;
  96. #endif
  97. #if defined(__CSKYABIV2__)
  98. unsigned int insn_opcode = 0x0;
  99. unsigned short *opcode16_addr;
  100. #endif
  101. reloc_addr = (unsigned long *)(intptr_t)(tpnt->loadaddr + (unsigned long)rpnt->r_offset);
  102. #if defined(__CSKYABIV2__)
  103. opcode16_addr = (unsigned short *)reloc_addr;
  104. #endif
  105. reloc_type = ELF32_R_TYPE(rpnt->r_info);
  106. if (reloc_type == R_CKCORE_NONE)
  107. return 0;
  108. symtab_index = ELF32_R_SYM(rpnt->r_info);
  109. symbol_addr = 0;
  110. sym_ref.sym = &symtab[symtab_index];
  111. sym_ref.tpnt = NULL;
  112. symname = strtab + symtab[symtab_index].st_name;
  113. if (symtab_index) {
  114. symbol_addr = (unsigned long)_dl_find_hash(symname, scope, tpnt,
  115. elf_machine_type_class(reloc_type), &sym_ref);
  116. /*
  117. * We want to allow undefined references to weak symbols - this
  118. * might have been intentional. We should not be linking local
  119. * symbols here, so all bases should be covered.
  120. */
  121. // if (unlikely(!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK))
  122. if (!symbol_addr && (ELF_ST_TYPE(symtab[symtab_index].st_info) != STT_TLS)
  123. && (ELF_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK))
  124. return 1;
  125. #if defined USE_TLS && USE_TLS
  126. tls_tpnt = sym_ref.tpnt;
  127. #endif
  128. }else{
  129. /*
  130. * Relocs against STN_UNDEF are usually treated as using a
  131. * symbol value of zero, and using the module containing the
  132. * reloc itself.
  133. */
  134. symbol_addr = symtab[symtab_index].st_name;
  135. #if defined USE_TLS && USE_TLS
  136. tls_tpnt = tpnt;
  137. #endif
  138. }
  139. #if defined (__SUPPORT_LD_DEBUG__)
  140. old_val = *reloc_addr;
  141. #endif
  142. switch (reloc_type) { /* need modify */
  143. case R_CKCORE_NONE:
  144. case R_CKCORE_PCRELJSR_IMM11BY2:
  145. break;
  146. case R_CKCORE_ADDR32:
  147. *reloc_addr = symbol_addr + rpnt->r_addend;
  148. break;
  149. case R_CKCORE_GLOB_DAT:
  150. case R_CKCORE_JUMP_SLOT:
  151. *reloc_addr = symbol_addr;
  152. break;
  153. case R_CKCORE_RELATIVE:
  154. *reloc_addr = (unsigned long)tpnt->loadaddr + rpnt->r_addend;
  155. break;
  156. #if defined(__CSKYABIV2__)
  157. case R_CKCORE_ADDR_HI16:
  158. insn_opcode = (*opcode16_addr << 16) | (*(opcode16_addr + 1));
  159. insn_opcode = (insn_opcode & 0xffff0000)
  160. | (((symbol_addr + rpnt->r_addend) >> 16) & 0xffff);
  161. *(opcode16_addr++) = (unsigned short)(insn_opcode >> 16);
  162. *opcode16_addr = (unsigned short)(insn_opcode & 0xffff);
  163. break;
  164. case R_CKCORE_ADDR_LO16:
  165. insn_opcode = (*opcode16_addr << 16) | (*(opcode16_addr + 1));
  166. insn_opcode = (insn_opcode & 0xffff0000)
  167. | ((symbol_addr + rpnt->r_addend) & 0xffff);
  168. *(opcode16_addr++) = (unsigned short)(insn_opcode >> 16);
  169. *opcode16_addr = (unsigned short)(insn_opcode & 0xffff);
  170. break;
  171. case R_CKCORE_PCREL_IMM26BY2:
  172. {
  173. unsigned int offset = ((symbol_addr + rpnt->r_addend -
  174. (unsigned int)reloc_addr) >> 1);
  175. insn_opcode = (*opcode16_addr << 16) | (*(opcode16_addr + 1));
  176. if (offset > 0x3ffffff){
  177. _dl_dprintf(2, "%s:The reloc R_CKCORE_PCREL_IMM26BY2 cannot reach the symbol '%s'.\n", _dl_progname, symname);
  178. _dl_exit(1);
  179. }
  180. insn_opcode = (insn_opcode & ~0x3ffffff) | offset;
  181. *(opcode16_addr++) = (unsigned short)(insn_opcode >> 16);
  182. *opcode16_addr = (unsigned short)(insn_opcode & 0xffff);
  183. break;
  184. }
  185. case R_CKCORE_PCREL_JSR_IMM26BY2:
  186. break;
  187. #endif
  188. case R_CKCORE_COPY:
  189. if (symbol_addr) {
  190. #if defined (__SUPPORT_LD_DEBUG__)
  191. if (_dl_debug_move)
  192. _dl_dprintf(_dl_debug_file,
  193. "\n%s move %d bytes from %x to %x",
  194. symname, symtab[symtab_index].st_size,
  195. symbol_addr, reloc_addr);
  196. #endif
  197. _dl_memcpy((char *)reloc_addr,
  198. (char *)symbol_addr,
  199. symtab[symtab_index].st_size);
  200. }
  201. break;
  202. #if defined USE_TLS && USE_TLS
  203. case R_CKCORE_TLS_DTPMOD32:
  204. *reloc_addr = tls_tpnt->l_tls_modid;
  205. break;
  206. case R_CKCORE_TLS_DTPOFF32:
  207. *reloc_addr += symbol_addr;
  208. break;
  209. case R_CKCORE_TLS_TPOFF32:
  210. CHECK_STATIC_TLS ((struct link_map *) tls_tpnt);
  211. *reloc_addr += tls_tpnt->l_tls_offset + symbol_addr;
  212. break;
  213. #endif
  214. default:
  215. return -1;
  216. }
  217. #if defined (__SUPPORT_LD_DEBUG__)
  218. if (_dl_debug_reloc && _dl_debug_detail)
  219. _dl_dprintf(_dl_debug_file, "\n\tpatched: %x ==> %x @ %x",
  220. old_val, *reloc_addr, reloc_addr);
  221. #endif
  222. return 0;
  223. }
  224. static int
  225. _dl_do_lazy_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
  226. ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
  227. {
  228. int reloc_type;
  229. unsigned long *reloc_addr;
  230. #if defined (__SUPPORT_LD_DEBUG__)
  231. unsigned long old_val;
  232. #endif
  233. reloc_addr = (unsigned long *)(intptr_t)(tpnt->loadaddr + (unsigned long)rpnt->r_offset);
  234. reloc_type = ELF32_R_TYPE(rpnt->r_info);
  235. #if defined (__SUPPORT_LD_DEBUG__)
  236. old_val = *reloc_addr;
  237. #endif
  238. switch (reloc_type) {
  239. case R_CKCORE_NONE:
  240. case R_CKCORE_PCRELJSR_IMM11BY2:
  241. break;
  242. case R_CKCORE_JUMP_SLOT:
  243. *reloc_addr = (unsigned long)tpnt->loadaddr + rpnt->r_addend;
  244. break;
  245. default:
  246. return -1;
  247. }
  248. #if defined (__SUPPORT_LD_DEBUG__)
  249. if (_dl_debug_reloc && _dl_debug_detail)
  250. _dl_dprintf(_dl_debug_file, "\n\tpatched: %x ==> %x @ %x",
  251. old_val, *reloc_addr, reloc_addr);
  252. #endif
  253. return 0;
  254. }
  255. void
  256. _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
  257. unsigned long rel_addr,
  258. unsigned long rel_size)
  259. {
  260. (void)_dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc);
  261. }
  262. int
  263. _dl_parse_relocation_information(struct dyn_elf *rpnt,
  264. struct r_scope_elem *scope,
  265. unsigned long rel_addr,
  266. unsigned long rel_size)
  267. {
  268. return _dl_parse(rpnt->dyn, scope, rel_addr, rel_size, _dl_do_reloc);
  269. }