aot_reloc_thumb.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  1. /*
  2. * Copyright (C) 2019 Intel Corporation. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #include "aot_reloc.h"
  6. #define R_ARM_ABS32 2 /* Direct 32 bit */
  7. #define R_ARM_THM_CALL 10 /* PC relative (Thumb BL and ARMv5 Thumb BLX). */
  8. #define R_ARM_THM_JMP24 30 /* B.W */
  9. #define R_ARM_THM_MOVW_ABS_NC 47
  10. #define R_ARM_THM_MOVT_ABS 48
  11. #define R_ARM_THM_MOVW_PREL_NC 49
  12. #define R_ARM_THM_MOVT_PREL 50
  13. /* clang-format off */
  14. void __adddf3(void);
  15. void __addsf3(void);
  16. void __aeabi_d2f(void);
  17. void __aeabi_d2iz(void);
  18. void __aeabi_d2lz(void);
  19. void __aeabi_d2uiz(void);
  20. void __aeabi_d2ulz(void);
  21. void __aeabi_dadd(void);
  22. void __aeabi_dcmpeq(void);
  23. void __aeabi_dcmpge(void);
  24. void __aeabi_dcmpgt(void);
  25. void __aeabi_dcmple(void);
  26. void __aeabi_dcmplt(void);
  27. void __aeabi_dcmpun(void);
  28. void __aeabi_ddiv(void);
  29. void __aeabi_dmul(void);
  30. void __aeabi_dsub(void);
  31. void __aeabi_f2d(void);
  32. void __aeabi_f2iz(void);
  33. void __aeabi_f2lz(void);
  34. void __aeabi_f2ulz(void);
  35. void __aeabi_fadd(void);
  36. void __aeabi_fcmpeq(void);
  37. void __aeabi_fcmpge(void);
  38. void __aeabi_fcmpgt(void);
  39. void __aeabi_fcmple(void);
  40. void __aeabi_fcmplt(void);
  41. void __aeabi_fcmpun(void);
  42. void __aeabi_fdiv(void);
  43. void __aeabi_fmul(void);
  44. void __aeabi_fsub(void);
  45. void __aeabi_i2d(void);
  46. void __aeabi_i2f(void);
  47. void __aeabi_idiv(void);
  48. void __aeabi_idivmod(void);
  49. void __aeabi_l2d(void);
  50. void __aeabi_l2f(void);
  51. void __aeabi_ldivmod(void);
  52. void __aeabi_llsl(void);
  53. void __aeabi_llsr(void);
  54. void __aeabi_lmul(void);
  55. void __aeabi_ui2d(void);
  56. void __aeabi_ui2f(void);
  57. void __aeabi_uidiv(void);
  58. void __aeabi_uidivmod(void);
  59. void __aeabi_ul2d(void);
  60. void __aeabi_ul2f(void);
  61. void __aeabi_uldivmod(void);
  62. void __ashldi3(void);
  63. void __clzsi2(void);
  64. void __divdf3(void);
  65. void __divdi3(void);
  66. void __divsi3(void);
  67. void __eqdf2(void);
  68. void __eqsf2(void);
  69. void __extendsfdf2(void);
  70. void __fixdfdi(void);
  71. void __fixdfsi(void);
  72. void __fixsfdi(void);
  73. void __fixunsdfdi(void);
  74. void __fixunsdfsi(void);
  75. void __fixunssfdi(void);
  76. void __floatdidf(void);
  77. void __floatdisf(void);
  78. void __floatsidf(void);
  79. void __floatsisf(void);
  80. void __floatundidf(void);
  81. void __floatundisf(void);
  82. void __floatunsidf(void);
  83. void __floatunsisf(void);
  84. void __gedf2(void);
  85. void __gesf2(void);
  86. void __gtdf2(void);
  87. void __gtsf2(void);
  88. void __ledf2(void);
  89. void __lesf2(void);
  90. void __lshrdi3(void);
  91. void __ltdf2(void);
  92. void __ltsf2(void);
  93. void __moddi3(void);
  94. void __modsi3(void);
  95. void __muldf3(void);
  96. void __muldi3(void);
  97. void __mulsf3(void);
  98. void __nedf2(void);
  99. void __nesf2(void);
  100. void __subdf3(void);
  101. void __subsf3(void);
  102. void __truncdfsf2(void);
  103. void __udivdi3(void);
  104. void __udivmoddi4(void);
  105. void __udivsi3(void);
  106. void __umoddi3(void);
  107. void __umodsi3(void);
  108. void __unorddf2(void);
  109. void __unordsf2(void);
  110. /* clang-format on */
  111. static SymbolMap target_sym_map[] = {
  112. /* clang-format off */
  113. REG_COMMON_SYMBOLS
  114. /* compiler-rt symbols that come from compiler(e.g. gcc) */
  115. #if __ARM_ARCH != 6
  116. REG_SYM(__adddf3),
  117. REG_SYM(__addsf3),
  118. REG_SYM(__divdf3),
  119. REG_SYM(__extendsfdf2),
  120. REG_SYM(__fixdfsi),
  121. REG_SYM(__floatsidf),
  122. REG_SYM(__floatsisf),
  123. REG_SYM(__floatunsidf),
  124. REG_SYM(__floatunsisf),
  125. REG_SYM(__muldf3),
  126. REG_SYM(__mulsf3),
  127. REG_SYM(__subdf3),
  128. REG_SYM(__subsf3),
  129. REG_SYM(__truncdfsf2),
  130. REG_SYM(__unorddf2),
  131. REG_SYM(__unordsf2),
  132. #endif
  133. /* clang-format on */
  134. REG_SYM(__aeabi_d2f),
  135. REG_SYM(__aeabi_d2iz),
  136. REG_SYM(__aeabi_d2lz),
  137. REG_SYM(__aeabi_d2uiz),
  138. REG_SYM(__aeabi_d2ulz),
  139. REG_SYM(__aeabi_dadd),
  140. REG_SYM(__aeabi_dcmpeq),
  141. REG_SYM(__aeabi_dcmpge),
  142. REG_SYM(__aeabi_dcmpgt),
  143. REG_SYM(__aeabi_dcmple),
  144. REG_SYM(__aeabi_dcmplt),
  145. REG_SYM(__aeabi_dcmpun),
  146. REG_SYM(__aeabi_ddiv),
  147. REG_SYM(__aeabi_dmul),
  148. REG_SYM(__aeabi_dsub),
  149. REG_SYM(__aeabi_f2d),
  150. REG_SYM(__aeabi_f2iz),
  151. REG_SYM(__aeabi_f2lz),
  152. REG_SYM(__aeabi_f2ulz),
  153. REG_SYM(__aeabi_fadd),
  154. REG_SYM(__aeabi_fcmpeq),
  155. REG_SYM(__aeabi_fcmpge),
  156. REG_SYM(__aeabi_fcmpgt),
  157. REG_SYM(__aeabi_fcmple),
  158. REG_SYM(__aeabi_fcmplt),
  159. REG_SYM(__aeabi_fcmpun),
  160. REG_SYM(__aeabi_fdiv),
  161. REG_SYM(__aeabi_fmul),
  162. REG_SYM(__aeabi_fsub),
  163. REG_SYM(__aeabi_i2d),
  164. REG_SYM(__aeabi_i2f),
  165. REG_SYM(__aeabi_idiv),
  166. REG_SYM(__aeabi_idivmod),
  167. REG_SYM(__aeabi_l2d),
  168. REG_SYM(__aeabi_l2f),
  169. REG_SYM(__aeabi_ldivmod),
  170. REG_SYM(__aeabi_llsl),
  171. REG_SYM(__aeabi_llsr),
  172. REG_SYM(__aeabi_lmul),
  173. REG_SYM(__aeabi_ui2d),
  174. REG_SYM(__aeabi_ui2f),
  175. REG_SYM(__aeabi_uidiv),
  176. REG_SYM(__aeabi_uidivmod),
  177. REG_SYM(__aeabi_ul2d),
  178. REG_SYM(__aeabi_ul2f),
  179. REG_SYM(__aeabi_uldivmod),
  180. REG_SYM(__ashldi3),
  181. REG_SYM(__clzsi2),
  182. REG_SYM(__divdi3),
  183. REG_SYM(__divsi3),
  184. REG_SYM(__eqdf2),
  185. REG_SYM(__eqsf2),
  186. REG_SYM(__fixdfdi),
  187. REG_SYM(__fixsfdi),
  188. REG_SYM(__fixunsdfdi),
  189. REG_SYM(__fixunsdfsi),
  190. REG_SYM(__fixunssfdi),
  191. REG_SYM(__floatdidf),
  192. REG_SYM(__floatdisf),
  193. REG_SYM(__floatundidf),
  194. REG_SYM(__floatundisf),
  195. REG_SYM(__gedf2),
  196. REG_SYM(__gesf2),
  197. REG_SYM(__gtdf2),
  198. REG_SYM(__gtsf2),
  199. REG_SYM(__ledf2),
  200. REG_SYM(__lesf2),
  201. REG_SYM(__lshrdi3),
  202. REG_SYM(__ltdf2),
  203. REG_SYM(__ltsf2),
  204. REG_SYM(__moddi3),
  205. REG_SYM(__modsi3),
  206. REG_SYM(__muldi3),
  207. REG_SYM(__nedf2),
  208. REG_SYM(__nesf2),
  209. REG_SYM(__udivdi3),
  210. REG_SYM(__udivmoddi4),
  211. REG_SYM(__udivsi3),
  212. REG_SYM(__umoddi3),
  213. REG_SYM(__umodsi3),
  214. };
  215. static void
  216. set_error_buf(char *error_buf, uint32 error_buf_size, const char *string)
  217. {
  218. if (error_buf != NULL)
  219. snprintf(error_buf, error_buf_size, "%s", string);
  220. }
  221. SymbolMap *
  222. get_target_symbol_map(uint32 *sym_num)
  223. {
  224. *sym_num = sizeof(target_sym_map) / sizeof(SymbolMap);
  225. return target_sym_map;
  226. }
  227. #define BUILD_TARGET_THUMB_V4T "thumbv4t"
  228. void
  229. get_current_target(char *target_buf, uint32 target_buf_size)
  230. {
  231. const char *s = BUILD_TARGET;
  232. size_t s_size = sizeof(BUILD_TARGET);
  233. char *d = target_buf;
  234. /* Set to "thumbv4t" by default if sub version isn't specified */
  235. if (strcmp(s, "THUMB") == 0) {
  236. s = BUILD_TARGET_THUMB_V4T;
  237. s_size = sizeof(BUILD_TARGET_THUMB_V4T);
  238. }
  239. if (target_buf_size < s_size) {
  240. s_size = target_buf_size;
  241. }
  242. while (--s_size) {
  243. if (*s >= 'A' && *s <= 'Z')
  244. *d++ = *s++ + 'a' - 'A';
  245. else
  246. *d++ = *s++;
  247. }
  248. /* Ensure the string is null byte ('\0') terminated */
  249. *d = '\0';
  250. }
  251. #undef BUILD_TARGET_THUMB_V4T
  252. uint32
  253. get_plt_item_size(void)
  254. {
  255. /* 16 bytes instructions and 4 bytes symbol address */
  256. return 20;
  257. }
  258. uint32
  259. get_plt_table_size()
  260. {
  261. return get_plt_item_size() * (sizeof(target_sym_map) / sizeof(SymbolMap));
  262. }
  263. void
  264. init_plt_table(uint8 *plt)
  265. {
  266. uint32 i, num = sizeof(target_sym_map) / sizeof(SymbolMap);
  267. for (i = 0; i < num; i++) {
  268. uint16 *p = (uint16 *)plt;
  269. /* nop */
  270. *p++ = 0xbf00;
  271. /* push {r4} */
  272. *p++ = 0xb410;
  273. /* add r4, pc, #8 */
  274. *p++ = 0xa402;
  275. /* ldr r4, [r4, #0] */
  276. *p++ = 0x6824;
  277. /* mov ip, r4 */
  278. *p++ = 0x46a4;
  279. /* pop {r4} */
  280. *p++ = 0xbc10;
  281. /* mov pc, ip */
  282. *p++ = 0x46e7;
  283. /* nop */
  284. *p++ = 0xbf00;
  285. /* symbol addr */
  286. *(uint32 *)p = (uint32)(uintptr_t)target_sym_map[i].symbol_addr;
  287. plt += get_plt_item_size();
  288. }
  289. }
  290. static bool
  291. check_reloc_offset(uint32 target_section_size, uint64 reloc_offset,
  292. uint32 reloc_data_size, char *error_buf,
  293. uint32 error_buf_size)
  294. {
  295. if (!(reloc_offset < (uint64)target_section_size
  296. && reloc_offset + reloc_data_size <= (uint64)target_section_size)) {
  297. set_error_buf(error_buf, error_buf_size,
  298. "AOT module load failed: invalid relocation offset.");
  299. return false;
  300. }
  301. return true;
  302. }
  303. bool
  304. apply_relocation(AOTModule *module, uint8 *target_section_addr,
  305. uint32 target_section_size, uint64 reloc_offset,
  306. int64 reloc_addend, uint32 reloc_type, void *symbol_addr,
  307. int32 symbol_index, char *error_buf, uint32 error_buf_size)
  308. {
  309. switch (reloc_type) {
  310. case R_ARM_THM_CALL:
  311. case R_ARM_THM_JMP24:
  312. {
  313. int32 RESULT_MASK = 0x01FFFFFE;
  314. int32 result, result_masked;
  315. int16 *reloc_addr;
  316. int32 initial_addend_0, initial_addend_1, initial_addend;
  317. bool sign;
  318. CHECK_RELOC_OFFSET(sizeof(int32));
  319. reloc_addr = (int16 *)(target_section_addr + reloc_offset);
  320. initial_addend_0 = (*reloc_addr) & 0x7FF;
  321. initial_addend_1 = (*(reloc_addr + 1)) & 0x7FF;
  322. sign = (initial_addend_0 & 0x400) ? true : false;
  323. initial_addend = (initial_addend_0 << 12) | (initial_addend_1 << 1)
  324. | (sign ? 0xFF800000 : 0);
  325. if (symbol_index < 0) {
  326. /* Symbol address itself is an AOT function.
  327. * Apply relocation with the symbol directly.
  328. * Suppose the symbol address is in +-4MB relative
  329. * to the relocation address.
  330. */
  331. /* operation: ((S + A) | T) - P where S is symbol address
  332. and T is 1 */
  333. result =
  334. (int32)(((intptr_t)((uintptr_t)symbol_addr
  335. + (intptr_t)reloc_addend)
  336. | 1)
  337. - (intptr_t)(target_section_addr + reloc_offset));
  338. }
  339. else {
  340. if (reloc_addend > 0) {
  341. set_error_buf(
  342. error_buf, error_buf_size,
  343. "AOT module load failed: relocate to plt table "
  344. "with reloc addend larger than 0 is unsupported.");
  345. return false;
  346. }
  347. /* Symbol address is not an AOT function,
  348. * but a function of runtime or native. Its address is
  349. * beyond of the +-4MB space. Apply relocation with
  350. * the PLT which branch to the target symbol address.
  351. */
  352. /* operation: ((S + A) | T) - P where S is PLT address
  353. and T is 1 */
  354. uint8 *plt = (uint8 *)module->code + module->code_size
  355. - get_plt_table_size()
  356. + get_plt_item_size() * symbol_index + 1;
  357. result =
  358. (int32)(((intptr_t)plt | 1)
  359. - (intptr_t)(target_section_addr + reloc_offset));
  360. }
  361. result += initial_addend;
  362. /* Check overflow: +-4MB */
  363. if (result > (4 * BH_MB) || result < (-4 * BH_MB)) {
  364. set_error_buf(error_buf, error_buf_size,
  365. "AOT module load failed: "
  366. "target address out of range.");
  367. return false;
  368. }
  369. result_masked = (int32)result & RESULT_MASK;
  370. initial_addend_0 = (result_masked >> 12) & 0x7FF;
  371. initial_addend_1 = (result_masked >> 1) & 0x7FF;
  372. *reloc_addr = (*reloc_addr & ~0x7FF) | initial_addend_0;
  373. *(reloc_addr + 1) = (*(reloc_addr + 1) & ~0x7FF) | initial_addend_1;
  374. break;
  375. }
  376. case R_ARM_ABS32:
  377. {
  378. intptr_t initial_addend;
  379. /* (S + A) | T where T is 0 */
  380. CHECK_RELOC_OFFSET(sizeof(void *));
  381. initial_addend =
  382. *(intptr_t *)(target_section_addr + (uint32)reloc_offset);
  383. *(uintptr_t *)(target_section_addr + reloc_offset) =
  384. (uintptr_t)symbol_addr + initial_addend
  385. + (intptr_t)reloc_addend;
  386. break;
  387. }
  388. case R_ARM_THM_MOVW_ABS_NC:
  389. case R_ARM_THM_MOVT_ABS:
  390. case R_ARM_THM_MOVW_PREL_NC:
  391. case R_ARM_THM_MOVT_PREL:
  392. {
  393. uint16 upper = *(uint16 *)(target_section_addr + reloc_offset);
  394. uint16 lower = *(uint16 *)(target_section_addr + reloc_offset + 2);
  395. int32 offset;
  396. /*
  397. * MOVT/MOVW instructions encoding in Thumb-2:
  398. *
  399. * i = upper[10]
  400. * imm4 = upper[3:0]
  401. * imm3 = lower[14:12]
  402. * imm8 = lower[7:0]
  403. *
  404. * imm16 = imm4:i:imm3:imm8
  405. */
  406. offset = ((upper & 0x000f) << 12) | ((upper & 0x0400) << 1)
  407. | ((lower & 0x7000) >> 4) | (lower & 0x00ff);
  408. offset = (offset ^ 0x8000) - 0x8000;
  409. offset += (symbol_addr + reloc_addend);
  410. if (reloc_type == R_ARM_THM_MOVT_PREL
  411. || reloc_type == R_ARM_THM_MOVW_PREL_NC)
  412. offset -= (int32)(target_section_addr + reloc_offset);
  413. if (reloc_type == R_ARM_THM_MOVT_ABS
  414. || reloc_type == R_ARM_THM_MOVT_PREL)
  415. offset >>= 16;
  416. upper = (uint16)((upper & 0xfbf0) | ((offset & 0xf000) >> 12)
  417. | ((offset & 0x0800) >> 1));
  418. lower = (uint16)((lower & 0x8f00) | ((offset & 0x0700) << 4)
  419. | (offset & 0x00ff));
  420. *(uint16 *)(target_section_addr + reloc_offset) = upper;
  421. *(uint16 *)(target_section_addr + reloc_offset + 2) = lower;
  422. break;
  423. }
  424. default:
  425. if (error_buf != NULL)
  426. snprintf(error_buf, error_buf_size,
  427. "Load relocation section failed: "
  428. "invalid relocation type %" PRId32 ".",
  429. reloc_type);
  430. return false;
  431. }
  432. return true;
  433. }