From 26a21a7a1004e79bf5d4af8adf1100c3d45591f1 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Wed, 10 Jan 2024 15:26:53 +0100 Subject: [PATCH] jit/cache: Fix for arm CPUs with GCC target arm-linux-gnueabihf. * tests/jit/test-cache.c (CODE): Define differently on arm. (SET_CODE, IS, SET_IS): New macros. (main): New variables is_of_return1, is_of_return2. Use the SET_CODE and SET_IS macros. --- ChangeLog | 8 ++++++++ tests/jit/test-cache.c | 35 +++++++++++++++++++++++++++++++++-- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index aa6177fbd3..b6de485579 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2024-01-10 Bruno Haible + + jit/cache: Fix for arm CPUs with GCC target arm-linux-gnueabihf. + * tests/jit/test-cache.c (CODE): Define differently on arm. + (SET_CODE, IS, SET_IS): New macros. + (main): New variables is_of_return1, is_of_return2. Use the SET_CODE and + SET_IS macros. + 2024-01-10 Bruno Haible jit/cache tests: Avoid compiler warnings on OpenBSD. diff --git a/tests/jit/test-cache.c b/tests/jit/test-cache.c index cabbc0ddfd..cad6d2a214 100644 --- a/tests/jit/test-cache.c +++ b/tests/jit/test-cache.c @@ -90,7 +90,25 @@ struct func #ifdef FUNCPTR_POINTS_TO_CODE /* A function pointer points directly to the code. */ # define COPY_FUNCPTR(funcptr) funcptr -# define CODE(funcptr) (funcptr) +/* On arm, bit 0 of a function pointer tells which instruction set the function + uses. */ +# if defined __arm__ || defined __armhf__ +# define CODE(funcptr) ((void *) ((uintptr_t) (funcptr) & ~(intptr_t)1)) +# define SET_CODE(funcptr,code_addr) \ + ((void) ((funcptr) = \ + (void *) (((uintptr_t) (funcptr) & (intptr_t)1) \ + | (uintptr_t) (code_addr)))) +# define IS(funcptr) ((uintptr_t) (funcptr) & 1) +# define SET_IS(funcptr,is) \ + ((void) ((funcptr) = \ + (void *) (((uintptr_t) (funcptr) & ~(intptr_t)1) | (is)))) +# else +# define CODE(funcptr) (funcptr) +# define SET_CODE(funcptr,code_addr) \ + ((void) ((funcptr) = (void *) (code_addr))) +# define IS(funcptr) ((void) (funcptr), 0) +# define SET_IS(funcptr,is) ((void) (funcptr), (void) (is)) +# endif #else /* A function pointer points to a 'struct func'. */ # if FUNCPTR_BIAS @@ -119,6 +137,10 @@ xcopy_structptr (struct func *structptr) structptr_to_funcptr (xcopy_structptr (funcptr_to_structptr (funcptr))) # define CODE(funcptr) \ ((funcptr_to_structptr (funcptr))->code_address) +# define SET_CODE(funcptr,code_addr) \ + ((void) (CODE (funcptr) = (code_addr))) +# define IS(funcptr) ((void) (funcptr), 0) +# define SET_IS(funcptr,is) ((void) (funcptr), (void) (is)) #endif /* This test assumes that the code generated by the compiler for the @@ -212,6 +234,8 @@ main () void const *code_of_return2; size_t size_of_return1; size_t size_of_return2; + int is_of_return1; + int is_of_return2; #if defined __OpenBSD__ || defined _RET_PROTECTOR /* OpenBSD maps code with PROT_EXEC (as opposed to PROT_READ | PROT_EXEC). We need to use predetermined code for 'return1' and 'return2'. */ @@ -224,12 +248,17 @@ main () code_of_return2 = return2_code; size_of_return1 = sizeof (return1_code); size_of_return2 = sizeof (return2_code); + /* On arm, return1_code and return2_code use the "ARM" instruction set. */ + is_of_return1 = 0; + is_of_return2 = 0; #else code_of_return1 = CODE (return1); code_of_return2 = CODE (return2); /* We assume that the code is not longer than 64 bytes. */ size_of_return1 = 64; size_of_return2 = 64; + is_of_return1 = IS (return1); + is_of_return2 = IS (return2); #endif int const pagesize = getpagesize (); @@ -306,13 +335,15 @@ main () } int (*f) (void) = COPY_FUNCPTR (return1); - CODE (f) = start; + SET_CODE (f, start); memcpy (start_rw, code_of_return1, size_of_return1); + SET_IS (f, is_of_return1); clear_cache (start, end); ASSERT (f () == 1); memcpy (start_rw, code_of_return2, size_of_return2); + SET_IS (f, is_of_return2); clear_cache (start, end); ASSERT (f () == 2); -- 2.39.5