Revision c0ce998e
b/cpu-defs.h | ||
---|---|---|
28 | 28 |
#include <setjmp.h> |
29 | 29 |
#include <inttypes.h> |
30 | 30 |
#include "osdep.h" |
31 |
#include "sys-queue.h" |
|
31 | 32 |
|
32 | 33 |
#ifndef TARGET_LONG_BITS |
33 | 34 |
#error TARGET_LONG_BITS must be defined before including this header |
... | ... | |
146 | 147 |
typedef struct CPUBreakpoint { |
147 | 148 |
target_ulong pc; |
148 | 149 |
int flags; /* BP_* */ |
149 |
struct CPUBreakpoint *prev, *next;
|
|
150 |
TAILQ_ENTRY(CPUBreakpoint) entry;
|
|
150 | 151 |
} CPUBreakpoint; |
151 | 152 |
|
152 | 153 |
typedef struct CPUWatchpoint { |
153 | 154 |
target_ulong vaddr; |
154 | 155 |
target_ulong len_mask; |
155 | 156 |
int flags; /* BP_* */ |
156 |
struct CPUWatchpoint *prev, *next;
|
|
157 |
TAILQ_ENTRY(CPUWatchpoint) entry;
|
|
157 | 158 |
} CPUWatchpoint; |
158 | 159 |
|
159 | 160 |
#define CPU_TEMP_BUF_NLONGS 128 |
... | ... | |
188 | 189 |
\ |
189 | 190 |
/* from this point: preserved by CPU reset */ \ |
190 | 191 |
/* ice debug support */ \ |
191 |
CPUBreakpoint *breakpoints; \
|
|
192 |
TAILQ_HEAD(breakpoints_head, CPUBreakpoint) breakpoints; \
|
|
192 | 193 |
int singlestep_enabled; \ |
193 | 194 |
\ |
194 |
CPUWatchpoint *watchpoints; \
|
|
195 |
TAILQ_HEAD(watchpoints_head, CPUWatchpoint) watchpoints; \
|
|
195 | 196 |
CPUWatchpoint *watchpoint_hit; \ |
196 | 197 |
\ |
197 | 198 |
struct GDBRegisterState *gdb_regs; \ |
b/cpu-exec.c | ||
---|---|---|
198 | 198 |
CPUWatchpoint *wp; |
199 | 199 |
|
200 | 200 |
if (!env->watchpoint_hit) |
201 |
for (wp = env->watchpoints; wp != NULL; wp = wp->next)
|
|
201 |
TAILQ_FOREACH(wp, &env->watchpoints, entry)
|
|
202 | 202 |
wp->flags &= ~BP_WATCHPOINT_HIT; |
203 | 203 |
|
204 | 204 |
if (debug_excp_handler) |
b/exec.c | ||
---|---|---|
537 | 537 |
cpu_index++; |
538 | 538 |
} |
539 | 539 |
env->cpu_index = cpu_index; |
540 |
TAILQ_INIT(&env->breakpoints); |
|
541 |
TAILQ_INIT(&env->watchpoints); |
|
540 | 542 |
*penv = env; |
541 | 543 |
#if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY) |
542 | 544 |
register_savevm("cpu_common", cpu_index, CPU_COMMON_SAVE_VERSION, |
... | ... | |
1302 | 1304 |
int flags, CPUWatchpoint **watchpoint) |
1303 | 1305 |
{ |
1304 | 1306 |
target_ulong len_mask = ~(len - 1); |
1305 |
CPUWatchpoint *wp, *prev_wp;
|
|
1307 |
CPUWatchpoint *wp; |
|
1306 | 1308 |
|
1307 | 1309 |
/* sanity checks: allow power-of-2 lengths, deny unaligned watchpoints */ |
1308 | 1310 |
if ((len != 1 && len != 2 && len != 4 && len != 8) || (addr & ~len_mask)) { |
... | ... | |
1319 | 1321 |
wp->flags = flags; |
1320 | 1322 |
|
1321 | 1323 |
/* keep all GDB-injected watchpoints in front */ |
1322 |
if (!(flags & BP_GDB) && env->watchpoints) { |
|
1323 |
prev_wp = env->watchpoints; |
|
1324 |
while (prev_wp->next != NULL && (prev_wp->next->flags & BP_GDB)) |
|
1325 |
prev_wp = prev_wp->next; |
|
1326 |
} else { |
|
1327 |
prev_wp = NULL; |
|
1328 |
} |
|
1329 |
|
|
1330 |
/* Insert new watchpoint */ |
|
1331 |
if (prev_wp) { |
|
1332 |
wp->next = prev_wp->next; |
|
1333 |
prev_wp->next = wp; |
|
1334 |
} else { |
|
1335 |
wp->next = env->watchpoints; |
|
1336 |
env->watchpoints = wp; |
|
1337 |
} |
|
1338 |
if (wp->next) |
|
1339 |
wp->next->prev = wp; |
|
1340 |
wp->prev = prev_wp; |
|
1324 |
if (flags & BP_GDB) |
|
1325 |
TAILQ_INSERT_HEAD(&env->watchpoints, wp, entry); |
|
1326 |
else |
|
1327 |
TAILQ_INSERT_TAIL(&env->watchpoints, wp, entry); |
|
1341 | 1328 |
|
1342 | 1329 |
tlb_flush_page(env, addr); |
1343 | 1330 |
|
... | ... | |
1353 | 1340 |
target_ulong len_mask = ~(len - 1); |
1354 | 1341 |
CPUWatchpoint *wp; |
1355 | 1342 |
|
1356 |
for (wp = env->watchpoints; wp != NULL; wp = wp->next) {
|
|
1343 |
TAILQ_FOREACH(wp, &env->watchpoints, entry) {
|
|
1357 | 1344 |
if (addr == wp->vaddr && len_mask == wp->len_mask |
1358 | 1345 |
&& flags == (wp->flags & ~BP_WATCHPOINT_HIT)) { |
1359 | 1346 |
cpu_watchpoint_remove_by_ref(env, wp); |
... | ... | |
1366 | 1353 |
/* Remove a specific watchpoint by reference. */ |
1367 | 1354 |
void cpu_watchpoint_remove_by_ref(CPUState *env, CPUWatchpoint *watchpoint) |
1368 | 1355 |
{ |
1369 |
if (watchpoint->next) |
|
1370 |
watchpoint->next->prev = watchpoint->prev; |
|
1371 |
if (watchpoint->prev) |
|
1372 |
watchpoint->prev->next = watchpoint->next; |
|
1373 |
else |
|
1374 |
env->watchpoints = watchpoint->next; |
|
1356 |
TAILQ_REMOVE(&env->watchpoints, watchpoint, entry); |
|
1375 | 1357 |
|
1376 | 1358 |
tlb_flush_page(env, watchpoint->vaddr); |
1377 | 1359 |
|
... | ... | |
1381 | 1363 |
/* Remove all matching watchpoints. */ |
1382 | 1364 |
void cpu_watchpoint_remove_all(CPUState *env, int mask) |
1383 | 1365 |
{ |
1384 |
CPUWatchpoint *wp; |
|
1366 |
CPUWatchpoint *wp, *next;
|
|
1385 | 1367 |
|
1386 |
for (wp = env->watchpoints; wp != NULL; wp = wp->next)
|
|
1368 |
TAILQ_FOREACH_SAFE(wp, &env->watchpoints, entry, next) {
|
|
1387 | 1369 |
if (wp->flags & mask) |
1388 | 1370 |
cpu_watchpoint_remove_by_ref(env, wp); |
1371 |
} |
|
1389 | 1372 |
} |
1390 | 1373 |
|
1391 | 1374 |
/* Add a breakpoint. */ |
... | ... | |
1393 | 1376 |
CPUBreakpoint **breakpoint) |
1394 | 1377 |
{ |
1395 | 1378 |
#if defined(TARGET_HAS_ICE) |
1396 |
CPUBreakpoint *bp, *prev_bp;
|
|
1379 |
CPUBreakpoint *bp; |
|
1397 | 1380 |
|
1398 | 1381 |
bp = qemu_malloc(sizeof(*bp)); |
1399 | 1382 |
if (!bp) |
... | ... | |
1403 | 1386 |
bp->flags = flags; |
1404 | 1387 |
|
1405 | 1388 |
/* keep all GDB-injected breakpoints in front */ |
1406 |
if (!(flags & BP_GDB) && env->breakpoints) { |
|
1407 |
prev_bp = env->breakpoints; |
|
1408 |
while (prev_bp->next != NULL && (prev_bp->next->flags & BP_GDB)) |
|
1409 |
prev_bp = prev_bp->next; |
|
1410 |
} else { |
|
1411 |
prev_bp = NULL; |
|
1412 |
} |
|
1413 |
|
|
1414 |
/* Insert new breakpoint */ |
|
1415 |
if (prev_bp) { |
|
1416 |
bp->next = prev_bp->next; |
|
1417 |
prev_bp->next = bp; |
|
1418 |
} else { |
|
1419 |
bp->next = env->breakpoints; |
|
1420 |
env->breakpoints = bp; |
|
1421 |
} |
|
1422 |
if (bp->next) |
|
1423 |
bp->next->prev = bp; |
|
1424 |
bp->prev = prev_bp; |
|
1389 |
if (flags & BP_GDB) |
|
1390 |
TAILQ_INSERT_HEAD(&env->breakpoints, bp, entry); |
|
1391 |
else |
|
1392 |
TAILQ_INSERT_TAIL(&env->breakpoints, bp, entry); |
|
1425 | 1393 |
|
1426 | 1394 |
breakpoint_invalidate(env, pc); |
1427 | 1395 |
|
... | ... | |
1439 | 1407 |
#if defined(TARGET_HAS_ICE) |
1440 | 1408 |
CPUBreakpoint *bp; |
1441 | 1409 |
|
1442 |
for (bp = env->breakpoints; bp != NULL; bp = bp->next) {
|
|
1410 |
TAILQ_FOREACH(bp, &env->breakpoints, entry) {
|
|
1443 | 1411 |
if (bp->pc == pc && bp->flags == flags) { |
1444 | 1412 |
cpu_breakpoint_remove_by_ref(env, bp); |
1445 | 1413 |
return 0; |
... | ... | |
1455 | 1423 |
void cpu_breakpoint_remove_by_ref(CPUState *env, CPUBreakpoint *breakpoint) |
1456 | 1424 |
{ |
1457 | 1425 |
#if defined(TARGET_HAS_ICE) |
1458 |
if (breakpoint->next) |
|
1459 |
breakpoint->next->prev = breakpoint->prev; |
|
1460 |
if (breakpoint->prev) |
|
1461 |
breakpoint->prev->next = breakpoint->next; |
|
1462 |
else |
|
1463 |
env->breakpoints = breakpoint->next; |
|
1426 |
TAILQ_REMOVE(&env->breakpoints, breakpoint, entry); |
|
1464 | 1427 |
|
1465 | 1428 |
breakpoint_invalidate(env, breakpoint->pc); |
1466 | 1429 |
|
... | ... | |
1472 | 1435 |
void cpu_breakpoint_remove_all(CPUState *env, int mask) |
1473 | 1436 |
{ |
1474 | 1437 |
#if defined(TARGET_HAS_ICE) |
1475 |
CPUBreakpoint *bp; |
|
1438 |
CPUBreakpoint *bp, *next;
|
|
1476 | 1439 |
|
1477 |
for (bp = env->breakpoints; bp != NULL; bp = bp->next)
|
|
1440 |
TAILQ_FOREACH_SAFE(bp, &env->breakpoints, entry, next) {
|
|
1478 | 1441 |
if (bp->flags & mask) |
1479 | 1442 |
cpu_breakpoint_remove_by_ref(env, bp); |
1443 |
} |
|
1480 | 1444 |
#endif |
1481 | 1445 |
} |
1482 | 1446 |
|
... | ... | |
2005 | 1969 |
code_address = address; |
2006 | 1970 |
/* Make accesses to pages with watchpoints go via the |
2007 | 1971 |
watchpoint trap routines. */ |
2008 |
for (wp = env->watchpoints; wp != NULL; wp = wp->next) {
|
|
1972 |
TAILQ_FOREACH(wp, &env->watchpoints, entry) {
|
|
2009 | 1973 |
if (vaddr == (wp->vaddr & TARGET_PAGE_MASK)) { |
2010 | 1974 |
iotlb = io_mem_watch + paddr; |
2011 | 1975 |
/* TODO: The memory case can be optimized by not trapping |
... | ... | |
2552 | 2516 |
return; |
2553 | 2517 |
} |
2554 | 2518 |
vaddr = (env->mem_io_vaddr & TARGET_PAGE_MASK) + offset; |
2555 |
for (wp = env->watchpoints; wp != NULL; wp = wp->next) {
|
|
2519 |
TAILQ_FOREACH(wp, &env->watchpoints, entry) {
|
|
2556 | 2520 |
if ((vaddr == (wp->vaddr & len_mask) || |
2557 | 2521 |
(vaddr & wp->len_mask) == wp->vaddr) && (wp->flags & flags)) { |
2558 | 2522 |
wp->flags |= BP_WATCHPOINT_HIT; |
b/target-alpha/translate.c | ||
---|---|---|
2363 | 2363 |
|
2364 | 2364 |
gen_icount_start(); |
2365 | 2365 |
for (ret = 0; ret == 0;) { |
2366 |
if (unlikely(env->breakpoints)) {
|
|
2367 |
for (bp = env->breakpoints; bp != NULL; bp = bp->next) {
|
|
2366 |
if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) {
|
|
2367 |
TAILQ_FOREACH(bp, &env->breakpoints, entry) {
|
|
2368 | 2368 |
if (bp->pc == ctx.pc) { |
2369 | 2369 |
gen_excp(&ctx, EXCP_DEBUG, 0); |
2370 | 2370 |
break; |
b/target-arm/translate.c | ||
---|---|---|
8677 | 8677 |
} |
8678 | 8678 |
#endif |
8679 | 8679 |
|
8680 |
if (unlikely(env->breakpoints)) {
|
|
8681 |
for (bp = env->breakpoints; bp != NULL; bp = bp->next) {
|
|
8680 |
if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) {
|
|
8681 |
TAILQ_FOREACH(bp, &env->breakpoints, entry) {
|
|
8682 | 8682 |
if (bp->pc == dc->pc) { |
8683 | 8683 |
gen_set_condexec(dc); |
8684 | 8684 |
gen_set_pc_im(dc->pc); |
b/target-cris/translate.c | ||
---|---|---|
3189 | 3189 |
{ |
3190 | 3190 |
CPUBreakpoint *bp; |
3191 | 3191 |
|
3192 |
if (unlikely(env->breakpoints)) {
|
|
3193 |
for (bp = env->breakpoints; bp != NULL; bp = bp->next) {
|
|
3192 |
if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) {
|
|
3193 |
TAILQ_FOREACH(bp, &env->breakpoints, entry) {
|
|
3194 | 3194 |
if (bp->pc == dc->pc) { |
3195 | 3195 |
cris_evaluate_flags (dc); |
3196 | 3196 |
tcg_gen_movi_tl(env_pc, dc->pc); |
b/target-i386/helper.c | ||
---|---|---|
1364 | 1364 |
cpu_resume_from_signal(env, NULL); |
1365 | 1365 |
} |
1366 | 1366 |
} else { |
1367 |
for (bp = env->breakpoints; bp != NULL; bp = bp->next)
|
|
1367 |
TAILQ_FOREACH(bp, &env->breakpoints, entry)
|
|
1368 | 1368 |
if (bp->pc == env->eip) { |
1369 | 1369 |
if (bp->flags & BP_CPU) { |
1370 | 1370 |
check_hw_breakpoints(env, 1); |
b/target-i386/translate.c | ||
---|---|---|
7606 | 7606 |
|
7607 | 7607 |
gen_icount_start(); |
7608 | 7608 |
for(;;) { |
7609 |
if (unlikely(env->breakpoints)) {
|
|
7610 |
for (bp = env->breakpoints; bp != NULL; bp = bp->next) {
|
|
7609 |
if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) {
|
|
7610 |
TAILQ_FOREACH(bp, &env->breakpoints, entry) {
|
|
7611 | 7611 |
if (bp->pc == pc_ptr) { |
7612 | 7612 |
gen_debug(dc, pc_ptr - dc->cs_base); |
7613 | 7613 |
break; |
b/target-m68k/translate.c | ||
---|---|---|
2999 | 2999 |
do { |
3000 | 3000 |
pc_offset = dc->pc - pc_start; |
3001 | 3001 |
gen_throws_exception = NULL; |
3002 |
if (unlikely(env->breakpoints)) {
|
|
3003 |
for (bp = env->breakpoints; bp != NULL; bp = bp->next) {
|
|
3002 |
if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) {
|
|
3003 |
TAILQ_FOREACH(bp, &env->breakpoints, entry) {
|
|
3004 | 3004 |
if (bp->pc == dc->pc) { |
3005 | 3005 |
gen_exception(dc, dc->pc, EXCP_DEBUG); |
3006 | 3006 |
dc->is_jmp = DISAS_JUMP; |
b/target-mips/translate.c | ||
---|---|---|
8286 | 8286 |
#endif |
8287 | 8287 |
gen_icount_start(); |
8288 | 8288 |
while (ctx.bstate == BS_NONE) { |
8289 |
if (unlikely(env->breakpoints)) {
|
|
8290 |
for (bp = env->breakpoints; bp != NULL; bp = bp->next) {
|
|
8289 |
if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) {
|
|
8290 |
TAILQ_FOREACH(bp, &env->breakpoints, entry) {
|
|
8291 | 8291 |
if (bp->pc == ctx.pc) { |
8292 | 8292 |
save_cpu_state(&ctx, 1); |
8293 | 8293 |
ctx.bstate = BS_BRANCH; |
b/target-ppc/translate.c | ||
---|---|---|
7562 | 7562 |
gen_icount_start(); |
7563 | 7563 |
/* Set env in case of segfault during code fetch */ |
7564 | 7564 |
while (ctx.exception == POWERPC_EXCP_NONE && gen_opc_ptr < gen_opc_end) { |
7565 |
if (unlikely(env->breakpoints)) {
|
|
7566 |
for (bp = env->breakpoints; bp != NULL; bp = bp->next) {
|
|
7565 |
if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) {
|
|
7566 |
TAILQ_FOREACH(bp, &env->breakpoints, entry) {
|
|
7567 | 7567 |
if (bp->pc == ctx.nip) { |
7568 | 7568 |
gen_update_nip(&ctx, ctx.nip); |
7569 | 7569 |
gen_helper_raise_debug(); |
b/target-sh4/translate.c | ||
---|---|---|
1776 | 1776 |
max_insns = CF_COUNT_MASK; |
1777 | 1777 |
gen_icount_start(); |
1778 | 1778 |
while (ctx.bstate == BS_NONE && gen_opc_ptr < gen_opc_end) { |
1779 |
if (unlikely(env->breakpoints)) {
|
|
1780 |
for (bp = env->breakpoints; bp != NULL; bp = bp->next) {
|
|
1779 |
if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) {
|
|
1780 |
TAILQ_FOREACH(bp, &env->breakpoints, entry) {
|
|
1781 | 1781 |
if (ctx.pc == bp->pc) { |
1782 | 1782 |
/* We have hit a breakpoint - make sure PC is up-to-date */ |
1783 | 1783 |
tcg_gen_movi_i32(cpu_pc, ctx.pc); |
b/target-sparc/translate.c | ||
---|---|---|
4816 | 4816 |
max_insns = CF_COUNT_MASK; |
4817 | 4817 |
gen_icount_start(); |
4818 | 4818 |
do { |
4819 |
if (unlikely(env->breakpoints)) {
|
|
4820 |
for (bp = env->breakpoints; bp != NULL; bp = bp->next) {
|
|
4819 |
if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) {
|
|
4820 |
TAILQ_FOREACH(bp, &env->breakpoints, entry) {
|
|
4821 | 4821 |
if (bp->pc == dc->pc) { |
4822 | 4822 |
if (dc->pc != pc_start) |
4823 | 4823 |
save_state(dc, cpu_cond); |
Also available in: Unified diff