diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2023-10-08 11:55:18 +0200 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2023-10-08 11:55:18 +0200 |
| commit | 85d2a06f6f3ebff025a7ce7c38d79f62df949c37 (patch) | |
| tree | 1065b94d9f818a9448f38dc0129699f581310b58 /src | |
| parent | 8a5719afe1bf613af9a2ddd66191cc101ceca1bf (diff) | |
| download | box64-85d2a06f6f3ebff025a7ce7c38d79f62df949c37.tar.gz box64-85d2a06f6f3ebff025a7ce7c38d79f62df949c37.zip | |
[ARM64] Some handling of unaligned write to device memory
Diffstat (limited to 'src')
| -rw-r--r-- | src/libtools/signals.c | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/src/libtools/signals.c b/src/libtools/signals.c index 1a241283..b74918a9 100644 --- a/src/libtools/signals.c +++ b/src/libtools/signals.c @@ -553,6 +553,33 @@ void copyUCTXreg2Emu(x64emu_t* emu, ucontext_t* p, uintptr_t ip) { #endif } +int sigbus_specialcases(siginfo_t* info, void * ucntx, void* pc) +{ + if((uintptr_t)pc<0x10000) + return 0; +#ifdef ARM64 + ucontext_t *p = (ucontext_t *)ucntx; + uint32_t opcode = *(uint32_t*)pc; + //printf_log(LOG_INFO, "Checking SIGBUS special casses with pc=%p, opcode=%x\n", pc, opcode); + if((opcode&0b10111000000000000000000000000000) == 0b10111000000000000000000000000000) { + // this is a STUR that SEGBUS if accessing unaligned device memory + int size = 1<<((opcode>>30)&3); + int val = opcode&31; + int dest = (opcode>>5)&31; + int64_t offset = (opcode>>12)&0b111111111; + if((offset>>(9-1))&1) + offset |= (0xffffffffffffffffll<<9); + uint8_t* addr = (uint8_t*)(p->uc_mcontext.regs[dest] + offset); + uint64_t value = p->uc_mcontext.regs[val]; + for(int i=0; i<size; ++i) + addr[i] = (value>>(i*8))&0xff; + p->uc_mcontext.pc+=4; // go to next opcode + return 1; + } +#endif + return 0; +} + void my_sigactionhandler_oldcode(int32_t sig, int simple, siginfo_t* info, void * ucntx, int* old_code, void* cur_db) { int Locks = unlockMutex(); @@ -969,6 +996,11 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx) void * pc = NULL; // unknow arch... #warning Unhandled architecture #endif + if((sig==SIGBUS) && (addr!=pc) && sigbus_specialcases(info, ucntx, pc)) { + // special case fixed, restore everything and just continues + printf_log(LOG_DEBUG, "Special unalinged cased fixed, continue"); + return; + } int Locks = unlockMutex(); uint32_t prot = getProtection((uintptr_t)addr); #ifdef BAD_SIGNAL |