1 /*
2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4 * Copyright (c) 1993-1996 Rick Sladkey <jrs@world.std.com>
5 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
6 * Copyright (c) 2007 Roland McGrath <roland@redhat.com>
7 * Copyright (c) 2011-2012 Denys Vlasenko <vda.linux@googlemail.com>
8 * Copyright (c) 2010-2015 Dmitry V. Levin <ldv@strace.io>
9 * Copyright (c) 2014-2021 The strace developers.
10 * All rights reserved.
11 *
12 * SPDX-License-Identifier: LGPL-2.1-or-later
13 */
14
15 #include "defs.h"
16
17 static void
18 printargv(struct tcb *const tcp, kernel_ulong_t addr)
19 {
20 if (!addr || !verbose(tcp)) {
21 printaddr(addr);
22 return;
23 }
24
25 const unsigned int wordsize = current_wordsize;
26 kernel_ulong_t prev_addr = 0;
27 unsigned int n = 0;
28
29 for (;; prev_addr = addr, addr += wordsize, ++n) {
30 union {
31 unsigned int w32;
32 kernel_ulong_t wl;
33 char data[sizeof(kernel_ulong_t)];
34 } cp;
35
36 if (addr < prev_addr || umoven(tcp, addr, wordsize, cp.data)) {
37 if (n == 0) {
38 printaddr(addr);
39 return;
40 }
41 tprint_array_next();
42 tprint_more_data_follows();
43 printaddr_comment(addr);
44 break;
45 }
46
47 const kernel_ulong_t word = (wordsize == sizeof(cp.w32))
48 ? (kernel_ulong_t) cp.w32 : cp.wl;
49 if (n == 0)
50 tprint_array_begin();
51 if (word == 0)
52 break;
53 if (n != 0)
54 tprint_array_next();
55
56 if (abbrev(tcp) && n >= max_strlen) {
57 tprint_more_data_follows();
58 break;
59 }
60
61 printstr(tcp, word);
62 }
63
64 tprint_array_end();
65 }
66
67 static void
68 printargc(struct tcb *const tcp, kernel_ulong_t addr)
69 {
70 printaddr(addr);
71
72 if (!addr || !verbose(tcp))
73 return;
74
75 const unsigned int wordsize = current_wordsize;
76 kernel_ulong_t prev_addr = 0;
77 unsigned int n;
78
79 for (n = 0; addr > prev_addr; prev_addr = addr, addr += wordsize, ++n) {
80 kernel_ulong_t word = 0;
81 if (umoven(tcp, addr, wordsize, &word)) {
82 if (n == 0)
83 return;
84
85 addr = 0;
86 break;
87 }
88 if (word == 0)
89 break;
90 }
91 tprintf_comment("%u var%s%s",
92 n, n == 1 ? "" : "s",
93 addr < prev_addr ? ", unterminated" : "");
94 }
95
96 static void
97 decode_execve(struct tcb *tcp, const unsigned int index)
98 {
99 /* pathname */
100 printpath(tcp, tcp->u_arg[index + 0]);
101 tprint_arg_next();
102
103 /* argv */
104 printargv(tcp, tcp->u_arg[index + 1]);
105 tprint_arg_next();
106
107 /* envp */
108 (abbrev(tcp) ? printargc : printargv) (tcp, tcp->u_arg[index + 2]);
109 }
110
111 SYS_FUNC(execve)
112 {
113 decode_execve(tcp, 0);
114
115 return RVAL_DECODED;
116 }
117
118 SYS_FUNC(execveat)
119 {
120 /* dirfd */
121 print_dirfd(tcp, tcp->u_arg[0]);
122 tprint_arg_next();
123
124 /* pathname, argv, envp */
125 decode_execve(tcp, 1);
126 tprint_arg_next();
127
128 /* flags */
129 printflags(at_flags, tcp->u_arg[4], "AT_???");
130
131 return RVAL_DECODED;
132 }
133
134 #if defined(SPARC) || defined(SPARC64)
135 SYS_FUNC(execv)
136 {
137 /* pathname */
138 printpath(tcp, tcp->u_arg[0]);
139 tprint_arg_next();
140
141 /* argv */
142 printargv(tcp, tcp->u_arg[1]);
143
144 return RVAL_DECODED;
145 }
146 #endif /* SPARC || SPARC64 */