Subversion Repositories HelenOS

Rev

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