@@ -98,6 +98,7 @@ enum SessionMode {
9898 RESET = 'reset'
9999}
100100
101+ const VarNotFoundMsg = 'Variable object not found' ;
101102export class ExtendedVariable {
102103 constructor ( public name , public options ) {
103104 }
@@ -2631,58 +2632,64 @@ export class GDBDebugSession extends LoggingDebugSession {
26312632 threadId : number , frameId : number , isFloating : boolean ) : Promise < DebugProtocol . Variable > {
26322633 try {
26332634 let varObj : VariableObject ;
2634- let outOfScope = false ;
2635- try {
2636- const changes = await this . miDebugger . varUpdate ( gdbVarName , threadId , frameId ) ;
2637- const changelist = changes . result ( 'changelist' ) ;
2638- for ( const change of changelist || [ ] ) {
2639- const inScope = MINode . valueOf ( change , 'in_scope' ) ;
2640- if ( inScope === 'true' ) {
2641- const name = MINode . valueOf ( change , 'name' ) ;
2642- const vId = this . variableHandlesReverse [ name ] ;
2643- const v = this . variableHandles . get ( vId ) as any ;
2644- v . applyChanges ( change /*, variable.valueStr*/ ) ;
2645- } else {
2646- const msg = `${ symOrExpr } currently not in scope` ;
2647- await this . miDebugger . sendCommand ( `var-delete ${ gdbVarName } ` ) ;
2648- if ( this . args . showDevDebugOutput ) {
2649- this . handleMsg ( 'log' , `Expression ${ msg } . Will try to create again\n` ) ;
2650- }
2651- outOfScope = true ;
2652- throw new Error ( msg ) ;
2653- }
2654- }
2655- const varId = this . variableHandlesReverse [ gdbVarName ] ;
2656- varObj = this . variableHandles . get ( varId ) as any ;
2657- }
2658- catch ( err ) {
2635+ let varId = this . variableHandlesReverse [ gdbVarName ] ;
2636+ let createNewVar = varId === undefined ;
2637+ let updateError = undefined ;
2638+ if ( ! createNewVar ) {
26592639 try {
2660- if ( outOfScope || ( err instanceof MIError && err . message === 'Variable object not found' ) ) {
2661- // Create variable in current frame/thread context. Matters when we have to set the variable */
2662- if ( isFloating ) {
2663- varObj = await this . miDebugger . varCreate ( parentVarReference , symOrExpr , gdbVarName ) ;
2640+ const changes = await this . miDebugger . varUpdate ( gdbVarName , threadId , frameId ) ;
2641+ const changelist = changes . result ( 'changelist' ) ;
2642+ for ( const change of changelist || [ ] ) {
2643+ const inScope = MINode . valueOf ( change , 'in_scope' ) ;
2644+ if ( inScope === 'true' ) {
2645+ const name = MINode . valueOf ( change , 'name' ) ;
2646+ const vId = this . variableHandlesReverse [ name ] ;
2647+ const v = this . variableHandles . get ( vId ) as any ;
2648+ v . applyChanges ( change /*, variable.valueStr*/ ) ;
26642649 } else {
2665- varObj = await this . miDebugger . varCreate ( parentVarReference , symOrExpr , gdbVarName , '@' , threadId , frameId ) ;
2650+ const msg = `${ symOrExpr } currently not in scope` ;
2651+ await this . miDebugger . sendCommand ( `var-delete ${ gdbVarName } ` ) ;
2652+ if ( this . args . showDevDebugOutput ) {
2653+ this . handleMsg ( 'log' , `Expression ${ msg } . Will try to create again\n` ) ;
2654+ }
2655+ createNewVar = true ;
2656+ throw new Error ( msg ) ;
26662657 }
2667- const varId = this . findOrCreateVariable ( varObj ) ;
2668- varObj . exp = symOrExpr ;
2669- varObj . id = varId ;
2670- } else if ( isFloating ) {
2671- throw err ;
26722658 }
2659+ varObj = this . variableHandles . get ( varId ) as any ;
26732660 }
26742661 catch ( err ) {
2662+ updateError = err ;
2663+ }
2664+ }
2665+
2666+ try {
2667+ if ( createNewVar || ( updateError instanceof MIError && updateError . message === VarNotFoundMsg ) ) {
2668+ // Create variable in current frame/thread context. Matters when we have to set the variable
26752669 if ( isFloating ) {
2676- if ( this . args . showDevDebugOutput ) {
2677- this . handleMsg ( 'stderr' , `Could not create global/static variable ${ symOrExpr } \n` ) ;
2678- this . handleMsg ( 'stderr' , `Error: ${ err } \n` ) ;
2679- }
2680- varObj = null ;
2670+ varObj = await this . miDebugger . varCreate ( parentVarReference , symOrExpr , gdbVarName , '@' ) ;
26812671 } else {
2682- throw err ;
2672+ varObj = await this . miDebugger . varCreate ( parentVarReference , symOrExpr , gdbVarName , '@' , threadId , frameId ) ;
2673+ }
2674+ varId = this . findOrCreateVariable ( varObj ) ;
2675+ varObj . exp = symOrExpr ;
2676+ varObj . id = varId ;
2677+ } else if ( ! varObj ) {
2678+ throw updateError || new Error ( 'updateOrCreateVariable: unknown error' ) ;
2679+ }
2680+ }
2681+ catch ( err ) {
2682+ if ( isFloating ) {
2683+ if ( this . args . showDevDebugOutput ) {
2684+ this . handleMsg ( 'stderr' , `Could not create global/static variable ${ symOrExpr } \n` ) ;
2685+ this . handleMsg ( 'stderr' , `Error: ${ err } \n` ) ;
26832686 }
2687+ varObj = null ;
2688+ } else {
2689+ throw err ;
26842690 }
26852691 }
2692+
26862693 if ( isFloating && varObj ) {
26872694 this . putFloatingVariable ( parentVarReference , symOrExpr , varObj ) ;
26882695 }
@@ -3181,54 +3188,52 @@ export class GDBDebugSession extends LoggingDebugSession {
31813188 const exprName = hasher . digest ( 'hex' ) ;
31823189 const varObjName = `${ args . context } _${ exprName } ` ;
31833190 let varObj : VariableObject ;
3184- let outOfScope = false ;
3185- try {
3186- const changes = await this . miDebugger . varUpdate ( varObjName , threadId , frameId ) ;
3187- const changelist = changes . result ( 'changelist' ) ;
3188- for ( const change of changelist || [ ] ) {
3189- const inScope = MINode . valueOf ( change , 'in_scope' ) ;
3190- if ( inScope === 'true' ) {
3191- const name = MINode . valueOf ( change , 'name' ) ;
3192- const vId = this . variableHandlesReverse [ name ] ;
3193- const v = this . variableHandles . get ( vId ) as any ;
3194- v . applyChanges ( change ) ;
3195- } else {
3196- const msg = `${ exp } currently not in scope` ;
3197- await this . miDebugger . sendCommand ( `var-delete ${ varObjName } ` ) ;
3198- if ( this . args . showDevDebugOutput ) {
3199- this . handleMsg ( 'log' , `Expression ${ msg } . Will try to create again\n` ) ;
3191+ let varId = this . variableHandlesReverse [ varObjName ] ;
3192+ let createNewVar = varId === undefined ;
3193+ let updateError = undefined ;
3194+ if ( ! createNewVar ) {
3195+ try {
3196+ const changes = await this . miDebugger . varUpdate ( varObjName , threadId , frameId ) ;
3197+ const changelist = changes . result ( 'changelist' ) ;
3198+ for ( const change of changelist || [ ] ) {
3199+ const inScope = MINode . valueOf ( change , 'in_scope' ) ;
3200+ if ( inScope === 'true' ) {
3201+ const name = MINode . valueOf ( change , 'name' ) ;
3202+ const vId = this . variableHandlesReverse [ name ] ;
3203+ const v = this . variableHandles . get ( vId ) as any ;
3204+ v . applyChanges ( change ) ;
3205+ } else {
3206+ const msg = `${ exp } currently not in scope` ;
3207+ await this . miDebugger . sendCommand ( `var-delete ${ varObjName } ` ) ;
3208+ if ( this . args . showDevDebugOutput ) {
3209+ this . handleMsg ( 'log' , `Expression ${ msg } . Will try to create again\n` ) ;
3210+ }
3211+ createNewVar = true ;
3212+ throw new Error ( msg ) ;
32003213 }
3201- outOfScope = true ;
3202- throw new Error ( msg ) ;
32033214 }
3215+ varObj = this . variableHandles . get ( varId ) as any ;
3216+ }
3217+ catch ( err ) {
3218+ updateError = err ;
32043219 }
3205- const varId = this . variableHandlesReverse [ varObjName ] ;
3206- varObj = this . variableHandles . get ( varId ) as any ;
32073220 }
3208- catch ( err ) {
3209- if ( ! this . isBusy ( ) && ( outOfScope || ( ( err instanceof MIError && err . message === 'Variable object not found' ) ) ) ) {
3210- try {
3211- // We always create a floating variable so it will be updated in the context of the current frame
3212- // Technicall, we should be able to bind this to this frame but for some reason gdb gets confused
3213- // from previous stack frames and returns the wrong results or says nothing changed when in fact it has
3214- if ( args . frameId === undefined ) {
3215- varObj = await this . miDebugger . varCreate ( 0 , exp , varObjName , '@' ) ; // Create floating variable
3216- } else {
3217- varObj = await this . miDebugger . varCreate ( 0 , exp , varObjName , '@' , threadId , frameId ) ;
3218- }
3219-
3220- const varId = findOrCreateVariable ( varObj ) ;
3221- varObj . exp = exp ;
3222- varObj . id = varId ;
3223- }
3224- catch ( e ) {
3225- throw e ;
3226- }
3221+ if ( ! this . isBusy ( ) && ( createNewVar || ( ( updateError instanceof MIError && updateError . message === VarNotFoundMsg ) ) ) ) {
3222+ // We always create a floating variable so it will be updated in the context of the current frame
3223+ // Technicall, we should be able to bind this to this frame but for some reason gdb gets confused
3224+ // from previous stack frames and returns the wrong results or says nothing changed when in fact it has
3225+ if ( args . frameId === undefined ) {
3226+ varObj = await this . miDebugger . varCreate ( 0 , exp , varObjName , '@' ) ; // Create floating variable
32273227 } else {
3228- throw err ;
3228+ varObj = await this . miDebugger . varCreate ( 0 , exp , varObjName , '@' , threadId , frameId ) ;
32293229 }
3230- }
32313230
3231+ const varId = findOrCreateVariable ( varObj ) ;
3232+ varObj . exp = exp ;
3233+ varObj . id = varId ;
3234+ } else if ( ! varObj ) {
3235+ throw updateError || new Error ( 'evaluateRequest: unknown error' ) ;
3236+ }
32323237 response . body = varObj . toProtocolEvaluateResponseBody ( ) ;
32333238 this . sendResponse ( response ) ;
32343239 }
0 commit comments