Subversion Repositories HelenOS

Rev

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

Rev 3100 Rev 3429
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 <errno.h>
41
#include <errno.h>
42
#include <udebug.h>
42
#include <udebug.h>
43
#include <async.h>
43
#include <async.h>
44
#include <string.h>
44
#include <string.h>
45
 
45
 
46
#include "cmd.h"
46
#include "cmd.h"
47
#include "cons.h"
47
#include "cons.h"
48
#include "dthread.h"
48
#include "dthread.h"
49
#include "breakpoint.h"
49
#include "breakpoint.h"
50
#include "include/arch.h"
50
#include "include/arch.h"
51
#include "main.h"
51
#include "main.h"
52
 
52
 
53
void thread_debug_start(unsigned thread_hash);
53
void thread_debug_start(unsigned thread_hash);
54
 
54
 
55
#define IN_BUF_SIZE 64
55
#define IN_BUF_SIZE 64
56
static char in_buf[IN_BUF_SIZE];
56
static char in_buf[IN_BUF_SIZE];
57
 
57
 
58
#define MAX_ARGC 10
58
#define MAX_ARGC 10
59
int cmd_argc;
59
int cmd_argc;
60
char *cmd_argv[MAX_ARGC + 1];   /* need one spare field for cmd_split() */
60
char *cmd_argv[MAX_ARGC + 1];   /* need one spare field for cmd_split() */
61
 
61
 
62
 
62
 
63
int next_thread_id;
63
int next_thread_id;
64
 
64
 
65
int app_phone;
65
int app_phone;
66
volatile bool abort_debug;
66
volatile bool abort_debug;
67
 
67
 
68
volatile int paused;
68
volatile int paused;
69
 
69
 
70
static void command_split(char *cmd_str)
70
static void command_split(char *cmd_str)
71
{
71
{
72
    char *p = cmd_str;
72
    char *p = cmd_str;
73
 
73
 
74
    if (*p == '\0') {
74
    if (*p == '\0') {
75
        cmd_argc = 0;
75
        cmd_argc = 0;
76
        return;
76
        return;
77
    }
77
    }
78
 
78
 
79
    cmd_argc = 1;
79
    cmd_argc = 1;
80
    cmd_argv[0] = p;
80
    cmd_argv[0] = p;
81
 
81
 
82
    while (*p != '\0') {
82
    while (*p != '\0') {
83
        if (*p == ' ') {
83
        if (*p == ' ') {
84
            cmd_argv[cmd_argc++] = p + 1;
84
            cmd_argv[cmd_argc++] = p + 1;
85
            *p = '\0';
85
            *p = '\0';
86
        }
86
        }
87
        ++p;
87
        ++p;
88
    }
88
    }
89
}
89
}
90
 
90
 
91
static void command_run(void)
91
static void command_run(void)
92
{
92
{
93
    int i;
93
    int i;
94
    int cmp_len;
94
    int cmp_len;
95
    int len;
95
    int len;
96
 
96
 
97
    int idx_found;
97
    int idx_found;
98
    int num_found;
98
    int num_found;
99
 
99
 
100
    len = strlen(cmd_argv[0]);
100
    len = strlen(cmd_argv[0]);
101
    cmp_len = 1;
101
    cmp_len = 1;
102
 
102
 
103
    /* Silence warnings */
103
    /* Silence warnings */
104
    num_found = 0;
104
    num_found = 0;
105
    idx_found = 0;
105
    idx_found = 0;
106
 
106
 
107
    while (cmp_len <= len + 1) {
107
    while (cmp_len <= len + 1) {
108
 
108
 
109
        num_found = 0;
109
        num_found = 0;
110
        i = 0;
110
        i = 0;
111
        while (cmd_table[i].name != NULL) {
111
        while (cmd_table[i].name != NULL) {
112
            if (strncmp(cmd_table[i].name, cmd_argv[0], cmp_len) == 0) {
112
            if (strncmp(cmd_table[i].name, cmd_argv[0], cmp_len) == 0) {
113
                idx_found = i;
113
                idx_found = i;
114
                ++num_found;
114
                ++num_found;
115
            }
115
            }
116
            ++i;
116
            ++i;
117
        }
117
        }
118
 
118
 
119
        if (num_found < 2) break;
119
        if (num_found < 2) break;
120
 
120
 
121
        ++cmp_len;
121
        ++cmp_len;
122
    }
122
    }
123
 
123
 
124
    if (num_found == 0) {
124
    if (num_found == 0) {
125
        cons_printf("Unknown command. Try one of:\n");
125
        cons_printf("Unknown command. Try one of:\n");
126
        cmd_help(0, NULL);
126
        cmd_help(0, NULL);
127
        return;
127
        return;
128
    }
128
    }
129
 
129
 
130
    if (cmd_argc - 1 != cmd_table[idx_found].argc) {
130
    if (cmd_argc - 1 != cmd_table[idx_found].argc) {
131
        cons_printf("Command '%s' expects %d arguments\n",
131
        cons_printf("Command '%s' expects %d arguments\n",
132
        cmd_table[idx_found].name, cmd_table[idx_found].argc);
132
        cmd_table[idx_found].name, cmd_table[idx_found].argc);
133
        return;
133
        return;
134
    }
134
    }
135
 
135
 
136
    (*cmd_table[idx_found].proc)(cmd_argc, cmd_argv);
136
    (*cmd_table[idx_found].proc)(cmd_argc, cmd_argv);
137
}
137
}
138
 
138
 
139
static void thread_stop(void)
139
static void thread_stop(void)
140
{
140
{
141
    dthread_t *dt;
141
    dthread_t *dt;
142
    uintptr_t pc;
142
    uintptr_t pc;
143
 
143
 
144
    dt = dthread_get();
144
    dt = dthread_get();
145
    pc = dthread_get_pc(dt);
145
    pc = dthread_get_pc(dt);
146
    cons_printf("[thread %d] stopped at 0x%lx\n", dt->id, pc);
146
    cons_printf("[thread %d] stopped at 0x%lx\n", dt->id, pc);
147
    dthread_stop_me();
147
    dthread_stop_me();
148
    cons_printf("[thread %d] go\n", dt->id);
148
    cons_printf("[thread %d] go\n", dt->id);
149
}
149
}
150
 
150
 
151
/*
151
/*
152
 * Called by a fibril (from arch code) when a breakpoint is hit.
152
 * Called by a fibril (from arch code) when a breakpoint is hit.
153
 */
153
 */
154
void breakpoint_hit(breakpoint_t *b)
154
void breakpoint_hit(breakpoint_t *b)
155
{
155
{
156
    dthread_t *dt;
156
    dthread_t *dt;
157
 
157
 
158
    dt = dthread_get();
158
    dt = dthread_get();
159
    cons_printf("Thread %d hit breakpoint %d at 0x%lx\n",
159
    cons_printf("Thread %d hit breakpoint %d at 0x%lx\n",
160
        dt->id, b->id, b->addr);
160
        dt->id, b->id, b->addr);
161
    thread_stop();
161
    thread_stop();
162
}
162
}
163
 
163
 
164
/*
164
/*
165
 * Called by a fibril (from arch code) when a single instruction
165
 * Called by a fibril (from arch code) when a single instruction
166
 * in singlestep is executed
166
 * in singlestep is executed
167
 */
167
 */
168
void singlestep_hit(void)
168
void singlestep_hit(void)
169
{
169
{
170
    cons_printf("singlestep hit\n");
170
    cons_printf("singlestep hit\n");
171
    thread_stop();
171
    thread_stop();
172
}
172
}
173
 
173
 
174
static int task_connect(int taskid)
174
static int task_connect(task_id_t task_id)
175
{
175
{
176
    int rc;
176
    int rc;
177
    unsigned evmask;
177
    unsigned evmask;
178
 
178
 
179
    cons_printf("ipc_connect_kbox(%d)... ", taskid);
179
    cons_printf("ipc_connect_kbox(%;;d)... ", task_id);
180
    rc = ipc_connect_kbox(taskid);
180
    rc = ipc_connect_kbox(task_id);
181
    cons_printf("-> %d\n", rc);
181
    cons_printf("-> %d\n", rc);
182
    app_phone = rc;
182
    app_phone = rc;
183
    if (rc < 0) return rc;
183
    if (rc < 0) return rc;
184
 
184
 
185
    cons_printf("udebug_begin()... ");
185
    cons_printf("udebug_begin()... ");
186
    rc = udebug_begin(app_phone);
186
    rc = udebug_begin(app_phone);
187
    cons_printf("-> %d\n", rc);
187
    cons_printf("-> %d\n", rc);
188
    if (rc < 0) return rc;
188
    if (rc < 0) return rc;
189
 
189
 
190
    evmask = UDEBUG_EM_ALL & ~(UDEBUG_EM_SYSCALL_B | UDEBUG_EM_SYSCALL_E);
190
    evmask = UDEBUG_EM_ALL & ~(UDEBUG_EM_SYSCALL_B | UDEBUG_EM_SYSCALL_E);
191
    cons_printf("udebug_set_evmask(0x%x)... ", evmask);
191
    cons_printf("udebug_set_evmask(0x%x)... ", evmask);
192
    rc = udebug_set_evmask(app_phone, evmask);
192
    rc = udebug_set_evmask(app_phone, evmask);
193
    cons_printf("-> %d\n", rc);
193
    cons_printf("-> %d\n", rc);
194
    if (rc < 0) return rc;
194
    if (rc < 0) return rc;
195
 
195
 
196
    return 0;
196
    return 0;
197
}
197
}
198
 
198
 
199
#define THASH_BUF_INIT_LENGTH 32
199
#define THASH_BUF_INIT_LENGTH 32
200
 
200
 
201
static int get_thread_list(thash_t **thash_buf_ptr, int *n)
201
static int get_thread_list(thash_t **thash_buf_ptr, int *n)
202
{
202
{
203
    int rc;
203
    int rc;
204
    size_t tb_copied;
204
    size_t tb_copied;
205
    size_t tb_needed;
205
    size_t tb_needed;
206
    int i;
206
    int i;
207
    size_t tb_size;
207
    size_t tb_size;
208
    thash_t *thash_buf;
208
    thash_t *thash_buf;
209
 
209
 
210
    tb_size = THASH_BUF_INIT_LENGTH * sizeof(thash_t);
210
    tb_size = THASH_BUF_INIT_LENGTH * sizeof(thash_t);
211
    thash_buf = malloc(tb_size);
211
    thash_buf = malloc(tb_size);
212
 
212
 
213
    rc = udebug_thread_read(app_phone, thash_buf,
213
    rc = udebug_thread_read(app_phone, thash_buf,
214
        tb_size, &tb_copied, &tb_needed);
214
        tb_size, &tb_copied, &tb_needed);
215
    if (rc < 0) return rc;
215
    if (rc < 0) return rc;
216
 
216
 
217
    if (tb_needed > tb_size) {
217
    if (tb_needed > tb_size) {
218
        /* Larger buffer needed  */
218
        /* Larger buffer needed  */
219
 
219
 
220
        free(thash_buf);
220
        free(thash_buf);
221
 
221
 
222
        tb_size = tb_needed;
222
        tb_size = tb_needed;
223
        thash_buf = malloc(tb_size);
223
        thash_buf = malloc(tb_size);
224
 
224
 
225
        if (!thash_buf) {
225
        if (!thash_buf) {
226
            printf("malloc failed\n");
226
            printf("malloc failed\n");
227
            exit(1);
227
            exit(1);
228
        }
228
        }
229
 
229
 
230
        /* Try again */
230
        /* Try again */
231
       
231
       
232
        rc = udebug_thread_read(app_phone, thash_buf,
232
        rc = udebug_thread_read(app_phone, thash_buf,
233
            tb_size, &tb_copied, &tb_needed);
233
            tb_size, &tb_copied, &tb_needed);
234
 
234
 
235
        if (rc < 0) return rc;
235
        if (rc < 0) return rc;
236
    }
236
    }
237
 
237
 
238
    *n = tb_copied / sizeof(thash_t);
238
    *n = tb_copied / sizeof(thash_t);
239
 
239
 
240
    cons_printf("thread hashes:");
240
    cons_printf("thread hashes:");
241
 
241
 
242
    for (i = 0; i < *n; ++i) {
242
    for (i = 0; i < *n; ++i) {
243
        cons_printf("0x%x\n", thash_buf[i]);
243
        cons_printf("0x%x\n", thash_buf[i]);
244
    }
244
    }
245
 
245
 
246
    cons_printf("Total of %u threads\n", *n);
246
    cons_printf("Total of %u threads\n", *n);
247
 
247
 
248
    *thash_buf_ptr = thash_buf;
248
    *thash_buf_ptr = thash_buf;
249
 
249
 
250
    return 0;
250
    return 0;
251
}
251
}
252
 
252
 
253
static void event_thread_b(unsigned hash)
253
static void event_thread_b(unsigned hash)
254
{
254
{
255
    async_serialize_start();
255
    async_serialize_start();
256
    cons_printf("new thread, hash 0x%x\n", hash);
256
    cons_printf("new thread, hash 0x%x\n", hash);
257
    async_serialize_end();
257
    async_serialize_end();
258
 
258
 
259
    thread_debug_start(hash);
259
    thread_debug_start(hash);
260
}
260
}
261
 
261
 
262
static void debug_event(thash_t thash, udebug_event_t ev_type, sysarg_t val0)
262
static void debug_event(thash_t thash, udebug_event_t ev_type, sysarg_t val0)
263
{
263
{
264
    switch (ev_type) {
264
    switch (ev_type) {
265
    case UDEBUG_EVENT_STOP:
265
    case UDEBUG_EVENT_STOP:
266
        cons_printf("stop event\n");
266
        cons_printf("stop event\n");
267
        thread_stop();
267
        thread_stop();
268
        break;
268
        break;
269
    case UDEBUG_EVENT_THREAD_B:
269
    case UDEBUG_EVENT_THREAD_B:
270
        event_thread_b(val0);
270
        event_thread_b(val0);
271
        break;
271
        break;
272
    case UDEBUG_EVENT_THREAD_E:
272
    case UDEBUG_EVENT_THREAD_E:
273
        cons_printf("thread 0x%x exited\n", val0);
273
        cons_printf("thread 0x%x exited\n", val0);
274
        abort_debug = true;
274
        abort_debug = true;
275
        break;
275
        break;
276
    case UDEBUG_EVENT_BREAKPOINT:
276
    case UDEBUG_EVENT_BREAKPOINT:
277
        arch_event_breakpoint(thash);
277
        arch_event_breakpoint(thash);
278
        break;
278
        break;
279
    case UDEBUG_EVENT_TRAP:
279
    case UDEBUG_EVENT_TRAP:
280
        arch_event_trap(dthread_get());
280
        arch_event_trap(dthread_get());
281
        break;
281
        break;
282
    default:
282
    default:
283
        cons_printf("unknown event type %d\n", ev_type);
283
        cons_printf("unknown event type %d\n", ev_type);
284
        break;
284
        break;
285
    }
285
    }
286
}
286
}
287
 
287
 
288
static int debug_loop(void *dt_arg)
288
static int debug_loop(void *dt_arg)
289
{
289
{
290
    int rc;
290
    int rc;
291
    udebug_event_t ev_type;
291
    udebug_event_t ev_type;
292
    unsigned val0, val1;
292
    unsigned val0, val1;
293
    dthread_t *dt;
293
    dthread_t *dt;
294
 
294
 
295
    dt = (dthread_t *)dt_arg;
295
    dt = (dthread_t *)dt_arg;
296
 
296
 
297
    cons_printf("debug_loop(%d)\n", dt->id);
297
    cons_printf("debug_loop(%d)\n", dt->id);
298
 
298
 
299
    while (!abort_debug) {
299
    while (!abort_debug) {
300
 
300
 
301
        /* Run thread until an event occurs */
301
        /* Run thread until an event occurs */
302
        rc = udebug_go(app_phone, dt->hash, &ev_type, &val0, &val1);
302
        rc = udebug_go(app_phone, dt->hash, &ev_type, &val0, &val1);
303
 
303
 
304
        if (ev_type == UDEBUG_EVENT_FINISHED) {
304
        if (ev_type == UDEBUG_EVENT_FINISHED) {
305
            cons_printf("thread %u debugging finished\n", dt->id);
305
            cons_printf("thread %u debugging finished\n", dt->id);
306
            break;
306
            break;
307
        }
307
        }
308
        if (rc >= 0) debug_event(dt->hash, ev_type, val0);
308
        if (rc >= 0) debug_event(dt->hash, ev_type, val0);
309
    }
309
    }
310
 
310
 
311
    cons_printf("debug_loop(%d) exiting\n", dt->id);
311
    cons_printf("debug_loop(%d) exiting\n", dt->id);
312
    return 0;
312
    return 0;
313
}
313
}
314
 
314
 
315
void thread_debug_start(unsigned thash)
315
void thread_debug_start(unsigned thash)
316
{
316
{
317
    fid_t fid;
317
    fid_t fid;
318
    dthread_t *dt;
318
    dthread_t *dt;
319
 
319
 
320
    dt = dthread_new(thash);
320
    dt = dthread_new(thash);
321
 
321
 
322
    fid = fibril_create(debug_loop, (void *)dt);
322
    fid = fibril_create(debug_loop, (void *)dt);
323
    if (fid == 0) {
323
    if (fid == 0) {
324
        cons_printf("Warning: Failed creating fibril\n");
324
        cons_printf("Warning: Failed creating fibril\n");
325
    }
325
    }
326
    dt->fid = fid;
326
    dt->fid = fid;
327
 
327
 
328
    fibril_add_ready(fid);
328
    fibril_add_ready(fid);
329
}
329
}
330
 
330
 
331
static void debug_active_task(void)
331
static void debug_active_task(task_id_t task_id)
332
{
332
{
333
    int taskid;
333
    int taskid;
334
    int i;
334
    int i;
335
    int rc;
335
    int rc;
336
 
336
 
337
    thash_t *thash_buffer;
337
    thash_t *thash_buffer;
338
    int n_threads;
338
    int n_threads;
339
 
339
 
340
    cons_printf("Breakpoint Debugger\n");
340
    cons_printf("Breakpoint Debugger\n");
341
    cons_printf("Press 'c' to connect\n");
-
 
342
    while ((i = getchar()) != 'c')
-
 
343
        putchar(i);
-
 
344
 
341
 
345
    taskid = /*13 mips32*/13;
-
 
346
    rc = task_connect(taskid);
342
    rc = task_connect(task_id);
347
    if (rc < 0) {
343
    if (rc < 0) {
348
        cons_printf("Failed to connect to task %d\n", taskid);
344
        cons_printf("Failed to connect to task %lld\n", task_id);
349
        return;
345
        return;
350
    }
346
    }
351
 
347
 
352
    cons_printf("Connected to task %d\n", taskid);
348
    cons_printf("Connected to task %lld\n", task_id);
353
 
349
 
354
    rc = get_thread_list(&thash_buffer, &n_threads);
350
    rc = get_thread_list(&thash_buffer, &n_threads);
355
    if (rc < 0) {
351
    if (rc < 0) {
356
        cons_printf("Failed to get thread list\n", rc);
352
        cons_printf("Failed to get thread list\n", rc);
357
        return;
353
        return;
358
    }
354
    }
359
 
355
 
360
    abort_debug = false;
356
    abort_debug = false;
361
 
357
 
362
    for (i = 0; i < n_threads; i++) {
358
    for (i = 0; i < n_threads; i++) {
363
        thread_debug_start(thash_buffer[i]);
359
        thread_debug_start(thash_buffer[i]);
364
    }
360
    }
365
 
361
 
366
    while (!quit) {
362
    while (!quit) {
367
        cons_read_line(in_buf, IN_BUF_SIZE);
363
        cons_read_line(in_buf, IN_BUF_SIZE);
368
        command_split(in_buf);
364
        command_split(in_buf);
369
        if (cmd_argc == 0) continue;
365
        if (cmd_argc == 0) continue;
370
 
366
 
371
        command_run();
367
        command_run();
372
    }
368
    }
373
 
369
 
374
    cons_printf("terminate debugging session...\n");
370
    cons_printf("terminate debugging session...\n");
375
    abort_debug = true;
371
    abort_debug = true;
376
    udebug_end(app_phone);
372
    udebug_end(app_phone);
377
    ipc_hangup(app_phone);
373
    ipc_hangup(app_phone);
378
 
374
 
379
    cons_printf("done\n");
375
    cons_printf("done\n");
380
    return;
376
    return;
381
}
377
}
382
 
378
 
383
static void main_init(void)
379
static void main_init(void)
384
{
380
{
385
    next_thread_id = 1;
381
    next_thread_id = 1;
386
    paused = 0;
382
    paused = 0;
387
   
383
   
388
    list_initialize(&dthreads);
384
    list_initialize(&dthreads);
389
    breakpoint_init();
385
    breakpoint_init();
390
    cwt = NULL;
386
    cwt = NULL;
391
}
387
}
392
 
388
 
393
int main(void)
389
static void print_syntax()
394
{
390
{
395
    main_init();
391
    printf("syntax: debug <task_id>\n");
-
 
392
}
396
 
393
 
-
 
394
int main(int argc, char *argv[])
-
 
395
{
-
 
396
    task_id_t task_id;
-
 
397
    char *err_p;
-
 
398
 
397
    while (1) {
399
    if (argc != 2) {
-
 
400
        printf("Mising argument\n");
398
        debug_active_task();
401
        print_syntax();
-
 
402
        return 1;
399
    }
403
    }
-
 
404
 
-
 
405
    task_id = strtol(argv[1], &err_p, 10);
-
 
406
 
-
 
407
    if (*err_p) {
-
 
408
        printf("Task ID syntax error\n");
-
 
409
        print_syntax();
-
 
410
        return 1;
-
 
411
    }
-
 
412
 
-
 
413
    main_init();
-
 
414
    debug_active_task(task_id);
400
}
415
}
401
 
416
 
402
/** @}
417
/** @}
403
 */
418
 */
404
 
419