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

add support for envFile #358

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
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
30 changes: 30 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,11 @@
"description": "Environment overriding the gdb (and in turn also the process) environment",
"default": null
},
"envFile": {
"type": "string",
"description": "path to a file containing environment variable definitions",
"default": null
},
"debugger_args": {
"type": "array",
"description": "Additional arguments to pass to GDB",
Expand Down Expand Up @@ -342,6 +347,11 @@
"description": "Environment overriding the gdb (and in turn also the process) environment",
"default": null
},
"envFile": {
"type": "string",
"description": "path to a file containing environment variable definitions",
"default": null
},
"debugger_args": {
"type": "array",
"description": "Additional arguments to pass to GDB",
Expand Down Expand Up @@ -629,6 +639,11 @@
"description": "Environment overriding the lldb-mi (and in turn also the process) environment",
"default": null
},
"envFile": {
"type": "string",
"description": "path to a file containing environment variable definitions",
"default": null
},
"debugger_args": {
"type": "array",
"description": "Additional arguments to pass to LLDB",
Expand Down Expand Up @@ -797,6 +812,11 @@
"description": "Environment overriding the lldb-mi (and in turn also the process) environment",
"default": null
},
"envFile": {
"type": "string",
"description": "path to a file containing environment variable definitions",
"default": null
},
"debugger_args": {
"type": "array",
"description": "Additional arguments to pass to LLDB",
Expand Down Expand Up @@ -948,6 +968,11 @@
"description": "Environment overriding the mago-mi (and in turn also the process) environment",
"default": null
},
"envFile": {
"type": "string",
"description": "path to a file containing environment variable definitions",
"default": null
},
"debugger_args": {
"type": "array",
"description": "Additional arguments to pass to mago",
Expand Down Expand Up @@ -1023,6 +1048,11 @@
"description": "Environment overriding the mago-mi (and in turn also the process) environment",
"default": null
},
"envFile": {
"type": "string",
"description": "path to a file containing environment variable definitions",
"default": null
},
"debugger_args": {
"type": "array",
"description": "Additional arguments to pass to mago",
Expand Down
66 changes: 49 additions & 17 deletions src/backend/mi2/mi2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,27 +25,30 @@ function couldBeOutput(line: string) {
const trace = false;

export class MI2 extends EventEmitter implements IBackend {
constructor(public application: string, public preargs: string[], public extraargs: string[], procEnv: any, public extraCommands: string[] = []) {
constructor(public application: string, public preargs: string[], public extraargs: string[], procEnv: any, envFile: string, public extraCommands: string[] = []) {
super();

if (!(envFile || procEnv))
return;

// FIXME: if actuall debugged process is Win32, which we only know _after_ connect,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Do we not really not know what type of process that will be debugged? The environment support is only applicable to the debugger running on the same machine as the debug adapter (not supported over SSH), so it should be able to determine the system it's running on via process.platform. Not sure I understand this issue.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

No, we don't know. I'm regularly using gdb to attach to gdbserver on a different machine myself. Works fine as long as the gdb has support for the target's architecture.

Copy link
Collaborator

Choose a reason for hiding this comment

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

But these environment variables are only being applied to the process where gdb is being run, not the process where gdbserver is run. I don't think I understand what the expectation of the environment variables would be in a remote scenario like that. Are they expected to be visible to the application being debugged?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Are they expected to be visible to the application being debugged?

likely yes, as long as we use set environment (or its mi equivalent) this will work both for GDB and (at least on GNU/Linux environments) gdbserver (since GDB 8.1); for running processes wed need to call into putenv()`, but I think it is fine to say that this is only supported for new inferiors.

// then the keys must be read via hashmap using only upper-case for hashing
// ... or entered/compared in upper-case --> possibly postpone this
const env = {};
// Duplicate process.env so we don't override it
for (const key in process.env)
if (process.env.hasOwnProperty(key))
env[key] = process.env[key];

// Overwrite with user specified variables
if (envFile) {
mergeEnv(env, readEnvFile(envFile));
}
if (procEnv) {
const env = {};
// Duplicate process.env so we don't override it
for (const key in process.env)
if (process.env.hasOwnProperty(key))
env[key] = process.env[key];

// Overwrite with user specified variables
for (const key in procEnv) {
if (procEnv.hasOwnProperty(key)) {
if (procEnv === undefined)
delete env[key];
else
env[key] = procEnv[key];
}
}
this.procEnv = env;
mergeEnv(env, procEnv);
}

this.procEnv = env;
}

load(cwd: string, target: string, procArgs: string, separateConsole: string): Thenable<any> {
Expand Down Expand Up @@ -886,3 +889,32 @@ export class MI2 extends EventEmitter implements IBackend {
protected stream;
protected sshConn;
}
function readEnvFile(filename: string): { [key: string]: string } {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I would probably recommend taking these functions, along with the functionality in the MI2 constructor above and moving it to its own class (e.g., "Environment"). This would encapsulate this functionality and make it easy to unit test.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, that's a general issue with the existing code - the environment variables are expected to be found in the inferior (this "just happens" when GDB starts it locally). If we cannot make this happen all environment settings should be dropped from all remote scenarios.
I think this should be changed in general to use; and I even forgot if there's a better way than call setenv (name, value, 1) [which likely only work for C/C++ code, not everything GDB supports].

Copy link
Collaborator

Choose a reason for hiding this comment

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

There does appear to be commands in both gdb and lldb for setting environment variables, so using that approach, rather than attempting to set them at the process level might be the way to go. The environment variable setting commands could just be issued during the MI2::initCommands, similarly to how the path mappings are handled (i.e., extra commands). The GDB documentation even says these environment variable settings are sent to gdbserver, so should support remote debugging as well (see here). This should also work with SSH connections too, since the commands are issued to the debugger itself.

  • gdb Add/Remove Environment Variable:
(gdb) set environment FOO=BAR
(gdb) unset environment FOO
  • lldb Add/Remove Environment Variable:
(lldb) settings set target.env-vars FOO=BAR
(lldb) settings remove target.env-vars FOO

const env = {};
if (!fs.existsSync(filename)) {
return env;
}
const buffer = fs.readFileSync(filename, 'utf8');
buffer.split('\n').forEach( line => {
// using a match which will automatically ignore "wrong" lines including
// lines that are empty or start with a "#", or //, or ...
const m = line.match(/^\s*([\w\.\-]+)\s*=\s*(.*)?\s*$/);
if (m != undefined) {
env[m[1]] = m[2] || '';
}
});

throw new Error("Function not implemented.");
}

function mergeEnv(env: {}, buffer: { [key: string]: string; }) {
for (const key in buffer) {
if (buffer.hasOwnProperty(key)) {
if (buffer === undefined)
delete env[key];
else
env[key] = buffer[key];
}
}
}

6 changes: 4 additions & 2 deletions src/gdb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export interface LaunchRequestArguments extends DebugProtocol.LaunchRequestArgum
target: string;
gdbpath: string;
env: any;
envFile: string;
debugger_args: string[];
pathSubstitutions: { [index: string]: string };
arguments: string;
Expand All @@ -26,6 +27,7 @@ export interface AttachRequestArguments extends DebugProtocol.AttachRequestArgum
target: string;
gdbpath: string;
env: any;
envFile: string;
debugger_args: string[];
pathSubstitutions: { [index: string]: string };
executable: string;
Expand Down Expand Up @@ -53,7 +55,7 @@ class GDBDebugSession extends MI2DebugSession {
}

protected launchRequest(response: DebugProtocol.LaunchResponse, args: LaunchRequestArguments): void {
this.miDebugger = new MI2(args.gdbpath || "gdb", ["-q", "--interpreter=mi2"], args.debugger_args, args.env);
this.miDebugger = new MI2(args.gdbpath || "gdb", ["-q", "--interpreter=mi2"], args.debugger_args, args.env, args.envFile);
this.setPathSubstitutions(args.pathSubstitutions);
this.initDebugger();
this.quit = false;
Expand Down Expand Up @@ -102,7 +104,7 @@ class GDBDebugSession extends MI2DebugSession {
}

protected attachRequest(response: DebugProtocol.AttachResponse, args: AttachRequestArguments): void {
this.miDebugger = new MI2(args.gdbpath || "gdb", ["-q", "--interpreter=mi2"], args.debugger_args, args.env);
this.miDebugger = new MI2(args.gdbpath || "gdb", ["-q", "--interpreter=mi2"], args.debugger_args, args.env, args.envFile);
this.setPathSubstitutions(args.pathSubstitutions);
this.initDebugger();
this.quit = false;
Expand Down
6 changes: 4 additions & 2 deletions src/lldb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export interface LaunchRequestArguments extends DebugProtocol.LaunchRequestArgum
target: string;
lldbmipath: string;
env: any;
envFile: string;
debugger_args: string[];
pathSubstitutions: { [index: string]: string };
arguments: string;
Expand All @@ -25,6 +26,7 @@ export interface AttachRequestArguments extends DebugProtocol.AttachRequestArgum
target: string;
lldbmipath: string;
env: any;
envFile: string;
debugger_args: string[];
pathSubstitutions: { [index: string]: string };
executable: string;
Expand All @@ -48,7 +50,7 @@ class LLDBDebugSession extends MI2DebugSession {
}

protected launchRequest(response: DebugProtocol.LaunchResponse, args: LaunchRequestArguments): void {
this.miDebugger = new MI2_LLDB(args.lldbmipath || "lldb-mi", [], args.debugger_args, args.env);
this.miDebugger = new MI2_LLDB(args.lldbmipath || "lldb-mi", [], args.debugger_args, args.env, args.envFile);
this.setPathSubstitutions(args.pathSubstitutions);
this.initDebugger();
this.quit = false;
Expand Down Expand Up @@ -93,7 +95,7 @@ class LLDBDebugSession extends MI2DebugSession {
}

protected attachRequest(response: DebugProtocol.AttachResponse, args: AttachRequestArguments): void {
this.miDebugger = new MI2_LLDB(args.lldbmipath || "lldb-mi", [], args.debugger_args, args.env);
this.miDebugger = new MI2_LLDB(args.lldbmipath || "lldb-mi", [], args.debugger_args, args.env, args.envFile);
this.setPathSubstitutions(args.pathSubstitutions);
this.initDebugger();
this.quit = false;
Expand Down
6 changes: 4 additions & 2 deletions src/mago.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export interface LaunchRequestArguments extends DebugProtocol.LaunchRequestArgum
target: string;
magomipath: string;
env: any;
envFile: string;
debugger_args: string[];
arguments: string;
autorun: string[];
Expand All @@ -22,6 +23,7 @@ export interface AttachRequestArguments extends DebugProtocol.AttachRequestArgum
target: string;
magomipath: string;
env: any;
envFile: string;
debugger_args: string[];
executable: string;
autorun: string[];
Expand Down Expand Up @@ -50,7 +52,7 @@ class MagoDebugSession extends MI2DebugSession {
}

protected launchRequest(response: DebugProtocol.LaunchResponse, args: LaunchRequestArguments): void {
this.miDebugger = new MI2_Mago(args.magomipath || "mago-mi", ["-q"], args.debugger_args, args.env);
this.miDebugger = new MI2_Mago(args.magomipath || "mago-mi", ["-q"], args.debugger_args, args.env, args.envFile);
this.initDebugger();
this.quit = false;
this.attached = false;
Expand All @@ -71,7 +73,7 @@ class MagoDebugSession extends MI2DebugSession {
}

protected attachRequest(response: DebugProtocol.AttachResponse, args: AttachRequestArguments): void {
this.miDebugger = new MI2_Mago(args.magomipath || "mago-mi", [], args.debugger_args, args.env);
this.miDebugger = new MI2_Mago(args.magomipath || "mago-mi", [], args.debugger_args, args.env, args.envFile);
this.initDebugger();
this.quit = false;
this.attached = true;
Expand Down