Subversion Repositories HelenOS

Rev

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