/* * Kernel Debugger Architecture Independent Breakpoint Handler * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * * Copyright (c) 1999-2004 Silicon Graphics, Inc. All Rights Reserved. * Copyright (c) 2009 Wind River Systems, Inc. All Rights Reserved.
*/
diag = kdbgetularg((char *)argv[nextarg],
&len); if (diag) return diag;
if (len > 8) return KDB_BADLENGTH;
bp->bph_length = len;
nextarg++;
}
if ((argc + 1) != nextarg) return KDB_ARGCOUNT;
}
*nextargp = nextarg; return 0;
}
staticint _kdb_bp_remove(kdb_bp_t *bp)
{ int ret = 1; if (!bp->bp_installed) return ret; if (!bp->bp_type)
ret = dbg_remove_sw_break(bp->bp_addr); else
ret = arch_kgdb_ops.remove_hw_breakpoint(bp->bp_addr,
bp->bph_length,
bp->bp_type); if (ret == 0)
bp->bp_installed = 0; return ret;
}
staticint _kdb_bp_install(struct pt_regs *regs, kdb_bp_t *bp)
{ int ret; /* * Install the breakpoint, if it is not already installed.
*/
if (KDB_DEBUG(BP))
kdb_printf("%s: bp_installed %d\n",
__func__, bp->bp_installed); if (!KDB_STATE(SSBPT))
bp->bp_delay = 0; if (bp->bp_installed) return 1; if (bp->bp_delay || (bp->bp_delayed && KDB_STATE(DOING_SS))) { if (KDB_DEBUG(BP))
kdb_printf("%s: delayed bp\n", __func__);
kdb_handle_bp(regs, bp); return 0;
} if (!bp->bp_type)
ret = dbg_set_sw_break(bp->bp_addr); else
ret = arch_kgdb_ops.set_hw_breakpoint(bp->bp_addr,
bp->bph_length,
bp->bp_type); if (ret == 0) {
bp->bp_installed = 1;
} else {
kdb_printf("%s: failed to set breakpoint at 0x%lx\n",
__func__, bp->bp_addr); if (!bp->bp_type) {
kdb_printf("Software breakpoints are unavailable.\n" " Boot the kernel with rodata=off\n" " OR use hw breaks: help bph\n");
} return 1;
} return 0;
}
/* * kdb_bp_install * * Install kdb_breakpoints prior to returning from the * kernel debugger. This allows the kdb_breakpoints to be set * upon functions that are used internally by kdb, such as * printk(). This function is only called once per kdb session.
*/ void kdb_bp_install(struct pt_regs *regs)
{ int i;
for (i = 0; i < KDB_MAXBPT; i++) {
kdb_bp_t *bp = &kdb_breakpoints[i];
if (KDB_DEBUG(BP)) {
kdb_printf("%s: bp %d bp_enabled %d\n",
__func__, i, bp->bp_enabled);
} if (bp->bp_enabled)
_kdb_bp_install(regs, bp);
}
}
/* * kdb_bp_remove * * Remove kdb_breakpoints upon entry to the kernel debugger. * * Parameters: * None. * Outputs: * None. * Returns: * None. * Locking: * None. * Remarks:
*/ void kdb_bp_remove(void)
{ int i;
for (i = KDB_MAXBPT - 1; i >= 0; i--) {
kdb_bp_t *bp = &kdb_breakpoints[i];
if (KDB_DEBUG(BP)) {
kdb_printf("%s: bp %d bp_enabled %d\n",
__func__, i, bp->bp_enabled);
} if (bp->bp_enabled)
_kdb_bp_remove(bp);
}
}
/* * kdb_printbp * * Internal function to format and print a breakpoint entry. * * Parameters: * None. * Outputs: * None. * Returns: * None. * Locking: * None. * Remarks:
*/
staticvoid kdb_printbp(kdb_bp_t *bp, int i)
{
kdb_printf("%s ", kdb_bptype(bp));
kdb_printf("BP #%d at ", i);
kdb_symbol_print(bp->bp_addr, NULL, KDB_SP_DEFAULT);
if (bp->bp_enabled)
kdb_printf("\n is enabled "); else
kdb_printf("\n is disabled");
kdb_printf(" addr at %016lx, hardtype=%d installed=%d\n",
bp->bp_addr, bp->bp_type, bp->bp_installed);
kdb_printf("\n");
}
/* * kdb_bp * * Handle the bp commands. * * [bp|bph] <addr-expression> [DATAR|DATAW] * * Parameters: * argc Count of arguments in argv * argv Space delimited command line arguments * Outputs: * None. * Returns: * Zero for success, a kdb diagnostic if failure. * Locking: * None. * Remarks: * * bp Set breakpoint on all cpus. Only use hardware assist if need. * bph Set breakpoint on all cpus. Force hardware register
*/
staticint kdb_bp(int argc, constchar **argv)
{ int i, bpno;
kdb_bp_t *bp, *bp_check; int diag; char *symname = NULL; long offset = 0ul; int nextarg;
kdb_bp_t template = {0};
if (argc == 0) { /* * Display breakpoint table
*/ for (bpno = 0, bp = kdb_breakpoints; bpno < KDB_MAXBPT;
bpno++, bp++) { if (bp->bp_free) continue;
kdb_printbp(bp, bpno);
}
return 0;
}
nextarg = 1;
diag = kdbgetaddrarg(argc, argv, &nextarg, &template.bp_addr,
&offset, &symname); if (diag) return diag; if (!template.bp_addr) return KDB_BADINT;
/* * This check is redundant (since the breakpoint machinery should * be doing the same check during kdb_bp_install) but gives the * user immediate feedback.
*/
diag = kgdb_validate_break_address(template.bp_addr); if (diag) return diag;
/* * Find an empty bp structure to allocate
*/ for (bpno = 0, bp = kdb_breakpoints; bpno < KDB_MAXBPT; bpno++, bp++) { if (bp->bp_free) break;
}
/* * Check for clashing breakpoints. * * Note, in this design we can't have hardware breakpoints * enabled for both read and write on the same address.
*/ for (i = 0, bp_check = kdb_breakpoints; i < KDB_MAXBPT;
i++, bp_check++) { if (!bp_check->bp_free &&
bp_check->bp_addr == template.bp_addr) {
kdb_printf("You already have a breakpoint at "
kdb_bfd_vma_fmt0 "\n", template.bp_addr); return KDB_DUPBPT;
}
}
template.bp_enabled = 1;
/* * Actually allocate the breakpoint found earlier
*/
*bp = template;
bp->bp_free = 0;
kdb_printbp(bp, bpno);
return 0;
}
/* * kdb_bc * * Handles the 'bc', 'be', and 'bd' commands * * [bd|bc|be] <breakpoint-number> * [bd|bc|be] * * * Parameters: * argc Count of arguments in argv * argv Space delimited command line arguments * Outputs: * None. * Returns: * Zero for success, a kdb diagnostic for failure * Locking: * None. * Remarks:
*/ staticint kdb_bc(int argc, constchar **argv)
{ unsignedlong addr;
kdb_bp_t *bp = NULL; int lowbp = KDB_MAXBPT; int highbp = 0; int done = 0; int i; int diag = 0;
/* * For addresses less than the maximum breakpoint number, * assume that the breakpoint number is desired.
*/ if (addr < KDB_MAXBPT) {
lowbp = highbp = addr;
highbp++;
} else { for (i = 0, bp = kdb_breakpoints; i < KDB_MAXBPT;
i++, bp++) { if (bp->bp_addr == addr) {
lowbp = highbp = i;
highbp++; break;
}
}
}
}
/* * Now operate on the set of breakpoints matching the input * criteria (either '*' for all, or an individual breakpoint).
*/ for (bp = &kdb_breakpoints[lowbp], i = lowbp;
i < highbp;
i++, bp++) { if (bp->bp_free) continue;
done++;
switch (cmd) { case KDBCMD_BC:
bp->bp_enabled = 0;
kdb_printf("Breakpoint %d at "
kdb_bfd_vma_fmt " cleared\n",
i, bp->bp_addr);
bp->bp_addr = 0;
bp->bp_free = 1;
break; case KDBCMD_BE: if (bp->bp_enabled) break;
bp->bp_enabled = 1;
kdb_printf("Breakpoint %d at "
kdb_bfd_vma_fmt " enabled\n",
i, bp->bp_addr);
break; case KDBCMD_BD: if (!bp->bp_enabled) break;
bp->bp_enabled = 0;
kdb_printf("Breakpoint %d at "
kdb_bfd_vma_fmt " disabled\n",
i, bp->bp_addr);
/* * kdb_ss * * Process the 'ss' (Single Step) command. * * ss * * Parameters: * argc Argument count * argv Argument vector * Outputs: * None. * Returns: * KDB_CMD_SS for success, a kdb error if failure. * Locking: * None. * Remarks: * * Set the arch specific option to trigger a debug trap after the next * instruction.
*/
staticint kdb_ss(int argc, constchar **argv)
{ if (argc != 0) return KDB_ARGCOUNT; /* * Set trace flag and go.
*/
KDB_STATE_SET(DOING_SS); return KDB_CMD_SS;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.