Fix some issues for Arm platform. (#457)

Motivation:
we found some issues during enable the WAMR on arm devices, such as relocation issues, stack alignment issues.

Proposed change:
We optimized the relocation process for arm platform, for relocation jump table, the SP should be aligned to 16 bytes. And we also make "getentropy" worked for other non-supported platform.
This commit is contained in:
sophy228 2020-12-02 10:22:55 +08:00 committed by GitHub
parent 591e4ce536
commit c8b0a1cee1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 166 additions and 18 deletions

View File

@ -1,12 +1,36 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* Copyright (C) 2020 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "aot_reloc.h"
#define R_AARCH64_MOVW_UABS_G0 263
#define R_AARCH64_MOVW_UABS_G0_NC 264
#define R_AARCH64_MOVW_UABS_G1 265
#define R_AARCH64_MOVW_UABS_G1_NC 266
#define R_AARCH64_MOVW_UABS_G2 267
#define R_AARCH64_MOVW_UABS_G2_NC 268
#define R_AARCH64_MOVW_UABS_G3 269
#define R_AARCH64_MOVW_SABS_G0 270
#define R_AARCH64_MOVW_SABS_G1 271
#define R_AARCH64_MOVW_SABS_G2 272
#define R_AARCH64_ADR_PREL_LO19 273
#define R_AARCH64_ADR_PREL_LO21 274
#define R_AARCH64_ADR_PREL_PG_HI21 275
#define R_AARCH64_ADR_PREL_PG_HI21_NC 276
#define R_AARCH64_ADD_ABS_LO12_NC 277
#define R_AARCH64_LDST8_ABS_LO12_NC 278
#define R_AARCH64_LDST16_ABS_LO12_NC 284
#define R_AARCH64_LDST32_ABS_LO12_NC 285
#define R_AARCH64_LDST64_ABS_LO12_NC 286
#define R_AARCH64_LDST128_ABS_LO12_NC 299
#define R_AARCH64_JUMP26 282
#define R_AARCH64_CALL26 283
static SymbolMap target_sym_map[] = {
@ -57,8 +81,8 @@ get_current_target(char *target_buf, uint32 target_buf_size)
static uint32
get_plt_item_size()
{
/* 8*4 bytes instructions and 8 bytes symbol address */
return 40;
/* 6*4 bytes instructions and 8 bytes symbol address */
return 32;
}
void
@ -67,13 +91,11 @@ init_plt_table(uint8 *plt)
uint32 i, num = sizeof(target_sym_map) / sizeof(SymbolMap);
for (i = 0; i < num; i++) {
uint32 *p = (uint32*)plt;
*p++ = 0xd10023ff; /* sub sp, sp, #0x8 */
*p++ = 0xf90003fe; /* str x30, [sp] */
*p++ = 0x100000de; /* adr x30, #24 */
*p++ = 0xf81f0ffe; /* str x30, [sp, #-16]! */
*p++ = 0x100000be; /* adr x30, #20 ;symbol addr is PC + 5 instructions below */
*p++ = 0xf94003de; /* ldr x30, [x30] */
*p++ = 0xd63f03c0; /* blr x30 */
*p++ = 0xf94003fe; /* ldr x30, [sp] */
*p++ = 0x910023ff; /* add sp, sp, #0x8 */
*p++ = 0xf84107fe; /* ldr x30, [sp], #16 */
*p++ = 0xd61f03c0; /* br x30 */
/* symbol addr */
*(uint64*)p = (uint64)(uintptr_t)target_sym_map[i].symbol_addr;
@ -173,7 +195,74 @@ apply_relocation(AOTModule *module,
break;
}
case R_AARCH64_MOVW_UABS_G0:
case R_AARCH64_MOVW_UABS_G0_NC:
case R_AARCH64_MOVW_UABS_G1:
case R_AARCH64_MOVW_UABS_G1_NC:
case R_AARCH64_MOVW_UABS_G2:
case R_AARCH64_MOVW_UABS_G2_NC:
case R_AARCH64_MOVW_UABS_G3:
{
void *S = symbol_addr, *P = (void*)(target_section_addr + reloc_offset);
int64 X, A, initial_addend;
int32 insn, imm16;
CHECK_RELOC_OFFSET(sizeof(int32));
insn = *(int32*)P;
imm16 = (insn >> 5) & 0xFFFF;
SIGN_EXTEND_TO_INT64(imm16, 16, initial_addend);
A = initial_addend;
A += (int64)reloc_addend;
/* S + A */
X = (int64)S + A;
/* No need to check overflow for this reloction type */
switch (reloc_type) {
case R_AARCH64_MOVW_UABS_G0:
if (X < 0 || X >= (1LL << 16))
goto overflow_check_fail;
break;
case R_AARCH64_MOVW_UABS_G1:
if (X < 0 || X >= (1LL << 32))
goto overflow_check_fail;
break;
case R_AARCH64_MOVW_UABS_G2:
if (X < 0 || X >= (1LL << 48))
goto overflow_check_fail;
break;
default:
break;
}
/* write the imm16 back to bits[5:20] of instruction */
switch (reloc_type) {
case R_AARCH64_MOVW_UABS_G0:
case R_AARCH64_MOVW_UABS_G0_NC:
*(int32*)P = (insn & 0xFFE0001F) | ((int32)((X & 0xFFFF) << 5));
break;
case R_AARCH64_MOVW_UABS_G1:
case R_AARCH64_MOVW_UABS_G1_NC:
*(int32*)P = (insn & 0xFFE0001F) | ((int32)(((X >> 16) & 0xFFFF) << 5));
break;
case R_AARCH64_MOVW_UABS_G2:
case R_AARCH64_MOVW_UABS_G2_NC:
*(int32*)P = (insn & 0xFFE0001F) | ((int32)(((X >> 32) & 0xFFFF) << 5));
break;
case R_AARCH64_MOVW_UABS_G3:
*(int32*)P = (insn & 0xFFE0001F) | ((int32)(((X >> 48) & 0xFFFF) << 5));
break;
default:
bh_assert(0);
break;
}
break;
}
case R_AARCH64_ADR_PREL_PG_HI21:
case R_AARCH64_ADR_PREL_PG_HI21_NC:
{
void *S = symbol_addr, *P = (void*)(target_section_addr + reloc_offset);
int64 X, A, initial_addend;
@ -194,12 +283,9 @@ apply_relocation(AOTModule *module,
X = Page((int64)S + A) - Page((int64)P);
/* Check overflow: +-4GB */
if (X > ((int64)4 * BH_GB) || X < ((int64)-4 * BH_GB)) {
set_error_buf(error_buf, error_buf_size,
"AOT module load failed: "
"target address out of range.");
return false;
}
if (reloc_type == R_AARCH64_ADR_PREL_PG_HI21
&& (X > ((int64)4 * BH_GB) || X < ((int64)-4 * BH_GB)))
goto overflow_check_fail;
/* write the imm21 back to instruction */
immhi19 = (int32)(((X >> 12) >> 2) & 0x7FFFF);
@ -234,6 +320,54 @@ apply_relocation(AOTModule *module,
break;
}
case R_AARCH64_LDST8_ABS_LO12_NC:
case R_AARCH64_LDST16_ABS_LO12_NC:
case R_AARCH64_LDST32_ABS_LO12_NC:
case R_AARCH64_LDST64_ABS_LO12_NC:
case R_AARCH64_LDST128_ABS_LO12_NC:
{
void *S = symbol_addr, *P = (void*)(target_section_addr + reloc_offset);
int64 X, A, initial_addend;
int32 insn, imm12;
CHECK_RELOC_OFFSET(sizeof(int32));
insn = *(int32*)P;
imm12 = (insn >> 10) & 0xFFF;
SIGN_EXTEND_TO_INT64(imm12, 12, initial_addend);
A = initial_addend;
A += (int64)reloc_addend;
/* S + A */
X = (int64)S + A;
/* No need to check overflow for this reloction type */
/* write the imm12 back to instruction */
switch (reloc_type) {
case R_AARCH64_LDST8_ABS_LO12_NC:
*(int32*)P = (insn & 0xFFC003FF) | ((int32)((X & 0xFFF) << 10));
break;
case R_AARCH64_LDST16_ABS_LO12_NC:
*(int32*)P = (insn & 0xFFC003FF) | ((int32)(((X & 0xFFF) >> 1) << 10));
break;
case R_AARCH64_LDST32_ABS_LO12_NC:
*(int32*)P = (insn & 0xFFC003FF) | ((int32)(((X & 0xFFF) >> 2) << 10));
break;
case R_AARCH64_LDST64_ABS_LO12_NC:
*(int32*)P = (insn & 0xFFC003FF) | ((int32)(((X & 0xFFF) >> 3) << 10));
break;
case R_AARCH64_LDST128_ABS_LO12_NC:
*(int32*)P = (insn & 0xFFC003FF) | ((int32)(((X & 0xFFF) >> 4) << 10));
break;
default:
bh_assert(0);
break;
}
break;
}
default:
if (error_buf != NULL)
snprintf(error_buf, error_buf_size,
@ -244,5 +378,11 @@ apply_relocation(AOTModule *module,
}
return true;
overflow_check_fail:
set_error_buf(error_buf, error_buf_size,
"AOT module load failed: "
"target address out of range.");
return false;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* Copyright (C) 2020 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
@ -744,6 +744,7 @@ static bool
is_target_arm(AOTCompContext *comp_ctx)
{
return !strncmp(comp_ctx->target_arch, "arm", 3) ||
!strncmp(comp_ctx->target_arch, "aarch64", 7) ||
!strncmp(comp_ctx->target_arch, "thumb", 5);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* Copyright (C) 2020 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
@ -7,6 +7,9 @@
#include "bh_log.h"
#include "wasm_export.h"
#include "../interpreter/wasm.h"
#ifndef _DEFAULT_SOURCE
#include "sys/syscall.h"
#endif
#define get_module_inst(exec_env) \
wasm_runtime_get_module_inst(exec_env)
@ -264,7 +267,11 @@ getentropy_wrapper(wasm_exec_env_t exec_env, void *buffer, uint32 length)
{
if (buffer == NULL)
return -1;
#ifdef _DEFAULT_SOURCE
return getentropy(buffer, length);
#else
return syscall(SYS_getrandom, buffer, length, 0);
#endif
}
static int

View File

@ -3,7 +3,7 @@
cmake_minimum_required (VERSION 2.8)
project (iwasm C ASM)
project (iwasm C ASM CXX)
enable_language(ASM_MASM)
# set (CMAKE_VERBOSE_MAKEFILE 1)

View File

@ -6,7 +6,7 @@ cmake_minimum_required (VERSION 2.8)
if (NOT WAMR_BUILD_PLATFORM STREQUAL "windows")
project (aot-compiler)
else()
project (aot-compiler C ASM)
project (aot-compiler C ASM CXX)
enable_language (ASM_MASM)
endif()