| 373 | // https://github.com/topjohnwu/Magisk/blob/master/native/src/zygisk/ptrace.cpp |
| 374 | |
| 375 | kitty_rp_call_t KittyTraceMgr::_callFunctionFrom(uintptr_t callerAddress, uintptr_t functionAddress, int nargs, ...) |
| 376 | { |
| 377 | if (!_attached || _pid <= 0 || functionAddress == 0) |
| 378 | return {KT_RP_CALL_FAILED, {0}}; |
| 379 | |
| 380 | user_regs_struct backup_regs, return_regs, tmp_regs; |
| 381 | memset(&backup_regs, 0, sizeof(backup_regs)); |
| 382 | memset(&return_regs, 0, sizeof(return_regs)); |
| 383 | memset(&tmp_regs, 0, sizeof(tmp_regs)); |
| 384 | |
| 385 | // backup current regs |
| 386 | if (!getRegs(&backup_regs)) |
| 387 | { |
| 388 | KITTY_LOGE("callFunction(%p): Failed, couldn't get regs.", (void *)functionAddress); |
| 389 | return {KT_RP_CALL_REGS_FAILED, {0}}; |
| 390 | } |
| 391 | |
| 392 | memcpy(&tmp_regs, &backup_regs, sizeof(backup_regs)); |
| 393 | |
| 394 | KT_REGS_ALIGN_STACK(backup_regs); |
| 395 | KT_REGS_ALIGN_STACK(tmp_regs); |
| 396 | KT_REGS_ALIGN_STACK(return_regs); |
| 397 | |
| 398 | KITTY_LOGD("callFunction(%p): Calling with %d args.", (void *)functionAddress, nargs); |
| 399 | |
| 400 | std::vector<uintptr_t> vargs(nargs, 0); |
| 401 | if (nargs > 0) |
| 402 | { |
| 403 | va_list vl; |
| 404 | va_start(vl, nargs); |
| 405 | for (int i = 0; i < nargs; i++) |
| 406 | { |
| 407 | vargs[i] = va_arg(vl, uintptr_t); |
| 408 | } |
| 409 | va_end(vl); |
| 410 | } |
| 411 | |
| 412 | // cleanup failure return |
| 413 | auto failure_return = [&](KT_RP_CALL_STATUS s = KT_RP_CALL_FAILED) -> kitty_rp_call_t { |
| 414 | KITTY_LOGE("callFunction(%p): Failed.", (void *)functionAddress); |
| 415 | if (_autoRestoreRegs) |
| 416 | setRegs(&backup_regs); |
| 417 | return {s, {0}}; |
| 418 | }; |
| 419 | |
| 420 | auto validate_ret = [this](const user_regs_struct ®s, uintptr_t return_addr) -> bool { |
| 421 | uintptr_t pc = regs.KT_REG_PC; |
| 422 | if (pc != return_addr) |
| 423 | { |
| 424 | #if defined(__arm__) |
| 425 | if (uintptr_t((intptr_t(pc) & ~1)) != uintptr_t((intptr_t(return_addr) & ~1))) |
| 426 | #elif defined(__i386__) || defined(__x86_64__) |
| 427 | if (pc < return_addr || pc > (return_addr + 7)) |
| 428 | #endif |
| 429 | { |
| 430 | siginfo_t si = {}; |
| 431 | getSignalInfo(&si); |
| 432 | return uintptr_t(si.si_addr) == return_addr; |
nothing calls this directly
no test coverage detected