Revision a1d1bb31 gdbstub.c
b/gdbstub.c | ||
---|---|---|
1145 | 1145 |
} |
1146 | 1146 |
} |
1147 | 1147 |
|
1148 |
/* GDB breakpoint/watchpoint types */ |
|
1149 |
#define GDB_BREAKPOINT_SW 0 |
|
1150 |
#define GDB_BREAKPOINT_HW 1 |
|
1151 |
#define GDB_WATCHPOINT_WRITE 2 |
|
1152 |
#define GDB_WATCHPOINT_READ 3 |
|
1153 |
#define GDB_WATCHPOINT_ACCESS 4 |
|
1154 |
|
|
1155 |
#ifndef CONFIG_USER_ONLY |
|
1156 |
static const int xlat_gdb_type[] = { |
|
1157 |
[GDB_WATCHPOINT_WRITE] = BP_GDB | BP_MEM_WRITE, |
|
1158 |
[GDB_WATCHPOINT_READ] = BP_GDB | BP_MEM_READ, |
|
1159 |
[GDB_WATCHPOINT_ACCESS] = BP_GDB | BP_MEM_ACCESS, |
|
1160 |
}; |
|
1161 |
#endif |
|
1162 |
|
|
1163 |
static int gdb_breakpoint_insert(CPUState *env, target_ulong addr, |
|
1164 |
target_ulong len, int type) |
|
1165 |
{ |
|
1166 |
switch (type) { |
|
1167 |
case GDB_BREAKPOINT_SW: |
|
1168 |
case GDB_BREAKPOINT_HW: |
|
1169 |
return cpu_breakpoint_insert(env, addr, BP_GDB, NULL); |
|
1170 |
#ifndef CONFIG_USER_ONLY |
|
1171 |
case GDB_WATCHPOINT_WRITE: |
|
1172 |
case GDB_WATCHPOINT_READ: |
|
1173 |
case GDB_WATCHPOINT_ACCESS: |
|
1174 |
return cpu_watchpoint_insert(env, addr, len, xlat_gdb_type[type], |
|
1175 |
NULL); |
|
1176 |
#endif |
|
1177 |
default: |
|
1178 |
return -ENOSYS; |
|
1179 |
} |
|
1180 |
} |
|
1181 |
|
|
1182 |
static int gdb_breakpoint_remove(CPUState *env, target_ulong addr, |
|
1183 |
target_ulong len, int type) |
|
1184 |
{ |
|
1185 |
switch (type) { |
|
1186 |
case GDB_BREAKPOINT_SW: |
|
1187 |
case GDB_BREAKPOINT_HW: |
|
1188 |
return cpu_breakpoint_remove(env, addr, BP_GDB); |
|
1189 |
#ifndef CONFIG_USER_ONLY |
|
1190 |
case GDB_WATCHPOINT_WRITE: |
|
1191 |
case GDB_WATCHPOINT_READ: |
|
1192 |
case GDB_WATCHPOINT_ACCESS: |
|
1193 |
return cpu_watchpoint_remove(env, addr, len, xlat_gdb_type[type]); |
|
1194 |
#endif |
|
1195 |
default: |
|
1196 |
return -ENOSYS; |
|
1197 |
} |
|
1198 |
} |
|
1199 |
|
|
1200 |
static void gdb_breakpoint_remove_all(CPUState *env) |
|
1201 |
{ |
|
1202 |
cpu_breakpoint_remove_all(env, BP_GDB); |
|
1203 |
#ifndef CONFIG_USER_ONLY |
|
1204 |
cpu_watchpoint_remove_all(env, BP_GDB); |
|
1205 |
#endif |
|
1206 |
} |
|
1207 |
|
|
1148 | 1208 |
static int gdb_handle_packet(GDBState *s, CPUState *env, const char *line_buf) |
1149 | 1209 |
{ |
1150 | 1210 |
const char *p; |
1151 |
int ch, reg_size, type; |
|
1211 |
int ch, reg_size, type, res;
|
|
1152 | 1212 |
char buf[MAX_PACKET_LENGTH]; |
1153 | 1213 |
uint8_t mem_buf[MAX_PACKET_LENGTH]; |
1154 | 1214 |
uint8_t *registers; |
... | ... | |
1168 | 1228 |
* because gdb is doing and initial connect and the state |
1169 | 1229 |
* should be cleaned up. |
1170 | 1230 |
*/ |
1171 |
cpu_breakpoint_remove_all(env); |
|
1172 |
cpu_watchpoint_remove_all(env); |
|
1231 |
gdb_breakpoint_remove_all(env); |
|
1173 | 1232 |
break; |
1174 | 1233 |
case 'c': |
1175 | 1234 |
if (*p != '\0') { |
... | ... | |
1203 | 1262 |
exit(0); |
1204 | 1263 |
case 'D': |
1205 | 1264 |
/* Detach packet */ |
1206 |
cpu_breakpoint_remove_all(env); |
|
1207 |
cpu_watchpoint_remove_all(env); |
|
1265 |
gdb_breakpoint_remove_all(env); |
|
1208 | 1266 |
gdb_continue(s); |
1209 | 1267 |
put_packet(s, "OK"); |
1210 | 1268 |
break; |
... | ... | |
1327 | 1385 |
put_packet(s, "OK"); |
1328 | 1386 |
break; |
1329 | 1387 |
case 'Z': |
1330 |
type = strtoul(p, (char **)&p, 16); |
|
1331 |
if (*p == ',') |
|
1332 |
p++; |
|
1333 |
addr = strtoull(p, (char **)&p, 16); |
|
1334 |
if (*p == ',') |
|
1335 |
p++; |
|
1336 |
len = strtoull(p, (char **)&p, 16); |
|
1337 |
switch (type) { |
|
1338 |
case 0: |
|
1339 |
case 1: |
|
1340 |
if (cpu_breakpoint_insert(env, addr) < 0) |
|
1341 |
goto breakpoint_error; |
|
1342 |
put_packet(s, "OK"); |
|
1343 |
break; |
|
1344 |
#ifndef CONFIG_USER_ONLY |
|
1345 |
case 2: |
|
1346 |
type = PAGE_WRITE; |
|
1347 |
goto insert_watchpoint; |
|
1348 |
case 3: |
|
1349 |
type = PAGE_READ; |
|
1350 |
goto insert_watchpoint; |
|
1351 |
case 4: |
|
1352 |
type = PAGE_READ | PAGE_WRITE; |
|
1353 |
insert_watchpoint: |
|
1354 |
if (cpu_watchpoint_insert(env, addr, type) < 0) |
|
1355 |
goto breakpoint_error; |
|
1356 |
put_packet(s, "OK"); |
|
1357 |
break; |
|
1358 |
#endif |
|
1359 |
default: |
|
1360 |
put_packet(s, ""); |
|
1361 |
break; |
|
1362 |
} |
|
1363 |
break; |
|
1364 |
breakpoint_error: |
|
1365 |
put_packet(s, "E22"); |
|
1366 |
break; |
|
1367 |
|
|
1368 | 1388 |
case 'z': |
1369 | 1389 |
type = strtoul(p, (char **)&p, 16); |
1370 | 1390 |
if (*p == ',') |
... | ... | |
1373 | 1393 |
if (*p == ',') |
1374 | 1394 |
p++; |
1375 | 1395 |
len = strtoull(p, (char **)&p, 16); |
1376 |
if (type == 0 || type == 1) { |
|
1377 |
cpu_breakpoint_remove(env, addr); |
|
1378 |
put_packet(s, "OK"); |
|
1379 |
#ifndef CONFIG_USER_ONLY |
|
1380 |
} else if (type >= 2 || type <= 4) { |
|
1381 |
cpu_watchpoint_remove(env, addr); |
|
1382 |
put_packet(s, "OK"); |
|
1383 |
#endif |
|
1384 |
} else { |
|
1396 |
if (ch == 'Z') |
|
1397 |
res = gdb_breakpoint_insert(env, addr, len, type); |
|
1398 |
else |
|
1399 |
res = gdb_breakpoint_remove(env, addr, len, type); |
|
1400 |
if (res >= 0) |
|
1401 |
put_packet(s, "OK"); |
|
1402 |
else if (res == -ENOSYS) |
|
1385 | 1403 |
put_packet(s, ""); |
1386 |
} |
|
1404 |
else |
|
1405 |
put_packet(s, "E22"); |
|
1387 | 1406 |
break; |
1388 | 1407 |
case 'q': |
1389 | 1408 |
case 'Q': |
... | ... | |
1504 | 1523 |
|
1505 | 1524 |
if (reason == EXCP_DEBUG) { |
1506 | 1525 |
if (s->env->watchpoint_hit) { |
1507 |
switch (s->env->watchpoint[s->env->watchpoint_hit - 1].type & |
|
1508 |
(PAGE_READ | PAGE_WRITE)) { |
|
1509 |
case PAGE_READ: |
|
1526 |
switch (s->env->watchpoint_hit->flags & BP_MEM_ACCESS) { |
|
1527 |
case BP_MEM_READ: |
|
1510 | 1528 |
type = "r"; |
1511 | 1529 |
break; |
1512 |
case PAGE_READ | PAGE_WRITE:
|
|
1530 |
case BP_MEM_ACCESS:
|
|
1513 | 1531 |
type = "a"; |
1514 | 1532 |
break; |
1515 | 1533 |
default: |
... | ... | |
1517 | 1535 |
break; |
1518 | 1536 |
} |
1519 | 1537 |
snprintf(buf, sizeof(buf), "T%02x%swatch:" TARGET_FMT_lx ";", |
1520 |
SIGTRAP, type, |
|
1521 |
s->env->watchpoint[s->env->watchpoint_hit - 1].vaddr); |
|
1538 |
SIGTRAP, type, s->env->watchpoint_hit->vaddr); |
|
1522 | 1539 |
put_packet(s, buf); |
1523 |
s->env->watchpoint_hit = 0;
|
|
1540 |
s->env->watchpoint_hit = NULL;
|
|
1524 | 1541 |
return; |
1525 | 1542 |
} |
1526 | 1543 |
tb_flush(s->env); |
Also available in: Unified diff