source: mainline/arch/mips32/src/debugger.c@ dc747e3

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since dc747e3 was dc747e3, checked in by Jakub Jermar <jakub@…>, 20 years ago

Add SPINLOCK_DECLARE and SPINLOCK_INITIALIZE macros.
SPINLOCK_DECLARE is to be used instead of direct spinlock_t declarations
in dynamically allocated structures on which spinlock_initialize() is called after
their creation.
SPINLOCK_INITIALIZE is to be used instead of direct spinlock_t declarations
of global spinlocks. It declares and initializes the spinlock.
Moreover, both macros are empty on UP so that -Wall warnings about unused structures
get supressed.

  • Property mode set to 100644
File size: 7.2 KB
Line 
1/*
2 * Copyright (C) 2005 Ondrej Palkovsky
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
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
15 * derived from this software without specific prior written permission.
16 *
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
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
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
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
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <arch/debugger.h>
30#include <memstr.h>
31#include <console/kconsole.h>
32#include <console/cmd.h>
33#include <symtab.h>
34#include <print.h>
35#include <panic.h>
36#include <arch.h>
37#include <arch/cp0.h>
38#include <func.h>
39
40bpinfo_t breakpoints[BKPOINTS_MAX];
41SPINLOCK_INITIALIZE(bkpoint_lock);
42
43static int cmd_print_breakpoints(cmd_arg_t *argv);
44static cmd_info_t pbkpt_info = {
45 .name = "pbkpt",
46 .description = "Print breakpoint table.",
47 .func = cmd_print_breakpoints,
48 .argc = 0,
49};
50
51static int cmd_del_breakpoint(cmd_arg_t *argv);
52static cmd_arg_t del_argv = {
53 .type = ARG_TYPE_INT
54};
55static cmd_info_t delbkpt_info = {
56 .name = "delbkpt",
57 .description = "delbkpt <number> - Delete breakpoint.",
58 .func = cmd_del_breakpoint,
59 .argc = 1,
60 .argv = &del_argv
61};
62
63static int cmd_add_breakpoint(cmd_arg_t *argv);
64static cmd_arg_t add_argv = {
65 .type = ARG_TYPE_INT
66};
67static cmd_info_t addbkpt_info = {
68 .name = "addbkpt",
69 .description = "addbkpt <&symbol> - new bkpoint. Break on J/Branch insts unsupported.",
70 .func = cmd_add_breakpoint,
71 .argc = 1,
72 .argv = &add_argv
73};
74
75/** Add new breakpoint to table */
76int cmd_add_breakpoint(cmd_arg_t *argv)
77{
78 bpinfo_t *cur = NULL;
79 ipl_t ipl;
80 int i;
81
82 if (argv->intval & 0x3) {
83 printf("Not aligned instruction, forgot to use &symbol?\n");
84 return 1;
85 }
86 ipl = interrupts_disable();
87 spinlock_lock(&bkpoint_lock);
88
89 /* Check, that the breakpoints do not conflict */
90 for (i=0; i<BKPOINTS_MAX; i++) {
91 if (breakpoints[i].address == (__address)argv->intval) {
92 printf("Duplicate breakpoint %d.\n", i);
93 spinlock_unlock(&bkpoints_lock);
94 return 0;
95 } else if (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);
98 spinlock_unlock(&bkpoints_lock);
99 return 0;
100 }
101
102 }
103
104 for (i=0; i<BKPOINTS_MAX; i++)
105 if (!breakpoints[i].address) {
106 cur = &breakpoints[i];
107 break;
108 }
109 if (!cur) {
110 printf("Too many breakpoints.\n");
111 spinlock_unlock(&bkpoint_lock);
112 interrupts_restore(ipl);
113 return 0;
114 }
115 cur->address = (__address) argv->intval;
116 printf("Adding breakpoint on address: %p\n", argv->intval);
117 cur->instruction = ((__native *)cur->address)[0];
118 cur->nextinstruction = ((__native *)cur->address)[1];
119 cur->executing = false;
120
121 /* Set breakpoint */
122 *((__native *)cur->address) = 0x0d;
123
124 spinlock_unlock(&bkpoint_lock);
125 interrupts_restore(ipl);
126
127 return 1;
128}
129
130/** Remove breakpoint from table */
131int cmd_del_breakpoint(cmd_arg_t *argv)
132{
133 bpinfo_t *cur;
134 ipl_t ipl;
135
136 if (argv->intval < 0 || argv->intval > BKPOINTS_MAX) {
137 printf("Invalid breakpoint number.\n");
138 return 0;
139 }
140 ipl = interrupts_disable();
141 spinlock_lock(&bkpoint_lock);
142
143 cur = &breakpoints[argv->intval];
144 if (!cur->address) {
145 printf("Breakpoint does not exist.\n");
146 spinlock_unlock(&bkpoint_lock);
147 interrupts_restore(ipl);
148 return 0;
149 }
150
151 ((__u32 *)cur->address)[0] = cur->instruction;
152 ((__u32 *)cur->address)[1] = cur->nextinstruction;
153
154 cur->address = NULL;
155
156 spinlock_unlock(&bkpoint_lock);
157 interrupts_restore(ipl);
158 return 1;
159}
160
161/** Print table of active breakpoints */
162int cmd_print_breakpoints(cmd_arg_t *argv)
163{
164 int i;
165 char *symbol;
166
167 printf("Breakpoint table.\n");
168 for (i=0; i < BKPOINTS_MAX; i++)
169 if (breakpoints[i].address) {
170 symbol = get_symtab_entry(breakpoints[i].address);
171 printf("%d. 0x%p in %s\n",i,
172 breakpoints[i].address, symbol);
173 }
174 return 1;
175}
176
177/** Initialize debugger */
178void debugger_init()
179{
180 int i;
181
182 for (i=0; i<BKPOINTS_MAX; i++)
183 breakpoints[i].address = NULL;
184
185 cmd_initialize(&pbkpt_info);
186 if (!cmd_register(&pbkpt_info))
187 panic("could not register command %s\n", pbkpt_info.name);
188
189 cmd_initialize(&delbkpt_info);
190 if (!cmd_register(&delbkpt_info))
191 panic("could not register command %s\n", delbkpt_info.name);
192
193 cmd_initialize(&addbkpt_info);
194 if (!cmd_register(&addbkpt_info))
195 panic("could not register command %s\n", addbkpt_info.name);
196}
197
198/** Handle breakpoint
199 *
200 * Find breakpoint in breakpoint table.
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.
203 * If breakpoint not found in breakpoint table, call kconsole and start
204 * next instruction.
205 */
206void debugger_bpoint(struct exception_regdump *pstate)
207{
208 char *symbol;
209 bpinfo_t *cur = NULL;
210 int i;
211
212 symbol = get_symtab_entry(pstate->epc);
213
214
215 /* test branch delay slot */
216 if (cp0_cause_read() & 0x80000000)
217 panic("Breakpoint in branch delay slot not supported.\n");
218
219 spinlock_lock(&bkpoint_lock);
220 for (i=0; i<BKPOINTS_MAX; i++) {
221 if (pstate->epc == breakpoints[i].address || \
222 (pstate->epc == breakpoints[i].address+sizeof(__native) &&\
223 breakpoints[i].executing))
224 cur = &breakpoints[i];
225 break;
226
227 }
228 if (cur) {
229 if ((cur->executing && pstate->epc==cur->address) ||
230 (!cur->executing && pstate->epc==cur->address+sizeof(__native)))
231 panic("Weird breakpoint state.\n");
232 if (!cur->executing) {
233 printf("***Breakpoint %d: 0x%p in %s.\n", i,
234 pstate->epc,symbol);
235 /* Return first instruction back */
236 ((__u32 *)cur->address)[0] = cur->instruction;
237 /* Set Breakpoint on second */
238 ((__u32 *)cur->address)[1] = 0x0d;
239 cur->executing = true;
240 } else {
241 /* Set breakpoint on first instruction */
242 ((__u32 *)cur->address)[0] = 0x0d;
243 /* Return back the second */
244 ((__u32 *)cur->address)[1] = cur->nextinstruction;
245 cur->executing = false;
246 spinlock_unlock(&bkpoint_lock);
247 return;
248 }
249 } else {
250 printf("***Breakpoint 0x%p in %s.\n", pstate->epc, symbol);
251 /* Move on to next instruction */
252 pstate->epc += 4;
253 }
254 spinlock_unlock(&bkpoint_lock);
255
256
257 printf("***Type 'exit' to exit kconsole.\n");
258 /* Umm..we should rather set some 'debugstate' here */
259 haltstate = 1;
260 kconsole("debug");
261 haltstate = 0;
262}
Note: See TracBrowser for help on using the repository browser.