Subversion Repositories HelenOS

Rev

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

Rev 673 Rev 850
1
/*
1
/*
2
 * Copyright (C) 2005 Ondrej Palkovsky
2
 * Copyright (C) 2005 Ondrej Palkovsky
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
#include <arch/debugger.h>
29
#include <arch/debugger.h>
30
#include <memstr.h>
30
#include <memstr.h>
31
#include <console/kconsole.h>
31
#include <console/kconsole.h>
32
#include <console/cmd.h>
32
#include <console/cmd.h>
33
#include <symtab.h>
33
#include <symtab.h>
34
#include <print.h>
34
#include <print.h>
35
#include <panic.h>
35
#include <panic.h>
36
#include <arch.h>
36
#include <arch.h>
37
#include <arch/cp0.h>
37
#include <arch/cp0.h>
38
#include <func.h>
38
#include <func.h>
39
 
39
 
40
bpinfo_t breakpoints[BKPOINTS_MAX];
40
bpinfo_t breakpoints[BKPOINTS_MAX];
41
SPINLOCK_INITIALIZE(bkpoint_lock);
41
SPINLOCK_INITIALIZE(bkpoint_lock);
42
 
42
 
43
static int cmd_print_breakpoints(cmd_arg_t *argv);
43
static int cmd_print_breakpoints(cmd_arg_t *argv);
44
static cmd_info_t bkpts_info = {
44
static cmd_info_t bkpts_info = {
45
    .name = "bkpts",
45
    .name = "bkpts",
46
    .description = "Print breakpoint table.",
46
    .description = "Print breakpoint table.",
47
    .func = cmd_print_breakpoints,
47
    .func = cmd_print_breakpoints,
48
    .argc = 0,
48
    .argc = 0,
49
};
49
};
50
 
50
 
51
static int cmd_del_breakpoint(cmd_arg_t *argv);
51
static int cmd_del_breakpoint(cmd_arg_t *argv);
52
static cmd_arg_t del_argv = {
52
static cmd_arg_t del_argv = {
53
    .type = ARG_TYPE_INT
53
    .type = ARG_TYPE_INT
54
};
54
};
55
static cmd_info_t delbkpt_info = {
55
static cmd_info_t delbkpt_info = {
56
    .name = "delbkpt",
56
    .name = "delbkpt",
57
    .description = "delbkpt <number> - Delete breakpoint.",
57
    .description = "delbkpt <number> - Delete breakpoint.",
58
    .func = cmd_del_breakpoint,
58
    .func = cmd_del_breakpoint,
59
    .argc = 1,
59
    .argc = 1,
60
    .argv = &del_argv
60
    .argv = &del_argv
61
};
61
};
62
 
62
 
63
static int cmd_add_breakpoint(cmd_arg_t *argv);
63
static int cmd_add_breakpoint(cmd_arg_t *argv);
64
static cmd_arg_t add_argv = {
64
static cmd_arg_t add_argv = {
65
    .type = ARG_TYPE_INT
65
    .type = ARG_TYPE_INT
66
};
66
};
67
static cmd_info_t addbkpt_info = {
67
static cmd_info_t addbkpt_info = {
68
    .name = "addbkpt",
68
    .name = "addbkpt",
69
    .description = "addbkpt <&symbol> - new bkpoint. Break on J/Branch insts unsupported.",
69
    .description = "addbkpt <&symbol> - new bkpoint. Break on J/Branch insts unsupported.",
70
    .func = cmd_add_breakpoint,
70
    .func = cmd_add_breakpoint,
71
    .argc = 1,
71
    .argc = 1,
72
    .argv = &add_argv
72
    .argv = &add_argv
73
};
73
};
74
 
74
 
75
static cmd_arg_t adde_argv[] = {
75
static cmd_arg_t adde_argv[] = {
76
    { .type = ARG_TYPE_INT },
76
    { .type = ARG_TYPE_INT },
77
    { .type = ARG_TYPE_INT }
77
    { .type = ARG_TYPE_INT }
78
};
78
};
79
static cmd_info_t addbkpte_info = {
79
static cmd_info_t addbkpte_info = {
80
    .name = "addbkpte",
80
    .name = "addbkpte",
81
    .description = "addebkpte <&symbol> <&func> - new bkpoint. Call func(or Nothing if 0).",
81
    .description = "addebkpte <&symbol> <&func> - new bkpoint. Call func(or Nothing if 0).",
82
    .func = cmd_add_breakpoint,
82
    .func = cmd_add_breakpoint,
83
    .argc = 2,
83
    .argc = 2,
84
    .argv = adde_argv
84
    .argv = adde_argv
85
};
85
};
86
 
86
 
87
static struct {
87
static struct {
88
    __u32 andmask;
88
    __u32 andmask;
89
    __u32 value;
89
    __u32 value;
90
}jmpinstr[] = {
90
}jmpinstr[] = {
91
    {0xf3ff0000, 0x41000000}, /* BCzF */
91
    {0xf3ff0000, 0x41000000}, /* BCzF */
92
    {0xf3ff0000, 0x41020000}, /* BCzFL */
92
    {0xf3ff0000, 0x41020000}, /* BCzFL */
93
    {0xf3ff0000, 0x41010000}, /* BCzT */
93
    {0xf3ff0000, 0x41010000}, /* BCzT */
94
    {0xf3ff0000, 0x41030000}, /* BCzTL */
94
    {0xf3ff0000, 0x41030000}, /* BCzTL */
95
    {0xfc000000, 0x10000000}, /* BEQ */
95
    {0xfc000000, 0x10000000}, /* BEQ */
96
    {0xfc000000, 0x50000000}, /* BEQL */
96
    {0xfc000000, 0x50000000}, /* BEQL */
97
    {0xfc1f0000, 0x04010000}, /* BEQL */
97
    {0xfc1f0000, 0x04010000}, /* BEQL */
98
    {0xfc1f0000, 0x04110000}, /* BGEZAL */
98
    {0xfc1f0000, 0x04110000}, /* BGEZAL */
99
    {0xfc1f0000, 0x04130000}, /* BGEZALL */
99
    {0xfc1f0000, 0x04130000}, /* BGEZALL */
100
    {0xfc1f0000, 0x04030000}, /* BGEZL */
100
    {0xfc1f0000, 0x04030000}, /* BGEZL */
101
    {0xfc1f0000, 0x1c000000}, /* BGTZ */
101
    {0xfc1f0000, 0x1c000000}, /* BGTZ */
102
    {0xfc1f0000, 0x5c000000}, /* BGTZL */
102
    {0xfc1f0000, 0x5c000000}, /* BGTZL */
103
    {0xfc1f0000, 0x18000000}, /* BLEZ */
103
    {0xfc1f0000, 0x18000000}, /* BLEZ */
104
    {0xfc1f0000, 0x58000000}, /* BLEZL */
104
    {0xfc1f0000, 0x58000000}, /* BLEZL */
105
    {0xfc1f0000, 0x04000000}, /* BLTZ */
105
    {0xfc1f0000, 0x04000000}, /* BLTZ */
106
    {0xfc1f0000, 0x04100000}, /* BLTZAL */
106
    {0xfc1f0000, 0x04100000}, /* BLTZAL */
107
    {0xfc1f0000, 0x04120000}, /* BLTZALL */
107
    {0xfc1f0000, 0x04120000}, /* BLTZALL */
108
    {0xfc1f0000, 0x04020000}, /* BLTZL */
108
    {0xfc1f0000, 0x04020000}, /* BLTZL */
109
    {0xfc000000, 0x14000000}, /* BNE */
109
    {0xfc000000, 0x14000000}, /* BNE */
110
    {0xfc000000, 0x54000000}, /* BNEL */
110
    {0xfc000000, 0x54000000}, /* BNEL */
111
    {0xfc000000, 0x08000000}, /* J */
111
    {0xfc000000, 0x08000000}, /* J */
112
    {0xfc000000, 0x0c000000}, /* JAL */
112
    {0xfc000000, 0x0c000000}, /* JAL */
113
    {0xfc1f07ff, 0x00000009}, /* JALR */
113
    {0xfc1f07ff, 0x00000009}, /* JALR */
114
    {0,0} /* EndOfTable */
114
    {0,0} /* EndOfTable */
115
};
115
};
116
 
116
 
117
/** Test, if the given instruction is a jump or branch instruction
117
/** Test, if the given instruction is a jump or branch instruction
118
 *
118
 *
119
 * @param instr Instruction code
119
 * @param instr Instruction code
120
 * @return true - it is jump instruction, false otherwise
120
 * @return true - it is jump instruction, false otherwise
121
 */
121
 */
122
static bool is_jump(__native instr)
122
static bool is_jump(__native instr)
123
{
123
{
124
    int i;
124
    int i;
125
 
125
 
126
    for (i=0;jmpinstr[i].andmask;i++) {
126
    for (i=0;jmpinstr[i].andmask;i++) {
127
        if ((instr & jmpinstr[i].andmask) == jmpinstr[i].value)
127
        if ((instr & jmpinstr[i].andmask) == jmpinstr[i].value)
128
            return true;
128
            return true;
129
    }
129
    }
130
 
130
 
131
    return false;
131
    return false;
132
}
132
}
133
 
133
 
134
/** Add new breakpoint to table */
134
/** Add new breakpoint to table */
135
int cmd_add_breakpoint(cmd_arg_t *argv)
135
int cmd_add_breakpoint(cmd_arg_t *argv)
136
{
136
{
137
    bpinfo_t *cur = NULL;
137
    bpinfo_t *cur = NULL;
138
    ipl_t ipl;
138
    ipl_t ipl;
139
    int i;
139
    int i;
140
 
140
 
141
    if (argv->intval & 0x3) {
141
    if (argv->intval & 0x3) {
142
        printf("Not aligned instruction, forgot to use &symbol?\n");
142
        printf("Not aligned instruction, forgot to use &symbol?\n");
143
        return 1;
143
        return 1;
144
    }
144
    }
145
    ipl = interrupts_disable();
145
    ipl = interrupts_disable();
146
    spinlock_lock(&bkpoint_lock);
146
    spinlock_lock(&bkpoint_lock);
147
 
147
 
148
    /* Check, that the breakpoints do not conflict */
148
    /* Check, that the breakpoints do not conflict */
149
    for (i=0; i<BKPOINTS_MAX; i++) {
149
    for (i=0; i<BKPOINTS_MAX; i++) {
150
        if (breakpoints[i].address == (__address)argv->intval) {
150
        if (breakpoints[i].address == (__address)argv->intval) {
151
            printf("Duplicate breakpoint %d.\n", i);
151
            printf("Duplicate breakpoint %d.\n", i);
152
            spinlock_unlock(&bkpoints_lock);
152
            spinlock_unlock(&bkpoints_lock);
153
            return 0;
153
            return 0;
154
        } else if (breakpoints[i].address == (__address)argv->intval + sizeof(__native) || \
154
        } else if (breakpoints[i].address == (__address)argv->intval + sizeof(__native) || \
155
               breakpoints[i].address == (__address)argv->intval - sizeof(__native)) {
155
               breakpoints[i].address == (__address)argv->intval - sizeof(__native)) {
156
            printf("Adjacent breakpoints not supported, conflict with %d.\n", i);
156
            printf("Adjacent breakpoints not supported, conflict with %d.\n", i);
157
            spinlock_unlock(&bkpoints_lock);
157
            spinlock_unlock(&bkpoints_lock);
158
            return 0;
158
            return 0;
159
        }
159
        }
160
           
160
           
161
    }
161
    }
162
 
162
 
163
    for (i=0; i<BKPOINTS_MAX; i++)
163
    for (i=0; i<BKPOINTS_MAX; i++)
164
        if (!breakpoints[i].address) {
164
        if (!breakpoints[i].address) {
165
            cur = &breakpoints[i];
165
            cur = &breakpoints[i];
166
            break;
166
            break;
167
        }
167
        }
168
    if (!cur) {
168
    if (!cur) {
169
        printf("Too many breakpoints.\n");
169
        printf("Too many breakpoints.\n");
170
        spinlock_unlock(&bkpoint_lock);
170
        spinlock_unlock(&bkpoint_lock);
171
        interrupts_restore(ipl);
171
        interrupts_restore(ipl);
172
        return 0;
172
        return 0;
173
    }
173
    }
174
    cur->address = (__address) argv->intval;
174
    cur->address = (__address) argv->intval;
175
    printf("Adding breakpoint on address: %p\n", argv->intval);
175
    printf("Adding breakpoint on address: %p\n", argv->intval);
176
    cur->instruction = ((__native *)cur->address)[0];
176
    cur->instruction = ((__native *)cur->address)[0];
177
    cur->nextinstruction = ((__native *)cur->address)[1];
177
    cur->nextinstruction = ((__native *)cur->address)[1];
178
    if (argv == &add_argv) {
178
    if (argv == &add_argv) {
179
        cur->flags = 0;
179
        cur->flags = 0;
180
    } else { /* We are add extended */
180
    } else { /* We are add extended */
181
        cur->flags = BKPOINT_FUNCCALL;
181
        cur->flags = BKPOINT_FUNCCALL;
182
        cur->bkfunc =   (void (*)(void *, struct exception_regdump *)) argv[1].intval;
182
        cur->bkfunc =   (void (*)(void *, struct exception_regdump *)) argv[1].intval;
183
    }
183
    }
184
    if (is_jump(cur->instruction))
184
    if (is_jump(cur->instruction))
185
        cur->flags |= BKPOINT_ONESHOT;
185
        cur->flags |= BKPOINT_ONESHOT;
186
    cur->counter = 0;
186
    cur->counter = 0;
187
 
187
 
188
    /* Set breakpoint */
188
    /* Set breakpoint */
189
    *((__native *)cur->address) = 0x0d;
189
    *((__native *)cur->address) = 0x0d;
190
 
190
 
191
    spinlock_unlock(&bkpoint_lock);
191
    spinlock_unlock(&bkpoint_lock);
192
    interrupts_restore(ipl);
192
    interrupts_restore(ipl);
193
 
193
 
194
    return 1;
194
    return 1;
195
}
195
}
196
 
196
 
197
 
197
 
198
 
198
 
199
/** Remove breakpoint from table */
199
/** Remove breakpoint from table */
200
int cmd_del_breakpoint(cmd_arg_t *argv)
200
int cmd_del_breakpoint(cmd_arg_t *argv)
201
{
201
{
202
    bpinfo_t *cur;
202
    bpinfo_t *cur;
203
    ipl_t ipl;
203
    ipl_t ipl;
204
 
204
 
205
    if (argv->intval < 0 || argv->intval > BKPOINTS_MAX) {
205
    if (argv->intval < 0 || argv->intval > BKPOINTS_MAX) {
206
        printf("Invalid breakpoint number.\n");
206
        printf("Invalid breakpoint number.\n");
207
        return 0;
207
        return 0;
208
    }
208
    }
209
    ipl = interrupts_disable();
209
    ipl = interrupts_disable();
210
    spinlock_lock(&bkpoint_lock);
210
    spinlock_lock(&bkpoint_lock);
211
 
211
 
212
    cur = &breakpoints[argv->intval];
212
    cur = &breakpoints[argv->intval];
213
    if (!cur->address) {
213
    if (!cur->address) {
214
        printf("Breakpoint does not exist.\n");
214
        printf("Breakpoint does not exist.\n");
215
        spinlock_unlock(&bkpoint_lock);
215
        spinlock_unlock(&bkpoint_lock);
216
        interrupts_restore(ipl);
216
        interrupts_restore(ipl);
217
        return 0;
217
        return 0;
218
    }
218
    }
219
    if ((cur->flags & BKPOINT_INPROG) && (cur->flags & BKPOINT_ONESHOT)) {
219
    if ((cur->flags & BKPOINT_INPROG) && (cur->flags & BKPOINT_ONESHOT)) {
220
        printf("Cannot remove one-shot breakpoint in-progress\n");
220
        printf("Cannot remove one-shot breakpoint in-progress\n");
221
        spinlock_unlock(&bkpoint_lock);
221
        spinlock_unlock(&bkpoint_lock);
222
        interrupts_restore(ipl);
222
        interrupts_restore(ipl);
223
        return 0;
223
        return 0;
224
    }
224
    }
225
    ((__u32 *)cur->address)[0] = cur->instruction;
225
    ((__u32 *)cur->address)[0] = cur->instruction;
226
    ((__u32 *)cur->address)[1] = cur->nextinstruction;
226
    ((__u32 *)cur->address)[1] = cur->nextinstruction;
227
 
227
 
228
    cur->address = NULL;
228
    cur->address = NULL;
229
 
229
 
230
    spinlock_unlock(&bkpoint_lock);
230
    spinlock_unlock(&bkpoint_lock);
231
    interrupts_restore(ipl);
231
    interrupts_restore(ipl);
232
    return 1;
232
    return 1;
233
}
233
}
234
 
234
 
235
/** Print table of active breakpoints */
235
/** Print table of active breakpoints */
236
int cmd_print_breakpoints(cmd_arg_t *argv)
236
int cmd_print_breakpoints(cmd_arg_t *argv)
237
{
237
{
238
    int i;
238
    int i;
239
    char *symbol;
239
    char *symbol;
240
 
240
 
241
    printf("Breakpoint table.\n");
241
    printf("Breakpoint table.\n");
242
    for (i=0; i < BKPOINTS_MAX; i++)
242
    for (i=0; i < BKPOINTS_MAX; i++)
243
        if (breakpoints[i].address) {
243
        if (breakpoints[i].address) {
244
            symbol = get_symtab_entry(breakpoints[i].address);
244
            symbol = get_symtab_entry(breakpoints[i].address);
245
            printf("%d. 0x%p in %s\n",i,
245
            printf("%d. 0x%p in %s\n",i,
246
                   breakpoints[i].address, symbol);
246
                   breakpoints[i].address, symbol);
247
            printf("     Count(%d) ", breakpoints[i].counter);
247
            printf("     Count(%d) ", breakpoints[i].counter);
248
            if (breakpoints[i].flags & BKPOINT_INPROG)
248
            if (breakpoints[i].flags & BKPOINT_INPROG)
249
                printf("INPROG ");
249
                printf("INPROG ");
250
            if (breakpoints[i].flags & BKPOINT_ONESHOT)
250
            if (breakpoints[i].flags & BKPOINT_ONESHOT)
251
                printf("ONESHOT ");
251
                printf("ONESHOT ");
252
            if (breakpoints[i].flags & BKPOINT_FUNCCALL)
252
            if (breakpoints[i].flags & BKPOINT_FUNCCALL)
253
                printf("FUNCCALL ");
253
                printf("FUNCCALL ");
254
            printf("\n");
254
            printf("\n");
255
        }
255
        }
256
    return 1;
256
    return 1;
257
}
257
}
258
 
258
 
259
/** Initialize debugger */
259
/** Initialize debugger */
260
void debugger_init()
260
void debugger_init()
261
{
261
{
262
    int i;
262
    int i;
263
 
263
 
264
    for (i=0; i<BKPOINTS_MAX; i++)
264
    for (i=0; i<BKPOINTS_MAX; i++)
265
        breakpoints[i].address = NULL;
265
        breakpoints[i].address = NULL;
266
   
266
   
267
    cmd_initialize(&bkpts_info);
267
    cmd_initialize(&bkpts_info);
268
    if (!cmd_register(&bkpts_info))
268
    if (!cmd_register(&bkpts_info))
269
        panic("could not register command %s\n", bkpts_info.name);
269
        panic("could not register command %s\n", bkpts_info.name);
270
 
270
 
271
    cmd_initialize(&delbkpt_info);
271
    cmd_initialize(&delbkpt_info);
272
    if (!cmd_register(&delbkpt_info))
272
    if (!cmd_register(&delbkpt_info))
273
        panic("could not register command %s\n", delbkpt_info.name);
273
        panic("could not register command %s\n", delbkpt_info.name);
274
 
274
 
275
    cmd_initialize(&addbkpt_info);
275
    cmd_initialize(&addbkpt_info);
276
    if (!cmd_register(&addbkpt_info))
276
    if (!cmd_register(&addbkpt_info))
277
        panic("could not register command %s\n", addbkpt_info.name);
277
        panic("could not register command %s\n", addbkpt_info.name);
278
 
278
 
279
    cmd_initialize(&addbkpte_info);
279
    cmd_initialize(&addbkpte_info);
280
    if (!cmd_register(&addbkpte_info))
280
    if (!cmd_register(&addbkpte_info))
281
        panic("could not register command %s\n", addbkpte_info.name);
281
        panic("could not register command %s\n", addbkpte_info.name);
282
}
282
}
283
 
283
 
284
/** Handle breakpoint
284
/** Handle breakpoint
285
 *
285
 *
286
 * Find breakpoint in breakpoint table.
286
 * Find breakpoint in breakpoint table.
287
 * If found, call kconsole, set break on next instruction and reexecute.
287
 * If found, call kconsole, set break on next instruction and reexecute.
288
 * If we are on "next instruction", set it back on the first and reexecute.
288
 * If we are on "next instruction", set it back on the first and reexecute.
289
 * If breakpoint not found in breakpoint table, call kconsole and start
289
 * If breakpoint not found in breakpoint table, call kconsole and start
290
 * next instruction.
290
 * next instruction.
291
 */
291
 */
292
void debugger_bpoint(struct exception_regdump *pstate)
292
void debugger_bpoint(struct exception_regdump *pstate)
293
{
293
{
294
    bpinfo_t *cur = NULL;
294
    bpinfo_t *cur = NULL;
295
    __address fireaddr = pstate->epc;
295
    __address fireaddr = pstate->epc;
296
    int i;
296
    int i;
297
 
297
 
298
    /* test branch delay slot */
298
    /* test branch delay slot */
299
    if (cp0_cause_read() & 0x80000000)
299
    if (cp0_cause_read() & 0x80000000)
300
        panic("Breakpoint in branch delay slot not supported.\n");
300
        panic("Breakpoint in branch delay slot not supported.\n");
301
 
301
 
302
    spinlock_lock(&bkpoint_lock);
302
    spinlock_lock(&bkpoint_lock);
303
    for (i=0; i<BKPOINTS_MAX; i++) {
303
    for (i=0; i<BKPOINTS_MAX; i++) {
304
        /* Normal breakpoint */
304
        /* Normal breakpoint */
305
        if (fireaddr == breakpoints[i].address \
305
        if (fireaddr == breakpoints[i].address \
306
            && !(breakpoints[i].flags & BKPOINT_REINST)) {
306
            && !(breakpoints[i].flags & BKPOINT_REINST)) {
307
            cur = &breakpoints[i];
307
            cur = &breakpoints[i];
308
            break;
308
            break;
309
        }
309
        }
310
        /* Reinst only breakpoint */
310
        /* Reinst only breakpoint */
311
        if ((breakpoints[i].flags & BKPOINT_REINST) \
311
        if ((breakpoints[i].flags & BKPOINT_REINST) \
312
            && (fireaddr ==breakpoints[i].address+sizeof(__native))) {
312
            && (fireaddr ==breakpoints[i].address+sizeof(__native))) {
313
            cur = &breakpoints[i];
313
            cur = &breakpoints[i];
314
            break;
314
            break;
315
        }
315
        }
316
    }
316
    }
317
    if (cur) {
317
    if (cur) {
318
        if (cur->flags & BKPOINT_REINST) {
318
        if (cur->flags & BKPOINT_REINST) {
319
            /* Set breakpoint on first instruction */
319
            /* Set breakpoint on first instruction */
320
            ((__u32 *)cur->address)[0] = 0x0d;
320
            ((__u32 *)cur->address)[0] = 0x0d;
321
            /* Return back the second */
321
            /* Return back the second */
322
            ((__u32 *)cur->address)[1] = cur->nextinstruction;
322
            ((__u32 *)cur->address)[1] = cur->nextinstruction;
323
            cur->flags &= ~BKPOINT_REINST;
323
            cur->flags &= ~BKPOINT_REINST;
324
            spinlock_unlock(&bkpoint_lock);
324
            spinlock_unlock(&bkpoint_lock);
325
            return;
325
            return;
326
        }
326
        }
327
        if (cur->flags & BKPOINT_INPROG)
327
        if (cur->flags & BKPOINT_INPROG)
328
            printf("Warning: breakpoint recursion\n");
328
            printf("Warning: breakpoint recursion\n");
329
       
329
       
330
        if (!(cur->flags & BKPOINT_FUNCCALL))
330
        if (!(cur->flags & BKPOINT_FUNCCALL))
331
            printf("***Breakpoint %d: 0x%p in %s.\n", i,
331
            printf("***Breakpoint %d: 0x%p in %s.\n", i,
332
                   fireaddr, get_symtab_entry(pstate->epc));
332
                   fireaddr, get_symtab_entry(pstate->epc));
333
 
333
 
334
        /* Return first instruction back */
334
        /* Return first instruction back */
335
        ((__u32 *)cur->address)[0] = cur->instruction;
335
        ((__u32 *)cur->address)[0] = cur->instruction;
336
 
336
 
337
        if (! (cur->flags & BKPOINT_ONESHOT)) {
337
        if (! (cur->flags & BKPOINT_ONESHOT)) {
338
            /* Set Breakpoint on next instruction */
338
            /* Set Breakpoint on next instruction */
339
            ((__u32 *)cur->address)[1] = 0x0d;
339
            ((__u32 *)cur->address)[1] = 0x0d;
340
            cur->flags |= BKPOINT_REINST;
340
            cur->flags |= BKPOINT_REINST;
341
        }
341
        }
342
        cur->flags |= BKPOINT_INPROG;
342
        cur->flags |= BKPOINT_INPROG;
343
    } else {
343
    } else {
344
        printf("***Breakpoint 0x%p in %s.\n", fireaddr,
344
        printf("***Breakpoint 0x%p in %s.\n", fireaddr,
345
               get_symtab_entry(fireaddr));
345
               get_symtab_entry(fireaddr));
346
        /* Move on to next instruction */
346
        /* Move on to next instruction */
347
        pstate->epc += 4;
347
        pstate->epc += 4;
348
    }
348
    }
349
   
349
    if (cur)
350
    cur->counter++;
350
        cur->counter++;
351
    if (cur && (cur->flags & BKPOINT_FUNCCALL)) {
351
    if (cur && (cur->flags & BKPOINT_FUNCCALL)) {
-
 
352
        printf("3.5\n");
352
        /* Allow zero bkfunc, just for counting */
353
        /* Allow zero bkfunc, just for counting */
353
        if (cur->bkfunc)
354
        if (cur->bkfunc)
354
            cur->bkfunc(cur, pstate);
355
            cur->bkfunc(cur, pstate);
355
    } else {
356
    } else {
356
        printf("***Type 'exit' to exit kconsole.\n");
357
        printf("***Type 'exit' to exit kconsole.\n");
357
        /* This disables all other processors - we are not SMP,
358
        /* This disables all other processors - we are not SMP,
358
         * actually this gets us to cpu_halt, if scheduler() is run
359
         * actually this gets us to cpu_halt, if scheduler() is run
359
         * - we generally do not want scheduler to be run from debug,
360
         * - we generally do not want scheduler to be run from debug,
360
         *   so this is a good idea
361
         *   so this is a good idea
361
         */
362
         */
362
        atomic_set(&haltstate,1);
363
        atomic_set(&haltstate,1);
363
        spinlock_unlock(&bkpoint_lock);
364
        spinlock_unlock(&bkpoint_lock);
364
 
365
 
365
        kconsole("debug");
366
        kconsole("debug");
366
 
367
 
367
        spinlock_lock(&bkpoint_lock);
368
        spinlock_lock(&bkpoint_lock);
368
        atomic_set(&haltstate,0);
369
        atomic_set(&haltstate,0);
369
    }
370
    }
370
 
-
 
371
    if (cur && cur->address == fireaddr && (cur->flags & BKPOINT_INPROG)) {
371
    if (cur && cur->address == fireaddr && (cur->flags & BKPOINT_INPROG)) {
372
        /* Remove one-shot breakpoint */
372
        /* Remove one-shot breakpoint */
373
        if ((cur->flags & BKPOINT_ONESHOT))
373
        if ((cur->flags & BKPOINT_ONESHOT))
374
            cur->address = NULL;
374
            cur->address = NULL;
375
        /* Remove in-progress flag */
375
        /* Remove in-progress flag */
376
        cur->flags &= ~BKPOINT_INPROG;
376
        cur->flags &= ~BKPOINT_INPROG;
377
    }
377
    }
378
    spinlock_unlock(&bkpoint_lock);
378
    spinlock_unlock(&bkpoint_lock);
379
}
379
}
380
 
380