2 * SPDX-License-Identifier: BSD-2-Clause
4 * Copyright (c) 2019 Isilon Systems, LLC.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * FreeBSD subsystem supporting debugging the FreeBSD kernel over the network.
32 * There are three pieces necessary to use NetGDB.
34 * First, a dedicated proxy server must be running to accept connections from
35 * both NetGDB and gdb(1), and pass bidirectional traffic between the two
38 * Second, The NetGDB client is activated much like ordinary 'gdb' and
39 * similarly to 'netdump' in ddb(4). Like other debugnet(4) clients
40 * (netdump(4)), the network interface on the route to the proxy server must be
41 * online and support debugnet(4).
43 * Finally, the remote (k)gdb(1) uses 'target remote <proxy>:<port>' to connect
44 * to the proxy server.
46 * NetGDBv1 speaks the literal GDB remote serial protocol, and uses a 1:1
47 * relationship between GDB packets and plain debugnet packets. There is no
48 * encryption utilized to keep debugging sessions private, so this is only
49 * appropriate for local segments or trusted networks.
52 #include <sys/cdefs.h>
53 __FBSDID("$FreeBSD$");
57 #error "NetGDB cannot be used without DDB at this time"
60 #include <sys/param.h>
63 #include <sys/socket.h>
64 #include <sys/sysctl.h>
65 #include <sys/ttydefaults.h>
67 #include <machine/gdb_machdep.h>
71 #include <ddb/db_command.h>
72 #include <ddb/db_lex.h>
75 #include <net/debugnet.h>
77 #include <net/if_var.h>
78 #include <net/route.h>
81 #include <gdb/gdb_int.h>
82 #include <gdb/netgdb.h>
84 FEATURE(netgdb, "NetGDB support");
85 SYSCTL_NODE(_debug_gdb, OID_AUTO, netgdb, CTLFLAG_RD | CTLFLAG_MPSAFE, NULL,
88 static unsigned netgdb_debug;
89 SYSCTL_UINT(_debug_gdb_netgdb, OID_AUTO, debug, CTLFLAG_RWTUN,
91 "Debug message verbosity (0: off; 1: on)");
93 #define NETGDB_DEBUG(f, ...) do { \
94 if (netgdb_debug > 0) \
95 printf(("%s [%s:%d]: " f), __func__, __FILE__, __LINE__, ## \
99 static void netgdb_fini(void);
102 static char netgdb_rxbuf[GDB_BUFSZ + 16]; /* Some overhead for framing. */
103 static struct sbuf netgdb_rxsb;
104 static ssize_t netgdb_rx_off;
106 static struct debugnet_pcb *netgdb_conn;
107 static struct gdb_dbgport *netgdb_prev_dbgport;
108 static int *netgdb_prev_kdb_inactive;
110 /* TODO(CEM) disable ack mode */
113 * Receive non-TX ACK packets on the client port.
115 * The mbuf chain will have all non-debugnet framing headers removed
116 * (ethernet, inet, udp). It will start with a debugnet_msg_hdr, of
117 * which the header is guaranteed to be contiguous. If m_pullup is
118 * used, the supplied in-out mbuf pointer should be updated
121 * If the handler frees the mbuf chain, it should set the mbuf pointer
122 * to NULL. Otherwise, the debugnet input framework will free the
126 netgdb_rx(struct debugnet_pcb *pcb, struct mbuf **mb)
128 const struct debugnet_msg_hdr *dnh;
130 uint32_t rlen, count;
134 dnh = mtod(m, const void *);
136 if (ntohl(dnh->mh_type) == DEBUGNET_FINISHED) {
137 sbuf_putc(&netgdb_rxsb, CTRL('C'));
141 if (ntohl(dnh->mh_type) != DEBUGNET_DATA) {
142 printf("%s: Got unexpected debugnet message %u\n",
143 __func__, ntohl(dnh->mh_type));
147 rlen = ntohl(dnh->mh_len);
148 #define _SBUF_FREESPACE(s) ((s)->s_size - ((s)->s_len + 1))
149 if (_SBUF_FREESPACE(&netgdb_rxsb) < rlen) {
150 NETGDB_DEBUG("Backpressure: Not ACKing RX of packet that "
151 "would overflow our buffer (%zd/%zd used).\n",
152 netgdb_rxsb.s_len, netgdb_rxsb.s_size);
155 #undef _SBUF_FREESPACE
157 error = debugnet_ack_output(pcb, dnh->mh_seqno);
159 printf("%s: Couldn't ACK rx packet %u; %d\n", __func__,
160 ntohl(dnh->mh_seqno), error);
162 * Sender will re-xmit, and assuming the condition is
163 * transient, we'll process the packet's contentss later.
168 m_adj(m, sizeof(*dnh));
172 * Inlined m_apply -- why isn't there a macro or inline function
175 while (m != NULL && m->m_len == 0)
178 MPASS(m != NULL && m->m_len >= 0);
179 count = min((uint32_t)m->m_len, rlen);
180 (void)sbuf_bcat(&netgdb_rxsb, mtod(m, const void *), count);
187 * The following routines implement a pseudo GDB debugport (an emulated serial
188 * driver that the MI gdb(4) code does I/O with).
192 netgdb_dbg_getc(void)
197 /* Pull bytes off any currently cached packet first. */
198 if (netgdb_rx_off < sbuf_len(&netgdb_rxsb)) {
199 c = netgdb_rxsb.s_buf[netgdb_rx_off];
204 /* Reached EOF? Reuse buffer. */
205 sbuf_clear(&netgdb_rxsb);
208 /* Check for CTRL-C on console/serial, if any. */
209 if (netgdb_prev_dbgport != NULL) {
210 c = netgdb_prev_dbgport->gdb_getc();
215 debugnet_network_poll(netgdb_conn);
218 if (c == CTRL('C')) {
220 /* Caller gdb_getc() will print that we got ^C. */
226 netgdb_dbg_sendpacket(const void *buf, size_t len)
228 struct debugnet_proto_aux aux;
231 MPASS(len <= UINT32_MAX);
234 * GDB packet boundaries matter. debugnet_send() fragments a single
235 * request into many sequential debugnet messages. Mark full packet
236 * length and offset for potential reassembly by the proxy.
238 aux = (struct debugnet_proto_aux) {
242 error = debugnet_send(netgdb_conn, DEBUGNET_DATA, buf, len, &aux);
244 printf("%s: Network error: %d; trying to switch back to ddb.\n",
248 if (kdb_dbbe_select("ddb") != 0)
249 printf("The ddb backend could not be selected.\n");
251 printf("using longjmp, hope it works!\n");
258 /* Just used for + / - GDB-level ACKs. */
260 netgdb_dbg_putc(int i)
265 netgdb_dbg_sendpacket(&c, 1);
269 static struct gdb_dbgport netgdb_gdb_dbgport = {
270 .gdb_name = "netgdb",
271 .gdb_getc = netgdb_dbg_getc,
272 .gdb_putc = netgdb_dbg_putc,
273 .gdb_term = netgdb_fini,
274 .gdb_sendpacket = netgdb_dbg_sendpacket,
275 .gdb_dbfeatures = GDB_DBGP_FEAT_WANTTERM | GDB_DBGP_FEAT_RELIABLE,
281 struct kdb_dbbe *be, **iter;
284 * Force enable GDB. (If no other debugports were registered at boot,
285 * KDB thinks it doesn't exist.)
287 SET_FOREACH(iter, kdb_dbbe_set) {
289 if (strcmp(be->dbbe_name, "gdb") != 0)
291 if (be->dbbe_active == -1) {
292 netgdb_prev_kdb_inactive = &be->dbbe_active;
298 /* Force netgdb debugport. */
299 netgdb_prev_dbgport = gdb_cur;
300 gdb_cur = &netgdb_gdb_dbgport;
302 sbuf_new(&netgdb_rxsb, netgdb_rxbuf, sizeof(netgdb_rxbuf),
311 /* TODO: tear down conn gracefully? */
312 if (netgdb_conn != NULL) {
313 debugnet_free(netgdb_conn);
317 sbuf_delete(&netgdb_rxsb);
319 gdb_cur = netgdb_prev_dbgport;
321 if (netgdb_prev_kdb_inactive != NULL) {
322 *netgdb_prev_kdb_inactive = -1;
323 netgdb_prev_kdb_inactive = NULL;
329 * Usage: netgdb -s <server> [-g <gateway -c <localip> -i <interface>]
331 * Order is not significant.
333 * Currently, this command does not support configuring encryption or
336 DB_COMMAND_FLAGS(netgdb, db_netgdb_cmd, CS_OWN)
338 struct debugnet_ddb_config params;
339 struct debugnet_conn_params dcp;
340 struct debugnet_pcb *pcb;
343 if (!KERNEL_PANICKED()) {
344 /* TODO: This limitation should be removed in future work. */
345 printf("%s: netgdb is currently limited to use only after a "
346 "panic. Sorry.\n", __func__);
350 error = debugnet_parse_ddb_cmd("netgdb", ¶ms);
352 db_printf("Error configuring netgdb: %d\n", error);
357 * Must initialize netgdb_rxsb before debugnet_connect(), because we
358 * might be getting rx handler callbacks from the send->poll path
359 * during debugnet_connect().
363 if (!params.dd_has_client)
364 params.dd_client = INADDR_ANY;
365 if (!params.dd_has_gateway)
366 params.dd_gateway = INADDR_ANY;
368 dcp = (struct debugnet_conn_params) {
369 .dc_ifp = params.dd_ifp,
370 .dc_client = params.dd_client,
371 .dc_server = params.dd_server,
372 .dc_gateway = params.dd_gateway,
373 .dc_herald_port = NETGDB_HERALDPORT,
374 .dc_client_port = NETGDB_CLIENTPORT,
375 .dc_herald_aux2 = NETGDB_PROTO_V1,
376 .dc_rx_handler = netgdb_rx,
379 error = debugnet_connect(&dcp, &pcb);
381 printf("failed to contact netgdb server: %d\n", error);
388 if (kdb_dbbe_select("gdb") != 0) {
389 db_printf("The remote GDB backend could not be selected.\n");
395 * Mark that we are done in ddb(4). Return -> kdb_trap() should
396 * re-enter with the new backend.
398 db_cmd_loop_done = 1;
399 gdb_return_to_ddb = true;
400 db_printf("(detaching GDB will return control to DDB)\n");
402 /* Aspirational, but does not work reliably. */
403 db_printf("(ctrl-c will return control to ddb)\n");