From aefbb5274deb6275104e3e3ebe3e8faa5a544dd8 Mon Sep 17 00:00:00 2001 From: herman ten brugge Date: Sat, 16 Jan 2021 07:01:59 +0100 Subject: [PATCH] BSD: arm support Support OpenBSD/FreeBSD/NetBSD on asm. move PAGESIZE to tcc.h and use _SC_PAGESIZE (netbsd/arm has 8192 pagesize) arm: - fix cmp instruction for qemu (raspberry pi works without patch?) - increase start address/size - use large plt size - add return R_ARM_PREL31 - add R_ARM_TARGET1 to prepare_dynamic_rel - add gcc_s to FreeBSD (unwind code) - do not use __clear_cache on bsd (sometimes bad system call) - do stack unwinding on bsd - test/tcctest.c: use %lld %llu on bsd --- arm-gen.c | 16 ++++++++++++---- arm-link.c | 16 +++++++++------- tcc.h | 8 ++++++++ tccelf.c | 4 ++++ tccrun.c | 16 +++++++++++++--- tests/tcctest.c | 4 +++- 6 files changed, 49 insertions(+), 15 deletions(-) diff --git a/arm-gen.c b/arm-gen.c index 20ceac4..5d8f07e 100644 --- a/arm-gen.c +++ b/arm-gen.c @@ -1674,8 +1674,12 @@ void gen_opi(int op) uint32_t x; x=stuff_const(opc|0x2000000|(c<<16),vtop->c.i); if(x) { - r=intr(vtop[-1].r=get_reg_ex(RC_INT,regmask(vtop[-1].r))); - o(x|(r<<12)); + if ((x & 0xfff00000) == 0xe3500000) // cmp rx,#c + o(x); + else { + r=intr(vtop[-1].r=get_reg_ex(RC_INT,regmask(vtop[-1].r))); + o(x|(r<<12)); + } goto done; } } @@ -1685,8 +1689,12 @@ void gen_opi(int op) c=intr(gv(RC_INT)); vswap(); } - r=intr(vtop[-1].r=get_reg_ex(RC_INT,two2mask(vtop->r,vtop[-1].r))); - o(opc|(c<<16)|(r<<12)|fr); + if ((opc & 0xfff00000) == 0xe1500000) // cmp rx,ry + o(opc|(c<<16)|fr); + else { + r=intr(vtop[-1].r=get_reg_ex(RC_INT,two2mask(vtop->r,vtop[-1].r))); + o(opc|(c<<16)|(r<<12)|fr); + } done: vtop--; if (op >= TOK_ULT && op <= TOK_GT) diff --git a/arm-link.c b/arm-link.c index a2a1d33..faf03d9 100644 --- a/arm-link.c +++ b/arm-link.c @@ -12,8 +12,8 @@ #define R_NUM R_ARM_NUM -#define ELF_START_ADDR 0x00008000 -#define ELF_PAGE_SIZE 0x1000 +#define ELF_START_ADDR 0x00010000 +#define ELF_PAGE_SIZE 0x10000 #define PCRELATIVE_DLLPLT 1 #define RELOCATE_DLLPLT 1 @@ -127,7 +127,7 @@ ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_ write32le(p, 0x4778); /* bx pc */ write32le(p+2, 0x46c0); /* nop */ } - p = section_ptr_add(plt, 12); + p = section_ptr_add(plt, 16); /* save GOT offset for relocate_plt */ write32le(p + 4, got_offset); return plt_offset; @@ -153,10 +153,11 @@ ST_FUNC void relocate_plt(TCCState *s1) unsigned off = x + read32le(p + 4) + (s1->plt->data - p) + 4; if (read32le(p) == 0x46c04778) /* PLT Thumb stub present */ p += 4; - write32le(p, 0xe28fc600 | ((off >> 20) & 0xff)); // add ip, pc, #0xNN00000 - write32le(p + 4, 0xe28cca00 | ((off >> 12) & 0xff)); // add ip, ip, #0xNN000 - write32le(p + 8, 0xe5bcf000 | (off & 0xfff)); // ldr pc, [ip, #0xNNN]! - p += 12; + write32le(p, 0xe28fc200 | ((off >> 28) & 0xf)); // add ip, pc, #0xN0000000 + write32le(p + 4, 0xe28cc600 | ((off >> 20) & 0xff)); // add ip, pc, #0xNN00000 + write32le(p + 8, 0xe28cca00 | ((off >> 12) & 0xff)); // add ip, ip, #0xNN000 + write32le(p + 12, 0xe5bcf000 | (off & 0xfff)); // ldr pc, [ip, #0xNNN]! + p += 16; } } } @@ -346,6 +347,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t tcc_error("can't relocate value at %x,%d",addr, type); (*(int *)ptr) |= x & 0x7fffffff; } + return; case R_ARM_ABS32: // case R_ARM_TARGET1: /* ??? as seen on NetBSD - FIXME! */ if (s1->output_type == TCC_OUTPUT_DLL) { diff --git a/tcc.h b/tcc.h index 71eb00a..b794590 100644 --- a/tcc.h +++ b/tcc.h @@ -86,6 +86,14 @@ extern long double strtold (const char *__nptr, char **__endptr); # undef CONFIG_TCC_STATIC #endif +#ifndef PAGESIZE +# ifdef _SC_PAGESIZE +# define PAGESIZE sysconf(_SC_PAGESIZE) +# else +# define PAGESIZE 4096 +# endif +#endif + #ifndef O_BINARY # define O_BINARY 0 #endif diff --git a/tccelf.c b/tccelf.c index 76487f5..53ec319 100644 --- a/tccelf.c +++ b/tccelf.c @@ -1055,6 +1055,7 @@ static int prepare_dynamic_rel(TCCState *s1, Section *sr) case R_X86_64_64: #elif defined(TCC_TARGET_ARM) case R_ARM_ABS32: + case R_ARM_TARGET1: #elif defined(TCC_TARGET_ARM64) case R_AARCH64_ABS32: case R_AARCH64_ABS64: @@ -1445,6 +1446,9 @@ ST_FUNC void tcc_add_runtime(TCCState *s1) tcc_add_dll(s1, TCC_LIBGCC, 0); } #endif +#if defined(TCC_TARGET_ARM) && defined(TARGETOS_FreeBSD) + tcc_add_library_err(s1, "gcc_s"); // unwind code +#endif #ifdef CONFIG_TCC_BCHECK if (s1->do_bounds_check && s1->output_type != TCC_OUTPUT_DLL) { tcc_add_library_err(s1, "pthread"); diff --git a/tccrun.c b/tccrun.c index 4c3cdf8..79dd1e2 100644 --- a/tccrun.c +++ b/tccrun.c @@ -352,7 +352,10 @@ static void set_pages_executable(TCCState *s1, void *ptr, unsigned long length) if (mprotect((void *)start, end - start, PROT_READ | PROT_EXEC)) tcc_error("mprotect failed: did you mean to configure --with-selinux?"); # endif -# if defined TCC_TARGET_ARM || defined TCC_TARGET_ARM64 +/* XXX: BSD sometimes dump core with bad system call */ +# if (defined(TCC_TARGET_ARM) && \ + !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__)) || \ + defined(TCC_TARGET_ARM64) # ifdef __APPLE__ sys_icache_invalidate(ptr, length); sys_dcache_flush(ptr, length); @@ -691,6 +694,12 @@ static void rt_getcontext(ucontext_t *uc, rt_context *rc) # if defined(__APPLE__) rc->ip = uc->uc_mcontext->__ss.__pc; rc->fp = uc->uc_mcontext->__ss.__r[11]; +# elif defined(__FreeBSD__) || defined(__NetBSD__) + rc->ip = uc->uc_mcontext.__gregs[_REG_PC]; + rc->fp = uc->uc_mcontext.__gregs[_REG_FP]; +# elif defined(__OpenBSD__) + rc->ip = uc->sc_pc; + rc->fp = uc->sc_fpreg[29]; # elif defined(__QNX__) rc->ip = uc->uc_mcontext.cpu.gpr[15]; rc->fp = uc->uc_mcontext.cpu.gpr[11]; @@ -860,8 +869,9 @@ static int rt_get_caller_pc(addr_t *paddr, rt_context *rc, int level) #elif defined(__arm__) static int rt_get_caller_pc(addr_t *paddr, rt_context *rc, int level) { - /* XXX: only supports linux */ -#if !defined(__linux__) + /* XXX: only supports linux/bsd */ +#if !defined(__linux__) && \ + !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) return -1; #else if (level == 0) { diff --git a/tests/tcctest.c b/tests/tcctest.c index 71089b5..3ca540e 100644 --- a/tests/tcctest.c +++ b/tests/tcctest.c @@ -21,7 +21,9 @@ typedef __SIZE_TYPE__ uintptr_t; #endif -#if defined(_WIN32) +#if defined(_WIN32) || \ + (defined(__arm__) && \ + (defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__))) #define LONG_LONG_FORMAT "%lld" #define ULONG_LONG_FORMAT "%llu" #else