]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/gdb/gdb_main.c
Merge branch 'releng/11.3' into releng-CDN/11.3
[FreeBSD/FreeBSD.git] / sys / gdb / gdb_main.c
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, NULL, gdb_trap);
48
49 static struct gdb_dbgport null_gdb_dbgport;
50 DATA_SET(gdb_dbgport_set, null_gdb_dbgport);
51 SET_DECLARE(gdb_dbgport_set, struct gdb_dbgport);
52
53 struct gdb_dbgport *gdb_cur = NULL;
54 int gdb_listening = 0;
55
56 static unsigned char gdb_bindata[64];
57
58 static int
59 gdb_init(void)
60 {
61         struct gdb_dbgport *dp, **iter;
62         int cur_pri, pri;
63
64         gdb_cur = NULL;
65         cur_pri = -1;
66         SET_FOREACH(iter, gdb_dbgport_set) {
67                 dp = *iter;
68                 pri = (dp->gdb_probe != NULL) ? dp->gdb_probe() : -1;
69                 dp->gdb_active = (pri >= 0) ? 0 : -1;
70                 if (pri > cur_pri) {
71                         cur_pri = pri;
72                         gdb_cur = dp;
73                 }
74         }
75         if (gdb_cur != NULL) {
76                 printf("GDB: debug ports:");
77                 SET_FOREACH(iter, gdb_dbgport_set) {
78                         dp = *iter;
79                         if (dp->gdb_active == 0)
80                                 printf(" %s", dp->gdb_name);
81                 }
82                 printf("\n");
83         } else
84                 printf("GDB: no debug ports present\n");
85         if (gdb_cur != NULL) {
86                 gdb_cur->gdb_init();
87                 printf("GDB: current port: %s\n", gdb_cur->gdb_name);
88         }
89         if (gdb_cur != NULL) {
90                 cur_pri = (boothowto & RB_GDB) ? 2 : 0;
91                 gdb_consinit();
92         } else
93                 cur_pri = -1;
94         return (cur_pri);
95 }
96
97 static int
98 gdb_trap(int type, int code)
99 {
100         jmp_buf jb;
101         struct thread *thr_iter;
102         void *prev_jb;
103
104         prev_jb = kdb_jmpbuf(jb);
105         if (setjmp(jb) != 0) {
106                 printf("%s bailing, hopefully back to ddb!\n", __func__);
107                 gdb_listening = 0;
108                 (void)kdb_jmpbuf(prev_jb);
109                 return (1);
110         }
111
112         gdb_listening = 0;
113         /*
114          * Send a T packet. We currently do not support watchpoints (the
115          * awatch, rwatch or watch elements).
116          */
117         gdb_tx_begin('T');
118         gdb_tx_hex(gdb_cpu_signal(type, code), 2);
119         gdb_tx_varhex(GDB_REG_PC);
120         gdb_tx_char(':');
121         gdb_tx_reg(GDB_REG_PC);
122         gdb_tx_char(';');
123         gdb_tx_str("thread:");
124         gdb_tx_varhex((long)kdb_thread->td_tid);
125         gdb_tx_char(';');
126         gdb_tx_end();                   /* XXX check error condition. */
127
128         thr_iter = NULL;
129         while (gdb_rx_begin() == 0) {
130                 /* printf("GDB: got '%s'\n", gdb_rxp); */
131                 switch (gdb_rx_char()) {
132                 case '?':       /* Last signal. */
133                         gdb_tx_begin('S');
134                         gdb_tx_hex(gdb_cpu_signal(type, code), 2);
135                         gdb_tx_end();
136                         break;
137                 case 'c': {     /* Continue. */
138                         uintmax_t addr;
139                         register_t pc;
140                         if (!gdb_rx_varhex(&addr)) {
141                                 pc = addr;
142                                 gdb_cpu_setreg(GDB_REG_PC, &pc);
143                         }
144                         kdb_cpu_clear_singlestep();
145                         gdb_listening = 1;
146                         return (1);
147                 }
148                 case 'C': {     /* Continue with signal. */
149                         uintmax_t addr, sig;
150                         register_t pc;
151                         if (!gdb_rx_varhex(&sig) && gdb_rx_char() == ';' &&
152                             !gdb_rx_varhex(&addr)) {
153                                 pc = addr;
154                                 gdb_cpu_setreg(GDB_REG_PC, &pc);
155                         }
156                         kdb_cpu_clear_singlestep();
157                         gdb_listening = 1;
158                         return (1);
159                 }
160                 case 'D': {     /* Detach */
161                         gdb_tx_ok();
162                         kdb_cpu_clear_singlestep();
163                         return (1);
164                 }
165                 case 'g': {     /* Read registers. */
166                         size_t r;
167                         gdb_tx_begin(0);
168                         for (r = 0; r < GDB_NREGS; r++)
169                                 gdb_tx_reg(r);
170                         gdb_tx_end();
171                         break;
172                 }
173                 case 'G':       /* Write registers. */
174                         gdb_tx_err(0);
175                         break;
176                 case 'H': {     /* Set thread. */
177                         intmax_t tid;
178                         struct thread *thr;
179                         gdb_rx_char();
180                         if (gdb_rx_varhex(&tid)) {
181                                 gdb_tx_err(EINVAL);
182                                 break;
183                         }
184                         if (tid > 0) {
185                                 thr = kdb_thr_lookup(tid);
186                                 if (thr == NULL) {
187                                         gdb_tx_err(ENOENT);
188                                         break;
189                                 }
190                                 kdb_thr_select(thr);
191                         }
192                         gdb_tx_ok();
193                         break;
194                 }
195                 case 'k':       /* Kill request. */
196                         kdb_cpu_clear_singlestep();
197                         gdb_listening = 1;
198                         return (1);
199                 case 'm': {     /* Read memory. */
200                         uintmax_t addr, size;
201                         if (gdb_rx_varhex(&addr) || gdb_rx_char() != ',' ||
202                             gdb_rx_varhex(&size)) {
203                                 gdb_tx_err(EINVAL);
204                                 break;
205                         }
206                         gdb_tx_begin(0);
207                         if (gdb_tx_mem((char *)(uintptr_t)addr, size))
208                                 gdb_tx_end();
209                         else
210                                 gdb_tx_err(EIO);
211                         break;
212                 }
213                 case 'M': {     /* Write memory. */
214                         uintmax_t addr, size;
215                         if (gdb_rx_varhex(&addr) || gdb_rx_char() != ',' ||
216                             gdb_rx_varhex(&size) || gdb_rx_char() != ':') {
217                                 gdb_tx_err(EINVAL);
218                                 break;
219                         }
220                         if (gdb_rx_mem((char *)(uintptr_t)addr, size) == 0)
221                                 gdb_tx_err(EIO);
222                         else
223                                 gdb_tx_ok();
224                         break;
225                 }
226                 case 'P': {     /* Write register. */
227                         char *val;
228                         uintmax_t reg;
229                         val = gdb_rxp;
230                         if (gdb_rx_varhex(&reg) || gdb_rx_char() != '=' ||
231                             !gdb_rx_mem(val, gdb_cpu_regsz(reg))) {
232                                 gdb_tx_err(EINVAL);
233                                 break;
234                         }
235                         gdb_cpu_setreg(reg, val);
236                         gdb_tx_ok();
237                         break;
238                 }
239                 case 'q':       /* General query. */
240                         if (gdb_rx_equal("fThreadInfo")) {
241                                 thr_iter = kdb_thr_first();
242                                 gdb_tx_begin('m');
243                                 gdb_tx_hex((long)thr_iter->td_tid, 8);
244                                 gdb_tx_end();
245                         } else if (gdb_rx_equal("sThreadInfo")) {
246                                 if (thr_iter == NULL) {
247                                         gdb_tx_err(ENXIO);
248                                         break;
249                                 }
250                                 thr_iter = kdb_thr_next(thr_iter);
251                                 if (thr_iter != NULL) {
252                                         gdb_tx_begin('m');
253                                         gdb_tx_hex((long)thr_iter->td_tid, 8);
254                                         gdb_tx_end();
255                                 } else {
256                                         gdb_tx_begin('l');
257                                         gdb_tx_end();
258                                 }
259                         } else if (gdb_rx_equal("Search:memory:")) {
260                                 size_t patlen;
261                                 intmax_t addr, size;
262                                 const unsigned char *found;
263                                 if (gdb_rx_varhex(&addr) || gdb_rx_char() != ';' ||
264                                     gdb_rx_varhex(&size) || gdb_rx_char() != ';' ||
265                                     gdb_rx_bindata(gdb_bindata, sizeof(gdb_bindata), &patlen)) {
266                                         gdb_tx_err(EINVAL);
267                                         break;
268                                 }
269                                 if (gdb_search_mem((char *)(uintptr_t)addr, size, gdb_bindata, patlen, &found)) {
270                                         if (found == 0ULL)
271                                                 gdb_tx_begin('0');
272                                         else {
273                                                 gdb_tx_begin('1');
274                                                 gdb_tx_char(',');
275                                                 gdb_tx_hex((intmax_t)(uintptr_t)found, 8);
276                                         }
277                                         gdb_tx_end();
278                                 } else
279                                         gdb_tx_err(EIO);
280                                 break;
281                         } else if (!gdb_cpu_query())
282                                 gdb_tx_empty();
283                         break;
284                 case 's': {     /* Step. */
285                         uintmax_t addr;
286                         register_t pc;
287                         if (!gdb_rx_varhex(&addr)) {
288                                 pc = addr;
289                                 gdb_cpu_setreg(GDB_REG_PC, &pc);
290                         }
291                         kdb_cpu_set_singlestep();
292                         gdb_listening = 1;
293                         return (1);
294                 }
295                 case 'S': {     /* Step with signal. */
296                         uintmax_t addr, sig;
297                         register_t pc;
298                         if (!gdb_rx_varhex(&sig) && gdb_rx_char() == ';' &&
299                             !gdb_rx_varhex(&addr)) {
300                                 pc = addr;
301                                 gdb_cpu_setreg(GDB_REG_PC, &pc);
302                         }
303                         kdb_cpu_set_singlestep();
304                         gdb_listening = 1;
305                         return (1);
306                 }
307                 case 'T': {     /* Thread alive. */
308                         intmax_t tid;
309                         if (gdb_rx_varhex(&tid)) {
310                                 gdb_tx_err(EINVAL);
311                                 break;
312                         }
313                         if (kdb_thr_lookup(tid) != NULL)
314                                 gdb_tx_ok();
315                         else
316                                 gdb_tx_err(ENOENT);
317                         break;
318                 }
319                 case -1:
320                         /* Empty command. Treat as unknown command. */
321                         /* FALLTHROUGH */
322                 default:
323                         /* Unknown command. Send empty response. */
324                         gdb_tx_empty();
325                         break;
326                 }
327         }
328         (void)kdb_jmpbuf(prev_jb);
329         return (0);
330 }