xdebug

next generation of mdebug (work in progress)
git clone http://frotz.net/git/xdebug.git
Log | Files | Refs | README

commands.c (9291B)


      1 // Copyright 2023, Brian Swetland <swetland@frotz.net>
      2 // Licensed under the Apache License, Version 2.0.
      3 
      4 #include <string.h>
      5 
      6 #include "xdebug.h"
      7 #include "transport.h"
      8 #include "arm-v7-debug.h"
      9 #include "arm-v7-system-control.h"
     10 
     11 
     12 static uint32_t swd_clock_freq = 1000000;
     13 
     14 int do_attach(DC* dc, CC* cc) {
     15 	uint32_t n;
     16 	dc_set_clock(dc, swd_clock_freq);
     17 	return dc_attach(dc, 0, 0, &n);
     18 }
     19 
     20 int do_setclock(DC* dc, CC* cc) {
     21 	uint32_t mhz;
     22 	if ((cmd_arg_u32(cc, 1, &mhz) < 0) || (mhz < 1) || (mhz > 20)) {
     23 		ERROR("setclock <mhz> -- between 1 and 20\n");
     24 		return DBG_ERR;
     25 	}
     26 	swd_clock_freq = mhz * 1000000;
     27 	dc_set_clock(dc, swd_clock_freq);
     28 	return 0;
     29 }
     30 
     31 static uint32_t reglist[20] = {
     32 	0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
     33 	10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
     34 };
     35 static uint32_t lastregs[20];
     36 
     37 static int read_show_regs(DC* dc) {
     38 	if (dc_core_reg_rd_list(dc, reglist, lastregs, 20)) {
     39 		return DBG_ERR;
     40 	}
     41 	INFO("r0 %08x r4 %08x r8 %08x ip %08x psr %08x\n",
     42 		lastregs[0], lastregs[4], lastregs[8],
     43 		lastregs[12], lastregs[16]);
     44 	INFO("r1 %08x r5 %08x r9 %08x sp %08x msp %08x\n",
     45 		lastregs[1], lastregs[5], lastregs[9],
     46 		lastregs[13], lastregs[17]);
     47 	INFO("r2 %08x r6 %08x 10 %08x lr %08x psp %08x\n",
     48 		lastregs[2], lastregs[6], lastregs[10],
     49 		lastregs[14], lastregs[18]);
     50 	INFO("r3 %08x r7 %08x 11 %08x pc %08x\n",
     51 		lastregs[3], lastregs[7], lastregs[11],
     52 		lastregs[15]);
     53 	INFO("control  %02x faultmsk %02x basepri  %02x primask  %02x\n",
     54 		lastregs[20] >> 24, (lastregs[20] >> 16) & 0xFF,
     55 		(lastregs[20] >> 8) & 0xFF, lastregs[20] & 0xFF);
     56 	return 0;
     57 }
     58 
     59 int do_regs(DC* dc, CC* cc) {
     60 	return read_show_regs(dc);
     61 }
     62 
     63 static uint32_t lastaddr = 0x20000000;
     64 static uint32_t lastcount = 0x40;
     65 
     66 int do_dw(DC* dc, CC* cc) {
     67 	uint32_t data[1024];
     68 	uint32_t addr;
     69 	uint32_t count;
     70 	unsigned n;
     71 
     72 	if (cmd_arg_u32_opt(cc, 1, &addr, lastaddr)) return DBG_ERR;
     73 	if (cmd_arg_u32_opt(cc, 2, &count, lastcount)) return DBG_ERR;
     74 	if (count > 1024) count = 1024;
     75 	lastaddr = addr;
     76 	lastcount = count;
     77 
     78 	if (addr & 3) {
     79 		ERROR("address is not word-aligned\n");
     80 		return DBG_ERR;
     81 	}
     82 	count /= 4;
     83 	if (count < 1) return 0;
     84 
     85 	if (dc_mem_rd_words(dc, addr, count, data)) return DBG_ERR;
     86 	for (n = 0; count > 0; n += 4, addr += 16) {
     87 		switch (count) {
     88 		case 1:
     89 			count = 0;
     90 			INFO("%08x: %08x\n", addr, data[n]);
     91 			break;
     92 		case 2:
     93 			count = 0;
     94 			INFO("%08x: %08x %08x\n",
     95 				addr, data[n], data[n+1]);
     96 			break;
     97 		case 3:
     98 			count = 0;
     99 			INFO("%08x: %08x %08x %08x\n",
    100 				addr, data[n], data[n+1], data[n+2]);
    101 			break;
    102 		default:
    103 			count -= 4;
    104 			INFO("%08x: %08x %08x %08x %08x\n",
    105 				addr, data[n], data[n+1], data[n+2], data[n+3]);
    106 			break;
    107 		}
    108 	}
    109 	return 0;
    110 }
    111 
    112 int do_db(DC* dc, CC* cc) {
    113 	uint32_t data[1024 + 8];
    114 	uint32_t addr, count, bytecount;
    115 	uint8_t *x;
    116 	unsigned n;
    117 
    118 	if (cmd_arg_u32_opt(cc, 1, &addr, lastaddr)) return DBG_ERR;
    119 	if (cmd_arg_u32_opt(cc, 2, &count, lastcount)) return DBG_ERR;
    120 	if (count > 1024) count = 1024;
    121 	lastaddr = addr;
    122 	lastcount = count;
    123 
    124 	bytecount = count;
    125 	x = (void*) data;
    126 	if (addr & 3) {
    127 		x += (addr & 3);
    128 		count += 4 - (addr & 3);
    129 		addr &= 3;
    130 	}
    131 	if (count & 3) {
    132 		count += 4 - (count & 3);
    133 	}
    134 	count /= 4;
    135 	if (count < 1) return 0;
    136 
    137 	if (dc_mem_rd_words(dc, addr, count, data)) return DBG_ERR;
    138 
    139 	while (bytecount > 0) {
    140 		n = (bytecount > 16) ? 16 : bytecount;
    141 		INFO("%08x:", addr);
    142 		bytecount -= n;
    143 		addr += n;
    144 		while (n-- > 0) {
    145 			INFO(" %02x", *x++);
    146 		}
    147 		INFO("\n");
    148 	}
    149 	return 0;
    150 }
    151 
    152 int do_rd(DC* dc, CC* cc) {
    153 	uint32_t addr, val;
    154 	if (cmd_arg_u32(cc, 1, &addr)) return DBG_ERR;
    155 	int r = dc_mem_rd32(dc, addr, &val);
    156 	if (r < 0) {
    157 		INFO("%08x: ????????\n", addr);
    158 	} else {
    159 		INFO("%08x: %08x\n", addr, val);
    160 	}
    161 	return r;
    162 }
    163 
    164 int do_wr(DC* dc, CC* cc) {
    165 	uint32_t addr, val;
    166 	if (cmd_arg_u32(cc, 1, &addr)) return DBG_ERR;
    167 	if (cmd_arg_u32(cc, 2, &val)) return DBG_ERR;
    168 	int r;
    169 	if ((r = dc_mem_wr32(dc, addr, val)) == 0) {
    170 		INFO("%08x< %08x\n", addr, val);
    171 	}
    172 	return r;
    173 }
    174 
    175 int do_stop(DC* dc, CC* cc) {
    176 	int r;
    177 	if ((r = dc_core_halt(dc)) < 0) {
    178 		return r;
    179 	}
    180 	if ((r = dc_core_wait_halt(dc)) < 0) {
    181 		return r;
    182 	}
    183 	return read_show_regs(dc);
    184 }
    185 
    186 int do_resume(DC* dc, CC* cc) {
    187 	return dc_core_resume(dc);
    188 }
    189 
    190 int do_step(DC* dc, CC* cc) {
    191 	int r;
    192 	if ((r = dc_core_step(dc)) < 0) {
    193 		return r;
    194 	}
    195 	if ((r = dc_core_wait_halt(dc)) < 0) {
    196 		return r;
    197 	}
    198 	return read_show_regs(dc);
    199 }
    200 
    201 static uint32_t vcflags = 0;
    202 
    203 int do_reset(DC* dc, CC* cc) {
    204 	int r;
    205 	if ((r = dc_core_halt(dc)) < 0) {
    206 		return r;
    207 	}
    208 	if ((r = dc_mem_wr32(dc, DEMCR, DEMCR_TRCENA | vcflags)) < 0) {
    209 		return r;
    210 	}
    211 	if ((r = dc_mem_wr32(dc, AIRCR, AIRCR_VECTKEY | AIRCR_SYSRESETREQ)) < 0) {
    212 		return r;
    213 	}
    214 	return 0;
    215 }
    216 
    217 static int wait_for_stop(DC* dc) {
    218 	unsigned m = 0;
    219 	uint32_t val;
    220 	int r;
    221 	for (unsigned n = 0; n < 100; n++) {
    222 		if ((r = dc_mem_rd32(dc, DHCSR, &val)) < 0) {
    223 			dc_attach(dc, 0, 0, &val);
    224 		} else {
    225 			if (val & DHCSR_S_HALT) {
    226 				INFO("halt: CPU HALTED (%u,%u)\n", n, m);
    227 				uint32_t dfsr = -1, demcr = -1;
    228 				dc_mem_rd32(dc, DFSR, &dfsr);
    229 				dc_mem_rd32(dc, DEMCR, &demcr);
    230 				INFO("halt: DHCSR %08x, DFSR %08x, DEMCR %08x\n", val, dfsr, demcr);
    231 				return 0;
    232 			}
    233 			if (val & DHCSR_S_RESET_ST) {
    234 				m++;
    235 			}
    236 			dc_mem_wr32(dc, DHCSR, DHCSR_DBGKEY | DHCSR_C_HALT | DHCSR_C_DEBUGEN);
    237 		}
    238 	}
    239 	return DC_ERR_FAILED;
    240 }
    241 
    242 int do_reset_stop(DC* dc, CC* cc) {
    243 	int r;
    244 	if ((r = dc_core_halt(dc)) < 0) {
    245 		return r;
    246 	}
    247 	if ((r = wait_for_stop(dc)) < 0) {
    248 		return r;
    249 	}
    250 	if ((r = dc_mem_wr32(dc, DEMCR, DEMCR_VC_CORERESET | DEMCR_TRCENA | vcflags)) < 0) {
    251 		return r;
    252 	}
    253 	if ((r = dc_mem_wr32(dc, AIRCR, AIRCR_VECTKEY | AIRCR_SYSRESETREQ)) < 0) {
    254 		return r;
    255 	}
    256 	if ((r = wait_for_stop(dc)) < 0) {
    257 		INFO("reset-stop: CPU DID NOT HALT\n");
    258 		return r;
    259 	}
    260 	return 0;
    261 }
    262 
    263 static struct {
    264 	uint32_t flag;
    265 	const char* name;
    266 	const char* info;
    267 } FLAGS[] = {
    268 	{ DCF_POLL,        "poll",        "verify target state while attached" },
    269 	{ DCF_AUTO_ATTACH, "auto-attach", "automatically attach to target on command" },
    270 	{ DCF_AUTO_CONFIG, "auto-config", "set flags based on target probe on attach" },
    271 };
    272 
    273 #define NUMFLAGS (sizeof(FLAGS)/sizeof(FLAGS[0]))
    274 
    275 static int text_to_flag(const char* s, uint32_t* flag) {
    276 	for (unsigned n = 0; n < NUMFLAGS; n++) {
    277 		if (!strcmp(FLAGS[n].name, s)) {
    278 			*flag = FLAGS[n].flag;
    279 			return 0;
    280 		}
    281 	}
    282 	return DBG_ERR;
    283 }
    284 
    285 int do_set(DC* dc, CC* cc) {
    286 	if (cmd_argc(cc) == 1) {
    287 		uint32_t set = dc_flags(dc, 0, 0);
    288 		for (unsigned n = 0; n < NUMFLAGS; n++) {
    289 			INFO("%c%-12s %s\n", set & FLAGS[n].flag ? '+' : '-',
    290 				FLAGS[n].name, FLAGS[n].info);
    291 		}
    292 		return 0;
    293 	}
    294 	int n = 1;
    295 	const char* s;
    296 	uint32_t clr = 0;
    297 	uint32_t set = 0;
    298 	while ((cmd_arg_str_opt(cc, n++, &s, NULL) == 0) && (s != NULL)){
    299 		if (s[0] == '-') {
    300 			if (text_to_flag(s + 1, &clr)) {
    301 				ERROR("unknown flag '%s'\n", s + 1);
    302 				return DBG_ERR;
    303 			}
    304 		} else if (s[0] == '+') {
    305 			if (text_to_flag(s + 1, &clr)) {
    306 				ERROR("unknown flag '%s'\n", s + 1);
    307 				return DBG_ERR;
    308 			}
    309 		} else {
    310 			ERROR("set requires [+-]<feature> arguments\n");
    311 			return DBG_ERR;
    312 		}
    313 	}
    314 	dc_flags(dc, clr, set);
    315 	return 0;
    316 }
    317 
    318 int do_exit(DC* dc, CC* cc) {
    319 	debugger_exit();
    320 	return 0;
    321 }
    322 
    323 struct {
    324 	const char* name;
    325 	int (*func)(DC* dc, CC* cc);
    326 	const char* help;
    327 } CMDS[] = {
    328 { "attach",     do_attach,     "connect to target" },
    329 { "stop",       do_stop,       "halt core" },
    330 { "halt",       do_stop,       NULL },
    331 { "go",         do_resume,     NULL },
    332 { "resume",     do_resume,     "resume core" },
    333 { "step",       do_step,       "single-step core" },
    334 { "reset",      do_reset,      "reset core" },
    335 { "reset-stop", do_reset_stop, "reset core and halt" },
    336 { "dw",         do_dw,         "dump words            dw <addr> [ <count> ]" },
    337 { "db",         do_db,         "dump bytes            db <addr> [ <count> ]" },
    338 { "rd",         do_rd,         "read word             rd <addr>" },
    339 { "dr",         do_rd,         NULL },
    340 { "wr",         do_wr,         "write word            wr <addr> <val>" },
    341 { "regs",       do_regs,       "dump registers" },
    342 { "setarch",    do_setarch,    "select flash agent    setarch <name>" },
    343 { "flash",      do_flash,      "write file to flash   flash <file> <addr>" },
    344 { "erase",      do_erase,      "erase flash           erase all | erase <addr> <len>" },
    345 { "download",   do_download,   "write file to memory  download <file> <addr>" },
    346 { "upload",     do_upload,     "read memory to file   upload <file> <addr> <len>" },
    347 { "setclock",   do_setclock,   "set SWD clock freq    setclock <mhz>" },
    348 { "set",        do_set,        "adjust features       set [+-]<feature>" },
    349 { "help",       do_help,       "list commands" },
    350 { "exit",       do_exit,       "exit debugger" },
    351 { "quit",       do_exit,       NULL },
    352 };
    353 
    354 int do_help(DC* dc, CC* cc) {
    355 	int w = 0;
    356 	for (int n = 0; n < sizeof(CMDS)/sizeof(CMDS[0]); n++) {
    357 		int len = strlen(CMDS[n].name);
    358 		if (len > w) w = len;
    359 	}
    360 	for (int n = 0; n < sizeof(CMDS)/sizeof(CMDS[0]); n++) {
    361 		if (CMDS[n].help == NULL) {
    362 			continue;
    363 		}
    364 		INFO("%-*s %s\n", w + 3, CMDS[n].name, CMDS[n].help);
    365 	}
    366 	return 0;
    367 }
    368 
    369 void debugger_command(DC* dc, CC* cc) {
    370 	const char* cmd = cmd_name(cc);
    371 	for (int n = 0; n < sizeof(CMDS)/sizeof(CMDS[0]); n++) {
    372 		if (!strcmp(cmd, CMDS[n].name)) {
    373 			CMDS[n].func(dc, cc);
    374 			return;
    375 		}
    376 	}
    377 	ERROR("unknown command '%s'\n", cmd);
    378 }
    379