Skip to content

Commit

Permalink
cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
Kethen committed May 1, 2024
1 parent 7ff48f9 commit fa0eaeb
Showing 1 changed file with 143 additions and 154 deletions.
297 changes: 143 additions & 154 deletions Core/HLE/sceKernelInterrupt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
);
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;
}
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 (!processing_specifier) {
if (*c == '%') {
specifier = "%";
processing_specifier = true;
bytes_to_read = 0;
} else {
result.append(1, *c);
}
} else {
specifier.append(1, *c);

if(state == 0){
if(*c == '%'){
cur_fmt = "%";
state = 1;
bytes_to_read = 0;
}else{
result.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);
}
}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++;
arg_idx++;

if(!Memory::IsValidAddress(val)){
ERROR_LOG(SCEKERNEL, "sprintf, bad string reference %08x", val);
return 0;
}
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);
}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++;
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;
}
/*
// 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);
val_from_arg = Memory::Read_U32(stack_cur);
DEBUG_LOG(SCEKERNEL, "sysclib_sprintf fetching %08x from sp + %u", val_from_arg, stack_idx * 4);
}
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;
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();
} else {
// What to do? Crash, probably.
return 0;
}

// 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) {
Expand Down

0 comments on commit fa0eaeb

Please sign in to comment.