Subversion Repositories HelenOS

Rev

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

Rev 623 Rev 631
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 pbkpt_info = {
44
static cmd_info_t pbkpt_info = {
45
    .name = "pbkpt",
45
    .name = "pbkpt",
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
/** Add new breakpoint to table */
75
/** Add new breakpoint to table */
76
int cmd_add_breakpoint(cmd_arg_t *argv)
76
int cmd_add_breakpoint(cmd_arg_t *argv)
77
{
77
{
78
    bpinfo_t *cur = NULL;
78
    bpinfo_t *cur = NULL;
79
    ipl_t ipl;
79
    ipl_t ipl;
80
    int i;
80
    int i;
81
 
81
 
82
    if (argv->intval & 0x3) {
82
    if (argv->intval & 0x3) {
83
        printf("Not aligned instruction, forgot to use &symbol?\n");
83
        printf("Not aligned instruction, forgot to use &symbol?\n");
84
        return 1;
84
        return 1;
85
    }
85
    }
86
    ipl = interrupts_disable();
86
    ipl = interrupts_disable();
87
    spinlock_lock(&bkpoint_lock);
87
    spinlock_lock(&bkpoint_lock);
88
 
88
 
89
    /* Check, that the breakpoints do not conflict */
89
    /* Check, that the breakpoints do not conflict */
90
    for (i=0; i<BKPOINTS_MAX; i++) {
90
    for (i=0; i<BKPOINTS_MAX; i++) {
91
        if (breakpoints[i].address == (__address)argv->intval) {
91
        if (breakpoints[i].address == (__address)argv->intval) {
92
            printf("Duplicate breakpoint %d.\n", i);
92
            printf("Duplicate breakpoint %d.\n", i);
93
            spinlock_unlock(&bkpoints_lock);
93
            spinlock_unlock(&bkpoints_lock);
94
            return 0;
94
            return 0;
95
        } else if (breakpoints[i].address == (__address)argv->intval + sizeof(__native) || \
95
        } else if (breakpoints[i].address == (__address)argv->intval + sizeof(__native) || \
96
               breakpoints[i].address == (__address)argv->intval - sizeof(__native)) {
96
               breakpoints[i].address == (__address)argv->intval - sizeof(__native)) {
97
            printf("Adjacent breakpoints not supported, conflict with %d.\n", i);
97
            printf("Adjacent breakpoints not supported, conflict with %d.\n", i);
98
            spinlock_unlock(&bkpoints_lock);
98
            spinlock_unlock(&bkpoints_lock);
99
            return 0;
99
            return 0;
100
        }
100
        }
101
           
101
           
102
    }
102
    }
103
 
103
 
104
    for (i=0; i<BKPOINTS_MAX; i++)
104
    for (i=0; i<BKPOINTS_MAX; i++)
105
        if (!breakpoints[i].address) {
105
        if (!breakpoints[i].address) {
106
            cur = &breakpoints[i];
106
            cur = &breakpoints[i];
107
            break;
107
            break;
108
        }
108
        }
109
    if (!cur) {
109
    if (!cur) {
110
        printf("Too many breakpoints.\n");
110
        printf("Too many breakpoints.\n");
111
        spinlock_unlock(&bkpoint_lock);
111
        spinlock_unlock(&bkpoint_lock);
112
        interrupts_restore(ipl);
112
        interrupts_restore(ipl);
113
        return 0;
113
        return 0;
114
    }
114
    }
115
    cur->address = (__address) argv->intval;
115
    cur->address = (__address) argv->intval;
116
    printf("Adding breakpoint on address: %p\n", argv->intval);
116
    printf("Adding breakpoint on address: %p\n", argv->intval);
117
    cur->instruction = ((__native *)cur->address)[0];
117
    cur->instruction = ((__native *)cur->address)[0];
118
    cur->nextinstruction = ((__native *)cur->address)[1];
118
    cur->nextinstruction = ((__native *)cur->address)[1];
119
    cur->executing = false;
119
    cur->executing = false;
120
 
120
 
121
    /* Set breakpoint */
121
    /* Set breakpoint */
122
    *((__native *)cur->address) = 0x0d;
122
    *((__native *)cur->address) = 0x0d;
123
 
123
 
124
    spinlock_unlock(&bkpoint_lock);
124
    spinlock_unlock(&bkpoint_lock);
125
    interrupts_restore(ipl);
125
    interrupts_restore(ipl);
126
 
126
 
127
    return 1;
127
    return 1;
128
}
128
}
129
 
129
 
130
/** Remove breakpoint from table */
130
/** Remove breakpoint from table */
131
int cmd_del_breakpoint(cmd_arg_t *argv)
131
int cmd_del_breakpoint(cmd_arg_t *argv)
132
{
132
{
133
    bpinfo_t *cur;
133
    bpinfo_t *cur;
134
    ipl_t ipl;
134
    ipl_t ipl;
135
 
135
 
136
    if (argv->intval < 0 || argv->intval > BKPOINTS_MAX) {
136
    if (argv->intval < 0 || argv->intval > BKPOINTS_MAX) {
137
        printf("Invalid breakpoint number.\n");
137
        printf("Invalid breakpoint number.\n");
138
        return 0;
138
        return 0;
139
    }
139
    }
140
    ipl = interrupts_disable();
140
    ipl = interrupts_disable();
141
    spinlock_lock(&bkpoint_lock);
141
    spinlock_lock(&bkpoint_lock);
142
 
142
 
143
    cur = &breakpoints[argv->intval];
143
    cur = &breakpoints[argv->intval];
144
    if (!cur->address) {
144
    if (!cur->address) {
145
        printf("Breakpoint does not exist.\n");
145
        printf("Breakpoint does not exist.\n");
146
        spinlock_unlock(&bkpoint_lock);
146
        spinlock_unlock(&bkpoint_lock);
147
        interrupts_restore(ipl);
147
        interrupts_restore(ipl);
148
        return 0;
148
        return 0;
149
    }
149
    }
150
   
150
   
151
    ((__u32 *)cur->address)[0] = cur->instruction;
151
    ((__u32 *)cur->address)[0] = cur->instruction;
152
    ((__u32 *)cur->address)[1] = cur->nextinstruction;
152
    ((__u32 *)cur->address)[1] = cur->nextinstruction;
153
 
153
 
154
    cur->address = NULL;
154
    cur->address = NULL;
155
 
155
 
156
    spinlock_unlock(&bkpoint_lock);
156
    spinlock_unlock(&bkpoint_lock);
157
    interrupts_restore(ipl);
157
    interrupts_restore(ipl);
158
    return 1;
158
    return 1;
159
}
159
}
160
 
160
 
161
/** Print table of active breakpoints */
161
/** Print table of active breakpoints */
162
int cmd_print_breakpoints(cmd_arg_t *argv)
162
int cmd_print_breakpoints(cmd_arg_t *argv)
163
{
163
{
164
    int i;
164
    int i;
165
    char *symbol;
165
    char *symbol;
166
 
166
 
167
    printf("Breakpoint table.\n");
167
    printf("Breakpoint table.\n");
168
    for (i=0; i < BKPOINTS_MAX; i++)
168
    for (i=0; i < BKPOINTS_MAX; i++)
169
        if (breakpoints[i].address) {
169
        if (breakpoints[i].address) {
170
            symbol = get_symtab_entry(breakpoints[i].address);
170
            symbol = get_symtab_entry(breakpoints[i].address);
171
            printf("%d. 0x%p in %s\n",i,
171
            printf("%d. 0x%p in %s\n",i,
172
                   breakpoints[i].address, symbol);
172
                   breakpoints[i].address, symbol);
173
        }
173
        }
174
    return 1;
174
    return 1;
175
}
175
}
176
 
176
 
177
/** Initialize debugger */
177
/** Initialize debugger */
178
void debugger_init()
178
void debugger_init()
179
{
179
{
180
    int i;
180
    int i;
181
 
181
 
182
    for (i=0; i<BKPOINTS_MAX; i++)
182
    for (i=0; i<BKPOINTS_MAX; i++)
183
        breakpoints[i].address = NULL;
183
        breakpoints[i].address = NULL;
184
   
184
   
185
    cmd_initialize(&pbkpt_info);
185
    cmd_initialize(&pbkpt_info);
186
    if (!cmd_register(&pbkpt_info))
186
    if (!cmd_register(&pbkpt_info))
187
        panic("could not register command %s\n", pbkpt_info.name);
187
        panic("could not register command %s\n", pbkpt_info.name);
188
 
188
 
189
    cmd_initialize(&delbkpt_info);
189
    cmd_initialize(&delbkpt_info);
190
    if (!cmd_register(&delbkpt_info))
190
    if (!cmd_register(&delbkpt_info))
191
        panic("could not register command %s\n", delbkpt_info.name);
191
        panic("could not register command %s\n", delbkpt_info.name);
192
 
192
 
193
    cmd_initialize(&addbkpt_info);
193
    cmd_initialize(&addbkpt_info);
194
    if (!cmd_register(&addbkpt_info))
194
    if (!cmd_register(&addbkpt_info))
195
        panic("could not register command %s\n", addbkpt_info.name);
195
        panic("could not register command %s\n", addbkpt_info.name);
196
}
196
}
197
 
197
 
198
/** Handle breakpoint
198
/** Handle breakpoint
199
 *
199
 *
200
 * Find breakpoint in breakpoint table.
200
 * Find breakpoint in breakpoint table.
201
 * If found, call kconsole, set break on next instruction and reexecute.
201
 * If found, call kconsole, set break on next instruction and reexecute.
202
 * If we are on "next instruction", set it back on the first and reexecute.
202
 * If we are on "next instruction", set it back on the first and reexecute.
203
 * If breakpoint not found in breakpoint table, call kconsole and start
203
 * If breakpoint not found in breakpoint table, call kconsole and start
204
 * next instruction.
204
 * next instruction.
205
 */
205
 */
206
void debugger_bpoint(struct exception_regdump *pstate)
206
void debugger_bpoint(struct exception_regdump *pstate)
207
{
207
{
208
    char *symbol;
208
    char *symbol;
209
    bpinfo_t *cur = NULL;
209
    bpinfo_t *cur = NULL;
210
    int i;
210
    int i;
211
 
211
 
212
    symbol = get_symtab_entry(pstate->epc);
212
    symbol = get_symtab_entry(pstate->epc);
213
   
213
   
214
 
214
 
215
    /* test branch delay slot */
215
    /* test branch delay slot */
216
    if (cp0_cause_read() & 0x80000000)
216
    if (cp0_cause_read() & 0x80000000)
217
        panic("Breakpoint in branch delay slot not supported.\n");
217
        panic("Breakpoint in branch delay slot not supported.\n");
218
 
218
 
219
    spinlock_lock(&bkpoint_lock);
219
    spinlock_lock(&bkpoint_lock);
220
    for (i=0; i<BKPOINTS_MAX; i++) {
220
    for (i=0; i<BKPOINTS_MAX; i++) {
221
        if (pstate->epc == breakpoints[i].address || \
221
        if (pstate->epc == breakpoints[i].address || \
222
            (pstate->epc == breakpoints[i].address+sizeof(__native) &&\
222
            (pstate->epc == breakpoints[i].address+sizeof(__native) &&\
223
             breakpoints[i].executing))
223
             breakpoints[i].executing))
224
            cur = &breakpoints[i];
224
            cur = &breakpoints[i];
225
        break;
225
        break;
226
 
226
 
227
    }
227
    }
228
    if (cur) {
228
    if (cur) {
229
        if ((cur->executing && pstate->epc==cur->address) ||
229
        if ((cur->executing && pstate->epc==cur->address) ||
230
            (!cur->executing && pstate->epc==cur->address+sizeof(__native)))
230
            (!cur->executing && pstate->epc==cur->address+sizeof(__native)))
231
            panic("Weird breakpoint state.\n");
231
            panic("Weird breakpoint state.\n");
232
        if (!cur->executing) {
232
        if (!cur->executing) {
233
            printf("***Breakpoint %d: 0x%p in %s.\n", i,
233
            printf("***Breakpoint %d: 0x%p in %s.\n", i,
234
                   pstate->epc,symbol);
234
                   pstate->epc,symbol);
235
            /* Return first instruction back */
235
            /* Return first instruction back */
236
            ((__u32 *)cur->address)[0] = cur->instruction;
236
            ((__u32 *)cur->address)[0] = cur->instruction;
237
            /* Set Breakpoint on second */
237
            /* Set Breakpoint on second */
238
            ((__u32 *)cur->address)[1] = 0x0d;
238
            ((__u32 *)cur->address)[1] = 0x0d;
239
            cur->executing = true;
239
            cur->executing = true;
240
        } else {
240
        } else {
241
            /* Set breakpoint on first instruction */
241
            /* Set breakpoint on first instruction */
242
            ((__u32 *)cur->address)[0] = 0x0d;
242
            ((__u32 *)cur->address)[0] = 0x0d;
243
            /* Return back the second */
243
            /* Return back the second */
244
            ((__u32 *)cur->address)[1] = cur->nextinstruction;
244
            ((__u32 *)cur->address)[1] = cur->nextinstruction;
245
            cur->executing = false;
245
            cur->executing = false;
246
            spinlock_unlock(&bkpoint_lock);
246
            spinlock_unlock(&bkpoint_lock);
247
            return;
247
            return;
248
        }
248
        }
249
    } else {
249
    } else {
250
        printf("***Breakpoint 0x%p in %s.\n", pstate->epc, symbol);
250
        printf("***Breakpoint 0x%p in %s.\n", pstate->epc, symbol);
251
        /* Move on to next instruction */
251
        /* Move on to next instruction */
252
        pstate->epc += 4;
252
        pstate->epc += 4;
253
    }
253
    }
254
    spinlock_unlock(&bkpoint_lock);
254
    spinlock_unlock(&bkpoint_lock);
255
 
255
 
256
           
256
           
257
    printf("***Type 'exit' to exit kconsole.\n");
257
    printf("***Type 'exit' to exit kconsole.\n");
258
    /* Umm..we should rather set some 'debugstate' here */
258
    /* Umm..we should rather set some 'debugstate' here */
259
    haltstate = 1;
259
    atomic_set(&haltstate,1);
260
    kconsole("debug");
260
    kconsole("debug");
261
    haltstate = 0;
261
    atomic_set(&haltstate,0);
262
}
262
}
263
 
263