From fa0eaebfb51e21dc890db0e8fef485833fda7c45 Mon Sep 17 00:00:00 2001 From: Katharine Chui Date: Wed, 1 May 2024 01:41:57 +0800 Subject: [PATCH] cleanup --- Core/HLE/sceKernelInterrupt.cpp | 315 +++++++++++++++----------------- 1 file changed, 152 insertions(+), 163 deletions(-) diff --git a/Core/HLE/sceKernelInterrupt.cpp b/Core/HLE/sceKernelInterrupt.cpp index e1acceddf3..72596e6ceb 100644 --- a/Core/HLE/sceKernelInterrupt.cpp +++ b/Core/HLE/sceKernelInterrupt.cpp @@ -743,172 +743,161 @@ static int sysclib_memcmp(u32 dst, u32 src, u32 size) { static int sysclib_sprintf(u32 dst, u32 fmt) { ERROR_LOG(SCEKERNEL, "Untested sysclib_sprintf(dst=%08x, fmt=%08x)", dst, fmt); - if (Memory::IsValidAddress(dst) && Memory::IsValidAddress(fmt)) { - - - u32 psp_stack_pointer = currentMIPS->r[MIPS_REG_SP]; - ERROR_LOG(SCEKERNEL, "Fmt: %s", Memory::GetCharPointerUnchecked(fmt)); - ERROR_LOG(SCEKERNEL, "PSP arg reg dump: 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x", - currentMIPS->r[MIPS_REG_A0], - currentMIPS->r[MIPS_REG_A1], - currentMIPS->r[MIPS_REG_A2], - currentMIPS->r[MIPS_REG_A3], - currentMIPS->r[MIPS_REG_T0], - currentMIPS->r[MIPS_REG_T1], - currentMIPS->r[MIPS_REG_T2], - currentMIPS->r[MIPS_REG_T3] - ); - for(int i = 0;i < 24; i+=8){ - u32 base = psp_stack_pointer + i * 4; - ERROR_LOG(SCEKERNEL, "PSP stack dump: 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x", - Memory::Read_U32(base), - Memory::Read_U32(base + 1 * 4), - Memory::Read_U32(base + 2 * 4), - Memory::Read_U32(base + 3 * 4), - Memory::Read_U32(base + 4 * 4), - Memory::Read_U32(base + 5 * 4), - Memory::Read_U32(base + 6 * 4), - Memory::Read_U32(base + 7 * 4) - ); - } - int state = 0; - std::string result = ""; - std::string cur_fmt = ""; - int bytes_to_read = 0; - int arg_idx = 0; - int fmt_len = 0; - - for(const char *c = Memory::GetCharPointerUnchecked(fmt); *c != '\0'; c++){ - // in case we have a bad fmt string, try not to crash the whole emulator - fmt_len++; - if(fmt_len == 1024){ - ERROR_LOG(SCEKERNEL, "sprintf, fmt is longer than 1024"); - return 0; - } - - if(state == 0){ - if(*c == '%'){ - cur_fmt = "%"; - state = 1; - bytes_to_read = 0; - }else{ - result.append(1, *c); - } - }else{ - cur_fmt.append(1, *c); - - // going by https://cplusplus.com/reference/cstdio/printf/#compatibility - // no idea what the kernel module really supports as of writing this - - if(*c == '%'){ - result.append(cur_fmt); - state = 0; - }else if(*c == 'd' || - *c == 'i' || - *c == 'u' || - *c == 'o' || - *c == 'x' || - *c == 'X' || - *c == 'f' || - *c == 'e' || - *c == 'E' || - *c == 'g' || - *c == 'G' || - *c == 'c' || - *c == 'p' || - *c == 'n' || - *c == 's' - ){ - // we have a format ending - if(*c == 's'){ - // consume 4 bytes from arguments - u32 val = 0; - if(arg_idx <= 1){ - val = currentMIPS->r[MIPS_REG_A2 + arg_idx]; - }else if(arg_idx <= 5){ - val = currentMIPS->r[MIPS_REG_T0 + arg_idx - 2]; - }else{ - // XXX assuming right to left arg pushing - int stack_idx = arg_idx - 6; - u32 stack_cur = psp_stack_pointer + stack_idx * 4; - - if(!Memory::IsValidAddress(stack_cur)){ - ERROR_LOG(SCEKERNEL, "sprintf, bad stack pointer %08x", stack_cur); - return 0; - } - val = Memory::Read_U32(stack_cur); - } - arg_idx++; - - if(!Memory::IsValidAddress(val)){ - ERROR_LOG(SCEKERNEL, "sprintf, bad string reference %08x", val); - return 0; - } - - const char *str = Memory::GetCharPointerUnchecked(val); - // limit the string length and hope that we don't crash on a bad string reference - char buf[1024] = {0}; - strncpy(buf, str, sizeof(buf)); - buf[sizeof(buf) - 1] = '\0'; - result.append(buf); - }else{ - u64 val = 0; - if(bytes_to_read == 0){ - bytes_to_read = 4; - } - int read_cnt = 0; - while(bytes_to_read != 0){ - u64 val_from_arg = 0; - if(arg_idx <= 1){ - val_from_arg = currentMIPS->r[MIPS_REG_A2 + arg_idx]; - }else if(arg_idx <= 5){ - val_from_arg = currentMIPS->r[MIPS_REG_T0 + arg_idx - 2]; - }else{ - // XXX assuming right to left arg pushing - int stack_idx = arg_idx - 6; - u32 stack_cur = psp_stack_pointer + stack_idx * 4; - - if(!Memory::IsValidAddress(stack_cur)){ - ERROR_LOG(SCEKERNEL, "sprintf, bad stack pointer %08x", stack_cur); - return 0; - } - val_from_arg = Memory::Read_U32(stack_cur); - } - arg_idx++; - - val = val | (val_from_arg << (read_cnt * 32)); - - bytes_to_read = bytes_to_read - 4; - read_cnt++; - } - /* - // windows compiler don't like this - int space_needed = snprintf(nullptr, 0, cur_fmt.c_str(), val); - char buf[space_needed + 1]; - sprintf(buf, cur_fmt.c_str(), val); - */ - char buf[1024] = {0}; - snprintf(buf, sizeof(buf), cur_fmt.c_str(), val); - buf[sizeof(buf) - 1] = '\0'; - result.append(buf); - } - state = 0; - }else if(*c == 'h'){ - // allegrex calling convention is 4 bytes aligned - bytes_to_read = 4; - }else if(*c == 'l'){ - bytes_to_read = bytes_to_read + 4; - } - } - } - - // if a small buffer was allocated by the program, we will likely crash - strcpy((char *)Memory::GetPointerUnchecked(dst), result.c_str()); - return result.length(); - } else { + if (!Memory::IsValidAddress(dst) || !Memory::IsValidAddress(fmt)) { // What to do? Crash, probably. return 0; } + + DEBUG_LOG(SCEKERNEL, "sysclib_sprintf fmt: %s", Memory::GetCharPointerUnchecked(fmt)); + DEBUG_LOG(SCEKERNEL, "sysclib_sprintf a0-a4, t0-t4: 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x", + currentMIPS->r[MIPS_REG_A0], + currentMIPS->r[MIPS_REG_A1], + currentMIPS->r[MIPS_REG_A2], + currentMIPS->r[MIPS_REG_A3], + currentMIPS->r[MIPS_REG_T0], + currentMIPS->r[MIPS_REG_T1], + currentMIPS->r[MIPS_REG_T2], + currentMIPS->r[MIPS_REG_T3] + ); + + bool processing_specifier = false; + std::string specifier = ""; + int bytes_to_read = 0; + int arg_idx = 0; + int fmt_len = 0; + std::string result = ""; + for (const char *c = Memory::GetCharPointerUnchecked(fmt); *c != '\0'; c++) { + // in case we have a bad fmt string, try not to crash the whole emulator + fmt_len++; + if (fmt_len == 1024) { + ERROR_LOG(SCEKERNEL, "sysclib_sprintf fmt is longer than 1024"); + return 0; + } + + if (!processing_specifier) { + if (*c == '%') { + specifier = "%"; + processing_specifier = true; + bytes_to_read = 0; + } else { + result.append(1, *c); + } + } else { + specifier.append(1, *c); + + // going by https://cplusplus.com/reference/cstdio/printf/#compatibility + // no idea what the kernel module really supports as of writing this + switch (*c) { + case '%': + { + result.append(specifier); + processing_specifier = false; + break; + } + case 's': + { + // consume 4 bytes from arguments + u32 val = 0; + if (arg_idx <= 1) { + val = currentMIPS->r[MIPS_REG_A2 + arg_idx]; + } else if(arg_idx <= 5) { + val = currentMIPS->r[MIPS_REG_T0 + arg_idx - 2]; + } else { + int stack_idx = arg_idx - 6; + u32 stack_cur = currentMIPS->r[MIPS_REG_SP] + stack_idx * 4; + + if (!Memory::IsValidAddress(stack_cur)) { + ERROR_LOG(SCEKERNEL, "sysclib_sprintf bad stack pointer %08x", stack_cur); + return 0; + } + val = Memory::Read_U32(stack_cur); + DEBUG_LOG(SCEKERNEL, "sysclib_sprintf fetching %08x from sp + %u", val, stack_idx * 4); + } + arg_idx++; + + if (!Memory::IsValidAddress(val)) { + ERROR_LOG(SCEKERNEL, "sysclib_sprintf bad string reference %08x", val); + return 0; + } + + const char *str = Memory::GetCharPointerUnchecked(val); + // limit the string length and hope that we don't crash on a bad string reference + char buf[1024] = {0}; + strncpy(buf, str, sizeof(buf)); + buf[sizeof(buf) - 1] = '\0'; + result.append(buf); + processing_specifier = false; + break; + } + case 'd': + case 'i': + case 'u': + case 'o': + case 'x': + case 'X': + case 'f': + case 'e': + case 'E': + case 'g': + case 'G': + case 'c': + case 'p': + case 'n': + { + u64 val = 0; + if (bytes_to_read == 0) { + bytes_to_read = 4; + } + int read_cnt = 0; + while (bytes_to_read != 0) { + u32 val_from_arg = 0; + if (arg_idx <= 1) { + val_from_arg = currentMIPS->r[MIPS_REG_A2 + arg_idx]; + } else if (arg_idx <= 5) { + val_from_arg = currentMIPS->r[MIPS_REG_T0 + arg_idx - 2]; + } else { + int stack_idx = arg_idx - 6; + u32 stack_cur = currentMIPS->r[MIPS_REG_SP] + stack_idx * 4; + + if (!Memory::IsValidAddress(stack_cur)) { + ERROR_LOG(SCEKERNEL, "sysclib_sprintf bad stack pointer %08x", stack_cur); + return 0; + } + val_from_arg = Memory::Read_U32(stack_cur); + DEBUG_LOG(SCEKERNEL, "sysclib_sprintf fetching %08x from sp + %u", val_from_arg, stack_idx * 4); + } + arg_idx++; + + val = val | ((u64)val_from_arg << (read_cnt * 32)); + + bytes_to_read = bytes_to_read - 4; + read_cnt++; + } + char buf[1024] = {0}; + snprintf(buf, sizeof(buf), specifier.c_str(), val); + buf[sizeof(buf) - 1] = '\0'; + result.append(buf); + processing_specifier = false; + break; + } + case 'h': + { + // allegrex calling convention is 4 bytes aligned + bytes_to_read = 4; + break; + } + case 'l': + { + bytes_to_read = bytes_to_read + 4; + break; + } + } + } + } + + // if a small buffer was allocated by the program, we will likely crash + strcpy((char *)Memory::GetPointerUnchecked(dst), result.c_str()); + return result.length(); } static u32 sysclib_memset(u32 destAddr, int data, int size) {