Bochs/bochs/bx_debug/dbg_breakpoints.cc
2022-08-23 21:46:04 +03:00

348 lines
9.8 KiB
C++

/////////////////////////////////////////////////////////////////////////
// $Id$
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2017 The Bochs Project
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
/////////////////////////////////////////////////////////////////////////
#include "bochs.h"
#include "debug.h"
#if BX_DEBUGGER
static unsigned next_bpoint_id = 1;
void bx_dbg_breakpoint_changed(void)
{
#if (BX_DBG_MAX_VIR_BPOINTS > 0)
if (bx_guard.iaddr.num_virtual)
bx_guard.guard_for |= BX_DBG_GUARD_IADDR_VIR;
else
bx_guard.guard_for &= ~BX_DBG_GUARD_IADDR_VIR;
#endif
#if (BX_DBG_MAX_LIN_BPOINTS > 0)
if (bx_guard.iaddr.num_linear)
bx_guard.guard_for |= BX_DBG_GUARD_IADDR_LIN;
else
bx_guard.guard_for &= ~BX_DBG_GUARD_IADDR_LIN;
#endif
#if (BX_DBG_MAX_PHY_BPOINTS > 0)
if (bx_guard.iaddr.num_physical)
bx_guard.guard_for |= BX_DBG_GUARD_IADDR_PHY;
else
bx_guard.guard_for &= ~BX_DBG_GUARD_IADDR_PHY;
#endif
}
void bx_dbg_en_dis_breakpoint_command(unsigned handle, bool enable)
{
#if (BX_DBG_MAX_VIR_BPOINTS > 0)
if (bx_dbg_en_dis_vbreak(handle, enable))
goto done;
#endif
#if (BX_DBG_MAX_LIN_BPOINTS > 0)
if (bx_dbg_en_dis_lbreak(handle, enable))
goto done;
#endif
#if (BX_DBG_MAX_PHY_BPOINTS > 0)
if (bx_dbg_en_dis_pbreak(handle, enable))
goto done;
#endif
dbg_printf("Error: breakpoint %u not found.\n", handle);
return;
done:
bx_dbg_breakpoint_changed();
}
bool bx_dbg_en_dis_pbreak(unsigned handle, bool enable)
{
#if (BX_DBG_MAX_PHY_BPOINTS > 0)
// see if breakpoint is a physical breakpoint
for (unsigned i=0; i<bx_guard.iaddr.num_physical; i++) {
if (bx_guard.iaddr.phy[i].bpoint_id == handle) {
bx_guard.iaddr.phy[i].enabled=enable;
return 1;
}
}
#endif
return 0;
}
bool bx_dbg_en_dis_lbreak(unsigned handle, bool enable)
{
#if (BX_DBG_MAX_LIN_BPOINTS > 0)
// see if breakpoint is a linear breakpoint
for (unsigned i=0; i<bx_guard.iaddr.num_linear; i++) {
if (bx_guard.iaddr.lin[i].bpoint_id == handle) {
bx_guard.iaddr.lin[i].enabled=enable;
return 1;
}
}
#endif
return 0;
}
bool bx_dbg_en_dis_vbreak(unsigned handle, bool enable)
{
#if (BX_DBG_MAX_VIR_BPOINTS > 0)
// see if breakpoint is a virtual breakpoint
for (unsigned i=0; i<bx_guard.iaddr.num_virtual; i++) {
if (bx_guard.iaddr.vir[i].bpoint_id == handle) {
bx_guard.iaddr.vir[i].enabled=enable;
return 1;
}
}
#endif
return 0;
}
void bx_dbg_del_breakpoint_command(unsigned handle)
{
#if (BX_DBG_MAX_VIR_BPOINTS > 0)
if (bx_dbg_del_vbreak(handle))
goto done;
#endif
#if (BX_DBG_MAX_LIN_BPOINTS > 0)
if (bx_dbg_del_lbreak(handle))
goto done;
#endif
#if (BX_DBG_MAX_PHY_BPOINTS > 0)
if (bx_dbg_del_pbreak(handle))
goto done;
#endif
dbg_printf("Error: breakpoint %u not found.\n", handle);
return;
done:
bx_dbg_breakpoint_changed();
}
bool bx_dbg_del_pbreak(unsigned handle)
{
#if (BX_DBG_MAX_PHY_BPOINTS > 0)
// see if breakpoint is a physical breakpoint
for (int i=0; i<(int)bx_guard.iaddr.num_physical; i++) {
if (bx_guard.iaddr.phy[i].bpoint_id == handle) {
// found breakpoint, delete it by shifting remaining entries left
if (bx_guard.iaddr.phy[i].condition) free(bx_guard.iaddr.phy[i].condition);
for (int j=i; j<(int)(bx_guard.iaddr.num_physical-1); j++) {
bx_guard.iaddr.phy[j] = bx_guard.iaddr.phy[j+1];
}
bx_guard.iaddr.num_physical--;
return 1;
}
}
#endif
return 0;
}
bool bx_dbg_del_lbreak(unsigned handle)
{
#if (BX_DBG_MAX_LIN_BPOINTS > 0)
// see if breakpoint is a linear breakpoint
for (int i=0; i<(int)bx_guard.iaddr.num_linear; i++) {
if (bx_guard.iaddr.lin[i].bpoint_id == handle) {
// found breakpoint, delete it by shifting remaining entries left
if (bx_guard.iaddr.lin[i].condition) free(bx_guard.iaddr.lin[i].condition);
for (int j=i; j<(int)(bx_guard.iaddr.num_linear-1); j++) {
bx_guard.iaddr.lin[j] = bx_guard.iaddr.lin[j+1];
}
bx_guard.iaddr.num_linear--;
return 1;
}
}
#endif
return 0;
}
bool bx_dbg_del_vbreak(unsigned handle)
{
#if (BX_DBG_MAX_VIR_BPOINTS > 0)
// see if breakpoint is a virtual breakpoint
for (int i=0; i<(int)bx_guard.iaddr.num_virtual; i++) {
if (bx_guard.iaddr.vir[i].bpoint_id == handle) {
// found breakpoint, delete it by shifting remaining entries left
if (bx_guard.iaddr.vir[i].condition) free(bx_guard.iaddr.vir[i].condition);
for (int j=i; j<(int)(bx_guard.iaddr.num_virtual-1); j++) {
bx_guard.iaddr.vir[j] = bx_guard.iaddr.vir[j+1];
}
bx_guard.iaddr.num_virtual--;
return 1;
}
}
#endif
return 0;
}
static char* prepare_condition(const char *str)
{
if (str == NULL) return NULL;
dbg_printf("condition set: <%s>\n", str);
size_t len = strlen(str);
char *condition = (char*) malloc(len+2);
strcpy(condition, str);
condition[len]='\n';
condition[len+1]='\0';
return condition;
}
int bx_dbg_vbreakpoint_command(BreakpointKind bk, Bit32u cs, bx_address eip, const char *condition)
{
#if (BX_DBG_MAX_VIR_BPOINTS > 0)
if (bk != bkRegular) {
dbg_printf("Error: vbreak of this kind not implemented yet.\n");
return -1;
}
if (bx_guard.iaddr.num_virtual >= BX_DBG_MAX_VIR_BPOINTS) {
dbg_printf("Error: no more virtual breakpoint slots left.\n");
dbg_printf("Error: see BX_DBG_MAX_VIR_BPOINTS.\n");
return -1;
}
struct bx_guard_t::ibreak::vbreak *bp = &bx_guard.iaddr.vir[bx_guard.iaddr.num_virtual];
bp->cs = cs;
bp->eip = eip;
bp->bpoint_id = next_bpoint_id++;
bp->condition = prepare_condition(condition);
bp->enabled=1;
bx_guard.iaddr.num_virtual++;
bx_guard.guard_for |= BX_DBG_GUARD_IADDR_VIR;
return bp->bpoint_id;
#else
dbg_printf("Error: virtual breakpoint support not compiled in.\n");
dbg_printf("Error: make sure BX_DBG_MAX_VIR_BPOINTS > 0\n");
return -1;
#endif
}
int bx_dbg_lbreakpoint_command(BreakpointKind bk, bx_address laddress, const char *condition)
{
#if (BX_DBG_MAX_LIN_BPOINTS > 0)
if (bk == bkAtIP) {
dbg_printf("Error: lbreak of this kind not implemented yet.\n");
return -1;
}
if (bx_guard.iaddr.num_linear >= BX_DBG_MAX_LIN_BPOINTS) {
dbg_printf("Error: no more linear breakpoint slots left.\n");
dbg_printf("Error: see BX_DBG_MAX_LIN_BPOINTS.\n");
return -1;
}
struct bx_guard_t::ibreak::lbreak *bp = &bx_guard.iaddr.lin[bx_guard.iaddr.num_linear];
bp->addr = laddress;
int BpId = (bk == bkStepOver) ? 0 : next_bpoint_id++;
bp->bpoint_id = BpId;
bp->condition = prepare_condition(condition);
bp->enabled=1;
bx_guard.iaddr.num_linear++;
bx_guard.guard_for |= BX_DBG_GUARD_IADDR_LIN;
return BpId;
#else
dbg_printf("Error: linear breakpoint support not compiled in.\n");
dbg_printf("Error: make sure BX_DBG_MAX_LIN_BPOINTS > 0\n");
return -1;
#endif
}
int bx_dbg_pbreakpoint_command(BreakpointKind bk, bx_phy_address paddress, const char *condition)
{
#if (BX_DBG_MAX_PHY_BPOINTS > 0)
if (bk != bkRegular) {
dbg_printf("Error: pbreak of this kind not implemented yet.\n");
return -1;
}
if (bx_guard.iaddr.num_physical >= BX_DBG_MAX_PHY_BPOINTS) {
dbg_printf("Error: no more physical breakpoint slots left.\n");
dbg_printf("Error: see BX_DBG_MAX_PHY_BPOINTS.\n");
return -1;
}
struct bx_guard_t::ibreak::pbreak *bp = &bx_guard.iaddr.phy[bx_guard.iaddr.num_physical];
bp->addr = paddress;
bp->bpoint_id = next_bpoint_id++;
bp->condition = prepare_condition(condition);
bp->enabled=1;
bx_guard.iaddr.num_physical++;
bx_guard.guard_for |= BX_DBG_GUARD_IADDR_PHY;
return bp->bpoint_id;
#else
dbg_printf("Error: physical breakpoint support not compiled in.\n");
dbg_printf("Error: make sure BX_DBG_MAX_PHY_BPOINTS > 0\n");
return -1;
#endif
}
void bx_dbg_info_bpoints_command(void)
{
unsigned i;
// Num Type Disp Enb Address
// 1 breakpoint keep y 0x00010664 condition
dbg_printf("Num Type Disp Enb Address\n");
#if (BX_DBG_MAX_VIR_BPOINTS > 0)
for (i=0; i<bx_guard.iaddr.num_virtual; i++) {
struct bx_guard_t::ibreak::vbreak *bp = &bx_guard.iaddr.vir[i];
dbg_printf("%3u ", bp->bpoint_id);
dbg_printf("vbreakpoint ");
dbg_printf("keep ");
dbg_printf(bp->enabled?"y ":"n ");
dbg_printf("0x%04x:" FMT_ADDRX " %s", bp->cs, bp->eip,
(bp->condition != NULL) ? bp->condition : "\n");
}
#endif
#if (BX_DBG_MAX_LIN_BPOINTS > 0)
for (i=0; i<bx_guard.iaddr.num_linear; i++) {
struct bx_guard_t::ibreak::lbreak *bp = &bx_guard.iaddr.lin[i];
dbg_printf("%3u ", bp->bpoint_id);
dbg_printf("lbreakpoint ");
dbg_printf("keep ");
dbg_printf(bp->enabled?"y ":"n ");
dbg_printf("0x" FMT_ADDRX " %s", bp->addr,
(bp->condition != NULL) ? bp->condition : "\n");
}
#endif
#if (BX_DBG_MAX_PHY_BPOINTS > 0)
for (i=0; i<bx_guard.iaddr.num_physical; i++) {
struct bx_guard_t::ibreak::pbreak *bp = &bx_guard.iaddr.phy[i];
dbg_printf("%3u ", bp->bpoint_id);
dbg_printf("pbreakpoint ");
dbg_printf("keep ");
dbg_printf(bp->enabled?"y ":"n ");
dbg_printf("0x" FMT_PHY_ADDRX " %s", bp->addr,
(bp->condition != NULL) ? bp->condition : "\n");
}
#endif
}
#endif /* if BX_DEBUGGER */