Subversion Repositories HelenOS

Rev

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