VirtualBox

source: vbox/trunk/src/VBox/Debugger/DBGCIoProvTcp.cpp@ 86327

Last change on this file since 86327 was 86327, checked in by vboxsync, 4 years ago

Debugger: Allow for different I/O providers instead of only TCP

So far TCP was the only option to communicate remotely with the internal debugger, the other option
was to use the console from the GUI directly. This commit reworks basic I/O to allow for different
providers where TCP is just one option. The second one being introduced is an IPC provider using a local
socket or named pipe depending on the platform. This allows for Windows kernel debugging over a pipe
using the KD stub in VirtualBox and WinDbg running on the host (not tested yet).

Furthermore this commit allows multiple stubs to be listening for connections at the same time, so
one can have a GDB stub listening on one TCP port and the native VBox debugger listening on another one
or even using a different I/O provider. Only one session can be active at a time though, because sharing
debugger states is impossible. To configure this the following CFGM keys need to be set for each listener:

"DBGC/<Some unique ID>/Provider" "tcp|ipc"
"DBGC/<Some unique ID>/StubType" "native|gdb|kd"
"DBGC/<Some unique ID>/Address" "<ip>|<local named pipe or socket path>"
"DBGC/<Some unique ID>/Port" "<port>" (for TCP only)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.0 KB
Line 
1/* $Id: DBGCIoProvTcp.cpp 86327 2020-09-28 16:20:50Z vboxsync $ */
2/** @file
3 * DBGC - Debugger Console, TCP I/O provider.
4 */
5
6/*
7 * Copyright (C) 2006-2020 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#include <VBox/dbg.h>
23#include <VBox/err.h>
24#include <VBox/log.h>
25
26#include <iprt/mem.h>
27#include <iprt/tcp.h>
28#include <iprt/assert.h>
29
30#include "DBGCIoProvInternal.h"
31
32
33/*********************************************************************************************************************************
34* Structures and Typedefs *
35*********************************************************************************************************************************/
36/**
37 * Debug console TCP connection data.
38 */
39typedef struct DBGCTCPCON
40{
41 /** The I/O callback table for the console. */
42 DBGCIO Io;
43 /** The socket of the connection. */
44 RTSOCKET hSock;
45 /** Connection status. */
46 bool fAlive;
47} DBGCTCPCON;
48/** Pointer to the instance data of the console TCP backend. */
49typedef DBGCTCPCON *PDBGCTCPCON;
50
51
52/*********************************************************************************************************************************
53* Internal Functions *
54*********************************************************************************************************************************/
55
56/**
57 * @interface_method_impl{DBGCIO,pfnDestroy}
58 */
59static DECLCALLBACK(void) dbgcIoProvTcpIoDestroy(PCDBGCIO pIo)
60{
61 PDBGCTCPCON pTcpCon = RT_FROM_MEMBER(pIo, DBGCTCPCON, Io);
62 RTSocketRelease(pTcpCon->hSock);
63 pTcpCon->fAlive =false;
64 RTMemFree(pTcpCon);
65}
66
67
68/**
69 * @interface_method_impl{DBGCIO,pfnInput}
70 */
71static DECLCALLBACK(bool) dbgcIoProvTcpIoInput(PCDBGCIO pIo, uint32_t cMillies)
72{
73 PDBGCTCPCON pTcpCon = RT_FROM_MEMBER(pIo, DBGCTCPCON, Io);
74 if (!pTcpCon->fAlive)
75 return false;
76 int rc = RTTcpSelectOne(pTcpCon->hSock, cMillies);
77 if (RT_FAILURE(rc) && rc != VERR_TIMEOUT)
78 pTcpCon->fAlive = false;
79 return rc != VERR_TIMEOUT;
80}
81
82
83/**
84 * @interface_method_impl{DBGCIO,pfnRead}
85 */
86static DECLCALLBACK(int) dbgcIoProvTcpIoRead(PCDBGCIO pIo, void *pvBuf, size_t cbBuf, size_t *pcbRead)
87{
88 PDBGCTCPCON pTcpCon = RT_FROM_MEMBER(pIo, DBGCTCPCON, Io);
89 if (!pTcpCon->fAlive)
90 return VERR_INVALID_HANDLE;
91 int rc = RTTcpRead(pTcpCon->hSock, pvBuf, cbBuf, pcbRead);
92 if (RT_SUCCESS(rc) && pcbRead != NULL && *pcbRead == 0)
93 rc = VERR_NET_SHUTDOWN;
94 if (RT_FAILURE(rc))
95 pTcpCon->fAlive = false;
96 return rc;
97}
98
99
100/**
101 * @interface_method_impl{DBGCIO,pfnWrite}
102 */
103static DECLCALLBACK(int) dbgcIoProvTcpIoWrite(PCDBGCIO pIo, const void *pvBuf, size_t cbBuf, size_t *pcbWritten)
104{
105 PDBGCTCPCON pTcpCon = RT_FROM_MEMBER(pIo, DBGCTCPCON, Io);
106 if (!pTcpCon->fAlive)
107 return VERR_INVALID_HANDLE;
108
109 int rc = RTTcpWrite(pTcpCon->hSock, pvBuf, cbBuf);
110 if (RT_FAILURE(rc))
111 pTcpCon->fAlive = false;
112
113 if (pcbWritten)
114 *pcbWritten = cbBuf;
115
116 return rc;
117}
118
119
120/**
121 * @interface_method_impl{DBGCIO,pfnSetReady}
122 */
123static DECLCALLBACK(void) dbgcIoProvTcpIoSetReady(PCDBGCIO pIo, bool fReady)
124{
125 /* stub */
126 NOREF(pIo);
127 NOREF(fReady);
128}
129
130
131/**
132 * @interface_method_impl{DBGCIOPROV,pfnCreate}
133 */
134static DECLCALLBACK(int) dbgcIoProvTcpCreate(PDBGCIOPROV phDbgcIoProv, PCFGMNODE pCfg)
135{
136 /*
137 * Get the port configuration.
138 */
139 uint32_t u32Port;
140 int rc = CFGMR3QueryU32Def(pCfg, "Port", &u32Port, 5000);
141 if (RT_FAILURE(rc))
142 {
143 LogRel(("Configuration error: Failed querying \"Port\" -> rc=%Rc\n", rc));
144 return rc;
145 }
146
147 /*
148 * Get the address configuration.
149 */
150 char szAddress[512];
151 rc = CFGMR3QueryStringDef(pCfg, "Address", szAddress, sizeof(szAddress), "");
152 if (RT_FAILURE(rc))
153 {
154 LogRel(("Configuration error: Failed querying \"Address\" -> rc=%Rc\n", rc));
155 return rc;
156 }
157
158 /*
159 * Create the server.
160 */
161 PRTTCPSERVER pServer;
162 rc = RTTcpServerCreateEx(szAddress, u32Port, &pServer);
163 if (RT_SUCCESS(rc))
164 {
165 LogFlow(("dbgcIoProvTcpCreate: Created server on port %d %s\n", u32Port, szAddress));
166 *phDbgcIoProv = (DBGCIOPROV)pServer;
167 return rc;
168 }
169
170 return rc;
171}
172
173
174/**
175 * @interface_method_impl{DBGCIOPROV,pfnDestroy}
176 */
177static DECLCALLBACK(void) dbgcIoProvTcpDestroy(DBGCIOPROV hDbgcIoProv)
178{
179 int rc = RTTcpServerDestroy((PRTTCPSERVER)hDbgcIoProv);
180 AssertRC(rc);
181}
182
183
184/**
185 * @interface_method_impl{DBGCIOPROV,pfnWaitForConnect}
186 */
187static DECLCALLBACK(int) dbgcIoProvTcpWaitForConnect(DBGCIOPROV hDbgcIoProv, RTMSINTERVAL cMsTimeout, PCDBGCIO *ppDbgcIo)
188{
189 PRTTCPSERVER pTcpSrv = (PRTTCPSERVER)hDbgcIoProv;
190 RT_NOREF(cMsTimeout);
191
192 RTSOCKET hSockCon = NIL_RTSOCKET;
193 int rc = RTTcpServerListen2(pTcpSrv, &hSockCon);
194 if (RT_SUCCESS(rc))
195 {
196 PDBGCTCPCON pTcpCon = (PDBGCTCPCON)RTMemAllocZ(sizeof(*pTcpCon));
197 if (RT_LIKELY(pTcpCon))
198 {
199 pTcpCon->Io.pfnDestroy = dbgcIoProvTcpIoDestroy;
200 pTcpCon->Io.pfnInput = dbgcIoProvTcpIoInput;
201 pTcpCon->Io.pfnRead = dbgcIoProvTcpIoRead;
202 pTcpCon->Io.pfnWrite = dbgcIoProvTcpIoWrite;
203 pTcpCon->Io.pfnSetReady = dbgcIoProvTcpIoSetReady;
204 pTcpCon->hSock = hSockCon;
205 pTcpCon->fAlive = true;
206 *ppDbgcIo = &pTcpCon->Io;
207 }
208 else
209 rc = VERR_NO_MEMORY;
210 }
211
212 return rc;
213}
214
215
216/**
217 * @interface_method_impl{DBGCIOPROV,pfnWaitInterrupt}
218 */
219static DECLCALLBACK(int) dbgcIoProvTcpWaitInterrupt(DBGCIOPROV hDbgcIoProv)
220{
221 PRTTCPSERVER pTcpSrv = (PRTTCPSERVER)hDbgcIoProv;
222
223 RT_NOREF(pTcpSrv);
224 /** @todo */
225 return VINF_SUCCESS;
226}
227
228
229/**
230 * TCP I/O provider registration record.
231 */
232const DBGCIOPROVREG g_DbgcIoProvTcp =
233{
234 /** pszName */
235 "tcp",
236 /** pszDesc */
237 "TCP I/O provider.",
238 /** pfnCreate */
239 dbgcIoProvTcpCreate,
240 /** pfnDestroy */
241 dbgcIoProvTcpDestroy,
242 /** pfnWaitForConnect */
243 dbgcIoProvTcpWaitForConnect,
244 /** pfnWaitInterrupt */
245 dbgcIoProvTcpWaitInterrupt
246};
247
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette