Subversion Repositories HelenOS

Rev

Rev 2877 | Rev 2880 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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