Subversion Repositories HelenOS

Rev

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