Subversion Repositories HelenOS

Rev

Rev 2868 | Rev 2872 | 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"
2871 svoboda 17
#include "ipc.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
 
2871 svoboda 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
 
2832 svoboda 132
void sc_ipc_call_async_slow(unsigned *sc_args)
133
{
2871 svoboda 134
    ipc_call_t call;
2832 svoboda 135
    int rc;
136
 
2871 svoboda 137
    memset(&call, 0, sizeof(call));
138
    rc = debug_mem_read(phoneid, &call.args, sc_args[1], sizeof(call.args));
2832 svoboda 139
 
140
    if (rc >= 0) {
2871 svoboda 141
        ipc_parse_call_out(sc_args[0], &call);
2832 svoboda 142
    }
143
}
144
 
2871 svoboda 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",
155
        phoneid, (int)&call, sc_args[0], sizeof(call), rc);
156
 
157
    if (rc >= 0) {
158
        ipc_parse_call_in(&call);
159
    }
160
}
161
 
2868 svoboda 162
void event_syscall(unsigned thread_id, unsigned thread_hash,  unsigned sc_id, int sc_rc)
2867 svoboda 163
{
164
    unsigned sc_args[6];
165
    int rv_type;
166
    int rc;
167
 
168
    /* Read syscall arguments */
2868 svoboda 169
    rc = debug_args_read(phoneid, thread_hash, sc_args);
2867 svoboda 170
 
171
    async_serialize_start();
172
 
2868 svoboda 173
    printf("[%d] ", thread_id);
2867 svoboda 174
 
175
    if (rc < 0) {
176
        printf("error\n");
177
        async_serialize_end();
178
        return;
179
    }
180
 
181
    /* Print syscall name, id and arguments */
182
    printf("%s", syscall_desc[sc_id].name);
183
    print_sc_args(sc_args, syscall_desc[sc_id].n_args);
184
    rv_type = syscall_desc[sc_id].rv_type;
185
    print_sc_retval(sc_rc, rv_type);
186
 
187
    switch (sc_id) {
2871 svoboda 188
    case SYS_IPC_CALL_ASYNC_FAST:
189
        sc_ipc_call_async_fast(sc_args);
190
        break;
2867 svoboda 191
    case SYS_IPC_CALL_ASYNC_SLOW:
192
        sc_ipc_call_async_slow(sc_args);
193
        break;
2871 svoboda 194
    case SYS_IPC_WAIT:
195
        sc_ipc_wait(sc_args, sc_rc);
196
        break;
2867 svoboda 197
    default:
198
        break;
199
    }
200
 
201
    async_serialize_end();
202
}
203
 
204
void event_new_thread(unsigned hash)
205
{
206
    async_serialize_start();
207
    printf("new thread, hash 0x%x\n", hash);
208
    async_serialize_end();
2868 svoboda 209
 
210
    thread_trace_start(hash);
2867 svoboda 211
}
212
 
2868 svoboda 213
void trace_loop(void *thread_hash_arg)
2835 svoboda 214
{
2832 svoboda 215
    int rc;
216
    unsigned ev_type;
2868 svoboda 217
    unsigned thread_hash;
218
    unsigned thread_id;
2867 svoboda 219
    unsigned val0, val1;
2832 svoboda 220
 
2868 svoboda 221
    thread_hash = (unsigned)thread_hash_arg;
222
    thread_id = next_thread_id++;
2835 svoboda 223
 
2868 svoboda 224
    printf("trace_loop(%d)\n", thread_id); 
225
 
2835 svoboda 226
    while (!abort_trace) {
227
 
2867 svoboda 228
        /* Run thread until an event occurs */
2868 svoboda 229
        rc = debug_go(phoneid, thread_hash,
2867 svoboda 230
            &ev_type, &val0, &val1);
2832 svoboda 231
 
2838 svoboda 232
        printf("rc = %d, ev_type=%d\n", rc, ev_type);
233
        if (ev_type == UDEBUG_EVENT_FINISHED) {
2868 svoboda 234
            printf("thread %u debugging finished\n", thread_id);
2838 svoboda 235
            break;
236
        }
237
 
2832 svoboda 238
        if (rc >= 0) {
2867 svoboda 239
            switch (ev_type) {
240
            case UDEBUG_EVENT_SYSCALL:
2868 svoboda 241
                event_syscall(thread_id, thread_hash, val0, (int)val1);
2867 svoboda 242
                break;
243
            case UDEBUG_EVENT_NEW_THREAD:
244
                event_new_thread(val0);
245
                break;
246
            default:
247
                printf("unknown event type %d\n", ev_type);
248
                break;
249
            }
2832 svoboda 250
        }
251
 
252
    }
2835 svoboda 253
 
2868 svoboda 254
    printf("trace_loop(%d) exiting\n", thread_id);
2832 svoboda 255
}
256
 
2868 svoboda 257
void thread_trace_start(unsigned thread_hash)
258
{
259
    fid_t fid;
2832 svoboda 260
 
2868 svoboda 261
    fid = fibril_create(trace_loop, (void *)thread_hash);
262
    if (fid == 0) {
263
        printf("Warning: Failed creating fibril\n");
264
    }
265
    fibril_add_ready(fid);
266
}
267
 
2832 svoboda 268
void trace_active_task(void)
269
{
270
    int taskid;
271
    int i;
272
    int rc;
273
 
274
    printf("Syscall Tracer\n");
275
    printf("Press 'c' to connect\n");
276
    while ((i = getchar()) != 'c')
277
        putchar(i);
278
 
2850 svoboda 279
    taskid = 14;
2832 svoboda 280
    rc = task_connect(taskid);
281
    if (rc < 0) {
282
        printf("Failed to connect to task %d\n", taskid);
283
        return;
284
    }
285
 
286
    printf("Connected to task %d\n", taskid);
287
 
288
    rc = get_thread_list();
289
    if (rc < 0) {
290
        printf("Failed to get thread list (error %d)\n", rc);
291
        return;
292
    }
293
 
2850 svoboda 294
    abort_trace = 0;
2832 svoboda 295
 
2850 svoboda 296
    for (i = 0; i < n_threads; i++) {
2868 svoboda 297
        thread_trace_start(thread_hash_buf[i]);
2850 svoboda 298
    }
299
 
300
    getchar();
301
 
302
    printf("terminate debugging session...\n");
303
    abort_trace = 1;
2835 svoboda 304
    debug_end(phoneid);
2850 svoboda 305
    ipc_hangup(phoneid);
306
 
2832 svoboda 307
    printf("done\n");
308
    return;
309
}
310
 
311
int main(void)
312
{
2868 svoboda 313
    next_thread_id = 1;
314
 
2835 svoboda 315
    while (1) {
316
        trace_active_task();
317
    }
2832 svoboda 318
}
319
 
320
/** @}
321
 */