Subversion Repositories HelenOS

Rev

Rev 2871 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 2871 Rev 2872
1
/** @addtogroup sctrace
1
/** @addtogroup sctrace
2
 * @{
2
 * @{
3
 */
3
 */
4
/** @file
4
/** @file
5
 */
5
 */
6
 
6
 
7
#include <stdio.h>
7
#include <stdio.h>
8
#include <unistd.h>
8
#include <unistd.h>
9
#include <syscall.h>
9
#include <syscall.h>
10
#include <ipc/ipc.h>
10
#include <ipc/ipc.h>
11
#include <fibril.h>
11
#include <fibril.h>
12
#include <errno.h>
12
#include <errno.h>
13
#include <udebug.h>
13
#include <udebug.h>
14
#include <async.h>
14
#include <async.h>
15
 
15
 
16
#include "syscalls.h"
16
#include "syscalls.h"
17
#include "ipc.h"
17
#include "ipc.h"
18
#include "errors.h"
18
#include "errors.h"
19
#include "debug_api.h"
19
#include "debug_api.h"
20
 
20
 
21
#define THBUF_SIZE 64
21
#define THBUF_SIZE 64
22
unsigned thread_hash_buf[THBUF_SIZE];
22
unsigned thread_hash_buf[THBUF_SIZE];
23
unsigned n_threads;
23
unsigned n_threads;
24
 
24
 
25
int next_thread_id;
25
int next_thread_id;
26
 
26
 
27
int phoneid;
27
int phoneid;
28
int abort_trace;
28
int abort_trace;
29
 
29
 
30
void thread_trace_start(unsigned thread_hash);
30
void thread_trace_start(unsigned thread_hash);
31
 
31
 
32
 
32
 
33
int task_connect(int taskid)
33
int task_connect(int taskid)
34
{
34
{
35
    int rc;
35
    int rc;
36
 
36
 
37
    printf("ipc_connect_task(%d)...\n", taskid);
37
    printf("ipc_connect_task(%d)...\n", taskid);
38
    rc = ipc_connect_kbox(taskid);
38
    rc = ipc_connect_kbox(taskid);
39
    printf("-> %d\n", rc);
39
    printf("-> %d\n", rc);
40
    phoneid = rc;
40
    phoneid = rc;
41
    if (rc < 0) return rc;
41
    if (rc < 0) return rc;
42
 
42
 
43
    printf("debug_begin()\n");
43
    printf("debug_begin()\n");
44
    rc = debug_begin(phoneid);
44
    rc = debug_begin(phoneid);
45
    printf("-> %d\n", rc);
45
    printf("-> %d\n", rc);
46
    if (rc < 0) return rc;
46
    if (rc < 0) return rc;
47
 
47
 
48
    return 0;
48
    return 0;
49
}
49
}
50
 
50
 
51
int get_thread_list(void)
51
int get_thread_list(void)
52
{
52
{
53
    int rc;
53
    int rc;
54
    int tb_copied;
54
    int tb_copied;
55
    int tb_needed;
55
    int tb_needed;
56
    int i;
56
    int i;
57
 
57
 
58
 
58
 
59
    printf("send IPC_M_DEBUG_THREAD_READ message\n");
59
    printf("send IPC_M_DEBUG_THREAD_READ message\n");
60
    rc = debug_thread_read(phoneid, (unsigned)thread_hash_buf,
60
    rc = debug_thread_read(phoneid, (unsigned)thread_hash_buf,
61
        THBUF_SIZE*sizeof(unsigned), &tb_copied, &tb_needed);
61
        THBUF_SIZE*sizeof(unsigned), &tb_copied, &tb_needed);
62
    printf("-> %d\n", rc);
62
    printf("-> %d\n", rc);
63
    if (rc < 0) return rc;
63
    if (rc < 0) return rc;
64
 
64
 
65
    n_threads = tb_copied / sizeof(unsigned);
65
    n_threads = tb_copied / sizeof(unsigned);
66
 
66
 
67
    printf("thread IDs:");
67
    printf("thread IDs:");
68
    for (i=0; i<n_threads; i++) {
68
    for (i=0; i<n_threads; i++) {
69
        printf(" %u", thread_hash_buf[i]);
69
        printf(" %u", thread_hash_buf[i]);
70
    }
70
    }
71
    printf("\ntotal of %u threads\n", tb_needed/sizeof(unsigned));
71
    printf("\ntotal of %u threads\n", tb_needed/sizeof(unsigned));
72
 
72
 
73
    return 0;
73
    return 0;
74
}
74
}
75
 
75
 
76
void print_sc_retval(int retval, rv_type_t rv_type)
76
void print_sc_retval(int retval, rv_type_t rv_type)
77
{
77
{
78
    printf (" -> ");
78
    printf (" -> ");
79
    if (rv_type == RV_INTEGER) {
79
    if (rv_type == RV_INTEGER) {
80
        printf("%d", retval);
80
        printf("%d", retval);
81
    } else if (rv_type == RV_HASH) {
81
    } else if (rv_type == RV_HASH) {
82
        printf("0x%08x", retval);
82
        printf("0x%08x", retval);
83
    } else if (rv_type == RV_ERRNO) {
83
    } else if (rv_type == RV_ERRNO) {
84
        if (retval >= -15 && retval <= 0) {
84
        if (retval >= -15 && retval <= 0) {
85
            printf("%d %s (%s)", retval,
85
            printf("%d %s (%s)", retval,
86
                err_desc[retval].name,
86
                err_desc[retval].name,
87
                err_desc[retval].desc);
87
                err_desc[retval].desc);
88
        } else {
88
        } else {
89
            printf("%d", retval);
89
            printf("%d", retval);
90
        }
90
        }
91
    } else if (rv_type == RV_INT_ERRNO) {
91
    } else if (rv_type == RV_INT_ERRNO) {
92
        if (retval >= -15 && retval < 0) {
92
        if (retval >= -15 && retval < 0) {
93
            printf("%d %s (%s)", retval,
93
            printf("%d %s (%s)", retval,
94
                err_desc[retval].name,
94
                err_desc[retval].name,
95
                err_desc[retval].desc);
95
                err_desc[retval].desc);
96
        } else {
96
        } else {
97
            printf("%d", retval);
97
            printf("%d", retval);
98
        }
98
        }
99
    }
99
    }
100
    putchar('\n');
100
    putchar('\n');
101
}
101
}
102
 
102
 
103
void print_sc_args(unsigned *sc_args, int n)
103
void print_sc_args(unsigned *sc_args, int n)
104
{
104
{
105
    int i;
105
    int i;
106
 
106
 
107
    putchar('(');
107
    putchar('(');
108
    if (n > 0) printf("%d", sc_args[0]);
108
    if (n > 0) printf("%d", sc_args[0]);
109
    for (i=1; i<n; i++) {
109
    for (i=1; i<n; i++) {
110
        printf(", %d", sc_args[i]);
110
        printf(", %d", sc_args[i]);
111
    }
111
    }
112
    putchar(')');
112
    putchar(')');
113
}
113
}
114
 
114
 
115
void sc_ipc_call_async_fast(unsigned *sc_args)
115
void sc_ipc_call_async_fast(unsigned *sc_args, int sc_rc)
116
{
116
{
117
    ipc_call_t call;
117
    ipc_call_t call;
118
    int phoneid;
118
    int phoneid;
119
 
119
   
-
 
120
    if (sc_rc == IPC_CALLRET_FATAL || sc_rc == IPC_CALLRET_TEMPORARY)
-
 
121
        return;
-
 
122
 
120
    phoneid = sc_args[0];
123
    phoneid = sc_args[0];
121
 
124
 
122
    IPC_SET_METHOD(call, sc_args[1]);
125
    IPC_SET_METHOD(call, sc_args[1]);
123
    IPC_SET_ARG1(call, sc_args[2]);
126
    IPC_SET_ARG1(call, sc_args[2]);
124
    IPC_SET_ARG2(call, sc_args[3]);
127
    IPC_SET_ARG2(call, sc_args[3]);
125
    IPC_SET_ARG3(call, sc_args[4]);
128
    IPC_SET_ARG3(call, sc_args[4]);
126
    IPC_SET_ARG4(call, sc_args[5]);
129
    IPC_SET_ARG4(call, sc_args[5]);
127
    IPC_SET_ARG5(call, 0);
130
    IPC_SET_ARG5(call, 0);
128
 
131
 
129
    ipc_parse_call_out(phoneid, &call);
132
    ipc_parse_call_out(phoneid, &call, sc_rc);
130
}
133
}
131
 
134
 
132
void sc_ipc_call_async_slow(unsigned *sc_args)
135
void sc_ipc_call_async_slow(unsigned *sc_args, int sc_rc)
133
{
136
{
134
    ipc_call_t call;
137
    ipc_call_t call;
135
    int rc;
138
    int rc;
136
 
139
 
-
 
140
    if (sc_rc == IPC_CALLRET_FATAL || sc_rc == IPC_CALLRET_TEMPORARY)
-
 
141
        return;
-
 
142
 
137
    memset(&call, 0, sizeof(call));
143
    memset(&call, 0, sizeof(call));
138
    rc = debug_mem_read(phoneid, &call.args, sc_args[1], sizeof(call.args));
144
    rc = debug_mem_read(phoneid, &call.args, sc_args[1], sizeof(call.args));
139
 
145
 
140
    if (rc >= 0) {
146
    if (rc >= 0) {
141
        ipc_parse_call_out(sc_args[0], &call);
147
        ipc_parse_call_out(sc_args[0], &call, sc_rc);
-
 
148
    }
-
 
149
}
-
 
150
 
-
 
151
void sc_ipc_call_sync_fast(unsigned *sc_args)
-
 
152
{
-
 
153
    ipc_call_t question, reply;
-
 
154
    int rc;
-
 
155
    int phoneidx;
-
 
156
 
-
 
157
    printf("sc_ipc_call_sync_fast()\n");
-
 
158
    phoneidx = sc_args[0];
-
 
159
 
-
 
160
    IPC_SET_METHOD(question, sc_args[1]);
-
 
161
    IPC_SET_ARG1(question, sc_args[2]);
-
 
162
    IPC_SET_ARG2(question, sc_args[3]);
-
 
163
    IPC_SET_ARG3(question, sc_args[4]);
-
 
164
    IPC_SET_ARG4(question, 0);
-
 
165
    IPC_SET_ARG5(question, 0);
-
 
166
 
-
 
167
    printf("memset\n");
-
 
168
    memset(&reply, 0, sizeof(reply));
-
 
169
    printf("debug_mem_read(phone=%d, buffer_ptr=%u, src_addr=%d, n=%d\n",
-
 
170
        phoneid, &reply.args, sc_args[5], sizeof(reply.args));
-
 
171
    rc = debug_mem_read(phoneid, &reply.args, sc_args[5], sizeof(reply.args));
-
 
172
    printf("dmr->%d\n", rc);
-
 
173
    if (rc < 0) return;
-
 
174
 
-
 
175
    printf("call ipc_parse_call_sync\n");
-
 
176
    ipc_parse_call_sync(phoneidx, &question, &reply);
142
    }
177
}
-
 
178
 
-
 
179
void sc_ipc_call_sync_slow(unsigned *sc_args)
-
 
180
{
-
 
181
    ipc_call_t question, reply;
-
 
182
    int rc;
-
 
183
 
-
 
184
    memset(&question, 0, sizeof(question));
-
 
185
    rc = debug_mem_read(phoneid, &question.args, sc_args[1], sizeof(question.args));
-
 
186
    printf("dmr->%d\n", rc);
-
 
187
    if (rc < 0) return;
-
 
188
 
-
 
189
    memset(&reply, 0, sizeof(reply));
-
 
190
    rc = debug_mem_read(phoneid, &reply.args, sc_args[2], sizeof(reply.args));
-
 
191
    printf("dmr->%d\n", rc);
-
 
192
    if (rc < 0) return;
-
 
193
 
-
 
194
    ipc_parse_call_sync(sc_args[0], &question, &reply);
143
}
195
}
144
 
196
 
145
void sc_ipc_wait(unsigned *sc_args, int sc_rc)
197
void sc_ipc_wait(unsigned *sc_args, int sc_rc)
146
{
198
{
147
    ipc_call_t call;
199
    ipc_call_t call;
148
    int rc;
200
    int rc;
149
 
201
 
150
    if (sc_rc == 0) return 0;
202
    if (sc_rc == 0) return 0;
151
 
203
 
152
    memset(&call, 0, sizeof(call));
204
    memset(&call, 0, sizeof(call));
153
    rc = debug_mem_read(phoneid, &call, sc_args[0], sizeof(call));
205
    rc = debug_mem_read(phoneid, &call, sc_args[0], sizeof(call));
154
    printf("debug_mem_read(phone %d, dest %d, app-mem src %d, size %d -> %d\n",
206
//  printf("debug_mem_read(phone %d, dest %d, app-mem src %d, size %d -> %d\n",
155
        phoneid, (int)&call, sc_args[0], sizeof(call), rc);
207
//      phoneid, (int)&call, sc_args[0], sizeof(call), rc);
156
 
208
 
157
    if (rc >= 0) {
209
    if (rc >= 0) {
158
        ipc_parse_call_in(&call);
210
        ipc_parse_call_in(&call, sc_rc);
159
    }
211
    }
160
}
212
}
161
 
213
 
162
void event_syscall(unsigned thread_id, unsigned thread_hash,  unsigned sc_id, int sc_rc)
214
void event_syscall(unsigned thread_id, unsigned thread_hash,  unsigned sc_id, int sc_rc)
163
{
215
{
164
    unsigned sc_args[6];
216
    unsigned sc_args[6];
165
    int rv_type;
217
    int rv_type;
166
    int rc;
218
    int rc;
167
 
219
 
168
    /* Read syscall arguments */
220
    /* Read syscall arguments */
169
    rc = debug_args_read(phoneid, thread_hash, sc_args);
221
    rc = debug_args_read(phoneid, thread_hash, sc_args);
170
 
222
 
171
    async_serialize_start();
223
    async_serialize_start();
172
 
224
 
173
    printf("[%d] ", thread_id);
225
//  printf("[%d] ", thread_id);
174
 
226
 
175
    if (rc < 0) {
227
    if (rc < 0) {
176
        printf("error\n");
228
        printf("error\n");
177
        async_serialize_end();
229
        async_serialize_end();
178
        return;
230
        return;
179
    }
231
    }
180
 
232
 
181
    /* Print syscall name, id and arguments */
233
    /* Print syscall name, id and arguments */
182
    printf("%s", syscall_desc[sc_id].name);
234
    printf("%s", syscall_desc[sc_id].name);
183
    print_sc_args(sc_args, syscall_desc[sc_id].n_args);
235
    print_sc_args(sc_args, syscall_desc[sc_id].n_args);
184
    rv_type = syscall_desc[sc_id].rv_type;
236
    rv_type = syscall_desc[sc_id].rv_type;
185
    print_sc_retval(sc_rc, rv_type);
237
    print_sc_retval(sc_rc, rv_type);
186
 
238
 
187
    switch (sc_id) {
239
    switch (sc_id) {
188
    case SYS_IPC_CALL_ASYNC_FAST:
240
    case SYS_IPC_CALL_ASYNC_FAST:
189
        sc_ipc_call_async_fast(sc_args);
241
        sc_ipc_call_async_fast(sc_args, sc_rc);
190
        break;
242
        break;
191
    case SYS_IPC_CALL_ASYNC_SLOW:
243
    case SYS_IPC_CALL_ASYNC_SLOW:
-
 
244
        sc_ipc_call_async_slow(sc_args, sc_rc);
-
 
245
        break;
-
 
246
    case SYS_IPC_CALL_SYNC_FAST:
-
 
247
        sc_ipc_call_sync_fast(sc_args);
-
 
248
        break;
-
 
249
    case SYS_IPC_CALL_SYNC_SLOW:
192
        sc_ipc_call_async_slow(sc_args);
250
        sc_ipc_call_sync_slow(sc_args);
193
        break;
251
        break;
194
    case SYS_IPC_WAIT:
252
    case SYS_IPC_WAIT:
195
        sc_ipc_wait(sc_args, sc_rc);
253
        sc_ipc_wait(sc_args, sc_rc);
196
        break;
254
        break;
197
    default:
255
    default:
198
        break;
256
        break;
199
    }
257
    }
200
 
258
 
201
    async_serialize_end();
259
    async_serialize_end();
202
}
260
}
203
 
261
 
204
void event_new_thread(unsigned hash)
262
void event_new_thread(unsigned hash)
205
{
263
{
206
    async_serialize_start();
264
    async_serialize_start();
207
    printf("new thread, hash 0x%x\n", hash);
265
    printf("new thread, hash 0x%x\n", hash);
208
    async_serialize_end();
266
    async_serialize_end();
209
 
267
 
210
    thread_trace_start(hash);
268
    thread_trace_start(hash);
211
}
269
}
212
 
270
 
213
void trace_loop(void *thread_hash_arg)
271
void trace_loop(void *thread_hash_arg)
214
{
272
{
215
    int rc;
273
    int rc;
216
    unsigned ev_type;
274
    unsigned ev_type;
217
    unsigned thread_hash;
275
    unsigned thread_hash;
218
    unsigned thread_id;
276
    unsigned thread_id;
219
    unsigned val0, val1;
277
    unsigned val0, val1;
220
 
278
 
221
    thread_hash = (unsigned)thread_hash_arg;
279
    thread_hash = (unsigned)thread_hash_arg;
222
    thread_id = next_thread_id++;
280
    thread_id = next_thread_id++;
223
 
281
 
224
    printf("trace_loop(%d)\n", thread_id); 
282
    printf("trace_loop(%d)\n", thread_id); 
225
 
283
 
226
    while (!abort_trace) {
284
    while (!abort_trace) {
227
 
285
 
228
        /* Run thread until an event occurs */
286
        /* Run thread until an event occurs */
229
        rc = debug_go(phoneid, thread_hash,
287
        rc = debug_go(phoneid, thread_hash,
230
            &ev_type, &val0, &val1);
288
            &ev_type, &val0, &val1);
231
 
289
 
232
        printf("rc = %d, ev_type=%d\n", rc, ev_type);
290
//      printf("rc = %d, ev_type=%d\n", rc, ev_type);
233
        if (ev_type == UDEBUG_EVENT_FINISHED) {
291
        if (ev_type == UDEBUG_EVENT_FINISHED) {
234
            printf("thread %u debugging finished\n", thread_id);
292
            printf("thread %u debugging finished\n", thread_id);
235
            break;
293
            break;
236
        }
294
        }
237
 
295
 
238
        if (rc >= 0) {
296
        if (rc >= 0) {
239
            switch (ev_type) {
297
            switch (ev_type) {
240
            case UDEBUG_EVENT_SYSCALL:
298
            case UDEBUG_EVENT_SYSCALL:
241
                event_syscall(thread_id, thread_hash, val0, (int)val1);
299
                event_syscall(thread_id, thread_hash, val0, (int)val1);
242
                break;
300
                break;
243
            case UDEBUG_EVENT_NEW_THREAD:
301
            case UDEBUG_EVENT_NEW_THREAD:
244
                event_new_thread(val0);
302
                event_new_thread(val0);
245
                break;
303
                break;
246
            default:
304
            default:
247
                printf("unknown event type %d\n", ev_type);
305
                printf("unknown event type %d\n", ev_type);
248
                break;
306
                break;
249
            }
307
            }
250
        }
308
        }
251
 
309
 
252
    }
310
    }
253
 
311
 
254
    printf("trace_loop(%d) exiting\n", thread_id);
312
    printf("trace_loop(%d) exiting\n", thread_id);
255
}
313
}
256
 
314
 
257
void thread_trace_start(unsigned thread_hash)
315
void thread_trace_start(unsigned thread_hash)
258
{
316
{
259
    fid_t fid;
317
    fid_t fid;
260
 
318
 
261
    fid = fibril_create(trace_loop, (void *)thread_hash);
319
    fid = fibril_create(trace_loop, (void *)thread_hash);
262
    if (fid == 0) {
320
    if (fid == 0) {
263
        printf("Warning: Failed creating fibril\n");
321
        printf("Warning: Failed creating fibril\n");
264
    }
322
    }
265
    fibril_add_ready(fid);
323
    fibril_add_ready(fid);
266
}
324
}
267
 
325
 
268
void trace_active_task(void)
326
void trace_active_task(void)
269
{
327
{
270
    int taskid;
328
    int taskid;
271
    int i;
329
    int i;
272
    int rc;
330
    int rc;
273
 
331
 
274
    printf("Syscall Tracer\n");
332
    printf("Syscall Tracer\n");
275
    printf("Press 'c' to connect\n");
333
    printf("Press 'c' to connect\n");
276
    while ((i = getchar()) != 'c')
334
    while ((i = getchar()) != 'c')
277
        putchar(i);
335
        putchar(i);
278
 
336
 
279
    taskid = 14;
337
    taskid = 14;
280
    rc = task_connect(taskid);
338
    rc = task_connect(taskid);
281
    if (rc < 0) {
339
    if (rc < 0) {
282
        printf("Failed to connect to task %d\n", taskid);
340
        printf("Failed to connect to task %d\n", taskid);
283
        return;
341
        return;
284
    }
342
    }
285
 
343
 
286
    printf("Connected to task %d\n", taskid);
344
    printf("Connected to task %d\n", taskid);
287
 
345
 
288
    rc = get_thread_list();
346
    rc = get_thread_list();
289
    if (rc < 0) {
347
    if (rc < 0) {
290
        printf("Failed to get thread list (error %d)\n", rc);
348
        printf("Failed to get thread list (error %d)\n", rc);
291
        return;
349
        return;
292
    }
350
    }
293
 
351
 
294
    abort_trace = 0;
352
    abort_trace = 0;
295
 
353
 
296
    for (i = 0; i < n_threads; i++) {
354
    for (i = 0; i < n_threads; i++) {
297
        thread_trace_start(thread_hash_buf[i]);
355
        thread_trace_start(thread_hash_buf[i]);
298
    }
356
    }
299
 
357
 
300
    getchar();
358
    getchar();
301
 
359
 
302
    printf("terminate debugging session...\n");
360
    printf("terminate debugging session...\n");
303
    abort_trace = 1;
361
    abort_trace = 1;
304
    debug_end(phoneid);
362
    debug_end(phoneid);
305
    ipc_hangup(phoneid);
363
    ipc_hangup(phoneid);
306
 
364
 
307
    printf("done\n");
365
    printf("done\n");
308
    return;
366
    return;
309
}
367
}
310
 
368
 
311
int main(void)
369
int main(void)
312
{
370
{
313
    next_thread_id = 1;
371
    next_thread_id = 1;
314
 
372
 
315
    while (1) {
373
    while (1) {
316
        trace_active_task();
374
        trace_active_task();
317
    }
375
    }
318
}
376
}
319
 
377
 
320
/** @}
378
/** @}
321
 */
379
 */
322
 
380