mirror of
https://github.com/mirror/tinycc.git
synced 2026-09-03 12:12:46 +08:00
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:
12
lib/Makefile
12
lib/Makefile
@@ -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)))
|
||||
|
||||
97
lib/bcheck.c
97
lib/bcheck.c
@@ -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
16
lib/fetch_and_add_arm.S
Normal 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
14
lib/fetch_and_add_arm64.S
Normal 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
|
||||
12
lib/fetch_and_add_riscv64.S
Normal file
12
lib/fetch_and_add_riscv64.S
Normal 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
|
||||
Reference in New Issue
Block a user