void do_syscall(struct syscallrecord *rec) { struct syscallentry *entry; struct msg_syscallprep scmsg; struct childdata *child = this_child(); unsigned int call; init_msgchildhdr(&scmsg.hdr, SYSCALL_PREP, pids[child->num], child->num); scmsg.sequence_nr = child->op_nr; scmsg.nr = rec->nr; scmsg.is32bit = rec->do32bit; scmsg.a1 = rec->a1; scmsg.a2 = rec->a2; scmsg.a3 = rec->a3; scmsg.a4 = rec->a4; scmsg.a5 = rec->a5; scmsg.a6 = rec->a6; rec->tp = scmsg.hdr.tp; sendudp((char *) &scmsg, sizeof(scmsg)); call = rec->nr; entry = syscalls[call].entry; if (entry->flags & EXTRA_FORK) do_extrafork(rec); else /* common-case, do the syscall in this child process. */ __do_syscall(rec, BEFORE); /* timestamp again for when we returned */ clock_gettime(CLOCK_MONOTONIC, &rec->tp); }
int hal_syscall_handler(void) { int func, arg1, arg2, arg3, arg4; int err, res, sig; func = get_register(R7); arg1 = get_register(R8); arg2 = get_register(R9); arg3 = get_register(R10); arg4 = get_register(R11); if (func == SYS_interrupt) { // A console interrupt landed us here. // Invoke the debug agent so as to cause a SIGINT. return SIGINT; } if ((res = __do_syscall(func, arg1, arg2, arg3, arg4, &err, &sig)) != 0) { // Skip over trap instruction put_register(PC, get_register(PC)+4); put_register(R8, err); return sig; } return SIGTRAP; }
int hal_syscall_handler(void) { CYG_ADDRWORD func, arg1, arg2, arg3, arg4; CYG_ADDRWORD err; func = get_register(ER0); arg1 = get_register(ER1); arg2 = get_register(ER2); arg3 = get_register(ER3); arg4 = 0; if (func == SYS_interrupt) { // A console interrupt landed us here. // Invoke the debug agent so as to cause a SIGINT. return SIGINT; } if (__do_syscall(func, arg1, arg2, arg3, arg4, &err)) { put_register(D0, err); return 0; } return SIGTRAP; }
int hal_syscall_handler(void) { CYG_ADDRWORD func, arg1, arg2, arg3, arg4; CYG_ADDRWORD err, sig; func = get_register(EAX); arg1 = get_register(EBX); arg2 = get_register(ECX); arg3 = get_register(EDX); arg4 = 0; switch (func) { case 1: func = SYS_exit; break; case 3: func = SYS_read; break; case 4: func = SYS_write; break; case 37: func = SYS_kill; break; case 48: // install signal handler // FIXME! put_register(EAX, 0); return 0; case 184: // get program arguments // FIXME! *(int *)arg1 = 0; put_register(EAX, 0); return 0; default: return SIGTRAP; } if (func == SYS_exit) { // We want to stop in exit so that the user may poke around // to see why his app exited. return SIGTRAP; } if (__do_syscall(func, arg1, arg2, arg3, arg4, &err, &sig)) { put_register(EAX, err); return (int)sig; } return SIGTRAP; }
int hal_syscall_handler(void) { int func, arg1, arg2, arg3, arg4; int err, sig; func = get_register(R4); arg1 = get_register(R5); arg2 = get_register(R6); arg3 = get_register(R7); arg4 = *(unsigned int *)(get_register(SP)); switch (func) { case _shnewlib_SYS_read: func = SYS_read; break; case _shnewlib_SYS_write: func = SYS_write; break; case _shnewlib_SYS_open: func = SYS_open; break; case _shnewlib_SYS_close: func = SYS_close; break; case _shnewlib_SYS_lseek: func = SYS_lseek; break; case _shnewlib_SYS_utime: func = SYS_utime; default: return SIGTRAP; } if (func == SYS_interrupt) { // A console interrupt landed us here. // Invoke the debug agent so as to cause a SIGINT. return SIGINT; } if (__do_syscall(func, arg1, arg2, arg3, arg4, &err, &sig)) { // R0 is normally result register, but newlib's trap // code looks in R1 for the return value put_register(R1, err); return sig; } return SIGTRAP; }
int hal_syscall_handler(void) { CYG_ADDRWORD func, arg1, arg2, arg3, arg4; CYG_ADDRWORD err, sig; int retreg; target_register_t sr = get_register(REG_SR); if ((sr & CYGARC_SR_PM) == 0 || (sr & CYGARC_SR_BS) == 0) { // bank zero regs func = get_register(REG_B0R0); arg1 = get_register(REG_B0R1); arg2 = get_register(REG_B0R2); arg3 = get_register(REG_B0R3); arg4 = 0; retreg = REG_B0R0; } else { func = get_register(REG_B1R0); arg1 = get_register(REG_B1R1); arg2 = get_register(REG_B1R2); arg3 = get_register(REG_B1R3); retreg = REG_B1R0; } set_pc(get_pc()+2); if (func == SYS_exit) { // We want to stop in exit so that the user may poke around // to see why his app exited. return SIGTRAP; } if (func == SYS_interrupt) { // A console interrupt landed us here. // Invoke the debug agent so as to cause a SIGINT. return SIGINT; } if (__do_syscall(func, arg1, arg2, arg3, arg4, &err, &sig)) { put_register(retreg, err); return (int)sig; } return SIGTRAP; }
/* This is a special case for things like execve, which would replace our * child process with something unknown to us. We use a 'throwaway' process * to do the execve in, and let it run for a max of a second before we kill it */ static void do_extrafork(struct syscallrecord *rec) { pid_t pid = 0; pid_t extrapid; extrapid = fork(); if (extrapid == 0) { /* grand-child */ char childname[]="trinity-subchild"; prctl(PR_SET_NAME, (unsigned long) &childname); __do_syscall(rec, GOING_AWAY); /* if this was for eg. an successful execve, we should never get here. * if it failed though... */ _exit(EXIT_SUCCESS); } /* misc failure. */ if (extrapid == -1) { //debugf("Couldn't fork grandchild: %s\n", strerror(errno)); return; } /* small pause to let grandchild do some work. */ if (pid_alive(extrapid) == TRUE) usleep(100); /* We take the rec lock here even though we don't obviously use it. * The reason, is that the grandchild is using it. */ lock(&rec->lock); while (pid == 0) { int childstatus; pid = waitpid(extrapid, &childstatus, WUNTRACED | WCONTINUED | WNOHANG); if (pid_alive(extrapid) == TRUE) kill(extrapid, SIGKILL); usleep(1000); } unlock(&rec->lock); }