m3dev

cortex m3 debug tools -- superceded by mdebug
git clone http://frotz.net/git/m3dev.git
Log | Files | Refs | README | LICENSE

debugger-core.c (10413B)


      1 /* debugger-core.c
      2  *
      3  * Copyright 2011 Brian Swetland <swetland@frotz.net>
      4  *
      5  * Licensed under the Apache License, Version 2.0 (the "License");
      6  * you may not use this file except in compliance with the License.
      7  * You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  */
     17 
     18 
     19 #include <stdio.h>
     20 #include <stdlib.h>
     21 #include <unistd.h>
     22 #include <string.h>
     23 #include <ctype.h>
     24 #include <stdarg.h>
     25 
     26 #include <pthread.h>
     27 #include <sys/socket.h>
     28 
     29 #include <fw/types.h>
     30 #include <protocol/rswdp.h>
     31 #include "debugger.h"
     32 #include "rswdp.h"
     33 
     34 #define DHCSR_C_DEBUGEN		(1 << 0)
     35 #define DHCSR_C_HALT		(1 << 1)
     36 #define DHCSR_C_STEP		(1 << 2)
     37 #define DHCSR_C_MASKINTS	(1 << 3)
     38 #define DHCSR_C_SNAPSTALL	(1 << 5)
     39 #define DHCSR_S_REGRDY		(1 << 16)
     40 #define DHCSR_S_HALT		(1 << 17)
     41 #define DHCSR_S_SLEEP		(1 << 18)
     42 #define DHCSR_S_LOCKUP		(1 << 19)
     43 #define DHCSR_S_RETIRE_ST	(1 << 24)
     44 #define DHCSR_S_RESET_ST	(1 << 25)
     45 
     46 #define DFSR			0xE000ED30
     47 #define DFSR_HALTED		(1 << 0)
     48 #define DFSR_BKPT		(1 << 1)
     49 #define DFSR_DWTTRAP		(1 << 2)
     50 #define DFSR_VCATCH		(1 << 3)
     51 #define DFSR_EXTERNAL		(1 << 4)
     52 #define DFSR_MASK		0x1F
     53 
     54 extern int swd_verbose;
     55 
     56 static void m_event(const char *evt) {
     57 	xprintf(XCORE, "DEBUG EVENT: %s\n", evt);
     58 }
     59 
     60 static void monitor(void) {
     61 	u32 v;
     62 	if (swdp_clear_error()) return;
     63 	if (swdp_ahb_read(DFSR, &v) == 0) {
     64 		if (v & DFSR_MASK) {
     65 			swdp_ahb_write(DFSR, DFSR_MASK);
     66 		}
     67 		if (v & DFSR_HALTED) m_event("HALTED");
     68 		if (v & DFSR_BKPT) m_event("BKPT");
     69 		if (v & DFSR_DWTTRAP) m_event("DWTTRAP");
     70 		if (v & DFSR_VCATCH) m_event("VCATCH");
     71 		if (v & DFSR_EXTERNAL) m_event("EXTERNAL");
     72 	}
     73 }
     74 
     75 static pthread_mutex_t _dbg_lock = PTHREAD_MUTEX_INITIALIZER;
     76 static pthread_t _dbg_thread;
     77 
     78 void debugger_lock() {
     79 	pthread_mutex_lock(&_dbg_lock);
     80 	if (swdp_clear_error()) {
     81 #if 0
     82 		// way too noisy if the link goes down
     83 		xprintf("SWD ERROR persists. Attempting link reset.\n");
     84 #endif
     85 		swdp_reset();
     86 	}
     87 	swd_verbose = 1;
     88 }
     89 
     90 void debugger_unlock() {
     91 #if 0
     92 	if (swdp_error()) {
     93 		xprintf(XCORE, "SWD ERROR\n");
     94 	}
     95 #endif
     96 	swd_verbose = 0;
     97 	pthread_mutex_unlock(&_dbg_lock);
     98 }
     99 
    100 void *debugger_monitor(void *arg) {
    101 	for (;;) {
    102 		pthread_mutex_lock(&_dbg_lock);
    103 		monitor();
    104 		pthread_mutex_unlock(&_dbg_lock);
    105 		usleep(250000);
    106 	}
    107 }
    108 
    109 void gdb_server(int fd);
    110 int socket_listen_tcp(unsigned port);
    111 
    112 static pthread_t _listen_master;
    113 void *gdb_listener(void *arg) {
    114 	int fd;
    115 	if ((fd = socket_listen_tcp(5555)) < 0) {
    116 		xprintf(XGDB, "gdb_listener() cannot bind to 5555\n");
    117 		return NULL;
    118 	}
    119 	for (;;) {
    120 		int s = accept(fd, NULL, NULL);
    121 		if (s >= 0) {
    122 			gdb_server(s);
    123 			close(s);
    124 		}
    125 	}
    126 	return NULL;
    127 }
    128 
    129 void debugger_init() {
    130 	pthread_create(&_dbg_thread, NULL, debugger_monitor, NULL);
    131 	pthread_create(&_listen_master, NULL, gdb_listener, NULL);
    132 }
    133 
    134 
    135 static struct varinfo *all_variables = 0;
    136 static struct funcinfo *allfuncs = 0;
    137 
    138 static int frame_argc = 0;
    139 static param *frame_argv = 0;
    140 
    141 static void variable_set(const char *name, u32 value) {
    142 	struct varinfo *vi;
    143 	int len;
    144 	for (vi = all_variables; vi; vi = vi->next) {
    145 		if (!strcmp(name, vi->name)) {
    146 			vi->value = value;
    147 			return;
    148 		}
    149 	}
    150 	len = strlen(name) + 1;
    151 	vi = malloc(sizeof(*vi) + len);
    152 	memcpy(vi->name, name, len);
    153 	vi->value = value;
    154 	vi->next = all_variables;
    155 	all_variables = vi;
    156 }
    157 
    158 static int variable_get(const char *name, u32 *value) {
    159 	struct varinfo *vi;
    160 	for (vi = all_variables; vi; vi = vi->next) {
    161 		if (!strcmp(name, vi->name)) {
    162 			*value = vi->value;
    163 			return 0;
    164 		}
    165 	}
    166 	return -1;
    167 }
    168 
    169 int debugger_variable(const char *name, u32 *value) {
    170 	return variable_get(name, value);
    171 }
    172 
    173 static int do_script(int argc, param *argv) {
    174 	FILE *fp;
    175 	char *line,linebuf[256];
    176 	struct funcinfo *newfunc = 0;
    177 	struct funcline *lastline = 0;
    178 	const char *fname = argv[0].s;
    179 
    180 	if (argc != 1)
    181 		return -1;
    182 
    183 	if (!strcmp(fname, "-")) {
    184 		fp = stdin;
    185 	} else {
    186 		if (!(fp = fopen(argv[0].s, "r"))) {
    187 			xprintf(XCORE, "error: cannot open '%s'\n", argv[0].s);
    188 			return -1;
    189 		}
    190 	}
    191 
    192 	while (fgets(linebuf, sizeof(linebuf), fp)) {
    193 		line = linebuf;
    194 		while (isspace(*line))
    195 			line++;
    196 		if (iscntrl(line[0]) || line[0] == '#')
    197 			continue;
    198 		if (!strncmp(line, "function", 8) && isspace(line[8])) {
    199 			char *name, *x;
    200 			name = line + 9;
    201 			if (newfunc) {
    202 				xprintf(XCORE, "error: nested functions not allowed\n");
    203 				break;
    204 			}
    205 			while (isspace(*name))
    206 				name++;
    207 			x = name;
    208 			while (!isspace(*x) && *x)
    209 				x++;
    210 			*x = 0;
    211 			if (*name == 0) {
    212 				xprintf(XCORE, "error: functions must have names\n");
    213 				break;
    214 			}
    215 			newfunc = malloc(sizeof(*newfunc) + strlen(name) + 1);
    216 			if (newfunc == 0) {
    217 				xprintf(XCORE, "error: out of memory\n");
    218 				break;
    219 			}
    220 			strcpy(newfunc->name, name);
    221 			newfunc->next = 0;
    222 			newfunc->lines = 0;
    223 			continue;
    224 		}
    225 		if (newfunc) {
    226 			struct funcline *fl;
    227 			if (!strncmp(line, "end", 3) && isspace(line[3])) {
    228 				newfunc->next = allfuncs;
    229 				allfuncs = newfunc;
    230 				newfunc = 0;
    231 				lastline = 0;
    232 				continue;
    233 			}
    234 			fl = malloc(sizeof(*fl) + strlen(line) + 1);
    235 			if (fl == 0) {
    236 				xprintf(XCORE, "out of memory");
    237 				newfunc = 0;
    238 				if (fp != stdin)
    239 					fclose(fp);
    240 				return -1;
    241 			}
    242 			strcpy(fl->text, line);
    243 			fl->next = 0;
    244 			if (lastline) {
    245 				lastline->next = fl;
    246 			} else {
    247 				newfunc->lines = fl;
    248 			}
    249 			lastline = fl;
    250 		} else {
    251 			xprintf(XCORE, "script> %s", line);
    252 			if (debugger_command(line))
    253 				return -1;
    254 		}
    255 	}
    256 	if (fp != stdin)
    257 		fclose(fp);
    258 
    259 	if (newfunc)
    260 		newfunc = 0;
    261 	return 0;
    262 }
    263 
    264 static int do_set(int argc, param *argv) {
    265 	const char *name;
    266 	if ((argc != 2) && (argc != 4)) {
    267 		xprintf(XCORE, "error: set requires two or four arguments\n");
    268 		return -1;
    269 	}
    270 	name = argv[0].s;
    271 	if (*name == '$')
    272 		name++;
    273 	if (*name == 0) {
    274 		xprintf(XCORE, "error: empty name?!\n");
    275 		return -1;
    276 	}
    277 	if (!isalpha(*name)) {
    278 		xprintf(XCORE, "error: variable name must begin with a letter\n");
    279 		return -1;
    280 	}
    281 
    282 	if (argc == 4) {
    283 		u32 a, b, n;
    284 		const char *op;
    285 		a = argv[1].n;
    286  		op = argv[2].s;
    287 		b = argv[3].n;
    288 		if (!strcmp(op,"+")) {
    289 			n = a + b;
    290 		} else if (!strcmp(op, "-")) {
    291 			n = a - b;
    292 		} else if (!strcmp(op, "<<")) {
    293 			n = a << b;
    294 		} else if (!strcmp(op, ">>")) {
    295 			n = a >> b;
    296 		} else if (!strcmp(op, "*")) {
    297 			n = a * b;
    298 		} else if (!strcmp(op, "/")) {
    299 			if (b == 0) {
    300 				n = 0;
    301 			} else {
    302 				n = a / b;
    303 			}
    304 		} else {
    305 			xprintf(XCORE, "error: set <var> <a> <op> <b> requires op: + - * / << >>\n");
    306 			return -1;
    307 		}
    308 		variable_set(name, n);
    309 	} else {
    310 		variable_set(name, argv[1].n);
    311 	}
    312 	return 0;
    313 }
    314 
    315 static int parse_number(const char *in, unsigned *out) {
    316 	u32 value;
    317 	char text[64];
    318 	char *obrack;
    319 	int r;
    320 
    321 	strncpy(text, in, sizeof(text));
    322 	text[sizeof(text)-1] = 0;
    323 
    324 	/* handle dereference forms */
    325 	obrack = strchr(text, '[');
    326 	if (obrack) {
    327 		unsigned base, index;
    328 		char *cbrack;
    329 		*obrack++ = 0;
    330 		cbrack = strchr(obrack, ']');
    331 		if (!cbrack)
    332 			return -1;
    333 		*cbrack = 0;
    334 		if (parse_number(text, &base))
    335 			return -1;
    336 		if (parse_number(obrack, &index))
    337 			return -1;
    338 		if (read_memory_word(base + index, &value))
    339 			return -1;
    340 		*out = value;
    341 		return 0;
    342 	}
    343 
    344 	/* handle local $[0..9] and global $... variables */
    345 	if (text[0] == '$') {
    346 		if (isdigit(text[1]) && (text[2] == 0)) {
    347 			r = atoi(text + 1);
    348 			if (r > 0) {
    349 				if (r <= frame_argc) {
    350 					*out = frame_argv[r - 1].n;
    351 					return 0;
    352 				}
    353 			}
    354 			xprintf(XCORE, "no local variable %s\n", text);
    355 			*out = 0;
    356 			return 0;
    357 		}
    358 		if (variable_get(text + 1, &value) == 0) {
    359 			*out = value;
    360 		} else {
    361 			xprintf(XCORE, "undefined variable '%s'\n", text + 1);
    362 			*out = 0;
    363 		}
    364 		return 0;
    365 	}
    366 
    367 	/* handle registers */
    368 	r = read_register(text, &value);
    369 	if (r != ERROR_UNKNOWN) {
    370 		*out = value;
    371 		return r;
    372 	}
    373 
    374 	/* otherwise decimal or hex constants */
    375 	if (text[0] == '.') {
    376 		*out = strtoul(text + 1, 0, 10);
    377 	} else {
    378 		*out = strtoul(text, 0, 16);
    379 	}
    380 	return 0;
    381 }
    382 
    383 static int exec_function(struct funcinfo *f, int argc, param *argv) {
    384 	param *saved_argv;
    385 	int saved_argc;
    386 	struct funcline *line;
    387 	char text[256];
    388 	int r, n;
    389 
    390 	saved_argv = frame_argv;
    391 	saved_argc = frame_argc;
    392 	frame_argv = argv;
    393 	frame_argc = argc;
    394 
    395 	for (line = f->lines, n = 1; line; line = line->next, n++) {
    396 		strcpy(text, line->text);
    397 		r = debugger_command(text);
    398 		if (r) {
    399 			xprintf(XCORE, "error: %s: line %d\n", f->name, n);
    400 			goto done;
    401 		}
    402 	}
    403 	r = 0;
    404 done:
    405 	frame_argc = saved_argc;
    406 	frame_argv = saved_argv;
    407 	return r;
    408 }
    409 
    410 static int _debugger_exec(const char *cmd, unsigned argc, param *argv) {
    411 	struct funcinfo *f;
    412 	struct debugger_command *c;
    413 
    414 	/* core built-ins */
    415 	if (!strcasecmp(cmd, "set"))
    416 		return do_set(argc, argv);
    417 	if (!strcasecmp(cmd, "script"))
    418 		return do_script(argc, argv);
    419 
    420 	for (c = debugger_commands; c->name; c++) {
    421 		if (!strcasecmp(cmd, c->name)) {
    422 			int n;
    423 			debugger_lock();
    424 			n = c->func(argc, argv);
    425 			debugger_unlock();
    426 			return n;
    427 		}
    428 	}
    429 	for (f = allfuncs; f; f = f->next) {
    430 		if (!strcasecmp(cmd, f->name)) {
    431 			return exec_function(f, argc, argv);
    432 		}
    433 	}
    434 	return ERROR_UNKNOWN;
    435 }
    436 
    437 int debugger_invoke(const char *cmd, unsigned argc, ...) {
    438 	param arg[32];
    439 	unsigned n;
    440 	va_list ap;
    441 
    442 	if (argc > 31)
    443 		return -1;
    444 
    445 	va_start(ap, argc);
    446 	for (n = 0; n < argc; n++) {
    447 		arg[n].s = "";
    448 		arg[n].n = va_arg(ap, unsigned);
    449 	}
    450 	return _debugger_exec(cmd, argc, arg);
    451 }
    452 
    453 int debugger_command(char *line) {
    454 	param arg[32];
    455 	unsigned c, n = 0;
    456 	int r;
    457 
    458 	while (*line && (*line == ' ')) line++;
    459 
    460 	if (*line == '/') {
    461 		arg[0].s = line + 1;
    462 		return _debugger_exec("wconsole", 1, arg);
    463 	}
    464 
    465 	while ((c = *line)) {
    466 		if (c <= ' ') {
    467 			line++;
    468 			continue;
    469 		}
    470 		arg[n].s = line;
    471 		for (;;) {
    472 			if (c == 0) {
    473 				n++;
    474 				break;
    475 			} else if (c == '#') {
    476 				*line = 0;
    477 				break;
    478 			} else if (c <= ' ') {
    479 				*line++ = 0;
    480 				n++;
    481 				break;
    482 			}
    483 			c = *++line;
    484 		}
    485 	}
    486 
    487 	if (n == 0)
    488 		return 0;
    489 
    490 	for (c = 0; c < n; c++) {
    491 		if (parse_number(arg[c].s, &(arg[c].n))) {
    492 			xprintf(XCORE, "error: bad number: %s\n", arg[c].s);
    493 			return -1;
    494 		}
    495 	}
    496 
    497 	r = _debugger_exec(arg[0].s, n - 1, arg + 1);
    498 	if (r == ERROR_UNKNOWN) {
    499 		xprintf(XCORE, "unknown command: %s\n", arg[0].s);
    500 	}
    501 	return r;
    502 }
    503