11import * as DebugAdapter from 'vscode-debugadapter' ;
2+ import * as Net from 'net' ;
23import { DebugSession , InitializedEvent , TerminatedEvent , StoppedEvent , ThreadEvent , OutputEvent , ContinuedEvent , Thread , StackFrame , Scope , Source , Handles } from 'vscode-debugadapter' ;
34import { DebugProtocol } from 'vscode-debugprotocol' ;
45import { Breakpoint , IBackend , Variable , VariableObject , ValuesFormattingMode , MIError } from './backend/backend' ;
@@ -11,6 +12,7 @@ import * as net from "net";
1112import * as os from "os" ;
1213import * as fs from "fs" ;
1314import { SourceFileMap } from "./source_file_map" ;
15+ import { MI2InferiorSession } from "./miinferior"
1416
1517class ExtendedVariable {
1618 constructor ( public name : string , public options : { "arg" : any } ) {
@@ -41,11 +43,12 @@ export class MI2DebugSession extends DebugSession {
4143 protected sourceFileMap : SourceFileMap ;
4244 protected started : boolean ;
4345 protected crashed : boolean ;
44- protected miDebugger : MI2 ;
46+ public miDebugger : MI2 ;
4547 protected commandServer : net . Server ;
4648 protected serverPath : string ;
4749 protected threadGroupPids = new Map < string , string > ( ) ;
4850 protected threadToPid = new Map < number , string > ( ) ;
51+ protected inferiorServers = new Array ( ) ;
4952
5053 public constructor ( debuggerLinesStartAt1 : boolean , isServer : boolean = false ) {
5154 super ( debuggerLinesStartAt1 , isServer ) ;
@@ -185,8 +188,55 @@ export class MI2DebugSession extends DebugSession {
185188 this . sendEvent ( new ThreadEvent ( "exited" , threadId ) ) ;
186189 }
187190
191+ private openInferiorDebugServer ( superiorServer : MI2DebugSession ) {
192+ function randomIntFromInterval ( min : number , max : number ) { // min and max included
193+ return Math . floor ( Math . random ( ) * ( max - min + 1 ) + min ) ;
194+ }
195+
196+ const port = 1337 + randomIntFromInterval ( 1 , 1000 ) ;
197+
198+ console . error ( `waiting for debug protocol on port ${ port } ` ) ;
199+
200+ const server = Net . createServer ( ( socket ) => {
201+ console . error ( '>> accepted connection from client' ) ;
202+ socket . on ( 'end' , ( ) => {
203+ console . error ( '>> client connection closed\n' ) ;
204+ } ) ;
205+ const session = new MI2InferiorSession ( superiorServer ) ;
206+ session . setRunAsServer ( true ) ;
207+ session . start ( socket , socket ) ;
208+ } ) . listen ( port ) ;
209+
210+ this . inferiorServers . push ( server ) ;
211+
212+ return server ;
213+ }
214+
188215 protected threadGroupStartedEvent ( info : MINode ) {
216+ let pid = parseInt ( info . record ( "pid" ) , 10 ) ;
217+
218+ this . miDebugger . log ( "stdout" , "threadGroupStartedEvent" )
219+ this . miDebugger . log ( "stdout" , pid . toString ( ) )
220+
189221 this . threadGroupPids . set ( info . record ( "id" ) , info . record ( "pid" ) ) ;
222+
223+ // If there are more than 1 threadgroups active, start a new debugger session in VSCode
224+ // This makes the UI all fancy with subprocesses and threads etc.
225+ if ( this . threadGroupPids . size > 1 ) {
226+ // Open a new port for the new DebugSession to attach to
227+ const server = this . openInferiorDebugServer ( this ) ;
228+ const serverAddress = ( server . address ( ) as Net . AddressInfo ) . port ;
229+
230+ this . startDebuggingRequest ( {
231+ request : "attach" ,
232+ configuration : {
233+ type : "gdb-inferior" ,
234+ target : info . record ( "pid" ) ,
235+ cwd : "${workspaceRoot}" ,
236+ debugServer : serverAddress
237+ }
238+ } , 1000 , ( ) => { } )
239+ }
190240 }
191241
192242 protected threadGroupExitedEvent ( info : MINode ) {
@@ -212,7 +262,7 @@ export class MI2DebugSession extends DebugSession {
212262 this . quitEvent ( ) ;
213263 }
214264
215- protected override disconnectRequest ( response : DebugProtocol . DisconnectResponse , args : DebugProtocol . DisconnectArguments ) : void {
265+ public override disconnectRequest ( response : DebugProtocol . DisconnectResponse , args : DebugProtocol . DisconnectArguments ) : void {
216266 if ( this . attached )
217267 this . miDebugger . detach ( ) ;
218268 else
@@ -222,7 +272,7 @@ export class MI2DebugSession extends DebugSession {
222272 this . sendResponse ( response ) ;
223273 }
224274
225- protected override async setVariableRequest ( response : DebugProtocol . SetVariableResponse , args : DebugProtocol . SetVariableArguments ) : Promise < void > {
275+ public override async setVariableRequest ( response : DebugProtocol . SetVariableResponse , args : DebugProtocol . SetVariableArguments ) : Promise < void > {
226276 try {
227277 if ( this . useVarObjects ) {
228278 let name = args . name ;
@@ -249,7 +299,7 @@ export class MI2DebugSession extends DebugSession {
249299 }
250300 }
251301
252- protected override setFunctionBreakPointsRequest ( response : DebugProtocol . SetFunctionBreakpointsResponse , args : DebugProtocol . SetFunctionBreakpointsArguments ) : void {
302+ public override setFunctionBreakPointsRequest ( response : DebugProtocol . SetFunctionBreakpointsResponse , args : DebugProtocol . SetFunctionBreakpointsArguments ) : void {
253303 const all : Thenable < [ boolean , Breakpoint ] > [ ] = [ ] ;
254304 args . breakpoints . forEach ( brk => {
255305 all . push ( this . miDebugger . addBreakPoint ( { raw : brk . name , condition : brk . condition , countCondition : brk . hitCondition } ) ) ;
@@ -269,7 +319,7 @@ export class MI2DebugSession extends DebugSession {
269319 } ) ;
270320 }
271321
272- protected override setBreakPointsRequest ( response : DebugProtocol . SetBreakpointsResponse , args : DebugProtocol . SetBreakpointsArguments ) : void {
322+ public override setBreakPointsRequest ( response : DebugProtocol . SetBreakpointsResponse , args : DebugProtocol . SetBreakpointsArguments ) : void {
273323 let path = args . source . path ;
274324 if ( this . isSSH ) {
275325 // convert local path to ssh path
@@ -299,7 +349,7 @@ export class MI2DebugSession extends DebugSession {
299349 } ) ;
300350 }
301351
302- protected override threadsRequest ( response : DebugProtocol . ThreadsResponse ) : void {
352+ public override threadsRequest ( response : DebugProtocol . ThreadsResponse ) : void {
303353 if ( ! this . miDebugger ) {
304354 this . sendResponse ( response ) ;
305355 return ;
@@ -336,7 +386,7 @@ export class MI2DebugSession extends DebugSession {
336386 return [ frameId & 0xffff , frameId >> 16 ] ;
337387 }
338388
339- protected override stackTraceRequest ( response : DebugProtocol . StackTraceResponse , args : DebugProtocol . StackTraceArguments ) : void {
389+ public override stackTraceRequest ( response : DebugProtocol . StackTraceResponse , args : DebugProtocol . StackTraceArguments ) : void {
340390 this . miDebugger . getStack ( args . startFrame , args . levels , args . threadId ) . then ( stack => {
341391 const ret : StackFrame [ ] = [ ] ;
342392 stack . forEach ( element => {
@@ -370,7 +420,7 @@ export class MI2DebugSession extends DebugSession {
370420 } ) ;
371421 }
372422
373- protected override configurationDoneRequest ( response : DebugProtocol . ConfigurationDoneResponse , args : DebugProtocol . ConfigurationDoneArguments ) : void {
423+ public override configurationDoneRequest ( response : DebugProtocol . ConfigurationDoneResponse , args : DebugProtocol . ConfigurationDoneArguments ) : void {
374424 const promises : Thenable < any > [ ] = [ ] ;
375425 let entryPoint : string | undefined = undefined ;
376426 let runToStart : boolean = false ;
@@ -439,7 +489,7 @@ export class MI2DebugSession extends DebugSession {
439489 } ) ;
440490 }
441491
442- protected override scopesRequest ( response : DebugProtocol . ScopesResponse , args : DebugProtocol . ScopesArguments ) : void {
492+ public override scopesRequest ( response : DebugProtocol . ScopesResponse , args : DebugProtocol . ScopesArguments ) : void {
443493 const scopes = new Array < Scope > ( ) ;
444494 const [ threadId , level ] = this . frameIdToThreadAndLevel ( args . frameId ) ;
445495
@@ -466,7 +516,7 @@ export class MI2DebugSession extends DebugSession {
466516 this . sendResponse ( response ) ;
467517 }
468518
469- protected override async variablesRequest ( response : DebugProtocol . VariablesResponse , args : DebugProtocol . VariablesArguments ) : Promise < void > {
519+ public override async variablesRequest ( response : DebugProtocol . VariablesResponse , args : DebugProtocol . VariablesArguments ) : Promise < void > {
470520 const variables : DebugProtocol . Variable [ ] = [ ] ;
471521 const id : VariableScope | string | VariableObject | ExtendedVariable = this . variableHandles . get ( args . variablesReference ) ;
472522
@@ -692,15 +742,15 @@ export class MI2DebugSession extends DebugSession {
692742 }
693743 }
694744
695- protected override pauseRequest ( response : DebugProtocol . PauseResponse , args : DebugProtocol . PauseArguments ) : void {
745+ public override pauseRequest ( response : DebugProtocol . PauseResponse , args : DebugProtocol . PauseArguments ) : void {
696746 this . miDebugger . interrupt ( args . threadId ) . then ( done => {
697747 this . sendResponse ( response ) ;
698748 } , msg => {
699749 this . sendErrorResponse ( response , 3 , `Could not pause: ${ msg } ` ) ;
700750 } ) ;
701751 }
702752
703- protected override reverseContinueRequest ( response : DebugProtocol . ReverseContinueResponse , args : DebugProtocol . ReverseContinueArguments ) : void {
753+ public override reverseContinueRequest ( response : DebugProtocol . ReverseContinueResponse , args : DebugProtocol . ReverseContinueArguments ) : void {
704754 this . miDebugger . continue ( true , args . threadId ) . then ( done => {
705755 if ( ! response . hasOwnProperty ( "body" ) ) {
706756 response . body = Object ( ) ;
@@ -713,7 +763,7 @@ export class MI2DebugSession extends DebugSession {
713763 } ) ;
714764 }
715765
716- protected override continueRequest ( response : DebugProtocol . ContinueResponse , args : DebugProtocol . ContinueArguments ) : void {
766+ public override continueRequest ( response : DebugProtocol . ContinueResponse , args : DebugProtocol . ContinueArguments ) : void {
717767 this . miDebugger . continue ( false , args . threadId ) . then ( done => {
718768 if ( ! response . hasOwnProperty ( "body" ) ) {
719769 response . body = Object ( ) ;
@@ -727,39 +777,39 @@ export class MI2DebugSession extends DebugSession {
727777 } ) ;
728778 }
729779
730- protected override stepBackRequest ( response : DebugProtocol . StepBackResponse , args : DebugProtocol . StepBackArguments ) : void {
780+ public override stepBackRequest ( response : DebugProtocol . StepBackResponse , args : DebugProtocol . StepBackArguments ) : void {
731781 this . miDebugger . step ( true ) . then ( done => {
732782 this . sendResponse ( response ) ;
733783 } , msg => {
734784 this . sendErrorResponse ( response , 4 , `Could not step back: ${ msg } - Try running 'target record-full' before stepping back` ) ;
735785 } ) ;
736786 }
737787
738- protected override stepInRequest ( response : DebugProtocol . StepInResponse , args : DebugProtocol . StepInArguments ) : void {
788+ public override stepInRequest ( response : DebugProtocol . StepInResponse , args : DebugProtocol . StepInArguments ) : void {
739789 this . miDebugger . step ( ) . then ( done => {
740790 this . sendResponse ( response ) ;
741791 } , msg => {
742792 this . sendErrorResponse ( response , 4 , `Could not step in: ${ msg } ` ) ;
743793 } ) ;
744794 }
745795
746- protected override stepOutRequest ( response : DebugProtocol . StepOutResponse , args : DebugProtocol . StepOutArguments ) : void {
796+ public override stepOutRequest ( response : DebugProtocol . StepOutResponse , args : DebugProtocol . StepOutArguments ) : void {
747797 this . miDebugger . stepOut ( ) . then ( done => {
748798 this . sendResponse ( response ) ;
749799 } , msg => {
750800 this . sendErrorResponse ( response , 5 , `Could not step out: ${ msg } ` ) ;
751801 } ) ;
752802 }
753803
754- protected override nextRequest ( response : DebugProtocol . NextResponse , args : DebugProtocol . NextArguments ) : void {
804+ public override nextRequest ( response : DebugProtocol . NextResponse , args : DebugProtocol . NextArguments ) : void {
755805 this . miDebugger . next ( ) . then ( done => {
756806 this . sendResponse ( response ) ;
757807 } , msg => {
758808 this . sendErrorResponse ( response , 6 , `Could not step over: ${ msg } ` ) ;
759809 } ) ;
760810 }
761811
762- protected override evaluateRequest ( response : DebugProtocol . EvaluateResponse , args : DebugProtocol . EvaluateArguments ) : void {
812+ public override evaluateRequest ( response : DebugProtocol . EvaluateResponse , args : DebugProtocol . EvaluateArguments ) : void {
763813 const [ threadId , level ] = this . frameIdToThreadAndLevel ( args . frameId ) ;
764814 if ( args . context === "watch" || args . context === "hover" ) {
765815 this . miDebugger . evalExpression ( args . expression , threadId , level ) . then ( ( res ) => {
@@ -795,7 +845,7 @@ export class MI2DebugSession extends DebugSession {
795845 }
796846 }
797847
798- protected override gotoTargetsRequest ( response : DebugProtocol . GotoTargetsResponse , args : DebugProtocol . GotoTargetsArguments ) : void {
848+ public override gotoTargetsRequest ( response : DebugProtocol . GotoTargetsResponse , args : DebugProtocol . GotoTargetsArguments ) : void {
799849 const path : string = this . isSSH ? this . sourceFileMap . toRemotePath ( args . source . path ) : args . source . path ;
800850 this . miDebugger . goto ( path , args . line ) . then ( done => {
801851 response . body = {
@@ -812,7 +862,7 @@ export class MI2DebugSession extends DebugSession {
812862 } ) ;
813863 }
814864
815- protected override gotoRequest ( response : DebugProtocol . GotoResponse , args : DebugProtocol . GotoArguments ) : void {
865+ public override gotoRequest ( response : DebugProtocol . GotoResponse , args : DebugProtocol . GotoArguments ) : void {
816866 this . sendResponse ( response ) ;
817867 }
818868
0 commit comments