Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Injecting Environment Variables to GDB and GDBSERVER processes #303

Merged
merged 15 commits into from
Oct 11, 2023
Merged
Show file tree
Hide file tree
Changes from 13 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
36 changes: 18 additions & 18 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,26 +22,26 @@
"docker:test": "docker run --rm -it -v $(git rev-parse --show-toplevel):/work -w /work/$(git rev-parse --show-prefix) --cap-add=SYS_PTRACE --security-opt seccomp=unconfined quay.io/eclipse-cdt/cdt-infra-eclipse-full:latest yarn test",
"test": "yarn test:integration && yarn test:integration-remote-target && yarn test:integration-gdb-async-off && yarn test:integration-gdb-async-off-remote-target && yarn test:integration-gdb-non-stop && yarn test:integration-gdb-non-stop-remote-target && yarn test:integration-hw-breakpoint-on-remote-target",
"test-run-in-terminal": "yarn test:pty && yarn test:integration-run-in-terminal && yarn test:integration-remote-target-run-in-terminal",
"test:integration": "cross-env JUNIT_REPORT_PATH=test-reports/integration.xml JUNIT_REPORT_STACK=1 JUNIT_REPORT_PACKAGES=1 mocha --exit --reporter mocha-jenkins-reporter -r ts-node/register src/integration-tests/*.spec.ts",
"test:integration-run-in-terminal": "cross-env JUNIT_REPORT_PATH=test-reports/integration-run-in-terminal.xml JUNIT_REPORT_STACK=1 JUNIT_REPORT_PACKAGES=1 mocha --exit --run-in-terminal --reporter mocha-jenkins-reporter -r ts-node/register src/integration-tests/*.spec.ts",
"test:integration-remote-target": "cross-env JUNIT_REPORT_PATH=test-reports/integration-remote-target.xml JUNIT_REPORT_STACK=1 JUNIT_REPORT_PACKAGES=1 mocha --exit --test-remote --reporter mocha-jenkins-reporter -r ts-node/register src/integration-tests/*.spec.ts",
"test:integration-remote-target-run-in-terminal": "cross-env JUNIT_REPORT_PATH=test-reports/integration-remote-target-run-in-terminal.xml JUNIT_REPORT_STACK=1 JUNIT_REPORT_PACKAGES=1 mocha --exit --test-remote --run-in-terminal --reporter mocha-jenkins-reporter -r ts-node/register src/integration-tests/*.spec.ts",
"test:integration-gdb-async-off": "cross-env JUNIT_REPORT_PATH=test-reports/integration-gdb-async-off.xml JUNIT_REPORT_STACK=1 JUNIT_REPORT_PACKAGES=1 mocha --exit --reporter mocha-jenkins-reporter -r ts-node/register src/integration-tests/*.spec.ts --test-gdb-async-off",
"test:integration-gdb-async-off-remote-target": "cross-env JUNIT_REPORT_PATH=test-reports/integration-gdb-async-off-remote-target.xml JUNIT_REPORT_STACK=1 JUNIT_REPORT_PACKAGES=1 mocha --exit --reporter mocha-jenkins-reporter -r ts-node/register src/integration-tests/*.spec.ts --test-gdb-async-off --test-remote",
"test:integration-gdb-non-stop": "cross-env JUNIT_REPORT_PATH=test-reports/integration-gdb-non-stop.xml JUNIT_REPORT_STACK=1 JUNIT_REPORT_PACKAGES=1 mocha --exit --reporter mocha-jenkins-reporter -r ts-node/register src/integration-tests/*.spec.ts --test-gdb-non-stop",
"test:integration-gdb-non-stop-remote-target": "cross-env JUNIT_REPORT_PATH=test-reports/integration-gdb-non-stop-remote-target.xml JUNIT_REPORT_STACK=1 JUNIT_REPORT_PACKAGES=1 mocha --exit --reporter mocha-jenkins-reporter -r ts-node/register src/integration-tests/*.spec.ts --test-gdb-non-stop --test-remote",
"test:integration-hw-breakpoint-on-remote-target": "cross-env JUNIT_REPORT_PATH=test-reports/integration-hw-breakpoint-on-remote-target.xml JUNIT_REPORT_STACK=1 JUNIT_REPORT_PACKAGES=1 mocha --exit --reporter mocha-jenkins-reporter -r ts-node/register src/integration-tests/*.spec.ts --test-hw-breakpoint-on --test-remote",
"test:integration": "cross-env JUNIT_REPORT_PATH=test-reports/integration.xml JUNIT_REPORT_STACK=1 JUNIT_REPORT_PACKAGES=1 ENV_TEST_VAR=VALUE1 mocha --exit --reporter mocha-jenkins-reporter -r ts-node/register src/integration-tests/*.spec.ts",
"test:integration-run-in-terminal": "cross-env JUNIT_REPORT_PATH=test-reports/integration-run-in-terminal.xml JUNIT_REPORT_STACK=1 JUNIT_REPORT_PACKAGES=1 ENV_TEST_VAR=VALUE1 mocha --exit --run-in-terminal --reporter mocha-jenkins-reporter -r ts-node/register src/integration-tests/*.spec.ts",
"test:integration-remote-target": "cross-env JUNIT_REPORT_PATH=test-reports/integration-remote-target.xml JUNIT_REPORT_STACK=1 JUNIT_REPORT_PACKAGES=1 ENV_TEST_VAR=VALUE1 mocha --exit --test-remote --reporter mocha-jenkins-reporter -r ts-node/register src/integration-tests/*.spec.ts",
"test:integration-remote-target-run-in-terminal": "cross-env JUNIT_REPORT_PATH=test-reports/integration-remote-target-run-in-terminal.xml JUNIT_REPORT_STACK=1 JUNIT_REPORT_PACKAGES=1 ENV_TEST_VAR=VALUE1 mocha --exit --test-remote --run-in-terminal --reporter mocha-jenkins-reporter -r ts-node/register src/integration-tests/*.spec.ts",
"test:integration-gdb-async-off": "cross-env JUNIT_REPORT_PATH=test-reports/integration-gdb-async-off.xml JUNIT_REPORT_STACK=1 JUNIT_REPORT_PACKAGES=1 ENV_TEST_VAR=VALUE1 mocha --exit --reporter mocha-jenkins-reporter -r ts-node/register src/integration-tests/*.spec.ts --test-gdb-async-off",
"test:integration-gdb-async-off-remote-target": "cross-env JUNIT_REPORT_PATH=test-reports/integration-gdb-async-off-remote-target.xml JUNIT_REPORT_STACK=1 JUNIT_REPORT_PACKAGES=1 ENV_TEST_VAR=VALUE1 mocha --exit --reporter mocha-jenkins-reporter -r ts-node/register src/integration-tests/*.spec.ts --test-gdb-async-off --test-remote",
"test:integration-gdb-non-stop": "cross-env JUNIT_REPORT_PATH=test-reports/integration-gdb-non-stop.xml JUNIT_REPORT_STACK=1 JUNIT_REPORT_PACKAGES=1 ENV_TEST_VAR=VALUE1 mocha --exit --reporter mocha-jenkins-reporter -r ts-node/register src/integration-tests/*.spec.ts --test-gdb-non-stop",
"test:integration-gdb-non-stop-remote-target": "cross-env JUNIT_REPORT_PATH=test-reports/integration-gdb-non-stop-remote-target.xml JUNIT_REPORT_STACK=1 JUNIT_REPORT_PACKAGES=1 ENV_TEST_VAR=VALUE1 mocha --exit --reporter mocha-jenkins-reporter -r ts-node/register src/integration-tests/*.spec.ts --test-gdb-non-stop --test-remote",
"test:integration-hw-breakpoint-on-remote-target": "cross-env JUNIT_REPORT_PATH=test-reports/integration-hw-breakpoint-on-remote-target.xml JUNIT_REPORT_STACK=1 JUNIT_REPORT_PACKAGES=1 ENV_TEST_VAR=VALUE1 mocha --exit --reporter mocha-jenkins-reporter -r ts-node/register src/integration-tests/*.spec.ts --test-hw-breakpoint-on --test-remote",
"test:pty": "cross-env JUNIT_REPORT_PATH=test-reports/native.xml JUNIT_REPORT_STACK=1 JUNIT_REPORT_PACKAGES=1 mocha --exit --reporter mocha-jenkins-reporter dist/native/*.spec.js",
"test-ci": "run-s --continue-on-error test-ci:integration test-ci:integration-remote-target test-ci:integration-gdb-async-off test-ci:integration-gdb-async-off-remote-target test-ci:integration-gdb-non-stop test-ci:integration-gdb-non-stop-remote-target test-ci:integration-hw-breakpoint-on-remote-target",
"test-ci:integration": "cross-env JUNIT_REPORT_PATH=test-reports/integration.xml JUNIT_REPORT_STACK=1 JUNIT_REPORT_PACKAGES=1 mocha --exit --skip-make --reporter mocha-jenkins-reporter -r ts-node/register src/integration-tests/*.spec.ts",
"test-ci:integration-run-in-terminal": "cross-env JUNIT_REPORT_PATH=test-reports/integration-run-in-terminal.xml JUNIT_REPORT_STACK=1 JUNIT_REPORT_PACKAGES=1 mocha --exit --skip-make --run-in-terminal --reporter mocha-jenkins-reporter -r ts-node/register src/integration-tests/*.spec.ts",
"test-ci:integration-remote-target": "cross-env JUNIT_REPORT_PATH=test-reports/integration-remote-target.xml JUNIT_REPORT_STACK=1 JUNIT_REPORT_PACKAGES=1 mocha --exit --skip-make --test-remote --reporter mocha-jenkins-reporter -r ts-node/register src/integration-tests/*.spec.ts",
"test-ci:integration-remote-target-run-in-terminal": "cross-env JUNIT_REPORT_PATH=test-reports/integration-remote-target-run-in-terminal.xml JUNIT_REPORT_STACK=1 JUNIT_REPORT_PACKAGES=1 mocha --exit --skip-make --test-remote --run-in-terminal --reporter mocha-jenkins-reporter -r ts-node/register src/integration-tests/*.spec.ts",
"test-ci:integration-gdb-async-off": "cross-env JUNIT_REPORT_PATH=test-reports/integration-gdb-async-off.xml JUNIT_REPORT_STACK=1 JUNIT_REPORT_PACKAGES=1 mocha --exit --skip-make --reporter mocha-jenkins-reporter -r ts-node/register src/integration-tests/*.spec.ts --test-gdb-async-off",
"test-ci:integration-gdb-async-off-remote-target": "cross-env JUNIT_REPORT_PATH=test-reports/integration-gdb-async-off-remote-target.xml JUNIT_REPORT_STACK=1 JUNIT_REPORT_PACKAGES=1 mocha --exit --skip-make --reporter mocha-jenkins-reporter -r ts-node/register src/integration-tests/*.spec.ts --test-gdb-async-off --test-remote",
"test-ci:integration-gdb-non-stop": "cross-env JUNIT_REPORT_PATH=test-reports/integration-gdb-non-stop.xml JUNIT_REPORT_STACK=1 JUNIT_REPORT_PACKAGES=1 mocha --exit --skip-make --reporter mocha-jenkins-reporter -r ts-node/register src/integration-tests/*.spec.ts --test-gdb-non-stop",
"test-ci:integration-gdb-non-stop-remote-target": "cross-env JUNIT_REPORT_PATH=test-reports/integration-gdb-non-stop-remote-target.xml JUNIT_REPORT_STACK=1 JUNIT_REPORT_PACKAGES=1 mocha --exit --skip-make --reporter mocha-jenkins-reporter -r ts-node/register src/integration-tests/*.spec.ts --test-gdb-non-stop --test-remote",
"test-ci:integration-hw-breakpoint-on-remote-target": "cross-env JUNIT_REPORT_PATH=test-reports/integration-hw-breakpoint-on-remote-target.xml JUNIT_REPORT_STACK=1 JUNIT_REPORT_PACKAGES=1 mocha --exit --skip-make --reporter mocha-jenkins-reporter -r ts-node/register src/integration-tests/*.spec.ts --test-hw-breakpoint-on --test-remote",
"test-ci:integration": "cross-env JUNIT_REPORT_PATH=test-reports/integration.xml JUNIT_REPORT_STACK=1 JUNIT_REPORT_PACKAGES=1 ENV_TEST_VAR=VALUE1 mocha --exit --skip-make --reporter mocha-jenkins-reporter -r ts-node/register src/integration-tests/*.spec.ts",
"test-ci:integration-run-in-terminal": "cross-env JUNIT_REPORT_PATH=test-reports/integration-run-in-terminal.xml JUNIT_REPORT_STACK=1 ENV_TEST_VAR=VALUE1 JUNIT_REPORT_PACKAGES=1 mocha --exit --skip-make --run-in-terminal --reporter mocha-jenkins-reporter -r ts-node/register src/integration-tests/*.spec.ts",
"test-ci:integration-remote-target": "cross-env JUNIT_REPORT_PATH=test-reports/integration-remote-target.xml JUNIT_REPORT_STACK=1 JUNIT_REPORT_PACKAGES=1 ENV_TEST_VAR=VALUE1 mocha --exit --skip-make --test-remote --reporter mocha-jenkins-reporter -r ts-node/register src/integration-tests/*.spec.ts",
"test-ci:integration-remote-target-run-in-terminal": "cross-env JUNIT_REPORT_PATH=test-reports/integration-remote-target-run-in-terminal.xml JUNIT_REPORT_STACK=1 JUNIT_REPORT_PACKAGES=1 ENV_TEST_VAR=VALUE1 mocha --exit --skip-make --test-remote --run-in-terminal --reporter mocha-jenkins-reporter -r ts-node/register src/integration-tests/*.spec.ts",
"test-ci:integration-gdb-async-off": "cross-env JUNIT_REPORT_PATH=test-reports/integration-gdb-async-off.xml JUNIT_REPORT_STACK=1 JUNIT_REPORT_PACKAGES=1 ENV_TEST_VAR=VALUE1 mocha --exit --skip-make --reporter mocha-jenkins-reporter -r ts-node/register src/integration-tests/*.spec.ts --test-gdb-async-off",
"test-ci:integration-gdb-async-off-remote-target": "cross-env JUNIT_REPORT_PATH=test-reports/integration-gdb-async-off-remote-target.xml JUNIT_REPORT_STACK=1 JUNIT_REPORT_PACKAGES=1 ENV_TEST_VAR=VALUE1 mocha --exit --skip-make --reporter mocha-jenkins-reporter -r ts-node/register src/integration-tests/*.spec.ts --test-gdb-async-off --test-remote",
"test-ci:integration-gdb-non-stop": "cross-env JUNIT_REPORT_PATH=test-reports/integration-gdb-non-stop.xml JUNIT_REPORT_STACK=1 JUNIT_REPORT_PACKAGES=1 ENV_TEST_VAR=VALUE1 mocha --exit --skip-make --reporter mocha-jenkins-reporter -r ts-node/register src/integration-tests/*.spec.ts --test-gdb-non-stop",
"test-ci:integration-gdb-non-stop-remote-target": "cross-env JUNIT_REPORT_PATH=test-reports/integration-gdb-non-stop-remote-target.xml JUNIT_REPORT_STACK=1 JUNIT_REPORT_PACKAGES=1 ENV_TEST_VAR=VALUE1 mocha --exit --skip-make --reporter mocha-jenkins-reporter -r ts-node/register src/integration-tests/*.spec.ts --test-gdb-non-stop --test-remote",
"test-ci:integration-hw-breakpoint-on-remote-target": "cross-env JUNIT_REPORT_PATH=test-reports/integration-hw-breakpoint-on-remote-target.xml JUNIT_REPORT_STACK=1 JUNIT_REPORT_PACKAGES=1 ENV_TEST_VAR=VALUE1 mocha --exit --skip-make --reporter mocha-jenkins-reporter -r ts-node/register src/integration-tests/*.spec.ts --test-hw-breakpoint-on --test-remote",
"test-ci:pty": "cross-env JUNIT_REPORT_PATH=test-reports/native.xml JUNIT_REPORT_STACK=1 JUNIT_REPORT_PACKAGES=1 mocha --exit --skip-make --reporter mocha-jenkins-reporter dist/native/*.spec.js"
},
"repository": {
Expand Down
18 changes: 12 additions & 6 deletions src/GDBBackend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import * as mi from './mi';
import { MIResponse } from './mi';
import { MIParser } from './MIParser';
import { VarManager } from './varManager';
import { compareVersions, getGdbVersion } from './util';
import { compareVersions, getGdbVersion, createEnvValues } from './util';

export interface MIExecNextRequest {
reverse?: boolean;
Expand Down Expand Up @@ -73,12 +73,15 @@ export class GDBBackend extends events.EventEmitter {
requestArgs: LaunchRequestArguments | AttachRequestArguments
) {
const gdbPath = requestArgs.gdb || 'gdb';
this.gdbVersion = await getGdbVersion(gdbPath);
this.gdbVersion = await getGdbVersion(gdbPath, requestArgs.environment);
let args = ['--interpreter=mi2'];
if (requestArgs.gdbArguments) {
args = args.concat(requestArgs.gdbArguments);
}
this.proc = spawn(gdbPath, args);
const gdbEnvironment = requestArgs.environment
? createEnvValues(process.env, requestArgs.environment)
: process.env;
this.proc = spawn(gdbPath, args, { env: gdbEnvironment });
if (this.proc.stdin == null || this.proc.stdout == null) {
throw new Error('Spawned GDB does not have stdout or stdin');
}
Expand All @@ -100,7 +103,7 @@ export class GDBBackend extends events.EventEmitter {
cb: (args: string[]) => Promise<void>
) {
const gdbPath = requestArgs.gdb || 'gdb';
this.gdbVersion = await getGdbVersion(gdbPath);
this.gdbVersion = await getGdbVersion(gdbPath, requestArgs.environment);
// Use dynamic import to remove need for natively building this adapter
// Useful when 'spawnInClientTerminal' isn't needed, but adapter is distributed on multiple OS's
const { Pty } = await import('./native/pty');
Expand Down Expand Up @@ -196,8 +199,11 @@ export class GDBBackend extends events.EventEmitter {
}
}

public async supportsNewUi(gdbPath?: string): Promise<boolean> {
this.gdbVersion = await getGdbVersion(gdbPath || 'gdb');
public async supportsNewUi(
gdbPath?: string,
environment?: Record<string, string | null>
): Promise<boolean> {
this.gdbVersion = await getGdbVersion(gdbPath || 'gdb', environment);
return this.gdbVersionAtLeast('7.12');
}

Expand Down
76 changes: 50 additions & 26 deletions src/GDBDebugSession.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,14 @@ import {
} from './mi/data';
import { StoppedEvent } from './stoppedEvent';
import { VarObjType } from './varManager';
import { createEnvValues } from './util';

export interface RequestArguments extends DebugProtocol.LaunchRequestArguments {
gdb?: string;
gdbArguments?: string[];
gdbAsync?: boolean;
gdbNonStop?: boolean;
environment?: Record<string, string | null>;
program: string;
cwd?: string; // TODO not implemented
verbose?: boolean;
Expand Down Expand Up @@ -275,10 +277,20 @@ export class GDBDebugSession extends LoggingDebugSession {
// This custom request exists to allow tests in this repository to run arbitrary commands
// Use at your own risk!
} else if (command === 'cdt-gdb-tests/executeCommand') {
const consoleOutput: string[] = [];
const consoleOutputListener = (line: string) =>
consoleOutput.push(line);
// Listens the console output for test and controls purpose during the
// test command execution. Boundry of the console output not guaranteed.
this.gdb.addListener('consoleStreamOutput', consoleOutputListener);
this.gdb
.sendCommand(args.command)
.then(() => {
response.body = 'Ok';
.then((result) => {
response.body = {
status: 'Ok',
result,
console: consoleOutput,
};
this.sendResponse(response);
})
.catch((e) => {
Expand All @@ -287,6 +299,12 @@ export class GDBDebugSession extends LoggingDebugSession {
? e.message
: `Encountered a problem executing ${args.command}`;
this.sendErrorResponse(response, 1, message);
})
.finally(() => {
this.gdb.removeListener(
'consoleStreamOutput',
consoleOutputListener
);
});
} else {
return super.customRequest(command, response, args);
Expand Down Expand Up @@ -420,7 +438,9 @@ export class GDBDebugSession extends LoggingDebugSession {
logger.warn(
'cdt-gdb-adapter: openGdbConsole is not supported on this platform'
);
} else if (!(await this.gdb.supportsNewUi(args.gdb))) {
} else if (
!(await this.gdb.supportsNewUi(args.gdb, args.environment))
) {
logger.warn(
`cdt-gdb-adapter: new-ui command not detected (${
args.gdb || 'gdb'
Expand All @@ -441,30 +461,34 @@ export class GDBDebugSession extends LoggingDebugSession {
| DebugProtocol.LaunchRequestArguments
| DebugProtocol.AttachRequestArguments
) {
return this.gdb.spawnInClientTerminal(
args as LaunchRequestArguments | AttachRequestArguments,
async (command) => {
const response = await new Promise<DebugProtocol.Response>(
(resolve) =>
this.sendRequest(
'runInTerminal',
{
kind: 'integrated',
cwd: process.cwd(),
env: process.env,
args: command,
} as DebugProtocol.RunInTerminalRequestArguments,
5000,
resolve
)
);
if (!response.success) {
const message = `could not start the terminal on the client: ${response.message}`;
logger.error(message);
throw new Error(message);
}
const requestArgs = args as
| LaunchRequestArguments
| AttachRequestArguments;
const gdbEnvironment = requestArgs.environment
? createEnvValues(process.env, requestArgs.environment)
: process.env;

return this.gdb.spawnInClientTerminal(requestArgs, async (command) => {
const response = await new Promise<DebugProtocol.Response>(
(resolve) =>
this.sendRequest(
'runInTerminal',
{
kind: 'integrated',
cwd: process.cwd(),
env: gdbEnvironment,
args: command,
} as DebugProtocol.RunInTerminalRequestArguments,
5000,
resolve
)
);
if (!response.success) {
const message = `could not start the terminal on the client: ${response.message}`;
logger.error(message);
throw new Error(message);
}
);
});
}

protected async setBreakPointsRequest(
Expand Down
Loading
Loading