rlm@1
|
1 // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
|
rlm@1
|
2 // Copyright (C) 1999-2003 Forgotten
|
rlm@1
|
3 // Copyright (C) 2004 Forgotten and the VBA development team
|
rlm@1
|
4
|
rlm@1
|
5 // This program is free software; you can redistribute it and/or modify
|
rlm@1
|
6 // it under the terms of the GNU General Public License as published by
|
rlm@1
|
7 // the Free Software Foundation; either version 2, or(at your option)
|
rlm@1
|
8 // any later version.
|
rlm@1
|
9 //
|
rlm@1
|
10 // This program is distributed in the hope that it will be useful,
|
rlm@1
|
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
|
rlm@1
|
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
rlm@1
|
13 // GNU General Public License for more details.
|
rlm@1
|
14 //
|
rlm@1
|
15 // You should have received a copy of the GNU General Public License
|
rlm@1
|
16 // along with this program; if not, write to the Free Software Foundation,
|
rlm@1
|
17 // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
rlm@1
|
18
|
rlm@1
|
19 extern "C" {
|
rlm@1
|
20 #include <stdio.h>
|
rlm@1
|
21 #include <stdlib.h>
|
rlm@1
|
22 } // FIXME: should use c++ headers instead
|
rlm@1
|
23
|
rlm@1
|
24 #include <string.h>
|
rlm@1
|
25
|
rlm@1
|
26 #include "Port.h"
|
rlm@1
|
27 #include "gba/GBA.h"
|
rlm@1
|
28 #include "gba/GBAGlobals.h"
|
rlm@1
|
29 #include "gba/GBACheats.h"
|
rlm@1
|
30 #include "gba/armdis.h"
|
rlm@1
|
31 #include "gba/elf.h"
|
rlm@1
|
32 #include "common/System.h"
|
rlm@1
|
33 #include "exprNode.h"
|
rlm@1
|
34
|
rlm@1
|
35 extern bool debugger;
|
rlm@1
|
36 extern int emulating;
|
rlm@1
|
37
|
rlm@1
|
38 extern struct EmulatedSystem theEmulator;
|
rlm@1
|
39
|
rlm@1
|
40 #define debuggerReadMemory(addr) \
|
rlm@1
|
41 READ32LE((&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]))
|
rlm@1
|
42
|
rlm@1
|
43 #define debuggerReadHalfWord(addr) \
|
rlm@1
|
44 READ16LE((&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]))
|
rlm@1
|
45
|
rlm@1
|
46 #define debuggerReadByte(addr) \
|
rlm@1
|
47 map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]
|
rlm@1
|
48
|
rlm@1
|
49 #define debuggerWriteMemory(addr, value) \
|
rlm@1
|
50 WRITE32LE(&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask], value)
|
rlm@1
|
51
|
rlm@1
|
52 #define debuggerWriteHalfWord(addr, value) \
|
rlm@1
|
53 WRITE16LE(&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask], value)
|
rlm@1
|
54
|
rlm@1
|
55 #define debuggerWriteByte(addr, value) \
|
rlm@1
|
56 map[(addr)>>24].address[(addr) & map[(addr)>>24].mask] = (value)
|
rlm@1
|
57
|
rlm@1
|
58 struct breakpointInfo {
|
rlm@1
|
59 u32 address;
|
rlm@1
|
60 u32 value;
|
rlm@1
|
61 int size;
|
rlm@1
|
62 };
|
rlm@1
|
63
|
rlm@1
|
64 struct DebuggerCommand {
|
rlm@1
|
65 const char *name;
|
rlm@1
|
66 void (*function)(int,char **);
|
rlm@1
|
67 const char *help;
|
rlm@1
|
68 const char *syntax;
|
rlm@1
|
69 };
|
rlm@1
|
70
|
rlm@1
|
71 void debuggerContinueAfterBreakpoint();
|
rlm@1
|
72
|
rlm@1
|
73 void debuggerHelp(int,char **);
|
rlm@1
|
74 void debuggerNext(int,char **);
|
rlm@1
|
75 void debuggerContinue(int, char **);
|
rlm@1
|
76 void debuggerRegisters(int, char **);
|
rlm@1
|
77 void debuggerBreak(int, char **);
|
rlm@1
|
78 void debuggerBreakDelete(int, char **);
|
rlm@1
|
79 void debuggerBreakList(int, char **);
|
rlm@1
|
80 void debuggerBreakArm(int, char **);
|
rlm@1
|
81 void debuggerBreakWriteClear(int, char **);
|
rlm@1
|
82 void debuggerBreakThumb(int, char **);
|
rlm@1
|
83 void debuggerBreakWrite(int, char **);
|
rlm@1
|
84 void debuggerDebug(int, char **);
|
rlm@1
|
85 void debuggerDisassemble(int, char **);
|
rlm@1
|
86 void debuggerDisassembleArm(int, char **);
|
rlm@1
|
87 void debuggerDisassembleThumb(int, char **);
|
rlm@1
|
88 void debuggerEditByte(int, char **);
|
rlm@1
|
89 void debuggerEditHalfWord(int, char **);
|
rlm@1
|
90 void debuggerEdit(int, char **);
|
rlm@1
|
91 void debuggerIo(int, char **);
|
rlm@1
|
92 void debuggerLocals(int, char **);
|
rlm@1
|
93 void debuggerMemoryByte(int, char **);
|
rlm@1
|
94 void debuggerMemoryHalfWord(int, char **);
|
rlm@1
|
95 void debuggerMemory(int, char **);
|
rlm@1
|
96 void debuggerPrint(int, char **);
|
rlm@1
|
97 void debuggerQuit(int, char **);
|
rlm@1
|
98 void debuggerSetRadix(int, char **);
|
rlm@1
|
99 void debuggerSymbols(int, char **);
|
rlm@1
|
100 void debuggerVerbose(int, char **);
|
rlm@1
|
101 void debuggerWhere(int, char **);
|
rlm@1
|
102
|
rlm@1
|
103 DebuggerCommand debuggerCommands[] = {
|
rlm@1
|
104 { "?", debuggerHelp, "Shows this help information. Type ? <command> for command help", "[<command>]" },
|
rlm@1
|
105 { "ba", debuggerBreakArm, "Adds an ARM breakpoint", "<address>" },
|
rlm@1
|
106 { "bd", debuggerBreakDelete,"Deletes a breakpoint", "<number>" },
|
rlm@1
|
107 { "bl", debuggerBreakList, "Lists breakpoints" },
|
rlm@1
|
108 { "bpw", debuggerBreakWrite, "Break on write", "<address> <size>" },
|
rlm@1
|
109 { "bpwc", debuggerBreakWriteClear, "Clear break on write", NULL },
|
rlm@1
|
110 { "break", debuggerBreak, "Adds a breakpoint on the given function", "<function>|<line>|<file:line>" },
|
rlm@1
|
111 { "bt", debuggerBreakThumb, "Adds a THUMB breakpoint", "<address>" },
|
rlm@1
|
112 { "c", debuggerContinue, "Continues execution" , NULL },
|
rlm@1
|
113 { "d", debuggerDisassemble, "Disassembles instructions", "[<address> [<number>]]" },
|
rlm@1
|
114 { "da", debuggerDisassembleArm, "Disassembles ARM instructions", "[<address> [<number>]]" },
|
rlm@1
|
115 { "dt", debuggerDisassembleThumb, "Disassembles THUMB instructions", "[<address> [<number>]]" },
|
rlm@1
|
116 { "eb", debuggerEditByte, "Modify memory location (byte)", "<address> <hex value>" },
|
rlm@1
|
117 { "eh", debuggerEditHalfWord,"Modify memory location (half-word)","<address> <hex value>" },
|
rlm@1
|
118 { "ew", debuggerEdit, "Modify memory location (word)", "<address> <hex value" },
|
rlm@1
|
119 { "h", debuggerHelp, "Shows this help information. Type h <command> for command help", "[<command>]" },
|
rlm@1
|
120 { "io", debuggerIo, "Show I/O registers status", "[video|video2|dma|timer|misc]" },
|
rlm@1
|
121 { "locals", debuggerLocals, "Shows local variables", NULL },
|
rlm@1
|
122 { "mb", debuggerMemoryByte, "Shows memory contents (bytes)", "<address>" },
|
rlm@1
|
123 { "mh", debuggerMemoryHalfWord, "Shows memory contents (half-words)", "<address>"},
|
rlm@1
|
124 { "mw", debuggerMemory, "Shows memory contents (words)", "<address>" },
|
rlm@1
|
125 { "n", debuggerNext, "Executes the next instruction", "[<count>]" },
|
rlm@1
|
126 { "print", debuggerPrint, "Print the value of a expression (if known)", "[/x|/o|/d] <expression>" },
|
rlm@1
|
127 { "q", debuggerQuit, "Quits the emulator", NULL },
|
rlm@1
|
128 { "r", debuggerRegisters, "Shows ARM registers", NULL },
|
rlm@1
|
129 { "radix", debuggerSetRadix, "Sets the print radix", "<radix>" },
|
rlm@1
|
130 { "symbols", debuggerSymbols, "List symbols", "[<symbol>]" },
|
rlm@1
|
131 #ifndef FINAL_VERSION
|
rlm@1
|
132 { "trace", debuggerDebug, "Sets the trace level", "<value>" },
|
rlm@1
|
133 #endif
|
rlm@1
|
134 #ifdef DEV_VERSION
|
rlm@1
|
135 { "verbose", debuggerVerbose, "Change verbose setting", "<value>" },
|
rlm@1
|
136 #endif
|
rlm@1
|
137 { "where", debuggerWhere, "Shows call chain", NULL },
|
rlm@1
|
138 { NULL, NULL, NULL, NULL} // end marker
|
rlm@1
|
139 };
|
rlm@1
|
140
|
rlm@1
|
141 breakpointInfo debuggerBreakpointList[100];
|
rlm@1
|
142
|
rlm@1
|
143 int debuggerNumOfBreakpoints = 0;
|
rlm@1
|
144 bool debuggerAtBreakpoint = false;
|
rlm@1
|
145 int debuggerBreakpointNumber = 0;
|
rlm@1
|
146 int debuggerRadix = 0;
|
rlm@1
|
147
|
rlm@1
|
148 void debuggerApplyBreakpoint(u32 address, int num, int size)
|
rlm@1
|
149 {
|
rlm@1
|
150 if(size)
|
rlm@1
|
151 debuggerWriteMemory(address, (u32)(0xe1200070 |
|
rlm@1
|
152 (num & 0xf) |
|
rlm@1
|
153 ((num<<4)&0xf0)));
|
rlm@1
|
154 else
|
rlm@1
|
155 debuggerWriteHalfWord(address,
|
rlm@1
|
156 (u16)(0xbe00 | num));
|
rlm@1
|
157 }
|
rlm@1
|
158
|
rlm@1
|
159 void debuggerDisableBreakpoints()
|
rlm@1
|
160 {
|
rlm@1
|
161 for(int i = 0; i < debuggerNumOfBreakpoints; i++) {
|
rlm@1
|
162 if(debuggerBreakpointList[i].size)
|
rlm@1
|
163 debuggerWriteMemory(debuggerBreakpointList[i].address,
|
rlm@1
|
164 debuggerBreakpointList[i].value);
|
rlm@1
|
165 else
|
rlm@1
|
166 debuggerWriteHalfWord(debuggerBreakpointList[i].address,
|
rlm@1
|
167 debuggerBreakpointList[i].value);
|
rlm@1
|
168 }
|
rlm@1
|
169 }
|
rlm@1
|
170
|
rlm@1
|
171 void debuggerEnableBreakpoints(bool skipPC)
|
rlm@1
|
172 {
|
rlm@1
|
173 for(int i = 0; i < debuggerNumOfBreakpoints; i++) {
|
rlm@1
|
174 if(debuggerBreakpointList[i].address == armNextPC && skipPC)
|
rlm@1
|
175 continue;
|
rlm@1
|
176
|
rlm@1
|
177 debuggerApplyBreakpoint(debuggerBreakpointList[i].address,
|
rlm@1
|
178 i,
|
rlm@1
|
179 debuggerBreakpointList[i].size);
|
rlm@1
|
180 }
|
rlm@1
|
181 }
|
rlm@1
|
182
|
rlm@1
|
183 void debuggerUsage(const char *cmd)
|
rlm@1
|
184 {
|
rlm@1
|
185 for(int i = 0; ; i++) {
|
rlm@1
|
186 if(debuggerCommands[i].name) {
|
rlm@1
|
187 if(!strcmp(debuggerCommands[i].name, cmd)) {
|
rlm@1
|
188 printf("%s %s\t%s\n",
|
rlm@1
|
189 debuggerCommands[i].name,
|
rlm@1
|
190 debuggerCommands[i].syntax ? debuggerCommands[i].syntax : "",
|
rlm@1
|
191 debuggerCommands[i].help);
|
rlm@1
|
192 break;
|
rlm@1
|
193 }
|
rlm@1
|
194 } else {
|
rlm@1
|
195 printf("Unrecognized command '%s'.", cmd);
|
rlm@1
|
196 break;
|
rlm@1
|
197 }
|
rlm@1
|
198 }
|
rlm@1
|
199 }
|
rlm@1
|
200
|
rlm@1
|
201 void debuggerPrintBaseType(Type *t, u32 value, u32 location,
|
rlm@1
|
202 LocationType type,
|
rlm@1
|
203 int bitSize, int bitOffset)
|
rlm@1
|
204 {
|
rlm@1
|
205 if(bitSize) {
|
rlm@1
|
206 if(bitOffset)
|
rlm@1
|
207 value >>= ((t->size*8)-bitOffset-bitSize);
|
rlm@1
|
208 value &= (1 << bitSize)-1;
|
rlm@1
|
209 } else {
|
rlm@1
|
210 if(t->size == 2)
|
rlm@1
|
211 value &= 0xFFFF;
|
rlm@1
|
212 else if(t->size == 1)
|
rlm@1
|
213 value &= 0xFF;
|
rlm@1
|
214 }
|
rlm@1
|
215
|
rlm@1
|
216 if(t->size == 8) {
|
rlm@1
|
217 u64 value = 0;
|
rlm@1
|
218 if(type == LOCATION_memory) {
|
rlm@1
|
219 value = debuggerReadMemory(location) |
|
rlm@1
|
220 ((u64)debuggerReadMemory(location+4)<<32);
|
rlm@1
|
221 } else if(type == LOCATION_register) {
|
rlm@1
|
222 value = reg[location].I | ((u64)reg[location+1].I << 32);
|
rlm@1
|
223 }
|
rlm@1
|
224 switch(t->encoding) {
|
rlm@1
|
225 case DW_ATE_signed:
|
rlm@1
|
226 switch(debuggerRadix) {
|
rlm@1
|
227 case 0:
|
rlm@1
|
228 printf("%lld", value);
|
rlm@1
|
229 break;
|
rlm@1
|
230 case 1:
|
rlm@1
|
231 printf("0x%llx", value);
|
rlm@1
|
232 break;
|
rlm@1
|
233 case 2:
|
rlm@1
|
234 printf("0%llo", value);
|
rlm@1
|
235 break;
|
rlm@1
|
236 }
|
rlm@1
|
237 break;
|
rlm@1
|
238 case DW_ATE_unsigned:
|
rlm@1
|
239 switch(debuggerRadix) {
|
rlm@1
|
240 case 0:
|
rlm@1
|
241 printf("%llu", value);
|
rlm@1
|
242 break;
|
rlm@1
|
243 case 1:
|
rlm@1
|
244 printf("0x%llx", value);
|
rlm@1
|
245 break;
|
rlm@1
|
246 case 2:
|
rlm@1
|
247 printf("0%llo", value);
|
rlm@1
|
248 break;
|
rlm@1
|
249 }
|
rlm@1
|
250 break;
|
rlm@1
|
251 default:
|
rlm@1
|
252 printf("Unknowing 64-bit encoding\n");
|
rlm@1
|
253 }
|
rlm@1
|
254 return;
|
rlm@1
|
255 }
|
rlm@1
|
256
|
rlm@1
|
257 switch(t->encoding) {
|
rlm@1
|
258 case DW_ATE_boolean:
|
rlm@1
|
259 if(value)
|
rlm@1
|
260 printf("true");
|
rlm@1
|
261 else
|
rlm@1
|
262 printf("false");
|
rlm@1
|
263 break;
|
rlm@1
|
264 case DW_ATE_signed:
|
rlm@1
|
265 switch(debuggerRadix) {
|
rlm@1
|
266 case 0:
|
rlm@1
|
267 printf("%d", value);
|
rlm@1
|
268 break;
|
rlm@1
|
269 case 1:
|
rlm@1
|
270 printf("0x%x", value);
|
rlm@1
|
271 break;
|
rlm@1
|
272 case 2:
|
rlm@1
|
273 printf("0%o", value);
|
rlm@1
|
274 break;
|
rlm@1
|
275 }
|
rlm@1
|
276 break;
|
rlm@1
|
277 case DW_ATE_unsigned:
|
rlm@1
|
278 case DW_ATE_unsigned_char:
|
rlm@1
|
279 switch(debuggerRadix) {
|
rlm@1
|
280 case 0:
|
rlm@1
|
281 printf("%u", value);
|
rlm@1
|
282 break;
|
rlm@1
|
283 case 1:
|
rlm@1
|
284 printf("0x%x", value);
|
rlm@1
|
285 break;
|
rlm@1
|
286 case 2:
|
rlm@1
|
287 printf("0%o", value);
|
rlm@1
|
288 break;
|
rlm@1
|
289 }
|
rlm@1
|
290 break;
|
rlm@1
|
291 default:
|
rlm@1
|
292 printf("UNKNOWN BASE %d %08x", t->encoding, value);
|
rlm@1
|
293 }
|
rlm@1
|
294 }
|
rlm@1
|
295
|
rlm@1
|
296 char *debuggerPrintType(Type *t)
|
rlm@1
|
297 {
|
rlm@1
|
298 char buffer[1024];
|
rlm@1
|
299 static char buffer2[1024];
|
rlm@1
|
300
|
rlm@1
|
301 if(t->type == TYPE_pointer) {
|
rlm@1
|
302 if(t->pointer)
|
rlm@1
|
303 strcpy(buffer, debuggerPrintType(t->pointer));
|
rlm@1
|
304 else
|
rlm@1
|
305 strcpy(buffer, "void");
|
rlm@1
|
306 sprintf(buffer2, "%s *", buffer);
|
rlm@1
|
307 return buffer2;
|
rlm@1
|
308 } else if(t->type == TYPE_reference) {
|
rlm@1
|
309 strcpy(buffer, debuggerPrintType(t->pointer));
|
rlm@1
|
310 sprintf(buffer2, "%s &", buffer);
|
rlm@1
|
311 return buffer2;
|
rlm@1
|
312 }
|
rlm@1
|
313 return t->name;
|
rlm@1
|
314 }
|
rlm@1
|
315
|
rlm@1
|
316 void debuggerPrintValueInternal(Function *, Type *, ELFBlock *, int, int, u32);
|
rlm@1
|
317 void debuggerPrintValueInternal(Function *f, Type *t,
|
rlm@1
|
318 int bitSize, int bitOffset,
|
rlm@1
|
319 u32 objLocation, LocationType type);
|
rlm@1
|
320
|
rlm@1
|
321 u32 debuggerGetValue(u32 location, LocationType type)
|
rlm@1
|
322 {
|
rlm@1
|
323 switch(type) {
|
rlm@1
|
324 case LOCATION_memory:
|
rlm@1
|
325 return debuggerReadMemory(location);
|
rlm@1
|
326 case LOCATION_register:
|
rlm@1
|
327 return reg[location].I;
|
rlm@1
|
328 case LOCATION_value:
|
rlm@1
|
329 return location;
|
rlm@1
|
330 }
|
rlm@1
|
331 return 0;
|
rlm@1
|
332 }
|
rlm@1
|
333
|
rlm@1
|
334 void debuggerPrintPointer(Type *t, u32 value)
|
rlm@1
|
335 {
|
rlm@1
|
336 printf("(%s)0x%08x", debuggerPrintType(t), value);
|
rlm@1
|
337 }
|
rlm@1
|
338
|
rlm@1
|
339 void debuggerPrintReference(Type *t, u32 value)
|
rlm@1
|
340 {
|
rlm@1
|
341 printf("(%s)0x%08x", debuggerPrintType(t), value);
|
rlm@1
|
342 }
|
rlm@1
|
343
|
rlm@1
|
344 void debuggerPrintFunction(Type *t, u32 value)
|
rlm@1
|
345 {
|
rlm@1
|
346 printf("(%s)0x%08x", debuggerPrintType(t), value);
|
rlm@1
|
347 }
|
rlm@1
|
348
|
rlm@1
|
349 void debuggerPrintArray(Type *t, u32 value)
|
rlm@1
|
350 {
|
rlm@1
|
351 // todo
|
rlm@1
|
352 printf("(%s[])0x%08x", debuggerPrintType(t->array->type), value);
|
rlm@1
|
353 }
|
rlm@1
|
354
|
rlm@1
|
355 void debuggerPrintMember(Function *f,
|
rlm@1
|
356 Member *m,
|
rlm@1
|
357 u32 objLocation,
|
rlm@1
|
358 u32 location)
|
rlm@1
|
359 {
|
rlm@1
|
360 int bitSize = m->bitSize;
|
rlm@1
|
361 if(bitSize) {
|
rlm@1
|
362 u32 value = 0;
|
rlm@1
|
363 int off = m->bitOffset;
|
rlm@1
|
364 int size = m->byteSize;
|
rlm@1
|
365 u32 v = 0;
|
rlm@1
|
366 if(size == 1)
|
rlm@1
|
367 v = debuggerReadByte(location);
|
rlm@1
|
368 else if(size == 2)
|
rlm@1
|
369 v = debuggerReadHalfWord(location);
|
rlm@1
|
370 else if(size == 4)
|
rlm@1
|
371 v = debuggerReadMemory(location);
|
rlm@1
|
372
|
rlm@1
|
373 while(bitSize) {
|
rlm@1
|
374 int top = size*8 - off;
|
rlm@1
|
375 int bot = top - bitSize;
|
rlm@1
|
376 top--;
|
rlm@1
|
377 if(bot >= 0) {
|
rlm@1
|
378 value = (v >> (size*8 - bitSize - off)) & ((1 << bitSize)-1);
|
rlm@1
|
379 bitSize = 0;
|
rlm@1
|
380 } else {
|
rlm@1
|
381 value |= (v & ((1 << top)-1)) << (bitSize - top);
|
rlm@1
|
382 bitSize -= (top+1);
|
rlm@1
|
383 location -= size;
|
rlm@1
|
384 off = 0;
|
rlm@1
|
385 if(size == 1)
|
rlm@1
|
386 v = debuggerReadByte(location);
|
rlm@1
|
387 else if(size == 2)
|
rlm@1
|
388 v = debuggerReadHalfWord(location);
|
rlm@1
|
389 else
|
rlm@1
|
390 v = debuggerReadMemory(location);
|
rlm@1
|
391 }
|
rlm@1
|
392 }
|
rlm@1
|
393 debuggerPrintBaseType(m->type, value, location, LOCATION_memory,
|
rlm@1
|
394 bitSize, 0);
|
rlm@1
|
395 } else {
|
rlm@1
|
396 debuggerPrintValueInternal(f, m->type, m->location, m->bitSize,
|
rlm@1
|
397 m->bitOffset, objLocation);
|
rlm@1
|
398 }
|
rlm@1
|
399 }
|
rlm@1
|
400
|
rlm@1
|
401 void debuggerPrintStructure(Function *f, Type *t, u32 objLocation)
|
rlm@1
|
402 {
|
rlm@1
|
403 printf("{");
|
rlm@1
|
404 int count = t->structure->memberCount;
|
rlm@1
|
405 int i = 0;
|
rlm@1
|
406 while(i < count) {
|
rlm@1
|
407 Member *m = &t->structure->members[i];
|
rlm@1
|
408 printf("%s=", m->name);
|
rlm@1
|
409 LocationType type;
|
rlm@1
|
410 u32 location = elfDecodeLocation(f, m->location, &type, objLocation);
|
rlm@1
|
411 debuggerPrintMember(f, m, objLocation, location);
|
rlm@1
|
412 i++;
|
rlm@1
|
413 if(i < count)
|
rlm@1
|
414 printf(",");
|
rlm@1
|
415 }
|
rlm@1
|
416 printf("}");
|
rlm@1
|
417 }
|
rlm@1
|
418
|
rlm@1
|
419 void debuggerPrintUnion(Function *f, Type *t, u32 objLocation)
|
rlm@1
|
420 {
|
rlm@1
|
421 // todo
|
rlm@1
|
422 printf("{");
|
rlm@1
|
423 int count = t->structure->memberCount;
|
rlm@1
|
424 int i = 0;
|
rlm@1
|
425 while(i < count) {
|
rlm@1
|
426 Member *m = &t->structure->members[i];
|
rlm@1
|
427 printf("%s=", m->name);
|
rlm@1
|
428 debuggerPrintMember(f, m, objLocation, 0);
|
rlm@1
|
429 i++;
|
rlm@1
|
430 if(i < count)
|
rlm@1
|
431 printf(",");
|
rlm@1
|
432 }
|
rlm@1
|
433 printf("}");
|
rlm@1
|
434 }
|
rlm@1
|
435
|
rlm@1
|
436 void debuggerPrintEnum(Type *t, u32 value)
|
rlm@1
|
437 {
|
rlm@1
|
438 int i;
|
rlm@1
|
439 for(i = 0; i < t->enumeration->count; i++) {
|
rlm@1
|
440 EnumMember *m = (EnumMember *)&t->enumeration->members[i];
|
rlm@1
|
441 if(value == m->value) {
|
rlm@1
|
442 puts(m->name);
|
rlm@1
|
443 return;
|
rlm@1
|
444 }
|
rlm@1
|
445 }
|
rlm@1
|
446 printf("(UNKNOWN VALUE) %d", value);
|
rlm@1
|
447 }
|
rlm@1
|
448
|
rlm@1
|
449 void debuggerPrintValueInternal(Function *f, Type *t,
|
rlm@1
|
450 int bitSize, int bitOffset,
|
rlm@1
|
451 u32 objLocation, LocationType type)
|
rlm@1
|
452 {
|
rlm@1
|
453 u32 value = debuggerGetValue(objLocation, type);
|
rlm@1
|
454 if(!t) {
|
rlm@1
|
455 printf("void");
|
rlm@1
|
456 return;
|
rlm@1
|
457 }
|
rlm@1
|
458 switch(t->type) {
|
rlm@1
|
459 case TYPE_base:
|
rlm@1
|
460 debuggerPrintBaseType(t, value, objLocation, type, bitSize, bitOffset);
|
rlm@1
|
461 break;
|
rlm@1
|
462 case TYPE_pointer:
|
rlm@1
|
463 debuggerPrintPointer(t, value);
|
rlm@1
|
464 break;
|
rlm@1
|
465 case TYPE_reference:
|
rlm@1
|
466 debuggerPrintReference(t, value);
|
rlm@1
|
467 break;
|
rlm@1
|
468 case TYPE_function:
|
rlm@1
|
469 debuggerPrintFunction(t, value);
|
rlm@1
|
470 break;
|
rlm@1
|
471 case TYPE_array:
|
rlm@1
|
472 debuggerPrintArray(t, objLocation);
|
rlm@1
|
473 break;
|
rlm@1
|
474 case TYPE_struct:
|
rlm@1
|
475 debuggerPrintStructure(f, t, objLocation);
|
rlm@1
|
476 break;
|
rlm@1
|
477 case TYPE_union:
|
rlm@1
|
478 debuggerPrintUnion(f, t, objLocation);
|
rlm@1
|
479 break;
|
rlm@1
|
480 case TYPE_enum:
|
rlm@1
|
481 debuggerPrintEnum(t, value);
|
rlm@1
|
482 break;
|
rlm@1
|
483 default:
|
rlm@1
|
484 printf("%08x", value);
|
rlm@1
|
485 break;
|
rlm@1
|
486 }
|
rlm@1
|
487 }
|
rlm@1
|
488
|
rlm@1
|
489 void debuggerPrintValueInternal(Function *f, Type *t, ELFBlock *loc,
|
rlm@1
|
490 int bitSize, int bitOffset, u32 objLocation)
|
rlm@1
|
491 {
|
rlm@1
|
492 LocationType type;
|
rlm@1
|
493 u32 location;
|
rlm@1
|
494 if(loc) {
|
rlm@1
|
495 if(objLocation)
|
rlm@1
|
496 location = elfDecodeLocation(f, loc, &type, objLocation);
|
rlm@1
|
497 else
|
rlm@1
|
498 location = elfDecodeLocation(f, loc,&type);
|
rlm@1
|
499 } else {
|
rlm@1
|
500 location = objLocation;
|
rlm@1
|
501 type = LOCATION_memory;
|
rlm@1
|
502 }
|
rlm@1
|
503
|
rlm@1
|
504 debuggerPrintValueInternal(f, t, bitSize, bitOffset, location, type);
|
rlm@1
|
505 }
|
rlm@1
|
506
|
rlm@1
|
507 void debuggerPrintValue(Function *f, Object *o)
|
rlm@1
|
508 {
|
rlm@1
|
509 debuggerPrintValueInternal(f, o->type, o->location, 0, 0, 0);
|
rlm@1
|
510
|
rlm@1
|
511 printf("\n");
|
rlm@1
|
512 }
|
rlm@1
|
513
|
rlm@1
|
514 void debuggerSymbols(int argc, char **argv)
|
rlm@1
|
515 {
|
rlm@1
|
516 int i = 0;
|
rlm@1
|
517 u32 value;
|
rlm@1
|
518 u32 size;
|
rlm@1
|
519 int type;
|
rlm@1
|
520 bool match = false;
|
rlm@1
|
521 int matchSize = 0;
|
rlm@1
|
522 char *matchStr = NULL;
|
rlm@1
|
523
|
rlm@1
|
524 if(argc == 2) {
|
rlm@1
|
525 match = true;
|
rlm@1
|
526 matchSize = strlen(argv[1]);
|
rlm@1
|
527 matchStr = argv[1];
|
rlm@1
|
528 }
|
rlm@1
|
529 printf("Symbol Value Size Type \n");
|
rlm@1
|
530 printf("-------------------- ------- -------- -------\n");
|
rlm@1
|
531 char *s = NULL;
|
rlm@1
|
532 while((s = elfGetSymbol(i, &value, &size, &type))) {
|
rlm@1
|
533 if(*s) {
|
rlm@1
|
534 if(match) {
|
rlm@1
|
535 if(strncmp(s, matchStr, matchSize) != 0) {
|
rlm@1
|
536 i++;
|
rlm@1
|
537 continue;
|
rlm@1
|
538 }
|
rlm@1
|
539 }
|
rlm@1
|
540 const char *ts = "?";
|
rlm@1
|
541 switch(type) {
|
rlm@1
|
542 case 2:
|
rlm@1
|
543 ts = "ARM";
|
rlm@1
|
544 break;
|
rlm@1
|
545 case 0x0d:
|
rlm@1
|
546 ts = "THUMB";
|
rlm@1
|
547 break;
|
rlm@1
|
548 case 1:
|
rlm@1
|
549 ts = "DATA";
|
rlm@1
|
550 break;
|
rlm@1
|
551 }
|
rlm@1
|
552 printf("%-20s %08x %08x %-7s\n",
|
rlm@1
|
553 s, value, size, ts);
|
rlm@1
|
554 }
|
rlm@1
|
555 i++;
|
rlm@1
|
556 }
|
rlm@1
|
557 }
|
rlm@1
|
558
|
rlm@1
|
559 void debuggerSetRadix(int argc, char **argv)
|
rlm@1
|
560 {
|
rlm@1
|
561 if(argc != 2)
|
rlm@1
|
562 debuggerUsage(argv[0]);
|
rlm@1
|
563 else {
|
rlm@1
|
564 int r = atoi(argv[1]);
|
rlm@1
|
565
|
rlm@1
|
566 bool error = false;
|
rlm@1
|
567 switch(r) {
|
rlm@1
|
568 case 10:
|
rlm@1
|
569 debuggerRadix = 0;
|
rlm@1
|
570 break;
|
rlm@1
|
571 case 8:
|
rlm@1
|
572 debuggerRadix = 2;
|
rlm@1
|
573 break;
|
rlm@1
|
574 case 16:
|
rlm@1
|
575 debuggerRadix = 1;
|
rlm@1
|
576 break;
|
rlm@1
|
577 default:
|
rlm@1
|
578 error = true;
|
rlm@1
|
579 printf("Unknown radix %d. Valid values are 8, 10 and 16.\n", r);
|
rlm@1
|
580 break;
|
rlm@1
|
581 }
|
rlm@1
|
582 if(!error)
|
rlm@1
|
583 printf("Radix set to %d\n", r);
|
rlm@1
|
584 }
|
rlm@1
|
585 }
|
rlm@1
|
586
|
rlm@1
|
587 void debuggerPrint(int argc, char **argv)
|
rlm@1
|
588 {
|
rlm@1
|
589 if(argc != 2 && argc != 3) {
|
rlm@1
|
590 debuggerUsage(argv[0]);
|
rlm@1
|
591 } else {
|
rlm@1
|
592 u32 pc = armNextPC;
|
rlm@1
|
593 Function *f = NULL;
|
rlm@1
|
594 CompileUnit *u = NULL;
|
rlm@1
|
595
|
rlm@1
|
596 elfGetCurrentFunction(pc,
|
rlm@1
|
597 &f, &u);
|
rlm@1
|
598
|
rlm@1
|
599 int oldRadix = debuggerRadix;
|
rlm@1
|
600 if(argc == 3) {
|
rlm@1
|
601 if(argv[1][0] == '/') {
|
rlm@1
|
602 if(argv[1][1] == 'x')
|
rlm@1
|
603 debuggerRadix = 1;
|
rlm@1
|
604 else if(argv[1][1] == 'o')
|
rlm@1
|
605 debuggerRadix = 2;
|
rlm@1
|
606 else if(argv[1][1] == 'd')
|
rlm@1
|
607 debuggerRadix = 0;
|
rlm@1
|
608 else {
|
rlm@1
|
609 printf("Unknown format %c\n", argv[1][1]);
|
rlm@1
|
610 return;
|
rlm@1
|
611 }
|
rlm@1
|
612 } else {
|
rlm@1
|
613 printf("Unknown option %s\n", argv[1]);
|
rlm@1
|
614 return;
|
rlm@1
|
615 }
|
rlm@1
|
616 }
|
rlm@1
|
617
|
rlm@1
|
618 char *s = argc == 2 ? argv[1] : argv[2];
|
rlm@1
|
619
|
rlm@1
|
620 extern char *exprString;
|
rlm@1
|
621 extern int exprCol;
|
rlm@1
|
622 extern int yyparse();
|
rlm@1
|
623 exprString = s;
|
rlm@1
|
624 exprCol = 0;
|
rlm@1
|
625 if(!yyparse()) {
|
rlm@1
|
626 extern Node *result;
|
rlm@1
|
627 if(result->resolve(result, f, u)) {
|
rlm@1
|
628 if(result->member)
|
rlm@1
|
629 debuggerPrintMember(f,
|
rlm@1
|
630 result->member,
|
rlm@1
|
631 result->objLocation,
|
rlm@1
|
632 result->location);
|
rlm@1
|
633 else
|
rlm@1
|
634 debuggerPrintValueInternal(f, result->type, 0, 0,
|
rlm@1
|
635 result->location,
|
rlm@1
|
636 result->locType);
|
rlm@1
|
637 printf("\n");
|
rlm@1
|
638 } else {
|
rlm@1
|
639 printf("Error resolving expression\n");
|
rlm@1
|
640 }
|
rlm@1
|
641 } else {
|
rlm@1
|
642 printf("Error parsing expression:\n");
|
rlm@1
|
643 printf("%s\n", s);
|
rlm@1
|
644 exprCol--;
|
rlm@1
|
645 for(int i = 0; i < exprCol; i++)
|
rlm@1
|
646 printf(" ");
|
rlm@1
|
647 printf("^\n");
|
rlm@1
|
648 }
|
rlm@1
|
649 extern void exprCleanBuffer();
|
rlm@1
|
650 exprCleanBuffer();
|
rlm@1
|
651 exprNodeCleanUp();
|
rlm@1
|
652 debuggerRadix = oldRadix;
|
rlm@1
|
653 }
|
rlm@1
|
654 }
|
rlm@1
|
655
|
rlm@1
|
656 void debuggerHelp(int n, char **args)
|
rlm@1
|
657 {
|
rlm@1
|
658 if(n == 2) {
|
rlm@1
|
659 debuggerUsage(args[1]);
|
rlm@1
|
660 } else {
|
rlm@1
|
661 for(int i = 0; ; i++) {
|
rlm@1
|
662 if(debuggerCommands[i].name) {
|
rlm@1
|
663 printf("%s\t%s\n", debuggerCommands[i].name, debuggerCommands[i].help);
|
rlm@1
|
664 } else
|
rlm@1
|
665 break;
|
rlm@1
|
666 }
|
rlm@1
|
667 }
|
rlm@1
|
668 }
|
rlm@1
|
669
|
rlm@1
|
670 void debuggerDebug(int n, char **args)
|
rlm@1
|
671 {
|
rlm@1
|
672 if(n == 2) {
|
rlm@1
|
673 int v = 0;
|
rlm@1
|
674 sscanf(args[1], "%d", &v);
|
rlm@1
|
675 systemDebug = v;
|
rlm@1
|
676 printf("Debug level set to %d\n", systemDebug);
|
rlm@1
|
677 } else
|
rlm@1
|
678 debuggerUsage("trace");
|
rlm@1
|
679 }
|
rlm@1
|
680
|
rlm@1
|
681 void debuggerVerbose(int n, char **args)
|
rlm@1
|
682 {
|
rlm@1
|
683 if(n == 2) {
|
rlm@1
|
684 int v = 0;
|
rlm@1
|
685 sscanf(args[1], "%d", &v);
|
rlm@1
|
686 systemVerbose = v;
|
rlm@1
|
687 printf("Verbose level set to %d\n", systemVerbose);
|
rlm@1
|
688 } else
|
rlm@1
|
689 debuggerUsage("verbose");
|
rlm@1
|
690 }
|
rlm@1
|
691
|
rlm@1
|
692 void debuggerWhere(int n, char **args)
|
rlm@1
|
693 {
|
rlm@1
|
694 void elfPrintCallChain(u32);
|
rlm@1
|
695 elfPrintCallChain(armNextPC);
|
rlm@1
|
696 }
|
rlm@1
|
697
|
rlm@1
|
698 void debuggerLocals(int n, char **args)
|
rlm@1
|
699 {
|
rlm@1
|
700 Function *f = NULL;
|
rlm@1
|
701 CompileUnit *u = NULL;
|
rlm@1
|
702 u32 pc = armNextPC;
|
rlm@1
|
703 if(elfGetCurrentFunction(pc,
|
rlm@1
|
704 &f, &u)) {
|
rlm@1
|
705 Object *o = f->parameters;
|
rlm@1
|
706 while(o) {
|
rlm@1
|
707 printf("%s=", o->name);
|
rlm@1
|
708 debuggerPrintValue(f, o);
|
rlm@1
|
709 o = o->next;
|
rlm@1
|
710 }
|
rlm@1
|
711
|
rlm@1
|
712 o = f->variables;
|
rlm@1
|
713 while(o) {
|
rlm@1
|
714 bool visible = o->startScope ? pc>=o->startScope : true;
|
rlm@1
|
715 if(visible)
|
rlm@1
|
716 visible = o->endScope ? pc < o->endScope : true;
|
rlm@1
|
717 if(visible) {
|
rlm@1
|
718 printf("%s=", o->name);
|
rlm@1
|
719 debuggerPrintValue(f, o);
|
rlm@1
|
720 }
|
rlm@1
|
721 o = o->next;
|
rlm@1
|
722 }
|
rlm@1
|
723 } else {
|
rlm@1
|
724 printf("No information for current address\n");
|
rlm@1
|
725 }
|
rlm@1
|
726 }
|
rlm@1
|
727
|
rlm@1
|
728 void debuggerNext(int n, char **args)
|
rlm@1
|
729 {
|
rlm@1
|
730 int count = 1;
|
rlm@1
|
731 if(n == 2) {
|
rlm@1
|
732 sscanf(args[1], "%d", &count);
|
rlm@1
|
733 }
|
rlm@1
|
734 for(int i = 0; i < count; i++) {
|
rlm@1
|
735 if(debuggerAtBreakpoint) {
|
rlm@1
|
736 debuggerContinueAfterBreakpoint();
|
rlm@1
|
737 debuggerEnableBreakpoints(false);
|
rlm@1
|
738 } else
|
rlm@1
|
739 theEmulator.emuMain(1);
|
rlm@1
|
740 }
|
rlm@1
|
741 debuggerDisableBreakpoints();
|
rlm@1
|
742 Function *f = NULL;
|
rlm@1
|
743 CompileUnit *u = NULL;
|
rlm@1
|
744 u32 a = armNextPC;
|
rlm@1
|
745 if(elfGetCurrentFunction(a, &f, &u)) {
|
rlm@1
|
746 char *file;
|
rlm@1
|
747 int line = elfFindLine(u, f, a, &file);
|
rlm@1
|
748
|
rlm@1
|
749 printf("File %s, function %s, line %d\n", file, f->name,
|
rlm@1
|
750 line);
|
rlm@1
|
751 }
|
rlm@1
|
752 debuggerRegisters(0, NULL);
|
rlm@1
|
753 }
|
rlm@1
|
754
|
rlm@1
|
755 void debuggerContinue(int n, char **args)
|
rlm@1
|
756 {
|
rlm@1
|
757 if(debuggerAtBreakpoint)
|
rlm@1
|
758 debuggerContinueAfterBreakpoint();
|
rlm@1
|
759 debuggerEnableBreakpoints(false);
|
rlm@1
|
760 debugger = false;
|
rlm@1
|
761 }
|
rlm@1
|
762
|
rlm@1
|
763 void debuggerSignal(int sig,int number)
|
rlm@1
|
764 {
|
rlm@1
|
765 switch(sig) {
|
rlm@1
|
766 case 4:
|
rlm@1
|
767 {
|
rlm@1
|
768 printf("Illegal instruction at %08x\n", armNextPC);
|
rlm@1
|
769 debugger = true;
|
rlm@1
|
770 }
|
rlm@1
|
771 break;
|
rlm@1
|
772 case 5:
|
rlm@1
|
773 {
|
rlm@1
|
774 printf("Breakpoint %d reached\n", number);
|
rlm@1
|
775 debugger = true;
|
rlm@1
|
776 debuggerAtBreakpoint = true;
|
rlm@1
|
777 debuggerBreakpointNumber = number;
|
rlm@1
|
778 debuggerDisableBreakpoints();
|
rlm@1
|
779
|
rlm@1
|
780 Function *f = NULL;
|
rlm@1
|
781 CompileUnit *u = NULL;
|
rlm@1
|
782
|
rlm@1
|
783 if(elfGetCurrentFunction(armNextPC, &f, &u)) {
|
rlm@1
|
784 char *file;
|
rlm@1
|
785 int line = elfFindLine(u,f,armNextPC,&file);
|
rlm@1
|
786 printf("File %s, function %s, line %d\n", file, f->name,
|
rlm@1
|
787 line);
|
rlm@1
|
788 }
|
rlm@1
|
789 }
|
rlm@1
|
790 break;
|
rlm@1
|
791 default:
|
rlm@1
|
792 printf("Unknown signal %d\n", sig);
|
rlm@1
|
793 break;
|
rlm@1
|
794 }
|
rlm@1
|
795 }
|
rlm@1
|
796
|
rlm@1
|
797 void debuggerBreakList(int, char **)
|
rlm@1
|
798 {
|
rlm@1
|
799 printf("Num Address Type Symbol\n");
|
rlm@1
|
800 printf("--- -------- ----- ------\n");
|
rlm@1
|
801 for(int i = 0; i < debuggerNumOfBreakpoints; i++) {
|
rlm@1
|
802 printf("%3d %08x %s %s\n",i, debuggerBreakpointList[i].address,
|
rlm@1
|
803 debuggerBreakpointList[i].size ? "ARM" : "THUMB",
|
rlm@1
|
804 elfGetAddressSymbol(debuggerBreakpointList[i].address));
|
rlm@1
|
805 }
|
rlm@1
|
806 }
|
rlm@1
|
807
|
rlm@1
|
808 void debuggerBreakDelete(int n, char **args)
|
rlm@1
|
809 {
|
rlm@1
|
810 if(n == 2) {
|
rlm@1
|
811 int n = 0;
|
rlm@1
|
812 sscanf(args[1], "%d", &n);
|
rlm@1
|
813 printf("Deleting breakpoint %d (%d)\n", n, debuggerNumOfBreakpoints);
|
rlm@1
|
814 if(n >= 0 && n < debuggerNumOfBreakpoints) {
|
rlm@1
|
815 n++;
|
rlm@1
|
816 if(n < debuggerNumOfBreakpoints) {
|
rlm@1
|
817 for(int i = n; i < debuggerNumOfBreakpoints; i++) {
|
rlm@1
|
818 debuggerBreakpointList[i-1].address =
|
rlm@1
|
819 debuggerBreakpointList[i].address;
|
rlm@1
|
820 debuggerBreakpointList[i-1].value =
|
rlm@1
|
821 debuggerBreakpointList[i].value;
|
rlm@1
|
822 debuggerBreakpointList[i-1].size =
|
rlm@1
|
823 debuggerBreakpointList[i].size;
|
rlm@1
|
824 }
|
rlm@1
|
825 }
|
rlm@1
|
826 debuggerNumOfBreakpoints--;
|
rlm@1
|
827 }
|
rlm@1
|
828 } else
|
rlm@1
|
829 debuggerUsage("bd");
|
rlm@1
|
830 }
|
rlm@1
|
831
|
rlm@1
|
832 void debuggerBreak(int n, char **args)
|
rlm@1
|
833 {
|
rlm@1
|
834 if(n == 2) {
|
rlm@1
|
835 u32 address = 0;
|
rlm@1
|
836 u32 value = 0;
|
rlm@1
|
837 int type = 0;
|
rlm@1
|
838 char *s = args[1];
|
rlm@1
|
839 char c = *s;
|
rlm@1
|
840 if(strchr(s, ':')) {
|
rlm@1
|
841 char *name = s;
|
rlm@1
|
842 char *l = strchr(s, ':');
|
rlm@1
|
843 *l++ = 0;
|
rlm@1
|
844 int line = atoi(l);
|
rlm@1
|
845
|
rlm@1
|
846 u32 addr;
|
rlm@1
|
847 Function *f;
|
rlm@1
|
848 CompileUnit *u;
|
rlm@1
|
849
|
rlm@1
|
850 if(elfFindLineInModule(&addr, name, line)) {
|
rlm@1
|
851 if(elfGetCurrentFunction(addr, &f, &u)) {
|
rlm@1
|
852 u32 addr2;
|
rlm@1
|
853 if(elfGetSymbolAddress(f->name, &addr2, &value, &type)) {
|
rlm@1
|
854 address = addr;
|
rlm@1
|
855 } else {
|
rlm@1
|
856 printf("Unable to get function symbol data\n");
|
rlm@1
|
857 return;
|
rlm@1
|
858 }
|
rlm@1
|
859 } else {
|
rlm@1
|
860 printf("Unable to find function for address\n");
|
rlm@1
|
861 return;
|
rlm@1
|
862 }
|
rlm@1
|
863 } else {
|
rlm@1
|
864 printf("Unable to find module or line\n");
|
rlm@1
|
865 return;
|
rlm@1
|
866 }
|
rlm@1
|
867 } else if(c >= '0' && c <= '9') {
|
rlm@1
|
868 int line = atoi(s);
|
rlm@1
|
869 Function *f;
|
rlm@1
|
870 CompileUnit *u;
|
rlm@1
|
871 u32 addr;
|
rlm@1
|
872
|
rlm@1
|
873 if(elfGetCurrentFunction(armNextPC, &f, &u)) {
|
rlm@1
|
874 if(elfFindLineInUnit(&addr, u, line)) {
|
rlm@1
|
875 if(elfGetCurrentFunction(addr, &f, &u)) {
|
rlm@1
|
876 u32 addr2;
|
rlm@1
|
877 if(elfGetSymbolAddress(f->name, &addr2, &value, &type)) {
|
rlm@1
|
878 address = addr;
|
rlm@1
|
879 } else {
|
rlm@1
|
880 printf("Unable to get function symbol data\n");
|
rlm@1
|
881 return;
|
rlm@1
|
882 }
|
rlm@1
|
883 } else {
|
rlm@1
|
884 printf("Unable to find function for address\n");
|
rlm@1
|
885 return;
|
rlm@1
|
886 }
|
rlm@1
|
887 } else {
|
rlm@1
|
888 printf("Unable to find line\n");
|
rlm@1
|
889 return;
|
rlm@1
|
890 }
|
rlm@1
|
891 } else {
|
rlm@1
|
892 printf("Cannot find current function\n");
|
rlm@1
|
893 return;
|
rlm@1
|
894 }
|
rlm@1
|
895 } else {
|
rlm@1
|
896 if(!elfGetSymbolAddress(s, &address, &value, &type)) {
|
rlm@1
|
897 printf("Function %s not found\n", args[1]);
|
rlm@1
|
898 return;
|
rlm@1
|
899 }
|
rlm@1
|
900 }
|
rlm@1
|
901 if(type == 0x02 || type == 0x0d) {
|
rlm@1
|
902 int i = debuggerNumOfBreakpoints;
|
rlm@1
|
903 int size = 0;
|
rlm@1
|
904 if(type == 2)
|
rlm@1
|
905 size = 1;
|
rlm@1
|
906 debuggerBreakpointList[i].address = address;
|
rlm@1
|
907 debuggerBreakpointList[i].value = type == 0x02 ?
|
rlm@1
|
908 debuggerReadMemory(address) : debuggerReadHalfWord(address);
|
rlm@1
|
909 debuggerBreakpointList[i].size = size;
|
rlm@1
|
910 // debuggerApplyBreakpoint(address, i, size);
|
rlm@1
|
911 debuggerNumOfBreakpoints++;
|
rlm@1
|
912 if(size)
|
rlm@1
|
913 printf("Added ARM breakpoint at %08x\n", address);
|
rlm@1
|
914 else
|
rlm@1
|
915 printf("Added THUMB breakpoint at %08x\n", address);
|
rlm@1
|
916 } else {
|
rlm@1
|
917 printf("%s is not a function symbol\n", args[1]);
|
rlm@1
|
918 }
|
rlm@1
|
919 } else
|
rlm@1
|
920 debuggerUsage("break");
|
rlm@1
|
921 }
|
rlm@1
|
922
|
rlm@1
|
923 void debuggerBreakThumb(int n, char **args)
|
rlm@1
|
924 {
|
rlm@1
|
925 if(n == 2) {
|
rlm@1
|
926 u32 address = 0;
|
rlm@1
|
927 sscanf(args[1],"%x", &address);
|
rlm@1
|
928 int i = debuggerNumOfBreakpoints;
|
rlm@1
|
929 debuggerBreakpointList[i].address = address;
|
rlm@1
|
930 debuggerBreakpointList[i].value = debuggerReadHalfWord(address);
|
rlm@1
|
931 debuggerBreakpointList[i].size = 0;
|
rlm@1
|
932 // debuggerApplyBreakpoint(address, i, 0);
|
rlm@1
|
933 debuggerNumOfBreakpoints++;
|
rlm@1
|
934 printf("Added THUMB breakpoint at %08x\n", address);
|
rlm@1
|
935 } else
|
rlm@1
|
936 debuggerUsage("bt");
|
rlm@1
|
937 }
|
rlm@1
|
938
|
rlm@1
|
939 void debuggerBreakArm(int n, char **args)
|
rlm@1
|
940 {
|
rlm@1
|
941 if(n == 2) {
|
rlm@1
|
942 u32 address = 0;
|
rlm@1
|
943 sscanf(args[1],"%x", &address);
|
rlm@1
|
944 int i = debuggerNumOfBreakpoints;
|
rlm@1
|
945 debuggerBreakpointList[i].address = address;
|
rlm@1
|
946 debuggerBreakpointList[i].value = debuggerReadMemory(address);
|
rlm@1
|
947 debuggerBreakpointList[i].size = 1;
|
rlm@1
|
948 // debuggerApplyBreakpoint(address, i, 1);
|
rlm@1
|
949 debuggerNumOfBreakpoints++;
|
rlm@1
|
950 printf("Added ARM breakpoint at %08x\n", address);
|
rlm@1
|
951 } else
|
rlm@1
|
952 debuggerUsage("ba");
|
rlm@1
|
953 }
|
rlm@1
|
954
|
rlm@1
|
955 void debuggerBreakOnWrite(u32 *mem, u32 oldvalue, u32 value, int size)
|
rlm@1
|
956 {
|
rlm@1
|
957 u32 address = 0;
|
rlm@1
|
958 if(mem >= (u32*)&workRAM[0] && mem <= (u32*)&workRAM[0x3ffff])
|
rlm@1
|
959 address = 0x2000000 + ((u64)mem - (u64)&workRAM[0]);
|
rlm@1
|
960 else
|
rlm@1
|
961 address = 0x3000000 + ((u64)mem - (u64)&internalRAM[0]);
|
rlm@1
|
962
|
rlm@1
|
963 if(size == 2)
|
rlm@1
|
964 printf("Breakpoint (on write) address %08x old:%08x new:%08x\n",
|
rlm@1
|
965 address, oldvalue, value);
|
rlm@1
|
966 else if(size == 1)
|
rlm@1
|
967 printf("Breakpoint (on write) address %08x old:%04x new:%04x\n",
|
rlm@1
|
968 address, (u16)oldvalue,(u16)value);
|
rlm@1
|
969 else
|
rlm@1
|
970 printf("Breakpoint (on write) address %08x old:%02x new:%02x\n",
|
rlm@1
|
971 address, (u8)oldvalue, (u8)value);
|
rlm@1
|
972 debugger = true;
|
rlm@1
|
973 }
|
rlm@1
|
974
|
rlm@1
|
975 void debuggerBreakWriteClear(int n, char **args)
|
rlm@1
|
976 {
|
rlm@1
|
977 memset(freezeWorkRAM, false, 0x40000);
|
rlm@1
|
978 memset(freezeInternalRAM, false, 0x8000);
|
rlm@1
|
979 printf("Cleared all break on write\n");
|
rlm@1
|
980 }
|
rlm@1
|
981
|
rlm@1
|
982 void debuggerBreakWrite(int n, char **args)
|
rlm@1
|
983 {
|
rlm@1
|
984 if(n == 3) {
|
rlm@1
|
985 if(cheatsNumber != 0) {
|
rlm@1
|
986 printf("Cheats are enabled. Cannot continue.\n");
|
rlm@1
|
987 return;
|
rlm@1
|
988 }
|
rlm@1
|
989 u32 address = 0;
|
rlm@1
|
990 sscanf(args[1], "%x", &address);
|
rlm@1
|
991 int n = 0;
|
rlm@1
|
992 sscanf(args[2], "%d", &n);
|
rlm@1
|
993
|
rlm@1
|
994 if(address < 0x2000000 || address > 0x3007fff) {
|
rlm@1
|
995 printf("Invalid address: %08x\n", address);
|
rlm@1
|
996 return;
|
rlm@1
|
997 }
|
rlm@1
|
998
|
rlm@1
|
999 if(address > 0x203ffff && address < 0x3000000) {
|
rlm@1
|
1000 printf("Invalid address: %08x\n", address);
|
rlm@1
|
1001 return;
|
rlm@1
|
1002 }
|
rlm@1
|
1003
|
rlm@1
|
1004 u32 final = address + n;
|
rlm@1
|
1005
|
rlm@1
|
1006 if(address < 0x2040000 && final > 0x2040000) {
|
rlm@1
|
1007 printf("Invalid byte count: %d\n", n);
|
rlm@1
|
1008 return;
|
rlm@1
|
1009 } else if(address < 0x3008000 && final > 0x3008000) {
|
rlm@1
|
1010 printf("Invalid byte count: %d\n", n);
|
rlm@1
|
1011 return;
|
rlm@1
|
1012 }
|
rlm@1
|
1013 printf("Added break on write at %08x for %d bytes\n", address, n);
|
rlm@1
|
1014 for(int i = 0; i < n; i++) {
|
rlm@1
|
1015 if((address >> 24) == 2)
|
rlm@1
|
1016 freezeWorkRAM[address & 0x3ffff] = true;
|
rlm@1
|
1017 else
|
rlm@1
|
1018 freezeInternalRAM[address & 0x7fff] = true;
|
rlm@1
|
1019 address++;
|
rlm@1
|
1020 }
|
rlm@1
|
1021 } else
|
rlm@1
|
1022 debuggerUsage("bpw");
|
rlm@1
|
1023 }
|
rlm@1
|
1024
|
rlm@1
|
1025 void debuggerDisassembleArm(int n, char **args)
|
rlm@1
|
1026 {
|
rlm@1
|
1027 char buffer[80];
|
rlm@1
|
1028 u32 pc = reg[15].I;
|
rlm@1
|
1029 pc -= 4;
|
rlm@1
|
1030 int count = 20;
|
rlm@1
|
1031 if(n >= 2) {
|
rlm@1
|
1032 sscanf(args[1], "%x", &pc);
|
rlm@1
|
1033 }
|
rlm@1
|
1034 if(pc & 3) {
|
rlm@1
|
1035 printf("Misaligned address %08x\n", pc);
|
rlm@1
|
1036 pc &= 0xfffffffc;
|
rlm@1
|
1037 }
|
rlm@1
|
1038 if(n >= 3) {
|
rlm@1
|
1039 sscanf(args[2], "%d", &count);
|
rlm@1
|
1040 }
|
rlm@1
|
1041 int i = 0;
|
rlm@1
|
1042 int len = 0;
|
rlm@1
|
1043 char format[30];
|
rlm@1
|
1044 for(i = 0; i < count; i++) {
|
rlm@1
|
1045 int l = strlen(elfGetAddressSymbol(pc+4*i));
|
rlm@1
|
1046 if(l > len)
|
rlm@1
|
1047 len = l;
|
rlm@1
|
1048 }
|
rlm@1
|
1049 sprintf(format, "%%08x %%-%ds %%s\n", len);
|
rlm@1
|
1050 for(i = 0; i < count; i++) {
|
rlm@1
|
1051 u32 addr = pc;
|
rlm@1
|
1052 pc += disArm(pc, buffer, 2);
|
rlm@1
|
1053 printf(format, addr, elfGetAddressSymbol(addr), buffer);
|
rlm@1
|
1054 }
|
rlm@1
|
1055 }
|
rlm@1
|
1056
|
rlm@1
|
1057 void debuggerDisassembleThumb(int n, char **args)
|
rlm@1
|
1058 {
|
rlm@1
|
1059 char buffer[80];
|
rlm@1
|
1060 u32 pc = reg[15].I;
|
rlm@1
|
1061 pc -= 2;
|
rlm@1
|
1062 int count = 20;
|
rlm@1
|
1063 if(n >= 2) {
|
rlm@1
|
1064 sscanf(args[1], "%x", &pc);
|
rlm@1
|
1065 }
|
rlm@1
|
1066 if(pc & 1) {
|
rlm@1
|
1067 printf("Misaligned address %08x\n", pc);
|
rlm@1
|
1068 pc &= 0xfffffffe;
|
rlm@1
|
1069 }
|
rlm@1
|
1070 if(n >= 3) {
|
rlm@1
|
1071 sscanf(args[2], "%d", &count);
|
rlm@1
|
1072 }
|
rlm@1
|
1073
|
rlm@1
|
1074 int i = 0;
|
rlm@1
|
1075 int len = 0;
|
rlm@1
|
1076 char format[30];
|
rlm@1
|
1077 for(i = 0; i < count; i++) {
|
rlm@1
|
1078 int l = strlen(elfGetAddressSymbol(pc+2*i));
|
rlm@1
|
1079 if(l > len)
|
rlm@1
|
1080 len = l;
|
rlm@1
|
1081 }
|
rlm@1
|
1082 sprintf(format, "%%08x %%-%ds %%s\n", len);
|
rlm@1
|
1083
|
rlm@1
|
1084 for(i = 0; i < count; i++) {
|
rlm@1
|
1085 u32 addr = pc;
|
rlm@1
|
1086 pc += disThumb(pc, buffer, 2);
|
rlm@1
|
1087 printf(format, addr, elfGetAddressSymbol(addr), buffer);
|
rlm@1
|
1088 }
|
rlm@1
|
1089 }
|
rlm@1
|
1090
|
rlm@1
|
1091 void debuggerDisassemble(int n, char **args)
|
rlm@1
|
1092 {
|
rlm@1
|
1093 if(armState)
|
rlm@1
|
1094 debuggerDisassembleArm(n, args);
|
rlm@1
|
1095 else
|
rlm@1
|
1096 debuggerDisassembleThumb(n, args);
|
rlm@1
|
1097 }
|
rlm@1
|
1098
|
rlm@1
|
1099 void debuggerContinueAfterBreakpoint()
|
rlm@1
|
1100 {
|
rlm@1
|
1101 printf("Continuing after breakpoint\n");
|
rlm@1
|
1102 debuggerEnableBreakpoints(true);
|
rlm@1
|
1103 theEmulator.emuMain(1);
|
rlm@1
|
1104 debuggerAtBreakpoint = false;
|
rlm@1
|
1105 }
|
rlm@1
|
1106
|
rlm@1
|
1107 void debuggerRegisters(int, char **)
|
rlm@1
|
1108 {
|
rlm@1
|
1109 char *command[3];
|
rlm@1
|
1110 char buffer[10];
|
rlm@1
|
1111
|
rlm@1
|
1112 printf("R00=%08x R04=%08x R08=%08x R12=%08x\n",
|
rlm@1
|
1113 reg[0].I, reg[4].I, reg[8].I, reg[12].I);
|
rlm@1
|
1114 printf("R01=%08x R05=%08x R09=%08x R13=%08x\n",
|
rlm@1
|
1115 reg[1].I, reg[5].I, reg[9].I, reg[13].I);
|
rlm@1
|
1116 printf("R02=%08x R06=%08x R10=%08x R14=%08x\n",
|
rlm@1
|
1117 reg[2].I, reg[6].I, reg[10].I, reg[14].I);
|
rlm@1
|
1118 printf("R03=%08x R07=%08x R11=%08x R15=%08x\n",
|
rlm@1
|
1119 reg[3].I, reg[7].I, reg[11].I, reg[15].I);
|
rlm@1
|
1120 printf("CPSR=%08x (%c%c%c%c%c%c%c Mode: %02x)\n",
|
rlm@1
|
1121 reg[16].I,
|
rlm@1
|
1122 (N_FLAG ? 'N' : '.'),
|
rlm@1
|
1123 (Z_FLAG ? 'Z' : '.'),
|
rlm@1
|
1124 (C_FLAG ? 'C' : '.'),
|
rlm@1
|
1125 (V_FLAG ? 'V' : '.'),
|
rlm@1
|
1126 (armIrqEnable ? '.' : 'I'),
|
rlm@1
|
1127 ((!(reg[16].I & 0x40)) ? '.' : 'F'),
|
rlm@1
|
1128 (armState ? '.' : 'T'),
|
rlm@1
|
1129 armMode);
|
rlm@1
|
1130 sprintf(buffer,"%08x", armState ? reg[15].I - 4 : reg[15].I - 2);
|
rlm@1
|
1131 command[0]=const_cast<char *>("m");
|
rlm@1
|
1132 command[1]=buffer;
|
rlm@1
|
1133 command[2]=const_cast<char *>("1");
|
rlm@1
|
1134 debuggerDisassemble(3, command);
|
rlm@1
|
1135 }
|
rlm@1
|
1136
|
rlm@1
|
1137 void debuggerIoVideo()
|
rlm@1
|
1138 {
|
rlm@1
|
1139 printf("DISPCNT = %04x\n", DISPCNT);
|
rlm@1
|
1140 printf("DISPSTAT = %04x\n", DISPSTAT);
|
rlm@1
|
1141 printf("VCOUNT = %04x\n", VCOUNT);
|
rlm@1
|
1142 printf("BG0CNT = %04x\n", BG0CNT);
|
rlm@1
|
1143 printf("BG1CNT = %04x\n", BG1CNT);
|
rlm@1
|
1144 printf("BG2CNT = %04x\n", BG2CNT);
|
rlm@1
|
1145 printf("BG3CNT = %04x\n", BG3CNT);
|
rlm@1
|
1146 printf("WIN0H = %04x\n", WIN0H);
|
rlm@1
|
1147 printf("WIN0V = %04x\n", WIN0V);
|
rlm@1
|
1148 printf("WIN1H = %04x\n", WIN1H);
|
rlm@1
|
1149 printf("WIN1V = %04x\n", WIN1V);
|
rlm@1
|
1150 printf("WININ = %04x\n", WININ);
|
rlm@1
|
1151 printf("WINOUT = %04x\n", WINOUT);
|
rlm@1
|
1152 printf("MOSAIC = %04x\n", MOSAIC);
|
rlm@1
|
1153 printf("BLDMOD = %04x\n", BLDMOD);
|
rlm@1
|
1154 printf("COLEV = %04x\n", COLEV);
|
rlm@1
|
1155 printf("COLY = %04x\n", COLY);
|
rlm@1
|
1156 }
|
rlm@1
|
1157
|
rlm@1
|
1158 void debuggerIoVideo2()
|
rlm@1
|
1159 {
|
rlm@1
|
1160 printf("BG0HOFS = %04x\n", BG0HOFS);
|
rlm@1
|
1161 printf("BG0VOFS = %04x\n", BG0VOFS);
|
rlm@1
|
1162 printf("BG1HOFS = %04x\n", BG1HOFS);
|
rlm@1
|
1163 printf("BG1VOFS = %04x\n", BG1VOFS);
|
rlm@1
|
1164 printf("BG2HOFS = %04x\n", BG2HOFS);
|
rlm@1
|
1165 printf("BG2VOFS = %04x\n", BG2VOFS);
|
rlm@1
|
1166 printf("BG3HOFS = %04x\n", BG3HOFS);
|
rlm@1
|
1167 printf("BG3VOFS = %04x\n", BG3VOFS);
|
rlm@1
|
1168 printf("BG2PA = %04x\n", BG2PA);
|
rlm@1
|
1169 printf("BG2PB = %04x\n", BG2PB);
|
rlm@1
|
1170 printf("BG2PC = %04x\n", BG2PC);
|
rlm@1
|
1171 printf("BG2PD = %04x\n", BG2PD);
|
rlm@1
|
1172 printf("BG2X = %08x\n", (BG2X_H<<16)|BG2X_L);
|
rlm@1
|
1173 printf("BG2Y = %08x\n", (BG2Y_H<<16)|BG2Y_L);
|
rlm@1
|
1174 printf("BG3PA = %04x\n", BG3PA);
|
rlm@1
|
1175 printf("BG3PB = %04x\n", BG3PB);
|
rlm@1
|
1176 printf("BG3PC = %04x\n", BG3PC);
|
rlm@1
|
1177 printf("BG3PD = %04x\n", BG3PD);
|
rlm@1
|
1178 printf("BG3X = %08x\n", (BG3X_H<<16)|BG3X_L);
|
rlm@1
|
1179 printf("BG3Y = %08x\n", (BG3Y_H<<16)|BG3Y_L);
|
rlm@1
|
1180 }
|
rlm@1
|
1181
|
rlm@1
|
1182 void debuggerIoDMA()
|
rlm@1
|
1183 {
|
rlm@1
|
1184 printf("DM0SAD = %08x\n", (DM0SAD_H<<16)|DM0SAD_L);
|
rlm@1
|
1185 printf("DM0DAD = %08x\n", (DM0DAD_H<<16)|DM0DAD_L);
|
rlm@1
|
1186 printf("DM0CNT = %08x\n", (DM0CNT_H<<16)|DM0CNT_L);
|
rlm@1
|
1187 printf("DM1SAD = %08x\n", (DM1SAD_H<<16)|DM1SAD_L);
|
rlm@1
|
1188 printf("DM1DAD = %08x\n", (DM1DAD_H<<16)|DM1DAD_L);
|
rlm@1
|
1189 printf("DM1CNT = %08x\n", (DM1CNT_H<<16)|DM1CNT_L);
|
rlm@1
|
1190 printf("DM2SAD = %08x\n", (DM2SAD_H<<16)|DM2SAD_L);
|
rlm@1
|
1191 printf("DM2DAD = %08x\n", (DM2DAD_H<<16)|DM2DAD_L);
|
rlm@1
|
1192 printf("DM2CNT = %08x\n", (DM2CNT_H<<16)|DM2CNT_L);
|
rlm@1
|
1193 printf("DM3SAD = %08x\n", (DM3SAD_H<<16)|DM3SAD_L);
|
rlm@1
|
1194 printf("DM3DAD = %08x\n", (DM3DAD_H<<16)|DM3DAD_L);
|
rlm@1
|
1195 printf("DM3CNT = %08x\n", (DM3CNT_H<<16)|DM3CNT_L);
|
rlm@1
|
1196 }
|
rlm@1
|
1197
|
rlm@1
|
1198 void debuggerIoTimer()
|
rlm@1
|
1199 {
|
rlm@1
|
1200 printf("TM0D = %04x\n", TM0D);
|
rlm@1
|
1201 printf("TM0CNT = %04x\n", TM0CNT);
|
rlm@1
|
1202 printf("TM1D = %04x\n", TM1D);
|
rlm@1
|
1203 printf("TM1CNT = %04x\n", TM1CNT);
|
rlm@1
|
1204 printf("TM2D = %04x\n", TM2D);
|
rlm@1
|
1205 printf("TM2CNT = %04x\n", TM2CNT);
|
rlm@1
|
1206 printf("TM3D = %04x\n", TM3D);
|
rlm@1
|
1207 printf("TM3CNT = %04x\n", TM3CNT);
|
rlm@1
|
1208 }
|
rlm@1
|
1209
|
rlm@1
|
1210 void debuggerIoMisc()
|
rlm@1
|
1211 {
|
rlm@1
|
1212 printf("P1 = %04x\n", P1);
|
rlm@1
|
1213 printf("IE = %04x\n", IE);
|
rlm@1
|
1214 printf("IF = %04x\n", IF);
|
rlm@1
|
1215 printf("IME = %04x\n", IME);
|
rlm@1
|
1216 }
|
rlm@1
|
1217
|
rlm@1
|
1218 void debuggerIo(int n, char **args)
|
rlm@1
|
1219 {
|
rlm@1
|
1220 if(n == 1) {
|
rlm@1
|
1221 debuggerIoVideo();
|
rlm@1
|
1222 return;
|
rlm@1
|
1223 }
|
rlm@1
|
1224 if(!strcmp(args[1], "video"))
|
rlm@1
|
1225 debuggerIoVideo();
|
rlm@1
|
1226 else if(!strcmp(args[1], "video2"))
|
rlm@1
|
1227 debuggerIoVideo2();
|
rlm@1
|
1228 else if(!strcmp(args[1], "dma"))
|
rlm@1
|
1229 debuggerIoDMA();
|
rlm@1
|
1230 else if(!strcmp(args[1], "timer"))
|
rlm@1
|
1231 debuggerIoTimer();
|
rlm@1
|
1232 else if(!strcmp(args[1], "misc"))
|
rlm@1
|
1233 debuggerIoMisc();
|
rlm@1
|
1234 else printf("Unrecognized option %s\n", args[1]);
|
rlm@1
|
1235 }
|
rlm@1
|
1236
|
rlm@1
|
1237 void debuggerEditByte(int n, char **args)
|
rlm@1
|
1238 {
|
rlm@1
|
1239 if(n == 3) {
|
rlm@1
|
1240 u32 address;
|
rlm@1
|
1241 u32 byte;
|
rlm@1
|
1242 sscanf(args[1], "%x", &address);
|
rlm@1
|
1243 sscanf(args[2], "%x", &byte);
|
rlm@1
|
1244 debuggerWriteByte(address, (u8)byte);
|
rlm@1
|
1245 } else
|
rlm@1
|
1246 debuggerUsage("eb");
|
rlm@1
|
1247 }
|
rlm@1
|
1248
|
rlm@1
|
1249 void debuggerEditHalfWord(int n, char **args)
|
rlm@1
|
1250 {
|
rlm@1
|
1251 if(n == 3) {
|
rlm@1
|
1252 u32 address;
|
rlm@1
|
1253 u32 byte;
|
rlm@1
|
1254 sscanf(args[1], "%x", &address);
|
rlm@1
|
1255 if(address & 1) {
|
rlm@1
|
1256 printf("Error: address must be half-word aligned\n");
|
rlm@1
|
1257 return;
|
rlm@1
|
1258 }
|
rlm@1
|
1259 sscanf(args[2], "%x", &byte);
|
rlm@1
|
1260 debuggerWriteHalfWord(address, (u16)byte);
|
rlm@1
|
1261 } else
|
rlm@1
|
1262 debuggerUsage("eh");
|
rlm@1
|
1263 }
|
rlm@1
|
1264
|
rlm@1
|
1265 void debuggerEdit(int n, char **args)
|
rlm@1
|
1266 {
|
rlm@1
|
1267 if(n == 3) {
|
rlm@1
|
1268 u32 address;
|
rlm@1
|
1269 u32 byte;
|
rlm@1
|
1270 sscanf(args[1], "%x", &address);
|
rlm@1
|
1271 if(address & 3) {
|
rlm@1
|
1272 printf("Error: address must be word aligned\n");
|
rlm@1
|
1273 return;
|
rlm@1
|
1274 }
|
rlm@1
|
1275 sscanf(args[2], "%x", &byte);
|
rlm@1
|
1276 debuggerWriteMemory(address, (u32)byte);
|
rlm@1
|
1277 } else
|
rlm@1
|
1278 debuggerUsage("ew");
|
rlm@1
|
1279 }
|
rlm@1
|
1280
|
rlm@1
|
1281
|
rlm@1
|
1282 #define ASCII(c) (c) < 32 ? '.' : (c) > 127 ? '.' : (c)
|
rlm@1
|
1283
|
rlm@1
|
1284 void debuggerMemoryByte(int n, char **args)
|
rlm@1
|
1285 {
|
rlm@1
|
1286 if(n == 2) {
|
rlm@1
|
1287 u32 addr = 0;
|
rlm@1
|
1288 sscanf(args[1], "%x", &addr);
|
rlm@1
|
1289 for(int ii = 0; ii < 16; ii++) {
|
rlm@1
|
1290 int a = debuggerReadByte(addr);
|
rlm@1
|
1291 int b = debuggerReadByte(addr+1);
|
rlm@1
|
1292 int c = debuggerReadByte(addr+2);
|
rlm@1
|
1293 int d = debuggerReadByte(addr+3);
|
rlm@1
|
1294 int e = debuggerReadByte(addr+4);
|
rlm@1
|
1295 int f = debuggerReadByte(addr+5);
|
rlm@1
|
1296 int g = debuggerReadByte(addr+6);
|
rlm@1
|
1297 int h = debuggerReadByte(addr+7);
|
rlm@1
|
1298 int i = debuggerReadByte(addr+8);
|
rlm@1
|
1299 int j = debuggerReadByte(addr+9);
|
rlm@1
|
1300 int k = debuggerReadByte(addr+10);
|
rlm@1
|
1301 int l = debuggerReadByte(addr+11);
|
rlm@1
|
1302 int m = debuggerReadByte(addr+12);
|
rlm@1
|
1303 int n = debuggerReadByte(addr+13);
|
rlm@1
|
1304 int o = debuggerReadByte(addr+14);
|
rlm@1
|
1305 int p = debuggerReadByte(addr+15);
|
rlm@1
|
1306
|
rlm@1
|
1307 printf("%08x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
|
rlm@1
|
1308 addr,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,
|
rlm@1
|
1309 ASCII(a),ASCII(b),ASCII(c),ASCII(d),
|
rlm@1
|
1310 ASCII(e),ASCII(f),ASCII(g),ASCII(h),
|
rlm@1
|
1311 ASCII(i),ASCII(j),ASCII(k),ASCII(l),
|
rlm@1
|
1312 ASCII(m),ASCII(n),ASCII(o),ASCII(p));
|
rlm@1
|
1313 addr += 16;
|
rlm@1
|
1314 }
|
rlm@1
|
1315 } else
|
rlm@1
|
1316 debuggerUsage("mb");
|
rlm@1
|
1317 }
|
rlm@1
|
1318
|
rlm@1
|
1319 void debuggerMemoryHalfWord(int n, char **args)
|
rlm@1
|
1320 {
|
rlm@1
|
1321 if(n == 2) {
|
rlm@1
|
1322 u32 addr = 0;
|
rlm@1
|
1323 sscanf(args[1], "%x", &addr);
|
rlm@1
|
1324 addr = addr & 0xfffffffe;
|
rlm@1
|
1325 for(int ii = 0; ii < 16; ii++) {
|
rlm@1
|
1326 int a = debuggerReadByte(addr);
|
rlm@1
|
1327 int b = debuggerReadByte(addr+1);
|
rlm@1
|
1328 int c = debuggerReadByte(addr+2);
|
rlm@1
|
1329 int d = debuggerReadByte(addr+3);
|
rlm@1
|
1330 int e = debuggerReadByte(addr+4);
|
rlm@1
|
1331 int f = debuggerReadByte(addr+5);
|
rlm@1
|
1332 int g = debuggerReadByte(addr+6);
|
rlm@1
|
1333 int h = debuggerReadByte(addr+7);
|
rlm@1
|
1334 int i = debuggerReadByte(addr+8);
|
rlm@1
|
1335 int j = debuggerReadByte(addr+9);
|
rlm@1
|
1336 int k = debuggerReadByte(addr+10);
|
rlm@1
|
1337 int l = debuggerReadByte(addr+11);
|
rlm@1
|
1338 int m = debuggerReadByte(addr+12);
|
rlm@1
|
1339 int n = debuggerReadByte(addr+13);
|
rlm@1
|
1340 int o = debuggerReadByte(addr+14);
|
rlm@1
|
1341 int p = debuggerReadByte(addr+15);
|
rlm@1
|
1342
|
rlm@1
|
1343 printf("%08x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
|
rlm@1
|
1344 addr,b,a,d,c,f,e,h,g,j,i,l,k,n,m,p,o,
|
rlm@1
|
1345 ASCII(a),ASCII(b),ASCII(c),ASCII(d),
|
rlm@1
|
1346 ASCII(e),ASCII(f),ASCII(g),ASCII(h),
|
rlm@1
|
1347 ASCII(i),ASCII(j),ASCII(k),ASCII(l),
|
rlm@1
|
1348 ASCII(m),ASCII(n),ASCII(o),ASCII(p));
|
rlm@1
|
1349 addr += 16;
|
rlm@1
|
1350 }
|
rlm@1
|
1351 } else
|
rlm@1
|
1352 debuggerUsage("mh");
|
rlm@1
|
1353 }
|
rlm@1
|
1354
|
rlm@1
|
1355 void debuggerMemory(int n, char **args)
|
rlm@1
|
1356 {
|
rlm@1
|
1357 if(n == 2) {
|
rlm@1
|
1358 u32 addr = 0;
|
rlm@1
|
1359 sscanf(args[1], "%x", &addr);
|
rlm@1
|
1360 addr = addr & 0xfffffffc;
|
rlm@1
|
1361 for(int ii = 0; ii < 16; ii++) {
|
rlm@1
|
1362 int a = debuggerReadByte(addr);
|
rlm@1
|
1363 int b = debuggerReadByte(addr+1);
|
rlm@1
|
1364 int c = debuggerReadByte(addr+2);
|
rlm@1
|
1365 int d = debuggerReadByte(addr+3);
|
rlm@1
|
1366
|
rlm@1
|
1367 int e = debuggerReadByte(addr+4);
|
rlm@1
|
1368 int f = debuggerReadByte(addr+5);
|
rlm@1
|
1369 int g = debuggerReadByte(addr+6);
|
rlm@1
|
1370 int h = debuggerReadByte(addr+7);
|
rlm@1
|
1371
|
rlm@1
|
1372 int i = debuggerReadByte(addr+8);
|
rlm@1
|
1373 int j = debuggerReadByte(addr+9);
|
rlm@1
|
1374 int k = debuggerReadByte(addr+10);
|
rlm@1
|
1375 int l = debuggerReadByte(addr+11);
|
rlm@1
|
1376
|
rlm@1
|
1377 int m = debuggerReadByte(addr+12);
|
rlm@1
|
1378 int n = debuggerReadByte(addr+13);
|
rlm@1
|
1379 int o = debuggerReadByte(addr+14);
|
rlm@1
|
1380 int p = debuggerReadByte(addr+15);
|
rlm@1
|
1381
|
rlm@1
|
1382 printf("%08x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
|
rlm@1
|
1383 addr,d,c,b,a,h,g,f,e,l,k,j,i,p,o,n,m,
|
rlm@1
|
1384 ASCII(a),ASCII(b),ASCII(c),ASCII(d),
|
rlm@1
|
1385 ASCII(e),ASCII(f),ASCII(g),ASCII(h),
|
rlm@1
|
1386 ASCII(i),ASCII(j),ASCII(k),ASCII(l),
|
rlm@1
|
1387 ASCII(m),ASCII(n),ASCII(o),ASCII(p));
|
rlm@1
|
1388 addr += 16;
|
rlm@1
|
1389 }
|
rlm@1
|
1390 } else
|
rlm@1
|
1391 debuggerUsage("mw");
|
rlm@1
|
1392 }
|
rlm@1
|
1393
|
rlm@1
|
1394 void debuggerQuit(int, char **)
|
rlm@1
|
1395 {
|
rlm@1
|
1396 char buffer[10];
|
rlm@1
|
1397 printf("Are you sure you want to quit (y/n)? ");
|
rlm@1
|
1398 fgets(buffer, 1024, stdin);
|
rlm@1
|
1399
|
rlm@1
|
1400 if(buffer[0] == 'y' || buffer[0] == 'Y') {
|
rlm@1
|
1401 debugger = false;
|
rlm@1
|
1402 emulating = false;
|
rlm@1
|
1403 }
|
rlm@1
|
1404 }
|
rlm@1
|
1405
|
rlm@1
|
1406 void debuggerOutput(char *s, u32 addr)
|
rlm@1
|
1407 {
|
rlm@1
|
1408 if(s)
|
rlm@1
|
1409 puts(s);
|
rlm@1
|
1410 else {
|
rlm@1
|
1411 char c;
|
rlm@1
|
1412
|
rlm@1
|
1413 c = debuggerReadByte(addr);
|
rlm@1
|
1414 addr++;
|
rlm@1
|
1415 while(c) {
|
rlm@1
|
1416 putchar(c);
|
rlm@1
|
1417 c = debuggerReadByte(addr);
|
rlm@1
|
1418 addr++;
|
rlm@1
|
1419 }
|
rlm@1
|
1420 }
|
rlm@1
|
1421 }
|
rlm@1
|
1422
|
rlm@1
|
1423 void debuggerMain()
|
rlm@1
|
1424 {
|
rlm@1
|
1425 char buffer[1024];
|
rlm@1
|
1426 char *commands[10];
|
rlm@1
|
1427 int commandCount = 0;
|
rlm@1
|
1428
|
rlm@1
|
1429 if(theEmulator.emuUpdateCPSR)
|
rlm@1
|
1430 theEmulator.emuUpdateCPSR();
|
rlm@1
|
1431 debuggerRegisters(0, NULL);
|
rlm@1
|
1432
|
rlm@1
|
1433 while(debugger) {
|
rlm@1
|
1434 systemSoundPause();
|
rlm@1
|
1435 printf("debugger> ");
|
rlm@1
|
1436 commandCount = 0;
|
rlm@1
|
1437 char *s = fgets(buffer, 1024, stdin);
|
rlm@1
|
1438
|
rlm@1
|
1439 commands[0] = strtok(s, " \t\n");
|
rlm@1
|
1440 if(commands[0] == NULL)
|
rlm@1
|
1441 continue;
|
rlm@1
|
1442 commandCount++;
|
rlm@1
|
1443 while((s = strtok(NULL, " \t\n"))) {
|
rlm@1
|
1444 commands[commandCount++] = s;
|
rlm@1
|
1445 if(commandCount == 10)
|
rlm@1
|
1446 break;
|
rlm@1
|
1447 }
|
rlm@1
|
1448
|
rlm@1
|
1449 for(int j = 0; ; j++) {
|
rlm@1
|
1450 if(debuggerCommands[j].name == NULL) {
|
rlm@1
|
1451 printf("Unrecognized command %s. Type h for help.\n", commands[0]);
|
rlm@1
|
1452 break;
|
rlm@1
|
1453 }
|
rlm@1
|
1454 if(!strcmp(commands[0], debuggerCommands[j].name)) {
|
rlm@1
|
1455 debuggerCommands[j].function(commandCount, commands);
|
rlm@1
|
1456 break;
|
rlm@1
|
1457 }
|
rlm@1
|
1458 }
|
rlm@1
|
1459 }
|
rlm@1
|
1460 }
|