Add bound checking to arm, arm64 and riscv64

Checked on:
- i386/x86_64 (linux/windows)
- arm/arm64 (rapberry pi)
- riscv64 (simulator)
Not tested for arm softfloat because raspberry pi does not support it.

Modifications:

Makefile:
  add arm-asm.c to arm64_FILES
  add riscv64-asm.c (new file) to riscv64_FILES

lib/Makefile:
  add fetch_and_add_arm.o(new file) to ARM_O
  add fetch_and_add_arm64.o(new file) to ARM64_O
  add fetch_and_add_riscv64.o(new file) to RISCV64_O
  add $(BCHECK_O) to OBJ-arm/OBJ-arm64/OBJ-riscv64

tcc.h:
  Enable CONFIG_TCC_BCHECK for arm32/arm64/riscv64
  Add arm-asm.c, riscv64-asm.c

tcctok.h:
  for arm use memmove4 instead of memcpy4
  for arm use memmove8 instead of memcpy8

tccgen.c:
  put_extern_sym2: for arm check memcpy/memmove/memset/memmove4/memmove8
                   only use alloca for i386/x86_64
  for arm use memmove4 instead of memcpy4
  for arm use memmove8 instead of memcpy8
  fix builtin_frame_address/builtin_return_address for arm/riscv64

tccrun.c:
  Add riscv64 support
  fix rt_getcontext/rt_get_caller_pc for arm

tccelf.c:
  tcc_load_dll: Print filename for bad architecture

libtcc.c:
  add arm-asm.c/riscv64-asm.c

tcc-doc.texi:
  Add arm, arm64, riscv64 support for bound checking

lib/bcheck.c:
  add __bound___aeabi_memcpy/__bound___aeabi_memmove
      __bound___aeabi_memmove4/__bound___aeabi_memmove8
      __bound___aeabi_memset for arm
  call fetch_and_add_arm/fetch_and_add_arm64/fetch_and_add_riscv64
  __bound_init: Fix type for start/end/ad
  __bound_malloc/__bound_memalign/__bound_realloc/__bound_calloc: Use size + 1

arm-gen.c:
  add bound checking code like i386/x86_64
  assign_regs: only malloc if nb_args != 0
  gen_opi/gen_opf: Fix reload problems

arm-link.c:
  relocate_plt: Fix address calculating

arm64-gen.c:
  add bound checking code like i386/x86_64
  load/store: remove VT_BOUNDED from sv->r
  arm64_hfa_aux/arm64_hfa_aux: Fix array code
  gfunc_prolog: only malloc if n != 0

arm64-link.c:
  code_reloc/gotplt_entry_type/relocate: add R_AARCH64_LDST64_ABS_LO12_NC
  relocate: Use addXXle instead of writeXXle

riscv64-gen.c:
  add bound checking code like i386/x86_64
  add NB_ASM_REGS/CONFIG_TCC_ASM

riscv64-link.c:
  relocate: Use addXXle instead of writeXXle

i386-gen.c/x86_64-gen.c
  gen_bounds_epilog: Fix code (unrelated)

tests/Makefile:
  add $(BTESTS) for arm/arm64/riscv64

tests/tests2/Makefile:
  Use 85 only on i386/x86_64 because of asm code
  Use 113 only on i386/x86_64 because of DLL code
  Add 112/114/115/116 for arm/arm64/riscv64
  Fix FILTER (failed on riscv64)

tests/boundtest.c:
  Only use alloca for i386/x86_64
This commit is contained in:
herman ten brugge
2020-06-16 07:39:48 +02:00
parent 9eef33993a
commit 0b8ee7364a
25 changed files with 865 additions and 77 deletions

View File

@@ -43,9 +43,9 @@ endif
I386_O = libtcc1.o alloca86.o alloca86-bt.o $(BT_O)
X86_64_O = libtcc1.o alloca86_64.o alloca86_64-bt.o $(BT_O)
ARM_O = libtcc1.o armeabi.o alloca-arm.o armflush.o $(BT_O)
ARM64_O = lib-arm64.o $(BT_O)
RISCV64_O = lib-arm64.o $(BT_O)
ARM_O = libtcc1.o armeabi.o alloca-arm.o armflush.o fetch_and_add_arm.o $(BT_O)
ARM64_O = lib-arm64.o fetch_and_add_arm64.o $(BT_O)
RISCV64_O = lib-arm64.o fetch_and_add_riscv64.o $(BT_O)
WIN_O = crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o
OBJ-i386 = $(I386_O) $(BCHECK_O) $(DSO_O)
@@ -53,15 +53,15 @@ OBJ-x86_64 = $(X86_64_O) va_list.o $(BCHECK_O) $(DSO_O)
OBJ-x86_64-osx = $(X86_64_O) va_list.o
OBJ-i386-win32 = $(I386_O) chkstk.o $(B_O) $(WIN_O)
OBJ-x86_64-win32 = $(X86_64_O) chkstk.o $(B_O) $(WIN_O)
OBJ-arm64 = $(ARM64_O) $(DSO_O)
OBJ-arm = $(ARM_O) $(DSO_O)
OBJ-arm64 = $(ARM64_O) $(BCHECK_O) $(DSO_O)
OBJ-arm = $(ARM_O) $(BCHECK_O) $(DSO_O)
OBJ-arm-fpa = $(ARM_O) $(DSO_O)
OBJ-arm-fpa-ld = $(ARM_O) $(DSO_O)
OBJ-arm-vfp = $(ARM_O) $(DSO_O)
OBJ-arm-eabi = $(ARM_O) $(DSO_O)
OBJ-arm-eabihf = $(ARM_O) $(DSO_O)
OBJ-arm-wince = $(ARM_O) $(WIN_O)
OBJ-riscv64 = $(RISCV64_O) $(DSO_O)
OBJ-riscv64 = $(RISCV64_O) $(BCHECK_O) $(DSO_O)
OBJ-extra = $(filter $(B_O),$(OBJ-$T))
OBJ-libtcc1 = $(addprefix $(X),$(filter-out $(OBJ-extra),$(OBJ-$T)))

View File

@@ -163,7 +163,7 @@ typedef struct alloca_list_struct {
#if defined(_WIN32)
#define BOUND_TID_TYPE DWORD
#define BOUND_GET_TID GetCurrentThreadId()
#elif defined(__i386__) || defined(__x86_64__)
#elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) || defined(__riscv)
#define BOUND_TID_TYPE pid_t
#define BOUND_GET_TID syscall (SYS_gettid)
#else
@@ -223,6 +223,19 @@ DLL_EXPORT char *__bound_strcat(char *dest, const char *src);
DLL_EXPORT char *__bound_strchr(const char *string, int ch);
DLL_EXPORT char *__bound_strdup(const char *s);
#if defined(__arm__)
DLL_EXPORT void *__bound___aeabi_memcpy(void *dst, const void *src, size_t size);
DLL_EXPORT void *__bound___aeabi_memmove(void *dst, const void *src, size_t size);
DLL_EXPORT void *__bound___aeabi_memmove4(void *dst, const void *src, size_t size);
DLL_EXPORT void *__bound___aeabi_memmove8(void *dst, const void *src, size_t size);
DLL_EXPORT void *__bound___aeabi_memset(void *dst, int c, size_t size);
DLL_EXPORT void *__aeabi_memcpy(void *dst, const void *src, size_t size);
DLL_EXPORT void *__aeabi_memmove(void *dst, const void *src, size_t size);
DLL_EXPORT void *__aeabi_memmove4(void *dst, const void *src, size_t size);
DLL_EXPORT void *__aeabi_memmove8(void *dst, const void *src, size_t size);
DLL_EXPORT void *__aeabi_memset(void *dst, int c, size_t size);
#endif
#if MALLOC_REDIR
#define BOUND_MALLOC(a) malloc_redir(a)
#define BOUND_MEMALIGN(a,b) memalign_redir(a,b)
@@ -320,6 +333,15 @@ static void fetch_and_add(signed char* variable, signed char value)
: // No input-only
: "memory"
);
#elif defined __arm__
extern fetch_and_add_arm(signed char* variable, signed char value);
fetch_and_add_arm(variable, value);
#elif defined __aarch64__
extern fetch_and_add_arm64(signed char* variable, signed char value);
fetch_and_add_arm64(variable, value);
#elif defined __riscv
extern fetch_and_add_riscv64(signed char* variable, signed char value);
fetch_and_add_riscv64(variable, value);
#else
*variable += value;
#endif
@@ -814,10 +836,10 @@ void __bound_init(size_t *p)
{
FILE *fp;
unsigned char found;
unsigned long long start;
unsigned long long end;
unsigned long long ad =
(unsigned long long) __builtin_return_address(0);
unsigned long start;
unsigned long end;
unsigned long ad =
(unsigned long) __builtin_return_address(0);
char line[1000];
/* Display exec name. Usefull when a lot of code is compiled with tcc */
@@ -835,7 +857,7 @@ void __bound_init(size_t *p)
fp = fopen ("/proc/self/maps", "r");
if (fp) {
while (fgets (line, sizeof(line), fp)) {
if (sscanf (line, "%Lx-%Lx", &start, &end) == 2 &&
if (sscanf (line, "%lx-%lx", &start, &end) == 2 &&
ad >= start && ad < end) {
found = 1;
break;
@@ -1099,7 +1121,7 @@ void *__bound_malloc(size_t size, const void *caller)
INCR_COUNT(bound_malloc_count);
if (ptr) {
tree = splay_insert ((size_t) ptr, size, tree);
tree = splay_insert ((size_t) ptr, size ? size : size + 1, tree);
if (tree && tree->start == (size_t) ptr)
tree->type = TCC_TYPE_MALLOC;
}
@@ -1138,7 +1160,7 @@ void *__bound_memalign(size_t size, size_t align, const void *caller)
INCR_COUNT(bound_memalign_count);
if (ptr) {
tree = splay_insert((size_t) ptr, size, tree);
tree = splay_insert((size_t) ptr, size ? size : size + 1, tree);
if (tree && tree->start == (size_t) ptr)
tree->type = TCC_TYPE_MEMALIGN;
}
@@ -1205,7 +1227,7 @@ void *__bound_realloc(void *ptr, size_t size, const void *caller)
return NULL;
}
new_ptr = BOUND_REALLOC (ptr, size);
new_ptr = BOUND_REALLOC (ptr, size + 1);
dprintf(stderr, "%s, %s(): %p, 0x%lx\n",
__FILE__, __FUNCTION__, new_ptr, (unsigned long)size);
@@ -1216,7 +1238,7 @@ void *__bound_realloc(void *ptr, size_t size, const void *caller)
if (ptr)
tree = splay_delete ((size_t) ptr, tree);
if (new_ptr) {
tree = splay_insert ((size_t) new_ptr, size, tree);
tree = splay_insert ((size_t) new_ptr, size ? size : size + 1, tree);
if (tree && tree->start == (size_t) new_ptr)
tree->type = TCC_TYPE_REALLOC;
}
@@ -1259,7 +1281,7 @@ void *__bound_calloc(size_t nmemb, size_t size)
if (no_checking == 0) {
WAIT_SEM ();
INCR_COUNT(bound_calloc_count);
tree = splay_insert ((size_t) ptr, size, tree);
tree = splay_insert ((size_t) ptr, size ? size : size + 1, tree);
if (tree && tree->start == (size_t) ptr)
tree->type = TCC_TYPE_CALLOC;
POST_SEM ();
@@ -1387,6 +1409,59 @@ void *__bound_memset(void *s, int c, size_t n)
return memset(s, c, n);
}
#if defined(__arm__)
void *__bound___aeabi_memcpy(void *dest, const void *src, size_t n)
{
dprintf(stderr, "%s, %s(): %p, %p, 0x%lx\n",
__FILE__, __FUNCTION__, dest, src, (unsigned long)n);
INCR_COUNT(bound_mempcy_count);
__bound_check(dest, n, "memcpy dest");
__bound_check(src, n, "memcpy src");
if (check_overlap(dest, n, src, n, "memcpy"))
return dest;
return __aeabi_memcpy(dest, src, n);
}
void *__bound___aeabi_memmove(void *dest, const void *src, size_t n)
{
dprintf(stderr, "%s, %s(): %p, %p, 0x%lx\n",
__FILE__, __FUNCTION__, dest, src, (unsigned long)n);
INCR_COUNT(bound_memmove_count);
__bound_check(dest, n, "memmove dest");
__bound_check(src, n, "memmove src");
return __aeabi_memmove(dest, src, n);
}
void *__bound___aeabi_memmove4(void *dest, const void *src, size_t n)
{
dprintf(stderr, "%s, %s(): %p, %p, 0x%lx\n",
__FILE__, __FUNCTION__, dest, src, (unsigned long)n);
INCR_COUNT(bound_memmove_count);
__bound_check(dest, n, "memmove dest");
__bound_check(src, n, "memmove src");
return __aeabi_memmove4(dest, src, n);
}
void *__bound___aeabi_memmove8(void *dest, const void *src, size_t n)
{
dprintf(stderr, "%s, %s(): %p, %p, 0x%lx\n",
__FILE__, __FUNCTION__, dest, src, (unsigned long)n);
INCR_COUNT(bound_memmove_count);
__bound_check(dest, n, "memmove dest");
__bound_check(src, n, "memmove src");
return __aeabi_memmove8(dest, src, n);
}
void *__bound___aeabi_memset(void *s, int c, size_t n)
{
dprintf(stderr, "%s, %s(): %p, %d, 0x%lx\n",
__FILE__, __FUNCTION__, s, c, (unsigned long)n);
INCR_COUNT(bound_memset_count);
__bound_check(s, n, "memset");
return __aeabi_memset(s, c, n);
}
#endif
int __bound_strlen(const char *s)
{
const char *p = s;

16
lib/fetch_and_add_arm.S Normal file
View File

@@ -0,0 +1,16 @@
.text
.align 2
.global fetch_and_add_arm
.type fetch_and_add_arm, %function
fetch_and_add_arm:
.int 0xee070fba # mcr 15, 0, r0, cr7, cr10, {5}
.int 0xe1903f9f # ldrex r3, [r0]
.int 0xe2833001 # add r3, r3, #1
.int 0xe1802f93 # strex r2, r3, [r0]
.int 0xe3520000 # cmp r2, #0
.int 0x1afffffa # bne 4 <fetch_and_add_arm+0x4>
.int 0xee070fba # mcr 15, 0, r0, cr7, cr10, {5}
.int 0xe1a00003 # mov r0, r3
.int 0xe12fff1e # bx lr
.size fetch_and_add_arm, .-fetch_and_add_arm

14
lib/fetch_and_add_arm64.S Normal file
View File

@@ -0,0 +1,14 @@
.text
.align 2
.global fetch_and_add_arm64
.type fetch_and_add_arm64, %function
fetch_and_add_arm64:
.int 0x885f7c01 # ldxr w1, [x0]
.int 0x11000421 # add w1, w1, #0x1
.int 0x8802fc01 # stlxr w2, w1, [x0]
.int 0x35ffffa2 # cbnz w2, 0 <fetch_and_add_arm64>
.int 0xd5033bbf # dmb ish
.int 0x2a0103e0 # mov w0, w1
.int 0xd65f03c0 # ret
.size fetch_and_add_arm64, .-fetch_and_add_arm64

View File

@@ -0,0 +1,12 @@
.text
.align 2
.global fetch_and_add_riscv64
.type fetch_and_add_riscv64, %function
fetch_and_add_riscv64:
.short 0x4705 # li a4,1
.int 0x0f50000f # fence iorw,ow
.int 0x04e527af # amoadd.w.aq a5,a4,(a0)
.int 0x0017851b # addiw a0,a5,1
.short 0x8082 # ret
.size fetch_and_add_riscv64, .-fetch_and_add_riscv64