Author: jingham
Date: Mon Oct 13 20:20:07 2014
New Revision: 219654
URL: http://llvm.org/viewvc/llvm-project?rev=219654&view=rev
Log:
This adds a "batch mode" to lldb kinda like the gdb batch mode. It will quit
the debugger
after all the commands have been executed except if one of the commands was an
execution control
command that stopped because of a signal or exception.
Also adds a variant of SBCommandInterpreter::HandleCommand that takes an
SBExecutionContext. That
way you can run an lldb command targeted at a particular target, thread or
process w/o having to
select same before running the command.
Also exposes CommandInterpreter::HandleCommandsFromFile to the
SBCommandInterpreter API, since that
seemed generally useful.
Modified:
lldb/trunk/include/lldb/API/SBCommandInterpreter.h
lldb/trunk/include/lldb/API/SBDebugger.h
lldb/trunk/include/lldb/API/SBExecutionContext.h
lldb/trunk/include/lldb/API/SBFileSpec.h
lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h
lldb/trunk/lldb.xcodeproj/xcshareddata/xcschemes/lldb-tool.xcscheme
lldb/trunk/scripts/Python/interface/SBCommandInterpreter.i
lldb/trunk/scripts/Python/interface/SBDebugger.i
lldb/trunk/source/API/SBCommandInterpreter.cpp
lldb/trunk/source/API/SBDebugger.cpp
lldb/trunk/source/API/SBExecutionContext.cpp
lldb/trunk/source/Interpreter/CommandInterpreter.cpp
lldb/trunk/tools/driver/Driver.cpp
lldb/trunk/tools/driver/Driver.h
Modified: lldb/trunk/include/lldb/API/SBCommandInterpreter.h
URL:
http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBCommandInterpreter.h?rev=219654&r1=219653&r2=219654&view=diff
==============================================================================
--- lldb/trunk/include/lldb/API/SBCommandInterpreter.h (original)
+++ lldb/trunk/include/lldb/API/SBCommandInterpreter.h Mon Oct 13 20:20:07 2014
@@ -18,6 +18,8 @@ namespace lldb {
class SBCommandInterpreterRunOptions
{
friend class SBDebugger;
+friend class SBCommandInterpreter;
+
public:
SBCommandInterpreterRunOptions();
~SBCommandInterpreterRunOptions();
@@ -138,6 +140,15 @@ public:
lldb::ReturnStatus
HandleCommand (const char *command_line, lldb::SBCommandReturnObject
&result, bool add_to_history = false);
+ lldb::ReturnStatus
+ HandleCommand (const char *command_line, SBExecutionContext &exe_ctx,
SBCommandReturnObject &result, bool add_to_history = false);
+
+ void
+ HandleCommandsFromFile (lldb::SBFileSpec &file,
+ lldb::SBExecutionContext &override_context,
+ lldb::SBCommandInterpreterRunOptions &options,
+ lldb::SBCommandReturnObject result);
+
// The pointer based interface is not useful in SWIG, since the cursor &
last_char arguments are string pointers INTO current_line
// and you can't do that in a scripting language interface in general...
Modified: lldb/trunk/include/lldb/API/SBDebugger.h
URL:
http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBDebugger.h?rev=219654&r1=219653&r2=219654&view=diff
==============================================================================
--- lldb/trunk/include/lldb/API/SBDebugger.h (original)
+++ lldb/trunk/include/lldb/API/SBDebugger.h Mon Oct 13 20:20:07 2014
@@ -327,7 +327,8 @@ public:
bool spawn_thread,
SBCommandInterpreterRunOptions &options,
int &num_errors,
- bool &quit_requested);
+ bool &quit_requested,
+ bool &stopped_for_crash);
private:
friend class SBCommandInterpreter;
Modified: lldb/trunk/include/lldb/API/SBExecutionContext.h
URL:
http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBExecutionContext.h?rev=219654&r1=219653&r2=219654&view=diff
==============================================================================
--- lldb/trunk/include/lldb/API/SBExecutionContext.h (original)
+++ lldb/trunk/include/lldb/API/SBExecutionContext.h Mon Oct 13 20:20:07 2014
@@ -20,6 +20,8 @@ namespace lldb {
class SBExecutionContext
{
+friend class SBCommandInterpreter;
+
public:
SBExecutionContext();
Modified: lldb/trunk/include/lldb/API/SBFileSpec.h
URL:
http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBFileSpec.h?rev=219654&r1=219653&r2=219654&view=diff
==============================================================================
--- lldb/trunk/include/lldb/API/SBFileSpec.h (original)
+++ lldb/trunk/include/lldb/API/SBFileSpec.h Mon Oct 13 20:20:07 2014
@@ -63,6 +63,7 @@ public:
private:
friend class SBAttachInfo;
friend class SBBlock;
+ friend class SBCommandInterpreter;
friend class SBCompileUnit;
friend class SBDeclaration;
friend class SBFileSpecList;
Modified: lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h
URL:
http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h?rev=219654&r1=219653&r2=219654&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h (original)
+++ lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h Mon Oct 13
20:20:07 2014
@@ -628,6 +628,12 @@ public:
{
return m_quit_requested;
}
+
+ bool
+ GetStoppedForCrash () const
+ {
+ return m_stopped_for_crash;
+ }
protected:
friend class Debugger;
@@ -685,6 +691,7 @@ private:
std::vector<uint32_t> m_command_source_flags;
uint32_t m_num_errors;
bool m_quit_requested;
+ bool m_stopped_for_crash;
};
Modified: lldb/trunk/lldb.xcodeproj/xcshareddata/xcschemes/lldb-tool.xcscheme
URL:
http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/xcshareddata/xcschemes/lldb-tool.xcscheme?rev=219654&r1=219653&r2=219654&view=diff
==============================================================================
--- lldb/trunk/lldb.xcodeproj/xcshareddata/xcschemes/lldb-tool.xcscheme
(original)
+++ lldb/trunk/lldb.xcodeproj/xcshareddata/xcschemes/lldb-tool.xcscheme Mon Oct
13 20:20:07 2014
@@ -84,7 +84,7 @@
<LaunchAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
- launchStyle = "0"
+ launchStyle = "1"
useCustomWorkingDirectory = "NO"
customWorkingDirectory = "/Volumes/work/gclayton/Documents/devb/attach"
buildConfiguration = "Debug"
Modified: lldb/trunk/scripts/Python/interface/SBCommandInterpreter.i
URL:
http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/Python/interface/SBCommandInterpreter.i?rev=219654&r1=219653&r2=219654&view=diff
==============================================================================
--- lldb/trunk/scripts/Python/interface/SBCommandInterpreter.i (original)
+++ lldb/trunk/scripts/Python/interface/SBCommandInterpreter.i Mon Oct 13
20:20:07 2014
@@ -182,6 +182,15 @@ public:
lldb::ReturnStatus
HandleCommand (const char *command_line, lldb::SBCommandReturnObject
&result, bool add_to_history = false);
+ lldb::ReturnStatus
+ HandleCommand (const char *command_line, SBExecutionContext &exe_ctx,
SBCommandReturnObject &result, bool add_to_history = false);
+
+ void
+ HandleCommandsFromFile (lldb::SBFileSpec &file,
+ lldb::SBExecutionContext &override_context,
+ lldb::SBCommandInterpreterRunOptions &options,
+ lldb::SBCommandReturnObject result);
+
int
HandleCompletion (const char *current_line,
uint32_t cursor_pos,
Modified: lldb/trunk/scripts/Python/interface/SBDebugger.i
URL:
http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/Python/interface/SBDebugger.i?rev=219654&r1=219653&r2=219654&view=diff
==============================================================================
--- lldb/trunk/scripts/Python/interface/SBDebugger.i (original)
+++ lldb/trunk/scripts/Python/interface/SBDebugger.i Mon Oct 13 20:20:07 2014
@@ -369,7 +369,8 @@ public:
bool spawn_thread,
SBCommandInterpreterRunOptions &options,
int &num_errors,
- bool &quit_requested);
+ bool &quit_requested,
+ bool &stopped_for_crash);
}; // class SBDebugger
} // namespace lldb
Modified: lldb/trunk/source/API/SBCommandInterpreter.cpp
URL:
http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBCommandInterpreter.cpp?rev=219654&r1=219653&r2=219654&view=diff
==============================================================================
--- lldb/trunk/source/API/SBCommandInterpreter.cpp (original)
+++ lldb/trunk/source/API/SBCommandInterpreter.cpp Mon Oct 13 20:20:07 2014
@@ -20,6 +20,7 @@
#include "lldb/API/SBBroadcaster.h"
#include "lldb/API/SBCommandReturnObject.h"
#include "lldb/API/SBCommandInterpreter.h"
+#include "lldb/API/SBExecutionContext.h"
#include "lldb/API/SBProcess.h"
#include "lldb/API/SBTarget.h"
#include "lldb/API/SBListener.h"
@@ -222,6 +223,13 @@ SBCommandInterpreter::GetIOHandlerContro
lldb::ReturnStatus
SBCommandInterpreter::HandleCommand (const char *command_line,
SBCommandReturnObject &result, bool add_to_history)
{
+ SBExecutionContext sb_exe_ctx;
+ return HandleCommand (command_line, sb_exe_ctx, result, add_to_history);
+}
+
+lldb::ReturnStatus
+SBCommandInterpreter::HandleCommand (const char *command_line,
SBExecutionContext &override_context, SBCommandReturnObject &result, bool
add_to_history)
+{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
@@ -229,11 +237,21 @@ SBCommandInterpreter::HandleCommand (con
static_cast<void*>(m_opaque_ptr), command_line,
static_cast<void*>(result.get()), add_to_history);
+ ExecutionContext ctx, *ctx_ptr;
+ if (override_context.get())
+ {
+ ctx = override_context.get()->Lock(true);
+ ctx_ptr = &ctx;
+ }
+ else
+ ctx_ptr = nullptr;
+
+
result.Clear();
if (command_line && m_opaque_ptr)
{
result.ref().SetInteractive(false);
- m_opaque_ptr->HandleCommand (command_line, add_to_history ?
eLazyBoolYes : eLazyBoolNo, result.ref());
+ m_opaque_ptr->HandleCommand (command_line, add_to_history ?
eLazyBoolYes : eLazyBoolNo, result.ref(), ctx_ptr);
}
else
{
@@ -256,6 +274,54 @@ SBCommandInterpreter::HandleCommand (con
return result.GetStatus();
}
+void
+SBCommandInterpreter::HandleCommandsFromFile (lldb::SBFileSpec &file,
+ lldb::SBExecutionContext
&override_context,
+
lldb::SBCommandInterpreterRunOptions &options,
+ lldb::SBCommandReturnObject
result)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+
+ if (log)
+ {
+ SBStream s;
+ file.GetDescription (s);
+ log->Printf ("SBCommandInterpreter(%p)::HandleCommandsFromFile
(file=\"%s\", SBCommandReturnObject(%p))",
+ static_cast<void*>(m_opaque_ptr), s.GetData(),
+ static_cast<void*>(result.get()));
+ }
+
+ if (!m_opaque_ptr)
+ {
+ result->AppendError ("SBCommandInterpreter is not valid.");
+ result->SetStatus (eReturnStatusFailed);
+ return;
+ }
+
+ if (!file.IsValid())
+ {
+ SBStream s;
+ file.GetDescription (s);
+ result->AppendErrorWithFormat ("File is not valid: %s.", s.GetData());
+ result->SetStatus (eReturnStatusFailed);
+ }
+
+ FileSpec tmp_spec = file.ref();
+ ExecutionContext ctx, *ctx_ptr;
+ if (override_context.get())
+ {
+ ctx = override_context.get()->Lock(true);
+ ctx_ptr = &ctx;
+ }
+ else
+ ctx_ptr = nullptr;
+
+
+ m_opaque_ptr->HandleCommandsFromFile (tmp_spec, ctx_ptr, options.ref(),
result.ref());
+
+}
+
+
int
SBCommandInterpreter::HandleCompletion (const char *current_line,
const char *cursor,
Modified: lldb/trunk/source/API/SBDebugger.cpp
URL:
http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBDebugger.cpp?rev=219654&r1=219653&r2=219654&view=diff
==============================================================================
--- lldb/trunk/source/API/SBDebugger.cpp (original)
+++ lldb/trunk/source/API/SBDebugger.cpp Mon Oct 13 20:20:07 2014
@@ -986,7 +986,8 @@ SBDebugger::RunCommandInterpreter (bool
bool spawn_thread,
SBCommandInterpreterRunOptions &options,
int &num_errors,
- bool &quit_requested)
+ bool &quit_requested,
+ bool &stopped_for_crash)
{
if (m_opaque_sp)
@@ -995,6 +996,7 @@ SBDebugger::RunCommandInterpreter (bool
interp.RunCommandInterpreter(auto_handle_events, spawn_thread,
options.ref());
num_errors = interp.GetNumErrors();
quit_requested = interp.GetQuitRequested();
+ stopped_for_crash = interp.GetStoppedForCrash();
}
}
Modified: lldb/trunk/source/API/SBExecutionContext.cpp
URL:
http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBExecutionContext.cpp?rev=219654&r1=219653&r2=219654&view=diff
==============================================================================
--- lldb/trunk/source/API/SBExecutionContext.cpp (original)
+++ lldb/trunk/source/API/SBExecutionContext.cpp Mon Oct 13 20:20:07 2014
@@ -69,6 +69,12 @@ SBExecutionContext::operator = (const ll
return *this;
}
+ExecutionContextRef *
+SBExecutionContext::get () const
+{
+ return m_exe_ctx_sp.get();
+}
+
SBTarget
SBExecutionContext::GetTarget () const
{
Modified: lldb/trunk/source/Interpreter/CommandInterpreter.cpp
URL:
http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/CommandInterpreter.cpp?rev=219654&r1=219653&r2=219654&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/CommandInterpreter.cpp (original)
+++ lldb/trunk/source/Interpreter/CommandInterpreter.cpp Mon Oct 13 20:20:07
2014
@@ -121,7 +121,8 @@ CommandInterpreter::CommandInterpreter
m_truncation_warning(eNoTruncation),
m_command_source_depth (0),
m_num_errors(0),
- m_quit_requested(false)
+ m_quit_requested(false),
+ m_stopped_for_crash(false)
{
debugger.SetScriptLanguage (script_language);
@@ -2568,6 +2569,42 @@ CommandInterpreter::HandleCommands (cons
return;
}
}
+
+ // Also check for "stop on crash here:
+ bool should_stop = false;
+ if (tmp_result.GetDidChangeProcessState() && options.GetStopOnCrash())
+ {
+ TargetSP target_sp
(m_debugger.GetTargetList().GetSelectedTarget());
+ if (target_sp)
+ {
+ ProcessSP process_sp (target_sp->GetProcessSP());
+ if (process_sp)
+ {
+ for (ThreadSP thread_sp :
process_sp->GetThreadList().Threads())
+ {
+ StopReason reason = thread_sp->GetStopReason();
+ if (reason == eStopReasonSignal || reason ==
eStopReasonException || reason == eStopReasonInstrumentation)
+ {
+ should_stop = true;
+ break;
+ }
+ }
+ }
+ }
+ if (should_stop)
+ {
+ if (idx != num_lines - 1)
+ result.AppendErrorWithFormat("Aborting reading of commands
after command #%" PRIu64 ": '%s' stopped with a signal or exception.\n",
+ (uint64_t)idx + 1, cmd);
+ else
+ result.AppendMessageWithFormat("Command #%" PRIu64 " '%s'
stopped with a signal or exception.\n", (uint64_t)idx + 1, cmd);
+
+ result.SetStatus(tmp_result.GetStatus());
+ m_debugger.SetAsyncExecution (old_async_execution);
+
+ return;
+ }
+ }
}
@@ -2639,6 +2676,19 @@ CommandInterpreter::HandleCommandsFromFi
flags |= eHandleCommandFlagStopOnError;
}
+ if (options.GetStopOnCrash())
+ {
+ if (m_command_source_flags.empty())
+ {
+ // Echo command by default
+ flags |= eHandleCommandFlagStopOnCrash;
+ }
+ else if (m_command_source_flags.back() &
eHandleCommandFlagStopOnCrash)
+ {
+ flags |= eHandleCommandFlagStopOnCrash;
+ }
+ }
+
if (options.m_echo_commands == eLazyBoolCalculate)
{
if (m_command_source_flags.empty())
@@ -2694,7 +2744,7 @@ CommandInterpreter::HandleCommandsFromFi
*this));
const bool old_async_execution = debugger.GetAsyncExecution();
- // Set synchronous execution if we not stopping when we continue
+ // Set synchronous execution if we are not stopping on continue
if ((flags & eHandleCommandFlagStopOnContinue) == 0)
debugger.SetAsyncExecution (false);
@@ -3069,6 +3119,50 @@ CommandInterpreter::IOHandlerInputComple
io_handler.SetIsDone(true);
break;
}
+
+ // Finally, if we're going to stop on crash, check that here:
+ if (!m_quit_requested
+ && result.GetDidChangeProcessState()
+ && io_handler.GetFlags().Test(eHandleCommandFlagStopOnCrash))
+ {
+ bool should_stop = false;
+ TargetSP target_sp (m_debugger.GetTargetList().GetSelectedTarget());
+ if (target_sp)
+ {
+ ProcessSP process_sp (target_sp->GetProcessSP());
+ if (process_sp)
+ {
+ for (ThreadSP thread_sp :
process_sp->GetThreadList().Threads())
+ {
+ StopReason reason = thread_sp->GetStopReason();
+ if (reason == eStopReasonSignal || reason ==
eStopReasonException || reason == eStopReasonInstrumentation)
+ {
+ // If we are printing results, we ought to show the
resaon why we are stopping here:
+ if
(io_handler.GetFlags().Test(eHandleCommandFlagPrintResult))
+ {
+ if (!result.GetImmediateOutputStream())
+ {
+ const uint32_t start_frame = 0;
+ const uint32_t num_frames = 1;
+ const uint32_t num_frames_with_source = 1;
+ thread_sp->GetStatus
(*io_handler.GetOutputStreamFile().get(),
+ start_frame,
+ num_frames,
+ num_frames_with_source);
+ }
+ }
+ should_stop = true;
+ break;
+ }
+ }
+ }
+ }
+ if (should_stop)
+ {
+ io_handler.SetIsDone(true);
+ m_stopped_for_crash = true;
+ }
+ }
}
bool
@@ -3155,6 +3249,7 @@ CommandInterpreter::RunCommandInterprete
const bool multiple_lines = false;
m_num_errors = 0;
m_quit_requested = false;
+ m_stopped_for_crash = false;
// Always re-create the IOHandlerEditline in case the input
// changed. The old instance might have had a non-interactive
Modified: lldb/trunk/tools/driver/Driver.cpp
URL:
http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/driver/Driver.cpp?rev=219654&r1=219653&r2=219654&view=diff
==============================================================================
--- lldb/trunk/tools/driver/Driver.cpp (original)
+++ lldb/trunk/tools/driver/Driver.cpp Mon Oct 13 20:20:07 2014
@@ -109,7 +109,10 @@ static OptionDefinition g_options[] =
{ LLDB_3_TO_5, false, "one-line-before-file" , 'O',
required_argument, 0, eArgTypeNone,
"Tells the debugger to execute this one-line lldb command before any
file provided on the command line has been loaded." },
{ LLDB_3_TO_5, false, "source-quietly" , 'Q', no_argument
, 0, eArgTypeNone,
- "Tells the debugger suppress output from commands provided in the -s,
-S, -O and -o commands." },
+ "Tells the debugger to execute this one-line lldb command before any
file provided on the command line has been loaded." },
+ { LLDB_3_TO_5, false, "batch" , 'b', no_argument , 0,
eArgTypeNone,
+ "Tells the debugger to running the commands from -s, -S, -o & -O, and
then quit. However if any run command stopped due to a signal or crash, "
+ "the debugger will return to the interactive prompt at the place of
the crash." },
{ LLDB_3_TO_5, false, "editor" , 'e', no_argument , 0,
eArgTypeNone,
"Tells the debugger to open source files using the host's \"external
editor\" mechanism." },
{ LLDB_3_TO_5, false, "no-lldbinit" , 'x', no_argument , 0,
eArgTypeNone,
@@ -406,6 +409,7 @@ Driver::OptionData::OptionData () :
m_process_name(),
m_process_pid(LLDB_INVALID_PROCESS_ID),
m_use_external_editor(false),
+ m_batch(false),
m_seen_options()
{
}
@@ -429,6 +433,7 @@ Driver::OptionData::Clear ()
m_use_external_editor = false;
m_wait_for = false;
m_process_name.erase();
+ m_batch = false;
m_process_pid = LLDB_INVALID_PROCESS_ID;
}
@@ -641,6 +646,10 @@ Driver::ParseArgs (int argc, const char
m_option_data.m_print_python_path = true;
break;
+ case 'b':
+ m_option_data.m_batch = true;
+ break;
+
case 'c':
{
SBFileSpec file(optarg);
@@ -924,6 +933,7 @@ Driver::MainLoop ()
// The command file might have requested that we quit, this variable will
track that.
bool quit_requested = false;
+ bool stopped_for_crash = false;
if (commands_data && commands_size)
{
enum PIPES { READ, WRITE }; // Constants 0 and 1 for READ and WRITE
@@ -973,8 +983,15 @@ Driver::MainLoop ()
SBCommandInterpreterRunOptions options;
options.SetStopOnError (true);
-
- m_debugger.RunCommandInterpreter(handle_events,
spawn_thread, options, num_errors, quit_requested);
+ if (m_option_data.m_batch)
+ options.SetStopOnCrash (true);
+
+ m_debugger.RunCommandInterpreter(handle_events,
+ spawn_thread,
+ options,
+ num_errors,
+ quit_requested,
+ stopped_for_crash);
m_debugger.SetAsync(old_async);
}
else
@@ -1030,7 +1047,13 @@ Driver::MainLoop ()
// interpreter again in interactive mode and let the debugger
// take ownership of stdin
- if (!quit_requested)
+ bool go_interactive = true;
+ if (quit_requested)
+ go_interactive = false;
+ else if (m_option_data.m_batch && !stopped_for_crash)
+ go_interactive = false;
+
+ if (go_interactive)
{
m_debugger.SetInputFileHandle (stdin, true);
m_debugger.RunCommandInterpreter(handle_events, spawn_thread);
Modified: lldb/trunk/tools/driver/Driver.h
URL:
http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/driver/Driver.h?rev=219654&r1=219653&r2=219654&view=diff
==============================================================================
--- lldb/trunk/tools/driver/Driver.h (original)
+++ lldb/trunk/tools/driver/Driver.h Mon Oct 13 20:20:07 2014
@@ -87,6 +87,7 @@ public:
std::string m_process_name;
lldb::pid_t m_process_pid;
bool m_use_external_editor; // FIXME: When we have set/show variables
we can remove this from here.
+ bool m_batch;
typedef std::set<char> OptionSet;
OptionSet m_seen_options;
};
_______________________________________________
lldb-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits