diff options
Diffstat (limited to 'fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/arch/aot_reloc_xtensa.c')
-rw-r--r-- | fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/arch/aot_reloc_xtensa.c | 302 |
1 files changed, 302 insertions, 0 deletions
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/arch/aot_reloc_xtensa.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/arch/aot_reloc_xtensa.c new file mode 100644 index 000000000..3327c396f --- /dev/null +++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/arch/aot_reloc_xtensa.c @@ -0,0 +1,302 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "aot_reloc.h" + +#define R_XTENSA_32 1 /* Direct 32 bit */ +#define R_XTENSA_SLOT0_OP 20 /* PC relative */ + +/* clang-format off */ +/* for soft-float */ +void __floatsidf(); +void __divdf3(); +void __ltdf2(); + +/* for mul32 */ +void __mulsi3(); +void __muldi3(); + +void __modsi3(); + +void __divdi3(); + +void __udivdi3(); +void __unorddf2(); +void __adddf3(); +void __eqdf2(); +void __muldf3(); +void __gedf2(); +void __ledf2(); +void __fixunsdfsi(); +void __floatunsidf(); +void __subdf3(); +void __nedf2(); +void __fixdfsi(); +void __moddi3(); +void __extendsfdf2(); +void __truncdfsf2(); +void __gtdf2(); +void __umoddi3(); +void __floatdidf(); +void __divsf3(); +void __fixdfdi(); +void __floatundidf(); + + +static SymbolMap target_sym_map[] = { + REG_COMMON_SYMBOLS + + /* API's for soft-float */ + /* TODO: only register these symbols when Floating-Point Coprocessor + * Option is not enabled */ + REG_SYM(__floatsidf), + REG_SYM(__divdf3), + REG_SYM(__ltdf2), + + /* API's for 32-bit integer multiply */ + /* TODO: only register these symbols when 32-bit Integer Multiply Option + * is not enabled */ + REG_SYM(__mulsi3), + REG_SYM(__muldi3), + + REG_SYM(__modsi3), + REG_SYM(__divdi3), + + REG_SYM(__udivdi3), + REG_SYM(__unorddf2), + REG_SYM(__adddf3), + REG_SYM(__eqdf2), + REG_SYM(__muldf3), + REG_SYM(__gedf2), + REG_SYM(__ledf2), + REG_SYM(__fixunsdfsi), + REG_SYM(__floatunsidf), + REG_SYM(__subdf3), + REG_SYM(__nedf2), + REG_SYM(__fixdfsi), + REG_SYM(__moddi3), + REG_SYM(__extendsfdf2), + REG_SYM(__truncdfsf2), + REG_SYM(__gtdf2), + REG_SYM(__umoddi3), + REG_SYM(__floatdidf), + REG_SYM(__divsf3), + REG_SYM(__fixdfdi), + REG_SYM(__floatundidf), +}; +/* clang-format on */ + +static void +set_error_buf(char *error_buf, uint32 error_buf_size, const char *string) +{ + if (error_buf != NULL) + snprintf(error_buf, error_buf_size, "%s", string); +} + +SymbolMap * +get_target_symbol_map(uint32 *sym_num) +{ + *sym_num = sizeof(target_sym_map) / sizeof(SymbolMap); + return target_sym_map; +} + +void +get_current_target(char *target_buf, uint32 target_buf_size) +{ + snprintf(target_buf, target_buf_size, "xtensa"); +} + +static uint32 +get_plt_item_size() +{ + return 0; +} + +void +init_plt_table(uint8 *plt) +{ + (void)plt; +} + +uint32 +get_plt_table_size() +{ + return get_plt_item_size() * (sizeof(target_sym_map) / sizeof(SymbolMap)); +} + +static bool +check_reloc_offset(uint32 target_section_size, uint64 reloc_offset, + uint32 reloc_data_size, char *error_buf, + uint32 error_buf_size) +{ + if (!(reloc_offset < (uint64)target_section_size + && reloc_offset + reloc_data_size <= (uint64)target_section_size)) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: invalid relocation offset."); + return false; + } + return true; +} + +/* + * CPU like esp32 can read and write data through the instruction bus, but only + * in a word aligned manner; non-word-aligned access will cause a CPU exception. + * This function uses a world aligned manner to write 16bit value to instruction + * addreess. + */ +static void +put_imm16_to_addr(int16 imm16, int16 *addr) +{ + int8 bytes[8]; + int32 *addr_aligned1, *addr_aligned2; + + addr_aligned1 = (int32 *)((intptr_t)addr & ~3); + + if ((intptr_t)addr % 4 != 3) { + *(int32 *)bytes = *addr_aligned1; + *(int16 *)(bytes + ((intptr_t)addr % 4)) = imm16; + *addr_aligned1 = *(int32 *)bytes; + } + else { + addr_aligned2 = (int32 *)(((intptr_t)addr + 3) & ~3); + *(int32 *)bytes = *addr_aligned1; + *(int32 *)(bytes + 4) = *addr_aligned2; + *(int16 *)(bytes + 3) = imm16; + memcpy(addr_aligned1, bytes, 8); + } +} + +static union { + int a; + char b; +} __ue = { .a = 1 }; + +#define is_little_endian() (__ue.b == 1) + +#if !defined(__packed) +/* + * Note: This version check is a bit relaxed. + * The __packed__ attribute has been there since gcc 2 era. + */ +#if __GNUC__ >= 3 +#define __packed __attribute__((__packed__)) +#endif +#endif + +typedef union { + struct l32r_le { + int8 other; + int16 imm16; + } __packed l; + + struct l32r_be { + int16 imm16; + int8 other; + } __packed b; +} l32r_insn_t; + +bool +apply_relocation(AOTModule *module, uint8 *target_section_addr, + uint32 target_section_size, uint64 reloc_offset, + int64 reloc_addend, uint32 reloc_type, void *symbol_addr, + int32 symbol_index, char *error_buf, uint32 error_buf_size) +{ + switch (reloc_type) { + case R_XTENSA_32: + { + uint8 *insn_addr = target_section_addr + reloc_offset; + int32 initial_addend; + /* (S + A) */ + if ((intptr_t)insn_addr & 3) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: " + "instruction address unaligned."); + return false; + } + CHECK_RELOC_OFFSET(4); + initial_addend = *(int32 *)insn_addr; + *(uintptr_t *)insn_addr = (uintptr_t)symbol_addr + initial_addend + + (intptr_t)reloc_addend; + break; + } + + case R_XTENSA_SLOT0_OP: + { + uint8 *insn_addr = target_section_addr + reloc_offset; + /* Currently only l32r instruction generates R_XTENSA_SLOT0_OP + * relocation */ + l32r_insn_t *l32r_insn = (l32r_insn_t *)insn_addr; + uint8 *reloc_addr; + int32 relative_offset /*, initial_addend */; + int16 imm16; + + CHECK_RELOC_OFFSET(3); /* size of l32r instruction */ + + /* + imm16 = is_little_endian() ? + l32r_insn->l.imm16 : l32r_insn->b.imm16; + initial_addend = (int32)imm16 << 2; + */ + + reloc_addr = + (uint8 *)((uintptr_t)symbol_addr + (intptr_t)reloc_addend); + + if ((intptr_t)reloc_addr & 3) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: " + "relocation address unaligned."); + return false; + } + + relative_offset = + (int32)((intptr_t)reloc_addr + - (((intptr_t)insn_addr + 3) & ~(intptr_t)3)); + /* relative_offset += initial_addend; */ + + /* check relative offset boundary */ + if (relative_offset < -256 * BH_KB || relative_offset > -4) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: " + "target address out of range.\n" + "Try using `wamrc --size-level=0` to generate " + ".literal island."); + return false; + } + + imm16 = (int16)(relative_offset >> 2); + + /* write back the imm16 to the l32r instruction */ + + /* GCC >= 9 complains if we have a pointer that could be + * unaligned. This can happen because the struct is packed. + * These pragma are to suppress the warnings because the + * function put_imm16_to_addr already handles unaligned + * pointers correctly. */ +#if __GNUC__ >= 9 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Waddress-of-packed-member" +#endif + if (is_little_endian()) + put_imm16_to_addr(imm16, &l32r_insn->l.imm16); + else + put_imm16_to_addr(imm16, &l32r_insn->b.imm16); +#if __GNUC__ >= 9 +#pragma GCC diagnostic pop +#endif + + break; + } + + default: + if (error_buf != NULL) + snprintf(error_buf, error_buf_size, + "Load relocation section failed: " + "invalid relocation type %d.", + (int)reloc_type); + return false; + } + + return true; +} |