Subversion Repositories HelenOS

Rev

Rev 2867 | Rev 2871 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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