pharo-vm on NetBSD/amd64
Pharo 9のVMがNetBSD/amd64でも動かせるようになったのでメモ。
source
リポジトリは https://github.com/pharo-project/opensmalltalk-vm にあるが、こちらはVMMakerで自動生成されたコードは入っていない。自動生成させるにはpharo-vmが必要なので、「pharo-vmバイナリを作るのにpharo-vmのソースが必要で、pharo-vmのソースを作るのにpharo-vmバイナリが必要で……」という循環参照が発生する。
幸い自動生成されたコードも含めたものが http://files.pharo.org/vm/pharo-spur64-headless/Linux-x86_64/source/ にあるので、こっちから持ってくれば問題ない。ディレクトリ名に「headless」とあるけどcmakeのオプション指定で非headlessにできるので問題なし。
patch
とりあえず動くようにはなったけど、これで正解なのかは知らない。
"cmake/<OS>.cmake" を要求するので、とりあえず "cmake/OpenBSD.cmake" を "cmake/NetBSD.cmake" にコピー
backtrace(3) を使用しているので libexecinfo が必要になる
--- CMakeLists.txt.orig +++ CMakeLists.txt @@ -367,6 +367,7 @@ check_library_exists(dl dlopen "" HAVE_LIBDL) check_library_exists(dyld dlopen "" HAVE_DYLD) check_struct_has_member("struct tm" tm_gmtoff time.h HAVE_TM_GMTOFF) +check_library_exists(execinfo backtrace "" HAVE_EXECINFO) #Required by the UUID Plugin @@ -451,6 +452,10 @@ add_executable(${VM_EXECUTABLE_NAME} ${VM_FRONTEND_APPLICATION_TYPE} ${VM_FRONTEND_SOURCES}) addLibraryWithRPATH(${VM_LIBRARY_NAME} ${VM_SOURCES}) +if(${HAVE_EXECINFO}) + target_link_libraries(${VM_LIBRARY_NAME} execinfo) +endif() + # # LibFFI #
- uuidgen(2) を使用する(同時に libuuid の uuid_generate との衝突を回避)
- もともと uuidgen(2) を使用するコードがあったのでなるべくそちらを使うように頑張ったけど、やっぱり面倒だったので libuuid の uuid_generate に統一しても良いんじゃないかと思った次第。
--- CMakeLists.txt.orig +++ CMakeLists.txt @@ -374,6 +374,6 @@ check_include_files(uuid/uuid.h HAVE_UUID_UUID_H) check_include_files(uuid.h HAVE_UUID_H) -check_library_exists(uuid uuidgen "" HAVE_UUIDGEN) +check_function_exists(uuidgen HAVE_UUIDGEN) check_library_exists(uuid uuid_generate "" HAVE_UUID_GENERATE) --- plugins.cmake.orig +++ plugins.cmake @@ -77,7 +77,7 @@ addLibraryWithRPATH(UUIDPlugin ${UUIDPlugin_SOURCES}) if(WIN) target_link_libraries(UUIDPlugin PRIVATE "-lole32") - elseif(UNIX AND NOT OSX) + elseif(UNIX AND NOT OSX AND HAVE_UUID_GENENATE) #find_path(LIB_UUID_INCLUDE_DIR uuid.h PATH_SUFFIXES uuid) find_library(LIB_UUID_LIBRARY uuid) message(STATUS "Using uuid library:" ${LIB_UUID_LIBRARY})
- uuidgen(2) は native byte-order なので、 uuid_generate に合わせて big endian に強制する
- やっぱり uuid_generate に統一したほうが楽そう
--- plugins/UUIDPlugin/common/UUIDPlugin.c.orig +++ plugins/UUIDPlugin/common/UUIDPlugin.c @@ -41,6 +41,9 @@ #if defined(HAVE_UUIDGEN) uuidgen(&uuid, 1); + uuid.time_low = htobe32(uuid.time_low); + uuid.time_mid = htobe16(uuid.time_mid); + uuid.time_hi_and_version = htobe16(uuid.time_hi_and_version); #else uuid_generate(uuid); #endif
- clone(2) と名前が衝突したので、とりあえず sqclone へ変更
--- generated/64/vm/src/gcc3x-cointerp.c.orig +++ generated/64/vm/src/gcc3x-cointerp.c @@ -1068,7 +1068,7 @@ extern sqInt classUnsafeAlien(void); static void clearLeakMapAndMapAccessibleFreeSpace(void); static sqInt NoDbgRegParms cloneInOldSpaceforPinning(sqInt objOop, sqInt forPinning); -extern sqInt clone(sqInt objOop); +extern sqInt sqclone(sqInt objOop); extern sqInt compactClassIndexOf(sqInt objOop); static sqInt NoDbgRegParms copyObjtoAddrstopAtsavedFirstFieldsindex(sqInt objOop, sqInt segAddr, sqInt endSeg, sqInt savedFirstFields, sqInt i); extern void countMarkedAndUnmarkdObjects(sqInt printFlags); @@ -46834,7 +46834,7 @@ /* SpurMemoryManager>>#clone: */ sqInt -clone(sqInt objOop) +sqclone(sqInt objOop) { DECL_MAYBE_SQ_GLOBAL_STRUCT sqInt classIndex; sqInt classIndex1; @@ -54408,14 +54408,14 @@ clone1 = (((longAt(obj1)) & (classIndexMask())) == ClassMethodContextCompactIndex ? cloneContext(obj1) - : clone(obj1)); + : sqclone(obj1)); if (!(clone1)) { error("Not enough space to copy the objects in two-way become. This should have been detected before"); return; } clone2 = (((longAt(obj2)) & (classIndexMask())) == ClassMethodContextCompactIndex ? cloneContext(obj2) - : clone(obj2)); + : sqclone(obj2)); if (!(clone2)) { error("Not enough space to copy the objects in two-way become. This should have been detected before"); return; @@ -75835,7 +75835,7 @@ else { if ((GIV(argumentCount) == 0) || (!(((longAt(rcvr)) & ((classIndexMask()) - (isForwardedObjectClassIndexPun()))) == 0))) { - newCopy = clone(rcvr); + newCopy = sqclone(rcvr); } else { newCopy = 0;
--- src/debugUnix.c.orig +++ src/debugUnix.c @@ -16,6 +16,12 @@ #endif +#if __NetBSD__ + +#include <ucontext.h> + +#endif + #ifdef HAVE_EXECINFO_H # include <execinfo.h> @@ -250,6 +256,20 @@ regs->mc_edi, regs->mc_edi, regs->mc_ebp, regs->mc_esp, regs->mc_eip); return regs->mc_eip; +#elif __NetBSD__ && __x86_64__ + __greg_t *regs = &uap->uc_mcontext.__gregs; + fprintf(output, + "\trax 0x%08llx rbx 0x%08llx rcx 0x%08llx rdx 0x%08llx\n" + "\trdi 0x%08llx rsi 0x%08llx rbp 0x%08llx rsp 0x%08llx\n" + "\tr8 0x%08llx r9 0x%08llx r10 0x%08llx r11 0x%08llx\n" + "\tr12 0x%08llx r13 0x%08llx r14 0x%08llx r15 0x%08llx\n" + "\trip 0x%08llx\n", + regs[_REG_RAX], regs[_REG_RBX], regs[_REG_RCX], regs[_REG_RDX], + regs[_REG_RDI], regs[_REG_RSI], regs[_REG_RBP], regs[_REG_RSP], + regs[_REG_R8 ], regs[_REG_R9 ], regs[_REG_R10], regs[_REG_R11], + regs[_REG_R12], regs[_REG_R13], regs[_REG_R14], regs[_REG_R15], + regs[_REG_RIP]); + return (void *)regs[_REG_RIP]; #elif __linux__ && __x86_64__ greg_t *regs = uap->uc_mcontext.gregs; fprintf(output, @@ -409,6 +429,9 @@ # elif __FreeBSD__ && __i386__ void *fp = (void *)(uap ? uap->uc_mcontext.mc_ebp: 0); void *sp = (void *)(uap ? uap->uc_mcontext.mc_esp: 0); +#elif __NetBSD__ + void *fp = (void *)(uap ? _UC_MACHINE_FP(uap) : 0); + void *sp = (void *)(uap ? _UC_MACHINE_SP(uap) : 0); # elif __OpenBSD__ void *fp = (void *)(uap ? uap->sc_rbp: 0); void *sp = (void *)(uap ? uap->sc_rsp: 0);
- 起動スクリプトで LD_LIBRAY_PATHに @pkglibdir@ (後で /usr/pkg/lib に置換)を追加
--- packaging/linux/bin/launch.sh.in.orig +++ packaging/linux/bin/launch.sh.in @@ -18,8 +18,8 @@ *) PLUGINS="`pwd`/$BIN" esac -if [ $(uname -s) = "OpenBSD" ]; then - LD_LIBRARY_PATH="$PLUGINS:${LD_LIBRARY_PATH}" exec $GDB "$BIN/@VM_EXECUTABLE_NAME@" "$@" +if [ $(uname -s) = "OpenBSD" -o $(uname -s) = "NetBSD" ]; then + LD_LIBRARY_PATH="$PLUGINS:@pkglibdir@:${LD_LIBRARY_PATH}" exec $GDB "$BIN/@VM_EXECUTABLE_NAME@" "$@" fi # On some linuxes there multiple versions of the C library. If the image uses
cmake option
-DFLAVOUR=CoInterpreter
: デフォルト値と同じだけどJenkinsfileが指定してたので。-DALWAYS_INTERACTIVE=1
: 非headlessなVMが必要な場合に指定する。これもJenkinsfileで指定されていたので。-DGENERATE_SOURCES=OFF
: ソースの自動生成を行わなくする。-DPHARO_BIN_LOCATION=${PREFIX}/lib/pharo
起動スクリプトがここで指定されたバイナリを実行する。
after build
build/vm/*
がバイナリとライブラリ、 build/packaging/linux/bin/pharo
が起動スクリプトなので適当に回収する。
なお build/vm/pharo
はJITで動く関係か paxctl -m
で PaX MPROTECT を解除しておく必要がる。