Subversion Repositories HelenOS

Rev

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

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