mirror of
https://github.com/Pharaoh2k/ps5debug-NG.git
synced 2026-10-21 11:23:27 -05:00
The variadic __crt_syscall reads each argument as a 64-bit long; a bare int (e.g. the -1 mmap fd) leaves the upper 32 bits undefined and can fail call-site-dependently. Route the remaining bare sites through the typed ps5debug_syscall wrapper (behavior-preserving): net.c select(93), debug.c wait4(7), proc_remote.c ptrace(26) + wait4(7), installer find_pid.c sysctl(202), installer proc_remote.c ptrace(26).
560 lines
17 KiB
C
560 lines
17 KiB
C
// SPDX-License-Identifier: GPL-3.0-only
|
|
|
|
#include "protocol.h"
|
|
#include "sdk_shim.h"
|
|
#include "proc.h"
|
|
#include "kern_rw_fast.h"
|
|
#include "debug_state.h"
|
|
|
|
#include <stdarg.h>
|
|
#include <sys/mman.h>
|
|
#include <sys/wait.h>
|
|
|
|
#define PCRK_SIZEOF_REG 0xb0
|
|
#define PCRK_R_R10 0x28
|
|
#define PCRK_R_R9 0x30
|
|
#define PCRK_R_R8 0x38
|
|
#define PCRK_R_RDI 0x40
|
|
#define PCRK_R_RSI 0x48
|
|
#define PCRK_R_RDX 0x60
|
|
#define PCRK_R_RCX 0x68
|
|
#define PCRK_R_RAX 0x70
|
|
#define PCRK_R_RIP 0x88
|
|
#define PCRK_R_RSP 0xa0
|
|
|
|
#define NID_LIBKERNEL_SYSCALL "W0xkN0+ZkCE"
|
|
|
|
static void *g_server_mutex = (void *)0;
|
|
static int g_server_mutex_init_done = 0;
|
|
|
|
static void mutex_lock(void) {
|
|
if (!g_server_mutex_init_done) {
|
|
scePthreadMutexInit(&g_server_mutex, (void *)0, "proc_remote");
|
|
g_server_mutex_init_done = 1;
|
|
}
|
|
scePthreadMutexLock(&g_server_mutex);
|
|
}
|
|
static void mutex_unlock(void) { scePthreadMutexUnlock(&g_server_mutex); }
|
|
static void debugger_usleep(unsigned long us) { sceKernelUsleep((unsigned int)us); }
|
|
|
|
extern long __crt_syscall(long sysno, ...);
|
|
|
|
long ptrace_raw(int op, int pid, void *addr, int data) {
|
|
// ps5debug_syscall promotes op/pid/data (int) + addr (pointer) to long at the
|
|
// typed parameter boundary -> no undefined upper bits. Same syscall, same args.
|
|
return ps5debug_syscall(26 /*ptrace*/, (long)op, (long)pid, (long)addr, (long)data, 0L, 0L);
|
|
}
|
|
|
|
#if 0
|
|
extern int sceKernelSendNotificationRequest(int unused, void *req,
|
|
size_t reqsz, int flag);
|
|
|
|
static void caveat4_diag(int self_pid) {
|
|
char buf[1024];
|
|
uint8_t sdk_caps [16] = {0};
|
|
uint8_t fast_caps[16] = {0};
|
|
|
|
intptr_t sdk_kproc = kernel_get_proc(self_pid);
|
|
intptr_t fast_kproc = kernel_get_proc_fast(self_pid);
|
|
|
|
intptr_t sdk_ucred = kernel_get_proc_ucred(self_pid);
|
|
intptr_t fast_ucred = kernel_get_proc_ucred_fast(self_pid);
|
|
|
|
uint64_t sdk_authid = kernel_get_ucred_authid(self_pid);
|
|
uint64_t fast_authid = kernel_get_ucred_authid_fast(self_pid);
|
|
|
|
int sdk_caps_rc = kernel_get_ucred_caps(self_pid, sdk_caps);
|
|
int fast_caps_rc = kernel_get_ucred_caps_fast(self_pid, fast_caps);
|
|
|
|
uint64_t saved_authid = fast_authid;
|
|
uint8_t saved_caps[16];
|
|
memcpy(saved_caps, fast_caps, 16);
|
|
|
|
uint8_t all_ones[16];
|
|
memset(all_ones, 0xFF, 16);
|
|
|
|
int set_authid_rc = kernel_set_ucred_authid_fast(self_pid, 0x4800000000010003ULL);
|
|
|
|
uint64_t authid_after_set = kernel_get_ucred_authid_fast(self_pid);
|
|
|
|
uint64_t sdk_authid_after = kernel_get_ucred_authid(self_pid);
|
|
|
|
int set_caps_rc = kernel_set_ucred_caps_fast(self_pid, all_ones);
|
|
uint8_t caps_after_set[16] = {0};
|
|
kernel_get_ucred_caps_fast(self_pid, caps_after_set);
|
|
|
|
int restore_authid_rc = kernel_set_ucred_authid_fast(self_pid, saved_authid);
|
|
int restore_caps_rc = kernel_set_ucred_caps_fast(self_pid, saved_caps);
|
|
|
|
uint64_t authid_after_restore = kernel_get_ucred_authid_fast(self_pid);
|
|
uint8_t caps_after_restore[16] = {0};
|
|
kernel_get_ucred_caps_fast(self_pid, caps_after_restore);
|
|
|
|
int snlen = snprintf(buf, sizeof(buf),
|
|
"C4-DIAG pid=%d\n"
|
|
"READ kproc: SDK=%lx FAST=%lx %s\n"
|
|
"READ ucred: SDK=%lx FAST=%lx %s\n"
|
|
"READ authid: SDK=%lx FAST=%lx %s\n"
|
|
"READ caps: SDK rc=%d %02x%02x%02x%02x%02x%02x%02x%02x\n"
|
|
" FAST rc=%d %02x%02x%02x%02x%02x%02x%02x%02x %s\n"
|
|
"WRITE set_authid(debug) FAST rc=%d after_FAST=%lx after_SDK=%lx\n"
|
|
"WRITE set_caps(0xFF*16) FAST rc=%d after_caps=%02x%02x%02x%02x%02x%02x%02x%02x\n"
|
|
"RESTORE set_authid(saved) FAST rc=%d\n"
|
|
"RESTORE set_caps(saved) FAST rc=%d\n"
|
|
"VERIFY authid: %lx %s\n"
|
|
"VERIFY caps : %02x%02x%02x%02x%02x%02x%02x%02x %s\n",
|
|
self_pid,
|
|
(unsigned long)sdk_kproc, (unsigned long)fast_kproc,
|
|
(sdk_kproc == fast_kproc) ? "MATCH" : "DIFFER",
|
|
(unsigned long)sdk_ucred, (unsigned long)fast_ucred,
|
|
(sdk_ucred == fast_ucred) ? "MATCH" : "DIFFER",
|
|
(unsigned long)sdk_authid, (unsigned long)fast_authid,
|
|
(sdk_authid == fast_authid) ? "MATCH" : "DIFFER",
|
|
sdk_caps_rc,
|
|
sdk_caps[0], sdk_caps[1], sdk_caps[2], sdk_caps[3],
|
|
sdk_caps[4], sdk_caps[5], sdk_caps[6], sdk_caps[7],
|
|
fast_caps_rc,
|
|
fast_caps[0], fast_caps[1], fast_caps[2], fast_caps[3],
|
|
fast_caps[4], fast_caps[5], fast_caps[6], fast_caps[7],
|
|
(memcmp(sdk_caps, fast_caps, 16) == 0) ? "MATCH" : "DIFFER",
|
|
set_authid_rc, (unsigned long)authid_after_set, (unsigned long)sdk_authid_after,
|
|
set_caps_rc,
|
|
caps_after_set[0], caps_after_set[1], caps_after_set[2], caps_after_set[3],
|
|
caps_after_set[4], caps_after_set[5], caps_after_set[6], caps_after_set[7],
|
|
restore_authid_rc, restore_caps_rc,
|
|
(unsigned long)authid_after_restore,
|
|
(authid_after_restore == saved_authid) ? "OK" : "BAD",
|
|
caps_after_restore[0], caps_after_restore[1], caps_after_restore[2], caps_after_restore[3],
|
|
caps_after_restore[4], caps_after_restore[5], caps_after_restore[6], caps_after_restore[7],
|
|
(memcmp(caps_after_restore, saved_caps, 16) == 0) ? "OK" : "BAD");
|
|
(void)snlen;
|
|
|
|
klog_puts(buf);
|
|
typedef struct { char useless1[45]; char message[3075]; } req_t;
|
|
req_t req;
|
|
memset(&req, 0, sizeof(req));
|
|
strncpy(req.message, buf, sizeof(req.message) - 1);
|
|
sceKernelSendNotificationRequest(0, &req, sizeof(req), 0);
|
|
}
|
|
|
|
}
|
|
#endif
|
|
|
|
int elev_save_and_set(struct elev_state *st) {
|
|
int self = getpid();
|
|
st->valid = 0;
|
|
st->saved_authid = kernel_get_ucred_authid_fast(self);
|
|
if (st->saved_authid == 0) return -1;
|
|
if (kernel_get_ucred_caps_fast(self, st->saved_caps) != 0) return -1;
|
|
if (kernel_set_ucred_authid_fast(self, 0x4800000000010003ULL) != 0) return -1;
|
|
uint8_t all_ones[16];
|
|
memset(all_ones, 0xFF, 16);
|
|
if (kernel_set_ucred_caps_fast(self, all_ones) != 0) {
|
|
kernel_set_ucred_authid_fast(self, st->saved_authid);
|
|
return -1;
|
|
}
|
|
st->valid = 1;
|
|
return 0;
|
|
}
|
|
|
|
void elev_restore(struct elev_state *st) {
|
|
if (!st->valid) return;
|
|
int self = getpid();
|
|
kernel_set_ucred_authid_fast(self, st->saved_authid);
|
|
kernel_set_ucred_caps_fast(self, st->saved_caps);
|
|
st->valid = 0;
|
|
}
|
|
|
|
long ptrace_elev(int op, int pid, void *addr, int data) {
|
|
struct elev_state es;
|
|
if (elev_save_and_set(&es) != 0) return -1;
|
|
long rc = ptrace_raw(op, pid, addr, data);
|
|
elev_restore(&es);
|
|
return rc;
|
|
}
|
|
|
|
int kern_ptrace_attach_and_wait(int pid)
|
|
{
|
|
if (ptrace_elev(0x0A , pid, 0, 0) == -1) return -1;
|
|
|
|
int status = 0;
|
|
if (wait4((pid_t)pid, &status, 0, NULL) == -1) {
|
|
sceKernelUsleep(20000);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int resume_app_via_self_id(int pid)
|
|
{
|
|
int app_id = 0;
|
|
int rc = _sceApplicationGetAppId(pid, &app_id);
|
|
if (rc != 0) return rc;
|
|
return sceApplicationContinue(app_id);
|
|
}
|
|
|
|
int pt_detach(int pid) {
|
|
return (ptrace_elev(0x0B , pid, 0, 0) == -1) ? -1 : 0;
|
|
}
|
|
|
|
extern void *curdbgctx;
|
|
struct dbgctx_pid { uint32_t pid; };
|
|
|
|
int proc_rpc_stop_target(int wpid)
|
|
{
|
|
struct dbgctx_pid *ctx = (struct dbgctx_pid *)curdbgctx;
|
|
uint32_t state = g_stopgo_last_signal;
|
|
int hit_second_kill = 0;
|
|
|
|
if (ctx != NULL) {
|
|
int target_pid = (int)ctx->pid;
|
|
if (state == 0x11 && g_stopgo_target_pid == (uint32_t)wpid) {
|
|
resume_app_via_self_id(wpid);
|
|
if (target_pid == wpid) {
|
|
ptrace_elev(7 , wpid, (void *)1, 0);
|
|
kill(wpid, 0x11 );
|
|
waitpid(wpid, NULL, 0);
|
|
return 0;
|
|
}
|
|
hit_second_kill = 1;
|
|
} else if (target_pid == wpid) {
|
|
|
|
kill(wpid, 0x11);
|
|
waitpid(wpid, NULL, 0);
|
|
return 0;
|
|
}
|
|
} else if (state == 0x11 && g_stopgo_target_pid == (uint32_t)wpid) {
|
|
resume_app_via_self_id(wpid);
|
|
hit_second_kill = 1;
|
|
}
|
|
|
|
if (hit_second_kill) {
|
|
kill(wpid, 0x13 );
|
|
waitpid(wpid, NULL, 0);
|
|
}
|
|
|
|
int rc = kern_ptrace_attach_and_wait(wpid);
|
|
return rc ? -1 : 0;
|
|
}
|
|
|
|
int proc_detach_or_stop(int pid)
|
|
{
|
|
struct dbgctx_pid *ctx = (struct dbgctx_pid *)curdbgctx;
|
|
uint32_t state = g_stopgo_last_signal;
|
|
|
|
if (ctx != NULL && (int)ctx->pid == pid) {
|
|
if (state == 0x11) {
|
|
uint32_t bound_pid = g_stopgo_target_pid;
|
|
resume_app_via_self_id(pid);
|
|
ptrace_elev(7 , pid, (void *)1, 0);
|
|
if (bound_pid != (uint32_t)pid) return 0;
|
|
kill(pid, 0x11);
|
|
waitpid(pid, NULL, 0);
|
|
return 0;
|
|
}
|
|
|
|
resume_app_via_self_id(pid);
|
|
ptrace_elev(7, pid, (void *)1, 0);
|
|
return 0;
|
|
}
|
|
|
|
if (state == 0x11) {
|
|
uint32_t bound_pid = g_stopgo_target_pid;
|
|
resume_app_via_self_id(pid);
|
|
int rc = pt_detach(pid);
|
|
if (rc != 0) return -1;
|
|
if (bound_pid == (uint32_t)pid) {
|
|
kill(pid, 0x11);
|
|
waitpid(pid, NULL, 0);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
resume_app_via_self_id(pid);
|
|
int rc = pt_detach(pid);
|
|
return rc ? -1 : 0;
|
|
}
|
|
|
|
__attribute__((noinline))
|
|
uint64_t proc_call_remote_kern(int pid, uint64_t func_addr, ...)
|
|
{
|
|
uint8_t saved_regs [PCRK_SIZEOF_REG];
|
|
uint8_t modified_regs[PCRK_SIZEOF_REG];
|
|
uint64_t kdata;
|
|
int status = 0;
|
|
|
|
void *proc = (void *)kernel_get_proc_fast(pid);
|
|
if (proc == 0) return (uint64_t)-1;
|
|
uint64_t kdata_u = kernel_dynlib_mapbase_addr_by_proc_fast(proc, 0x2001);
|
|
if (kdata_u == (uint64_t)-1 || kdata_u == 0) return (uint64_t)-1;
|
|
kdata = kdata_u;
|
|
|
|
if (ptrace_elev(0x21 , pid, saved_regs, 0) != 0)
|
|
return (uint64_t)-1;
|
|
|
|
memcpy(modified_regs, saved_regs, PCRK_SIZEOF_REG);
|
|
|
|
*(uint64_t *)(modified_regs + PCRK_R_RIP) = func_addr;
|
|
*(uint64_t *)(modified_regs + PCRK_R_RSP) -= 8;
|
|
|
|
{
|
|
va_list ap;
|
|
va_start(ap, func_addr);
|
|
*(uint64_t *)(modified_regs + PCRK_R_RDI) = va_arg(ap, uint64_t);
|
|
*(uint64_t *)(modified_regs + PCRK_R_RSI) = va_arg(ap, uint64_t);
|
|
*(uint64_t *)(modified_regs + PCRK_R_RDX) = va_arg(ap, uint64_t);
|
|
*(uint64_t *)(modified_regs + PCRK_R_RCX) = va_arg(ap, uint64_t);
|
|
*(uint64_t *)(modified_regs + PCRK_R_R8 ) = va_arg(ap, uint64_t);
|
|
*(uint64_t *)(modified_regs + PCRK_R_R9 ) = va_arg(ap, uint64_t);
|
|
va_end(ap);
|
|
}
|
|
|
|
if (ptrace_elev(0x22 , pid, modified_regs, 0) != 0)
|
|
return (uint64_t)-1;
|
|
|
|
{
|
|
uint64_t target_rsp = *(uint64_t *)(modified_regs + PCRK_R_RSP);
|
|
sys_proc_rw_w1((uint64_t)pid, target_rsp, 8, &kdata, 0);
|
|
}
|
|
|
|
ptrace_elev(7 , pid, (void *)1, 0);
|
|
waitpid(pid, &status, 0);
|
|
|
|
if (ptrace_elev(0x21 , pid, modified_regs, 0) != 0)
|
|
return (uint64_t)-1;
|
|
if (ptrace_elev(0x22 , pid, saved_regs, 0) != 0)
|
|
return (uint64_t)-1;
|
|
|
|
return *(uint64_t *)(modified_regs + PCRK_R_RAX);
|
|
}
|
|
|
|
__attribute__((noinline))
|
|
uint64_t proc_call_remote_sys(int pid, int sysno, ...)
|
|
{
|
|
uint8_t saved_regs [PCRK_SIZEOF_REG];
|
|
uint8_t modified_regs[PCRK_SIZEOF_REG];
|
|
|
|
uint64_t nid_addr = kernel_dynlib_resolve_fast(pid, 1, NID_LIBKERNEL_SYSCALL);
|
|
if (nid_addr == 0) {
|
|
nid_addr = kernel_dynlib_resolve_fast(pid, 0x2001, NID_LIBKERNEL_SYSCALL);
|
|
if (nid_addr == 0) return (uint64_t)-1;
|
|
}
|
|
|
|
int step_pid = pid;
|
|
int numlwps = (int)ptrace_elev(0x0E , pid, 0, 0);
|
|
if (numlwps > 0) {
|
|
int *lwp_buf = (int *)malloc((unsigned long)numlwps * 4u);
|
|
if (lwp_buf != 0) {
|
|
ptrace_elev(0x0F , pid, lwp_buf, numlwps);
|
|
step_pid = lwp_buf[0];
|
|
free(lwp_buf);
|
|
}
|
|
}
|
|
|
|
if (ptrace_elev(0x21 , pid, saved_regs, 0) != 0)
|
|
return (uint64_t)-1;
|
|
|
|
nid_addr += 0x0A;
|
|
memcpy(modified_regs, saved_regs, PCRK_SIZEOF_REG);
|
|
|
|
*(uint64_t *)(modified_regs + PCRK_R_RIP) = (uint64_t)nid_addr;
|
|
*(uint64_t *)(modified_regs + PCRK_R_RAX) = (uint64_t)(int64_t)sysno;
|
|
|
|
{
|
|
va_list ap;
|
|
va_start(ap, sysno);
|
|
*(uint64_t *)(modified_regs + PCRK_R_RDI) = va_arg(ap, uint64_t);
|
|
*(uint64_t *)(modified_regs + PCRK_R_RSI) = va_arg(ap, uint64_t);
|
|
*(uint64_t *)(modified_regs + PCRK_R_RDX) = va_arg(ap, uint64_t);
|
|
*(uint64_t *)(modified_regs + PCRK_R_R10) = va_arg(ap, uint64_t);
|
|
*(uint64_t *)(modified_regs + PCRK_R_R8 ) = va_arg(ap, uint64_t);
|
|
*(uint64_t *)(modified_regs + PCRK_R_R9 ) = va_arg(ap, uint64_t);
|
|
va_end(ap);
|
|
}
|
|
|
|
if (ptrace_elev(0x22 , pid, modified_regs, 0) != 0)
|
|
return (uint64_t)-1;
|
|
|
|
int success = (*(uint64_t *)(modified_regs + PCRK_R_RSP) >
|
|
*(uint64_t *)(saved_regs + PCRK_R_RSP));
|
|
|
|
for (int retry = 0; retry < 3 && !success; retry++) {
|
|
if (ptrace_elev(9 , step_pid, (void *)(uintptr_t)1, 0) != 0)
|
|
return (uint64_t)-1;
|
|
if ((int)waitpid(pid, 0, 0) < 0)
|
|
return (uint64_t)-1;
|
|
if (ptrace_elev(0x21, pid, modified_regs, 0) != 0)
|
|
return (uint64_t)-1;
|
|
success = (*(uint64_t *)(modified_regs + PCRK_R_RSP) >
|
|
*(uint64_t *)(saved_regs + PCRK_R_RSP));
|
|
}
|
|
if (!success) {
|
|
if (ptrace_elev(9, step_pid, (void *)(uintptr_t)1, 0) != 0)
|
|
return (uint64_t)-1;
|
|
if ((int)waitpid(pid, 0, 0) < 0)
|
|
return (uint64_t)-1;
|
|
if (ptrace_elev(0x21, pid, modified_regs, 0) != 0)
|
|
return (uint64_t)-1;
|
|
|
|
}
|
|
|
|
int set_rc = (int)ptrace_elev(0x22, pid, saved_regs, 0);
|
|
uint64_t result = success
|
|
? *(uint64_t *)(modified_regs + PCRK_R_RAX)
|
|
: (uint64_t)-1;
|
|
if (set_rc != 0) result = (uint64_t)-1;
|
|
return result;
|
|
}
|
|
|
|
void *freebsd_mmap(unsigned long pid, void *addr, unsigned long length,
|
|
int prot, int flags, int fd, long offset)
|
|
{
|
|
return (void *)proc_call_remote_sys(
|
|
(int)pid, 0x1DD, addr, length, prot, flags, fd, offset, 0L);
|
|
}
|
|
|
|
int freebsd_munmap(int pid, unsigned long addr, unsigned long len)
|
|
{
|
|
return (int)proc_call_remote_sys(pid, 0x49, addr, len);
|
|
}
|
|
|
|
int sys_proc_alloc(uint32_t pid, void **out_addr_ptr, uint64_t length)
|
|
{
|
|
length = (length + 0x3fffull) & ~0x3fffull;
|
|
if (out_addr_ptr == 0) return 1;
|
|
|
|
int my_pid = getpid();
|
|
|
|
if (my_pid == (int)pid) {
|
|
|
|
void *result = mmap(*out_addr_ptr, (size_t)length, 7, 0x1002, -1, 0);
|
|
*out_addr_ptr = result;
|
|
uint64_t a = (uint64_t)result - 1;
|
|
if (a > 0xfffffffffffffffdull) return -1;
|
|
return 0;
|
|
}
|
|
|
|
if (proc_rpc_stop_target((int)pid) != 0) return -1;
|
|
|
|
void *result = freebsd_mmap((unsigned long)pid, *out_addr_ptr,
|
|
(unsigned long)length, 7, 0x1002, -1, 0);
|
|
*out_addr_ptr = result;
|
|
|
|
if ((intptr_t)result != -1L) {
|
|
kernel_mprotect((pid_t)pid, (intptr_t)result, (size_t)length, 7);
|
|
}
|
|
|
|
if (proc_detach_or_stop((int)pid) != 0) return -1;
|
|
|
|
void *final = *out_addr_ptr;
|
|
uint64_t a = (uint64_t)final - 1;
|
|
if (a > 0xfffffffffffffffdull) return -1;
|
|
return 0;
|
|
}
|
|
|
|
int sys_proc_free(uint32_t pid, void *addr, uint64_t length)
|
|
{
|
|
length = (length + 0x3fffull) & ~0x3fffull;
|
|
if (addr == 0) return 1;
|
|
|
|
int my_pid = getpid();
|
|
if (my_pid == (int)pid) {
|
|
return munmap(addr, (size_t)length);
|
|
}
|
|
|
|
if (proc_rpc_stop_target((int)pid) != 0) return -1;
|
|
|
|
int rc = freebsd_munmap((int)pid, (unsigned long)(uintptr_t)addr,
|
|
(unsigned long)length);
|
|
|
|
if (proc_detach_or_stop((int)pid) != 0) return -1;
|
|
|
|
return (rc >= 0) ? rc : -1;
|
|
}
|
|
|
|
int sys_proc_call(int pid, struct sys_proc_call_args *args)
|
|
{
|
|
if (proc_rpc_stop_target(pid) != 0) return -1;
|
|
|
|
uint64_t ret = proc_call_remote_kern(
|
|
pid, args->rip,
|
|
args->rdi, args->rsi, args->rdx, args->rcx, args->r8, args->r9);
|
|
|
|
if (ret == (uint64_t)-1) {
|
|
proc_detach_or_stop(pid);
|
|
return -1;
|
|
}
|
|
|
|
args->rax = ret;
|
|
int rc = proc_detach_or_stop(pid);
|
|
return rc ? -1 : 0;
|
|
}
|
|
|
|
int proc_remote_alloc(uint32_t pid, uint64_t *out_addr,
|
|
uint64_t length, uint64_t hint)
|
|
{
|
|
mutex_lock();
|
|
|
|
void *p = (void *)(uintptr_t)hint;
|
|
int rc = sys_proc_alloc(pid, &p, length);
|
|
if (rc != 0) {
|
|
p = (void *)(uintptr_t)hint;
|
|
debugger_usleep(40000);
|
|
int retries = 100;
|
|
for (;;) {
|
|
rc = sys_proc_alloc(pid, &p, length);
|
|
if (rc == 0) break;
|
|
p = (void *)(uintptr_t)hint;
|
|
debugger_usleep(40000);
|
|
if (--retries == 0) {
|
|
mutex_unlock();
|
|
*out_addr = (uint64_t)(uintptr_t)p;
|
|
return rc;
|
|
}
|
|
}
|
|
}
|
|
|
|
mutex_unlock();
|
|
*out_addr = (uint64_t)(uintptr_t)p;
|
|
return 0;
|
|
}
|
|
|
|
int proc_remote_free(uint32_t pid, uint64_t addr, uint64_t length)
|
|
{
|
|
mutex_lock();
|
|
|
|
int rc = sys_proc_free(pid, (void *)(uintptr_t)addr, length);
|
|
if (rc < 0) {
|
|
int retries = 11;
|
|
do {
|
|
debugger_usleep(40000);
|
|
if (sys_proc_free(pid, (void *)(uintptr_t)addr, length) >= 0) {
|
|
rc = 0;
|
|
break;
|
|
}
|
|
} while (--retries > 0);
|
|
}
|
|
|
|
mutex_unlock();
|
|
return rc;
|
|
}
|
|
|
|
int proc_remote_call(int pid, struct sys_proc_call_args *args)
|
|
{
|
|
mutex_lock();
|
|
|
|
int rc = sys_proc_call(pid, args);
|
|
if (rc != 0) {
|
|
debugger_usleep(40000);
|
|
int retries = 6;
|
|
for (;;) {
|
|
rc = sys_proc_call(pid, args);
|
|
if (rc == 0) break;
|
|
debugger_usleep(40000);
|
|
if (--retries == 0) break;
|
|
}
|
|
}
|
|
|
|
mutex_unlock();
|
|
return rc;
|
|
}
|