[lldb/test] Add ability to specify environment when spawning processes

We only had that ability for regular debugger launches. This meant that
it was not possible to use the normal dlopen patterns in attach tests.
This fixes that.
This commit is contained in:
Pavel Labath 2021-09-27 14:12:29 +02:00
parent 156cb4cc64
commit 9413ead7bc
3 changed files with 28 additions and 37 deletions

View file

@ -360,7 +360,7 @@ class _BaseProcess(object):
"""Returns process PID if has been launched already."""
@abc.abstractmethod
def launch(self, executable, args):
def launch(self, executable, args, extra_env):
"""Launches new process with given executable and args."""
@abc.abstractmethod
@ -379,13 +379,19 @@ class _LocalProcess(_BaseProcess):
def pid(self):
return self._proc.pid
def launch(self, executable, args):
def launch(self, executable, args, extra_env):
env=None
if extra_env:
env = dict(os.environ)
env.update([kv.split("=", 1) for kv in extra_env])
self._proc = Popen(
[executable] + args,
stdout=open(
os.devnull) if not self._trace_on else None,
stdin=PIPE,
preexec_fn=lldbplatformutil.enable_attach)
preexec_fn=lldbplatformutil.enable_attach,
env=env)
def terminate(self):
if self._proc.poll() is None:
@ -424,7 +430,7 @@ class _RemoteProcess(_BaseProcess):
def pid(self):
return self._pid
def launch(self, executable, args):
def launch(self, executable, args, extra_env):
if self._install_remote:
src_path = executable
dst_path = lldbutil.join_remote_paths(
@ -450,6 +456,9 @@ class _RemoteProcess(_BaseProcess):
launch_info.AddSuppressFileAction(1, False, True)
launch_info.AddSuppressFileAction(2, False, True)
if extra_env:
launch_info.SetEnvironmentEntries(extra_env, True)
err = lldb.remote_platform.Launch(launch_info)
if err.Fail():
raise Exception(
@ -952,13 +961,13 @@ class Base(unittest2.TestCase):
del p
del self.subprocesses[:]
def spawnSubprocess(self, executable, args=[], install_remote=True):
def spawnSubprocess(self, executable, args=[], extra_env=None, install_remote=True):
""" Creates a subprocess.Popen object with the specified executable and arguments,
saves it in self.subprocesses, and returns the object.
"""
proc = _RemoteProcess(
install_remote) if lldb.remote_platform else _LocalProcess(self.TraceOn())
proc.launch(executable, args)
proc.launch(executable, args, extra_env=extra_env)
self.subprocesses.append(proc)
return proc

View file

@ -6,6 +6,7 @@ from lldbsuite.test import lldbutil
class TestCase(TestBase):
mydir = TestBase.compute_mydir(__file__)
NO_DEBUG_INFO_TESTCASE = True
@skipIfRemote
def test_load_after_attach(self):
@ -17,18 +18,19 @@ class TestCase(TestBase):
exe = self.getBuildArtifact("a.out")
lib = self.getBuildArtifact(lib_name)
target = self.dbg.CreateTarget(exe)
environment = self.registerSharedLibrariesWithTarget(target, ["lib_b"])
# Spawn a new process.
# use realpath to workaround llvm.org/pr48376
# Pass path to solib for dlopen to properly locate the library.
popen = self.spawnSubprocess(os.path.realpath(exe), args = [os.path.realpath(lib)])
pid = popen.pid
popen = self.spawnSubprocess(os.path.realpath(exe), extra_env=environment)
# Attach to the spawned process.
self.runCmd("process attach -p " + str(pid))
target = self.dbg.GetSelectedTarget()
process = target.GetProcess()
self.assertTrue(process, PROCESS_IS_VALID)
error = lldb.SBError()
process = target.AttachToProcessWithID(self.dbg.GetListener(),
popen.pid, error)
self.assertSuccess(error)
# Continue until first breakpoint.
breakpoint1 = self.target().BreakpointCreateBySourceRegex(

View file

@ -1,30 +1,10 @@
#ifdef _WIN32
#include <Windows.h>
#else
#include <dlfcn.h>
#include <unistd.h>
#endif
#include <assert.h>
#include <stdio.h>
#include "dylib.h"
#include <cassert>
#include <cstdio>
#include <thread>
#include <chrono>
// We do not use the dylib.h implementation, because
// we need to pass full path to the dylib.
void* dylib_open(const char* full_path) {
#ifdef _WIN32
return LoadLibraryA(full_path);
#else
return dlopen(full_path, RTLD_LAZY);
#endif
}
int main(int argc, char* argv[]) {
assert(argc == 2 && "argv[1] must be the full path to lib_b library");
const char* dylib_full_path= argv[1];
printf("Using dylib at: %s\n", dylib_full_path);
// Wait until debugger is attached.
int main_thread_continue = 0;
int i = 0;
@ -38,7 +18,7 @@ int main(int argc, char* argv[]) {
assert(i != timeout && "timed out waiting for debugger");
// dlopen the 'liblib_b.so' shared library.
void* dylib_handle = dylib_open(dylib_full_path);
void* dylib_handle = dylib_open("lib_b");
assert(dylib_handle && "dlopen failed");
return i; // break after dlopen