annotate src/sdl/debugger.cpp @ 580:46bbeac1b329

saving progress.
author Robert McIntyre <rlm@mit.edu>
date Sat, 01 Sep 2012 06:15:23 -0500
parents f9f4f1b99eed
children
rev   line source
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 }