Subversion Repositories HelenOS

Rev

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

Rev 3429 Rev 3472
1
/*
1
/*
2
 * Copyright (c) 2008 Jiri Svoboda
2
 * Copyright (c) 2008 Jiri Svoboda
3
 * All rights reserved.
3
 * All rights reserved.
4
 *
4
 *
5
 * Redistribution and use in source and binary forms, with or without
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
6
 * modification, are permitted provided that the following conditions
7
 * are met:
7
 * are met:
8
 *
8
 *
9
 * - Redistributions of source code must retain the above copyright
9
 * - Redistributions of source code must retain the above copyright
10
 *   notice, this list of conditions and the following disclaimer.
10
 *   notice, this list of conditions and the following disclaimer.
11
 * - Redistributions in binary form must reproduce the above copyright
11
 * - Redistributions in binary form must reproduce the above copyright
12
 *   notice, this list of conditions and the following disclaimer in the
12
 *   notice, this list of conditions and the following disclaimer in the
13
 *   documentation and/or other materials provided with the distribution.
13
 *   documentation and/or other materials provided with the distribution.
14
 * - The name of the author may not be used to endorse or promote products
14
 * - The name of the author may not be used to endorse or promote products
15
 *   derived from this software without specific prior written permission.
15
 *   derived from this software without specific prior written permission.
16
 *
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
 */
27
 */
28
 
28
 
29
/** @addtogroup debug
29
/** @addtogroup debug
30
 * @{
30
 * @{
31
 */
31
 */
32
/** @file
32
/** @file
33
 */
33
 */
34
 
34
 
35
#include <stdio.h>
35
#include <stdio.h>
36
#include <stdlib.h>
36
#include <stdlib.h>
37
#include <unistd.h>
37
#include <unistd.h>
38
#include <syscall.h>
38
#include <syscall.h>
39
#include <ipc/ipc.h>
39
#include <ipc/ipc.h>
40
#include <fibril.h>
40
#include <fibril.h>
-
 
41
#include <loader/loader.h>
41
#include <errno.h>
42
#include <errno.h>
42
#include <udebug.h>
43
#include <udebug.h>
43
#include <async.h>
44
#include <async.h>
44
#include <string.h>
45
#include <string.h>
45
 
46
 
46
#include "cmd.h"
47
#include "cmd.h"
47
#include "cons.h"
48
#include "cons.h"
48
#include "dthread.h"
49
#include "dthread.h"
49
#include "breakpoint.h"
50
#include "breakpoint.h"
50
#include "include/arch.h"
51
#include "include/arch.h"
51
#include "main.h"
52
#include "main.h"
52
 
53
 
53
void thread_debug_start(unsigned thread_hash);
54
void thread_debug_start(unsigned thread_hash);
54
 
55
 
55
#define IN_BUF_SIZE 64
56
#define IN_BUF_SIZE 64
56
static char in_buf[IN_BUF_SIZE];
57
static char in_buf[IN_BUF_SIZE];
57
 
58
 
58
#define MAX_ARGC 10
59
#define MAX_ARGC 10
59
int cmd_argc;
60
int cmd_argc;
60
char *cmd_argv[MAX_ARGC + 1];   /* need one spare field for cmd_split() */
61
char *cmd_argv[MAX_ARGC + 1];   /* need one spare field for cmd_split() */
61
 
62
 
62
 
63
 
63
int next_thread_id;
64
int next_thread_id;
64
 
65
 
65
int app_phone;
66
int app_phone;
66
volatile bool abort_debug;
67
volatile bool abort_debug;
67
 
68
 
68
volatile int paused;
69
volatile int paused;
69
 
70
 
-
 
71
static task_id_t task_id;
-
 
72
static loader_t *task_ldr;
-
 
73
 
-
 
74
static int program_run_fibril(void *arg);
-
 
75
 
-
 
76
static void program_run(void)
-
 
77
{
-
 
78
    fid_t fid;
-
 
79
 
-
 
80
    fid = fibril_create(program_run_fibril, NULL);
-
 
81
    if (fid == 0) {
-
 
82
        printf("Error creating fibril\n");
-
 
83
        exit(1);
-
 
84
    }
-
 
85
 
-
 
86
    fibril_add_ready(fid);
-
 
87
}
-
 
88
 
-
 
89
static int program_run_fibril(void *arg)
-
 
90
{
-
 
91
    int rc;
-
 
92
 
-
 
93
    /*
-
 
94
     * This must be done in background as it will block until
-
 
95
     * we let the task reply to this call.
-
 
96
     */
-
 
97
    rc = loader_run(task_ldr);
-
 
98
    if (rc != 0) {
-
 
99
        printf("Error running program\n");
-
 
100
        exit(1);
-
 
101
    }
-
 
102
 
-
 
103
    free(task_ldr);
-
 
104
    task_ldr = NULL;
-
 
105
 
-
 
106
    return 0;
-
 
107
}
-
 
108
 
-
 
109
static loader_t *preload_task(const char *path, char *const argv[],
-
 
110
    task_id_t *task_id)
-
 
111
{
-
 
112
    loader_t *ldr;
-
 
113
    int rc;
-
 
114
 
-
 
115
    /* Spawn a program loader */   
-
 
116
    ldr = loader_spawn();
-
 
117
    if (ldr == NULL)
-
 
118
        return 0;
-
 
119
 
-
 
120
    /* Get task ID. */
-
 
121
    rc = loader_get_task_id(ldr, task_id);
-
 
122
    if (rc != EOK)
-
 
123
        goto error;
-
 
124
 
-
 
125
    /* Send program pathname */
-
 
126
    rc = loader_set_pathname(ldr, path);
-
 
127
    if (rc != EOK)
-
 
128
        goto error;
-
 
129
 
-
 
130
    /* Send arguments */
-
 
131
    rc = loader_set_args(ldr, argv);
-
 
132
    if (rc != EOK)
-
 
133
        goto error;
-
 
134
 
-
 
135
    /* Load the program. */
-
 
136
    rc = loader_load_program(ldr);
-
 
137
    if (rc != EOK)
-
 
138
        goto error;
-
 
139
 
-
 
140
    /* Success */
-
 
141
    return ldr;
-
 
142
 
-
 
143
    /* Error exit */
-
 
144
error:
-
 
145
    loader_abort(ldr);
-
 
146
    free(ldr);
-
 
147
    return NULL;
-
 
148
}
-
 
149
 
-
 
150
 
70
static void command_split(char *cmd_str)
151
static void command_split(char *cmd_str)
71
{
152
{
72
    char *p = cmd_str;
153
    char *p = cmd_str;
73
 
154
 
74
    if (*p == '\0') {
155
    if (*p == '\0') {
75
        cmd_argc = 0;
156
        cmd_argc = 0;
76
        return;
157
        return;
77
    }
158
    }
78
 
159
 
79
    cmd_argc = 1;
160
    cmd_argc = 1;
80
    cmd_argv[0] = p;
161
    cmd_argv[0] = p;
81
 
162
 
82
    while (*p != '\0') {
163
    while (*p != '\0') {
83
        if (*p == ' ') {
164
        if (*p == ' ') {
84
            cmd_argv[cmd_argc++] = p + 1;
165
            cmd_argv[cmd_argc++] = p + 1;
85
            *p = '\0';
166
            *p = '\0';
86
        }
167
        }
87
        ++p;
168
        ++p;
88
    }
169
    }
89
}
170
}
90
 
171
 
91
static void command_run(void)
172
static void command_run(void)
92
{
173
{
93
    int i;
174
    int i;
94
    int cmp_len;
175
    int cmp_len;
95
    int len;
176
    int len;
96
 
177
 
97
    int idx_found;
178
    int idx_found;
98
    int num_found;
179
    int num_found;
99
 
180
 
100
    len = strlen(cmd_argv[0]);
181
    len = strlen(cmd_argv[0]);
101
    cmp_len = 1;
182
    cmp_len = 1;
102
 
183
 
103
    /* Silence warnings */
184
    /* Silence warnings */
104
    num_found = 0;
185
    num_found = 0;
105
    idx_found = 0;
186
    idx_found = 0;
106
 
187
 
107
    while (cmp_len <= len + 1) {
188
    while (cmp_len <= len + 1) {
108
 
189
 
109
        num_found = 0;
190
        num_found = 0;
110
        i = 0;
191
        i = 0;
111
        while (cmd_table[i].name != NULL) {
192
        while (cmd_table[i].name != NULL) {
112
            if (strncmp(cmd_table[i].name, cmd_argv[0], cmp_len) == 0) {
193
            if (strncmp(cmd_table[i].name, cmd_argv[0], cmp_len) == 0) {
113
                idx_found = i;
194
                idx_found = i;
114
                ++num_found;
195
                ++num_found;
115
            }
196
            }
116
            ++i;
197
            ++i;
117
        }
198
        }
118
 
199
 
119
        if (num_found < 2) break;
200
        if (num_found < 2) break;
120
 
201
 
121
        ++cmp_len;
202
        ++cmp_len;
122
    }
203
    }
123
 
204
 
124
    if (num_found == 0) {
205
    if (num_found == 0) {
125
        cons_printf("Unknown command. Try one of:\n");
206
        cons_printf("Unknown command. Try one of:\n");
126
        cmd_help(0, NULL);
207
        cmd_help(0, NULL);
127
        return;
208
        return;
128
    }
209
    }
129
 
210
 
130
    if (cmd_argc - 1 != cmd_table[idx_found].argc) {
211
    if (cmd_argc - 1 != cmd_table[idx_found].argc) {
131
        cons_printf("Command '%s' expects %d arguments\n",
212
        cons_printf("Command '%s' expects %d arguments\n",
132
        cmd_table[idx_found].name, cmd_table[idx_found].argc);
213
        cmd_table[idx_found].name, cmd_table[idx_found].argc);
133
        return;
214
        return;
134
    }
215
    }
135
 
216
 
136
    (*cmd_table[idx_found].proc)(cmd_argc, cmd_argv);
217
    (*cmd_table[idx_found].proc)(cmd_argc, cmd_argv);
137
}
218
}
138
 
219
 
139
static void thread_stop(void)
220
static void thread_stop(void)
140
{
221
{
141
    dthread_t *dt;
222
    dthread_t *dt;
142
    uintptr_t pc;
223
    uintptr_t pc;
143
 
224
 
144
    dt = dthread_get();
225
    dt = dthread_get();
145
    pc = dthread_get_pc(dt);
226
    pc = dthread_get_pc(dt);
146
    cons_printf("[thread %d] stopped at 0x%lx\n", dt->id, pc);
227
    cons_printf("[thread %d] stopped at 0x%lx\n", dt->id, pc);
147
    dthread_stop_me();
228
    dthread_stop_me();
148
    cons_printf("[thread %d] go\n", dt->id);
229
    cons_printf("[thread %d] go\n", dt->id);
149
}
230
}
150
 
231
 
151
/*
232
/*
152
 * Called by a fibril (from arch code) when a breakpoint is hit.
233
 * Called by a fibril (from arch code) when a breakpoint is hit.
153
 */
234
 */
154
void breakpoint_hit(breakpoint_t *b)
235
void breakpoint_hit(breakpoint_t *b)
155
{
236
{
156
    dthread_t *dt;
237
    dthread_t *dt;
157
 
238
 
158
    dt = dthread_get();
239
    dt = dthread_get();
159
    cons_printf("Thread %d hit breakpoint %d at 0x%lx\n",
240
    cons_printf("Thread %d hit breakpoint %d at 0x%lx\n",
160
        dt->id, b->id, b->addr);
241
        dt->id, b->id, b->addr);
161
    thread_stop();
242
    thread_stop();
162
}
243
}
163
 
244
 
164
/*
245
/*
165
 * Called by a fibril (from arch code) when a single instruction
246
 * Called by a fibril (from arch code) when a single instruction
166
 * in singlestep is executed
247
 * in singlestep is executed
167
 */
248
 */
168
void singlestep_hit(void)
249
void singlestep_hit(void)
169
{
250
{
170
    cons_printf("singlestep hit\n");
251
    cons_printf("singlestep hit\n");
171
    thread_stop();
252
    thread_stop();
172
}
253
}
173
 
254
 
174
static int task_connect(task_id_t task_id)
255
static int connect_task(task_id_t task_id)
175
{
256
{
176
    int rc;
257
    int rc;
177
    unsigned evmask;
258
    unsigned evmask;
178
 
259
 
179
    cons_printf("ipc_connect_kbox(%;;d)... ", task_id);
260
    cons_printf("ipc_connect_kbox(%;;d)... ", task_id);
180
    rc = ipc_connect_kbox(task_id);
261
    rc = ipc_connect_kbox(task_id);
181
    cons_printf("-> %d\n", rc);
262
    cons_printf("-> %d\n", rc);
182
    app_phone = rc;
263
    app_phone = rc;
183
    if (rc < 0) return rc;
264
    if (rc < 0) return rc;
184
 
265
 
185
    cons_printf("udebug_begin()... ");
266
    cons_printf("udebug_begin()... ");
186
    rc = udebug_begin(app_phone);
267
    rc = udebug_begin(app_phone);
187
    cons_printf("-> %d\n", rc);
268
    cons_printf("-> %d\n", rc);
188
    if (rc < 0) return rc;
269
    if (rc < 0) return rc;
189
 
270
 
190
    evmask = UDEBUG_EM_ALL & ~(UDEBUG_EM_SYSCALL_B | UDEBUG_EM_SYSCALL_E);
271
    evmask = UDEBUG_EM_ALL & ~(UDEBUG_EM_SYSCALL_B | UDEBUG_EM_SYSCALL_E);
191
    cons_printf("udebug_set_evmask(0x%x)... ", evmask);
272
    cons_printf("udebug_set_evmask(0x%x)... ", evmask);
192
    rc = udebug_set_evmask(app_phone, evmask);
273
    rc = udebug_set_evmask(app_phone, evmask);
193
    cons_printf("-> %d\n", rc);
274
    cons_printf("-> %d\n", rc);
194
    if (rc < 0) return rc;
275
    if (rc < 0) return rc;
195
 
276
 
196
    return 0;
277
    return 0;
197
}
278
}
198
 
279
 
199
#define THASH_BUF_INIT_LENGTH 32
280
#define THASH_BUF_INIT_LENGTH 32
200
 
281
 
201
static int get_thread_list(thash_t **thash_buf_ptr, int *n)
282
static int get_thread_list(thash_t **thash_buf_ptr, int *n)
202
{
283
{
203
    int rc;
284
    int rc;
204
    size_t tb_copied;
285
    size_t tb_copied;
205
    size_t tb_needed;
286
    size_t tb_needed;
206
    int i;
287
    int i;
207
    size_t tb_size;
288
    size_t tb_size;
208
    thash_t *thash_buf;
289
    thash_t *thash_buf;
209
 
290
 
210
    tb_size = THASH_BUF_INIT_LENGTH * sizeof(thash_t);
291
    tb_size = THASH_BUF_INIT_LENGTH * sizeof(thash_t);
211
    thash_buf = malloc(tb_size);
292
    thash_buf = malloc(tb_size);
212
 
293
 
213
    rc = udebug_thread_read(app_phone, thash_buf,
294
    rc = udebug_thread_read(app_phone, thash_buf,
214
        tb_size, &tb_copied, &tb_needed);
295
        tb_size, &tb_copied, &tb_needed);
215
    if (rc < 0) return rc;
296
    if (rc < 0) return rc;
216
 
297
 
217
    if (tb_needed > tb_size) {
298
    if (tb_needed > tb_size) {
218
        /* Larger buffer needed  */
299
        /* Larger buffer needed  */
219
 
300
 
220
        free(thash_buf);
301
        free(thash_buf);
221
 
302
 
222
        tb_size = tb_needed;
303
        tb_size = tb_needed;
223
        thash_buf = malloc(tb_size);
304
        thash_buf = malloc(tb_size);
224
 
305
 
225
        if (!thash_buf) {
306
        if (!thash_buf) {
226
            printf("malloc failed\n");
307
            printf("malloc failed\n");
227
            exit(1);
308
            exit(1);
228
        }
309
        }
229
 
310
 
230
        /* Try again */
311
        /* Try again */
231
       
312
       
232
        rc = udebug_thread_read(app_phone, thash_buf,
313
        rc = udebug_thread_read(app_phone, thash_buf,
233
            tb_size, &tb_copied, &tb_needed);
314
            tb_size, &tb_copied, &tb_needed);
234
 
315
 
235
        if (rc < 0) return rc;
316
        if (rc < 0) return rc;
236
    }
317
    }
237
 
318
 
238
    *n = tb_copied / sizeof(thash_t);
319
    *n = tb_copied / sizeof(thash_t);
239
 
320
 
240
    cons_printf("thread hashes:");
321
    cons_printf("thread hashes:");
241
 
322
 
242
    for (i = 0; i < *n; ++i) {
323
    for (i = 0; i < *n; ++i) {
243
        cons_printf("0x%x\n", thash_buf[i]);
324
        cons_printf("0x%x\n", thash_buf[i]);
244
    }
325
    }
245
 
326
 
246
    cons_printf("Total of %u threads\n", *n);
327
    cons_printf("Total of %u threads\n", *n);
247
 
328
 
248
    *thash_buf_ptr = thash_buf;
329
    *thash_buf_ptr = thash_buf;
249
 
330
 
250
    return 0;
331
    return 0;
251
}
332
}
252
 
333
 
253
static void event_thread_b(unsigned hash)
334
static void event_thread_b(unsigned hash)
254
{
335
{
255
    async_serialize_start();
336
    async_serialize_start();
256
    cons_printf("new thread, hash 0x%x\n", hash);
337
    cons_printf("new thread, hash 0x%x\n", hash);
257
    async_serialize_end();
338
    async_serialize_end();
258
 
339
 
259
    thread_debug_start(hash);
340
    thread_debug_start(hash);
260
}
341
}
261
 
342
 
262
static void debug_event(thash_t thash, udebug_event_t ev_type, sysarg_t val0)
343
static void debug_event(thash_t thash, udebug_event_t ev_type, sysarg_t val0)
263
{
344
{
264
    switch (ev_type) {
345
    switch (ev_type) {
265
    case UDEBUG_EVENT_STOP:
346
    case UDEBUG_EVENT_STOP:
266
        cons_printf("stop event\n");
347
        cons_printf("stop event\n");
267
        thread_stop();
348
        thread_stop();
268
        break;
349
        break;
269
    case UDEBUG_EVENT_THREAD_B:
350
    case UDEBUG_EVENT_THREAD_B:
270
        event_thread_b(val0);
351
        event_thread_b(val0);
271
        break;
352
        break;
272
    case UDEBUG_EVENT_THREAD_E:
353
    case UDEBUG_EVENT_THREAD_E:
273
        cons_printf("thread 0x%x exited\n", val0);
354
        cons_printf("thread 0x%x exited\n", val0);
274
        abort_debug = true;
355
        abort_debug = true;
275
        break;
356
        break;
276
    case UDEBUG_EVENT_BREAKPOINT:
357
    case UDEBUG_EVENT_BREAKPOINT:
277
        arch_event_breakpoint(thash);
358
        arch_event_breakpoint(thash);
278
        break;
359
        break;
279
    case UDEBUG_EVENT_TRAP:
360
    case UDEBUG_EVENT_TRAP:
280
        arch_event_trap(dthread_get());
361
        arch_event_trap(dthread_get());
281
        break;
362
        break;
282
    default:
363
    default:
283
        cons_printf("unknown event type %d\n", ev_type);
364
        cons_printf("unknown event type %d\n", ev_type);
284
        break;
365
        break;
285
    }
366
    }
286
}
367
}
287
 
368
 
288
static int debug_loop(void *dt_arg)
369
static int debug_loop(void *dt_arg)
289
{
370
{
290
    int rc;
371
    int rc;
291
    udebug_event_t ev_type;
372
    udebug_event_t ev_type;
292
    unsigned val0, val1;
373
    unsigned val0, val1;
293
    dthread_t *dt;
374
    dthread_t *dt;
294
 
375
 
295
    dt = (dthread_t *)dt_arg;
376
    dt = (dthread_t *)dt_arg;
296
 
377
 
297
    cons_printf("debug_loop(%d)\n", dt->id);
378
    cons_printf("debug_loop(%d)\n", dt->id);
298
 
379
 
299
    while (!abort_debug) {
380
    while (!abort_debug) {
300
 
381
 
301
        /* Run thread until an event occurs */
382
        /* Run thread until an event occurs */
302
        rc = udebug_go(app_phone, dt->hash, &ev_type, &val0, &val1);
383
        rc = udebug_go(app_phone, dt->hash, &ev_type, &val0, &val1);
303
 
384
 
304
        if (ev_type == UDEBUG_EVENT_FINISHED) {
385
        if (ev_type == UDEBUG_EVENT_FINISHED) {
305
            cons_printf("thread %u debugging finished\n", dt->id);
386
            cons_printf("thread %u debugging finished\n", dt->id);
306
            break;
387
            break;
307
        }
388
        }
308
        if (rc >= 0) debug_event(dt->hash, ev_type, val0);
389
        if (rc >= 0) debug_event(dt->hash, ev_type, val0);
309
    }
390
    }
310
 
391
 
311
    cons_printf("debug_loop(%d) exiting\n", dt->id);
392
    cons_printf("debug_loop(%d) exiting\n", dt->id);
312
    return 0;
393
    return 0;
313
}
394
}
314
 
395
 
315
void thread_debug_start(unsigned thash)
396
void thread_debug_start(unsigned thash)
316
{
397
{
317
    fid_t fid;
398
    fid_t fid;
318
    dthread_t *dt;
399
    dthread_t *dt;
319
 
400
 
320
    dt = dthread_new(thash);
401
    dt = dthread_new(thash);
321
 
402
 
322
    fid = fibril_create(debug_loop, (void *)dt);
403
    fid = fibril_create(debug_loop, (void *)dt);
323
    if (fid == 0) {
404
    if (fid == 0) {
324
        cons_printf("Warning: Failed creating fibril\n");
405
        cons_printf("Warning: Failed creating fibril\n");
325
    }
406
    }
326
    dt->fid = fid;
407
    dt->fid = fid;
327
 
408
 
328
    fibril_add_ready(fid);
409
    fibril_add_ready(fid);
329
}
410
}
330
 
411
 
331
static void debug_active_task(task_id_t task_id)
412
static void debug_task(task_id_t task_id)
332
{
413
{
333
    int taskid;
-
 
334
    int i;
414
    int i;
335
    int rc;
415
    int rc;
336
 
416
 
337
    thash_t *thash_buffer;
417
    thash_t *thash_buffer;
338
    int n_threads;
418
    int n_threads;
339
 
419
 
340
    cons_printf("Breakpoint Debugger\n");
-
 
341
 
-
 
342
    rc = task_connect(task_id);
-
 
343
    if (rc < 0) {
-
 
344
        cons_printf("Failed to connect to task %lld\n", task_id);
-
 
345
        return;
-
 
346
    }
-
 
347
 
-
 
348
    cons_printf("Connected to task %lld\n", task_id);
-
 
349
 
-
 
350
    rc = get_thread_list(&thash_buffer, &n_threads);
420
    rc = get_thread_list(&thash_buffer, &n_threads);
351
    if (rc < 0) {
421
    if (rc < 0) {
352
        cons_printf("Failed to get thread list\n", rc);
422
        cons_printf("Failed to get thread list\n", rc);
353
        return;
423
        return;
354
    }
424
    }
355
 
425
 
356
    abort_debug = false;
426
    abort_debug = false;
357
 
427
 
358
    for (i = 0; i < n_threads; i++) {
428
    for (i = 0; i < n_threads; i++) {
359
        thread_debug_start(thash_buffer[i]);
429
        thread_debug_start(thash_buffer[i]);
360
    }
430
    }
361
 
431
 
362
    while (!quit) {
432
    while (!quit) {
363
        cons_read_line(in_buf, IN_BUF_SIZE);
433
        cons_read_line(in_buf, IN_BUF_SIZE);
364
        command_split(in_buf);
434
        command_split(in_buf);
365
        if (cmd_argc == 0) continue;
435
        if (cmd_argc == 0) continue;
366
 
436
 
367
        command_run();
437
        command_run();
368
    }
438
    }
369
 
439
 
370
    cons_printf("terminate debugging session...\n");
440
    cons_printf("terminate debugging session...\n");
371
    abort_debug = true;
441
    abort_debug = true;
372
    udebug_end(app_phone);
442
    udebug_end(app_phone);
373
    ipc_hangup(app_phone);
443
    ipc_hangup(app_phone);
374
 
444
 
375
    cons_printf("done\n");
445
    cons_printf("done\n");
376
    return;
446
    return;
377
}
447
}
378
 
448
 
379
static void main_init(void)
449
static void main_init(void)
380
{
450
{
381
    next_thread_id = 1;
451
    next_thread_id = 1;
382
    paused = 0;
452
    paused = 0;
383
   
453
   
384
    list_initialize(&dthreads);
454
    list_initialize(&dthreads);
385
    breakpoint_init();
455
    breakpoint_init();
386
    cwt = NULL;
456
    cwt = NULL;
387
}
457
}
388
 
458
 
389
static void print_syntax()
459
static void print_syntax()
390
{
460
{
-
 
461
    printf("Syntax:\n");
-
 
462
    printf("\tdebug <executable> [<arg1> [...]]\n");
391
    printf("syntax: debug <task_id>\n");
463
    printf("or\tdebug -t <task_id>\n");
392
}
464
}
393
 
465
 
394
int main(int argc, char *argv[])
466
static int parse_args(int argc, char *argv[])
395
{
467
{
396
    task_id_t task_id;
468
    char *arg;
397
    char *err_p;
469
    char *err_p;
398
 
470
 
-
 
471
    task_id = 0;
-
 
472
 
-
 
473
    --argc; ++argv;
-
 
474
 
399
    if (argc != 2) {
475
    while (argc > 0) {
-
 
476
        arg = *argv;
-
 
477
        if (arg[0] == '-') {
-
 
478
            if (arg[1] == 't') {
-
 
479
                /* Trace an already running task */
-
 
480
                --argc; ++argv;
-
 
481
                task_id = strtol(*argv, &err_p, 10);
-
 
482
                task_ldr = NULL;
-
 
483
                if (*err_p) {
400
        printf("Mising argument\n");
484
                    printf("Task ID syntax error\n");
-
 
485
                    print_syntax();
-
 
486
                    return -1;
-
 
487
                }
-
 
488
            } else {
-
 
489
                printf("Uknown option '%s'\n", arg[0]);
401
        print_syntax();
490
                print_syntax();
402
        return 1;
491
                return -1;
-
 
492
            }
-
 
493
        } else {
-
 
494
            break;
-
 
495
        }
-
 
496
 
-
 
497
        --argc; ++argv;
403
    }
498
    }
404
 
499
 
-
 
500
    if (task_id != 0) {
-
 
501
        if (argc == 0) return 0;
405
    task_id = strtol(argv[1], &err_p, 10);
502
        printf("Extra arguments\n");
-
 
503
        print_syntax();
-
 
504
        return -1;
-
 
505
    }
406
 
506
 
407
    if (*err_p) {
507
    if (argc < 1) {
408
        printf("Task ID syntax error\n");
508
        printf("Missing argument\n");
409
        print_syntax();
509
        print_syntax();
410
        return 1;
510
        return -1;
411
    }
511
    }
412
 
512
 
-
 
513
    /* Preload the specified program file. */
-
 
514
    printf("Spawning '%s' with arguments:\n", *argv);
-
 
515
    {
-
 
516
        char **cp = argv;
-
 
517
        while (*cp) printf("'%s'\n", *cp++);
-
 
518
    }
-
 
519
    task_ldr = preload_task(*argv, argv, &task_id);
-
 
520
 
-
 
521
    return 0;
-
 
522
}
-
 
523
 
-
 
524
int main(int argc, char *argv[])
-
 
525
{
-
 
526
    int rc;
-
 
527
 
-
 
528
    cons_printf("Breakpoint Debugger\n");
-
 
529
 
413
    main_init();
530
    main_init();
-
 
531
 
-
 
532
    if (parse_args(argc, argv) < 0)
-
 
533
        return 1;
-
 
534
 
-
 
535
    rc = connect_task(task_id);
-
 
536
    if (rc < 0) {
-
 
537
        printf("Failed connecting to task %lld\n", task_id);
-
 
538
        return 1;
-
 
539
    }
-
 
540
 
-
 
541
    cons_printf("Connected to task %lld\n", task_id);
-
 
542
 
-
 
543
    if (task_ldr != NULL) {
-
 
544
        program_run();
-
 
545
    }
-
 
546
 
414
    debug_active_task(task_id);
547
    debug_task(task_id);
-
 
548
 
-
 
549
    return 0;
415
}
550
}
416
 
551
 
417
/** @}
552
/** @}
418
 */
553
 */
419
 
554