root / linux-user / strace.c @ 1dd9ffb9
History | View | Annotate | Download (7.9 kB)
1 | 33189d31 | ths | #include <stdio.h> |
---|---|---|---|
2 | 33189d31 | ths | #include <errno.h> |
3 | 33189d31 | ths | #include <sys/ipc.h> |
4 | 33189d31 | ths | #include <sys/msg.h> |
5 | 33189d31 | ths | #include <sys/sem.h> |
6 | 33189d31 | ths | #include <sys/shm.h> |
7 | 33189d31 | ths | #include <sys/select.h> |
8 | 33189d31 | ths | #include <sys/types.h> |
9 | 33189d31 | ths | #include <unistd.h> |
10 | 33189d31 | ths | #include "qemu.h" |
11 | 33189d31 | ths | |
12 | 33189d31 | ths | int do_strace=0; |
13 | 33189d31 | ths | |
14 | 33189d31 | ths | struct syscallname {
|
15 | 33189d31 | ths | int nr;
|
16 | 7ccfb2eb | blueswir1 | const char *name; |
17 | 7ccfb2eb | blueswir1 | const char *format; |
18 | 7ccfb2eb | blueswir1 | void (*call)(const struct syscallname *, |
19 | c16f9ed3 | bellard | abi_long, abi_long, abi_long, |
20 | c16f9ed3 | bellard | abi_long, abi_long, abi_long); |
21 | 7ccfb2eb | blueswir1 | void (*result)(const struct syscallname *, abi_long); |
22 | 33189d31 | ths | }; |
23 | 33189d31 | ths | |
24 | 33189d31 | ths | /*
|
25 | 33189d31 | ths | * Utility functions
|
26 | 33189d31 | ths | */
|
27 | 33189d31 | ths | static void |
28 | 33189d31 | ths | print_ipc_cmd(int cmd)
|
29 | 33189d31 | ths | { |
30 | 33189d31 | ths | #define output_cmd(val) \
|
31 | 33189d31 | ths | if( cmd == val ) { \
|
32 | 33189d31 | ths | gemu_log(#val); \
|
33 | 33189d31 | ths | return; \
|
34 | 33189d31 | ths | } |
35 | 33189d31 | ths | |
36 | 33189d31 | ths | cmd &= 0xff;
|
37 | 33189d31 | ths | |
38 | 33189d31 | ths | /* General IPC commands */
|
39 | 33189d31 | ths | output_cmd( IPC_RMID ); |
40 | 33189d31 | ths | output_cmd( IPC_SET ); |
41 | 33189d31 | ths | output_cmd( IPC_STAT ); |
42 | 33189d31 | ths | output_cmd( IPC_INFO ); |
43 | 33189d31 | ths | /* msgctl() commands */
|
44 | 33189d31 | ths | #ifdef __USER_MISC
|
45 | 33189d31 | ths | output_cmd( MSG_STAT ); |
46 | 33189d31 | ths | output_cmd( MSG_INFO ); |
47 | 33189d31 | ths | #endif
|
48 | 33189d31 | ths | /* shmctl() commands */
|
49 | 33189d31 | ths | output_cmd( SHM_LOCK ); |
50 | 33189d31 | ths | output_cmd( SHM_UNLOCK ); |
51 | 33189d31 | ths | output_cmd( SHM_STAT ); |
52 | 33189d31 | ths | output_cmd( SHM_INFO ); |
53 | 33189d31 | ths | /* semctl() commands */
|
54 | 33189d31 | ths | output_cmd( GETPID ); |
55 | 33189d31 | ths | output_cmd( GETVAL ); |
56 | 33189d31 | ths | output_cmd( GETALL ); |
57 | 33189d31 | ths | output_cmd( GETNCNT ); |
58 | 33189d31 | ths | output_cmd( GETZCNT ); |
59 | 33189d31 | ths | output_cmd( SETVAL ); |
60 | 33189d31 | ths | output_cmd( SETALL ); |
61 | 33189d31 | ths | output_cmd( SEM_STAT ); |
62 | 33189d31 | ths | output_cmd( SEM_INFO ); |
63 | 33189d31 | ths | output_cmd( IPC_RMID ); |
64 | 33189d31 | ths | output_cmd( IPC_RMID ); |
65 | 33189d31 | ths | output_cmd( IPC_RMID ); |
66 | 33189d31 | ths | output_cmd( IPC_RMID ); |
67 | 33189d31 | ths | output_cmd( IPC_RMID ); |
68 | 33189d31 | ths | output_cmd( IPC_RMID ); |
69 | 33189d31 | ths | output_cmd( IPC_RMID ); |
70 | 33189d31 | ths | output_cmd( IPC_RMID ); |
71 | 33189d31 | ths | output_cmd( IPC_RMID ); |
72 | 33189d31 | ths | |
73 | 33189d31 | ths | /* Some value we don't recognize */
|
74 | 33189d31 | ths | gemu_log("%d",cmd);
|
75 | 33189d31 | ths | } |
76 | 33189d31 | ths | |
77 | c16f9ed3 | bellard | #ifdef TARGET_NR__newselect
|
78 | 33189d31 | ths | static void |
79 | c16f9ed3 | bellard | print_fdset(int n, abi_ulong target_fds_addr)
|
80 | 33189d31 | ths | { |
81 | 33189d31 | ths | int i;
|
82 | 33189d31 | ths | |
83 | 33189d31 | ths | gemu_log("[");
|
84 | 33189d31 | ths | if( target_fds_addr ) {
|
85 | 579a97f7 | bellard | abi_long *target_fds; |
86 | 33189d31 | ths | |
87 | 579a97f7 | bellard | target_fds = lock_user(VERIFY_READ, |
88 | 579a97f7 | bellard | target_fds_addr, |
89 | 579a97f7 | bellard | sizeof(*target_fds)*(n / TARGET_ABI_BITS + 1), |
90 | 579a97f7 | bellard | 1);
|
91 | 579a97f7 | bellard | |
92 | 579a97f7 | bellard | if (!target_fds)
|
93 | 33189d31 | ths | return;
|
94 | 33189d31 | ths | |
95 | 33189d31 | ths | for (i=n; i>=0; i--) { |
96 | 579a97f7 | bellard | if ((tswapl(target_fds[i / TARGET_ABI_BITS]) >> (i & (TARGET_ABI_BITS - 1))) & 1) |
97 | 33189d31 | ths | gemu_log("%d,", i );
|
98 | 33189d31 | ths | } |
99 | 33189d31 | ths | unlock_user(target_fds, target_fds_addr, 0);
|
100 | 33189d31 | ths | } |
101 | 33189d31 | ths | gemu_log("]");
|
102 | 33189d31 | ths | } |
103 | 33189d31 | ths | |
104 | 33189d31 | ths | static void |
105 | c16f9ed3 | bellard | print_timeval(abi_ulong tv_addr) |
106 | 33189d31 | ths | { |
107 | 33189d31 | ths | if( tv_addr ) {
|
108 | 33189d31 | ths | struct target_timeval *tv;
|
109 | 33189d31 | ths | |
110 | 579a97f7 | bellard | tv = lock_user(VERIFY_READ, tv_addr, sizeof(*tv), 1); |
111 | 579a97f7 | bellard | if (!tv)
|
112 | 33189d31 | ths | return;
|
113 | f3e3285d | ths | gemu_log("{" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "}", |
114 | f3e3285d | ths | tv->tv_sec, tv->tv_usec); |
115 | 33189d31 | ths | unlock_user(tv, tv_addr, 0);
|
116 | 33189d31 | ths | } else
|
117 | 33189d31 | ths | gemu_log("NULL");
|
118 | 33189d31 | ths | } |
119 | c16f9ed3 | bellard | #endif
|
120 | 33189d31 | ths | |
121 | 33189d31 | ths | /*
|
122 | 33189d31 | ths | * Sysycall specific output functions
|
123 | 33189d31 | ths | */
|
124 | 33189d31 | ths | |
125 | 33189d31 | ths | /* select */
|
126 | c16f9ed3 | bellard | #ifdef TARGET_NR__newselect
|
127 | 33189d31 | ths | static long newselect_arg1 = 0; |
128 | 33189d31 | ths | static long newselect_arg2 = 0; |
129 | 33189d31 | ths | static long newselect_arg3 = 0; |
130 | 33189d31 | ths | static long newselect_arg4 = 0; |
131 | 33189d31 | ths | static long newselect_arg5 = 0; |
132 | 33189d31 | ths | |
133 | 33189d31 | ths | static void |
134 | 7ccfb2eb | blueswir1 | print_newselect(const struct syscallname *name, |
135 | c16f9ed3 | bellard | abi_long arg1, abi_long arg2, abi_long arg3, |
136 | c16f9ed3 | bellard | abi_long arg4, abi_long arg5, abi_long arg6) |
137 | 33189d31 | ths | { |
138 | c16f9ed3 | bellard | gemu_log("%s(" TARGET_ABI_FMT_ld ",", name->name, arg1); |
139 | 33189d31 | ths | print_fdset(arg1, arg2); |
140 | 33189d31 | ths | gemu_log(",");
|
141 | 33189d31 | ths | print_fdset(arg1, arg3); |
142 | 33189d31 | ths | gemu_log(",");
|
143 | 33189d31 | ths | print_fdset(arg1, arg4); |
144 | 33189d31 | ths | gemu_log(",");
|
145 | 33189d31 | ths | print_timeval(arg5); |
146 | 33189d31 | ths | gemu_log(")");
|
147 | 33189d31 | ths | |
148 | 33189d31 | ths | /* save for use in the return output function below */
|
149 | 33189d31 | ths | newselect_arg1=arg1; |
150 | 33189d31 | ths | newselect_arg2=arg2; |
151 | 33189d31 | ths | newselect_arg3=arg3; |
152 | 33189d31 | ths | newselect_arg4=arg4; |
153 | 33189d31 | ths | newselect_arg5=arg5; |
154 | 33189d31 | ths | } |
155 | c16f9ed3 | bellard | #endif
|
156 | 33189d31 | ths | |
157 | 3e46b2ef | blueswir1 | #ifdef TARGET_NR_semctl
|
158 | 33189d31 | ths | static void |
159 | 7ccfb2eb | blueswir1 | print_semctl(const struct syscallname *name, |
160 | c16f9ed3 | bellard | abi_long arg1, abi_long arg2, abi_long arg3, |
161 | c16f9ed3 | bellard | abi_long arg4, abi_long arg5, abi_long arg6) |
162 | 33189d31 | ths | { |
163 | c16f9ed3 | bellard | gemu_log("%s(" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld ",", name->name, arg1, arg2); |
164 | 33189d31 | ths | print_ipc_cmd(arg3); |
165 | c16f9ed3 | bellard | gemu_log(",0x" TARGET_ABI_FMT_lx ")", arg4); |
166 | 33189d31 | ths | } |
167 | 3e46b2ef | blueswir1 | #endif
|
168 | 33189d31 | ths | |
169 | 33189d31 | ths | static void |
170 | 7ccfb2eb | blueswir1 | print_execve(const struct syscallname *name, |
171 | c16f9ed3 | bellard | abi_long arg1, abi_long arg2, abi_long arg3, |
172 | c16f9ed3 | bellard | abi_long arg4, abi_long arg5, abi_long arg6) |
173 | 33189d31 | ths | { |
174 | c16f9ed3 | bellard | abi_ulong arg_ptr_addr; |
175 | 33189d31 | ths | char *s;
|
176 | 33189d31 | ths | |
177 | 579a97f7 | bellard | if (!(s = lock_user_string(arg1)))
|
178 | 33189d31 | ths | return;
|
179 | 33189d31 | ths | gemu_log("%s(\"%s\",{", name->name, s);
|
180 | 33189d31 | ths | unlock_user(s, arg1, 0);
|
181 | 33189d31 | ths | |
182 | c16f9ed3 | bellard | for (arg_ptr_addr = arg2; ; arg_ptr_addr += sizeof(abi_ulong)) { |
183 | 98448f58 | blueswir1 | abi_ulong *arg_ptr, arg_addr; |
184 | 33189d31 | ths | |
185 | c16f9ed3 | bellard | arg_ptr = lock_user(VERIFY_READ, arg_ptr_addr, sizeof(abi_ulong), 1); |
186 | 579a97f7 | bellard | if (!arg_ptr)
|
187 | 33189d31 | ths | return;
|
188 | 33189d31 | ths | arg_addr = tswapl(*arg_ptr); |
189 | 33189d31 | ths | unlock_user(arg_ptr, arg_ptr_addr, 0);
|
190 | 33189d31 | ths | if (!arg_addr)
|
191 | 33189d31 | ths | break;
|
192 | 579a97f7 | bellard | if ((s = lock_user_string(arg_addr))) {
|
193 | 579a97f7 | bellard | gemu_log("\"%s\",", s);
|
194 | 98448f58 | blueswir1 | unlock_user(s, arg_addr, 0);
|
195 | 579a97f7 | bellard | } |
196 | 33189d31 | ths | } |
197 | 33189d31 | ths | |
198 | 33189d31 | ths | gemu_log("NULL})");
|
199 | 33189d31 | ths | } |
200 | 33189d31 | ths | |
201 | c16f9ed3 | bellard | #ifdef TARGET_NR_ipc
|
202 | 33189d31 | ths | static void |
203 | 7ccfb2eb | blueswir1 | print_ipc(const struct syscallname *name, |
204 | c16f9ed3 | bellard | abi_long arg1, abi_long arg2, abi_long arg3, |
205 | c16f9ed3 | bellard | abi_long arg4, abi_long arg5, abi_long arg6) |
206 | 33189d31 | ths | { |
207 | 33189d31 | ths | switch(arg1) {
|
208 | 33189d31 | ths | case IPCOP_semctl:
|
209 | 7ccfb2eb | blueswir1 | gemu_log("semctl(" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld ",", arg1, arg2); |
210 | 7ccfb2eb | blueswir1 | print_ipc_cmd(arg3); |
211 | 7ccfb2eb | blueswir1 | gemu_log(",0x" TARGET_ABI_FMT_lx ")", arg4); |
212 | 33189d31 | ths | break;
|
213 | 33189d31 | ths | default:
|
214 | c16f9ed3 | bellard | gemu_log("%s(" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld ")", |
215 | 33189d31 | ths | name->name, arg1, arg2, arg3, arg4); |
216 | 33189d31 | ths | } |
217 | 33189d31 | ths | } |
218 | c16f9ed3 | bellard | #endif
|
219 | 33189d31 | ths | |
220 | 33189d31 | ths | /*
|
221 | 33189d31 | ths | * Variants for the return value output function
|
222 | 33189d31 | ths | */
|
223 | 33189d31 | ths | |
224 | 33189d31 | ths | static void |
225 | 7ccfb2eb | blueswir1 | print_syscall_ret_addr(const struct syscallname *name, abi_long ret) |
226 | 33189d31 | ths | { |
227 | 33189d31 | ths | if( ret == -1 ) { |
228 | 33189d31 | ths | gemu_log(" = -1 errno=%d (%s)\n", errno, target_strerror(errno));
|
229 | 33189d31 | ths | } else {
|
230 | 29fa23e7 | bellard | gemu_log(" = 0x" TARGET_ABI_FMT_lx "\n", ret); |
231 | 33189d31 | ths | } |
232 | 33189d31 | ths | } |
233 | 33189d31 | ths | |
234 | f3e3285d | ths | #if 0 /* currently unused */
|
235 | 33189d31 | ths | static void
|
236 | c16f9ed3 | bellard | print_syscall_ret_raw(struct syscallname *name, abi_long ret)
|
237 | 33189d31 | ths | {
|
238 | 29fa23e7 | bellard | gemu_log(" = 0x" TARGET_ABI_FMT_lx "\n", ret);
|
239 | 33189d31 | ths | }
|
240 | f3e3285d | ths | #endif
|
241 | 33189d31 | ths | |
242 | f3e3285d | ths | #ifdef TARGET_NR__newselect
|
243 | 33189d31 | ths | static void |
244 | 7ccfb2eb | blueswir1 | print_syscall_ret_newselect(const struct syscallname *name, abi_long ret) |
245 | 33189d31 | ths | { |
246 | 29fa23e7 | bellard | gemu_log(" = 0x" TARGET_ABI_FMT_lx " (", ret); |
247 | 33189d31 | ths | print_fdset(newselect_arg1,newselect_arg2); |
248 | 33189d31 | ths | gemu_log(",");
|
249 | 33189d31 | ths | print_fdset(newselect_arg1,newselect_arg3); |
250 | 33189d31 | ths | gemu_log(",");
|
251 | 33189d31 | ths | print_fdset(newselect_arg1,newselect_arg4); |
252 | 33189d31 | ths | gemu_log(",");
|
253 | 33189d31 | ths | print_timeval(newselect_arg5); |
254 | 33189d31 | ths | gemu_log(")\n");
|
255 | 33189d31 | ths | } |
256 | f3e3285d | ths | #endif
|
257 | 33189d31 | ths | |
258 | 33189d31 | ths | /*
|
259 | 33189d31 | ths | * An array of all of the syscalls we know about
|
260 | 33189d31 | ths | */
|
261 | 33189d31 | ths | |
262 | 7ccfb2eb | blueswir1 | static const struct syscallname scnames[] = { |
263 | 33189d31 | ths | #include "strace.list" |
264 | 33189d31 | ths | }; |
265 | 33189d31 | ths | |
266 | b1503cda | malc | static int nsyscalls = ARRAY_SIZE(scnames); |
267 | 33189d31 | ths | |
268 | 33189d31 | ths | /*
|
269 | 33189d31 | ths | * The public interface to this module.
|
270 | 33189d31 | ths | */
|
271 | 33189d31 | ths | void
|
272 | 33189d31 | ths | print_syscall(int num,
|
273 | c16f9ed3 | bellard | abi_long arg1, abi_long arg2, abi_long arg3, |
274 | c16f9ed3 | bellard | abi_long arg4, abi_long arg5, abi_long arg6) |
275 | 33189d31 | ths | { |
276 | 33189d31 | ths | int i;
|
277 | 7ccfb2eb | blueswir1 | const char *format="%s(" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld ")"; |
278 | 33189d31 | ths | |
279 | 33189d31 | ths | gemu_log("%d ", getpid() );
|
280 | 33189d31 | ths | |
281 | 33189d31 | ths | for(i=0;i<nsyscalls;i++) |
282 | 33189d31 | ths | if( scnames[i].nr == num ) {
|
283 | 33189d31 | ths | if( scnames[i].call != NULL ) { |
284 | 33189d31 | ths | scnames[i].call(&scnames[i],arg1,arg2,arg3,arg4,arg5,arg6); |
285 | 33189d31 | ths | } else {
|
286 | 6b23f777 | bellard | /* XXX: this format system is broken because it uses
|
287 | 6b23f777 | bellard | host types and host pointers for strings */
|
288 | 33189d31 | ths | if( scnames[i].format != NULL ) |
289 | 33189d31 | ths | format = scnames[i].format; |
290 | 33189d31 | ths | gemu_log(format,scnames[i].name, arg1,arg2,arg3,arg4,arg5,arg6); |
291 | 33189d31 | ths | } |
292 | 74c11e55 | pbrook | return;
|
293 | 33189d31 | ths | } |
294 | 74c11e55 | pbrook | gemu_log("Unknown syscall %d\n", num);
|
295 | 33189d31 | ths | } |
296 | 33189d31 | ths | |
297 | 33189d31 | ths | |
298 | 33189d31 | ths | void
|
299 | c16f9ed3 | bellard | print_syscall_ret(int num, abi_long ret)
|
300 | 33189d31 | ths | { |
301 | 33189d31 | ths | int i;
|
302 | 33189d31 | ths | |
303 | 33189d31 | ths | for(i=0;i<nsyscalls;i++) |
304 | 33189d31 | ths | if( scnames[i].nr == num ) {
|
305 | 33189d31 | ths | if( scnames[i].result != NULL ) { |
306 | 33189d31 | ths | scnames[i].result(&scnames[i],ret); |
307 | 33189d31 | ths | } else {
|
308 | 33189d31 | ths | if( ret < 0 ) { |
309 | c16f9ed3 | bellard | gemu_log(" = -1 errno=" TARGET_ABI_FMT_ld " (%s)\n", -ret, target_strerror(-ret)); |
310 | 33189d31 | ths | } else {
|
311 | c16f9ed3 | bellard | gemu_log(" = " TARGET_ABI_FMT_ld "\n", ret); |
312 | 33189d31 | ths | } |
313 | 33189d31 | ths | } |
314 | 33189d31 | ths | break;
|
315 | 33189d31 | ths | } |
316 | 33189d31 | ths | } |