11/*
2- * Copyright (C) 2019 Intel Corporation. All rights reserved.
2+ * Copyright (C) 2020 Intel Corporation. All rights reserved.
33 * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
44 */
55
66#include "aot_reloc.h"
77
8+ #define R_AARCH64_MOVW_UABS_G0 263
9+ #define R_AARCH64_MOVW_UABS_G0_NC 264
10+ #define R_AARCH64_MOVW_UABS_G1 265
11+ #define R_AARCH64_MOVW_UABS_G1_NC 266
12+ #define R_AARCH64_MOVW_UABS_G2 267
13+ #define R_AARCH64_MOVW_UABS_G2_NC 268
14+ #define R_AARCH64_MOVW_UABS_G3 269
15+
16+ #define R_AARCH64_MOVW_SABS_G0 270
17+ #define R_AARCH64_MOVW_SABS_G1 271
18+ #define R_AARCH64_MOVW_SABS_G2 272
19+
20+ #define R_AARCH64_ADR_PREL_LO19 273
21+ #define R_AARCH64_ADR_PREL_LO21 274
822#define R_AARCH64_ADR_PREL_PG_HI21 275
23+ #define R_AARCH64_ADR_PREL_PG_HI21_NC 276
24+
925#define R_AARCH64_ADD_ABS_LO12_NC 277
26+
27+ #define R_AARCH64_LDST8_ABS_LO12_NC 278
28+ #define R_AARCH64_LDST16_ABS_LO12_NC 284
29+ #define R_AARCH64_LDST32_ABS_LO12_NC 285
30+ #define R_AARCH64_LDST64_ABS_LO12_NC 286
31+ #define R_AARCH64_LDST128_ABS_LO12_NC 299
32+
33+ #define R_AARCH64_JUMP26 282
1034#define R_AARCH64_CALL26 283
1135
1236static SymbolMap target_sym_map [] = {
@@ -57,8 +81,8 @@ get_current_target(char *target_buf, uint32 target_buf_size)
5781static uint32
5882get_plt_item_size ()
5983{
60- /* 8 *4 bytes instructions and 8 bytes symbol address */
61- return 40 ;
84+ /* 6 *4 bytes instructions and 8 bytes symbol address */
85+ return 32 ;
6286}
6387
6488void
@@ -67,13 +91,11 @@ init_plt_table(uint8 *plt)
6791 uint32 i , num = sizeof (target_sym_map ) / sizeof (SymbolMap );
6892 for (i = 0 ; i < num ; i ++ ) {
6993 uint32 * p = (uint32 * )plt ;
70- * p ++ = 0xd10023ff ; /* sub sp, sp, #0x8 */
71- * p ++ = 0xf90003fe ; /* str x30, [sp] */
72- * p ++ = 0x100000de ; /* adr x30, #24 */
94+ * p ++ = 0xf81f0ffe ; /* str x30, [sp, #-16]! */
95+ * p ++ = 0x100000be ; /* adr x30, #20 ;symbol addr is PC + 5 instructions below */
7396 * p ++ = 0xf94003de ; /* ldr x30, [x30] */
7497 * p ++ = 0xd63f03c0 ; /* blr x30 */
75- * p ++ = 0xf94003fe ; /* ldr x30, [sp] */
76- * p ++ = 0x910023ff ; /* add sp, sp, #0x8 */
98+ * p ++ = 0xf84107fe ; /* ldr x30, [sp], #16 */
7799 * p ++ = 0xd61f03c0 ; /* br x30 */
78100 /* symbol addr */
79101 * (uint64 * )p = (uint64 )(uintptr_t )target_sym_map [i ].symbol_addr ;
@@ -173,7 +195,74 @@ apply_relocation(AOTModule *module,
173195 break ;
174196 }
175197
198+ case R_AARCH64_MOVW_UABS_G0 :
199+ case R_AARCH64_MOVW_UABS_G0_NC :
200+ case R_AARCH64_MOVW_UABS_G1 :
201+ case R_AARCH64_MOVW_UABS_G1_NC :
202+ case R_AARCH64_MOVW_UABS_G2 :
203+ case R_AARCH64_MOVW_UABS_G2_NC :
204+ case R_AARCH64_MOVW_UABS_G3 :
205+ {
206+ void * S = symbol_addr , * P = (void * )(target_section_addr + reloc_offset );
207+ int64 X , A , initial_addend ;
208+ int32 insn , imm16 ;
209+
210+ CHECK_RELOC_OFFSET (sizeof (int32 ));
211+
212+ insn = * (int32 * )P ;
213+ imm16 = (insn >> 5 ) & 0xFFFF ;
214+
215+ SIGN_EXTEND_TO_INT64 (imm16 , 16 , initial_addend );
216+ A = initial_addend ;
217+ A += (int64 )reloc_addend ;
218+
219+ /* S + A */
220+ X = (int64 )S + A ;
221+
222+ /* No need to check overflow for this reloction type */
223+ switch (reloc_type ) {
224+ case R_AARCH64_MOVW_UABS_G0 :
225+ if (X < 0 || X >= (1LL << 16 ))
226+ goto overflow_check_fail ;
227+ break ;
228+ case R_AARCH64_MOVW_UABS_G1 :
229+ if (X < 0 || X >= (1LL << 32 ))
230+ goto overflow_check_fail ;
231+ break ;
232+ case R_AARCH64_MOVW_UABS_G2 :
233+ if (X < 0 || X >= (1LL << 48 ))
234+ goto overflow_check_fail ;
235+ break ;
236+ default :
237+ break ;
238+ }
239+
240+ /* write the imm16 back to bits[5:20] of instruction */
241+ switch (reloc_type ) {
242+ case R_AARCH64_MOVW_UABS_G0 :
243+ case R_AARCH64_MOVW_UABS_G0_NC :
244+ * (int32 * )P = (insn & 0xFFE0001F ) | ((int32 )((X & 0xFFFF ) << 5 ));
245+ break ;
246+ case R_AARCH64_MOVW_UABS_G1 :
247+ case R_AARCH64_MOVW_UABS_G1_NC :
248+ * (int32 * )P = (insn & 0xFFE0001F ) | ((int32 )(((X >> 16 ) & 0xFFFF ) << 5 ));
249+ break ;
250+ case R_AARCH64_MOVW_UABS_G2 :
251+ case R_AARCH64_MOVW_UABS_G2_NC :
252+ * (int32 * )P = (insn & 0xFFE0001F ) | ((int32 )(((X >> 32 ) & 0xFFFF ) << 5 ));
253+ break ;
254+ case R_AARCH64_MOVW_UABS_G3 :
255+ * (int32 * )P = (insn & 0xFFE0001F ) | ((int32 )(((X >> 48 ) & 0xFFFF ) << 5 ));
256+ break ;
257+ default :
258+ bh_assert (0 );
259+ break ;
260+ }
261+ break ;
262+ }
263+
176264 case R_AARCH64_ADR_PREL_PG_HI21 :
265+ case R_AARCH64_ADR_PREL_PG_HI21_NC :
177266 {
178267 void * S = symbol_addr , * P = (void * )(target_section_addr + reloc_offset );
179268 int64 X , A , initial_addend ;
@@ -194,12 +283,9 @@ apply_relocation(AOTModule *module,
194283 X = Page ((int64 )S + A ) - Page ((int64 )P );
195284
196285 /* Check overflow: +-4GB */
197- if (X > ((int64 )4 * BH_GB ) || X < ((int64 )-4 * BH_GB )) {
198- set_error_buf (error_buf , error_buf_size ,
199- "AOT module load failed: "
200- "target address out of range." );
201- return false;
202- }
286+ if (reloc_type == R_AARCH64_ADR_PREL_PG_HI21
287+ && (X > ((int64 )4 * BH_GB ) || X < ((int64 )-4 * BH_GB )))
288+ goto overflow_check_fail ;
203289
204290 /* write the imm21 back to instruction */
205291 immhi19 = (int32 )(((X >> 12 ) >> 2 ) & 0x7FFFF );
@@ -234,6 +320,54 @@ apply_relocation(AOTModule *module,
234320 break ;
235321 }
236322
323+ case R_AARCH64_LDST8_ABS_LO12_NC :
324+ case R_AARCH64_LDST16_ABS_LO12_NC :
325+ case R_AARCH64_LDST32_ABS_LO12_NC :
326+ case R_AARCH64_LDST64_ABS_LO12_NC :
327+ case R_AARCH64_LDST128_ABS_LO12_NC :
328+ {
329+ void * S = symbol_addr , * P = (void * )(target_section_addr + reloc_offset );
330+ int64 X , A , initial_addend ;
331+ int32 insn , imm12 ;
332+
333+ CHECK_RELOC_OFFSET (sizeof (int32 ));
334+
335+ insn = * (int32 * )P ;
336+ imm12 = (insn >> 10 ) & 0xFFF ;
337+
338+ SIGN_EXTEND_TO_INT64 (imm12 , 12 , initial_addend );
339+ A = initial_addend ;
340+ A += (int64 )reloc_addend ;
341+
342+ /* S + A */
343+ X = (int64 )S + A ;
344+
345+ /* No need to check overflow for this reloction type */
346+
347+ /* write the imm12 back to instruction */
348+ switch (reloc_type ) {
349+ case R_AARCH64_LDST8_ABS_LO12_NC :
350+ * (int32 * )P = (insn & 0xFFC003FF ) | ((int32 )((X & 0xFFF ) << 10 ));
351+ break ;
352+ case R_AARCH64_LDST16_ABS_LO12_NC :
353+ * (int32 * )P = (insn & 0xFFC003FF ) | ((int32 )(((X & 0xFFF ) >> 1 ) << 10 ));
354+ break ;
355+ case R_AARCH64_LDST32_ABS_LO12_NC :
356+ * (int32 * )P = (insn & 0xFFC003FF ) | ((int32 )(((X & 0xFFF ) >> 2 ) << 10 ));
357+ break ;
358+ case R_AARCH64_LDST64_ABS_LO12_NC :
359+ * (int32 * )P = (insn & 0xFFC003FF ) | ((int32 )(((X & 0xFFF ) >> 3 ) << 10 ));
360+ break ;
361+ case R_AARCH64_LDST128_ABS_LO12_NC :
362+ * (int32 * )P = (insn & 0xFFC003FF ) | ((int32 )(((X & 0xFFF ) >> 4 ) << 10 ));
363+ break ;
364+ default :
365+ bh_assert (0 );
366+ break ;
367+ }
368+ break ;
369+ }
370+
237371 default :
238372 if (error_buf != NULL )
239373 snprintf (error_buf , error_buf_size ,
@@ -244,5 +378,11 @@ apply_relocation(AOTModule *module,
244378 }
245379
246380 return true;
381+
382+ overflow_check_fail :
383+ set_error_buf (error_buf , error_buf_size ,
384+ "AOT module load failed: "
385+ "target address out of range." );
386+ return false;
247387}
248388
0 commit comments