Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions src/gdb/GDBDebugSessionBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ import { DEFAULT_STEPPING_RESPONSE_TIMEOUT } from '../constants/session';
import { ThreadWithStatus } from './common';
import { RESUME_COMMANDS, SET_ALL_CHARSET_REGEXPS } from '../constants/gdb';
import { GDBThreadRunning } from './errors';
import { MIGDBDataEvaluateExpressionResponse } from '../mi';

/**
* Keeps track of where in the configuration phase (between initialized event
Expand Down Expand Up @@ -157,6 +158,8 @@ export abstract class GDBDebugSessionBase extends LoggingDebugSession {
protected isRunning = false;

protected supportsRunInTerminalRequest = false;
protected supportsMemoryReferences = false;
protected supportsMemoryEvent = false;
public supportsGdbConsole = false;

/* A reference to the logger to be used by subclasses */
Expand Down Expand Up @@ -419,6 +422,8 @@ export abstract class GDBDebugSessionBase extends LoggingDebugSession {
): void {
this.supportsRunInTerminalRequest =
args.supportsRunInTerminalRequest === true;
this.supportsMemoryReferences = args.supportsMemoryReferences === true;
this.supportsMemoryEvent = args.supportsMemoryEvent === true;
this.supportsGdbConsole =
os.platform() === 'linux' && this.supportsRunInTerminalRequest;
response.body = response.body || {};
Expand Down Expand Up @@ -2674,10 +2679,35 @@ export abstract class GDBDebugSessionBase extends LoggingDebugSession {
varobjName: varobj.varname,
})
: 0;
let memoryReferenceResult:
| MIGDBDataEvaluateExpressionResponse
| undefined;
let hasMemoryReference = false;

@jreineckearm jreineckearm Jun 8, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: probably one of the two variables would have been enough (undefined for memoryReferenceResult meaning no memory reference). Maybe next time we touch this area.

if (this.supportsMemoryReferences) {
try {
memoryReferenceResult =
await mi.sendDataEvaluateExpression(
gdb,
`&(${varobj.expression})`
);
// Depending on the GDBServer being used, sometimes the result of evaluating an address of a symbol returns "<address> <symbol name>"
if (memoryReferenceResult.value?.includes(' ')) {
memoryReferenceResult.value =
memoryReferenceResult.value.split(' ')[0];
}
hasMemoryReference = true;
} catch {
hasMemoryReference = false;
}
}
response.body = {
result,
type: varobj.type,
variablesReference,
memoryReference:
hasMemoryReference && memoryReferenceResult
? memoryReferenceResult.value
: undefined,
};
}

Expand Down Expand Up @@ -3311,6 +3341,9 @@ export abstract class GDBDebugSessionBase extends LoggingDebugSession {
this.handleCmdParamChanged(notifyData);
break;
case 'memory-changed': {
if (!this.supportsMemoryEvent) {
break;
}
let length = 0;
if (isNaN(notifyData.len)) {
logger.warn(
Expand Down
3 changes: 2 additions & 1 deletion src/integration-tests/breakpoints.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,7 @@ describe('breakpoints', async function () {
// win32 host can only pause remote + mi-async targets
this.skip();
}
const firstStoppedEvent = dc.waitForEvent('stopped');
let response = await dc.setBreakpointsRequest({
source: {
name: 'count.c',
Expand All @@ -458,7 +459,7 @@ describe('breakpoints', async function () {
});
expect(response.body.breakpoints.length).to.eq(1);
await dc.configurationDoneRequest();
await dc.waitForEvent('stopped');
await firstStoppedEvent;
const scope = await getScopes(dc);
await dc.continueRequest({ threadId: scope.thread.id });

Expand Down
2 changes: 2 additions & 0 deletions src/integration-tests/debugClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,8 @@ export class CdtDebugClient extends DebugClient {
if (!args) {
args = {
supportsRunInTerminalRequest: true,
supportsMemoryEvent: true,
supportsMemoryReferences: true,
Comment thread
omarArm marked this conversation as resolved.
adapterID: this['_debugType'],
linesStartAt1: true,
columnsStartAt1: true,
Expand Down
20 changes: 20 additions & 0 deletions src/integration-tests/evaluate.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,26 @@ describe('evaluate request global variables', function () {
});
expect(evalRes.body.result).to.equal('25');
});

it('response for variables should include memory reference if the expression has an lvalue', async function () {
// Read a global variable using evaluateRequest
const watchRes = await dc.evaluateRequest({
context: 'watch',
expression: 'global_int',
frameId: scope.frame.id,
});
expect(watchRes.body.memoryReference).to.not.be.undefined;
});

it('should not include memory reference if the expression does not have an lvalue', async function () {
const watchRes = await dc.evaluateRequest({
context: 'watch',
expression: 'global_int + 1',
frameId: scope.frame.id,
});

expect(watchRes.body.memoryReference).to.be.undefined;
});
});

describe('evaluate request - watch local variable across lexical scope transition', function () {
Expand Down
Loading