0

The title pretty much says it all. Looking for the Linux equivalent of cpu_set_syscall_retval() found in /usr/src/sys/amd64/amd64/vm_machdep.c. Not sure if there is even such a thing in Linux but I thought I'd ask anyway.

   cpu_set_syscall_retval(struct thread *td, int error)
   {
       switch (error) {
       case 0:
               td->td_frame->tf_rax = td->td_retval[0];
               td->td_frame->tf_rdx = td->td_retval[1];
               td->td_frame->tf_rflags &= ~PSL_C;
               break;

       case ERESTART:
               /*
                * Reconstruct pc, we know that 'syscall' is 2 bytes,
                * lcall $X,y is 7 bytes, int 0x80 is 2 bytes.
                * We saved this in tf_err.
                * %r10 (which was holding the value of %rcx) is restored
                * for the next iteration.
                * %r10 restore is only required for freebsd/amd64 processes,
                * but shall be innocent for any ia32 ABI.
                */
               td->td_frame->tf_rip -= td->td_frame->tf_err;
               td->td_frame->tf_r10 = td->td_frame->tf_rcx;
               break;

       case EJUSTRETURN:
               break;

       default:
               if (td->td_proc->p_sysent->sv_errsize) {
                       if (error >= td->td_proc->p_sysent->sv_errsize)
                               error = -1;     /* XXX */
                       else
                               error = td->td_proc->p_sysent->sv_errtbl[error];
               }
               td->td_frame->tf_rax = error;
               td->td_frame->tf_rflags |= PSL_C;
               break;
       }
}

1 Answers1

0

There's no way to do the equivalent in linux. The return value of system calls is propagated via return value from whatever functions are called internally to implement the function all the way back to user-mode. The general convention is that a non-negative return value means success and a negative value indicates an error (with the errno being the negated return value: for example, a "-2" indicates an error with an errno value of 2 [ENOENT]).

You could look up the stored register values that will be popped on return to user-mode and replace one of them (what the BSD code here is doing), but the critical one that contains the return value will just be overwritten by the normal return-from-system-call path anyway, just prior to returning to user mode.

Gil Hamilton
  • 11,973
  • 28
  • 51