^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * Kernel Debug Core
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Maintainer: Jason Wessel <jason.wessel@windriver.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 2000-2001 VERITAS Software Corporation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (C) 2002-2004 Timesys Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (C) 2003-2004 Amit S. Kale <amitkale@linsyssoft.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Copyright (C) 2004 Pavel Machek <pavel@ucw.cz>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Copyright (C) 2004-2006 Tom Rini <trini@kernel.crashing.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Copyright (C) 2004-2006 LinSysSoft Technologies Pvt. Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Copyright (C) 2005-2009 Wind River Systems, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * Copyright (C) 2007 MontaVista Software, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * Copyright (C) 2008 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * Contributors at various stages not listed above:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * Jason Wessel ( jason.wessel@windriver.com )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * George Anzinger <george@mvista.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * Anurekh Saxena (anurekh.saxena@timesys.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * Lake Stevens Instrument Division (Glenn Engel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * Jim Kingdon, Cygnus Support.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * Original KGDB stub: David Grothe <dave@gcom.com>,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * Tigran Aivazian <tigran@sco.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * This file is licensed under the terms of the GNU General Public License
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * version 2. This program is licensed "as is" without any warranty of any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * kind, whether express or implied.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/sched/signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/kgdb.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <linux/kdb.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <linux/serial_core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <linux/reboot.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <asm/cacheflush.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <asm/unaligned.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include "debug_core.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define KGDB_MAX_THREAD_QUERY 17
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) /* Our I/O buffers. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) static char remcom_in_buffer[BUFMAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) static char remcom_out_buffer[BUFMAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) static int gdbstub_use_prev_in_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) static int gdbstub_prev_in_buf_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) /* Storage for the registers, in GDB format. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) static unsigned long gdb_regs[(NUMREGBYTES +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) sizeof(unsigned long) - 1) /
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) sizeof(unsigned long)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * GDB remote protocol parser:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #ifdef CONFIG_KGDB_KDB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) static int gdbstub_read_wait(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) int ret = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) if (unlikely(gdbstub_use_prev_in_buf)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) if (gdbstub_prev_in_buf_pos < gdbstub_use_prev_in_buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) return remcom_in_buffer[gdbstub_prev_in_buf_pos++];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) gdbstub_use_prev_in_buf = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) /* poll any additional I/O interfaces that are defined */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) while (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) for (i = 0; kdb_poll_funcs[i] != NULL; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) ret = kdb_poll_funcs[i]();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) if (ret > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) static int gdbstub_read_wait(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) int ret = dbg_io_ops->read_char();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) while (ret == NO_POLL_CHAR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) ret = dbg_io_ops->read_char();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) /* scan for the sequence $<data>#<checksum> */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) static void get_packet(char *buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) unsigned char checksum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) unsigned char xmitcsum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) int count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) char ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * Spin and wait around for the start character, ignore all
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * other characters:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) while ((ch = (gdbstub_read_wait())) != '$')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) /* nothing */;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) kgdb_connected = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) checksum = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) xmitcsum = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) * now, read until a # or end of buffer is found:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) while (count < (BUFMAX - 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) ch = gdbstub_read_wait();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) if (ch == '#')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) checksum = checksum + ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) buffer[count] = ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) count = count + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) if (ch == '#') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) xmitcsum = hex_to_bin(gdbstub_read_wait()) << 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) xmitcsum += hex_to_bin(gdbstub_read_wait());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) if (checksum != xmitcsum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) /* failed checksum */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) dbg_io_ops->write_char('-');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) /* successful transfer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) dbg_io_ops->write_char('+');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) if (dbg_io_ops->flush)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) dbg_io_ops->flush();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) buffer[count] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) } while (checksum != xmitcsum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) * Send the packet in buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) * Check for gdb connection if asked for.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) static void put_packet(char *buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) unsigned char checksum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) int count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) char ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) * $<packet info>#<checksum>.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) dbg_io_ops->write_char('$');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) checksum = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) while ((ch = buffer[count])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) dbg_io_ops->write_char(ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) checksum += ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) dbg_io_ops->write_char('#');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) dbg_io_ops->write_char(hex_asc_hi(checksum));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) dbg_io_ops->write_char(hex_asc_lo(checksum));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) if (dbg_io_ops->flush)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) dbg_io_ops->flush();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) /* Now see what we get in reply. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) ch = gdbstub_read_wait();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) if (ch == 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) ch = gdbstub_read_wait();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) /* If we get an ACK, we are done. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) if (ch == '+')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) * If we get the start of another packet, this means
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) * that GDB is attempting to reconnect. We will NAK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) * the packet being sent, and stop trying to send this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) * packet.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) if (ch == '$') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) dbg_io_ops->write_char('-');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) if (dbg_io_ops->flush)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) dbg_io_ops->flush();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) static char gdbmsgbuf[BUFMAX + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) void gdbstub_msg_write(const char *s, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) char *bufptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) int wcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) if (len == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) len = strlen(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) /* 'O'utput */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) gdbmsgbuf[0] = 'O';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) /* Fill and send buffers... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) while (len > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) bufptr = gdbmsgbuf + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) /* Calculate how many this time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) if ((len << 1) > (BUFMAX - 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) wcount = (BUFMAX - 2) >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) wcount = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) /* Pack in hex chars */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) for (i = 0; i < wcount; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) bufptr = hex_byte_pack(bufptr, s[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) *bufptr = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) /* Move up */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) s += wcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) len -= wcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) /* Write packet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) put_packet(gdbmsgbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) * Convert the memory pointed to by mem into hex, placing result in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) * buf. Return a pointer to the last char put in buf (null). May
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) * return an error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) char *kgdb_mem2hex(char *mem, char *buf, int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) char *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) * We use the upper half of buf as an intermediate buffer for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) * raw memory copy. Hex conversion will work against this one.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) tmp = buf + count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) err = copy_from_kernel_nofault(tmp, mem, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) while (count > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) buf = hex_byte_pack(buf, *tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) tmp++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) *buf = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) * Convert the hex array pointed to by buf into binary to be placed in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) * mem. Return a pointer to the character AFTER the last byte
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) * written. May return an error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) int kgdb_hex2mem(char *buf, char *mem, int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) char *tmp_raw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) char *tmp_hex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) * We use the upper half of buf as an intermediate buffer for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) * raw memory that is converted from hex.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) tmp_raw = buf + count * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) tmp_hex = tmp_raw - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) while (tmp_hex >= buf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) tmp_raw--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) *tmp_raw = hex_to_bin(*tmp_hex--);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) *tmp_raw |= hex_to_bin(*tmp_hex--) << 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) return copy_to_kernel_nofault(mem, tmp_raw, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) * While we find nice hex chars, build a long_val.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) * Return number of chars processed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) int kgdb_hex2long(char **ptr, unsigned long *long_val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) int hex_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) int num = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) int negate = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) *long_val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) if (**ptr == '-') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) negate = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) (*ptr)++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) while (**ptr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) hex_val = hex_to_bin(**ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) if (hex_val < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) *long_val = (*long_val << 4) | hex_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) num++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) (*ptr)++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) if (negate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) *long_val = -*long_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) return num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) * Copy the binary array pointed to by buf into mem. Fix $, #, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) * 0x7d escaped with 0x7d. Return -EFAULT on failure or 0 on success.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) * The input buf is overwitten with the result to write to mem.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) static int kgdb_ebin2mem(char *buf, char *mem, int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) int size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) char *c = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) while (count-- > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) c[size] = *buf++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) if (c[size] == 0x7d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) c[size] = *buf++ ^ 0x20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) size++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) return copy_to_kernel_nofault(mem, c, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) #if DBG_MAX_REG_NUM > 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) int idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) char *ptr = (char *)gdb_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) for (i = 0; i < DBG_MAX_REG_NUM; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) dbg_get_reg(i, ptr + idx, regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) idx += dbg_reg_def[i].size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) int idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) char *ptr = (char *)gdb_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) for (i = 0; i < DBG_MAX_REG_NUM; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) dbg_set_reg(i, ptr + idx, regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) idx += dbg_reg_def[i].size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) #endif /* DBG_MAX_REG_NUM > 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) /* Write memory due to an 'M' or 'X' packet. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) static int write_mem_msg(int binary)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) char *ptr = &remcom_in_buffer[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) unsigned long addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) unsigned long length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) if (kgdb_hex2long(&ptr, &addr) > 0 && *(ptr++) == ',' &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) kgdb_hex2long(&ptr, &length) > 0 && *(ptr++) == ':') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) if (binary)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) err = kgdb_ebin2mem(ptr, (char *)addr, length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) err = kgdb_hex2mem(ptr, (char *)addr, length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) if (CACHE_FLUSH_IS_SAFE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) flush_icache_range(addr, addr + length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) static void error_packet(char *pkt, int error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) error = -error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) pkt[0] = 'E';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) pkt[1] = hex_asc[(error / 10)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) pkt[2] = hex_asc[(error % 10)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) pkt[3] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) * Thread ID accessors. We represent a flat TID space to GDB, where
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) * the per CPU idle threads (which under Linux all have PID 0) are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) * remapped to negative TIDs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) #define BUF_THREAD_ID_SIZE 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) static char *pack_threadid(char *pkt, unsigned char *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) unsigned char *limit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) int lzero = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) limit = id + (BUF_THREAD_ID_SIZE / 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) while (id < limit) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) if (!lzero || *id != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) pkt = hex_byte_pack(pkt, *id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) lzero = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) id++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) if (lzero)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) pkt = hex_byte_pack(pkt, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) return pkt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) static void int_to_threadref(unsigned char *id, int value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) put_unaligned_be32(value, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) static struct task_struct *getthread(struct pt_regs *regs, int tid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) * Non-positive TIDs are remapped to the cpu shadow information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) if (tid == 0 || tid == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) tid = -atomic_read(&kgdb_active) - 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) if (tid < -1 && tid > -NR_CPUS - 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) if (kgdb_info[-tid - 2].task)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) return kgdb_info[-tid - 2].task;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) return idle_task(-tid - 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) if (tid <= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) printk(KERN_ERR "KGDB: Internal thread select error\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) dump_stack();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) * find_task_by_pid_ns() does not take the tasklist lock anymore
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) * but is nicely RCU locked - hence is a pretty resilient
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) * thing to use:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) return find_task_by_pid_ns(tid, &init_pid_ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) * Remap normal tasks to their real PID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) * CPU shadow threads are mapped to -CPU - 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) static inline int shadow_pid(int realpid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) if (realpid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) return realpid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) return -raw_smp_processor_id() - 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) * All the functions that start with gdb_cmd are the various
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) * operations to implement the handlers for the gdbserial protocol
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) * where KGDB is communicating with an external debugger
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) /* Handle the '?' status packets */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) static void gdb_cmd_status(struct kgdb_state *ks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) * We know that this packet is only sent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) * during initial connect. So to be safe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) * we clear out our breakpoints now in case
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) * GDB is reconnecting.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) dbg_remove_all_break();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) remcom_out_buffer[0] = 'S';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) hex_byte_pack(&remcom_out_buffer[1], ks->signo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) static void gdb_get_regs_helper(struct kgdb_state *ks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) struct task_struct *thread;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) void *local_debuggerinfo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) thread = kgdb_usethread;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) if (!thread) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) thread = kgdb_info[ks->cpu].task;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) local_debuggerinfo = kgdb_info[ks->cpu].debuggerinfo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) local_debuggerinfo = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) for_each_online_cpu(i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) * Try to find the task on some other
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) * or possibly this node if we do not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) * find the matching task then we try
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) * to approximate the results.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) if (thread == kgdb_info[i].task)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) local_debuggerinfo = kgdb_info[i].debuggerinfo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) * All threads that don't have debuggerinfo should be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) * in schedule() sleeping, since all other CPUs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) * are in kgdb_wait, and thus have debuggerinfo.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) if (local_debuggerinfo) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) pt_regs_to_gdb_regs(gdb_regs, local_debuggerinfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) * Pull stuff saved during switch_to; nothing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) * else is accessible (or even particularly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) * relevant).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) * This should be enough for a stack trace.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) sleeping_thread_to_gdb_regs(gdb_regs, thread);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) /* Handle the 'g' get registers request */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) static void gdb_cmd_getregs(struct kgdb_state *ks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) gdb_get_regs_helper(ks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) kgdb_mem2hex((char *)gdb_regs, remcom_out_buffer, NUMREGBYTES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) /* Handle the 'G' set registers request */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) static void gdb_cmd_setregs(struct kgdb_state *ks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) kgdb_hex2mem(&remcom_in_buffer[1], (char *)gdb_regs, NUMREGBYTES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) if (kgdb_usethread && kgdb_usethread != current) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) error_packet(remcom_out_buffer, -EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) gdb_regs_to_pt_regs(gdb_regs, ks->linux_regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) strcpy(remcom_out_buffer, "OK");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) /* Handle the 'm' memory read bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) static void gdb_cmd_memread(struct kgdb_state *ks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) char *ptr = &remcom_in_buffer[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) unsigned long length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) unsigned long addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) char *err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) if (kgdb_hex2long(&ptr, &addr) > 0 && *ptr++ == ',' &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) kgdb_hex2long(&ptr, &length) > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) err = kgdb_mem2hex((char *)addr, remcom_out_buffer, length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) if (!err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) error_packet(remcom_out_buffer, -EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) error_packet(remcom_out_buffer, -EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) /* Handle the 'M' memory write bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) static void gdb_cmd_memwrite(struct kgdb_state *ks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) int err = write_mem_msg(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) error_packet(remcom_out_buffer, err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) strcpy(remcom_out_buffer, "OK");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) #if DBG_MAX_REG_NUM > 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) static char *gdb_hex_reg_helper(int regnum, char *out)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) int offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) for (i = 0; i < regnum; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) offset += dbg_reg_def[i].size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) return kgdb_mem2hex((char *)gdb_regs + offset, out,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) dbg_reg_def[i].size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) /* Handle the 'p' individual regster get */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) static void gdb_cmd_reg_get(struct kgdb_state *ks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) unsigned long regnum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) char *ptr = &remcom_in_buffer[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) kgdb_hex2long(&ptr, ®num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) if (regnum >= DBG_MAX_REG_NUM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) error_packet(remcom_out_buffer, -EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) gdb_get_regs_helper(ks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) gdb_hex_reg_helper(regnum, remcom_out_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) /* Handle the 'P' individual regster set */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) static void gdb_cmd_reg_set(struct kgdb_state *ks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) unsigned long regnum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) char *ptr = &remcom_in_buffer[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) kgdb_hex2long(&ptr, ®num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) if (*ptr++ != '=' ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) !(!kgdb_usethread || kgdb_usethread == current) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) !dbg_get_reg(regnum, gdb_regs, ks->linux_regs)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) error_packet(remcom_out_buffer, -EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) memset(gdb_regs, 0, sizeof(gdb_regs));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) while (i < sizeof(gdb_regs) * 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) if (hex_to_bin(ptr[i]) >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) i = i / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) kgdb_hex2mem(ptr, (char *)gdb_regs, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) dbg_set_reg(regnum, gdb_regs, ks->linux_regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) strcpy(remcom_out_buffer, "OK");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) #endif /* DBG_MAX_REG_NUM > 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) /* Handle the 'X' memory binary write bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) static void gdb_cmd_binwrite(struct kgdb_state *ks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) int err = write_mem_msg(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) error_packet(remcom_out_buffer, err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) strcpy(remcom_out_buffer, "OK");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) /* Handle the 'D' or 'k', detach or kill packets */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) static void gdb_cmd_detachkill(struct kgdb_state *ks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) /* The detach case */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) if (remcom_in_buffer[0] == 'D') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) error = dbg_remove_all_break();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) if (error < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) error_packet(remcom_out_buffer, error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) strcpy(remcom_out_buffer, "OK");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) kgdb_connected = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) put_packet(remcom_out_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) * Assume the kill case, with no exit code checking,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) * trying to force detach the debugger:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) dbg_remove_all_break();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) kgdb_connected = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) /* Handle the 'R' reboot packets */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) static int gdb_cmd_reboot(struct kgdb_state *ks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) /* For now, only honor R0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) if (strcmp(remcom_in_buffer, "R0") == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) printk(KERN_CRIT "Executing emergency reboot\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) strcpy(remcom_out_buffer, "OK");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) put_packet(remcom_out_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) * Execution should not return from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) * machine_emergency_restart()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) machine_emergency_restart();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) kgdb_connected = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) /* Handle the 'q' query packets */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) static void gdb_cmd_query(struct kgdb_state *ks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) struct task_struct *g;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) struct task_struct *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) unsigned char thref[BUF_THREAD_ID_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) char *ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) int cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) int finished = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) switch (remcom_in_buffer[1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) case 's':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) case 'f':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) if (memcmp(remcom_in_buffer + 2, "ThreadInfo", 10))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) remcom_out_buffer[0] = 'm';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) ptr = remcom_out_buffer + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) if (remcom_in_buffer[1] == 'f') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) /* Each cpu is a shadow thread */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) for_each_online_cpu(cpu) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) ks->thr_query = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) int_to_threadref(thref, -cpu - 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) ptr = pack_threadid(ptr, thref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) *(ptr++) = ',';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) for_each_process_thread(g, p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) if (i >= ks->thr_query && !finished) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) int_to_threadref(thref, p->pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) ptr = pack_threadid(ptr, thref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) *(ptr++) = ',';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) ks->thr_query++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) if (ks->thr_query % KGDB_MAX_THREAD_QUERY == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) finished = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) *(--ptr) = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) case 'C':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) /* Current thread id */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) strcpy(remcom_out_buffer, "QC");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) ks->threadid = shadow_pid(current->pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) int_to_threadref(thref, ks->threadid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) pack_threadid(remcom_out_buffer + 2, thref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) case 'T':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) if (memcmp(remcom_in_buffer + 1, "ThreadExtraInfo,", 16))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) ks->threadid = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) ptr = remcom_in_buffer + 17;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) kgdb_hex2long(&ptr, &ks->threadid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) if (!getthread(ks->linux_regs, ks->threadid)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) error_packet(remcom_out_buffer, -EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) if ((int)ks->threadid > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) kgdb_mem2hex(getthread(ks->linux_regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) ks->threadid)->comm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) remcom_out_buffer, 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) static char tmpstr[23 + BUF_THREAD_ID_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) sprintf(tmpstr, "shadowCPU%d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) (int)(-ks->threadid - 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) kgdb_mem2hex(tmpstr, remcom_out_buffer, strlen(tmpstr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) #ifdef CONFIG_KGDB_KDB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) case 'R':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) if (strncmp(remcom_in_buffer, "qRcmd,", 6) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) int len = strlen(remcom_in_buffer + 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) if ((len % 2) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) strcpy(remcom_out_buffer, "E01");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) kgdb_hex2mem(remcom_in_buffer + 6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) remcom_out_buffer, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) len = len / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) remcom_out_buffer[len++] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) kdb_common_init_state(ks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) kdb_parse(remcom_out_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) kdb_common_deinit_state();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) strcpy(remcom_out_buffer, "OK");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) #ifdef CONFIG_HAVE_ARCH_KGDB_QXFER_PKT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) case 'S':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) if (!strncmp(remcom_in_buffer, "qSupported:", 11))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) strcpy(remcom_out_buffer, kgdb_arch_gdb_stub_feature);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) case 'X':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) if (!strncmp(remcom_in_buffer, "qXfer:", 6))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) kgdb_arch_handle_qxfer_pkt(remcom_in_buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) remcom_out_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) /* Handle the 'H' task query packets */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) static void gdb_cmd_task(struct kgdb_state *ks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) struct task_struct *thread;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) char *ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) switch (remcom_in_buffer[1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) case 'g':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) ptr = &remcom_in_buffer[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) kgdb_hex2long(&ptr, &ks->threadid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) thread = getthread(ks->linux_regs, ks->threadid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) if (!thread && ks->threadid > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) error_packet(remcom_out_buffer, -EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) kgdb_usethread = thread;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) ks->kgdb_usethreadid = ks->threadid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) strcpy(remcom_out_buffer, "OK");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) case 'c':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) ptr = &remcom_in_buffer[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) kgdb_hex2long(&ptr, &ks->threadid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) if (!ks->threadid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) kgdb_contthread = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) thread = getthread(ks->linux_regs, ks->threadid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) if (!thread && ks->threadid > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) error_packet(remcom_out_buffer, -EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) kgdb_contthread = thread;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) strcpy(remcom_out_buffer, "OK");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) /* Handle the 'T' thread query packets */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) static void gdb_cmd_thread(struct kgdb_state *ks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) char *ptr = &remcom_in_buffer[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) struct task_struct *thread;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) kgdb_hex2long(&ptr, &ks->threadid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) thread = getthread(ks->linux_regs, ks->threadid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) if (thread)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) strcpy(remcom_out_buffer, "OK");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) error_packet(remcom_out_buffer, -EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) /* Handle the 'z' or 'Z' breakpoint remove or set packets */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) static void gdb_cmd_break(struct kgdb_state *ks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) * Since GDB-5.3, it's been drafted that '0' is a software
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) * breakpoint, '1' is a hardware breakpoint, so let's do that.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) char *bpt_type = &remcom_in_buffer[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) char *ptr = &remcom_in_buffer[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) unsigned long addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) unsigned long length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) int error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) if (arch_kgdb_ops.set_hw_breakpoint && *bpt_type >= '1') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) /* Unsupported */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) if (*bpt_type > '4')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) if (*bpt_type != '0' && *bpt_type != '1')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) /* Unsupported. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) * Test if this is a hardware breakpoint, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) * if we support it:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) if (*bpt_type == '1' && !(arch_kgdb_ops.flags & KGDB_HW_BREAKPOINT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) /* Unsupported. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) if (*(ptr++) != ',') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) error_packet(remcom_out_buffer, -EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) if (!kgdb_hex2long(&ptr, &addr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) error_packet(remcom_out_buffer, -EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) if (*(ptr++) != ',' ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) !kgdb_hex2long(&ptr, &length)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) error_packet(remcom_out_buffer, -EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) if (remcom_in_buffer[0] == 'Z' && *bpt_type == '0')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) error = dbg_set_sw_break(addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) else if (remcom_in_buffer[0] == 'z' && *bpt_type == '0')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) error = dbg_remove_sw_break(addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) else if (remcom_in_buffer[0] == 'Z')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) error = arch_kgdb_ops.set_hw_breakpoint(addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) (int)length, *bpt_type - '0');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) else if (remcom_in_buffer[0] == 'z')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) error = arch_kgdb_ops.remove_hw_breakpoint(addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) (int) length, *bpt_type - '0');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) if (error == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) strcpy(remcom_out_buffer, "OK");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) error_packet(remcom_out_buffer, error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) /* Handle the 'C' signal / exception passing packets */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) static int gdb_cmd_exception_pass(struct kgdb_state *ks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) /* C09 == pass exception
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) * C15 == detach kgdb, pass exception
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) if (remcom_in_buffer[1] == '0' && remcom_in_buffer[2] == '9') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) ks->pass_exception = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) remcom_in_buffer[0] = 'c';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) } else if (remcom_in_buffer[1] == '1' && remcom_in_buffer[2] == '5') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) ks->pass_exception = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) remcom_in_buffer[0] = 'D';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) dbg_remove_all_break();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) kgdb_connected = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) gdbstub_msg_write("KGDB only knows signal 9 (pass)"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) " and 15 (pass and disconnect)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) "Executing a continue without signal passing\n", 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) remcom_in_buffer[0] = 'c';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) /* Indicate fall through */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) * This function performs all gdbserial command procesing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) int gdb_serial_stub(struct kgdb_state *ks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) int error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) int tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) /* Initialize comm buffer and globals. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) memset(remcom_out_buffer, 0, sizeof(remcom_out_buffer));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) kgdb_usethread = kgdb_info[ks->cpu].task;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) ks->kgdb_usethreadid = shadow_pid(kgdb_info[ks->cpu].task->pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) ks->pass_exception = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) if (kgdb_connected) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) unsigned char thref[BUF_THREAD_ID_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) char *ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) /* Reply to host that an exception has occurred */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) ptr = remcom_out_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) *ptr++ = 'T';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) ptr = hex_byte_pack(ptr, ks->signo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) ptr += strlen(strcpy(ptr, "thread:"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) int_to_threadref(thref, shadow_pid(current->pid));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) ptr = pack_threadid(ptr, thref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) *ptr++ = ';';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) put_packet(remcom_out_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) /* Clear the out buffer. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) memset(remcom_out_buffer, 0, sizeof(remcom_out_buffer));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) get_packet(remcom_in_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) switch (remcom_in_buffer[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) case '?': /* gdbserial status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) gdb_cmd_status(ks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) case 'g': /* return the value of the CPU registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) gdb_cmd_getregs(ks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) case 'G': /* set the value of the CPU registers - return OK */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) gdb_cmd_setregs(ks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) gdb_cmd_memread(ks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA..AA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) gdb_cmd_memwrite(ks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) #if DBG_MAX_REG_NUM > 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) case 'p': /* pXX Return gdb register XX (in hex) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) gdb_cmd_reg_get(ks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) case 'P': /* PXX=aaaa Set gdb register XX to aaaa (in hex) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) gdb_cmd_reg_set(ks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) #endif /* DBG_MAX_REG_NUM > 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) case 'X': /* XAA..AA,LLLL: Write LLLL bytes at address AA..AA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) gdb_cmd_binwrite(ks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) /* kill or detach. KGDB should treat this like a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) * continue.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) case 'D': /* Debugger detach */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) case 'k': /* Debugger detach via kill */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) gdb_cmd_detachkill(ks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) goto default_handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) case 'R': /* Reboot */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) if (gdb_cmd_reboot(ks))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) goto default_handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) case 'q': /* query command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) gdb_cmd_query(ks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) case 'H': /* task related */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) gdb_cmd_task(ks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) case 'T': /* Query thread status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) gdb_cmd_thread(ks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) case 'z': /* Break point remove */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) case 'Z': /* Break point set */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) gdb_cmd_break(ks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) #ifdef CONFIG_KGDB_KDB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) case '3': /* Escape into back into kdb */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) if (remcom_in_buffer[1] == '\0') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) gdb_cmd_detachkill(ks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) return DBG_PASS_EVENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) case 'C': /* Exception passing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) tmp = gdb_cmd_exception_pass(ks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) if (tmp > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) goto default_handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) if (tmp == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) fallthrough; /* on tmp < 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) case 'c': /* Continue packet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) case 's': /* Single step packet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) if (kgdb_contthread && kgdb_contthread != current) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) /* Can't switch threads in kgdb */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) error_packet(remcom_out_buffer, -EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) fallthrough; /* to default processing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) default_handle:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) error = kgdb_arch_handle_exception(ks->ex_vector,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) ks->signo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) ks->err_code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) remcom_in_buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) remcom_out_buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) ks->linux_regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) * Leave cmd processing on error, detach,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) * kill, continue, or single step.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) if (error >= 0 || remcom_in_buffer[0] == 'D' ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) remcom_in_buffer[0] == 'k') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) goto kgdb_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) /* reply to the request */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) put_packet(remcom_out_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) kgdb_exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) if (ks->pass_exception)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) error = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) int gdbstub_state(struct kgdb_state *ks, char *cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) switch (cmd[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) case 'e':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) error = kgdb_arch_handle_exception(ks->ex_vector,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) ks->signo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) ks->err_code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) remcom_in_buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) remcom_out_buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) ks->linux_regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) case 's':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) case 'c':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) strscpy(remcom_in_buffer, cmd, sizeof(remcom_in_buffer));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) case '$':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) strscpy(remcom_in_buffer, cmd, sizeof(remcom_in_buffer));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) gdbstub_use_prev_in_buf = strlen(remcom_in_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) gdbstub_prev_in_buf_pos = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) dbg_io_ops->write_char('+');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) put_packet(remcom_out_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) * gdbstub_exit - Send an exit message to GDB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) * @status: The exit code to report.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) void gdbstub_exit(int status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) unsigned char checksum, ch, buffer[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) int loop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) if (!kgdb_connected)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) kgdb_connected = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) if (!dbg_io_ops || dbg_kdb_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) buffer[0] = 'W';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) buffer[1] = hex_asc_hi(status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) buffer[2] = hex_asc_lo(status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) dbg_io_ops->write_char('$');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) checksum = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) for (loop = 0; loop < 3; loop++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) ch = buffer[loop];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) checksum += ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) dbg_io_ops->write_char(ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) dbg_io_ops->write_char('#');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) dbg_io_ops->write_char(hex_asc_hi(checksum));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) dbg_io_ops->write_char(hex_asc_lo(checksum));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) /* make sure the output is flushed, lest the bootloader clobber it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) if (dbg_io_ops->flush)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) dbg_io_ops->flush();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) }