--- nono/util/runx/runx.cpp 2026/04/29 17:05:27 1.1 +++ nono/util/runx/runx.cpp 2026/04/29 17:05:36 1.1.1.2 @@ -69,6 +69,7 @@ static uint32 loadfileR(); static void dumpwait(int); static void dumpreg(const struct reg *); static int run(uint32); +static int run_parent(int, int); int opt_debug; int opt_trace; @@ -246,23 +247,25 @@ loadfileX() while (reloc_pos < reloc_end) { uint32 D; D = be16toh(*(const uint16 *)&file[reloc_pos]); - DEBUG(2, "D=%x", D); + DEBUG(3, "%s: D=%x", __func__, D); reloc_pos += 2; if (D == 1) { D = be32toh(*(const uint32 *)&file[reloc_pos]); - DEBUG(2, " odd, D=%x", D); + DEBUG(3, "%s: odd, D=%x", __func__, D); reloc_pos += 4; } if ((D & 1) == 0) { A += D; uint32 old = readmem4(A); writemem4(A, old + C); - DEBUG(2, " Write_L A=%x, old=%x new=%x", A, old, old + C); + DEBUG(3, "%s: Write_L A=%x, old=%x new=%x", __func__, + A, old, old + C); } else { A += D - 1; uint32 old = readmem2(A); writemem2(A, old + C); - DEBUG(2, " Write_W A=%x, old=%x new=%x", A, old, old + C); + DEBUG(3, "%s: Write_W A=%x, old=%x new=%x", __func__, + A, old, old + C); } } munmap(file, st.st_size); @@ -473,130 +476,152 @@ run(uint32 exec_addr) func_t p = (func_t)boot_addr; r = p(); - exit(r); } else { /* parent */ - int status; - uint32 nextpc; + r = run_parent(pid, fd[1]); - DEBUG(1, "child pid=%u", pid); + kill(pid, SIGKILL); + } + exit(r); +} - if (ptrace(PT_ATTACH, pid, NULL, 0) < 0) { - err(1, "ptrace(PT_ATTACH)"); - } +// 親プロセス側。 +static int +run_parent(int pid, int wfd) +{ + int status; + uint32 nextpc; - // nextpc==1 は STOP した直後から再開、の意。 - nextpc = 1; + DEBUG(1, "child pid=%u", pid); - for (;;) { - r = wait(&status); - if (opt_debug >= 2) { - dumpwait(status); - } - if (WIFEXITED(status)) { - break; - } + if (ptrace(PT_ATTACH, pid, NULL, 0) < 0) { + warn("ptrace(PT_ATTACH)"); + return 1; + } - if (WIFSTOPPED(status)) { - struct reg regbuf; - struct reg *reg = ®buf; + // nextpc==1 は STOP した直後から再開、の意。 + nextpc = 1; - if (ptrace(PT_GETREGS, pid, reg, 0) < 0) { - err(1, "ptrace(PT_GETREGS)"); - } + for (;;) { + if (wait(&status) < 0) { + warn("wait"); + return 1; + } + if (opt_debug >= 2) { + dumpwait(status); + } + if (WIFEXITED(status)) { + break; + } - int signo = WSTOPSIG(status); + if (WIFSTOPPED(status)) { + struct reg regbuf; + struct reg *reg = ®buf; + + if (ptrace(PT_GETREGS, pid, reg, 0) < 0) { + warn("ptrace(PT_GETREGS)"); + return 1; + } - // PT_ATTACH が効くと SIGSTOP が来る。 - if (signo == SIGSTOP) { - // 準備が出来たので通知 (同期)。 - write(fd[1], "", 1); - DEBUG(1, "STOP -> Continue"); - } else if (signo == SIGILL || signo == SIGSEGV) { - // 特権違反命令や未実装命令は SIGILL、 - // メモリアクセス違反は SIGSEGV が飛んでくるが、 - // どちらも命令コードを調べて再実行するところは同じ。 - uint32 inst32; - errno = 0; - inst32 = ptrace(PT_READ_I, pid, (void *)RegPC, 0); - if (errno != 0) { - err(1, "ptrace(PT_READ_I)"); - } - if (opt_debug >= 2) { - dumpreg(reg); - } - DEBUG(2, "pc=%08x inst32=%08x", RegPC, inst32); - uint16 inst = inst32 >> 16; + int signo = WSTOPSIG(status); - if ((inst & 0xff00) == 0xff00) { - r = doscall(pid, (inst & 0xff), reg); - if (r == 1) { - nextpc = ret_addr; - goto next; - } - nextpc = RegPC + 2; - } else { - nextpc = exec_op(pid, reg, signo, inst); - if (nextpc == (uint32)-1) { - break; - } - } + // PT_ATTACH が効くと SIGSTOP が来る。 + if (signo == SIGSTOP) { + // 準備が出来たので通知 (同期)。 + write(wfd, "", 1); + DEBUG(1, "STOP -> Continue"); + } else if (signo == SIGILL || signo == SIGSEGV) { + // 特権違反命令や未実装命令は SIGILL、 + // メモリアクセス違反は SIGSEGV が飛んでくるが、 + // どちらも命令コードを調べて再実行するところは同じ。 + uint32 inst32; + errno = 0; + inst32 = ptrace(PT_READ_I, pid, (void *)RegPC, 0); + if (errno != 0) { + warn("ptrace(PT_READ_I)"); + return 1; + } + DEBUG(2, "pc=%08x inst32=%08x", RegPC, inst32); + if (opt_debug >= 2) { + dumpreg(reg); + } + uint16 inst = inst32 >> 16; - } else if (signo == SIGTRAP || signo == SIGFPE) { - // TRAP15 は SIGTRAP、CHK* 命令やゼロ除算は SIGFPE、と - // 本来別のシグナルが飛んで来るが - // どちらも同じ形式で処理できるのでまとめてある。 - struct ptrace_siginfo psi; - if (ptrace(PT_GET_SIGINFO, pid, &psi, sizeof(psi)) < 0) { - err(1, "ptrace(PT_GET_SIGINFO)"); - } - if (signo == SIGTRAP - && psi.psi_siginfo.si_code == TRAP_CHLD) { - // 子プロセス起動時にこちらが来る場合がある。 - // see kern_sig.c eventswitch() - DEBUG(1, "TRAP_CHLD"); + if ((inst & 0xff00) == 0xff00) { + if (doscall(pid, (inst & 0xff), reg) == 1) { + nextpc = ret_addr; goto next; } - switch (psi.psi_siginfo.si_trap) { - case T_ZERODIV: - TRACE(RegPC, "previous op issued T_ZERODIV"); - nextpc = exception_format2(reg, 5); - break; - case T_CHKINST: - TRACE(RegPC, "previous op issued T_CHKINST"); - nextpc = exception_format2(reg, 6); - break; - case T_TRAPVINST: - TRACE(RegPC, "previous op issued T_TRAPVINST"); - nextpc = exception_format2(reg, 7); - break; - case T_TRAP15: - iocscall(pid, reg); - // nextpc は更新されている。 + nextpc = RegPC + 2; + } else { + nextpc = exec_op(pid, reg, signo, inst); + if (nextpc == (uint32)-1) { break; - default: - errx(1, "%06x: Not implemented si_trap %d", - RegPC, psi.psi_siginfo.si_trap); } + } - } else { - errx(1, "%06x: Unknown signal %d", RegPC, signo); + } else if (signo == SIGTRAP || signo == SIGFPE) { + // TRAP15 は SIGTRAP、CHK* 命令やゼロ除算は SIGFPE、と + // 本来別のシグナルが飛んで来るが + // どちらも同じ形式で処理できるのでまとめてある。 + struct ptrace_siginfo psi; + if (ptrace(PT_GET_SIGINFO, pid, &psi, sizeof(psi)) < 0) { + warn("ptrace(PT_GET_SIGINFO)"); + return 1; + } + if (signo == SIGTRAP && psi.psi_siginfo.si_code == TRAP_CHLD) { + // 子プロセス起動時にこちらが来る場合がある。 + // see kern_sig.c eventswitch() + DEBUG(1, "TRAP_CHLD"); + goto next; } + switch (psi.psi_siginfo.si_trap) { + case T_ZERODIV: + TRACE(RegPC, "previous op issued T_ZERODIV"); + nextpc = exception_format2(reg, 5); + break; + case T_CHKINST: + TRACE(RegPC, "previous op issued T_CHKINST"); + nextpc = exception_format2(reg, 6); + break; + case T_TRAPVINST: + TRACE(RegPC, "previous op issued T_TRAPVINST"); + nextpc = exception_format2(reg, 7); + break; + case T_TRAP15: + iocscall(pid, reg); + // nextpc は更新されている。 + break; + case T_FPEMULD: + // FPE の Unsupported Data Type でこれが飛んでくるっぽいが + // とりあえず F ライン例外に落としておく。 + TRACE(RegPC, "previous op issued T_FPEMULD"); + nextpc = exception_format2(reg, 11); + break; + default: + warnx("%06x: Not implemented si_trap %d", + RegPC, psi.psi_siginfo.si_trap); + return 1; + } + + } else { + warnx("%06x: Unknown signal %d", RegPC, signo); + return 1; + } next: - if (ptrace(PT_SETREGS, pid, reg, 0) < 0) { - err(1, "ptrace(PT_SETREGS)"); - } + if (ptrace(PT_SETREGS, pid, reg, 0) < 0) { + warn("ptrace(PT_SETREGS)"); + return 1; + } - // 実行を再開し、次に何か起きるまで待つ。 - if (ptrace(PT_CONTINUE, pid, (void *)nextpc, 0) < 0) { - err(1, "PT_CONTINUE"); - } - nextpc = 1; + // 実行を再開し、次に何か起きるまで待つ。 + if (ptrace(PT_CONTINUE, pid, (void *)nextpc, 0) < 0) { + err(1, "PT_CONTINUE"); } + nextpc = 1; } } - kill(pid, SIGKILL); return 0; }