Subversion Repositories HelenOS

Rev

Rev 3022 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 3022 Rev 4055
Line 31... Line 31...
31
 */
31
 */
32
/** @file
32
/** @file
33
 */
33
 */
34
 
34
 
35
#include <arch/debugger.h>
35
#include <arch/debugger.h>
-
 
36
#include <arch/barrier.h>
36
#include <memstr.h>
37
#include <memstr.h>
37
#include <console/kconsole.h>
38
#include <console/kconsole.h>
38
#include <console/cmd.h>
39
#include <console/cmd.h>
39
#include <symtab.h>
40
#include <symtab.h>
40
#include <print.h>
41
#include <print.h>
Line 44... Line 45...
44
#include <func.h>
45
#include <func.h>
45
 
46
 
46
bpinfo_t breakpoints[BKPOINTS_MAX];
47
bpinfo_t breakpoints[BKPOINTS_MAX];
47
SPINLOCK_INITIALIZE(bkpoint_lock);
48
SPINLOCK_INITIALIZE(bkpoint_lock);
48
 
49
 
-
 
50
#ifdef CONFIG_KCONSOLE
-
 
51
 
49
static int cmd_print_breakpoints(cmd_arg_t *argv);
52
static int cmd_print_breakpoints(cmd_arg_t *argv);
50
static cmd_info_t bkpts_info = {
53
static cmd_info_t bkpts_info = {
51
    .name = "bkpts",
54
    .name = "bkpts",
52
    .description = "Print breakpoint table.",
55
    .description = "Print breakpoint table.",
53
    .func = cmd_print_breakpoints,
56
    .func = cmd_print_breakpoints,
Line 70... Line 73...
70
static cmd_arg_t add_argv = {
73
static cmd_arg_t add_argv = {
71
    .type = ARG_TYPE_INT
74
    .type = ARG_TYPE_INT
72
};
75
};
73
static cmd_info_t addbkpt_info = {
76
static cmd_info_t addbkpt_info = {
74
    .name = "addbkpt",
77
    .name = "addbkpt",
75
    .description = "addbkpt <&symbol> - new bkpoint. Break on J/Branch insts unsupported.",
78
    .description = "addbkpt <&symbol> - new bkpoint. Break on J/Branch "
-
 
79
        "insts unsupported.",
76
    .func = cmd_add_breakpoint,
80
    .func = cmd_add_breakpoint,
77
    .argc = 1,
81
    .argc = 1,
78
    .argv = &add_argv
82
    .argv = &add_argv
79
};
83
};
80
 
84
 
Line 82... Line 86...
82
    { .type = ARG_TYPE_INT },
86
    { .type = ARG_TYPE_INT },
83
    { .type = ARG_TYPE_INT }
87
    { .type = ARG_TYPE_INT }
84
};
88
};
85
static cmd_info_t addbkpte_info = {
89
static cmd_info_t addbkpte_info = {
86
    .name = "addbkpte",
90
    .name = "addbkpte",
87
    .description = "addebkpte <&symbol> <&func> - new bkpoint. Call func(or Nothing if 0).",
91
    .description = "addebkpte <&symbol> <&func> - new bkpoint. Call "
-
 
92
        "func(or Nothing if 0).",
88
    .func = cmd_add_breakpoint,
93
    .func = cmd_add_breakpoint,
89
    .argc = 2,
94
    .argc = 2,
90
    .argv = adde_argv
95
    .argv = adde_argv
91
};
96
};
92
 
97
 
93
static struct {
98
static struct {
94
    uint32_t andmask;
99
    uint32_t andmask;
95
    uint32_t value;
100
    uint32_t value;
96
}jmpinstr[] = {
101
} jmpinstr[] = {
97
    {0xf3ff0000, 0x41000000}, /* BCzF */
102
    {0xf3ff0000, 0x41000000}, /* BCzF */
98
    {0xf3ff0000, 0x41020000}, /* BCzFL */
103
    {0xf3ff0000, 0x41020000}, /* BCzFL */
99
    {0xf3ff0000, 0x41010000}, /* BCzT */
104
    {0xf3ff0000, 0x41010000}, /* BCzT */
100
    {0xf3ff0000, 0x41030000}, /* BCzTL */
105
    {0xf3ff0000, 0x41030000}, /* BCzTL */
101
    {0xfc000000, 0x10000000}, /* BEQ */
106
    {0xfc000000, 0x10000000}, /* BEQ */
Line 115... Line 120...
115
    {0xfc000000, 0x14000000}, /* BNE */
120
    {0xfc000000, 0x14000000}, /* BNE */
116
    {0xfc000000, 0x54000000}, /* BNEL */
121
    {0xfc000000, 0x54000000}, /* BNEL */
117
    {0xfc000000, 0x08000000}, /* J */
122
    {0xfc000000, 0x08000000}, /* J */
118
    {0xfc000000, 0x0c000000}, /* JAL */
123
    {0xfc000000, 0x0c000000}, /* JAL */
119
    {0xfc1f07ff, 0x00000009}, /* JALR */
124
    {0xfc1f07ff, 0x00000009}, /* JALR */
120
    {0,0} /* EndOfTable */
125
    {0, 0} /* EndOfTable */
121
};
126
};
122
 
127
 
-
 
128
 
123
/** Test, if the given instruction is a jump or branch instruction
129
/** Test, if the given instruction is a jump or branch instruction
124
 *
130
 *
125
 * @param instr Instruction code
131
 * @param instr Instruction code
126
 * @return true - it is jump instruction, false otherwise
132
 * @return true - it is jump instruction, false otherwise
-
 
133
 *
127
 */
134
 */
128
static bool is_jump(unative_t instr)
135
static bool is_jump(unative_t instr)
129
{
136
{
130
    int i;
137
    int i;
131
 
138
 
132
    for (i=0;jmpinstr[i].andmask;i++) {
139
    for (i = 0; jmpinstr[i].andmask; i++) {
133
        if ((instr & jmpinstr[i].andmask) == jmpinstr[i].value)
140
        if ((instr & jmpinstr[i].andmask) == jmpinstr[i].value)
134
            return true;
141
            return true;
135
    }
142
    }
136
 
143
 
137
    return false;
144
    return false;
Line 150... Line 157...
150
    }
157
    }
151
    ipl = interrupts_disable();
158
    ipl = interrupts_disable();
152
    spinlock_lock(&bkpoint_lock);
159
    spinlock_lock(&bkpoint_lock);
153
 
160
 
154
    /* Check, that the breakpoints do not conflict */
161
    /* Check, that the breakpoints do not conflict */
155
    for (i=0; i<BKPOINTS_MAX; i++) {
162
    for (i = 0; i < BKPOINTS_MAX; i++) {
156
        if (breakpoints[i].address == (uintptr_t)argv->intval) {
163
        if (breakpoints[i].address == (uintptr_t)argv->intval) {
157
            printf("Duplicate breakpoint %d.\n", i);
164
            printf("Duplicate breakpoint %d.\n", i);
158
            spinlock_unlock(&bkpoints_lock);
165
            spinlock_unlock(&bkpoint_lock);
159
            return 0;
166
            return 0;
160
        } else if (breakpoints[i].address == (uintptr_t)argv->intval + sizeof(unative_t) || \
167
        } else if (breakpoints[i].address == (uintptr_t)argv->intval +
-
 
168
            sizeof(unative_t) || breakpoints[i].address ==
161
               breakpoints[i].address == (uintptr_t)argv->intval - sizeof(unative_t)) {
169
            (uintptr_t)argv->intval - sizeof(unative_t)) {
162
            printf("Adjacent breakpoints not supported, conflict with %d.\n", i);
170
            printf("Adjacent breakpoints not supported, conflict "
-
 
171
                "with %d.\n", i);
163
            spinlock_unlock(&bkpoints_lock);
172
            spinlock_unlock(&bkpoint_lock);
164
            return 0;
173
            return 0;
165
        }
174
        }
166
           
175
       
167
    }
176
    }
168
 
177
 
169
    for (i=0; i<BKPOINTS_MAX; i++)
178
    for (i = 0; i < BKPOINTS_MAX; i++)
170
        if (!breakpoints[i].address) {
179
        if (!breakpoints[i].address) {
171
            cur = &breakpoints[i];
180
            cur = &breakpoints[i];
172
            break;
181
            break;
173
        }
182
        }
174
    if (!cur) {
183
    if (!cur) {
Line 183... Line 192...
183
    cur->nextinstruction = ((unative_t *)cur->address)[1];
192
    cur->nextinstruction = ((unative_t *)cur->address)[1];
184
    if (argv == &add_argv) {
193
    if (argv == &add_argv) {
185
        cur->flags = 0;
194
        cur->flags = 0;
186
    } else { /* We are add extended */
195
    } else { /* We are add extended */
187
        cur->flags = BKPOINT_FUNCCALL;
196
        cur->flags = BKPOINT_FUNCCALL;
188
        cur->bkfunc =   (void (*)(void *, istate_t *)) argv[1].intval;
197
        cur->bkfunc = (void (*)(void *, istate_t *)) argv[1].intval;
189
    }
198
    }
190
    if (is_jump(cur->instruction))
199
    if (is_jump(cur->instruction))
191
        cur->flags |= BKPOINT_ONESHOT;
200
        cur->flags |= BKPOINT_ONESHOT;
192
    cur->counter = 0;
201
    cur->counter = 0;
193
 
202
 
194
    /* Set breakpoint */
203
    /* Set breakpoint */
195
    *((unative_t *)cur->address) = 0x0d;
204
    *((unative_t *)cur->address) = 0x0d;
-
 
205
    smc_coherence(cur->address);
196
 
206
 
197
    spinlock_unlock(&bkpoint_lock);
207
    spinlock_unlock(&bkpoint_lock);
198
    interrupts_restore(ipl);
208
    interrupts_restore(ipl);
199
 
209
 
200
    return 1;
210
    return 1;
201
}
211
}
202
 
212
 
203
 
-
 
204
 
-
 
205
/** Remove breakpoint from table */
213
/** Remove breakpoint from table */
206
int cmd_del_breakpoint(cmd_arg_t *argv)
214
int cmd_del_breakpoint(cmd_arg_t *argv)
207
{
215
{
208
    bpinfo_t *cur;
216
    bpinfo_t *cur;
209
    ipl_t ipl;
217
    ipl_t ipl;
Line 227... Line 235...
227
        spinlock_unlock(&bkpoint_lock);
235
        spinlock_unlock(&bkpoint_lock);
228
        interrupts_restore(ipl);
236
        interrupts_restore(ipl);
229
        return 0;
237
        return 0;
230
    }
238
    }
231
    ((uint32_t *)cur->address)[0] = cur->instruction;
239
    ((uint32_t *)cur->address)[0] = cur->instruction;
-
 
240
    smc_coherence(((uint32_t *)cur->address)[0]);
232
    ((uint32_t *)cur->address)[1] = cur->nextinstruction;
241
    ((uint32_t *)cur->address)[1] = cur->nextinstruction;
-
 
242
    smc_coherence(((uint32_t *)cur->address)[1]);
233
 
243
 
234
    cur->address = NULL;
244
    cur->address = NULL;
235
 
245
 
236
    spinlock_unlock(&bkpoint_lock);
246
    spinlock_unlock(&bkpoint_lock);
237
    interrupts_restore(ipl);
247
    interrupts_restore(ipl);
Line 250... Line 260...
250
    for (i = 0; i < BKPOINTS_MAX; i++)
260
    for (i = 0; i < BKPOINTS_MAX; i++)
251
        if (breakpoints[i].address) {
261
        if (breakpoints[i].address) {
252
            symbol = get_symtab_entry(breakpoints[i].address);
262
            symbol = get_symtab_entry(breakpoints[i].address);
253
           
263
           
254
            printf("%-2u %-5d %#10zx %-6s %-7s %-8s %s\n", i,
264
            printf("%-2u %-5d %#10zx %-6s %-7s %-8s %s\n", i,
255
                breakpoints[i].counter, breakpoints[i].address,
265
                breakpoints[i].counter, breakpoints[i].address,
256
                ((breakpoints[i].flags & BKPOINT_INPROG) ? "true" : "false"),
266
                ((breakpoints[i].flags & BKPOINT_INPROG) ? "true" :
257
                ((breakpoints[i].flags & BKPOINT_ONESHOT) ? "true" : "false"),
267
                "false"), ((breakpoints[i].flags & BKPOINT_ONESHOT)
-
 
268
                ? "true" : "false"), ((breakpoints[i].flags &
258
                ((breakpoints[i].flags & BKPOINT_FUNCCALL) ? "true" : "false"),
269
                BKPOINT_FUNCCALL) ? "true" : "false"), symbol);
259
                symbol);
-
 
260
        }
270
        }
261
    return 1;
271
    return 1;
262
}
272
}
263
 
273
 
-
 
274
#endif
-
 
275
 
264
/** Initialize debugger */
276
/** Initialize debugger */
265
void debugger_init()
277
void debugger_init()
266
{
278
{
267
    int i;
279
    int i;
268
 
280
 
269
    for (i=0; i<BKPOINTS_MAX; i++)
281
    for (i = 0; i < BKPOINTS_MAX; i++)
270
        breakpoints[i].address = NULL;
282
        breakpoints[i].address = NULL;
271
   
283
 
-
 
284
#ifdef CONFIG_KCONSOLE
272
    cmd_initialize(&bkpts_info);
285
    cmd_initialize(&bkpts_info);
273
    if (!cmd_register(&bkpts_info))
286
    if (!cmd_register(&bkpts_info))
274
        panic("could not register command %s\n", bkpts_info.name);
287
        printf("Cannot register command %s\n", bkpts_info.name);
275
 
288
 
276
    cmd_initialize(&delbkpt_info);
289
    cmd_initialize(&delbkpt_info);
277
    if (!cmd_register(&delbkpt_info))
290
    if (!cmd_register(&delbkpt_info))
278
        panic("could not register command %s\n", delbkpt_info.name);
291
        printf("Cannot register command %s\n", delbkpt_info.name);
279
 
292
 
280
    cmd_initialize(&addbkpt_info);
293
    cmd_initialize(&addbkpt_info);
281
    if (!cmd_register(&addbkpt_info))
294
    if (!cmd_register(&addbkpt_info))
282
        panic("could not register command %s\n", addbkpt_info.name);
295
        printf("Cannot register command %s\n", addbkpt_info.name);
283
 
296
 
284
    cmd_initialize(&addbkpte_info);
297
    cmd_initialize(&addbkpte_info);
285
    if (!cmd_register(&addbkpte_info))
298
    if (!cmd_register(&addbkpte_info))
286
        panic("could not register command %s\n", addbkpte_info.name);
299
        printf("Cannot register command %s\n", addbkpte_info.name);
-
 
300
#endif
287
}
301
}
288
 
302
 
289
/** Handle breakpoint
303
/** Handle breakpoint
290
 *
304
 *
291
 * Find breakpoint in breakpoint table.
305
 * Find breakpoint in breakpoint table.
Line 300... Line 314...
300
    uintptr_t fireaddr = istate->epc;
314
    uintptr_t fireaddr = istate->epc;
301
    int i;
315
    int i;
302
 
316
 
303
    /* test branch delay slot */
317
    /* test branch delay slot */
304
    if (cp0_cause_read() & 0x80000000)
318
    if (cp0_cause_read() & 0x80000000)
305
        panic("Breakpoint in branch delay slot not supported.\n");
319
        panic("Breakpoint in branch delay slot not supported.");
306
 
320
 
307
    spinlock_lock(&bkpoint_lock);
321
    spinlock_lock(&bkpoint_lock);
308
    for (i=0; i<BKPOINTS_MAX; i++) {
322
    for (i = 0; i < BKPOINTS_MAX; i++) {
309
        /* Normal breakpoint */
323
        /* Normal breakpoint */
310
        if (fireaddr == breakpoints[i].address \
324
        if (fireaddr == breakpoints[i].address &&
311
            && !(breakpoints[i].flags & BKPOINT_REINST)) {
325
            !(breakpoints[i].flags & BKPOINT_REINST)) {
312
            cur = &breakpoints[i];
326
            cur = &breakpoints[i];
313
            break;
327
            break;
314
        }
328
        }
315
        /* Reinst only breakpoint */
329
        /* Reinst only breakpoint */
316
        if ((breakpoints[i].flags & BKPOINT_REINST) \
330
        if ((breakpoints[i].flags & BKPOINT_REINST) &&
317
            && (fireaddr ==breakpoints[i].address+sizeof(unative_t))) {
331
            (fireaddr == breakpoints[i].address + sizeof(unative_t))) {
318
            cur = &breakpoints[i];
332
            cur = &breakpoints[i];
319
            break;
333
            break;
320
        }
334
        }
321
    }
335
    }
322
    if (cur) {
336
    if (cur) {
323
        if (cur->flags & BKPOINT_REINST) {
337
        if (cur->flags & BKPOINT_REINST) {
324
            /* Set breakpoint on first instruction */
338
            /* Set breakpoint on first instruction */
325
            ((uint32_t *)cur->address)[0] = 0x0d;
339
            ((uint32_t *)cur->address)[0] = 0x0d;
-
 
340
            smc_coherence(((uint32_t *)cur->address)[0]);
326
            /* Return back the second */
341
            /* Return back the second */
327
            ((uint32_t *)cur->address)[1] = cur->nextinstruction;
342
            ((uint32_t *)cur->address)[1] = cur->nextinstruction;
-
 
343
            smc_coherence(((uint32_t *)cur->address)[1]);
328
            cur->flags &= ~BKPOINT_REINST;
344
            cur->flags &= ~BKPOINT_REINST;
329
            spinlock_unlock(&bkpoint_lock);
345
            spinlock_unlock(&bkpoint_lock);
330
            return;
346
            return;
331
        }
347
        }
332
        if (cur->flags & BKPOINT_INPROG)
348
        if (cur->flags & BKPOINT_INPROG)
333
            printf("Warning: breakpoint recursion\n");
349
            printf("Warning: breakpoint recursion\n");
334
       
350
       
335
        if (!(cur->flags & BKPOINT_FUNCCALL))
351
        if (!(cur->flags & BKPOINT_FUNCCALL))
336
            printf("***Breakpoint %d: %p in %s.\n", i,
352
            printf("***Breakpoint %d: %p in %s.\n", i, fireaddr,
337
                   fireaddr, get_symtab_entry(istate->epc));
353
                get_symtab_entry(istate->epc));
338
 
354
 
339
        /* Return first instruction back */
355
        /* Return first instruction back */
340
        ((uint32_t *)cur->address)[0] = cur->instruction;
356
        ((uint32_t *)cur->address)[0] = cur->instruction;
-
 
357
        smc_coherence(cur->address);
341
 
358
 
342
        if (! (cur->flags & BKPOINT_ONESHOT)) {
359
        if (! (cur->flags & BKPOINT_ONESHOT)) {
343
            /* Set Breakpoint on next instruction */
360
            /* Set Breakpoint on next instruction */
344
            ((uint32_t *)cur->address)[1] = 0x0d;
361
            ((uint32_t *)cur->address)[1] = 0x0d;
345
            cur->flags |= BKPOINT_REINST;
362
            cur->flags |= BKPOINT_REINST;
Line 356... Line 373...
356
    if (cur && (cur->flags & BKPOINT_FUNCCALL)) {
373
    if (cur && (cur->flags & BKPOINT_FUNCCALL)) {
357
        /* Allow zero bkfunc, just for counting */
374
        /* Allow zero bkfunc, just for counting */
358
        if (cur->bkfunc)
375
        if (cur->bkfunc)
359
            cur->bkfunc(cur, istate);
376
            cur->bkfunc(cur, istate);
360
    } else {
377
    } else {
361
        printf("***Type 'exit' to exit kconsole.\n");
378
#ifdef CONFIG_KCONSOLE
362
        /* This disables all other processors - we are not SMP,
379
        /* This disables all other processors - we are not SMP,
363
         * actually this gets us to cpu_halt, if scheduler() is run
380
         * actually this gets us to cpu_halt, if scheduler() is run
364
         * - we generally do not want scheduler to be run from debug,
381
         * - we generally do not want scheduler to be run from debug,
365
         *   so this is a good idea
382
         *   so this is a good idea
366
         */
383
         */
367
        atomic_set(&haltstate,1);
384
        atomic_set(&haltstate, 1);
368
        spinlock_unlock(&bkpoint_lock);
385
        spinlock_unlock(&bkpoint_lock);
369
 
386
       
370
        kconsole("debug");
387
        kconsole("debug", "Debug console ready (type 'exit' to continue)\n", false);
371
 
388
       
372
        spinlock_lock(&bkpoint_lock);
389
        spinlock_lock(&bkpoint_lock);
373
        atomic_set(&haltstate,0);
390
        atomic_set(&haltstate, 0);
-
 
391
#endif
374
    }
392
    }
375
    if (cur && cur->address == fireaddr && (cur->flags & BKPOINT_INPROG)) {
393
    if (cur && cur->address == fireaddr && (cur->flags & BKPOINT_INPROG)) {
376
        /* Remove one-shot breakpoint */
394
        /* Remove one-shot breakpoint */
377
        if ((cur->flags & BKPOINT_ONESHOT))
395
        if ((cur->flags & BKPOINT_ONESHOT))
378
            cur->address = NULL;
396
            cur->address = NULL;