blob: 7de55f2fdcf9afdee06431740dba1b8804d288c1 [file] [log] [blame]
Todd Fiala6d6b55d2014-06-30 00:30:53 +00001//===-- ProcessLaunchInfo.cpp -----------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Eugene Zelenko9394d7722016-02-18 00:10:17 +000010// C Includes
11// C++ Includes
12#include <climits>
Todd Fiala2850b1b2014-06-30 23:51:35 +000013
Eugene Zelenko9394d7722016-02-18 00:10:17 +000014// Other libraries and framework includes
15// Project includes
Greg Clayton8012cad2014-11-17 19:39:20 +000016#include "lldb/Core/Debugger.h"
Zachary Turner190fadc2016-03-22 17:58:09 +000017#include "lldb/Host/Config.h"
Zachary Turner4eff2d32015-10-14 21:37:36 +000018#include "lldb/Host/FileSystem.h"
Zachary Turner190fadc2016-03-22 17:58:09 +000019#include "lldb/Host/HostInfo.h"
Zachary Turner696b5282014-08-14 16:01:25 +000020#include "lldb/Target/FileAction.h"
Zachary Turner190fadc2016-03-22 17:58:09 +000021#include "lldb/Target/ProcessLaunchInfo.h"
Todd Fiala6d6b55d2014-06-30 00:30:53 +000022#include "lldb/Target/Target.h"
Zachary Turner6f9e6902017-03-03 20:56:28 +000023#include "lldb/Utility/Log.h"
Zachary Turner2f3df612017-04-06 21:28:29 +000024#include "lldb/Utility/StreamString.h"
Todd Fiala6d6b55d2014-06-30 00:30:53 +000025
Zachary Turner190fadc2016-03-22 17:58:09 +000026#include "llvm/Support/ConvertUTF.h"
Pavel Labath1d5855b2017-01-23 15:56:45 +000027#include "llvm/Support/FileSystem.h"
Zachary Turner190fadc2016-03-22 17:58:09 +000028
29#if !defined(_WIN32)
30#include <limits.h>
31#endif
32
Todd Fiala6d6b55d2014-06-30 00:30:53 +000033using namespace lldb;
34using namespace lldb_private;
35
36//----------------------------------------------------------------------------
Todd Fiala6d6b55d2014-06-30 00:30:53 +000037// ProcessLaunchInfo member functions
38//----------------------------------------------------------------------------
39
Kate Stoneb9c1b512016-09-06 20:57:50 +000040ProcessLaunchInfo::ProcessLaunchInfo()
41 : ProcessInfo(), m_working_dir(), m_plugin_name(), m_flags(0),
42 m_file_actions(), m_pty(new lldb_utility::PseudoTerminal),
43 m_resume_count(0), m_monitor_callback(nullptr),
44 m_monitor_callback_baton(nullptr), m_monitor_signals(false),
45 m_listener_sp(), m_hijack_listener_sp() {}
Todd Fiala6d6b55d2014-06-30 00:30:53 +000046
Chaoren Lind3173f32015-05-29 19:52:29 +000047ProcessLaunchInfo::ProcessLaunchInfo(const FileSpec &stdin_file_spec,
48 const FileSpec &stdout_file_spec,
49 const FileSpec &stderr_file_spec,
50 const FileSpec &working_directory,
Kate Stoneb9c1b512016-09-06 20:57:50 +000051 uint32_t launch_flags)
52 : ProcessInfo(), m_working_dir(), m_plugin_name(), m_flags(launch_flags),
53 m_file_actions(), m_pty(new lldb_utility::PseudoTerminal),
54 m_resume_count(0), m_monitor_callback(nullptr),
55 m_monitor_callback_baton(nullptr), m_monitor_signals(false),
56 m_listener_sp(), m_hijack_listener_sp() {
57 if (stdin_file_spec) {
Todd Fiala6d6b55d2014-06-30 00:30:53 +000058 FileAction file_action;
Kate Stoneb9c1b512016-09-06 20:57:50 +000059 const bool read = true;
60 const bool write = false;
61 if (file_action.Open(STDIN_FILENO, stdin_file_spec, read, write))
62 AppendFileAction(file_action);
63 }
64 if (stdout_file_spec) {
Todd Fiala6d6b55d2014-06-30 00:30:53 +000065 FileAction file_action;
Kate Stoneb9c1b512016-09-06 20:57:50 +000066 const bool read = false;
67 const bool write = true;
68 if (file_action.Open(STDOUT_FILENO, stdout_file_spec, read, write))
69 AppendFileAction(file_action);
70 }
71 if (stderr_file_spec) {
Todd Fiala6d6b55d2014-06-30 00:30:53 +000072 FileAction file_action;
Kate Stoneb9c1b512016-09-06 20:57:50 +000073 const bool read = false;
74 const bool write = true;
75 if (file_action.Open(STDERR_FILENO, stderr_file_spec, read, write))
76 AppendFileAction(file_action);
77 }
78 if (working_directory)
79 SetWorkingDirectory(working_directory);
Todd Fiala6d6b55d2014-06-30 00:30:53 +000080}
81
Kate Stoneb9c1b512016-09-06 20:57:50 +000082bool ProcessLaunchInfo::AppendCloseFileAction(int fd) {
83 FileAction file_action;
84 if (file_action.Close(fd)) {
85 AppendFileAction(file_action);
86 return true;
87 }
88 return false;
Todd Fiala6d6b55d2014-06-30 00:30:53 +000089}
90
Kate Stoneb9c1b512016-09-06 20:57:50 +000091bool ProcessLaunchInfo::AppendDuplicateFileAction(int fd, int dup_fd) {
92 FileAction file_action;
93 if (file_action.Duplicate(fd, dup_fd)) {
94 AppendFileAction(file_action);
95 return true;
96 }
97 return false;
Todd Fiala6d6b55d2014-06-30 00:30:53 +000098}
99
Kate Stoneb9c1b512016-09-06 20:57:50 +0000100bool ProcessLaunchInfo::AppendOpenFileAction(int fd, const FileSpec &file_spec,
101 bool read, bool write) {
102 FileAction file_action;
103 if (file_action.Open(fd, file_spec, read, write)) {
104 AppendFileAction(file_action);
105 return true;
106 }
107 return false;
Todd Fiala6d6b55d2014-06-30 00:30:53 +0000108}
109
Kate Stoneb9c1b512016-09-06 20:57:50 +0000110bool ProcessLaunchInfo::AppendSuppressFileAction(int fd, bool read,
111 bool write) {
112 FileAction file_action;
113 if (file_action.Open(fd, FileSpec{FileSystem::DEV_NULL, false}, read,
114 write)) {
115 AppendFileAction(file_action);
116 return true;
117 }
118 return false;
Todd Fiala6d6b55d2014-06-30 00:30:53 +0000119}
120
Kate Stoneb9c1b512016-09-06 20:57:50 +0000121const FileAction *ProcessLaunchInfo::GetFileActionAtIndex(size_t idx) const {
122 if (idx < m_file_actions.size())
123 return &m_file_actions[idx];
124 return nullptr;
Todd Fiala6d6b55d2014-06-30 00:30:53 +0000125}
126
Kate Stoneb9c1b512016-09-06 20:57:50 +0000127const FileAction *ProcessLaunchInfo::GetFileActionForFD(int fd) const {
128 for (size_t idx = 0, count = m_file_actions.size(); idx < count; ++idx) {
129 if (m_file_actions[idx].GetFD() == fd)
130 return &m_file_actions[idx];
131 }
132 return nullptr;
Todd Fiala6d6b55d2014-06-30 00:30:53 +0000133}
134
Kate Stoneb9c1b512016-09-06 20:57:50 +0000135const FileSpec &ProcessLaunchInfo::GetWorkingDirectory() const {
136 return m_working_dir;
Todd Fiala6d6b55d2014-06-30 00:30:53 +0000137}
138
Kate Stoneb9c1b512016-09-06 20:57:50 +0000139void ProcessLaunchInfo::SetWorkingDirectory(const FileSpec &working_dir) {
140 m_working_dir = working_dir;
Todd Fiala6d6b55d2014-06-30 00:30:53 +0000141}
142
Kate Stoneb9c1b512016-09-06 20:57:50 +0000143const char *ProcessLaunchInfo::GetProcessPluginName() const {
144 return (m_plugin_name.empty() ? nullptr : m_plugin_name.c_str());
Todd Fiala6d6b55d2014-06-30 00:30:53 +0000145}
146
Zachary Turnerfe114832016-11-12 16:56:47 +0000147void ProcessLaunchInfo::SetProcessPluginName(llvm::StringRef plugin) {
148 m_plugin_name = plugin;
Todd Fiala6d6b55d2014-06-30 00:30:53 +0000149}
150
Kate Stoneb9c1b512016-09-06 20:57:50 +0000151const FileSpec &ProcessLaunchInfo::GetShell() const { return m_shell; }
152
153void ProcessLaunchInfo::SetShell(const FileSpec &shell) {
154 m_shell = shell;
155 if (m_shell) {
156 m_shell.ResolveExecutableLocation();
157 m_flags.Set(lldb::eLaunchFlagLaunchInShell);
158 } else
159 m_flags.Clear(lldb::eLaunchFlagLaunchInShell);
Todd Fiala6d6b55d2014-06-30 00:30:53 +0000160}
161
Kate Stoneb9c1b512016-09-06 20:57:50 +0000162void ProcessLaunchInfo::SetLaunchInSeparateProcessGroup(bool separate) {
163 if (separate)
164 m_flags.Set(lldb::eLaunchFlagLaunchInSeparateProcessGroup);
165 else
166 m_flags.Clear(lldb::eLaunchFlagLaunchInSeparateProcessGroup);
167}
168
169void ProcessLaunchInfo::SetShellExpandArguments(bool expand) {
170 if (expand)
171 m_flags.Set(lldb::eLaunchFlagShellExpandArguments);
172 else
173 m_flags.Clear(lldb::eLaunchFlagShellExpandArguments);
174}
175
176void ProcessLaunchInfo::Clear() {
177 ProcessInfo::Clear();
178 m_working_dir.Clear();
179 m_plugin_name.clear();
180 m_shell.Clear();
181 m_flags.Clear();
182 m_file_actions.clear();
183 m_resume_count = 0;
184 m_listener_sp.reset();
185 m_hijack_listener_sp.reset();
186}
187
188void ProcessLaunchInfo::SetMonitorProcessCallback(
189 const Host::MonitorChildProcessCallback &callback, bool monitor_signals) {
190 m_monitor_callback = callback;
191 m_monitor_signals = monitor_signals;
192}
193
194bool ProcessLaunchInfo::MonitorProcess() const {
195 if (m_monitor_callback && ProcessIDIsValid()) {
196 Host::StartMonitoringChildProcess(m_monitor_callback, GetProcessID(),
197 m_monitor_signals);
198 return true;
199 }
200 return false;
201}
202
203void ProcessLaunchInfo::SetDetachOnError(bool enable) {
204 if (enable)
205 m_flags.Set(lldb::eLaunchFlagDetachOnError);
206 else
207 m_flags.Clear(lldb::eLaunchFlagDetachOnError);
208}
209
210void ProcessLaunchInfo::FinalizeFileActions(Target *target,
211 bool default_to_use_pty) {
212 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
213
214 // If nothing for stdin or stdout or stderr was specified, then check the
215 // process for any default
216 // settings that were set with "settings set"
217 if (GetFileActionForFD(STDIN_FILENO) == nullptr ||
218 GetFileActionForFD(STDOUT_FILENO) == nullptr ||
219 GetFileActionForFD(STDERR_FILENO) == nullptr) {
220 if (log)
221 log->Printf("ProcessLaunchInfo::%s at least one of stdin/stdout/stderr "
222 "was not set, evaluating default handling",
223 __FUNCTION__);
224
225 if (m_flags.Test(eLaunchFlagLaunchInTTY)) {
226 // Do nothing, if we are launching in a remote terminal
227 // no file actions should be done at all.
228 return;
Todd Fiala6d6b55d2014-06-30 00:30:53 +0000229 }
Todd Fiala6d6b55d2014-06-30 00:30:53 +0000230
Kate Stoneb9c1b512016-09-06 20:57:50 +0000231 if (m_flags.Test(eLaunchFlagDisableSTDIO)) {
232 if (log)
233 log->Printf("ProcessLaunchInfo::%s eLaunchFlagDisableSTDIO set, adding "
234 "suppression action for stdin, stdout and stderr",
235 __FUNCTION__);
236 AppendSuppressFileAction(STDIN_FILENO, true, false);
237 AppendSuppressFileAction(STDOUT_FILENO, false, true);
238 AppendSuppressFileAction(STDERR_FILENO, false, true);
239 } else {
240 // Check for any values that might have gotten set with any of:
241 // (lldb) settings set target.input-path
242 // (lldb) settings set target.output-path
243 // (lldb) settings set target.error-path
244 FileSpec in_file_spec;
245 FileSpec out_file_spec;
246 FileSpec err_file_spec;
247 if (target) {
248 // Only override with the target settings if we don't already have
249 // an action for in, out or error
250 if (GetFileActionForFD(STDIN_FILENO) == nullptr)
251 in_file_spec = target->GetStandardInputPath();
252 if (GetFileActionForFD(STDOUT_FILENO) == nullptr)
253 out_file_spec = target->GetStandardOutputPath();
254 if (GetFileActionForFD(STDERR_FILENO) == nullptr)
255 err_file_spec = target->GetStandardErrorPath();
256 }
Todd Fiala6d6b55d2014-06-30 00:30:53 +0000257
Kate Stoneb9c1b512016-09-06 20:57:50 +0000258 if (log)
259 log->Printf("ProcessLaunchInfo::%s target stdin='%s', target "
260 "stdout='%s', stderr='%s'",
261 __FUNCTION__,
262 in_file_spec ? in_file_spec.GetCString() : "<null>",
263 out_file_spec ? out_file_spec.GetCString() : "<null>",
264 err_file_spec ? err_file_spec.GetCString() : "<null>");
Todd Fiala75f47c32014-10-11 21:42:09 +0000265
Kate Stoneb9c1b512016-09-06 20:57:50 +0000266 if (in_file_spec) {
267 AppendOpenFileAction(STDIN_FILENO, in_file_spec, true, false);
Todd Fiala75f47c32014-10-11 21:42:09 +0000268 if (log)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000269 log->Printf(
270 "ProcessLaunchInfo::%s appended stdin open file action for %s",
271 __FUNCTION__, in_file_spec.GetCString());
272 }
Todd Fiala75f47c32014-10-11 21:42:09 +0000273
Kate Stoneb9c1b512016-09-06 20:57:50 +0000274 if (out_file_spec) {
275 AppendOpenFileAction(STDOUT_FILENO, out_file_spec, false, true);
276 if (log)
277 log->Printf(
278 "ProcessLaunchInfo::%s appended stdout open file action for %s",
279 __FUNCTION__, out_file_spec.GetCString());
280 }
Greg Claytonbf91f712015-07-10 18:04:46 +0000281
Kate Stoneb9c1b512016-09-06 20:57:50 +0000282 if (err_file_spec) {
283 AppendOpenFileAction(STDERR_FILENO, err_file_spec, false, true);
284 if (log)
285 log->Printf(
286 "ProcessLaunchInfo::%s appended stderr open file action for %s",
287 __FUNCTION__, err_file_spec.GetCString());
288 }
Todd Fiala6d6b55d2014-06-30 00:30:53 +0000289
Kate Stoneb9c1b512016-09-06 20:57:50 +0000290 if (default_to_use_pty &&
291 (!in_file_spec || !out_file_spec || !err_file_spec)) {
292 if (log)
293 log->Printf("ProcessLaunchInfo::%s default_to_use_pty is set, and at "
294 "least one stdin/stderr/stdout is unset, so generating a "
295 "pty to use for it",
296 __FUNCTION__);
Todd Fiala75f47c32014-10-11 21:42:09 +0000297
Kate Stoneb9c1b512016-09-06 20:57:50 +0000298 int open_flags = O_RDWR | O_NOCTTY;
Hafiz Abid Qadeerf6ee79c2016-12-15 15:00:41 +0000299#if !defined(_WIN32)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000300 // We really shouldn't be specifying platform specific flags
301 // that are intended for a system call in generic code. But
302 // this will have to do for now.
303 open_flags |= O_CLOEXEC;
Zachary Turner362a8132015-02-04 19:11:48 +0000304#endif
Kate Stoneb9c1b512016-09-06 20:57:50 +0000305 if (m_pty->OpenFirstAvailableMaster(open_flags, nullptr, 0)) {
306 const FileSpec slave_file_spec{m_pty->GetSlaveName(nullptr, 0),
307 false};
Todd Fiala6d6b55d2014-06-30 00:30:53 +0000308
Kate Stoneb9c1b512016-09-06 20:57:50 +0000309 // Only use the slave tty if we don't have anything specified for
310 // input and don't have an action for stdin
311 if (!in_file_spec && GetFileActionForFD(STDIN_FILENO) == nullptr) {
312 AppendOpenFileAction(STDIN_FILENO, slave_file_spec, true, false);
313 }
Todd Fiala6d6b55d2014-06-30 00:30:53 +0000314
Kate Stoneb9c1b512016-09-06 20:57:50 +0000315 // Only use the slave tty if we don't have anything specified for
316 // output and don't have an action for stdout
317 if (!out_file_spec && GetFileActionForFD(STDOUT_FILENO) == nullptr) {
318 AppendOpenFileAction(STDOUT_FILENO, slave_file_spec, false, true);
319 }
Todd Fiala6d6b55d2014-06-30 00:30:53 +0000320
Kate Stoneb9c1b512016-09-06 20:57:50 +0000321 // Only use the slave tty if we don't have anything specified for
322 // error and don't have an action for stderr
323 if (!err_file_spec && GetFileActionForFD(STDERR_FILENO) == nullptr) {
324 AppendOpenFileAction(STDERR_FILENO, slave_file_spec, false, true);
325 }
Todd Fiala6d6b55d2014-06-30 00:30:53 +0000326 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000327 }
Todd Fiala6d6b55d2014-06-30 00:30:53 +0000328 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000329 }
Todd Fiala6d6b55d2014-06-30 00:30:53 +0000330}
331
Kate Stoneb9c1b512016-09-06 20:57:50 +0000332bool ProcessLaunchInfo::ConvertArgumentsForLaunchingInShell(
333 Error &error, bool localhost, bool will_debug,
334 bool first_arg_is_full_shell_command, int32_t num_resumes) {
335 error.Clear();
Todd Fiala6d6b55d2014-06-30 00:30:53 +0000336
Kate Stoneb9c1b512016-09-06 20:57:50 +0000337 if (GetFlags().Test(eLaunchFlagLaunchInShell)) {
338 if (m_shell) {
339 std::string shell_executable = m_shell.GetPath();
Todd Fiala6d6b55d2014-06-30 00:30:53 +0000340
Kate Stoneb9c1b512016-09-06 20:57:50 +0000341 const char **argv = GetArguments().GetConstArgumentVector();
342 if (argv == nullptr || argv[0] == nullptr)
343 return false;
344 Args shell_arguments;
345 std::string safe_arg;
Zachary Turnerecbb0bb2016-09-19 17:54:06 +0000346 shell_arguments.AppendArgument(shell_executable);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000347 const llvm::Triple &triple = GetArchitecture().GetTriple();
348 if (triple.getOS() == llvm::Triple::Win32 &&
349 !triple.isWindowsCygwinEnvironment())
Zachary Turnerecbb0bb2016-09-19 17:54:06 +0000350 shell_arguments.AppendArgument(llvm::StringRef("/C"));
Kate Stoneb9c1b512016-09-06 20:57:50 +0000351 else
Zachary Turnerecbb0bb2016-09-19 17:54:06 +0000352 shell_arguments.AppendArgument(llvm::StringRef("-c"));
Zachary Turner270e99a2014-12-08 21:36:42 +0000353
Kate Stoneb9c1b512016-09-06 20:57:50 +0000354 StreamString shell_command;
355 if (will_debug) {
356 // Add a modified PATH environment variable in case argv[0]
357 // is a relative path.
358 const char *argv0 = argv[0];
359 FileSpec arg_spec(argv0, false);
360 if (arg_spec.IsRelative()) {
361 // We have a relative path to our executable which may not work if
362 // we just try to run "a.out" (without it being converted to
363 // "./a.out")
364 FileSpec working_dir = GetWorkingDirectory();
365 // Be sure to put quotes around PATH's value in case any paths have
366 // spaces...
367 std::string new_path("PATH=\"");
368 const size_t empty_path_len = new_path.size();
Todd Fiala6d6b55d2014-06-30 00:30:53 +0000369
Kate Stoneb9c1b512016-09-06 20:57:50 +0000370 if (working_dir) {
371 new_path += working_dir.GetPath();
372 } else {
Pavel Labath1d5855b2017-01-23 15:56:45 +0000373 llvm::SmallString<64> cwd;
374 if (! llvm::sys::fs::current_path(cwd))
Kate Stoneb9c1b512016-09-06 20:57:50 +0000375 new_path += cwd;
376 }
377 std::string curr_path;
378 if (HostInfo::GetEnvironmentVar("PATH", curr_path)) {
379 if (new_path.size() > empty_path_len)
380 new_path += ':';
381 new_path += curr_path;
382 }
383 new_path += "\" ";
Malcolm Parsons771ef6d2016-11-02 20:34:10 +0000384 shell_command.PutCString(new_path);
Todd Fiala6d6b55d2014-06-30 00:30:53 +0000385 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000386
387 if (triple.getOS() != llvm::Triple::Win32 ||
388 triple.isWindowsCygwinEnvironment())
389 shell_command.PutCString("exec");
390
391 // Only Apple supports /usr/bin/arch being able to specify the
392 // architecture
393 if (GetArchitecture().IsValid() && // Valid architecture
394 GetArchitecture().GetTriple().getVendor() ==
395 llvm::Triple::Apple && // Apple only
396 GetArchitecture().GetCore() !=
397 ArchSpec::eCore_x86_64_x86_64h) // Don't do this for x86_64h
398 {
399 shell_command.Printf(" /usr/bin/arch -arch %s",
400 GetArchitecture().GetArchitectureName());
401 // Set the resume count to 2:
402 // 1 - stop in shell
403 // 2 - stop in /usr/bin/arch
404 // 3 - then we will stop in our program
405 SetResumeCount(num_resumes + 1);
406 } else {
407 // Set the resume count to 1:
408 // 1 - stop in shell
409 // 2 - then we will stop in our program
410 SetResumeCount(num_resumes);
411 }
412 }
413
414 if (first_arg_is_full_shell_command) {
415 // There should only be one argument that is the shell command itself to
416 // be used as is
417 if (argv[0] && !argv[1])
418 shell_command.Printf("%s", argv[0]);
Todd Fiala6d6b55d2014-06-30 00:30:53 +0000419 else
Kate Stoneb9c1b512016-09-06 20:57:50 +0000420 return false;
421 } else {
422 for (size_t i = 0; argv[i] != nullptr; ++i) {
423 const char *arg =
424 Args::GetShellSafeArgument(m_shell, argv[i], safe_arg);
425 shell_command.Printf(" %s", arg);
Todd Fiala6d6b55d2014-06-30 00:30:53 +0000426 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000427 }
Zachary Turnerecbb0bb2016-09-19 17:54:06 +0000428 shell_arguments.AppendArgument(shell_command.GetString());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000429 m_executable = m_shell;
430 m_arguments = shell_arguments;
431 return true;
432 } else {
433 error.SetErrorString("invalid shell path");
Todd Fiala6d6b55d2014-06-30 00:30:53 +0000434 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000435 } else {
436 error.SetErrorString("not launching in shell");
437 }
438 return false;
Todd Fiala6d6b55d2014-06-30 00:30:53 +0000439}
Greg Clayton8012cad2014-11-17 19:39:20 +0000440
Kate Stoneb9c1b512016-09-06 20:57:50 +0000441ListenerSP ProcessLaunchInfo::GetListenerForProcess(Debugger &debugger) {
442 if (m_listener_sp)
443 return m_listener_sp;
444 else
445 return debugger.GetListener();
Greg Clayton8012cad2014-11-17 19:39:20 +0000446}