root / linux-user / strace.c @ 1ffc346f
History | View | Annotate | Download (7.7 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 | 33189d31 | ths | char *name;
|
17 | 33189d31 | ths | char *format;
|
18 | 33189d31 | ths | void (*call)(struct syscallname *, |
19 | c16f9ed3 | bellard | abi_long, abi_long, abi_long, |
20 | c16f9ed3 | bellard | abi_long, abi_long, abi_long); |
21 | c16f9ed3 | bellard | void (*result)(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 | 33189d31 | ths | print_newselect(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 | 33189d31 | ths | static void |
158 | 33189d31 | ths | print_semctl(struct syscallname *name,
|
159 | c16f9ed3 | bellard | abi_long arg1, abi_long arg2, abi_long arg3, |
160 | c16f9ed3 | bellard | abi_long arg4, abi_long arg5, abi_long arg6) |
161 | 33189d31 | ths | { |
162 | c16f9ed3 | bellard | gemu_log("%s(" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld ",", name->name, arg1, arg2); |
163 | 33189d31 | ths | print_ipc_cmd(arg3); |
164 | c16f9ed3 | bellard | gemu_log(",0x" TARGET_ABI_FMT_lx ")", arg4); |
165 | 33189d31 | ths | } |
166 | 33189d31 | ths | |
167 | 33189d31 | ths | static void |
168 | 33189d31 | ths | print_execve(struct syscallname *name,
|
169 | c16f9ed3 | bellard | abi_long arg1, abi_long arg2, abi_long arg3, |
170 | c16f9ed3 | bellard | abi_long arg4, abi_long arg5, abi_long arg6) |
171 | 33189d31 | ths | { |
172 | c16f9ed3 | bellard | abi_ulong arg_ptr_addr; |
173 | 33189d31 | ths | char *s;
|
174 | 33189d31 | ths | |
175 | 579a97f7 | bellard | if (!(s = lock_user_string(arg1)))
|
176 | 33189d31 | ths | return;
|
177 | 33189d31 | ths | gemu_log("%s(\"%s\",{", name->name, s);
|
178 | 33189d31 | ths | unlock_user(s, arg1, 0);
|
179 | 33189d31 | ths | |
180 | c16f9ed3 | bellard | for (arg_ptr_addr = arg2; ; arg_ptr_addr += sizeof(abi_ulong)) { |
181 | c16f9ed3 | bellard | abi_ulong *arg_ptr, arg_addr, s_addr; |
182 | 33189d31 | ths | |
183 | c16f9ed3 | bellard | arg_ptr = lock_user(VERIFY_READ, arg_ptr_addr, sizeof(abi_ulong), 1); |
184 | 579a97f7 | bellard | if (!arg_ptr)
|
185 | 33189d31 | ths | return;
|
186 | 33189d31 | ths | arg_addr = tswapl(*arg_ptr); |
187 | 33189d31 | ths | unlock_user(arg_ptr, arg_ptr_addr, 0);
|
188 | 33189d31 | ths | if (!arg_addr)
|
189 | 33189d31 | ths | break;
|
190 | 579a97f7 | bellard | if ((s = lock_user_string(arg_addr))) {
|
191 | 579a97f7 | bellard | gemu_log("\"%s\",", s);
|
192 | 579a97f7 | bellard | unlock_user(s, s_addr, 0);
|
193 | 579a97f7 | bellard | } |
194 | 33189d31 | ths | } |
195 | 33189d31 | ths | |
196 | 33189d31 | ths | gemu_log("NULL})");
|
197 | 33189d31 | ths | } |
198 | 33189d31 | ths | |
199 | c16f9ed3 | bellard | #ifdef TARGET_NR_ipc
|
200 | 33189d31 | ths | static void |
201 | 33189d31 | ths | print_ipc(struct syscallname *name,
|
202 | c16f9ed3 | bellard | abi_long arg1, abi_long arg2, abi_long arg3, |
203 | c16f9ed3 | bellard | abi_long arg4, abi_long arg5, abi_long arg6) |
204 | 33189d31 | ths | { |
205 | 33189d31 | ths | switch(arg1) {
|
206 | 33189d31 | ths | case IPCOP_semctl:
|
207 | 33189d31 | ths | name->name = "semctl";
|
208 | 33189d31 | ths | print_semctl(name,arg2,arg3,arg4,arg5,arg6,0);
|
209 | 33189d31 | ths | break;
|
210 | 33189d31 | ths | default:
|
211 | c16f9ed3 | bellard | gemu_log("%s(" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld ")", |
212 | 33189d31 | ths | name->name, arg1, arg2, arg3, arg4); |
213 | 33189d31 | ths | } |
214 | 33189d31 | ths | } |
215 | c16f9ed3 | bellard | #endif
|
216 | 33189d31 | ths | |
217 | 33189d31 | ths | /*
|
218 | 33189d31 | ths | * Variants for the return value output function
|
219 | 33189d31 | ths | */
|
220 | 33189d31 | ths | |
221 | 33189d31 | ths | static void |
222 | c16f9ed3 | bellard | print_syscall_ret_addr(struct syscallname *name, abi_long ret)
|
223 | 33189d31 | ths | { |
224 | 33189d31 | ths | if( ret == -1 ) { |
225 | 33189d31 | ths | gemu_log(" = -1 errno=%d (%s)\n", errno, target_strerror(errno));
|
226 | 33189d31 | ths | } else {
|
227 | 29fa23e7 | bellard | gemu_log(" = 0x" TARGET_ABI_FMT_lx "\n", ret); |
228 | 33189d31 | ths | } |
229 | 33189d31 | ths | } |
230 | 33189d31 | ths | |
231 | f3e3285d | ths | #if 0 /* currently unused */
|
232 | 33189d31 | ths | static void
|
233 | c16f9ed3 | bellard | print_syscall_ret_raw(struct syscallname *name, abi_long ret)
|
234 | 33189d31 | ths | {
|
235 | 29fa23e7 | bellard | gemu_log(" = 0x" TARGET_ABI_FMT_lx "\n", ret);
|
236 | 33189d31 | ths | }
|
237 | f3e3285d | ths | #endif
|
238 | 33189d31 | ths | |
239 | f3e3285d | ths | #ifdef TARGET_NR__newselect
|
240 | 33189d31 | ths | static void |
241 | c16f9ed3 | bellard | print_syscall_ret_newselect(struct syscallname *name, abi_long ret)
|
242 | 33189d31 | ths | { |
243 | 29fa23e7 | bellard | gemu_log(" = 0x" TARGET_ABI_FMT_lx " (", ret); |
244 | 33189d31 | ths | print_fdset(newselect_arg1,newselect_arg2); |
245 | 33189d31 | ths | gemu_log(",");
|
246 | 33189d31 | ths | print_fdset(newselect_arg1,newselect_arg3); |
247 | 33189d31 | ths | gemu_log(",");
|
248 | 33189d31 | ths | print_fdset(newselect_arg1,newselect_arg4); |
249 | 33189d31 | ths | gemu_log(",");
|
250 | 33189d31 | ths | print_timeval(newselect_arg5); |
251 | 33189d31 | ths | gemu_log(")\n");
|
252 | 33189d31 | ths | } |
253 | f3e3285d | ths | #endif
|
254 | 33189d31 | ths | |
255 | 33189d31 | ths | /*
|
256 | 33189d31 | ths | * An array of all of the syscalls we know about
|
257 | 33189d31 | ths | */
|
258 | 33189d31 | ths | |
259 | 33189d31 | ths | static struct syscallname scnames[] = { |
260 | 33189d31 | ths | #include "strace.list" |
261 | 33189d31 | ths | }; |
262 | 33189d31 | ths | |
263 | 33189d31 | ths | static int nsyscalls = sizeof(scnames)/sizeof(struct syscallname); |
264 | 33189d31 | ths | |
265 | 33189d31 | ths | /*
|
266 | 33189d31 | ths | * The public interface to this module.
|
267 | 33189d31 | ths | */
|
268 | 33189d31 | ths | void
|
269 | 33189d31 | ths | print_syscall(int num,
|
270 | c16f9ed3 | bellard | abi_long arg1, abi_long arg2, abi_long arg3, |
271 | c16f9ed3 | bellard | abi_long arg4, abi_long arg5, abi_long arg6) |
272 | 33189d31 | ths | { |
273 | 33189d31 | ths | int i;
|
274 | 6b23f777 | bellard | 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 ")"; |
275 | 33189d31 | ths | |
276 | 33189d31 | ths | gemu_log("%d ", getpid() );
|
277 | 33189d31 | ths | |
278 | 33189d31 | ths | for(i=0;i<nsyscalls;i++) |
279 | 33189d31 | ths | if( scnames[i].nr == num ) {
|
280 | 33189d31 | ths | if( scnames[i].call != NULL ) { |
281 | 33189d31 | ths | scnames[i].call(&scnames[i],arg1,arg2,arg3,arg4,arg5,arg6); |
282 | 33189d31 | ths | } else {
|
283 | 6b23f777 | bellard | /* XXX: this format system is broken because it uses
|
284 | 6b23f777 | bellard | host types and host pointers for strings */
|
285 | 33189d31 | ths | if( scnames[i].format != NULL ) |
286 | 33189d31 | ths | format = scnames[i].format; |
287 | 33189d31 | ths | gemu_log(format,scnames[i].name, arg1,arg2,arg3,arg4,arg5,arg6); |
288 | 33189d31 | ths | } |
289 | 33189d31 | ths | break;
|
290 | 33189d31 | ths | } |
291 | 33189d31 | ths | } |
292 | 33189d31 | ths | |
293 | 33189d31 | ths | |
294 | 33189d31 | ths | void
|
295 | c16f9ed3 | bellard | print_syscall_ret(int num, abi_long ret)
|
296 | 33189d31 | ths | { |
297 | 33189d31 | ths | int i;
|
298 | 33189d31 | ths | |
299 | 33189d31 | ths | for(i=0;i<nsyscalls;i++) |
300 | 33189d31 | ths | if( scnames[i].nr == num ) {
|
301 | 33189d31 | ths | if( scnames[i].result != NULL ) { |
302 | 33189d31 | ths | scnames[i].result(&scnames[i],ret); |
303 | 33189d31 | ths | } else {
|
304 | 33189d31 | ths | if( ret < 0 ) { |
305 | c16f9ed3 | bellard | gemu_log(" = -1 errno=" TARGET_ABI_FMT_ld " (%s)\n", -ret, target_strerror(-ret)); |
306 | 33189d31 | ths | } else {
|
307 | c16f9ed3 | bellard | gemu_log(" = " TARGET_ABI_FMT_ld "\n", ret); |
308 | 33189d31 | ths | } |
309 | 33189d31 | ths | } |
310 | 33189d31 | ths | break;
|
311 | 33189d31 | ths | } |
312 | 33189d31 | ths | } |