1 /*
2 * Copyright (c) 2015-2021 The strace developers.
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: LGPL-2.1-or-later
6 */
7
8 /* Return -1 on error or 1 on success (never 0!). */
9 static int
10 arch_get_syscall_args(struct tcb *tcp)
11 {
12 #if defined LINUX_MIPSN64 || defined LINUX_MIPSN32
13 tcp->u_arg[0] = mips_REG_A0;
14 tcp->u_arg[1] = mips_REG_A1;
15 tcp->u_arg[2] = mips_REG_A2;
16 tcp->u_arg[3] = mips_REG_A3;
17 tcp->u_arg[4] = mips_REG_A4;
18 tcp->u_arg[5] = mips_REG_A5;
19 #elif defined LINUX_MIPSO32
20 tcp->u_arg[0] = mips_REG_A0;
21 tcp->u_arg[1] = mips_REG_A1;
22 tcp->u_arg[2] = mips_REG_A2;
23 tcp->u_arg[3] = mips_REG_A3;
24 if (n_args(tcp) > 4
25 && umoven(tcp, mips_REG_SP + 4 * sizeof(tcp->u_arg[0]),
26 (n_args(tcp) - 4) * sizeof(tcp->u_arg[0]),
27 &tcp->u_arg[4]) < 0) {
28 error_msg("pid %d: cannot fetch 5th and 6th syscall arguments"
29 " from tracee's memory", tcp->pid);
30
31 /*
32 * Let's proceed with the first 4 arguments
33 * instead of reporting the failure.
34 */
35 memset(&tcp->u_arg[4], 0,
36 (n_args(tcp) - 4) * sizeof(tcp->u_arg[0]));
37 }
38 #else
39 # error unsupported mips abi
40 #endif
41 return 1;
42 }
43
44 #ifdef LINUX_MIPSO32
45 static void
46 arch_get_syscall_args_extra(struct tcb *tcp, const unsigned int n)
47 {
48 /* This assumes n >= 4. */
49 if (n_args(tcp) > n
50 && umoven(tcp, mips_REG_SP + n * sizeof(tcp->u_arg[0]),
51 (n_args(tcp) - n) * sizeof(tcp->u_arg[0]),
52 &tcp->u_arg[n]) < 0) {
53 /*
54 * Let's proceed with the first n arguments
55 * instead of reporting the failure.
56 */
57 memset(&tcp->u_arg[n], 0,
58 (n_args(tcp) - n) * sizeof(tcp->u_arg[0]));
59 }
60 }
61 #endif
62
63 #ifdef SYS_syscall_subcall
64 static void
65 decode_syscall_subcall(struct tcb *tcp)
66 {
67 if (!scno_is_valid(tcp->u_arg[0]))
68 return;
69 tcp->true_scno = tcp->scno = tcp->u_arg[0];
70 tcp->qual_flg = qual_flags(tcp->scno);
71 tcp->s_ent = &sysent[tcp->scno];
72 memmove(&tcp->u_arg[0], &tcp->u_arg[1],
73 sizeof(tcp->u_arg) - sizeof(tcp->u_arg[0]));
74 /*
75 * Fetching the last arg of 7-arg syscalls (fadvise64_64
76 * and sync_file_range) requires additional code,
77 * see arch_get_syscall_args() above.
78 */
79 if (n_args(tcp) == MAX_ARGS) {
80 if (umoven(tcp,
81 mips_REG_SP + MAX_ARGS * sizeof(tcp->u_arg[0]),
82 sizeof(tcp->u_arg[0]),
83 &tcp->u_arg[MAX_ARGS - 1]) < 0)
84 tcp->u_arg[MAX_ARGS - 1] = 0;
85 }
86 }
87 #endif /* SYS_syscall_subcall */