Subversion Repositories HelenOS-historic

Rev

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

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