1 /*- 2 * Copyright (c) 2004 Marcel Moolenaar 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #include <sys/cdefs.h> 28 __FBSDID("$FreeBSD$"); 29 30 #include <sys/param.h> 31 #include <sys/systm.h> 32 #include <sys/kdb.h> 33 #include <sys/kernel.h> 34 #include <sys/pcpu.h> 35 #include <sys/proc.h> 36 #include <sys/reboot.h> 37 38 #include <machine/gdb_machdep.h> 39 #include <machine/kdb.h> 40 41 #include <gdb/gdb.h> 42 #include <gdb/gdb_int.h> 43 44 static dbbe_init_f gdb_init; 45 static dbbe_trap_f gdb_trap; 46 47 KDB_BACKEND(gdb, gdb_init, NULL, gdb_trap); 48 49 GDB_DBGPORT(null, NULL, NULL, NULL, NULL, NULL, NULL); 50 SET_DECLARE(gdb_dbgport_set, struct gdb_dbgport); 51 52 struct gdb_dbgport *gdb_cur = NULL; 53 int gdb_listening = 0; 54 55 static int 56 gdb_init(void) 57 { 58 struct gdb_dbgport *dp, **iter; 59 int cur_pri, pri; 60 61 gdb_cur = NULL; 62 cur_pri = -1; 63 SET_FOREACH(iter, gdb_dbgport_set) { 64 dp = *iter; 65 pri = (dp->gdb_probe != NULL) ? dp->gdb_probe() : -1; 66 dp->gdb_active = (pri >= 0) ? 0 : -1; 67 if (pri > cur_pri) { 68 cur_pri = pri; 69 gdb_cur = dp; 70 } 71 } 72 if (gdb_cur != NULL) { 73 printf("GDB: debug ports:"); 74 SET_FOREACH(iter, gdb_dbgport_set) { 75 dp = *iter; 76 if (dp->gdb_active == 0) 77 printf(" %s", dp->gdb_name); 78 } 79 printf("\n"); 80 } else 81 printf("GDB: no debug ports present\n"); 82 if (gdb_cur != NULL) { 83 gdb_cur->gdb_init(); 84 printf("GDB: current port: %s\n", gdb_cur->gdb_name); 85 } 86 if (gdb_cur != NULL) { 87 cur_pri = (boothowto & RB_GDB) ? 2 : 0; 88 gdb_consinit(); 89 } else 90 cur_pri = -1; 91 return (cur_pri); 92 } 93 94 static int 95 gdb_trap(int type, int code) 96 { 97 struct thread *thr_iter; 98 99 gdb_listening = 0; 100 /* 101 * Send a T packet. We currently do not support watchpoints (the 102 * awatch, rwatch or watch elements). 103 */ 104 gdb_tx_begin('T'); 105 gdb_tx_hex(gdb_cpu_signal(type, code), 2); 106 gdb_tx_varhex(GDB_REG_PC); 107 gdb_tx_char(':'); 108 gdb_tx_reg(GDB_REG_PC); 109 gdb_tx_char(';'); 110 gdb_tx_str("thread:"); 111 gdb_tx_varhex((long)kdb_thread->td_tid); 112 gdb_tx_char(';'); 113 gdb_tx_end(); /* XXX check error condition. */ 114 115 thr_iter = NULL; 116 while (gdb_rx_begin() == 0) { 117 /* printf("GDB: got '%s'\n", gdb_rxp); */ 118 switch (gdb_rx_char()) { 119 case '?': /* Last signal. */ 120 gdb_tx_begin('S'); 121 gdb_tx_hex(gdb_cpu_signal(type, code), 2); 122 gdb_tx_end(); 123 break; 124 case 'c': { /* Continue. */ 125 uintmax_t addr; 126 register_t pc; 127 if (!gdb_rx_varhex(&addr)) { 128 pc = addr; 129 gdb_cpu_setreg(GDB_REG_PC, &pc); 130 } 131 kdb_cpu_clear_singlestep(); 132 gdb_listening = 1; 133 return (1); 134 } 135 case 'C': { /* Continue with signal. */ 136 uintmax_t addr, sig; 137 register_t pc; 138 if (!gdb_rx_varhex(&sig) && gdb_rx_char() == ';' && 139 !gdb_rx_varhex(&addr)) { 140 pc = addr; 141 gdb_cpu_setreg(GDB_REG_PC, &pc); 142 } 143 kdb_cpu_clear_singlestep(); 144 gdb_listening = 1; 145 return (1); 146 } 147 case 'g': { /* Read registers. */ 148 size_t r; 149 gdb_tx_begin(0); 150 for (r = 0; r < GDB_NREGS; r++) 151 gdb_tx_reg(r); 152 gdb_tx_end(); 153 break; 154 } 155 case 'G': /* Write registers. */ 156 gdb_tx_err(0); 157 break; 158 case 'H': { /* Set thread. */ 159 intmax_t tid; 160 struct thread *thr; 161 gdb_rx_char(); 162 if (gdb_rx_varhex(&tid)) { 163 gdb_tx_err(EINVAL); 164 break; 165 } 166 if (tid > 0) { 167 thr = kdb_thr_lookup(tid); 168 if (thr == NULL) { 169 gdb_tx_err(ENOENT); 170 break; 171 } 172 kdb_thr_select(thr); 173 } 174 gdb_tx_ok(); 175 break; 176 } 177 case 'k': /* Kill request. */ 178 kdb_cpu_clear_singlestep(); 179 gdb_listening = 1; 180 return (1); 181 case 'm': { /* Read memory. */ 182 uintmax_t addr, size; 183 if (gdb_rx_varhex(&addr) || gdb_rx_char() != ',' || 184 gdb_rx_varhex(&size)) { 185 gdb_tx_err(EINVAL); 186 break; 187 } 188 gdb_tx_begin(0); 189 if (gdb_tx_mem((char *)(uintptr_t)addr, size)) 190 gdb_tx_end(); 191 else 192 gdb_tx_err(EIO); 193 break; 194 } 195 case 'M': { /* Write memory. */ 196 uintmax_t addr, size; 197 if (gdb_rx_varhex(&addr) || gdb_rx_char() != ',' || 198 gdb_rx_varhex(&size) || gdb_rx_char() != ':') { 199 gdb_tx_err(EINVAL); 200 break; 201 } 202 if (gdb_rx_mem((char *)(uintptr_t)addr, size) == 0) 203 gdb_tx_err(EIO); 204 else 205 gdb_tx_ok(); 206 break; 207 } 208 case 'P': { /* Write register. */ 209 char *val; 210 uintmax_t reg; 211 val = gdb_rxp; 212 if (gdb_rx_varhex(®) || gdb_rx_char() != '=' || 213 !gdb_rx_mem(val, gdb_cpu_regsz(reg))) { 214 gdb_tx_err(EINVAL); 215 break; 216 } 217 gdb_cpu_setreg(reg, val); 218 gdb_tx_ok(); 219 break; 220 } 221 case 'q': /* General query. */ 222 if (gdb_rx_equal("fThreadInfo")) { 223 thr_iter = kdb_thr_first(); 224 gdb_tx_begin('m'); 225 gdb_tx_hex((long)thr_iter->td_tid, 8); 226 gdb_tx_end(); 227 } else if (gdb_rx_equal("sThreadInfo")) { 228 if (thr_iter == NULL) { 229 gdb_tx_err(ENXIO); 230 break; 231 } 232 thr_iter = kdb_thr_next(thr_iter); 233 if (thr_iter != NULL) { 234 gdb_tx_begin('m'); 235 gdb_tx_hex((long)thr_iter->td_tid, 8); 236 gdb_tx_end(); 237 } else { 238 gdb_tx_begin('l'); 239 gdb_tx_end(); 240 } 241 } else if (!gdb_cpu_query()) 242 gdb_tx_empty(); 243 break; 244 case 's': { /* Step. */ 245 uintmax_t addr; 246 register_t pc; 247 if (!gdb_rx_varhex(&addr)) { 248 pc = addr; 249 gdb_cpu_setreg(GDB_REG_PC, &pc); 250 } 251 kdb_cpu_set_singlestep(); 252 gdb_listening = 1; 253 return (1); 254 } 255 case 'S': { /* Step with signal. */ 256 uintmax_t addr, sig; 257 register_t pc; 258 if (!gdb_rx_varhex(&sig) && gdb_rx_char() == ';' && 259 !gdb_rx_varhex(&addr)) { 260 pc = addr; 261 gdb_cpu_setreg(GDB_REG_PC, &pc); 262 } 263 kdb_cpu_set_singlestep(); 264 gdb_listening = 1; 265 return (1); 266 } 267 case 'T': { /* Thread alive. */ 268 intmax_t tid; 269 if (gdb_rx_varhex(&tid)) { 270 gdb_tx_err(EINVAL); 271 break; 272 } 273 if (kdb_thr_lookup(tid) != NULL) 274 gdb_tx_ok(); 275 else 276 gdb_tx_err(ENOENT); 277 break; 278 } 279 case -1: 280 /* Empty command. Treat as unknown command. */ 281 /* FALLTHROUGH */ 282 default: 283 /* Unknown command. Send empty response. */ 284 gdb_tx_empty(); 285 break; 286 } 287 } 288 return (0); 289 } 290