Commit dc1ce18b authored by Richard Henderson's avatar Richard Henderson Committed by Laurent Vivier
Browse files

linux-user: Split out do_syscall1



There was supposed to be a single point of return for do_syscall
so that tracing works properly.  However, there are a few bugs
in that area.  It is significantly simpler to simply split out
an inner function to enforce this.

Reviewed-by: default avatarPhilippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: default avatarLaurent Vivier <laurent@vivier.eu>
Signed-off-by: default avatarRichard Henderson <richard.henderson@linaro.org>
Message-Id: <20180818190118.12911-3-richard.henderson@linaro.org>
Signed-off-by: default avatarLaurent Vivier <laurent@vivier.eu>
parent 8a85e5dd
Loading
Loading
Loading
Loading
+48 −29
Original line number Diff line number Diff line
@@ -8092,10 +8092,12 @@ static int host_to_target_cpu_mask(const unsigned long *host_mask,
    return 0;
}

/* do_syscall() should always have a single exit point at the end so
   that actions, such as logging of syscall results, can be performed.
   All errnos that do_syscall() returns must be -TARGET_<errcode>. */
abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
/* This is an internal helper for do_syscall so that it is easier
 * to have a single return point, so that actions, such as logging
 * of syscall results, can be performed.
 * All errnos that do_syscall() returns must be -TARGET_<errcode>.
 */
static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
                            abi_long arg2, abi_long arg3, abi_long arg4,
                            abi_long arg5, abi_long arg6, abi_long arg7,
                            abi_long arg8)
@@ -8113,25 +8115,6 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
#endif
    void *p;

#if defined(DEBUG_ERESTARTSYS)
    /* Debug-only code for exercising the syscall-restart code paths
     * in the per-architecture cpu main loops: restart every syscall
     * the guest makes once before letting it through.
     */
    {
        static int flag;

        flag = !flag;
        if (flag) {
            return -TARGET_ERESTARTSYS;
        }
    }
#endif

    trace_guest_user_syscall(cpu, num, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
    if(do_strace)
        print_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);

    switch(num) {
    case TARGET_NR_exit:
        /* In old applications this may be used to implement _exit(2).
@@ -12942,11 +12925,47 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
        break;
    }
fail:
    if(do_strace)
        print_syscall_ret(num, ret);
    trace_guest_user_syscall_ret(cpu, num, ret);
    return ret;
efault:
    ret = -TARGET_EFAULT;
    goto fail;
}

abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
                    abi_long arg2, abi_long arg3, abi_long arg4,
                    abi_long arg5, abi_long arg6, abi_long arg7,
                    abi_long arg8)
{
    CPUState *cpu = ENV_GET_CPU(cpu_env);
    abi_long ret;

#ifdef DEBUG_ERESTARTSYS
    /* Debug-only code for exercising the syscall-restart code paths
     * in the per-architecture cpu main loops: restart every syscall
     * the guest makes once before letting it through.
     */
    {
        static bool flag;
        flag = !flag;
        if (flag) {
            return -TARGET_ERESTARTSYS;
        }
    }
#endif

    trace_guest_user_syscall(cpu, num, arg1, arg2, arg3, arg4,
                             arg5, arg6, arg7, arg8);

    if (unlikely(do_strace)) {
        print_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
        ret = do_syscall1(cpu_env, num, arg1, arg2, arg3, arg4,
                          arg5, arg6, arg7, arg8);
        print_syscall_ret(num, ret);
    } else {
        ret = do_syscall1(cpu_env, num, arg1, arg2, arg3, arg4,
                          arg5, arg6, arg7, arg8);
    }

    trace_guest_user_syscall_ret(cpu, num, ret);
    return ret;
}