VirtualBox

source: vbox/trunk/src/VBox/Debugger/DBGCIoProvIpc.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: 6.8 KB
Line 
1/* $Id: DBGCIoProvIpc.cpp 86327 2020-09-28 16:20:50Z vboxsync $ */
2/** @file
3 * DBGC - Debugger Console, IPC I/O provider.
4 */
5
6/*
7 * Copyright (C) 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/localipc.h>
27#include <iprt/mem.h>
28#include <iprt/assert.h>
29
30#include "DBGCIoProvInternal.h"
31
32
33/*********************************************************************************************************************************
34* Structures and Typedefs *
35*********************************************************************************************************************************/
36/**
37 * Debug console IPC connection data.
38 */
39typedef struct DBGCIPCCON
40{
41 /** The I/O callback table for the console. */
42 DBGCIO Io;
43 /** The socket of the connection. */
44 RTLOCALIPCSESSION hSession;
45 /** Connection status. */
46 bool fAlive;
47} DBGCIPCCON;
48/** Pointer to the instance data of the console IPC backend. */
49typedef DBGCIPCCON *PDBGCIPCCON;
50
51
52/*********************************************************************************************************************************
53* Internal Functions *
54*********************************************************************************************************************************/
55
56/**
57 * @interface_method_impl{DBGCIO,pfnDestroy}
58 */
59static DECLCALLBACK(void) dbgcIoProvIpcIoDestroy(PCDBGCIO pIo)
60{
61 PDBGCIPCCON pIpcCon = RT_FROM_MEMBER(pIo, DBGCIPCCON, Io);
62 RTLocalIpcSessionClose(pIpcCon->hSession);
63 pIpcCon->fAlive =false;
64 RTMemFree(pIpcCon);
65}
66
67
68/**
69 * @interface_method_impl{DBGCIO,pfnInput}
70 */
71static DECLCALLBACK(bool) dbgcIoProvIpcIoInput(PCDBGCIO pIo, uint32_t cMillies)
72{
73 PDBGCIPCCON pIpcCon = RT_FROM_MEMBER(pIo, DBGCIPCCON, Io);
74 if (!pIpcCon->fAlive)
75 return false;
76 int rc = RTLocalIpcSessionWaitForData(pIpcCon->hSession, cMillies);
77 if (RT_FAILURE(rc) && rc != VERR_TIMEOUT)
78 pIpcCon->fAlive = false;
79 return rc != VERR_TIMEOUT;
80}
81
82
83/**
84 * @interface_method_impl{DBGCIO,pfnRead}
85 */
86static DECLCALLBACK(int) dbgcIoProvIpcIoRead(PCDBGCIO pIo, void *pvBuf, size_t cbBuf, size_t *pcbRead)
87{
88 PDBGCIPCCON pIpcCon = RT_FROM_MEMBER(pIo, DBGCIPCCON, Io);
89 if (!pIpcCon->fAlive)
90 return VERR_INVALID_HANDLE;
91 int rc = RTLocalIpcSessionRead(pIpcCon->hSession, pvBuf, cbBuf, pcbRead);
92 if (RT_SUCCESS(rc) && pcbRead != NULL && *pcbRead == 0)
93 rc = VERR_NET_SHUTDOWN;
94 if (RT_FAILURE(rc))
95 pIpcCon->fAlive = false;
96 return rc;
97}
98
99
100/**
101 * @interface_method_impl{DBGCIO,pfnWrite}
102 */
103static DECLCALLBACK(int) dbgcIoProvIpcIoWrite(PCDBGCIO pIo, const void *pvBuf, size_t cbBuf, size_t *pcbWritten)
104{
105 PDBGCIPCCON pIpcCon = RT_FROM_MEMBER(pIo, DBGCIPCCON, Io);
106 if (!pIpcCon->fAlive)
107 return VERR_INVALID_HANDLE;
108
109 int rc = RTLocalIpcSessionWrite(pIpcCon->hSession, pvBuf, cbBuf);
110 if (RT_FAILURE(rc))
111 pIpcCon->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) dbgcIoProvIpcIoSetReady(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) dbgcIoProvIpcCreate(PDBGCIOPROV phDbgcIoProv, PCFGMNODE pCfg)
135{
136 /*
137 * Get the address configuration.
138 */
139 char szAddress[512];
140 int rc = CFGMR3QueryStringDef(pCfg, "Address", szAddress, sizeof(szAddress), "");
141 if (RT_FAILURE(rc))
142 {
143 LogRel(("Configuration error: Failed querying \"Address\" -> rc=%Rc\n", rc));
144 return rc;
145 }
146
147 /*
148 * Create the server.
149 */
150 RTLOCALIPCSERVER hIpcSrv;
151 rc = RTLocalIpcServerCreate(&hIpcSrv, szAddress, RTLOCALIPC_FLAGS_NATIVE_NAME);
152 if (RT_SUCCESS(rc))
153 {
154 LogFlow(("dbgcIoProvIpcCreate: Created server on \"%s\"\n", szAddress));
155 *phDbgcIoProv = (DBGCIOPROV)hIpcSrv;
156 return rc;
157 }
158
159 return rc;
160}
161
162
163/**
164 * @interface_method_impl{DBGCIOPROV,pfnDestroy}
165 */
166static DECLCALLBACK(void) dbgcIoProvIpcDestroy(DBGCIOPROV hDbgcIoProv)
167{
168 int rc = RTLocalIpcServerDestroy((RTLOCALIPCSERVER)hDbgcIoProv);
169 AssertRC(rc);
170}
171
172
173/**
174 * @interface_method_impl{DBGCIOPROV,pfnWaitForConnect}
175 */
176static DECLCALLBACK(int) dbgcIoProvIpcWaitForConnect(DBGCIOPROV hDbgcIoProv, RTMSINTERVAL cMsTimeout, PCDBGCIO *ppDbgcIo)
177{
178 RTLOCALIPCSERVER hIpcSrv = (RTLOCALIPCSERVER)hDbgcIoProv;
179 RT_NOREF(cMsTimeout);
180
181 RTLOCALIPCSESSION hSession = NIL_RTLOCALIPCSESSION;
182 int rc = RTLocalIpcServerListen(hIpcSrv, &hSession);
183 if (RT_SUCCESS(rc))
184 {
185 PDBGCIPCCON pIpcCon = (PDBGCIPCCON)RTMemAllocZ(sizeof(*pIpcCon));
186 if (RT_LIKELY(pIpcCon))
187 {
188 pIpcCon->Io.pfnDestroy = dbgcIoProvIpcIoDestroy;
189 pIpcCon->Io.pfnInput = dbgcIoProvIpcIoInput;
190 pIpcCon->Io.pfnRead = dbgcIoProvIpcIoRead;
191 pIpcCon->Io.pfnWrite = dbgcIoProvIpcIoWrite;
192 pIpcCon->Io.pfnSetReady = dbgcIoProvIpcIoSetReady;
193 pIpcCon->hSession = hSession;
194 pIpcCon->fAlive = true;
195 *ppDbgcIo = &pIpcCon->Io;
196 }
197 else
198 rc = VERR_NO_MEMORY;
199 }
200
201 return rc;
202}
203
204
205/**
206 * @interface_method_impl{DBGCIOPROV,pfnWaitInterrupt}
207 */
208static DECLCALLBACK(int) dbgcIoProvIpcWaitInterrupt(DBGCIOPROV hDbgcIoProv)
209{
210 return RTLocalIpcServerCancel((RTLOCALIPCSERVER)hDbgcIoProv);
211}
212
213
214/**
215 * TCP I/O provider registration record.
216 */
217const DBGCIOPROVREG g_DbgcIoProvIpc =
218{
219 /** pszName */
220 "ipc",
221 /** pszDesc */
222 "IPC I/O provider.",
223 /** pfnCreate */
224 dbgcIoProvIpcCreate,
225 /** pfnDestroy */
226 dbgcIoProvIpcDestroy,
227 /** pfnWaitForConnect */
228 dbgcIoProvIpcWaitForConnect,
229 /** pfnWaitInterrupt */
230 dbgcIoProvIpcWaitInterrupt
231};
232
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