mirror of
https://github.com/mkxp-z/mkxp-z.git
synced 2025-08-23 07:13:44 +02:00
Detect DLL architecture at runtime
This commit is contained in:
parent
9a4c53e6fe
commit
1785d7c2dd
3 changed files with 44 additions and 16 deletions
|
@ -97,6 +97,7 @@ RB_METHOD(MiniFFI_initialize) {
|
||||||
rb_iv_set(self, "_func", MVAL2RB((mffi_value)hfunc));
|
rb_iv_set(self, "_func", MVAL2RB((mffi_value)hfunc));
|
||||||
rb_iv_set(self, "_funcname", func);
|
rb_iv_set(self, "_funcname", func);
|
||||||
rb_iv_set(self, "_libname", libname);
|
rb_iv_set(self, "_libname", libname);
|
||||||
|
rb_iv_set(self, "_64bit", rb_bool_new(libIs64(RSTRING_PTR(func))));
|
||||||
|
|
||||||
VALUE ary_imports = rb_ary_new();
|
VALUE ary_imports = rb_ary_new();
|
||||||
VALUE *entry;
|
VALUE *entry;
|
||||||
|
|
|
@ -2,37 +2,49 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#if defined(__linux__) || defined(__APPLE__)
|
#if defined(__linux__) || defined(__APPLE__)
|
||||||
mffi_value miniffi_call_intern(MINIFFI_FUNC target, MiniFFIFuncArgs *p, int nparams) {
|
mffi_value miniffi_call_intern(MINIFFI_FUNC target, MiniFFIFuncArgs *p, int nparams, bool is64) {
|
||||||
assert(nparams <= 8);
|
assert(nparams <= 8);
|
||||||
return target(p->params[0], p->params[1], p->params[2], p->params[3],
|
return target(p->params[0], p->params[1], p->params[2], p->params[3],
|
||||||
p->params[4], p->params[5], p->params[6], p->params[7]);
|
p->params[4], p->params[5], p->params[6], p->params[7]);
|
||||||
}
|
}
|
||||||
|
// It does not actually matter whether the library is 64-bit or not,
|
||||||
|
// on Linux and macOS we only load the same architecture
|
||||||
|
// In the future this will probably only check so that it's possible
|
||||||
|
// to raise an error
|
||||||
|
bool libIs64(void *handle) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
|
#include <windows.h>
|
||||||
|
mffi_value miniffi_call_intern(MINIFFI_FUNC target, MiniFFIFuncArgs *p, int nparams, bool is64) {
|
||||||
|
#ifdef __MINGW64__
|
||||||
|
if (is64)
|
||||||
|
return call_asm64(target, p, nparams);
|
||||||
|
return call_asm32(target, p, nparams);
|
||||||
|
}
|
||||||
#define INTEL_ASM ".intel_syntax noprefix\n"
|
#define INTEL_ASM ".intel_syntax noprefix\n"
|
||||||
__attribute__((noinline))
|
__attribute__((noinline))
|
||||||
#ifndef __MINGW64__
|
mffi_value call_asm32(MINIFFI_FUNC target, MiniFFIFuncArgs *p, int nparams) {
|
||||||
mffi_value miniffi_call_intern(MINIFFI_FUNC target, MiniFFIFuncArgs *p, int nparams) {
|
|
||||||
mffi_value ret;
|
mffi_value ret;
|
||||||
void *old_esp = 0;
|
void *old_esp = 0;
|
||||||
|
|
||||||
asm volatile(INTEL_ASM
|
asm volatile(INTEL_ASM
|
||||||
|
|
||||||
"MiniFFI_call_asm:\n"
|
|
||||||
"mov [edi], esp\n"
|
"mov [edi], esp\n"
|
||||||
"test ebx, ebx\n"
|
"test ebx, ebx\n"
|
||||||
"jz mffi_call_void\n"
|
"jz mffi_call_void32\n"
|
||||||
|
|
||||||
"shl ebx, 2\n"
|
"shl ebx, 2\n"
|
||||||
"mov ecx, ebx\n"
|
"mov ecx, ebx\n"
|
||||||
|
|
||||||
"mffi_call_loop:\n"
|
"mffi_call_loop32:\n"
|
||||||
"sub ecx, 4\n"
|
"sub ecx, 4\n"
|
||||||
"mov ebx, [esi+ecx]\n"
|
"mov ebx, [esi+ecx]\n"
|
||||||
"push ebx\n"
|
"push ebx\n"
|
||||||
"test ecx, ecx\n"
|
"test ecx, ecx\n"
|
||||||
"jnz mffi_call_loop\n"
|
"jnz mffi_call_loop32\n"
|
||||||
|
|
||||||
"mffi_call_void:\n"
|
"mffi_call_void32:\n"
|
||||||
"call edx\n"
|
"call edx\n"
|
||||||
|
|
||||||
: "=a"(ret)
|
: "=a"(ret)
|
||||||
|
@ -53,28 +65,28 @@ mffi_value miniffi_call_intern(MINIFFI_FUNC target, MiniFFIFuncArgs *p, int npar
|
||||||
);
|
);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
#else
|
#ifdef __MINGW64__
|
||||||
mffi_value miniffi_call_intern(MINIFFI_FUNC target, MiniFFIFuncArgs *p, int nparams) {
|
__attribute__((noinline))
|
||||||
|
mffi_value call_asm64(MINIFFI_FUNC target, MiniFFIFuncArgs *p, int nparams) {
|
||||||
mffi_value ret;
|
mffi_value ret;
|
||||||
void *old_rsp = 0;
|
void *old_rsp = 0;
|
||||||
asm volatile(INTEL_ASM
|
asm volatile(INTEL_ASM
|
||||||
|
|
||||||
"MiniFFI_call_asm:\n"
|
|
||||||
"mov [rdi], rsp\n"
|
"mov [rdi], rsp\n"
|
||||||
"test rbx, rbx\n"
|
"test rbx, rbx\n"
|
||||||
"jz mffi_call_void\n"
|
"jz mffi_call_void64\n"
|
||||||
|
|
||||||
"shl rbx, 2\n"
|
"shl rbx, 2\n"
|
||||||
"mov rcx, rbx\n"
|
"mov rcx, rbx\n"
|
||||||
|
|
||||||
"mffi_call_loop:\n"
|
"mffi_call_loop64:\n"
|
||||||
"sub rcx, 4\n"
|
"sub rcx, 4\n"
|
||||||
"mov rbx, [rsi+rcx]\n"
|
"mov rbx, [rsi+rcx]\n"
|
||||||
"push rbx\n"
|
"push rbx\n"
|
||||||
"test rcx, rcx\n"
|
"test rcx, rcx\n"
|
||||||
"jnz mffi_call_loop\n"
|
"jnz mffi_call_loop64\n"
|
||||||
|
|
||||||
"mffi_call_void:\n"
|
"mffi_call_void64:\n"
|
||||||
"call rdx\n"
|
"call rdx\n"
|
||||||
|
|
||||||
: "=a"(ret)
|
: "=a"(ret)
|
||||||
|
@ -92,4 +104,17 @@ mffi_value miniffi_call_intern(MINIFFI_FUNC target, MiniFFIFuncArgs *p, int npar
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
bool libIs64(const char *lib) {
|
||||||
|
LOADED_IMAGE *img = ImageLoad(lib, NULL);
|
||||||
|
|
||||||
|
// Just assume 32-bit for now
|
||||||
|
if (!img)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
IMAGE_NT_HEADERS *imgheaders = img->FileHeader;
|
||||||
|
bool ret = imgheaders->FileHeader->Machine != IMAGE_FILE_MACHINE_I386;
|
||||||
|
ImageUnload(img);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -23,4 +23,6 @@ typedef struct {
|
||||||
mffi_value params[MINIFFI_MAX_ARGS];
|
mffi_value params[MINIFFI_MAX_ARGS];
|
||||||
} MiniFFIFuncArgs;
|
} MiniFFIFuncArgs;
|
||||||
|
|
||||||
mffi_value miniffi_call_intern(MINIFFI_FUNC target, MiniFFIFuncArgs *p, int nparams);
|
mffi_value miniffi_call_intern(MINIFFI_FUNC target, MiniFFIFuncArgs *p, int nparams, bool is64);
|
||||||
|
|
||||||
|
bool libIs64(void *handle);
|
Loading…
Add table
Reference in a new issue