diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_00.c | 4 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_helper.c | 3 | ||||
| -rw-r--r-- | src/tools/bridge.c | 37 |
3 files changed, 40 insertions, 4 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_00.c b/src/dynarec/arm64/dynarec_arm64_00.c index c78e4f74..443d497d 100644 --- a/src/dynarec/arm64/dynarec_arm64_00.c +++ b/src/dynarec/arm64/dynarec_arm64_00.c @@ -2602,7 +2602,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin x87_purgecache(dyn, ninst, 0, x3, x1, x4); if ((BOX64ENV(log)<2 && !BOX64ENV(rolling_log) && !BOX64ENV(dynarec_test)) && tmp) { //GETIP(ip+3+8+8); // read the 0xCC - call_n(dyn, ninst, *(void**)(addr+8), tmp); + call_n(dyn, ninst, (void*)(addr+8), tmp); addr+=8+8; } else { GETIP(ip+1); // read the 0xCC @@ -3395,7 +3395,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin x87_purgecache(dyn, ninst, 0, x3, x1, x4); if ((BOX64ENV(log)<2 && !BOX64ENV(rolling_log)) && dyn->insts[ninst].natcall && tmp) { //GETIP(ip+3+8+8); // read the 0xCC - call_n(dyn, ninst, *(void**)(dyn->insts[ninst].natcall+2+8), tmp); + call_n(dyn, ninst, (void*)(dyn->insts[ninst].natcall+2+8), tmp); SMWRITE2(); POP1(xRIP); // pop the return address dyn->last_ip = addr; diff --git a/src/dynarec/arm64/dynarec_arm64_helper.c b/src/dynarec/arm64/dynarec_arm64_helper.c index 12274e44..092452d2 100644 --- a/src/dynarec/arm64/dynarec_arm64_helper.c +++ b/src/dynarec/arm64/dynarec_arm64_helper.c @@ -879,7 +879,8 @@ void call_n(dynarec_arm_t* dyn, int ninst, void* fnc, int w) MOVx_REG(x4, xR8); MOVx_REG(x5, xR9); // native call - TABLE64(16, (uintptr_t)fnc); // using x16 as scratch regs for call address + // fnc is indirect, to help with relocation (but PltResolver might be an issue here) + TABLE64(16, *(uintptr_t*)fnc); // using x16 as scratch regs for call address BLR(16); // put return value in x64 regs if(w>0) { diff --git a/src/tools/bridge.c b/src/tools/bridge.c index e9669fa2..60b6024a 100644 --- a/src/tools/bridge.c +++ b/src/tools/bridge.c @@ -21,6 +21,9 @@ #ifdef DYNAREC #include "dynablock.h" #endif +#ifdef BOX32 +#include "box32context.h" +#endif KHASH_MAP_INIT_INT64(bridgemap, uintptr_t) @@ -258,10 +261,42 @@ void fini_bridge_helper() cleanAlternate(); } +#ifdef BOX32 +int isNativeCall32(uintptr_t addr, uintptr_t* calladdress, uint16_t* retn) +{ +#define PK(a) *(uint8_t*)(addr+a) +#define PK32(a) *(uint32_t*)(addr+a) + + if(!addr || !getProtection(addr)) + return 0; + if(PK(0)==0xff && PK(1)==0x25) { // absolute jump, maybe the GOT + ptr_t a1 = (PK32(2)); // need to add a check to see if the address is from the GOT ! + addr = (uintptr_t)getAlternate(from_ptrv(a1)); + } + if(addr<0x10000 || !getProtection(addr)) // too low, that is suspicious + return 0; + onebridge_t *b = (onebridge_t*)(addr); + if(b->CC==0xCC && b->S=='S' && b->C=='C' && b->w!=(wrapper_t)0 && b->f!=(uintptr_t)PltResolver32) { + // found ! + if(retn) *retn = (b->C3==0xC2)?b->N:0; + if(calladdress) *calladdress = addr+1; + return 1; + } + return 0; +#undef PK32 +#undef PK +} +#else +int isNativeCall32(uintptr_t addr, uintptr_t* calladdress, int* retn) +{ + return 0; +} +#endif + int isNativeCallInternal(uintptr_t addr, int is32bits, uintptr_t* calladdress, uint16_t* retn) { if (is32bits) - addr &= 0xFFFFFFFFLL; + return isNativeCall32(addr, calladdress, retn); #define PK(a) *(uint8_t*)(addr + a) #define PK32(a) *(int32_t*)(addr + a) |