Commit dd32aa10476d04853b71657d5345e812915d87ed
Committed by
Anthony Liguori
1 parent
8389e7f4
gdbstub: Add vCont support
This patch adds support for the vCont remote gdb command. It is used by gdb 6.8 or better to switch the debugging focus for single-stepping multi-threaded targets, ie. multi-threaded application in user mode emulation or VCPUs in system emulation. Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Showing
1 changed file
with
58 additions
and
0 deletions
gdbstub.c
| ... | ... | @@ -1631,6 +1631,64 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf) |
| 1631 | 1631 | s->signal = 0; |
| 1632 | 1632 | gdb_continue(s); |
| 1633 | 1633 | return RS_IDLE; |
| 1634 | + case 'v': | |
| 1635 | + if (strncmp(p, "Cont", 4) == 0) { | |
| 1636 | + int res_signal, res_thread; | |
| 1637 | + | |
| 1638 | + p += 4; | |
| 1639 | + if (*p == '?') { | |
| 1640 | + put_packet(s, "vCont;c;C;s;S"); | |
| 1641 | + break; | |
| 1642 | + } | |
| 1643 | + res = 0; | |
| 1644 | + res_signal = 0; | |
| 1645 | + res_thread = 0; | |
| 1646 | + while (*p) { | |
| 1647 | + int action, signal; | |
| 1648 | + | |
| 1649 | + if (*p++ != ';') { | |
| 1650 | + res = 0; | |
| 1651 | + break; | |
| 1652 | + } | |
| 1653 | + action = *p++; | |
| 1654 | + signal = 0; | |
| 1655 | + if (action == 'C' || action == 'S') { | |
| 1656 | + signal = strtoul(p, (char **)&p, 16); | |
| 1657 | + } else if (action != 'c' && action != 's') { | |
| 1658 | + res = 0; | |
| 1659 | + break; | |
| 1660 | + } | |
| 1661 | + thread = 0; | |
| 1662 | + if (*p == ':') { | |
| 1663 | + thread = strtoull(p+1, (char **)&p, 16); | |
| 1664 | + } | |
| 1665 | + action = tolower(action); | |
| 1666 | + if (res == 0 || (res == 'c' && action == 's')) { | |
| 1667 | + res = action; | |
| 1668 | + res_signal = signal; | |
| 1669 | + res_thread = thread; | |
| 1670 | + } | |
| 1671 | + } | |
| 1672 | + if (res) { | |
| 1673 | + if (res_thread != -1 && res_thread != 0) { | |
| 1674 | + env = find_cpu(res_thread); | |
| 1675 | + if (env == NULL) { | |
| 1676 | + put_packet(s, "E22"); | |
| 1677 | + break; | |
| 1678 | + } | |
| 1679 | + s->c_cpu = env; | |
| 1680 | + } | |
| 1681 | + if (res == 's') { | |
| 1682 | + cpu_single_step(s->c_cpu, sstep_flags); | |
| 1683 | + } | |
| 1684 | + s->signal = res_signal; | |
| 1685 | + gdb_continue(s); | |
| 1686 | + return RS_IDLE; | |
| 1687 | + } | |
| 1688 | + break; | |
| 1689 | + } else { | |
| 1690 | + goto unknown_command; | |
| 1691 | + } | |
| 1634 | 1692 | case 'k': |
| 1635 | 1693 | /* Kill the target */ |
| 1636 | 1694 | fprintf(stderr, "\nQEMU: Terminated via GDBstub\n"); | ... | ... |