mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-01-09 01:29:52 +00:00
[lldb-vscode] Add inheritEnvironment option
Summary: If no custom launching is used, lldb-vscode launches a program with an empty environment by default. In some scenarios, the user might want to simply use the same environment as the IDE to have a set of working environment variables (e.g. PATH wouldn't be empty). In fact, most DAPs in VSCode have this behavior by default. In other cases the user definitely needs to set their custom environment, which is already supported. To make the first case easier for the user (e.g. not having to copy the PATH to the launch.json every time they want to debug simple programs that rely on PATH), a new option is now offered. inheritEnvironment will launch the program copying its own environment, and it's just a boolean flag. {F11347695} Reviewers: clayborg, aadsm, diazhector98, kusmour Subscribers: labath, JDevlieghere, lldb-commits Tags: #lldb Differential Revision: https://reviews.llvm.org/D74636
This commit is contained in:
parent
a8c22ba416
commit
4ec6ebabfc
@ -267,7 +267,7 @@ class VSCodeTestCaseBase(TestBase):
|
||||
disableSTDIO=False, shellExpandArguments=False,
|
||||
trace=False, initCommands=None, preRunCommands=None,
|
||||
stopCommands=None, exitCommands=None,sourcePath= None,
|
||||
debuggerRoot=None, launchCommands=None):
|
||||
debuggerRoot=None, launchCommands=None, inheritEnvironment=False):
|
||||
'''Sending launch request to vscode
|
||||
'''
|
||||
|
||||
@ -298,7 +298,8 @@ class VSCodeTestCaseBase(TestBase):
|
||||
exitCommands=exitCommands,
|
||||
sourcePath=sourcePath,
|
||||
debuggerRoot=debuggerRoot,
|
||||
launchCommands=launchCommands)
|
||||
launchCommands=launchCommands,
|
||||
inheritEnvironment=inheritEnvironment)
|
||||
if not (response and response['success']):
|
||||
self.assertTrue(response['success'],
|
||||
'launch failed (%s)' % (response['message']))
|
||||
@ -308,7 +309,7 @@ class VSCodeTestCaseBase(TestBase):
|
||||
disableSTDIO=False, shellExpandArguments=False,
|
||||
trace=False, initCommands=None, preRunCommands=None,
|
||||
stopCommands=None, exitCommands=None,
|
||||
sourcePath=None, debuggerRoot=None):
|
||||
sourcePath=None, debuggerRoot=None, inheritEnvironment=False):
|
||||
'''Build the default Makefile target, create the VSCode debug adaptor,
|
||||
and launch the process.
|
||||
'''
|
||||
@ -318,4 +319,4 @@ class VSCodeTestCaseBase(TestBase):
|
||||
self.launch(program, args, cwd, env, stopOnEntry, disableASLR,
|
||||
disableSTDIO, shellExpandArguments, trace,
|
||||
initCommands, preRunCommands, stopCommands, exitCommands,
|
||||
sourcePath, debuggerRoot)
|
||||
sourcePath, debuggerRoot, inheritEnvironment=inheritEnvironment)
|
||||
|
@ -570,7 +570,7 @@ class DebugCommunication(object):
|
||||
disableSTDIO=False, shellExpandArguments=False,
|
||||
trace=False, initCommands=None, preRunCommands=None,
|
||||
stopCommands=None, exitCommands=None, sourcePath=None,
|
||||
debuggerRoot=None, launchCommands=None):
|
||||
debuggerRoot=None, launchCommands=None, inheritEnvironment=False):
|
||||
args_dict = {
|
||||
'program': program
|
||||
}
|
||||
@ -605,6 +605,8 @@ class DebugCommunication(object):
|
||||
args_dict['debuggerRoot'] = debuggerRoot
|
||||
if launchCommands:
|
||||
args_dict['launchCommands'] = launchCommands
|
||||
if inheritEnvironment:
|
||||
args_dict['inheritEnvironment'] = inheritEnvironment
|
||||
command_dict = {
|
||||
'command': 'launch',
|
||||
'type': 'request',
|
||||
@ -912,7 +914,8 @@ def run_vscode(dbg, args, options):
|
||||
initCommands=options.initCmds,
|
||||
preRunCommands=options.preRunCmds,
|
||||
stopCommands=options.stopCmds,
|
||||
exitCommands=options.exitCmds)
|
||||
exitCommands=options.exitCmds,
|
||||
inheritEnvironment=options.inheritEnvironment)
|
||||
|
||||
if response['success']:
|
||||
if options.sourceBreakpoints:
|
||||
|
@ -0,0 +1,3 @@
|
||||
CXX_SOURCES := main.cpp
|
||||
|
||||
include Makefile.rules
|
@ -0,0 +1,107 @@
|
||||
"""
|
||||
Test lldb-vscode environment variables
|
||||
"""
|
||||
|
||||
|
||||
import lldbvscode_testcase
|
||||
import unittest2
|
||||
import vscode
|
||||
import os
|
||||
from lldbsuite.test import lldbutil
|
||||
from lldbsuite.test.decorators import *
|
||||
from lldbsuite.test.lldbtest import *
|
||||
|
||||
class TestVSCode_variables(lldbvscode_testcase.VSCodeTestCaseBase):
|
||||
|
||||
mydir = TestBase.compute_mydir(__file__)
|
||||
|
||||
def getEnvOutputByProgram(self):
|
||||
env = {}
|
||||
for line in self.get_stdout().encode('utf-8').splitlines():
|
||||
(name, value) = line.split("=")
|
||||
env[name] = value
|
||||
return env
|
||||
|
||||
@skipIfWindows
|
||||
@skipIfRemote
|
||||
def test_empty_environment(self):
|
||||
"""
|
||||
Tests running a process with an empty environment
|
||||
"""
|
||||
program = self.getBuildArtifact("a.out")
|
||||
self.build_and_launch(program)
|
||||
self.continue_to_exit()
|
||||
env = self.getEnvOutputByProgram()
|
||||
|
||||
self.assertNotIn("PATH", env)
|
||||
|
||||
@skipIfWindows
|
||||
@skipIfRemote
|
||||
def test_inheriting_environment(self):
|
||||
"""
|
||||
Tests running a process inheriting the environment
|
||||
"""
|
||||
program = self.getBuildArtifact("a.out")
|
||||
self.build_and_launch(program, inheritEnvironment=True, env=["FOO=bar"])
|
||||
self.continue_to_exit()
|
||||
env = self.getEnvOutputByProgram()
|
||||
|
||||
self.assertEqual(env["PATH"], os.environ['PATH'])
|
||||
self.assertEqual(env["FOO"], "bar")
|
||||
|
||||
@skipIfWindows
|
||||
@skipIfRemote
|
||||
def test_override_when_inheriting_environment(self):
|
||||
"""
|
||||
Tests the environment variables priority.
|
||||
The launch.json's environment has precedence.
|
||||
"""
|
||||
program = self.getBuildArtifact("a.out")
|
||||
new_path_value = "#" + os.environ["PATH"]
|
||||
|
||||
self.build_and_launch(
|
||||
program,
|
||||
inheritEnvironment=True,
|
||||
env=["PATH=" + new_path_value])
|
||||
self.continue_to_exit()
|
||||
env = self.getEnvOutputByProgram()
|
||||
|
||||
self.assertEqual(env["PATH"], new_path_value)
|
||||
|
||||
@skipIfWindows
|
||||
@skipIfRemote
|
||||
def test_empty_environment_custom_launcher(self):
|
||||
"""
|
||||
Tests running a process with an empty environment from a custom
|
||||
launcher
|
||||
"""
|
||||
program = self.getBuildArtifact("a.out")
|
||||
self.build_and_create_debug_adaptor()
|
||||
|
||||
launchCommands = [
|
||||
'target create "%s"' % (program),
|
||||
"run"
|
||||
]
|
||||
self.launch(launchCommands=launchCommands)
|
||||
self.continue_to_exit()
|
||||
env = self.getEnvOutputByProgram()
|
||||
self.assertNotIn("PATH", env)
|
||||
|
||||
@skipIfWindows
|
||||
@skipIfRemote
|
||||
def test_inheriting_environment_custom_launcher(self):
|
||||
"""
|
||||
Tests running a process from a custom launcher inheriting the
|
||||
environment
|
||||
"""
|
||||
program = self.getBuildArtifact("a.out")
|
||||
self.build_and_create_debug_adaptor()
|
||||
|
||||
launchCommands = [
|
||||
'target create "%s"' % (program),
|
||||
"run"
|
||||
]
|
||||
self.launch(launchCommands=launchCommands, inheritEnvironment=True)
|
||||
self.continue_to_exit()
|
||||
env = self.getEnvOutputByProgram()
|
||||
self.assertIn("PATH", env)
|
@ -0,0 +1,15 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
extern char **environ;
|
||||
|
||||
int main(int argc, char const *argv[]) {
|
||||
char **env_var_pointer = environ;
|
||||
for (char *env_variable = *env_var_pointer; env_variable;
|
||||
env_variable = *++env_var_pointer) {
|
||||
printf("%s\n", env_variable);
|
||||
}
|
||||
return 0;
|
||||
}
|
@ -40,6 +40,7 @@
|
||||
#include <sstream>
|
||||
#include <thread>
|
||||
|
||||
#include "lldb/API/SBEnvironment.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/Option/Arg.h"
|
||||
#include "llvm/Option/ArgList.h"
|
||||
@ -1355,6 +1356,8 @@ void request_launch(const llvm::json::Object &request) {
|
||||
auto launchCommands = GetStrings(arguments, "launchCommands");
|
||||
g_vsc.stop_at_entry = GetBoolean(arguments, "stopOnEntry", false);
|
||||
const auto debuggerRoot = GetString(arguments, "debuggerRoot");
|
||||
bool launchWithDebuggerEnvironment =
|
||||
GetBoolean(arguments, "inheritEnvironment", false);
|
||||
|
||||
// This is a hack for loading DWARF in .o files on Mac where the .o files
|
||||
// in the debug map of the main executable have relative paths which require
|
||||
@ -1371,6 +1374,13 @@ void request_launch(const llvm::json::Object &request) {
|
||||
// the targets - preRunCommands are run with the target.
|
||||
g_vsc.RunInitCommands();
|
||||
|
||||
// Reset the default value of the inherit environment setting, so that the
|
||||
// environment of programs launched by launchCommands is consistent with the
|
||||
// "inheritEnvironment" argument.
|
||||
if (!launchWithDebuggerEnvironment)
|
||||
g_vsc.RunLLDBCommands(llvm::StringRef(),
|
||||
{"settings set target.inherit-env false"});
|
||||
|
||||
lldb::SBError status;
|
||||
g_vsc.SetTarget(g_vsc.CreateTargetFromArguments(*arguments, status));
|
||||
if (status.Fail()) {
|
||||
@ -1395,10 +1405,12 @@ void request_launch(const llvm::json::Object &request) {
|
||||
if (!args.empty())
|
||||
g_vsc.launch_info.SetArguments(MakeArgv(args).data(), true);
|
||||
|
||||
// Pass any environment variables along that the user specified.
|
||||
auto envs = GetStrings(arguments, "env");
|
||||
if (!envs.empty())
|
||||
g_vsc.launch_info.SetEnvironmentEntries(MakeArgv(envs).data(), true);
|
||||
// This mimics what CommandObjectProcess does when launching a process
|
||||
lldb::SBEnvironment env = g_vsc.target.GetEnvironment();
|
||||
for (const auto &name_and_value : GetStrings(arguments, "env"))
|
||||
env.PutEntry(name_and_value.c_str());
|
||||
|
||||
g_vsc.launch_info.SetEnvironment(env, true);
|
||||
|
||||
auto flags = g_vsc.launch_info.GetLaunchFlags();
|
||||
|
||||
|
@ -84,6 +84,11 @@
|
||||
"description": "Additional environment variables.",
|
||||
"default": []
|
||||
},
|
||||
"inheritEnvironment": {
|
||||
"type": "boolean",
|
||||
"description": "Inherit the debugger environment when launching a process. Only works for binaries launched directly by LLDB.",
|
||||
"default": false
|
||||
},
|
||||
"stopOnEntry": {
|
||||
"type": "boolean",
|
||||
"description": "Automatically stop after launch.",
|
||||
|
Loading…
Reference in New Issue
Block a user