Subversion Repositories HelenOS

Rev

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

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