Skip to content

Commit

Permalink
CogVM source as per VMMaker.oscog-eem.2988
Browse files Browse the repository at this point in the history
Add hook to IA32ABI's primAlienReplace for Apple Silicon to flip executable
pages into writability around a write to the page via primAlienReplace.
Add implementation in arm64abicc.c.

Get rid of compilaiton warnings with the register set printing code in
sqSqueakMainApp.m.  Normalize the ormatting in sqMacUnixExternalPrims.m.
[ci skip] cuz AFAIA Apple Silicon builds aren't set up yet.
  • Loading branch information
eliotmiranda committed Jul 19, 2021
1 parent ddc6ff0 commit 4bb3d87
Show file tree
Hide file tree
Showing 5 changed files with 138 additions and 64 deletions.
76 changes: 62 additions & 14 deletions platforms/Cross/plugins/IA32ABI/arm64abicc.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,25 @@
*
* Support for Call-outs and Call-backs from the Plugin on ARM.
* Written by Eliot Miranda & Ryan Macnak, 07/15.
* Updated for aarch64 by Ken Dickey
* Updated for aarch64 by Ken Dickey 02/19
* Updated for Apple Silicon 07/21
*/

/* null if compiled on other than arm64/aarch64, to get around gnu make bugs or
* misunderstandings on our part.
*/
#if defined(__ARM_ARCH_ISA_A64) || defined(__arm64__) || defined(__aarch64__) || defined(ARM64)

#include <unistd.h> /* for getpagesize/sysconf */
#include <stdlib.h> /* for valloc */
#include <sys/mman.h> /* for mprotect */
#include <unistd.h> // for getpagesize/sysconf
#include <stdlib.h> // for valloc
#include <sys/mman.h> // for mprotect
# if defined(MAP_JIT) && __APPLE__ // for pthread_jit_write_protect_np
# include <pthread.h>
# endif

#include <string.h> /* for memcpy et al */
#include <string.h> // for memcpy et al
#include <setjmp.h>
#include <stdio.h> /* for fprintf(stderr,...) */
#include <stdio.h> // for fprintf(stderr,...)

#include "sqMemoryAccess.h"
#include "vmCallback.h"
Expand Down Expand Up @@ -265,8 +269,11 @@ thunkEntry(long x0, long x1, long x2, long x3,
* page amongst thunks so there is no need to free these pages, since the image
* will recycle parts of the page for reclaimed thunks.
*/
#if defined(_MSC_VER) || defined(__MINGW32__)
static unsigned long pagesize = 0;
static usqInt pagesize = 0;

#if defined(MAP_JIT)
void **allocatedPages = 0;
int allocatedPagesSize = 0;
#endif

void *
Expand All @@ -275,9 +282,9 @@ allocateExecutablePage(sqIntptr_t *size)
void *mem;

#if defined(_MSC_VER) || defined(__MINGW32__)
#if !defined(MEM_TOP_DOWN)
# define MEM_TOP_DOWN 0x100000
#endif
# if !defined(MEM_TOP_DOWN)
# define MEM_TOP_DOWN 0x100000
# endif
if (!pagesize) {
SYSTEM_INFO sysinf;

Expand All @@ -301,7 +308,9 @@ allocateExecutablePage(sqIntptr_t *size)
# define MAP_FLAGS (MAP_ANON | MAP_PRIVATE)
# endif

long pagesize = getpagesize();
if (!pagesize)
pagesize = getpagesize();
void **newAllocatedPages;

mem = mmap( 0, pagesize,
PROT_READ | PROT_WRITE | PROT_EXEC,
Expand All @@ -311,13 +320,27 @@ allocateExecutablePage(sqIntptr_t *size)
return 0;
}
*size = pagesize;

# if defined(MAP_JIT)
++allocatedPagesSize;
newAllocatedPages = realloc(allocatedPages,
allocatedPagesSize * sizeof(void *));
if (!newAllocatedPages) {
munmap(mem, pagesize);
perror("Could not realloc allocatedPages");
return 0;
}
allocatedPages = newAllocatedPages;
newAllocatedPages[allocatedPagesSize - 1] = mem;
# endif
return mem;
#else

if (!pagesize)
# if !defined(_POSIX_C_SOURCE) || _POSIX_C_SOURCE < 200112L
long pagesize = getpagesize();
pagesize = getpagesize();
# else
long pagesize = sysconf(_SC_PAGESIZE);
pagesize = sysconf(_SC_PAGESIZE);
# endif

if (!(mem = valloc(pagesize)))
Expand All @@ -332,4 +355,29 @@ allocateExecutablePage(sqIntptr_t *size)
return mem;
#endif
}

#if defined(MAP_JIT)
sqInt
ifIsWithinExecutablePageMakePageWritable(char *address)
{
void *page = (void *)((uintptr_t)address & ~(pagesize - 1));
int i;

if (!pagesize)
return 0;

for (i = 0; i < allocatedPagesSize; i++)
if (allocatedPages[i] == page) {
pthread_jit_write_protect_np(0);
return 1;
}
return 0;
}

void
makePageExecutableAgain(char *address)
{
pthread_jit_write_protect_np(1);
}
#endif // defined(MAP_JIT)
#endif /* defined(__ARM_ARCH_ISA_A64) || defined(__arm64__) || ... */
9 changes: 9 additions & 0 deletions platforms/Cross/plugins/IA32ABI/ia32abi.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ extern sqInt callIA32FloatReturn (SIGNATURE);
extern sqInt callIA32DoubleReturn (SIGNATURE);

#define thunkEntryType long
#define ifIsWithinExecutablePageMakePageWritable(address) 0
#define makePageExecutableAgain(address) 0

#if defined(i386) || defined(__i386) || defined(__i386__) || (defined(_WIN32) && !defined(_WIN64)) || defined(_M_IX86)
# define INT_REG_ARGS /* none */
# define DBL_REG_ARGS /* none */
Expand All @@ -56,6 +59,12 @@ extern sqInt callIA32DoubleReturn (SIGNATURE);
# define thunkEntryType long long
# define INT_REG_ARGS long,long,long,long,long,long,long,long,
# define DBL_REG_ARGS double,double,double,double,double,double,double,double,
# if __APPLE__
# undef ifIsWithinExecutablePageMakePageWritable
# undef makePageExecutableAgain
extern sqInt ifIsWithinExecutablePageMakePageWritable(char *address);
extern void makePageExecutableAgain(char *address);
# endif
#elif defined(__ARM_ARCH__) || defined(__arm__) || defined(__arm32__) || defined(ARM32)
# undef thunkEntryType
# define thunkEntryType long long
Expand Down
19 changes: 11 additions & 8 deletions platforms/iOS/vm/Common/Classes/sqSqueakMainApp.m
Original file line number Diff line number Diff line change
Expand Up @@ -257,14 +257,17 @@ Some of this code was funded via a grant from the European Smalltalk User Group
"\tx24 %p x25 %p x26 %p x27 %p\n"
"\tx29 %p fp %p lr %p sp %p\n",
"\tcpsr 0x%08x\n",
regs->__x[0], regs->__x[1], regs->__x[2], regs->__x[3],
regs->__x[4], regs->__x[5], regs->__x[6], regs->__x[7],
regs->__x[8], regs->__x[9], regs->__x[10], regs->__x[11],
regs->__x[12], regs->__x[13], regs->__x[14], regs->__x[15],
regs->__x[16], regs->__x[17], regs->__x[18], regs->__x[19],
regs->__x[20], regs->__x[21], regs->__x[22], regs->__x[23],
regs->__x[24], regs->__x[25], regs->__x[26], regs->__x[27],
regs->__x[28], regs->__fp, regs->__lr, regs->__sp, regs->__pc, regs->__cpsr);
# define v(v) ((void *)(regs->v))
v(__x[0]), v(__x[1]), v(__x[2]), v(__x[3]),
v(__x[4]), v(__x[5]), v(__x[6]), v(__x[7]),
v(__x[8]), v(__x[9]), v(__x[10]), v(__x[11]),
v(__x[12]), v(__x[13]), v(__x[14]), v(__x[15]),
v(__x[16]), v(__x[17]), v(__x[18]), v(__x[19]),
v(__x[20]), v(__x[21]), v(__x[22]), v(__x[23]),
v(__x[24]), v(__x[25]), v(__x[26]), v(__x[27]),
v(__x[28]), v(__fp), v(__lr), v(__sp), v(__pc),
regs->__cpsr);
# undef v
#elif defined(__arm__) || defined(__arm32__)
_STRUCT_ARM_THREAD_STATE *regs = &uap->uc_mcontext->ss;
printf( "\t r0 0x%08x r1 0x%08x r2 0x%08x r3 0x%08x\n"
Expand Down
49 changes: 22 additions & 27 deletions platforms/iOS/vm/OSX/sqMacUnixExternalPrims.m
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@
dprintf((stderr, "ignoring directory: %s\n", libName));
else {
const char *why;
dprintf((stderr, "tryLoading %s\n", libName));
dprintf((stderr, "tryLoading %s\n", libName));
if ((handle = dlopen(libName, RTLD_NOW | RTLD_GLOBAL)))
return handle;
why = dlerror();
Expand Down Expand Up @@ -169,12 +169,11 @@
return NULL;
}
for (prefix= prefixes; *prefix; ++prefix)
for (suffix= suffixes; *suffix; ++suffix) {
for (suffix= suffixes; *suffix; ++suffix) {
libName = [dirNameString stringByAppendingPathComponent: @(*prefix)];
if (**prefix)
libName = [libName stringByAppendingString: @(moduleName)];
else
libName = [libName stringByAppendingPathComponent: @(moduleName)];
libName = **prefix
? [libName stringByAppendingString: @(moduleName)]
: [libName stringByAppendingPathComponent: @(moduleName)];
if (**suffix)
libName = [libName stringByAppendingPathExtension: @(*suffix)];

Expand All @@ -187,18 +186,16 @@
static void *
tryLoadingLinked(char *libName)
{
void *handle;

#if !PharoVM
if (thePListInterface.SqueakPluginsBuiltInOrLocalOnly)
return NULL;
#endif

handle = dlopen(libName, RTLD_NOW | RTLD_GLOBAL);
DPRINTF((stderr, __FILE__ " %d tryLoadingLinked dlopen(%s) = %p\n", __LINE__, libName, handle));
void *handle = dlopen(libName, RTLD_NOW | RTLD_GLOBAL);
DPRINTF((stderr, __FILE__ " %d tryLoadingLinked dlopen(%s) = %p\n", __LINE__, libName, handle));
#if DEBUG
if(handle != 0)
printf("%s: loaded plugin `%s'\n", exeName, libName);
if (handle)
printf("%s: loaded plugin `%s'\n", exeName, libName);
#endif
if (!handle) {
const char *why = dlerror();
Expand All @@ -207,7 +204,7 @@
else if (strstr(why,"undefined symbol"))
fprintf(stderr, "tryLoadingLinked: dlopen: %s\n", why);
}
return handle;
return handle;
}

/* Find and load the named module. Answer 0 if not found (do NOT fail
Expand All @@ -234,7 +231,7 @@
}
dprintf((stderr, "loaded: <intrinsic>\n"));
return handle;
}
}

#if PharoVM
/* first, look in the "<Squeak VM directory>Plugins" directory for the library */
Expand All @@ -246,19 +243,19 @@
if (thePListInterface.SqueakPluginsBuiltInOrLocalOnly) {
if (( handle= tryLoadingLinked( pluginName))
|| (handle= tryLoadingBundle( vmDirPath, pluginName))
|| (handle= tryLoadingVariations( frameworksDirPath, pluginName))
|| (handle= tryLoadingVariations( frameworksDirPath, pluginName))
#if PharoVM
|| (handle= tryLoadingVariations( pluginDirPath, pluginName))
|| (handle= tryLoadingVariations( pluginDirPath, pluginName))
#endif
)
return handle;
}
else {
else {
if (( handle= tryLoadingLinked( pluginName))
|| (handle= tryLoadingBundle( vmDirPath, pluginName))
|| (handle= tryLoadingVariations( frameworksDirPath, pluginName))
|| (handle= tryLoadingVariations( frameworksDirPath, pluginName))
#if PharoVM
|| (handle= tryLoadingVariations( pluginDirPath, pluginName))
|| (handle= tryLoadingVariations( pluginDirPath, pluginName))
#endif
|| (handle= tryLoadingVariations( @"./", pluginName))
|| (handle= tryLoadingVariations( @"", pluginName))
Expand Down Expand Up @@ -377,7 +374,7 @@
&& strcmp(lookupName, "shutdownModule")
&& strcmp(lookupName, "setInterpreter")
&& strcmp(lookupName, "getModuleName"))
fprintf(stderr, "ioFindExternalFunctionIn(%s, %p):\n %s\n",
fprintf(stderr, "ioFindExternalFunctionIn(%s, %p):\n %s\n",
lookupName, moduleHandle, dlerror());

#if SPURVM
Expand All @@ -404,12 +401,10 @@
*/
sqInt ioFreeModule(void *moduleHandle)
{
int results = dlclose(moduleHandle);
if (!dlclose(moduleHandle))
return 1;

if (results) {
char* why = dlerror();
dprintf((stderr, "ioFreeModule(%ld): %s\n", (long) moduleHandle, why));
return 0;
}
return 1;
char *why = dlerror();
dprintf((stderr, "ioFreeModule(%ld): %s\n", (long) moduleHandle, why));
return 0;
}
Loading

0 comments on commit 4bb3d87

Please sign in to comment.