2010-06-09 00:52:24 +08:00
//===-- Debugger.cpp --------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
2011-06-24 01:59:56 +08:00
# include "lldb/Core/Debugger.h"
# include <map>
2011-06-30 06:27:15 +08:00
# include "clang/AST/DeclCXX.h"
# include "clang/AST/Type.h"
2010-06-09 00:52:24 +08:00
# include "lldb/lldb-private.h"
# include "lldb/Core/ConnectionFileDescriptor.h"
2011-06-24 01:59:56 +08:00
# include "lldb/Core/FormatManager.h"
2010-06-09 00:52:24 +08:00
# include "lldb/Core/InputReader.h"
2011-05-10 04:18:18 +08:00
# include "lldb/Core/RegisterValue.h"
2010-06-09 00:52:24 +08:00
# include "lldb/Core/State.h"
2011-06-03 07:58:26 +08:00
# include "lldb/Core/StreamAsynchronousIO.h"
2010-09-19 10:33:57 +08:00
# include "lldb/Core/StreamString.h"
2010-06-09 00:52:24 +08:00
# include "lldb/Core/Timer.h"
2011-06-30 06:27:15 +08:00
# include "lldb/Core/ValueObject.h"
Added a new thread and frame format that can be used to display a function
name + arguments when the data is available. It seems to work really well,
but some more testing is needed before we make this on by default.
The new function format name is:
${function.name-with-args}
To see how to use these formats see the website:
http://lldb.llvm.org/formats.html
Here is a sample backtrace of debugging LLDB with LLDB using this new format
value:
(lldb) thread backtrace all
* thread #1: tid = 0x2203, 0x00007fff88a17bca libsystem_kernel.dylib __psynch_cvwait + 10, stop reason = signal SIGINT, name = <lldb.driver.main-thread>, queue = com.apple.main-thread
frame #0: 0x00007fff88a17bca libsystem_kernel.dylib __psynch_cvwait + 10
frame #1: 0x00007fff884ae274 libsystem_c.dylib _pthread_cond_wait + 840
frame #2: 0x00000001010778ea LLDB lldb_private::Condition::Wait(this=0x0000000104846770, mutex=0x0000000104846730, abstime=0x0000000000000000, timed_out=0x00007fff5fbfdea7) + 138 at Condition.cpp:92
frame #3: 0x0000000101244c21 LLDB lldb_private::Predicate<bool>::WaitForValueEqualTo(this=0x0000000104846728, value=true, abstime=0x0000000000000000, timed_out=0x00007fff5fbfdea7) + 209 at Predicate.h:317
frame #4: 0x0000000100f6eeb2 LLDB lldb_private::Listener::WaitForEventsInternal(this=0x0000000104846660, timeout=0x0000000000000000, broadcaster=0x0000000000000000, broadcaster_names=0x0000000000000000, num_broadcaster_names=0x00000000, event_type_mask=0x00000000, event_sp=0x00007fff5fbfe030) + 386 at Listener.cpp:388
frame #5: 0x0000000100f6f231 LLDB lldb_private::Listener::WaitForEvent(this=0x0000000104846660, timeout=0x0000000000000000, event_sp=0x00007fff5fbfe030) + 81 at Listener.cpp:436
frame #6: 0x0000000100098dcd LLDB lldb::SBListener::WaitForEvent(this=0x00007fff5fbff0f0, timeout_secs=0xffffffff, event=0x00007fff5fbfe430) + 685 at SBListener.cpp:181
frame #7: 0x000000010000628c lldb Driver::MainLoop(this=0x00007fff5fbff620) + 5244 at Driver.cpp:1325
frame #8: 0x0000000100006ca3 lldb main(argc=1, argv=0x00007fff5fbff758, envp=0x00007fff5fbff768) + 419 at Driver.cpp:1460
frame #9: 0x0000000100000d54 lldb start + 52
thread #3: tid = 0x2703, 0x00007fff88a17df2 libsystem_kernel.dylib select$DARWIN_EXTSN + 10, name = <lldb.comm.debugger.input>
frame #0: 0x00007fff88a17df2 libsystem_kernel.dylib select$DARWIN_EXTSN + 10
frame #1: 0x0000000100f3f072 LLDB lldb_private::ConnectionFileDescriptor::BytesAvailable(this=0x000000010524d040, timeout_usec=0x004c4b40, error_ptr=0x0000000105640a18) + 722 at ConnectionFileDescriptor.cpp:542
frame #2: 0x0000000100f3e6dd LLDB lldb_private::ConnectionFileDescriptor::Read(this=0x000000010524d040, dst=0x0000000105640a60, dst_len=1024, timeout_usec=0x004c4b40, status=0x0000000105640a14, error_ptr=0x0000000105640a18) + 301 at ConnectionFileDescriptor.cpp:273
frame #3: 0x0000000100f3b8f7 LLDB lldb_private::Communication::ReadFromConnection(this=0x0000000104846270, dst=0x0000000105640a60, dst_len=1024, timeout_usec=0x004c4b40, status=0x0000000105640a14, error_ptr=0x0000000105640a18) + 167 at Communication.cpp:317
frame #4: 0x0000000100f3b197 LLDB lldb_private::Communication::ReadThread(p=0x0000000104846270) + 327 at Communication.cpp:344
frame #5: 0x0000000101078923 LLDB ThreadCreateTrampoline(arg=0x00000001045f6650) + 227 at Host.cpp:549
frame #6: 0x00007fff884aa8bf libsystem_c.dylib _pthread_start + 335
frame #7: 0x00007fff884adb75 libsystem_c.dylib thread_start + 13
thread #4: tid = 0x2803, 0x00007fff88a17df2 libsystem_kernel.dylib select$DARWIN_EXTSN + 10, name = <lldb.comm.driver.editline>
frame #0: 0x00007fff88a17df2 libsystem_kernel.dylib select$DARWIN_EXTSN + 10
frame #1: 0x0000000100f3f072 LLDB lldb_private::ConnectionFileDescriptor::BytesAvailable(this=0x0000000105700370, timeout_usec=0x004c4b40, error_ptr=0x00000001056c3a18) + 722 at ConnectionFileDescriptor.cpp:542
frame #2: 0x0000000100f3e6dd LLDB lldb_private::ConnectionFileDescriptor::Read(this=0x0000000105700370, dst=0x00000001056c3a60, dst_len=1024, timeout_usec=0x004c4b40, status=0x00000001056c3a14, error_ptr=0x00000001056c3a18) + 301 at ConnectionFileDescriptor.cpp:273
frame #3: 0x0000000100f3b8f7 LLDB lldb_private::Communication::ReadFromConnection(this=0x0000000105700000, dst=0x00000001056c3a60, dst_len=1024, timeout_usec=0x004c4b40, status=0x00000001056c3a14, error_ptr=0x00000001056c3a18) + 167 at Communication.cpp:317
frame #4: 0x0000000100f3b197 LLDB lldb_private::Communication::ReadThread(p=0x0000000105700000) + 327 at Communication.cpp:344
frame #5: 0x0000000101078923 LLDB ThreadCreateTrampoline(arg=0x0000000105700430) + 227 at Host.cpp:549
frame #6: 0x00007fff884aa8bf libsystem_c.dylib _pthread_start + 335
frame #7: 0x00007fff884adb75 libsystem_c.dylib thread_start + 13
thread #5: tid = 0x2903, 0x00007fff88a17df2 libsystem_kernel.dylib select$DARWIN_EXTSN + 10, name = <lldb.comm.driver.editline_output>
frame #0: 0x00007fff88a17df2 libsystem_kernel.dylib select$DARWIN_EXTSN + 10
frame #1: 0x0000000100f3f072 LLDB lldb_private::ConnectionFileDescriptor::BytesAvailable(this=0x00000001057178f0, timeout_usec=0x004c4b40, error_ptr=0x0000000105980a18) + 722 at ConnectionFileDescriptor.cpp:542
frame #2: 0x0000000100f3e6dd LLDB lldb_private::ConnectionFileDescriptor::Read(this=0x00000001057178f0, dst=0x0000000105980a60, dst_len=1024, timeout_usec=0x004c4b40, status=0x0000000105980a14, error_ptr=0x0000000105980a18) + 301 at ConnectionFileDescriptor.cpp:273
frame #3: 0x0000000100f3b8f7 LLDB lldb_private::Communication::ReadFromConnection(this=0x0000000105717580, dst=0x0000000105980a60, dst_len=1024, timeout_usec=0x004c4b40, status=0x0000000105980a14, error_ptr=0x0000000105980a18) + 167 at Communication.cpp:317
frame #4: 0x0000000100f3b197 LLDB lldb_private::Communication::ReadThread(p=0x0000000105717580) + 327 at Communication.cpp:344
frame #5: 0x0000000101078923 LLDB ThreadCreateTrampoline(arg=0x00000001057179b0) + 227 at Host.cpp:549
frame #6: 0x00007fff884aa8bf libsystem_c.dylib _pthread_start + 335
frame #7: 0x00007fff884adb75 libsystem_c.dylib thread_start + 13
thread #6: tid = 0x2a03, 0x00007fff88a18af2 libsystem_kernel.dylib read + 10, name = <lldb.driver.commandline_io>
frame #0: 0x00007fff88a18af2 libsystem_kernel.dylib read + 10
frame #1: 0x0000000100050c3b libedit.3.dylib read_init + 247
frame #2: 0x0000000100050e96 libedit.3.dylib el_wgetc + 155
frame #3: 0x000000010005115d libedit.3.dylib el_wgets + 578
frame #4: 0x000000010005debc libedit.3.dylib el_gets + 37
frame #5: 0x000000010000d409 lldb IOChannel::LibeditGetInput(this=0x0000000105700490, new_line=0x0000000105a03db0) + 89 at IOChannel.cpp:311
frame #6: 0x000000010000d8b6 lldb IOChannel::Run(this=0x0000000105700490) + 806 at IOChannel.cpp:391
frame #7: 0x000000010000d57d lldb IOChannel::IOReadThread(ptr=0x0000000105700490) + 29 at IOChannel.cpp:345
frame #8: 0x0000000101078923 LLDB ThreadCreateTrampoline(arg=0x00000001057179f0) + 227 at Host.cpp:549
frame #9: 0x00007fff884aa8bf libsystem_c.dylib _pthread_start + 335
frame #10: 0x00007fff884adb75 libsystem_c.dylib thread_start + 13
(lldb)
llvm-svn: 148110
2012-01-13 16:39:16 +08:00
# include "lldb/Core/ValueObjectVariable.h"
2011-02-08 07:24:47 +08:00
# include "lldb/Host/Terminal.h"
2010-06-23 09:19:29 +08:00
# include "lldb/Interpreter/CommandInterpreter.h"
Added a new thread and frame format that can be used to display a function
name + arguments when the data is available. It seems to work really well,
but some more testing is needed before we make this on by default.
The new function format name is:
${function.name-with-args}
To see how to use these formats see the website:
http://lldb.llvm.org/formats.html
Here is a sample backtrace of debugging LLDB with LLDB using this new format
value:
(lldb) thread backtrace all
* thread #1: tid = 0x2203, 0x00007fff88a17bca libsystem_kernel.dylib __psynch_cvwait + 10, stop reason = signal SIGINT, name = <lldb.driver.main-thread>, queue = com.apple.main-thread
frame #0: 0x00007fff88a17bca libsystem_kernel.dylib __psynch_cvwait + 10
frame #1: 0x00007fff884ae274 libsystem_c.dylib _pthread_cond_wait + 840
frame #2: 0x00000001010778ea LLDB lldb_private::Condition::Wait(this=0x0000000104846770, mutex=0x0000000104846730, abstime=0x0000000000000000, timed_out=0x00007fff5fbfdea7) + 138 at Condition.cpp:92
frame #3: 0x0000000101244c21 LLDB lldb_private::Predicate<bool>::WaitForValueEqualTo(this=0x0000000104846728, value=true, abstime=0x0000000000000000, timed_out=0x00007fff5fbfdea7) + 209 at Predicate.h:317
frame #4: 0x0000000100f6eeb2 LLDB lldb_private::Listener::WaitForEventsInternal(this=0x0000000104846660, timeout=0x0000000000000000, broadcaster=0x0000000000000000, broadcaster_names=0x0000000000000000, num_broadcaster_names=0x00000000, event_type_mask=0x00000000, event_sp=0x00007fff5fbfe030) + 386 at Listener.cpp:388
frame #5: 0x0000000100f6f231 LLDB lldb_private::Listener::WaitForEvent(this=0x0000000104846660, timeout=0x0000000000000000, event_sp=0x00007fff5fbfe030) + 81 at Listener.cpp:436
frame #6: 0x0000000100098dcd LLDB lldb::SBListener::WaitForEvent(this=0x00007fff5fbff0f0, timeout_secs=0xffffffff, event=0x00007fff5fbfe430) + 685 at SBListener.cpp:181
frame #7: 0x000000010000628c lldb Driver::MainLoop(this=0x00007fff5fbff620) + 5244 at Driver.cpp:1325
frame #8: 0x0000000100006ca3 lldb main(argc=1, argv=0x00007fff5fbff758, envp=0x00007fff5fbff768) + 419 at Driver.cpp:1460
frame #9: 0x0000000100000d54 lldb start + 52
thread #3: tid = 0x2703, 0x00007fff88a17df2 libsystem_kernel.dylib select$DARWIN_EXTSN + 10, name = <lldb.comm.debugger.input>
frame #0: 0x00007fff88a17df2 libsystem_kernel.dylib select$DARWIN_EXTSN + 10
frame #1: 0x0000000100f3f072 LLDB lldb_private::ConnectionFileDescriptor::BytesAvailable(this=0x000000010524d040, timeout_usec=0x004c4b40, error_ptr=0x0000000105640a18) + 722 at ConnectionFileDescriptor.cpp:542
frame #2: 0x0000000100f3e6dd LLDB lldb_private::ConnectionFileDescriptor::Read(this=0x000000010524d040, dst=0x0000000105640a60, dst_len=1024, timeout_usec=0x004c4b40, status=0x0000000105640a14, error_ptr=0x0000000105640a18) + 301 at ConnectionFileDescriptor.cpp:273
frame #3: 0x0000000100f3b8f7 LLDB lldb_private::Communication::ReadFromConnection(this=0x0000000104846270, dst=0x0000000105640a60, dst_len=1024, timeout_usec=0x004c4b40, status=0x0000000105640a14, error_ptr=0x0000000105640a18) + 167 at Communication.cpp:317
frame #4: 0x0000000100f3b197 LLDB lldb_private::Communication::ReadThread(p=0x0000000104846270) + 327 at Communication.cpp:344
frame #5: 0x0000000101078923 LLDB ThreadCreateTrampoline(arg=0x00000001045f6650) + 227 at Host.cpp:549
frame #6: 0x00007fff884aa8bf libsystem_c.dylib _pthread_start + 335
frame #7: 0x00007fff884adb75 libsystem_c.dylib thread_start + 13
thread #4: tid = 0x2803, 0x00007fff88a17df2 libsystem_kernel.dylib select$DARWIN_EXTSN + 10, name = <lldb.comm.driver.editline>
frame #0: 0x00007fff88a17df2 libsystem_kernel.dylib select$DARWIN_EXTSN + 10
frame #1: 0x0000000100f3f072 LLDB lldb_private::ConnectionFileDescriptor::BytesAvailable(this=0x0000000105700370, timeout_usec=0x004c4b40, error_ptr=0x00000001056c3a18) + 722 at ConnectionFileDescriptor.cpp:542
frame #2: 0x0000000100f3e6dd LLDB lldb_private::ConnectionFileDescriptor::Read(this=0x0000000105700370, dst=0x00000001056c3a60, dst_len=1024, timeout_usec=0x004c4b40, status=0x00000001056c3a14, error_ptr=0x00000001056c3a18) + 301 at ConnectionFileDescriptor.cpp:273
frame #3: 0x0000000100f3b8f7 LLDB lldb_private::Communication::ReadFromConnection(this=0x0000000105700000, dst=0x00000001056c3a60, dst_len=1024, timeout_usec=0x004c4b40, status=0x00000001056c3a14, error_ptr=0x00000001056c3a18) + 167 at Communication.cpp:317
frame #4: 0x0000000100f3b197 LLDB lldb_private::Communication::ReadThread(p=0x0000000105700000) + 327 at Communication.cpp:344
frame #5: 0x0000000101078923 LLDB ThreadCreateTrampoline(arg=0x0000000105700430) + 227 at Host.cpp:549
frame #6: 0x00007fff884aa8bf libsystem_c.dylib _pthread_start + 335
frame #7: 0x00007fff884adb75 libsystem_c.dylib thread_start + 13
thread #5: tid = 0x2903, 0x00007fff88a17df2 libsystem_kernel.dylib select$DARWIN_EXTSN + 10, name = <lldb.comm.driver.editline_output>
frame #0: 0x00007fff88a17df2 libsystem_kernel.dylib select$DARWIN_EXTSN + 10
frame #1: 0x0000000100f3f072 LLDB lldb_private::ConnectionFileDescriptor::BytesAvailable(this=0x00000001057178f0, timeout_usec=0x004c4b40, error_ptr=0x0000000105980a18) + 722 at ConnectionFileDescriptor.cpp:542
frame #2: 0x0000000100f3e6dd LLDB lldb_private::ConnectionFileDescriptor::Read(this=0x00000001057178f0, dst=0x0000000105980a60, dst_len=1024, timeout_usec=0x004c4b40, status=0x0000000105980a14, error_ptr=0x0000000105980a18) + 301 at ConnectionFileDescriptor.cpp:273
frame #3: 0x0000000100f3b8f7 LLDB lldb_private::Communication::ReadFromConnection(this=0x0000000105717580, dst=0x0000000105980a60, dst_len=1024, timeout_usec=0x004c4b40, status=0x0000000105980a14, error_ptr=0x0000000105980a18) + 167 at Communication.cpp:317
frame #4: 0x0000000100f3b197 LLDB lldb_private::Communication::ReadThread(p=0x0000000105717580) + 327 at Communication.cpp:344
frame #5: 0x0000000101078923 LLDB ThreadCreateTrampoline(arg=0x00000001057179b0) + 227 at Host.cpp:549
frame #6: 0x00007fff884aa8bf libsystem_c.dylib _pthread_start + 335
frame #7: 0x00007fff884adb75 libsystem_c.dylib thread_start + 13
thread #6: tid = 0x2a03, 0x00007fff88a18af2 libsystem_kernel.dylib read + 10, name = <lldb.driver.commandline_io>
frame #0: 0x00007fff88a18af2 libsystem_kernel.dylib read + 10
frame #1: 0x0000000100050c3b libedit.3.dylib read_init + 247
frame #2: 0x0000000100050e96 libedit.3.dylib el_wgetc + 155
frame #3: 0x000000010005115d libedit.3.dylib el_wgets + 578
frame #4: 0x000000010005debc libedit.3.dylib el_gets + 37
frame #5: 0x000000010000d409 lldb IOChannel::LibeditGetInput(this=0x0000000105700490, new_line=0x0000000105a03db0) + 89 at IOChannel.cpp:311
frame #6: 0x000000010000d8b6 lldb IOChannel::Run(this=0x0000000105700490) + 806 at IOChannel.cpp:391
frame #7: 0x000000010000d57d lldb IOChannel::IOReadThread(ptr=0x0000000105700490) + 29 at IOChannel.cpp:345
frame #8: 0x0000000101078923 LLDB ThreadCreateTrampoline(arg=0x00000001057179f0) + 227 at Host.cpp:549
frame #9: 0x00007fff884aa8bf libsystem_c.dylib _pthread_start + 335
frame #10: 0x00007fff884adb75 libsystem_c.dylib thread_start + 13
(lldb)
llvm-svn: 148110
2012-01-13 16:39:16 +08:00
# include "lldb/Symbol/VariableList.h"
2010-06-09 00:52:24 +08:00
# include "lldb/Target/TargetList.h"
# include "lldb/Target/Process.h"
2010-09-19 10:33:57 +08:00
# include "lldb/Target/RegisterContext.h"
# include "lldb/Target/StopInfo.h"
2010-06-09 00:52:24 +08:00
# include "lldb/Target/Thread.h"
2011-10-14 15:41:33 +08:00
# include "lldb/Utility/AnsiTerminal.h"
2010-06-09 00:52:24 +08:00
using namespace lldb ;
using namespace lldb_private ;
2010-09-19 10:33:57 +08:00
static uint32_t g_shared_debugger_refcount = 0 ;
2010-07-01 00:22:25 +08:00
static lldb : : user_id_t g_unique_id = 1 ;
2010-09-19 10:33:57 +08:00
# pragma mark Static Functions
static Mutex &
GetDebuggerListMutex ( )
{
static Mutex g_mutex ( Mutex : : eMutexTypeRecursive ) ;
return g_mutex ;
}
typedef std : : vector < DebuggerSP > DebuggerList ;
static DebuggerList &
GetDebuggerList ( )
{
// hide the static debugger list inside a singleton accessor to avoid
// global init contructors
static DebuggerList g_list ;
return g_list ;
}
2011-11-22 05:44:34 +08:00
static const ConstString &
PromptVarName ( )
{
static ConstString g_const_string ( " prompt " ) ;
return g_const_string ;
}
static const ConstString &
GetFrameFormatName ( )
{
static ConstString g_const_string ( " frame-format " ) ;
return g_const_string ;
}
static const ConstString &
GetThreadFormatName ( )
{
static ConstString g_const_string ( " thread-format " ) ;
return g_const_string ;
}
static const ConstString &
ScriptLangVarName ( )
{
static ConstString g_const_string ( " script-lang " ) ;
return g_const_string ;
}
static const ConstString &
TermWidthVarName ( )
{
static ConstString g_const_string ( " term-width " ) ;
return g_const_string ;
}
static const ConstString &
UseExternalEditorVarName ( )
{
static ConstString g_const_string ( " use-external-editor " ) ;
return g_const_string ;
}
static const ConstString &
AutoConfirmName ( )
{
static ConstString g_const_string ( " auto-confirm " ) ;
return g_const_string ;
}
static const ConstString &
StopSourceContextBeforeName ( )
{
static ConstString g_const_string ( " stop-line-count-before " ) ;
return g_const_string ;
}
static const ConstString &
StopSourceContextAfterName ( )
{
static ConstString g_const_string ( " stop-line-count-after " ) ;
return g_const_string ;
}
static const ConstString &
StopDisassemblyCountName ( )
{
static ConstString g_const_string ( " stop-disassembly-count " ) ;
return g_const_string ;
}
static const ConstString &
StopDisassemblyDisplayName ( )
{
static ConstString g_const_string ( " stop-disassembly-display " ) ;
return g_const_string ;
}
OptionEnumValueElement
DebuggerInstanceSettings : : g_show_disassembly_enum_values [ ] =
{
{ eStopDisassemblyTypeNever , " never " , " Never show disassembly when displaying a stop context. " } ,
{ eStopDisassemblyTypeNoSource , " no-source " , " Show disassembly when there is no source information, or the source file is missing when displaying a stop context. " } ,
{ eStopDisassemblyTypeAlways , " always " , " Always show disassembly when displaying a stop context. " } ,
{ 0 , NULL , NULL }
} ;
2010-09-19 10:33:57 +08:00
# pragma mark Debugger
2010-11-19 07:32:35 +08:00
UserSettingsControllerSP &
Debugger : : GetSettingsController ( )
{
2012-01-30 15:41:31 +08:00
static UserSettingsControllerSP g_settings_controller_sp ;
if ( ! g_settings_controller_sp )
{
g_settings_controller_sp . reset ( new Debugger : : SettingsController ) ;
// The first shared pointer to Debugger::SettingsController in
// g_settings_controller_sp must be fully created above so that
// the DebuggerInstanceSettings can use a weak_ptr to refer back
// to the master setttings controller
InstanceSettingsSP default_instance_settings_sp ( new DebuggerInstanceSettings ( g_settings_controller_sp ,
false ,
InstanceSettings : : GetDefaultName ( ) . AsCString ( ) ) ) ;
g_settings_controller_sp - > SetDefaultInstanceSettings ( default_instance_settings_sp ) ;
}
return g_settings_controller_sp ;
2010-11-19 07:32:35 +08:00
}
2011-01-14 08:29:16 +08:00
int
Debugger : : TestDebuggerRefCount ( )
{
return g_shared_debugger_refcount ;
}
2010-06-09 00:52:24 +08:00
void
Debugger : : Initialize ( )
{
2010-06-23 09:19:29 +08:00
if ( g_shared_debugger_refcount = = 0 )
2010-11-19 07:32:35 +08:00
{
2010-11-19 11:46:01 +08:00
lldb_private : : Initialize ( ) ;
2010-11-19 07:32:35 +08:00
}
2010-06-23 09:19:29 +08:00
g_shared_debugger_refcount + + ;
2010-11-19 07:32:35 +08:00
2010-06-09 00:52:24 +08:00
}
void
Debugger : : Terminate ( )
{
2010-06-23 09:19:29 +08:00
if ( g_shared_debugger_refcount > 0 )
2010-06-09 00:52:24 +08:00
{
2010-06-23 09:19:29 +08:00
g_shared_debugger_refcount - - ;
if ( g_shared_debugger_refcount = = 0 )
2010-06-09 00:52:24 +08:00
{
2010-11-19 11:46:01 +08:00
lldb_private : : WillTerminate ( ) ;
lldb_private : : Terminate ( ) ;
2011-01-18 05:55:19 +08:00
// Clear our master list of debugger objects
Mutex : : Locker locker ( GetDebuggerListMutex ( ) ) ;
GetDebuggerList ( ) . clear ( ) ;
2010-06-09 00:52:24 +08:00
}
}
}
2011-03-11 06:14:10 +08:00
void
Debugger : : SettingsInitialize ( )
{
static bool g_initialized = false ;
if ( ! g_initialized )
{
g_initialized = true ;
2012-01-30 15:41:31 +08:00
UserSettingsController : : InitializeSettingsController ( GetSettingsController ( ) ,
2011-03-11 06:14:10 +08:00
SettingsController : : global_settings_table ,
SettingsController : : instance_settings_table ) ;
// Now call SettingsInitialize for each settings 'child' of Debugger
Target : : SettingsInitialize ( ) ;
}
}
void
Debugger : : SettingsTerminate ( )
{
// Must call SettingsTerminate() for each settings 'child' of Debugger, before terminating the Debugger's
// Settings.
Target : : SettingsTerminate ( ) ;
// Now terminate the Debugger Settings.
UserSettingsControllerSP & usc = GetSettingsController ( ) ;
UserSettingsController : : FinalizeSettingsController ( usc ) ;
usc . reset ( ) ;
}
2010-06-23 09:19:29 +08:00
DebuggerSP
Debugger : : CreateInstance ( )
{
DebuggerSP debugger_sp ( new Debugger ) ;
// Scope for locker
{
Mutex : : Locker locker ( GetDebuggerListMutex ( ) ) ;
GetDebuggerList ( ) . push_back ( debugger_sp ) ;
}
return debugger_sp ;
}
2011-01-22 09:02:07 +08:00
void
2011-09-17 16:33:22 +08:00
Debugger : : Destroy ( DebuggerSP & debugger_sp )
2011-01-22 09:02:07 +08:00
{
if ( debugger_sp . get ( ) = = NULL )
return ;
2011-09-16 05:36:42 +08:00
debugger_sp - > Clear ( ) ;
2011-01-22 09:02:07 +08:00
Mutex : : Locker locker ( GetDebuggerListMutex ( ) ) ;
DebuggerList & debugger_list = GetDebuggerList ( ) ;
DebuggerList : : iterator pos , end = debugger_list . end ( ) ;
for ( pos = debugger_list . begin ( ) ; pos ! = end ; + + pos )
{
if ( ( * pos ) . get ( ) = = debugger_sp . get ( ) )
{
debugger_list . erase ( pos ) ;
return ;
}
}
}
2011-09-17 16:33:22 +08:00
DebuggerSP
2010-09-04 08:03:46 +08:00
Debugger : : FindDebuggerWithInstanceName ( const ConstString & instance_name )
{
2011-09-17 16:33:22 +08:00
DebuggerSP debugger_sp ;
2010-09-04 08:03:46 +08:00
Mutex : : Locker locker ( GetDebuggerListMutex ( ) ) ;
DebuggerList & debugger_list = GetDebuggerList ( ) ;
DebuggerList : : iterator pos , end = debugger_list . end ( ) ;
for ( pos = debugger_list . begin ( ) ; pos ! = end ; + + pos )
{
if ( ( * pos ) . get ( ) - > m_instance_name = = instance_name )
{
debugger_sp = * pos ;
break ;
}
}
return debugger_sp ;
}
2010-06-23 09:19:29 +08:00
TargetSP
Debugger : : FindTargetWithProcessID ( lldb : : pid_t pid )
{
2011-09-17 16:33:22 +08:00
TargetSP target_sp ;
2010-06-23 09:19:29 +08:00
Mutex : : Locker locker ( GetDebuggerListMutex ( ) ) ;
DebuggerList & debugger_list = GetDebuggerList ( ) ;
DebuggerList : : iterator pos , end = debugger_list . end ( ) ;
for ( pos = debugger_list . begin ( ) ; pos ! = end ; + + pos )
{
target_sp = ( * pos ) - > GetTargetList ( ) . FindTargetWithProcessID ( pid ) ;
if ( target_sp )
break ;
}
return target_sp ;
}
2011-11-16 13:37:56 +08:00
TargetSP
Debugger : : FindTargetWithProcess ( Process * process )
{
TargetSP target_sp ;
Mutex : : Locker locker ( GetDebuggerListMutex ( ) ) ;
DebuggerList & debugger_list = GetDebuggerList ( ) ;
DebuggerList : : iterator pos , end = debugger_list . end ( ) ;
for ( pos = debugger_list . begin ( ) ; pos ! = end ; + + pos )
{
target_sp = ( * pos ) - > GetTargetList ( ) . FindTargetWithProcess ( process ) ;
if ( target_sp )
break ;
}
return target_sp ;
}
2010-06-23 09:19:29 +08:00
2010-06-09 00:52:24 +08:00
Debugger : : Debugger ( ) :
2010-07-01 00:22:25 +08:00
UserID ( g_unique_id + + ) ,
2012-01-30 15:41:31 +08:00
DebuggerInstanceSettings ( GetSettingsController ( ) ) ,
2010-12-04 10:39:47 +08:00
m_input_comm ( " debugger.input " ) ,
2010-06-09 00:52:24 +08:00
m_input_file ( ) ,
m_output_file ( ) ,
m_error_file ( ) ,
2012-02-16 14:50:00 +08:00
m_target_list ( * this ) ,
2011-03-19 09:12:21 +08:00
m_platform_list ( ) ,
2010-06-09 00:52:24 +08:00
m_listener ( " lldb.Debugger " ) ,
2011-09-13 08:29:56 +08:00
m_source_manager ( * this ) ,
m_source_file_cache ( ) ,
2010-06-23 09:19:29 +08:00
m_command_interpreter_ap ( new CommandInterpreter ( * this , eScriptLanguageDefault , false ) ) ,
2011-06-03 03:18:55 +08:00
m_input_reader_stack ( ) ,
2010-10-01 05:49:03 +08:00
m_input_reader_data ( )
2010-06-09 00:52:24 +08:00
{
2010-06-23 09:19:29 +08:00
m_command_interpreter_ap - > Initialize ( ) ;
2011-03-19 09:12:21 +08:00
// Always add our default platform to the platform list
PlatformSP default_platform_sp ( Platform : : GetDefaultPlatform ( ) ) ;
assert ( default_platform_sp . get ( ) ) ;
m_platform_list . Append ( default_platform_sp , true ) ;
2010-06-09 00:52:24 +08:00
}
Debugger : : ~ Debugger ( )
2011-09-16 05:36:42 +08:00
{
Clear ( ) ;
}
void
Debugger : : Clear ( )
2010-06-09 00:52:24 +08:00
{
2010-12-21 02:35:50 +08:00
CleanUpInputReaders ( ) ;
2011-10-01 08:45:15 +08:00
m_listener . Clear ( ) ;
2010-06-23 09:19:29 +08:00
int num_targets = m_target_list . GetNumTargets ( ) ;
for ( int i = 0 ; i < num_targets ; i + + )
{
2012-01-15 01:04:19 +08:00
TargetSP target_sp ( m_target_list . GetTargetAtIndex ( i ) ) ;
if ( target_sp )
2011-09-16 05:36:42 +08:00
{
2012-01-15 01:04:19 +08:00
ProcessSP process_sp ( target_sp - > GetProcessSP ( ) ) ;
if ( process_sp )
{
if ( process_sp - > GetShouldDetach ( ) )
process_sp - > Detach ( ) ;
}
target_sp - > Destroy ( ) ;
2011-09-16 05:36:42 +08:00
}
2010-06-23 09:19:29 +08:00
}
2012-02-16 14:50:00 +08:00
BroadcasterManager : : Clear ( ) ;
2010-06-23 09:19:29 +08:00
DisconnectInput ( ) ;
2010-06-09 00:52:24 +08:00
2011-09-16 05:36:42 +08:00
}
2010-06-09 00:52:24 +08:00
2011-05-29 12:06:55 +08:00
bool
Debugger : : GetCloseInputOnEOF ( ) const
{
return m_input_comm . GetCloseOnEOF ( ) ;
}
void
Debugger : : SetCloseInputOnEOF ( bool b )
{
m_input_comm . SetCloseOnEOF ( b ) ;
}
2010-06-09 00:52:24 +08:00
bool
Debugger : : GetAsyncExecution ( )
{
2010-06-23 09:19:29 +08:00
return ! m_command_interpreter_ap - > GetSynchronous ( ) ;
2010-06-09 00:52:24 +08:00
}
void
Debugger : : SetAsyncExecution ( bool async_execution )
{
2010-06-23 09:19:29 +08:00
m_command_interpreter_ap - > SetSynchronous ( ! async_execution ) ;
2010-06-09 00:52:24 +08:00
}
void
Debugger : : SetInputFileHandle ( FILE * fh , bool tranfer_ownership )
{
2011-02-09 09:08:52 +08:00
File & in_file = GetInputFile ( ) ;
in_file . SetStream ( fh , tranfer_ownership ) ;
if ( in_file . IsValid ( ) = = false )
in_file . SetStream ( stdin , true ) ;
2010-06-09 00:52:24 +08:00
// Disconnect from any old connection if we had one
m_input_comm . Disconnect ( ) ;
2012-01-15 04:47:38 +08:00
// Pass false as the second argument to ConnectionFileDescriptor below because
// our "in_file" above will already take ownership if requested and we don't
// want to objects trying to own and close a file descriptor.
m_input_comm . SetConnection ( new ConnectionFileDescriptor ( in_file . GetDescriptor ( ) , false ) ) ;
2010-06-09 00:52:24 +08:00
m_input_comm . SetReadThreadBytesReceivedCallback ( Debugger : : DispatchInputCallback , this ) ;
Error error ;
if ( m_input_comm . StartReadThread ( & error ) = = false )
{
2011-02-09 09:08:52 +08:00
File & err_file = GetErrorFile ( ) ;
2010-06-09 00:52:24 +08:00
2011-02-09 09:08:52 +08:00
err_file . Printf ( " error: failed to main input read thread: %s " , error . AsCString ( ) ? error . AsCString ( ) : " unkown error " ) ;
exit ( 1 ) ;
}
2010-06-09 00:52:24 +08:00
}
void
Debugger : : SetOutputFileHandle ( FILE * fh , bool tranfer_ownership )
{
2011-02-09 09:08:52 +08:00
File & out_file = GetOutputFile ( ) ;
out_file . SetStream ( fh , tranfer_ownership ) ;
if ( out_file . IsValid ( ) = = false )
out_file . SetStream ( stdout , false ) ;
2011-01-14 08:29:16 +08:00
GetCommandInterpreter ( ) . GetScriptInterpreter ( ) - > ResetOutputFileHandle ( fh ) ;
2010-06-09 00:52:24 +08:00
}
void
Debugger : : SetErrorFileHandle ( FILE * fh , bool tranfer_ownership )
{
2011-02-09 09:08:52 +08:00
File & err_file = GetErrorFile ( ) ;
err_file . SetStream ( fh , tranfer_ownership ) ;
if ( err_file . IsValid ( ) = = false )
err_file . SetStream ( stderr , false ) ;
2010-06-09 00:52:24 +08:00
}
ExecutionContext
2010-08-27 05:32:51 +08:00
Debugger : : GetSelectedExecutionContext ( )
2010-06-09 00:52:24 +08:00
{
ExecutionContext exe_ctx ;
2011-09-22 12:58:26 +08:00
TargetSP target_sp ( GetSelectedTarget ( ) ) ;
exe_ctx . SetTargetSP ( target_sp ) ;
2010-06-09 00:52:24 +08:00
if ( target_sp )
{
2011-09-22 12:58:26 +08:00
ProcessSP process_sp ( target_sp - > GetProcessSP ( ) ) ;
exe_ctx . SetProcessSP ( process_sp ) ;
if ( process_sp & & process_sp - > IsRunning ( ) = = false )
2010-06-09 00:52:24 +08:00
{
2011-09-22 12:58:26 +08:00
ThreadSP thread_sp ( process_sp - > GetThreadList ( ) . GetSelectedThread ( ) ) ;
if ( thread_sp )
2010-06-09 00:52:24 +08:00
{
2011-09-22 12:58:26 +08:00
exe_ctx . SetThreadSP ( thread_sp ) ;
exe_ctx . SetFrameSP ( thread_sp - > GetSelectedFrame ( ) ) ;
if ( exe_ctx . GetFramePtr ( ) = = NULL )
exe_ctx . SetFrameSP ( thread_sp - > GetStackFrameAtIndex ( 0 ) ) ;
2010-06-09 00:52:24 +08:00
}
}
}
return exe_ctx ;
}
2011-02-10 09:15:13 +08:00
InputReaderSP
Debugger : : GetCurrentInputReader ( )
{
InputReaderSP reader_sp ;
2011-06-03 03:18:55 +08:00
if ( ! m_input_reader_stack . IsEmpty ( ) )
2011-02-10 09:15:13 +08:00
{
// Clear any finished readers from the stack
while ( CheckIfTopInputReaderIsDone ( ) ) ;
2011-06-03 03:18:55 +08:00
if ( ! m_input_reader_stack . IsEmpty ( ) )
reader_sp = m_input_reader_stack . Top ( ) ;
2011-02-10 09:15:13 +08:00
}
return reader_sp ;
}
2010-06-09 00:52:24 +08:00
void
Debugger : : DispatchInputCallback ( void * baton , const void * bytes , size_t bytes_len )
{
2010-11-20 04:47:54 +08:00
if ( bytes_len > 0 )
( ( Debugger * ) baton ) - > DispatchInput ( ( char * ) bytes , bytes_len ) ;
else
( ( Debugger * ) baton ) - > DispatchInputEndOfFile ( ) ;
}
2010-06-09 00:52:24 +08:00
void
Debugger : : DispatchInput ( const char * bytes , size_t bytes_len )
{
2010-11-20 04:47:54 +08:00
if ( bytes = = NULL | | bytes_len = = 0 )
return ;
2010-06-09 00:52:24 +08:00
WriteToDefaultReader ( bytes , bytes_len ) ;
}
2010-11-20 04:47:54 +08:00
void
Debugger : : DispatchInputInterrupt ( )
{
m_input_reader_data . clear ( ) ;
2011-02-10 09:15:13 +08:00
InputReaderSP reader_sp ( GetCurrentInputReader ( ) ) ;
if ( reader_sp )
2010-11-20 04:47:54 +08:00
{
2011-02-10 09:15:13 +08:00
reader_sp - > Notify ( eInputReaderInterrupt ) ;
2010-11-20 04:47:54 +08:00
2011-02-10 09:15:13 +08:00
// If notifying the reader of the interrupt finished the reader, we should pop it off the stack.
2010-11-20 04:47:54 +08:00
while ( CheckIfTopInputReaderIsDone ( ) ) ;
}
}
void
Debugger : : DispatchInputEndOfFile ( )
{
m_input_reader_data . clear ( ) ;
2011-02-10 09:15:13 +08:00
InputReaderSP reader_sp ( GetCurrentInputReader ( ) ) ;
if ( reader_sp )
2010-11-20 04:47:54 +08:00
{
2011-02-10 09:15:13 +08:00
reader_sp - > Notify ( eInputReaderEndOfFile ) ;
2010-11-20 04:47:54 +08:00
2011-02-10 09:15:13 +08:00
// If notifying the reader of the end-of-file finished the reader, we should pop it off the stack.
2010-11-20 04:47:54 +08:00
while ( CheckIfTopInputReaderIsDone ( ) ) ;
}
}
2010-12-21 02:35:50 +08:00
void
Debugger : : CleanUpInputReaders ( )
{
m_input_reader_data . clear ( ) ;
2011-02-10 09:15:13 +08:00
// The bottom input reader should be the main debugger input reader. We do not want to close that one here.
2011-06-03 03:18:55 +08:00
while ( m_input_reader_stack . GetSize ( ) > 1 )
2010-12-21 02:35:50 +08:00
{
2011-02-10 09:15:13 +08:00
InputReaderSP reader_sp ( GetCurrentInputReader ( ) ) ;
2010-12-21 02:35:50 +08:00
if ( reader_sp )
{
reader_sp - > Notify ( eInputReaderEndOfFile ) ;
reader_sp - > SetIsDone ( true ) ;
}
}
}
This patch captures and serializes all output being written by the
command line driver, including the lldb prompt being output by
editline, the asynchronous process output & error messages, and
asynchronous messages written by target stop-hooks.
As part of this it introduces a new Stream class,
StreamAsynchronousIO. A StreamAsynchronousIO object is created with a
broadcaster, who will eventually broadcast the stream's data for a
listener to handle, and an event type indicating what type of event
the broadcaster will broadcast. When the Write method is called on a
StreamAsynchronousIO object, the data is appended to an internal
string. When the Flush method is called on a StreamAsynchronousIO
object, it broadcasts it's data string and clears the string.
Anything in lldb-core that needs to generate asynchronous output for
the end-user should use the StreamAsynchronousIO objects.
I have also added a new notification type for InputReaders, to let
them know that a asynchronous output has been written. This is to
allow the input readers to, for example, refresh their prompts and
lines, if desired. I added the case statements to all the input
readers to catch this notification, but I haven't added any code for
handling them yet (except to the IOChannel input reader).
llvm-svn: 130721
2011-05-03 04:41:46 +08:00
void
Debugger : : NotifyTopInputReader ( InputReaderAction notification )
{
InputReaderSP reader_sp ( GetCurrentInputReader ( ) ) ;
if ( reader_sp )
{
reader_sp - > Notify ( notification ) ;
// Flush out any input readers that are done.
while ( CheckIfTopInputReaderIsDone ( ) )
/* Do nothing. */ ;
}
}
2011-05-10 07:06:58 +08:00
bool
2011-09-17 16:33:22 +08:00
Debugger : : InputReaderIsTopReader ( const InputReaderSP & reader_sp )
2011-05-10 07:06:58 +08:00
{
2011-06-17 00:27:19 +08:00
InputReaderSP top_reader_sp ( GetCurrentInputReader ( ) ) ;
2011-05-10 07:06:58 +08:00
2011-06-17 00:27:19 +08:00
return ( reader_sp . get ( ) = = top_reader_sp . get ( ) ) ;
2011-05-10 07:06:58 +08:00
}
2010-06-09 00:52:24 +08:00
void
Debugger : : WriteToDefaultReader ( const char * bytes , size_t bytes_len )
{
if ( bytes & & bytes_len )
m_input_reader_data . append ( bytes , bytes_len ) ;
if ( m_input_reader_data . empty ( ) )
return ;
2011-06-03 03:18:55 +08:00
while ( ! m_input_reader_stack . IsEmpty ( ) & & ! m_input_reader_data . empty ( ) )
2010-06-09 00:52:24 +08:00
{
// Get the input reader from the top of the stack
2011-02-10 09:15:13 +08:00
InputReaderSP reader_sp ( GetCurrentInputReader ( ) ) ;
2010-06-09 00:52:24 +08:00
if ( ! reader_sp )
break ;
2010-07-21 06:52:08 +08:00
size_t bytes_handled = reader_sp - > HandleRawBytes ( m_input_reader_data . c_str ( ) ,
2010-06-09 00:52:24 +08:00
m_input_reader_data . size ( ) ) ;
if ( bytes_handled )
{
m_input_reader_data . erase ( 0 , bytes_handled ) ;
}
else
{
// No bytes were handled, we might not have reached our
// granularity, just return and wait for more data
break ;
}
}
2011-02-10 09:15:13 +08:00
// Flush out any input readers that are done.
2010-06-09 00:52:24 +08:00
while ( CheckIfTopInputReaderIsDone ( ) )
/* Do nothing. */ ;
}
void
Debugger : : PushInputReader ( const InputReaderSP & reader_sp )
{
if ( ! reader_sp )
return ;
2011-02-10 09:15:13 +08:00
// Deactivate the old top reader
InputReaderSP top_reader_sp ( GetCurrentInputReader ( ) ) ;
if ( top_reader_sp )
top_reader_sp - > Notify ( eInputReaderDeactivate ) ;
2011-06-03 03:18:55 +08:00
m_input_reader_stack . Push ( reader_sp ) ;
2010-06-09 00:52:24 +08:00
reader_sp - > Notify ( eInputReaderActivate ) ;
ActivateInputReader ( reader_sp ) ;
}
bool
2011-09-17 16:33:22 +08:00
Debugger : : PopInputReader ( const InputReaderSP & pop_reader_sp )
2010-06-09 00:52:24 +08:00
{
bool result = false ;
// The reader on the stop of the stack is done, so let the next
// read on the stack referesh its prompt and if there is one...
2011-06-03 03:18:55 +08:00
if ( ! m_input_reader_stack . IsEmpty ( ) )
2010-06-09 00:52:24 +08:00
{
2011-02-10 09:15:13 +08:00
// Cannot call GetCurrentInputReader here, as that would cause an infinite loop.
2011-06-03 03:18:55 +08:00
InputReaderSP reader_sp ( m_input_reader_stack . Top ( ) ) ;
2010-06-09 00:52:24 +08:00
if ( ! pop_reader_sp | | pop_reader_sp . get ( ) = = reader_sp . get ( ) )
{
2011-06-03 03:18:55 +08:00
m_input_reader_stack . Pop ( ) ;
2010-06-09 00:52:24 +08:00
reader_sp - > Notify ( eInputReaderDeactivate ) ;
reader_sp - > Notify ( eInputReaderDone ) ;
result = true ;
2011-06-03 03:18:55 +08:00
if ( ! m_input_reader_stack . IsEmpty ( ) )
2010-06-09 00:52:24 +08:00
{
2011-06-03 03:18:55 +08:00
reader_sp = m_input_reader_stack . Top ( ) ;
2010-06-09 00:52:24 +08:00
if ( reader_sp )
{
ActivateInputReader ( reader_sp ) ;
reader_sp - > Notify ( eInputReaderReactivate ) ;
}
}
}
}
return result ;
}
bool
Debugger : : CheckIfTopInputReaderIsDone ( )
{
bool result = false ;
2011-06-03 03:18:55 +08:00
if ( ! m_input_reader_stack . IsEmpty ( ) )
2010-06-09 00:52:24 +08:00
{
2011-02-10 09:15:13 +08:00
// Cannot call GetCurrentInputReader here, as that would cause an infinite loop.
2011-06-03 03:18:55 +08:00
InputReaderSP reader_sp ( m_input_reader_stack . Top ( ) ) ;
2010-06-09 00:52:24 +08:00
if ( reader_sp & & reader_sp - > IsDone ( ) )
{
result = true ;
PopInputReader ( reader_sp ) ;
}
}
return result ;
}
void
Debugger : : ActivateInputReader ( const InputReaderSP & reader_sp )
{
2011-02-09 09:08:52 +08:00
int input_fd = m_input_file . GetFile ( ) . GetDescriptor ( ) ;
2010-06-09 00:52:24 +08:00
2011-02-09 09:08:52 +08:00
if ( input_fd > = 0 )
2010-06-09 00:52:24 +08:00
{
2011-02-09 09:08:52 +08:00
Terminal tty ( input_fd ) ;
2011-02-08 07:24:47 +08:00
tty . SetEcho ( reader_sp - > GetEcho ( ) ) ;
2010-06-09 00:52:24 +08:00
2011-02-08 07:24:47 +08:00
switch ( reader_sp - > GetGranularity ( ) )
{
case eInputReaderGranularityByte :
case eInputReaderGranularityWord :
tty . SetCanonical ( false ) ;
break ;
case eInputReaderGranularityLine :
case eInputReaderGranularityAll :
tty . SetCanonical ( true ) ;
break ;
default :
break ;
2010-06-09 00:52:24 +08:00
}
}
}
2010-06-23 09:19:29 +08:00
2011-06-03 07:58:26 +08:00
StreamSP
Debugger : : GetAsyncOutputStream ( )
{
return StreamSP ( new StreamAsynchronousIO ( GetCommandInterpreter ( ) ,
CommandInterpreter : : eBroadcastBitAsynchronousOutputData ) ) ;
}
StreamSP
Debugger : : GetAsyncErrorStream ( )
{
return StreamSP ( new StreamAsynchronousIO ( GetCommandInterpreter ( ) ,
CommandInterpreter : : eBroadcastBitAsynchronousErrorData ) ) ;
}
2012-02-15 10:34:21 +08:00
uint32_t
Debugger : : GetNumDebuggers ( )
{
Mutex : : Locker locker ( GetDebuggerListMutex ( ) ) ;
return GetDebuggerList ( ) . size ( ) ;
}
lldb : : DebuggerSP
Debugger : : GetDebuggerAtIndex ( uint32_t index )
{
DebuggerSP debugger_sp ;
Mutex : : Locker locker ( GetDebuggerListMutex ( ) ) ;
DebuggerList & debugger_list = GetDebuggerList ( ) ;
if ( index < debugger_list . size ( ) )
debugger_sp = debugger_list [ index ] ;
return debugger_sp ;
}
2010-07-01 00:22:25 +08:00
DebuggerSP
Debugger : : FindDebuggerWithID ( lldb : : user_id_t id )
{
2011-09-17 16:33:22 +08:00
DebuggerSP debugger_sp ;
2010-07-01 00:22:25 +08:00
Mutex : : Locker locker ( GetDebuggerListMutex ( ) ) ;
DebuggerList & debugger_list = GetDebuggerList ( ) ;
DebuggerList : : iterator pos , end = debugger_list . end ( ) ;
for ( pos = debugger_list . begin ( ) ; pos ! = end ; + + pos )
{
if ( ( * pos ) . get ( ) - > GetID ( ) = = id )
{
debugger_sp = * pos ;
break ;
}
}
return debugger_sp ;
}
2010-09-04 08:03:46 +08:00
2010-09-19 10:33:57 +08:00
static void
TestPromptFormats ( StackFrame * frame )
{
if ( frame = = NULL )
return ;
StreamString s ;
const char * prompt_format =
" {addr = '${addr}' \n } "
" {process.id = '${process.id}' \n } "
" {process.name = '${process.name}' \n } "
" {process.file.basename = '${process.file.basename}' \n } "
" {process.file.fullpath = '${process.file.fullpath}' \n } "
" {thread.id = '${thread.id}' \n } "
" {thread.index = '${thread.index}' \n } "
" {thread.name = '${thread.name}' \n } "
" {thread.queue = '${thread.queue}' \n } "
" {thread.stop-reason = '${thread.stop-reason}' \n } "
" {target.arch = '${target.arch}' \n } "
" {module.file.basename = '${module.file.basename}' \n } "
" {module.file.fullpath = '${module.file.fullpath}' \n } "
" {file.basename = '${file.basename}' \n } "
" {file.fullpath = '${file.fullpath}' \n } "
" {frame.index = '${frame.index}' \n } "
" {frame.pc = '${frame.pc}' \n } "
" {frame.sp = '${frame.sp}' \n } "
" {frame.fp = '${frame.fp}' \n } "
" {frame.flags = '${frame.flags}' \n } "
" {frame.reg.rdi = '${frame.reg.rdi}' \n } "
" {frame.reg.rip = '${frame.reg.rip}' \n } "
" {frame.reg.rsp = '${frame.reg.rsp}' \n } "
" {frame.reg.rbp = '${frame.reg.rbp}' \n } "
" {frame.reg.rflags = '${frame.reg.rflags}' \n } "
" {frame.reg.xmm0 = '${frame.reg.xmm0}' \n } "
" {frame.reg.carp = '${frame.reg.carp}' \n } "
" {function.id = '${function.id}' \n } "
" {function.name = '${function.name}' \n } "
2012-01-15 01:04:19 +08:00
" {function.name-with-args = '${function.name-with-args}' \n } "
2010-09-19 10:33:57 +08:00
" {function.addr-offset = '${function.addr-offset}' \n } "
" {function.line-offset = '${function.line-offset}' \n } "
" {function.pc-offset = '${function.pc-offset}' \n } "
" {line.file.basename = '${line.file.basename}' \n } "
" {line.file.fullpath = '${line.file.fullpath}' \n } "
" {line.number = '${line.number}' \n } "
" {line.start-addr = '${line.start-addr}' \n } "
" {line.end-addr = '${line.end-addr}' \n } "
;
SymbolContext sc ( frame - > GetSymbolContext ( eSymbolContextEverything ) ) ;
ExecutionContext exe_ctx ;
2010-10-04 09:05:56 +08:00
frame - > CalculateExecutionContext ( exe_ctx ) ;
2010-09-19 10:33:57 +08:00
const char * end = NULL ;
if ( Debugger : : FormatPrompt ( prompt_format , & sc , & exe_ctx , & sc . line_entry . range . GetBaseAddress ( ) , s , & end ) )
{
printf ( " %s \n " , s . GetData ( ) ) ;
}
else
{
printf ( " error: at '%s' \n " , end ) ;
printf ( " what we got: %s \n " , s . GetData ( ) ) ;
}
}
2011-07-06 10:13:41 +08:00
static bool
2011-08-23 08:32:52 +08:00
ScanFormatDescriptor ( const char * var_name_begin ,
const char * var_name_end ,
const char * * var_name_final ,
const char * * percent_position ,
2011-09-17 16:33:22 +08:00
Format * custom_format ,
2011-08-23 08:32:52 +08:00
ValueObject : : ValueObjectRepresentationStyle * val_obj_display )
2011-07-06 10:13:41 +08:00
{
2011-07-23 01:03:19 +08:00
LogSP log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_TYPES ) ) ;
2011-07-06 10:13:41 +08:00
* percent_position = : : strchr ( var_name_begin , ' % ' ) ;
2011-07-06 12:07:21 +08:00
if ( ! * percent_position | | * percent_position > var_name_end )
2011-07-23 01:03:19 +08:00
{
if ( log )
log - > Printf ( " no format descriptor in string, skipping " ) ;
2011-07-06 10:13:41 +08:00
* var_name_final = var_name_end ;
2011-07-23 01:03:19 +08:00
}
2011-07-06 10:13:41 +08:00
else
{
* var_name_final = * percent_position ;
char * format_name = new char [ var_name_end - * var_name_final ] ; format_name [ var_name_end - * var_name_final - 1 ] = ' \0 ' ;
memcpy ( format_name , * var_name_final + 1 , var_name_end - * var_name_final - 1 ) ;
2011-07-23 01:03:19 +08:00
if ( log )
log - > Printf ( " parsing %s as a format descriptor " , format_name ) ;
2011-07-06 10:13:41 +08:00
if ( ! FormatManager : : GetFormatFromCString ( format_name ,
true ,
* custom_format ) )
{
2011-07-23 01:03:19 +08:00
if ( log )
log - > Printf ( " %s is an unknown format " , format_name ) ;
2011-07-06 10:13:41 +08:00
// if this is an @ sign, print ObjC description
2011-07-06 12:07:21 +08:00
if ( * format_name = = ' @ ' )
2011-07-06 10:13:41 +08:00
* val_obj_display = ValueObject : : eDisplayLanguageSpecific ;
// if this is a V, print the value using the default format
2011-07-23 01:03:19 +08:00
else if ( * format_name = = ' V ' )
2011-07-06 10:13:41 +08:00
* val_obj_display = ValueObject : : eDisplayValue ;
2011-07-22 08:16:08 +08:00
// if this is an L, print the location of the value
2011-07-23 01:03:19 +08:00
else if ( * format_name = = ' L ' )
2011-07-15 10:26:42 +08:00
* val_obj_display = ValueObject : : eDisplayLocation ;
2011-07-22 08:16:08 +08:00
// if this is an S, print the summary after all
2011-07-23 01:03:19 +08:00
else if ( * format_name = = ' S ' )
2011-07-22 08:16:08 +08:00
* val_obj_display = ValueObject : : eDisplaySummary ;
2011-08-04 10:34:29 +08:00
else if ( * format_name = = ' # ' )
* val_obj_display = ValueObject : : eDisplayChildrenCount ;
2011-08-20 05:13:46 +08:00
else if ( * format_name = = ' T ' )
* val_obj_display = ValueObject : : eDisplayType ;
2011-07-23 01:03:19 +08:00
else if ( log )
log - > Printf ( " %s is an error, leaving the previous value alone " , format_name ) ;
2011-07-06 10:13:41 +08:00
}
// a good custom format tells us to print the value using it
else
2011-07-23 01:03:19 +08:00
{
if ( log )
log - > Printf ( " will display value for this VO " ) ;
2011-07-06 10:13:41 +08:00
* val_obj_display = ValueObject : : eDisplayValue ;
2011-07-23 01:03:19 +08:00
}
2011-07-06 10:13:41 +08:00
delete format_name ;
}
2011-07-23 01:03:19 +08:00
if ( log )
log - > Printf ( " final format description outcome: custom_format = %d, val_obj_display = %d " ,
* custom_format ,
* val_obj_display ) ;
2011-07-06 10:13:41 +08:00
return true ;
}
static bool
2011-08-23 08:32:52 +08:00
ScanBracketedRange ( const char * var_name_begin ,
const char * var_name_end ,
const char * var_name_final ,
const char * * open_bracket_position ,
const char * * separator_position ,
const char * * close_bracket_position ,
const char * * var_name_final_if_array_range ,
int64_t * index_lower ,
int64_t * index_higher )
2011-07-06 10:13:41 +08:00
{
2011-07-23 01:03:19 +08:00
LogSP log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_TYPES ) ) ;
2011-07-06 10:13:41 +08:00
* open_bracket_position = : : strchr ( var_name_begin , ' [ ' ) ;
2011-07-06 12:07:21 +08:00
if ( * open_bracket_position & & * open_bracket_position < var_name_final )
2011-07-06 10:13:41 +08:00
{
* separator_position = : : strchr ( * open_bracket_position , ' - ' ) ; // might be NULL if this is a simple var[N] bitfield
* close_bracket_position = : : strchr ( * open_bracket_position , ' ] ' ) ;
// as usual, we assume that [] will come before %
//printf("trying to expand a []\n");
* var_name_final_if_array_range = * open_bracket_position ;
2011-07-06 12:07:21 +08:00
if ( * close_bracket_position - * open_bracket_position = = 1 )
2011-07-06 10:13:41 +08:00
{
2011-07-23 01:03:19 +08:00
if ( log )
log - > Printf ( " [] detected.. going from 0 to end of data " ) ;
2011-07-06 10:13:41 +08:00
* index_lower = 0 ;
}
else if ( * separator_position = = NULL | | * separator_position > var_name_end )
{
char * end = NULL ;
* index_lower = : : strtoul ( * open_bracket_position + 1 , & end , 0 ) ;
* index_higher = * index_lower ;
2011-07-23 01:03:19 +08:00
if ( log )
2011-09-21 05:44:10 +08:00
log - > Printf ( " [%lld] detected, high index is same " , * index_lower ) ;
2011-07-06 10:13:41 +08:00
}
2011-07-06 12:07:21 +08:00
else if ( * close_bracket_position & & * close_bracket_position < var_name_end )
2011-07-06 10:13:41 +08:00
{
char * end = NULL ;
* index_lower = : : strtoul ( * open_bracket_position + 1 , & end , 0 ) ;
* index_higher = : : strtoul ( * separator_position + 1 , & end , 0 ) ;
2011-07-23 01:03:19 +08:00
if ( log )
2011-09-21 05:44:10 +08:00
log - > Printf ( " [%lld-%lld] detected " , * index_lower , * index_higher ) ;
2011-07-06 10:13:41 +08:00
}
else
2011-07-23 01:03:19 +08:00
{
if ( log )
log - > Printf ( " expression is erroneous, cannot extract indices out of it " ) ;
2011-07-06 10:13:41 +08:00
return false ;
2011-07-23 01:03:19 +08:00
}
2011-07-06 10:13:41 +08:00
if ( * index_lower > * index_higher & & * index_higher > 0 )
{
2011-07-23 01:03:19 +08:00
if ( log )
log - > Printf ( " swapping indices " ) ;
2011-07-06 10:13:41 +08:00
int temp = * index_lower ;
* index_lower = * index_higher ;
* index_higher = temp ;
}
}
2011-07-23 01:03:19 +08:00
else if ( log )
log - > Printf ( " no bracketed range, skipping entirely " ) ;
2011-07-06 10:13:41 +08:00
return true ;
}
static ValueObjectSP
2011-08-23 08:32:52 +08:00
ExpandExpressionPath ( ValueObject * valobj ,
StackFrame * frame ,
bool * do_deref_pointer ,
const char * var_name_begin ,
const char * var_name_final ,
Error & error )
2011-07-06 10:13:41 +08:00
{
2011-07-23 01:03:19 +08:00
LogSP log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_TYPES ) ) ;
2011-07-06 10:13:41 +08:00
StreamString sstring ;
VariableSP var_sp ;
2011-07-06 12:07:21 +08:00
if ( * do_deref_pointer )
2011-07-23 01:03:19 +08:00
{
if ( log )
log - > Printf ( " been told to deref_pointer by caller " ) ;
2011-07-06 10:13:41 +08:00
sstring . PutChar ( ' * ' ) ;
2011-07-23 01:03:19 +08:00
}
2011-08-18 06:13:59 +08:00
else if ( valobj - > IsDereferenceOfParent ( ) & & ClangASTContext : : IsPointerType ( valobj - > GetParent ( ) - > GetClangType ( ) ) & & ! valobj - > IsArrayItemForPointer ( ) )
2011-07-06 10:13:41 +08:00
{
2011-07-23 01:03:19 +08:00
if ( log )
log - > Printf ( " decided to deref_pointer myself " ) ;
2011-07-06 10:13:41 +08:00
sstring . PutChar ( ' * ' ) ;
* do_deref_pointer = true ;
}
2011-08-18 06:13:59 +08:00
valobj - > GetExpressionPath ( sstring , true , ValueObject : : eHonorPointers ) ;
2011-07-23 01:03:19 +08:00
if ( log )
log - > Printf ( " expression path to expand in phase 0: %s " , sstring . GetData ( ) ) ;
2011-07-06 10:13:41 +08:00
sstring . PutRawBytes ( var_name_begin + 3 , var_name_final - var_name_begin - 3 ) ;
2011-07-23 01:03:19 +08:00
if ( log )
log - > Printf ( " expression path to expand in phase 1: %s " , sstring . GetData ( ) ) ;
2011-07-06 10:13:41 +08:00
std : : string name = std : : string ( sstring . GetData ( ) ) ;
ValueObjectSP target = frame - > GetValueForVariableExpressionPath ( name . c_str ( ) ,
eNoDynamicValues ,
0 ,
var_sp ,
error ) ;
return target ;
}
static ValueObjectSP
2011-08-23 08:32:52 +08:00
ExpandIndexedExpression ( ValueObject * valobj ,
uint32_t index ,
StackFrame * frame ,
bool deref_pointer )
2011-07-06 10:13:41 +08:00
{
2011-07-23 01:03:19 +08:00
LogSP log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_TYPES ) ) ;
2011-07-08 10:51:01 +08:00
const char * ptr_deref_format = " [%d] " ;
std : : auto_ptr < char > ptr_deref_buffer ( new char [ 10 ] ) ;
: : sprintf ( ptr_deref_buffer . get ( ) , ptr_deref_format , index ) ;
2011-07-23 01:03:19 +08:00
if ( log )
log - > Printf ( " name to deref: %s " , ptr_deref_buffer . get ( ) ) ;
2011-07-08 10:51:01 +08:00
const char * first_unparsed ;
ValueObject : : GetValueForExpressionPathOptions options ;
ValueObject : : ExpressionPathEndResultType final_value_type ;
ValueObject : : ExpressionPathScanEndReason reason_to_stop ;
ValueObject : : ExpressionPathAftermath what_next = ( deref_pointer ? ValueObject : : eDereference : ValueObject : : eNothing ) ;
2011-08-18 06:13:59 +08:00
ValueObjectSP item = valobj - > GetValueForExpressionPath ( ptr_deref_buffer . get ( ) ,
2011-07-08 10:51:01 +08:00
& first_unparsed ,
& reason_to_stop ,
& final_value_type ,
options ,
& what_next ) ;
if ( ! item )
{
2011-07-23 01:03:19 +08:00
if ( log )
log - > Printf ( " ERROR: unparsed portion = %s, why stopping = %d, "
" final_value_type %d " ,
2011-07-08 10:51:01 +08:00
first_unparsed , reason_to_stop , final_value_type ) ;
2011-07-06 10:13:41 +08:00
}
2011-07-08 10:51:01 +08:00
else
{
2011-07-23 01:03:19 +08:00
if ( log )
log - > Printf ( " ALL RIGHT: unparsed portion = %s, why stopping = %d, "
" final_value_type %d " ,
2011-07-08 10:51:01 +08:00
first_unparsed , reason_to_stop , final_value_type ) ;
}
2011-07-06 10:13:41 +08:00
return item ;
}
2010-09-19 10:33:57 +08:00
bool
Debugger : : FormatPrompt
(
const char * format ,
const SymbolContext * sc ,
const ExecutionContext * exe_ctx ,
const Address * addr ,
Stream & s ,
2011-06-30 06:27:15 +08:00
const char * * end ,
2011-08-18 06:13:59 +08:00
ValueObject * valobj
2010-09-19 10:33:57 +08:00
)
{
2011-08-18 06:13:59 +08:00
ValueObject * realvalobj = NULL ; // makes it super-easy to parse pointers
2010-09-19 10:33:57 +08:00
bool success = true ;
const char * p ;
2011-07-23 01:03:19 +08:00
LogSP log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_TYPES ) ) ;
2010-09-19 10:33:57 +08:00
for ( p = format ; * p ! = ' \0 ' ; + + p )
{
2011-08-18 06:13:59 +08:00
if ( realvalobj )
2011-06-30 06:27:15 +08:00
{
2011-08-18 06:13:59 +08:00
valobj = realvalobj ;
realvalobj = NULL ;
2011-06-30 06:27:15 +08:00
}
2010-09-19 10:33:57 +08:00
size_t non_special_chars = : : strcspn ( p , " ${} \\ " ) ;
if ( non_special_chars > 0 )
{
if ( success )
s . Write ( p , non_special_chars ) ;
p + = non_special_chars ;
}
if ( * p = = ' \0 ' )
{
break ;
}
else if ( * p = = ' { ' )
{
// Start a new scope that must have everything it needs if it is to
// to make it into the final output stream "s". If you want to make
// a format that only prints out the function or symbol name if there
// is one in the symbol context you can use:
// "{function =${function.name}}"
// The first '{' starts a new scope that end with the matching '}' at
// the end of the string. The contents "function =${function.name}"
// will then be evaluated and only be output if there is a function
// or symbol with a valid name.
StreamString sub_strm ;
+ + p ; // Skip the '{'
2011-08-18 06:13:59 +08:00
if ( FormatPrompt ( p , sc , exe_ctx , addr , sub_strm , & p , valobj ) )
2010-09-19 10:33:57 +08:00
{
// The stream had all it needed
s . Write ( sub_strm . GetData ( ) , sub_strm . GetSize ( ) ) ;
}
if ( * p ! = ' } ' )
{
success = false ;
break ;
}
}
else if ( * p = = ' } ' )
{
// End of a enclosing scope
break ;
}
else if ( * p = = ' $ ' )
{
// We have a prompt variable to print
+ + p ;
if ( * p = = ' { ' )
{
+ + p ;
const char * var_name_begin = p ;
const char * var_name_end = : : strchr ( p , ' } ' ) ;
if ( var_name_end & & var_name_begin < var_name_end )
{
// if we have already failed to parse, skip this variable
if ( success )
{
const char * cstr = NULL ;
Address format_addr ;
bool calculate_format_addr_function_offset = false ;
// Set reg_kind and reg_num to invalid values
RegisterKind reg_kind = kNumRegisterKinds ;
uint32_t reg_num = LLDB_INVALID_REGNUM ;
FileSpec format_file_spec ;
2011-03-25 05:19:54 +08:00
const RegisterInfo * reg_info = NULL ;
2010-09-19 10:33:57 +08:00
RegisterContext * reg_ctx = NULL ;
2011-07-06 10:13:41 +08:00
bool do_deref_pointer = false ;
2011-07-23 01:03:19 +08:00
ValueObject : : ExpressionPathScanEndReason reason_to_stop = ValueObject : : eEndOfString ;
ValueObject : : ExpressionPathEndResultType final_value_type = ValueObject : : ePlain ;
2011-07-08 10:51:01 +08:00
2010-09-19 10:33:57 +08:00
// Each variable must set success to true below...
bool var_success = false ;
switch ( var_name_begin [ 0 ] )
{
2011-06-30 06:27:15 +08:00
case ' * ' :
case ' v ' :
2011-07-30 03:53:35 +08:00
case ' s ' :
2011-06-30 06:27:15 +08:00
{
2011-08-18 06:13:59 +08:00
if ( ! valobj )
2011-07-30 03:53:35 +08:00
break ;
2011-08-03 01:27:39 +08:00
if ( log )
log - > Printf ( " initial string: %s " , var_name_begin ) ;
2011-07-30 03:53:35 +08:00
// check for *var and *svar
if ( * var_name_begin = = ' * ' )
{
do_deref_pointer = true ;
var_name_begin + + ;
}
2011-08-03 01:27:39 +08:00
if ( log )
log - > Printf ( " initial string: %s " , var_name_begin ) ;
2011-07-30 03:53:35 +08:00
if ( * var_name_begin = = ' s ' )
{
2011-09-17 16:33:22 +08:00
valobj = valobj - > GetSyntheticValue ( eUseSyntheticFilter ) . get ( ) ;
2011-07-30 03:53:35 +08:00
var_name_begin + + ;
}
2011-08-03 01:27:39 +08:00
if ( log )
log - > Printf ( " initial string: %s " , var_name_begin ) ;
2011-07-30 03:53:35 +08:00
// should be a 'v' by now
if ( * var_name_begin ! = ' v ' )
break ;
2011-08-03 01:27:39 +08:00
if ( log )
log - > Printf ( " initial string: %s " , var_name_begin ) ;
2011-07-08 10:51:01 +08:00
ValueObject : : ExpressionPathAftermath what_next = ( do_deref_pointer ?
ValueObject : : eDereference : ValueObject : : eNothing ) ;
ValueObject : : GetValueForExpressionPathOptions options ;
2011-08-12 01:08:01 +08:00
options . DontCheckDotVsArrowSyntax ( ) . DoAllowBitfieldSyntax ( ) . DoAllowFragileIVar ( ) . DoAllowSyntheticChildren ( ) ;
2011-07-06 12:07:21 +08:00
ValueObject : : ValueObjectRepresentationStyle val_obj_display = ValueObject : : eDisplaySummary ;
ValueObject * target = NULL ;
2011-09-17 16:33:22 +08:00
Format custom_format = eFormatInvalid ;
2011-07-06 12:07:21 +08:00
const char * var_name_final = NULL ;
const char * var_name_final_if_array_range = NULL ;
const char * close_bracket_position = NULL ;
int64_t index_lower = - 1 ;
int64_t index_higher = - 1 ;
bool is_array_range = false ;
2011-07-08 10:51:01 +08:00
const char * first_unparsed ;
2011-08-19 00:38:26 +08:00
bool was_plain_var = false ;
bool was_var_format = false ;
2011-07-08 10:51:01 +08:00
2011-08-18 06:13:59 +08:00
if ( ! valobj ) break ;
// simplest case ${var}, just print valobj's value
2011-07-06 12:07:21 +08:00
if ( : : strncmp ( var_name_begin , " var} " , strlen ( " var} " ) ) = = 0 )
{
2011-08-19 00:38:26 +08:00
was_plain_var = true ;
2011-08-18 06:13:59 +08:00
target = valobj ;
2011-07-06 12:07:21 +08:00
val_obj_display = ValueObject : : eDisplayValue ;
}
else if ( : : strncmp ( var_name_begin , " var% " , strlen ( " var% " ) ) = = 0 )
{
2011-08-19 00:38:26 +08:00
was_var_format = true ;
2011-07-06 12:07:21 +08:00
// this is a variable with some custom format applied to it
const char * percent_position ;
2011-08-18 06:13:59 +08:00
target = valobj ;
2011-07-06 12:07:21 +08:00
val_obj_display = ValueObject : : eDisplayValue ;
ScanFormatDescriptor ( var_name_begin ,
var_name_end ,
& var_name_final ,
& percent_position ,
& custom_format ,
& val_obj_display ) ;
}
// this is ${var.something} or multiple .something nested
else if ( : : strncmp ( var_name_begin , " var " , strlen ( " var " ) ) = = 0 )
2011-06-30 06:27:15 +08:00
{
2011-07-06 12:07:21 +08:00
const char * percent_position ;
ScanFormatDescriptor ( var_name_begin ,
var_name_end ,
& var_name_final ,
& percent_position ,
& custom_format ,
& val_obj_display ) ;
const char * open_bracket_position ;
const char * separator_position ;
ScanBracketedRange ( var_name_begin ,
var_name_end ,
var_name_final ,
& open_bracket_position ,
& separator_position ,
& close_bracket_position ,
& var_name_final_if_array_range ,
& index_lower ,
& index_higher ) ;
Error error ;
2011-07-08 10:51:01 +08:00
std : : auto_ptr < char > expr_path ( new char [ var_name_final - var_name_begin - 1 ] ) ;
: : memset ( expr_path . get ( ) , 0 , var_name_final - var_name_begin - 1 ) ;
memcpy ( expr_path . get ( ) , var_name_begin + 3 , var_name_final - var_name_begin - 3 ) ;
2011-07-23 01:03:19 +08:00
if ( log )
log - > Printf ( " symbol to expand: %s " , expr_path . get ( ) ) ;
2011-07-08 10:51:01 +08:00
2011-08-18 06:13:59 +08:00
target = valobj - > GetValueForExpressionPath ( expr_path . get ( ) ,
2011-07-08 10:51:01 +08:00
& first_unparsed ,
& reason_to_stop ,
& final_value_type ,
options ,
& what_next ) . get ( ) ;
if ( ! target )
2011-07-06 12:07:21 +08:00
{
2011-07-23 01:03:19 +08:00
if ( log )
log - > Printf ( " ERROR: unparsed portion = %s, why stopping = %d, "
" final_value_type %d " ,
2011-07-08 10:51:01 +08:00
first_unparsed , reason_to_stop , final_value_type ) ;
break ;
2011-07-06 10:13:41 +08:00
}
2011-07-08 10:51:01 +08:00
else
{
2011-07-23 01:03:19 +08:00
if ( log )
log - > Printf ( " ALL RIGHT: unparsed portion = %s, why stopping = %d, "
" final_value_type %d " ,
2011-07-08 10:51:01 +08:00
first_unparsed , reason_to_stop , final_value_type ) ;
}
2011-07-06 12:07:21 +08:00
}
else
2011-07-06 10:13:41 +08:00
break ;
2011-07-08 10:51:01 +08:00
is_array_range = ( final_value_type = = ValueObject : : eBoundedRange | |
final_value_type = = ValueObject : : eUnboundedRange ) ;
do_deref_pointer = ( what_next = = ValueObject : : eDereference ) ;
2011-07-06 12:07:21 +08:00
2011-07-07 03:27:11 +08:00
if ( do_deref_pointer & & ! is_array_range )
2011-07-06 10:13:41 +08:00
{
2011-07-06 12:07:21 +08:00
// I have not deref-ed yet, let's do it
// this happens when we are not going through GetValueForVariableExpressionPath
// to get to the target ValueObject
Error error ;
target = target - > Dereference ( error ) . get ( ) ;
2011-08-23 08:32:52 +08:00
if ( error . Fail ( ) )
{
if ( log )
log - > Printf ( " ERROR: %s \n " , error . AsCString ( " unknown " ) ) ; \
break ;
}
2011-07-06 12:07:21 +08:00
do_deref_pointer = false ;
2011-07-06 10:13:41 +08:00
}
2011-07-13 06:56:10 +08:00
2011-08-19 00:38:26 +08:00
// TODO use flags for these
2011-07-13 06:56:10 +08:00
bool is_array = ClangASTContext : : IsArrayType ( target - > GetClangType ( ) ) ;
bool is_pointer = ClangASTContext : : IsPointerType ( target - > GetClangType ( ) ) ;
2011-08-19 00:38:26 +08:00
bool is_aggregate = ClangASTContext : : IsAggregateType ( target - > GetClangType ( ) ) ;
2011-07-13 06:56:10 +08:00
if ( ( is_array | | is_pointer ) & & ( ! is_array_range ) & & val_obj_display = = ValueObject : : eDisplayValue ) // this should be wrong, but there are some exceptions
{
2011-08-19 00:38:26 +08:00
StreamString str_temp ;
2011-07-23 01:03:19 +08:00
if ( log )
log - > Printf ( " I am into array || pointer && !range " ) ;
2011-08-20 05:13:46 +08:00
if ( target - > HasSpecialCasesForPrintableRepresentation ( val_obj_display ,
custom_format ) )
2011-08-19 00:38:26 +08:00
{
2011-08-20 05:13:46 +08:00
// try to use the special cases
var_success = target - > DumpPrintableRepresentation ( str_temp ,
val_obj_display ,
custom_format ) ;
if ( log )
log - > Printf ( " special cases did%s match " , var_success ? " " : " n't " ) ;
// should not happen
if ( ! var_success )
s < < " <invalid usage of pointer value as object> " ;
else
s < < str_temp . GetData ( ) ;
2011-08-19 00:38:26 +08:00
var_success = true ;
2011-08-20 05:13:46 +08:00
break ;
2011-08-19 00:38:26 +08:00
}
else
2011-08-20 05:13:46 +08:00
{
2011-08-24 05:26:09 +08:00
if ( was_plain_var ) // if ${var}
2011-08-20 05:13:46 +08:00
{
s < < target - > GetTypeName ( ) < < " @ " < < target - > GetLocationAsCString ( ) ;
}
2011-08-24 05:26:09 +08:00
else if ( is_pointer ) // if pointer, value is the address stored
{
var_success = target - > GetPrintableRepresentation ( s ,
val_obj_display ,
custom_format ) ;
}
2011-08-20 05:13:46 +08:00
else
{
s < < " <invalid usage of pointer value as object> " ;
}
var_success = true ;
break ;
}
}
// if directly trying to print ${var}, and this is an aggregate, display a nice
// type @ location message
if ( is_aggregate & & was_plain_var )
{
s < < target - > GetTypeName ( ) < < " @ " < < target - > GetLocationAsCString ( ) ;
var_success = true ;
2011-08-19 00:38:26 +08:00
break ;
}
2011-08-20 05:13:46 +08:00
// if directly trying to print ${var%V}, and this is an aggregate, do not let the user do it
if ( is_aggregate & & ( ( was_var_format & & val_obj_display = = ValueObject : : eDisplayValue ) ) )
2011-08-19 00:38:26 +08:00
{
s < < " <invalid use of aggregate type> " ;
var_success = true ;
2011-07-13 06:56:10 +08:00
break ;
}
2011-07-06 12:07:21 +08:00
if ( ! is_array_range )
2011-07-23 01:03:19 +08:00
{
if ( log )
log - > Printf ( " dumping ordinary printable output " ) ;
2011-07-06 12:07:21 +08:00
var_success = target - > DumpPrintableRepresentation ( s , val_obj_display , custom_format ) ;
2011-07-23 01:03:19 +08:00
}
2011-07-06 12:07:21 +08:00
else
2011-07-23 01:03:19 +08:00
{
if ( log )
log - > Printf ( " checking if I can handle as array " ) ;
2011-07-06 12:07:21 +08:00
if ( ! is_array & & ! is_pointer )
break ;
2011-07-23 01:03:19 +08:00
if ( log )
log - > Printf ( " handle as array " ) ;
2011-07-08 10:51:01 +08:00
const char * special_directions = NULL ;
StreamString special_directions_writer ;
2011-07-06 12:07:21 +08:00
if ( close_bracket_position & & ( var_name_end - close_bracket_position > 1 ) )
{
2011-07-08 10:51:01 +08:00
ConstString additional_data ;
additional_data . SetCStringWithLength ( close_bracket_position + 1 , var_name_end - close_bracket_position - 1 ) ;
special_directions_writer . Printf ( " ${%svar%s} " ,
do_deref_pointer ? " * " : " " ,
additional_data . GetCString ( ) ) ;
special_directions = special_directions_writer . GetData ( ) ;
2011-07-06 12:07:21 +08:00
}
2011-07-06 10:13:41 +08:00
2011-07-06 12:07:21 +08:00
// let us display items index_lower thru index_higher of this array
s . PutChar ( ' [ ' ) ;
var_success = true ;
if ( index_higher < 0 )
2011-08-18 06:13:59 +08:00
index_higher = valobj - > GetNumChildren ( ) - 1 ;
2011-07-06 12:07:21 +08:00
2011-08-12 10:00:06 +08:00
uint32_t max_num_children = target - > GetUpdatePoint ( ) . GetTargetSP ( ) - > GetMaximumNumberOfChildrenToDisplay ( ) ;
2011-07-06 12:07:21 +08:00
for ( ; index_lower < = index_higher ; index_lower + + )
{
2011-09-22 12:58:26 +08:00
ValueObject * item = ExpandIndexedExpression ( target ,
index_lower ,
exe_ctx - > GetFramePtr ( ) ,
false ) . get ( ) ;
2011-07-06 12:07:21 +08:00
2011-07-08 10:51:01 +08:00
if ( ! item )
{
2011-07-23 01:03:19 +08:00
if ( log )
2011-09-21 05:44:10 +08:00
log - > Printf ( " ERROR in getting child item at index %lld " , index_lower ) ;
2011-07-08 10:51:01 +08:00
}
else
{
2011-07-23 01:03:19 +08:00
if ( log )
log - > Printf ( " special_directions for child item: %s " , special_directions ) ;
2011-07-08 10:51:01 +08:00
}
2011-07-06 12:07:21 +08:00
if ( ! special_directions )
var_success & = item - > DumpPrintableRepresentation ( s , val_obj_display , custom_format ) ;
else
var_success & = FormatPrompt ( special_directions , sc , exe_ctx , addr , s , NULL , item ) ;
2011-08-12 10:00:06 +08:00
if ( - - max_num_children = = 0 )
{
s . PutCString ( " , ... " ) ;
break ;
}
2011-07-06 12:07:21 +08:00
if ( index_lower < index_higher )
s . PutChar ( ' , ' ) ;
}
s . PutChar ( ' ] ' ) ;
2011-07-06 10:13:41 +08:00
}
2011-06-30 06:27:15 +08:00
}
2011-07-06 10:13:41 +08:00
break ;
2010-09-19 10:33:57 +08:00
case ' a ' :
if ( : : strncmp ( var_name_begin , " addr} " , strlen ( " addr} " ) ) = = 0 )
{
if ( addr & & addr - > IsValid ( ) )
{
var_success = true ;
format_addr = * addr ;
}
}
2011-10-14 15:41:33 +08:00
else if ( : : strncmp ( var_name_begin , " ansi. " , strlen ( " ansi. " ) ) = = 0 )
{
var_success = true ;
var_name_begin + = strlen ( " ansi. " ) ; // Skip the "ansi."
if ( : : strncmp ( var_name_begin , " fg. " , strlen ( " fg. " ) ) = = 0 )
{
var_name_begin + = strlen ( " fg. " ) ; // Skip the "fg."
if ( : : strncmp ( var_name_begin , " black} " , strlen ( " black} " ) ) = = 0 )
{
s . Printf ( " %s%s%s " ,
lldb_utility : : ansi : : k_escape_start ,
lldb_utility : : ansi : : k_fg_black ,
lldb_utility : : ansi : : k_escape_end ) ;
}
else if ( : : strncmp ( var_name_begin , " red} " , strlen ( " red} " ) ) = = 0 )
{
s . Printf ( " %s%s%s " ,
lldb_utility : : ansi : : k_escape_start ,
lldb_utility : : ansi : : k_fg_red ,
lldb_utility : : ansi : : k_escape_end ) ;
}
else if ( : : strncmp ( var_name_begin , " green} " , strlen ( " green} " ) ) = = 0 )
{
s . Printf ( " %s%s%s " ,
lldb_utility : : ansi : : k_escape_start ,
lldb_utility : : ansi : : k_fg_green ,
lldb_utility : : ansi : : k_escape_end ) ;
}
else if ( : : strncmp ( var_name_begin , " yellow} " , strlen ( " yellow} " ) ) = = 0 )
{
s . Printf ( " %s%s%s " ,
lldb_utility : : ansi : : k_escape_start ,
lldb_utility : : ansi : : k_fg_yellow ,
lldb_utility : : ansi : : k_escape_end ) ;
}
else if ( : : strncmp ( var_name_begin , " blue} " , strlen ( " blue} " ) ) = = 0 )
{
s . Printf ( " %s%s%s " ,
lldb_utility : : ansi : : k_escape_start ,
lldb_utility : : ansi : : k_fg_blue ,
lldb_utility : : ansi : : k_escape_end ) ;
}
else if ( : : strncmp ( var_name_begin , " purple} " , strlen ( " purple} " ) ) = = 0 )
{
s . Printf ( " %s%s%s " ,
lldb_utility : : ansi : : k_escape_start ,
lldb_utility : : ansi : : k_fg_purple ,
lldb_utility : : ansi : : k_escape_end ) ;
}
else if ( : : strncmp ( var_name_begin , " cyan} " , strlen ( " cyan} " ) ) = = 0 )
{
s . Printf ( " %s%s%s " ,
lldb_utility : : ansi : : k_escape_start ,
lldb_utility : : ansi : : k_fg_cyan ,
lldb_utility : : ansi : : k_escape_end ) ;
}
else if ( : : strncmp ( var_name_begin , " white} " , strlen ( " white} " ) ) = = 0 )
{
s . Printf ( " %s%s%s " ,
lldb_utility : : ansi : : k_escape_start ,
lldb_utility : : ansi : : k_fg_white ,
lldb_utility : : ansi : : k_escape_end ) ;
}
else
{
var_success = false ;
}
}
else if ( : : strncmp ( var_name_begin , " bg. " , strlen ( " bg. " ) ) = = 0 )
{
var_name_begin + = strlen ( " bg. " ) ; // Skip the "bg."
if ( : : strncmp ( var_name_begin , " black} " , strlen ( " black} " ) ) = = 0 )
{
s . Printf ( " %s%s%s " ,
lldb_utility : : ansi : : k_escape_start ,
lldb_utility : : ansi : : k_bg_black ,
lldb_utility : : ansi : : k_escape_end ) ;
}
else if ( : : strncmp ( var_name_begin , " red} " , strlen ( " red} " ) ) = = 0 )
{
s . Printf ( " %s%s%s " ,
lldb_utility : : ansi : : k_escape_start ,
lldb_utility : : ansi : : k_bg_red ,
lldb_utility : : ansi : : k_escape_end ) ;
}
else if ( : : strncmp ( var_name_begin , " green} " , strlen ( " green} " ) ) = = 0 )
{
s . Printf ( " %s%s%s " ,
lldb_utility : : ansi : : k_escape_start ,
lldb_utility : : ansi : : k_bg_green ,
lldb_utility : : ansi : : k_escape_end ) ;
}
else if ( : : strncmp ( var_name_begin , " yellow} " , strlen ( " yellow} " ) ) = = 0 )
{
s . Printf ( " %s%s%s " ,
lldb_utility : : ansi : : k_escape_start ,
lldb_utility : : ansi : : k_bg_yellow ,
lldb_utility : : ansi : : k_escape_end ) ;
}
else if ( : : strncmp ( var_name_begin , " blue} " , strlen ( " blue} " ) ) = = 0 )
{
s . Printf ( " %s%s%s " ,
lldb_utility : : ansi : : k_escape_start ,
lldb_utility : : ansi : : k_bg_blue ,
lldb_utility : : ansi : : k_escape_end ) ;
}
else if ( : : strncmp ( var_name_begin , " purple} " , strlen ( " purple} " ) ) = = 0 )
{
s . Printf ( " %s%s%s " ,
lldb_utility : : ansi : : k_escape_start ,
lldb_utility : : ansi : : k_bg_purple ,
lldb_utility : : ansi : : k_escape_end ) ;
}
else if ( : : strncmp ( var_name_begin , " cyan} " , strlen ( " cyan} " ) ) = = 0 )
{
s . Printf ( " %s%s%s " ,
lldb_utility : : ansi : : k_escape_start ,
lldb_utility : : ansi : : k_bg_cyan ,
lldb_utility : : ansi : : k_escape_end ) ;
}
else if ( : : strncmp ( var_name_begin , " white} " , strlen ( " white} " ) ) = = 0 )
{
s . Printf ( " %s%s%s " ,
lldb_utility : : ansi : : k_escape_start ,
lldb_utility : : ansi : : k_bg_white ,
lldb_utility : : ansi : : k_escape_end ) ;
}
else
{
var_success = false ;
}
}
else if ( : : strncmp ( var_name_begin , " normal} " , strlen ( " normal} " ) ) = = 0 )
{
s . Printf ( " %s%s%s " ,
lldb_utility : : ansi : : k_escape_start ,
lldb_utility : : ansi : : k_ctrl_normal ,
lldb_utility : : ansi : : k_escape_end ) ;
}
else if ( : : strncmp ( var_name_begin , " bold} " , strlen ( " bold} " ) ) = = 0 )
{
s . Printf ( " %s%s%s " ,
lldb_utility : : ansi : : k_escape_start ,
lldb_utility : : ansi : : k_ctrl_bold ,
lldb_utility : : ansi : : k_escape_end ) ;
}
else if ( : : strncmp ( var_name_begin , " faint} " , strlen ( " faint} " ) ) = = 0 )
{
s . Printf ( " %s%s%s " ,
lldb_utility : : ansi : : k_escape_start ,
lldb_utility : : ansi : : k_ctrl_faint ,
lldb_utility : : ansi : : k_escape_end ) ;
}
else if ( : : strncmp ( var_name_begin , " italic} " , strlen ( " italic} " ) ) = = 0 )
{
s . Printf ( " %s%s%s " ,
lldb_utility : : ansi : : k_escape_start ,
lldb_utility : : ansi : : k_ctrl_italic ,
lldb_utility : : ansi : : k_escape_end ) ;
}
else if ( : : strncmp ( var_name_begin , " underline} " , strlen ( " underline} " ) ) = = 0 )
{
s . Printf ( " %s%s%s " ,
lldb_utility : : ansi : : k_escape_start ,
lldb_utility : : ansi : : k_ctrl_underline ,
lldb_utility : : ansi : : k_escape_end ) ;
}
else if ( : : strncmp ( var_name_begin , " slow-blink} " , strlen ( " slow-blink} " ) ) = = 0 )
{
s . Printf ( " %s%s%s " ,
lldb_utility : : ansi : : k_escape_start ,
lldb_utility : : ansi : : k_ctrl_slow_blink ,
lldb_utility : : ansi : : k_escape_end ) ;
}
else if ( : : strncmp ( var_name_begin , " fast-blink} " , strlen ( " fast-blink} " ) ) = = 0 )
{
s . Printf ( " %s%s%s " ,
lldb_utility : : ansi : : k_escape_start ,
lldb_utility : : ansi : : k_ctrl_fast_blink ,
lldb_utility : : ansi : : k_escape_end ) ;
}
else if ( : : strncmp ( var_name_begin , " negative} " , strlen ( " negative} " ) ) = = 0 )
{
s . Printf ( " %s%s%s " ,
lldb_utility : : ansi : : k_escape_start ,
lldb_utility : : ansi : : k_ctrl_negative ,
lldb_utility : : ansi : : k_escape_end ) ;
}
else if ( : : strncmp ( var_name_begin , " conceal} " , strlen ( " conceal} " ) ) = = 0 )
{
s . Printf ( " %s%s%s " ,
lldb_utility : : ansi : : k_escape_start ,
lldb_utility : : ansi : : k_ctrl_conceal ,
lldb_utility : : ansi : : k_escape_end ) ;
}
else if ( : : strncmp ( var_name_begin , " crossed-out} " , strlen ( " crossed-out} " ) ) = = 0 )
{
s . Printf ( " %s%s%s " ,
lldb_utility : : ansi : : k_escape_start ,
lldb_utility : : ansi : : k_ctrl_crossed_out ,
lldb_utility : : ansi : : k_escape_end ) ;
}
else
{
var_success = false ;
}
}
2010-09-19 10:33:57 +08:00
break ;
case ' p ' :
if ( : : strncmp ( var_name_begin , " process. " , strlen ( " process. " ) ) = = 0 )
{
2011-09-22 12:58:26 +08:00
if ( exe_ctx )
2010-09-19 10:33:57 +08:00
{
2011-09-22 12:58:26 +08:00
Process * process = exe_ctx - > GetProcessPtr ( ) ;
if ( process )
2010-09-19 10:33:57 +08:00
{
2011-09-22 12:58:26 +08:00
var_name_begin + = : : strlen ( " process. " ) ;
if ( : : strncmp ( var_name_begin , " id} " , strlen ( " id} " ) ) = = 0 )
2010-09-19 10:33:57 +08:00
{
2011-10-20 02:09:39 +08:00
s . Printf ( " %llu " , process - > GetID ( ) ) ;
2011-09-22 12:58:26 +08:00
var_success = true ;
}
else if ( ( : : strncmp ( var_name_begin , " name} " , strlen ( " name} " ) ) = = 0 ) | |
( : : strncmp ( var_name_begin , " file.basename} " , strlen ( " file.basename} " ) ) = = 0 ) | |
( : : strncmp ( var_name_begin , " file.fullpath} " , strlen ( " file.fullpath} " ) ) = = 0 ) )
{
Module * exe_module = process - > GetTarget ( ) . GetExecutableModulePointer ( ) ;
if ( exe_module )
2010-09-19 10:33:57 +08:00
{
2011-09-22 12:58:26 +08:00
if ( var_name_begin [ 0 ] = = ' n ' | | var_name_begin [ 5 ] = = ' f ' )
{
format_file_spec . GetFilename ( ) = exe_module - > GetFileSpec ( ) . GetFilename ( ) ;
var_success = format_file_spec ;
}
else
{
format_file_spec = exe_module - > GetFileSpec ( ) ;
var_success = format_file_spec ;
}
2010-09-19 10:33:57 +08:00
}
}
}
2011-09-22 12:58:26 +08:00
}
2010-09-19 10:33:57 +08:00
}
break ;
case ' t ' :
if ( : : strncmp ( var_name_begin , " thread. " , strlen ( " thread. " ) ) = = 0 )
{
2011-09-22 12:58:26 +08:00
if ( exe_ctx )
2010-09-19 10:33:57 +08:00
{
2011-09-22 12:58:26 +08:00
Thread * thread = exe_ctx - > GetThreadPtr ( ) ;
if ( thread )
2010-09-19 10:33:57 +08:00
{
2011-09-22 12:58:26 +08:00
var_name_begin + = : : strlen ( " thread. " ) ;
if ( : : strncmp ( var_name_begin , " id} " , strlen ( " id} " ) ) = = 0 )
2010-09-19 10:33:57 +08:00
{
2011-10-20 02:09:39 +08:00
s . Printf ( " 0x%4.4llx " , thread - > GetID ( ) ) ;
2011-09-22 12:58:26 +08:00
var_success = true ;
}
else if ( : : strncmp ( var_name_begin , " index} " , strlen ( " index} " ) ) = = 0 )
{
s . Printf ( " %u " , thread - > GetIndexID ( ) ) ;
var_success = true ;
}
else if ( : : strncmp ( var_name_begin , " name} " , strlen ( " name} " ) ) = = 0 )
{
cstr = thread - > GetName ( ) ;
var_success = cstr & & cstr [ 0 ] ;
if ( var_success )
2010-09-19 10:33:57 +08:00
s . PutCString ( cstr ) ;
2011-09-22 12:58:26 +08:00
}
else if ( : : strncmp ( var_name_begin , " queue} " , strlen ( " queue} " ) ) = = 0 )
{
cstr = thread - > GetQueueName ( ) ;
var_success = cstr & & cstr [ 0 ] ;
if ( var_success )
s . PutCString ( cstr ) ;
}
else if ( : : strncmp ( var_name_begin , " stop-reason} " , strlen ( " stop-reason} " ) ) = = 0 )
{
StopInfoSP stop_info_sp = thread - > GetStopInfo ( ) ;
if ( stop_info_sp )
{
cstr = stop_info_sp - > GetDescription ( ) ;
if ( cstr & & cstr [ 0 ] )
{
s . PutCString ( cstr ) ;
var_success = true ;
}
2010-09-19 10:33:57 +08:00
}
}
2011-12-17 09:35:57 +08:00
else if ( : : strncmp ( var_name_begin , " return-value} " , strlen ( " return-value} " ) ) = = 0 )
{
StopInfoSP stop_info_sp = thread - > GetStopInfo ( ) ;
if ( stop_info_sp )
{
ValueObjectSP return_valobj_sp = StopInfo : : GetReturnValueObject ( stop_info_sp ) ;
if ( return_valobj_sp )
{
2011-12-23 03:12:40 +08:00
ValueObject : : DumpValueObjectOptions dump_options ;
ValueObject : : DumpValueObject ( s , return_valobj_sp . get ( ) , dump_options ) ;
var_success = true ;
2011-12-17 09:35:57 +08:00
}
}
}
2010-09-19 10:33:57 +08:00
}
}
}
else if ( : : strncmp ( var_name_begin , " target. " , strlen ( " target. " ) ) = = 0 )
{
2010-10-04 09:05:56 +08:00
Target * target = Target : : GetTargetFromContexts ( exe_ctx , sc ) ;
if ( target )
2010-09-19 10:33:57 +08:00
{
var_name_begin + = : : strlen ( " target. " ) ;
if ( : : strncmp ( var_name_begin , " arch} " , strlen ( " arch} " ) ) = = 0 )
{
ArchSpec arch ( target - > GetArchitecture ( ) ) ;
if ( arch . IsValid ( ) )
{
2011-02-23 08:35:02 +08:00
s . PutCString ( arch . GetArchitectureName ( ) ) ;
2010-09-19 10:33:57 +08:00
var_success = true ;
}
}
}
}
break ;
case ' m ' :
if ( : : strncmp ( var_name_begin , " module. " , strlen ( " module. " ) ) = = 0 )
{
2010-10-04 09:05:56 +08:00
if ( sc & & sc - > module_sp . get ( ) )
2010-09-19 10:33:57 +08:00
{
2010-10-04 09:05:56 +08:00
Module * module = sc - > module_sp . get ( ) ;
2010-09-19 10:33:57 +08:00
var_name_begin + = : : strlen ( " module. " ) ;
if ( : : strncmp ( var_name_begin , " file. " , strlen ( " file. " ) ) = = 0 )
{
if ( module - > GetFileSpec ( ) )
{
var_name_begin + = : : strlen ( " file. " ) ;
if ( : : strncmp ( var_name_begin , " basename} " , strlen ( " basename} " ) ) = = 0 )
{
format_file_spec . GetFilename ( ) = module - > GetFileSpec ( ) . GetFilename ( ) ;
var_success = format_file_spec ;
}
else if ( : : strncmp ( var_name_begin , " fullpath} " , strlen ( " fullpath} " ) ) = = 0 )
{
format_file_spec = module - > GetFileSpec ( ) ;
var_success = format_file_spec ;
}
}
}
}
}
break ;
case ' f ' :
if ( : : strncmp ( var_name_begin , " file. " , strlen ( " file. " ) ) = = 0 )
{
if ( sc & & sc - > comp_unit ! = NULL )
{
var_name_begin + = : : strlen ( " file. " ) ;
if ( : : strncmp ( var_name_begin , " basename} " , strlen ( " basename} " ) ) = = 0 )
{
format_file_spec . GetFilename ( ) = sc - > comp_unit - > GetFilename ( ) ;
var_success = format_file_spec ;
}
else if ( : : strncmp ( var_name_begin , " fullpath} " , strlen ( " fullpath} " ) ) = = 0 )
{
format_file_spec = * sc - > comp_unit ;
var_success = format_file_spec ;
}
}
}
else if ( : : strncmp ( var_name_begin , " frame. " , strlen ( " frame. " ) ) = = 0 )
{
2011-09-22 12:58:26 +08:00
if ( exe_ctx )
2010-09-19 10:33:57 +08:00
{
2011-09-22 12:58:26 +08:00
StackFrame * frame = exe_ctx - > GetFramePtr ( ) ;
if ( frame )
2010-09-19 10:33:57 +08:00
{
2011-09-22 12:58:26 +08:00
var_name_begin + = : : strlen ( " frame. " ) ;
if ( : : strncmp ( var_name_begin , " index} " , strlen ( " index} " ) ) = = 0 )
{
s . Printf ( " %u " , frame - > GetFrameIndex ( ) ) ;
var_success = true ;
}
else if ( : : strncmp ( var_name_begin , " pc} " , strlen ( " pc} " ) ) = = 0 )
{
reg_kind = eRegisterKindGeneric ;
reg_num = LLDB_REGNUM_GENERIC_PC ;
var_success = true ;
}
else if ( : : strncmp ( var_name_begin , " sp} " , strlen ( " sp} " ) ) = = 0 )
{
reg_kind = eRegisterKindGeneric ;
reg_num = LLDB_REGNUM_GENERIC_SP ;
var_success = true ;
}
else if ( : : strncmp ( var_name_begin , " fp} " , strlen ( " fp} " ) ) = = 0 )
{
reg_kind = eRegisterKindGeneric ;
reg_num = LLDB_REGNUM_GENERIC_FP ;
var_success = true ;
}
else if ( : : strncmp ( var_name_begin , " flags} " , strlen ( " flags} " ) ) = = 0 )
{
reg_kind = eRegisterKindGeneric ;
reg_num = LLDB_REGNUM_GENERIC_FLAGS ;
var_success = true ;
}
else if ( : : strncmp ( var_name_begin , " reg. " , strlen ( " reg. " ) ) = = 0 )
2010-09-19 10:33:57 +08:00
{
2011-09-22 12:58:26 +08:00
reg_ctx = frame - > GetRegisterContext ( ) . get ( ) ;
if ( reg_ctx )
2010-09-19 10:33:57 +08:00
{
2011-09-22 12:58:26 +08:00
var_name_begin + = : : strlen ( " reg. " ) ;
if ( var_name_begin < var_name_end )
{
std : : string reg_name ( var_name_begin , var_name_end ) ;
reg_info = reg_ctx - > GetRegisterInfoByName ( reg_name . c_str ( ) ) ;
if ( reg_info )
var_success = true ;
}
2010-09-19 10:33:57 +08:00
}
}
}
}
}
else if ( : : strncmp ( var_name_begin , " function. " , strlen ( " function. " ) ) = = 0 )
{
if ( sc & & ( sc - > function ! = NULL | | sc - > symbol ! = NULL ) )
{
var_name_begin + = : : strlen ( " function. " ) ;
if ( : : strncmp ( var_name_begin , " id} " , strlen ( " id} " ) ) = = 0 )
{
if ( sc - > function )
2011-10-20 02:09:39 +08:00
s . Printf ( " function{0x%8.8llx} " , sc - > function - > GetID ( ) ) ;
2010-09-19 10:33:57 +08:00
else
s . Printf ( " symbol[%u] " , sc - > symbol - > GetID ( ) ) ;
var_success = true ;
}
else if ( : : strncmp ( var_name_begin , " name} " , strlen ( " name} " ) ) = = 0 )
{
if ( sc - > function )
cstr = sc - > function - > GetName ( ) . AsCString ( NULL ) ;
else if ( sc - > symbol )
cstr = sc - > symbol - > GetName ( ) . AsCString ( NULL ) ;
if ( cstr )
{
s . PutCString ( cstr ) ;
2010-10-05 01:26:49 +08:00
if ( sc - > block )
{
Block * inline_block = sc - > block - > GetContainingInlinedBlock ( ) ;
if ( inline_block )
{
const InlineFunctionInfo * inline_info = sc - > block - > GetInlinedFunctionInfo ( ) ;
if ( inline_info )
{
s . PutCString ( " [inlined] " ) ;
inline_info - > GetName ( ) . Dump ( & s ) ;
}
}
}
2010-09-19 10:33:57 +08:00
var_success = true ;
}
}
Added a new thread and frame format that can be used to display a function
name + arguments when the data is available. It seems to work really well,
but some more testing is needed before we make this on by default.
The new function format name is:
${function.name-with-args}
To see how to use these formats see the website:
http://lldb.llvm.org/formats.html
Here is a sample backtrace of debugging LLDB with LLDB using this new format
value:
(lldb) thread backtrace all
* thread #1: tid = 0x2203, 0x00007fff88a17bca libsystem_kernel.dylib __psynch_cvwait + 10, stop reason = signal SIGINT, name = <lldb.driver.main-thread>, queue = com.apple.main-thread
frame #0: 0x00007fff88a17bca libsystem_kernel.dylib __psynch_cvwait + 10
frame #1: 0x00007fff884ae274 libsystem_c.dylib _pthread_cond_wait + 840
frame #2: 0x00000001010778ea LLDB lldb_private::Condition::Wait(this=0x0000000104846770, mutex=0x0000000104846730, abstime=0x0000000000000000, timed_out=0x00007fff5fbfdea7) + 138 at Condition.cpp:92
frame #3: 0x0000000101244c21 LLDB lldb_private::Predicate<bool>::WaitForValueEqualTo(this=0x0000000104846728, value=true, abstime=0x0000000000000000, timed_out=0x00007fff5fbfdea7) + 209 at Predicate.h:317
frame #4: 0x0000000100f6eeb2 LLDB lldb_private::Listener::WaitForEventsInternal(this=0x0000000104846660, timeout=0x0000000000000000, broadcaster=0x0000000000000000, broadcaster_names=0x0000000000000000, num_broadcaster_names=0x00000000, event_type_mask=0x00000000, event_sp=0x00007fff5fbfe030) + 386 at Listener.cpp:388
frame #5: 0x0000000100f6f231 LLDB lldb_private::Listener::WaitForEvent(this=0x0000000104846660, timeout=0x0000000000000000, event_sp=0x00007fff5fbfe030) + 81 at Listener.cpp:436
frame #6: 0x0000000100098dcd LLDB lldb::SBListener::WaitForEvent(this=0x00007fff5fbff0f0, timeout_secs=0xffffffff, event=0x00007fff5fbfe430) + 685 at SBListener.cpp:181
frame #7: 0x000000010000628c lldb Driver::MainLoop(this=0x00007fff5fbff620) + 5244 at Driver.cpp:1325
frame #8: 0x0000000100006ca3 lldb main(argc=1, argv=0x00007fff5fbff758, envp=0x00007fff5fbff768) + 419 at Driver.cpp:1460
frame #9: 0x0000000100000d54 lldb start + 52
thread #3: tid = 0x2703, 0x00007fff88a17df2 libsystem_kernel.dylib select$DARWIN_EXTSN + 10, name = <lldb.comm.debugger.input>
frame #0: 0x00007fff88a17df2 libsystem_kernel.dylib select$DARWIN_EXTSN + 10
frame #1: 0x0000000100f3f072 LLDB lldb_private::ConnectionFileDescriptor::BytesAvailable(this=0x000000010524d040, timeout_usec=0x004c4b40, error_ptr=0x0000000105640a18) + 722 at ConnectionFileDescriptor.cpp:542
frame #2: 0x0000000100f3e6dd LLDB lldb_private::ConnectionFileDescriptor::Read(this=0x000000010524d040, dst=0x0000000105640a60, dst_len=1024, timeout_usec=0x004c4b40, status=0x0000000105640a14, error_ptr=0x0000000105640a18) + 301 at ConnectionFileDescriptor.cpp:273
frame #3: 0x0000000100f3b8f7 LLDB lldb_private::Communication::ReadFromConnection(this=0x0000000104846270, dst=0x0000000105640a60, dst_len=1024, timeout_usec=0x004c4b40, status=0x0000000105640a14, error_ptr=0x0000000105640a18) + 167 at Communication.cpp:317
frame #4: 0x0000000100f3b197 LLDB lldb_private::Communication::ReadThread(p=0x0000000104846270) + 327 at Communication.cpp:344
frame #5: 0x0000000101078923 LLDB ThreadCreateTrampoline(arg=0x00000001045f6650) + 227 at Host.cpp:549
frame #6: 0x00007fff884aa8bf libsystem_c.dylib _pthread_start + 335
frame #7: 0x00007fff884adb75 libsystem_c.dylib thread_start + 13
thread #4: tid = 0x2803, 0x00007fff88a17df2 libsystem_kernel.dylib select$DARWIN_EXTSN + 10, name = <lldb.comm.driver.editline>
frame #0: 0x00007fff88a17df2 libsystem_kernel.dylib select$DARWIN_EXTSN + 10
frame #1: 0x0000000100f3f072 LLDB lldb_private::ConnectionFileDescriptor::BytesAvailable(this=0x0000000105700370, timeout_usec=0x004c4b40, error_ptr=0x00000001056c3a18) + 722 at ConnectionFileDescriptor.cpp:542
frame #2: 0x0000000100f3e6dd LLDB lldb_private::ConnectionFileDescriptor::Read(this=0x0000000105700370, dst=0x00000001056c3a60, dst_len=1024, timeout_usec=0x004c4b40, status=0x00000001056c3a14, error_ptr=0x00000001056c3a18) + 301 at ConnectionFileDescriptor.cpp:273
frame #3: 0x0000000100f3b8f7 LLDB lldb_private::Communication::ReadFromConnection(this=0x0000000105700000, dst=0x00000001056c3a60, dst_len=1024, timeout_usec=0x004c4b40, status=0x00000001056c3a14, error_ptr=0x00000001056c3a18) + 167 at Communication.cpp:317
frame #4: 0x0000000100f3b197 LLDB lldb_private::Communication::ReadThread(p=0x0000000105700000) + 327 at Communication.cpp:344
frame #5: 0x0000000101078923 LLDB ThreadCreateTrampoline(arg=0x0000000105700430) + 227 at Host.cpp:549
frame #6: 0x00007fff884aa8bf libsystem_c.dylib _pthread_start + 335
frame #7: 0x00007fff884adb75 libsystem_c.dylib thread_start + 13
thread #5: tid = 0x2903, 0x00007fff88a17df2 libsystem_kernel.dylib select$DARWIN_EXTSN + 10, name = <lldb.comm.driver.editline_output>
frame #0: 0x00007fff88a17df2 libsystem_kernel.dylib select$DARWIN_EXTSN + 10
frame #1: 0x0000000100f3f072 LLDB lldb_private::ConnectionFileDescriptor::BytesAvailable(this=0x00000001057178f0, timeout_usec=0x004c4b40, error_ptr=0x0000000105980a18) + 722 at ConnectionFileDescriptor.cpp:542
frame #2: 0x0000000100f3e6dd LLDB lldb_private::ConnectionFileDescriptor::Read(this=0x00000001057178f0, dst=0x0000000105980a60, dst_len=1024, timeout_usec=0x004c4b40, status=0x0000000105980a14, error_ptr=0x0000000105980a18) + 301 at ConnectionFileDescriptor.cpp:273
frame #3: 0x0000000100f3b8f7 LLDB lldb_private::Communication::ReadFromConnection(this=0x0000000105717580, dst=0x0000000105980a60, dst_len=1024, timeout_usec=0x004c4b40, status=0x0000000105980a14, error_ptr=0x0000000105980a18) + 167 at Communication.cpp:317
frame #4: 0x0000000100f3b197 LLDB lldb_private::Communication::ReadThread(p=0x0000000105717580) + 327 at Communication.cpp:344
frame #5: 0x0000000101078923 LLDB ThreadCreateTrampoline(arg=0x00000001057179b0) + 227 at Host.cpp:549
frame #6: 0x00007fff884aa8bf libsystem_c.dylib _pthread_start + 335
frame #7: 0x00007fff884adb75 libsystem_c.dylib thread_start + 13
thread #6: tid = 0x2a03, 0x00007fff88a18af2 libsystem_kernel.dylib read + 10, name = <lldb.driver.commandline_io>
frame #0: 0x00007fff88a18af2 libsystem_kernel.dylib read + 10
frame #1: 0x0000000100050c3b libedit.3.dylib read_init + 247
frame #2: 0x0000000100050e96 libedit.3.dylib el_wgetc + 155
frame #3: 0x000000010005115d libedit.3.dylib el_wgets + 578
frame #4: 0x000000010005debc libedit.3.dylib el_gets + 37
frame #5: 0x000000010000d409 lldb IOChannel::LibeditGetInput(this=0x0000000105700490, new_line=0x0000000105a03db0) + 89 at IOChannel.cpp:311
frame #6: 0x000000010000d8b6 lldb IOChannel::Run(this=0x0000000105700490) + 806 at IOChannel.cpp:391
frame #7: 0x000000010000d57d lldb IOChannel::IOReadThread(ptr=0x0000000105700490) + 29 at IOChannel.cpp:345
frame #8: 0x0000000101078923 LLDB ThreadCreateTrampoline(arg=0x00000001057179f0) + 227 at Host.cpp:549
frame #9: 0x00007fff884aa8bf libsystem_c.dylib _pthread_start + 335
frame #10: 0x00007fff884adb75 libsystem_c.dylib thread_start + 13
(lldb)
llvm-svn: 148110
2012-01-13 16:39:16 +08:00
else if ( : : strncmp ( var_name_begin , " name-with-args} " , strlen ( " name-with-args} " ) ) = = 0 )
{
// Print the function name with arguments in it
if ( sc - > function )
{
var_success = true ;
ExecutionContextScope * exe_scope = exe_ctx ? exe_ctx - > GetBestExecutionContextScope ( ) : NULL ;
cstr = sc - > function - > GetName ( ) . AsCString ( NULL ) ;
if ( cstr )
{
const InlineFunctionInfo * inline_info = NULL ;
VariableListSP variable_list_sp ;
bool get_function_vars = true ;
if ( sc - > block )
{
Block * inline_block = sc - > block - > GetContainingInlinedBlock ( ) ;
if ( inline_block )
{
get_function_vars = false ;
inline_info = sc - > block - > GetInlinedFunctionInfo ( ) ;
if ( inline_info )
variable_list_sp = inline_block - > GetBlockVariableList ( true ) ;
}
}
if ( get_function_vars )
{
variable_list_sp = sc - > function - > GetBlock ( true ) . GetBlockVariableList ( true ) ;
}
if ( inline_info )
{
s . PutCString ( cstr ) ;
s . PutCString ( " [inlined] " ) ;
cstr = inline_info - > GetName ( ) . GetCString ( ) ;
}
VariableList args ;
if ( variable_list_sp )
{
const size_t num_variables = variable_list_sp - > GetSize ( ) ;
for ( size_t var_idx = 0 ; var_idx < num_variables ; + + var_idx )
{
VariableSP var_sp ( variable_list_sp - > GetVariableAtIndex ( var_idx ) ) ;
if ( var_sp - > GetScope ( ) = = eValueTypeVariableArgument )
args . AddVariable ( var_sp ) ;
}
}
if ( args . GetSize ( ) > 0 )
{
const char * open_paren = strchr ( cstr , ' ( ' ) ;
const char * close_paren = NULL ;
if ( open_paren )
close_paren = strchr ( open_paren , ' ) ' ) ;
if ( open_paren )
s . Write ( cstr , open_paren - cstr + 1 ) ;
else
{
s . PutCString ( cstr ) ;
s . PutChar ( ' ( ' ) ;
}
2012-01-19 05:56:18 +08:00
const size_t num_args = args . GetSize ( ) ;
Added a new thread and frame format that can be used to display a function
name + arguments when the data is available. It seems to work really well,
but some more testing is needed before we make this on by default.
The new function format name is:
${function.name-with-args}
To see how to use these formats see the website:
http://lldb.llvm.org/formats.html
Here is a sample backtrace of debugging LLDB with LLDB using this new format
value:
(lldb) thread backtrace all
* thread #1: tid = 0x2203, 0x00007fff88a17bca libsystem_kernel.dylib __psynch_cvwait + 10, stop reason = signal SIGINT, name = <lldb.driver.main-thread>, queue = com.apple.main-thread
frame #0: 0x00007fff88a17bca libsystem_kernel.dylib __psynch_cvwait + 10
frame #1: 0x00007fff884ae274 libsystem_c.dylib _pthread_cond_wait + 840
frame #2: 0x00000001010778ea LLDB lldb_private::Condition::Wait(this=0x0000000104846770, mutex=0x0000000104846730, abstime=0x0000000000000000, timed_out=0x00007fff5fbfdea7) + 138 at Condition.cpp:92
frame #3: 0x0000000101244c21 LLDB lldb_private::Predicate<bool>::WaitForValueEqualTo(this=0x0000000104846728, value=true, abstime=0x0000000000000000, timed_out=0x00007fff5fbfdea7) + 209 at Predicate.h:317
frame #4: 0x0000000100f6eeb2 LLDB lldb_private::Listener::WaitForEventsInternal(this=0x0000000104846660, timeout=0x0000000000000000, broadcaster=0x0000000000000000, broadcaster_names=0x0000000000000000, num_broadcaster_names=0x00000000, event_type_mask=0x00000000, event_sp=0x00007fff5fbfe030) + 386 at Listener.cpp:388
frame #5: 0x0000000100f6f231 LLDB lldb_private::Listener::WaitForEvent(this=0x0000000104846660, timeout=0x0000000000000000, event_sp=0x00007fff5fbfe030) + 81 at Listener.cpp:436
frame #6: 0x0000000100098dcd LLDB lldb::SBListener::WaitForEvent(this=0x00007fff5fbff0f0, timeout_secs=0xffffffff, event=0x00007fff5fbfe430) + 685 at SBListener.cpp:181
frame #7: 0x000000010000628c lldb Driver::MainLoop(this=0x00007fff5fbff620) + 5244 at Driver.cpp:1325
frame #8: 0x0000000100006ca3 lldb main(argc=1, argv=0x00007fff5fbff758, envp=0x00007fff5fbff768) + 419 at Driver.cpp:1460
frame #9: 0x0000000100000d54 lldb start + 52
thread #3: tid = 0x2703, 0x00007fff88a17df2 libsystem_kernel.dylib select$DARWIN_EXTSN + 10, name = <lldb.comm.debugger.input>
frame #0: 0x00007fff88a17df2 libsystem_kernel.dylib select$DARWIN_EXTSN + 10
frame #1: 0x0000000100f3f072 LLDB lldb_private::ConnectionFileDescriptor::BytesAvailable(this=0x000000010524d040, timeout_usec=0x004c4b40, error_ptr=0x0000000105640a18) + 722 at ConnectionFileDescriptor.cpp:542
frame #2: 0x0000000100f3e6dd LLDB lldb_private::ConnectionFileDescriptor::Read(this=0x000000010524d040, dst=0x0000000105640a60, dst_len=1024, timeout_usec=0x004c4b40, status=0x0000000105640a14, error_ptr=0x0000000105640a18) + 301 at ConnectionFileDescriptor.cpp:273
frame #3: 0x0000000100f3b8f7 LLDB lldb_private::Communication::ReadFromConnection(this=0x0000000104846270, dst=0x0000000105640a60, dst_len=1024, timeout_usec=0x004c4b40, status=0x0000000105640a14, error_ptr=0x0000000105640a18) + 167 at Communication.cpp:317
frame #4: 0x0000000100f3b197 LLDB lldb_private::Communication::ReadThread(p=0x0000000104846270) + 327 at Communication.cpp:344
frame #5: 0x0000000101078923 LLDB ThreadCreateTrampoline(arg=0x00000001045f6650) + 227 at Host.cpp:549
frame #6: 0x00007fff884aa8bf libsystem_c.dylib _pthread_start + 335
frame #7: 0x00007fff884adb75 libsystem_c.dylib thread_start + 13
thread #4: tid = 0x2803, 0x00007fff88a17df2 libsystem_kernel.dylib select$DARWIN_EXTSN + 10, name = <lldb.comm.driver.editline>
frame #0: 0x00007fff88a17df2 libsystem_kernel.dylib select$DARWIN_EXTSN + 10
frame #1: 0x0000000100f3f072 LLDB lldb_private::ConnectionFileDescriptor::BytesAvailable(this=0x0000000105700370, timeout_usec=0x004c4b40, error_ptr=0x00000001056c3a18) + 722 at ConnectionFileDescriptor.cpp:542
frame #2: 0x0000000100f3e6dd LLDB lldb_private::ConnectionFileDescriptor::Read(this=0x0000000105700370, dst=0x00000001056c3a60, dst_len=1024, timeout_usec=0x004c4b40, status=0x00000001056c3a14, error_ptr=0x00000001056c3a18) + 301 at ConnectionFileDescriptor.cpp:273
frame #3: 0x0000000100f3b8f7 LLDB lldb_private::Communication::ReadFromConnection(this=0x0000000105700000, dst=0x00000001056c3a60, dst_len=1024, timeout_usec=0x004c4b40, status=0x00000001056c3a14, error_ptr=0x00000001056c3a18) + 167 at Communication.cpp:317
frame #4: 0x0000000100f3b197 LLDB lldb_private::Communication::ReadThread(p=0x0000000105700000) + 327 at Communication.cpp:344
frame #5: 0x0000000101078923 LLDB ThreadCreateTrampoline(arg=0x0000000105700430) + 227 at Host.cpp:549
frame #6: 0x00007fff884aa8bf libsystem_c.dylib _pthread_start + 335
frame #7: 0x00007fff884adb75 libsystem_c.dylib thread_start + 13
thread #5: tid = 0x2903, 0x00007fff88a17df2 libsystem_kernel.dylib select$DARWIN_EXTSN + 10, name = <lldb.comm.driver.editline_output>
frame #0: 0x00007fff88a17df2 libsystem_kernel.dylib select$DARWIN_EXTSN + 10
frame #1: 0x0000000100f3f072 LLDB lldb_private::ConnectionFileDescriptor::BytesAvailable(this=0x00000001057178f0, timeout_usec=0x004c4b40, error_ptr=0x0000000105980a18) + 722 at ConnectionFileDescriptor.cpp:542
frame #2: 0x0000000100f3e6dd LLDB lldb_private::ConnectionFileDescriptor::Read(this=0x00000001057178f0, dst=0x0000000105980a60, dst_len=1024, timeout_usec=0x004c4b40, status=0x0000000105980a14, error_ptr=0x0000000105980a18) + 301 at ConnectionFileDescriptor.cpp:273
frame #3: 0x0000000100f3b8f7 LLDB lldb_private::Communication::ReadFromConnection(this=0x0000000105717580, dst=0x0000000105980a60, dst_len=1024, timeout_usec=0x004c4b40, status=0x0000000105980a14, error_ptr=0x0000000105980a18) + 167 at Communication.cpp:317
frame #4: 0x0000000100f3b197 LLDB lldb_private::Communication::ReadThread(p=0x0000000105717580) + 327 at Communication.cpp:344
frame #5: 0x0000000101078923 LLDB ThreadCreateTrampoline(arg=0x00000001057179b0) + 227 at Host.cpp:549
frame #6: 0x00007fff884aa8bf libsystem_c.dylib _pthread_start + 335
frame #7: 0x00007fff884adb75 libsystem_c.dylib thread_start + 13
thread #6: tid = 0x2a03, 0x00007fff88a18af2 libsystem_kernel.dylib read + 10, name = <lldb.driver.commandline_io>
frame #0: 0x00007fff88a18af2 libsystem_kernel.dylib read + 10
frame #1: 0x0000000100050c3b libedit.3.dylib read_init + 247
frame #2: 0x0000000100050e96 libedit.3.dylib el_wgetc + 155
frame #3: 0x000000010005115d libedit.3.dylib el_wgets + 578
frame #4: 0x000000010005debc libedit.3.dylib el_gets + 37
frame #5: 0x000000010000d409 lldb IOChannel::LibeditGetInput(this=0x0000000105700490, new_line=0x0000000105a03db0) + 89 at IOChannel.cpp:311
frame #6: 0x000000010000d8b6 lldb IOChannel::Run(this=0x0000000105700490) + 806 at IOChannel.cpp:391
frame #7: 0x000000010000d57d lldb IOChannel::IOReadThread(ptr=0x0000000105700490) + 29 at IOChannel.cpp:345
frame #8: 0x0000000101078923 LLDB ThreadCreateTrampoline(arg=0x00000001057179f0) + 227 at Host.cpp:549
frame #9: 0x00007fff884aa8bf libsystem_c.dylib _pthread_start + 335
frame #10: 0x00007fff884adb75 libsystem_c.dylib thread_start + 13
(lldb)
llvm-svn: 148110
2012-01-13 16:39:16 +08:00
for ( size_t arg_idx = 0 ; arg_idx < num_args ; + + arg_idx )
{
VariableSP var_sp ( args . GetVariableAtIndex ( arg_idx ) ) ;
ValueObjectSP var_value_sp ( ValueObjectVariable : : Create ( exe_scope , var_sp ) ) ;
const char * var_name = var_value_sp - > GetName ( ) . GetCString ( ) ;
const char * var_value = var_value_sp - > GetValueAsCString ( ) ;
if ( var_value_sp - > GetError ( ) . Success ( ) )
{
if ( arg_idx > 0 )
s . PutCString ( " , " ) ;
s . Printf ( " %s=%s " , var_name , var_value ) ;
}
}
if ( close_paren )
s . PutCString ( close_paren ) ;
else
s . PutChar ( ' ) ' ) ;
}
else
{
s . PutCString ( cstr ) ;
}
}
}
else if ( sc - > symbol )
{
cstr = sc - > symbol - > GetName ( ) . AsCString ( NULL ) ;
if ( cstr )
{
s . PutCString ( cstr ) ;
var_success = true ;
}
}
}
2010-09-19 10:33:57 +08:00
else if ( : : strncmp ( var_name_begin , " addr-offset} " , strlen ( " addr-offset} " ) ) = = 0 )
{
var_success = addr ! = NULL ;
if ( var_success )
{
format_addr = * addr ;
calculate_format_addr_function_offset = true ;
}
}
else if ( : : strncmp ( var_name_begin , " line-offset} " , strlen ( " line-offset} " ) ) = = 0 )
{
var_success = sc - > line_entry . range . GetBaseAddress ( ) . IsValid ( ) ;
if ( var_success )
{
format_addr = sc - > line_entry . range . GetBaseAddress ( ) ;
calculate_format_addr_function_offset = true ;
}
}
else if ( : : strncmp ( var_name_begin , " pc-offset} " , strlen ( " pc-offset} " ) ) = = 0 )
{
2011-09-22 12:58:26 +08:00
StackFrame * frame = exe_ctx - > GetFramePtr ( ) ;
var_success = frame ! = NULL ;
2010-09-19 10:33:57 +08:00
if ( var_success )
{
2011-09-22 12:58:26 +08:00
format_addr = frame - > GetFrameCodeAddress ( ) ;
2010-09-19 10:33:57 +08:00
calculate_format_addr_function_offset = true ;
}
}
}
}
break ;
case ' l ' :
if ( : : strncmp ( var_name_begin , " line. " , strlen ( " line. " ) ) = = 0 )
{
if ( sc & & sc - > line_entry . IsValid ( ) )
{
var_name_begin + = : : strlen ( " line. " ) ;
if ( : : strncmp ( var_name_begin , " file. " , strlen ( " file. " ) ) = = 0 )
{
var_name_begin + = : : strlen ( " file. " ) ;
if ( : : strncmp ( var_name_begin , " basename} " , strlen ( " basename} " ) ) = = 0 )
{
format_file_spec . GetFilename ( ) = sc - > line_entry . file . GetFilename ( ) ;
var_success = format_file_spec ;
}
else if ( : : strncmp ( var_name_begin , " fullpath} " , strlen ( " fullpath} " ) ) = = 0 )
{
format_file_spec = sc - > line_entry . file ;
var_success = format_file_spec ;
}
}
else if ( : : strncmp ( var_name_begin , " number} " , strlen ( " number} " ) ) = = 0 )
{
var_success = true ;
s . Printf ( " %u " , sc - > line_entry . line ) ;
}
else if ( ( : : strncmp ( var_name_begin , " start-addr} " , strlen ( " start-addr} " ) ) = = 0 ) | |
( : : strncmp ( var_name_begin , " end-addr} " , strlen ( " end-addr} " ) ) = = 0 ) )
{
var_success = sc & & sc - > line_entry . range . GetBaseAddress ( ) . IsValid ( ) ;
if ( var_success )
{
format_addr = sc - > line_entry . range . GetBaseAddress ( ) ;
if ( var_name_begin [ 0 ] = = ' e ' )
format_addr . Slide ( sc - > line_entry . range . GetByteSize ( ) ) ;
}
}
}
}
break ;
}
if ( var_success )
{
// If format addr is valid, then we need to print an address
if ( reg_num ! = LLDB_INVALID_REGNUM )
{
2011-09-22 12:58:26 +08:00
StackFrame * frame = exe_ctx - > GetFramePtr ( ) ;
2010-09-19 10:33:57 +08:00
// We have a register value to display...
if ( reg_num = = LLDB_REGNUM_GENERIC_PC & & reg_kind = = eRegisterKindGeneric )
{
2011-09-22 12:58:26 +08:00
format_addr = frame - > GetFrameCodeAddress ( ) ;
2010-09-19 10:33:57 +08:00
}
else
{
if ( reg_ctx = = NULL )
2011-09-22 12:58:26 +08:00
reg_ctx = frame - > GetRegisterContext ( ) . get ( ) ;
2010-09-19 10:33:57 +08:00
if ( reg_ctx )
{
if ( reg_kind ! = kNumRegisterKinds )
reg_num = reg_ctx - > ConvertRegisterKindToRegisterNumber ( reg_kind , reg_num ) ;
reg_info = reg_ctx - > GetRegisterInfoAtIndex ( reg_num ) ;
var_success = reg_info ! = NULL ;
}
}
}
if ( reg_info ! = NULL )
{
2011-05-10 04:18:18 +08:00
RegisterValue reg_value ;
var_success = reg_ctx - > ReadRegister ( reg_info , reg_value ) ;
if ( var_success )
2010-09-19 10:33:57 +08:00
{
2011-05-15 12:12:07 +08:00
reg_value . Dump ( & s , reg_info , false , false , eFormatDefault ) ;
2010-09-19 10:33:57 +08:00
}
}
if ( format_file_spec )
{
s < < format_file_spec ;
}
// If format addr is valid, then we need to print an address
if ( format_addr . IsValid ( ) )
{
2010-10-04 09:05:56 +08:00
var_success = false ;
2010-09-19 10:33:57 +08:00
if ( calculate_format_addr_function_offset )
{
Address func_addr ;
2010-10-04 09:05:56 +08:00
if ( sc )
{
if ( sc - > function )
2010-10-05 01:26:49 +08:00
{
2010-10-04 09:05:56 +08:00
func_addr = sc - > function - > GetAddressRange ( ) . GetBaseAddress ( ) ;
2010-10-05 01:26:49 +08:00
if ( sc - > block )
{
// Check to make sure we aren't in an inline
// function. If we are, use the inline block
// range that contains "format_addr" since
// blocks can be discontiguous.
Block * inline_block = sc - > block - > GetContainingInlinedBlock ( ) ;
AddressRange inline_range ;
if ( inline_block & & inline_block - > GetRangeContainingAddress ( format_addr , inline_range ) )
func_addr = inline_range . GetBaseAddress ( ) ;
}
}
2010-10-04 09:05:56 +08:00
else if ( sc - > symbol & & sc - > symbol - > GetAddressRangePtr ( ) )
func_addr = sc - > symbol - > GetAddressRangePtr ( ) - > GetBaseAddress ( ) ;
}
if ( func_addr . IsValid ( ) )
2010-09-19 10:33:57 +08:00
{
if ( func_addr . GetSection ( ) = = format_addr . GetSection ( ) )
{
addr_t func_file_addr = func_addr . GetFileAddress ( ) ;
addr_t addr_file_addr = format_addr . GetFileAddress ( ) ;
if ( addr_file_addr > func_file_addr )
s . Printf ( " + %llu " , addr_file_addr - func_file_addr ) ;
else if ( addr_file_addr < func_file_addr )
s . Printf ( " - %llu " , func_file_addr - addr_file_addr ) ;
2010-10-04 09:05:56 +08:00
var_success = true ;
2010-09-19 10:33:57 +08:00
}
else
2010-10-04 09:05:56 +08:00
{
Target * target = Target : : GetTargetFromContexts ( exe_ctx , sc ) ;
if ( target )
{
addr_t func_load_addr = func_addr . GetLoadAddress ( target ) ;
addr_t addr_load_addr = format_addr . GetLoadAddress ( target ) ;
if ( addr_load_addr > func_load_addr )
s . Printf ( " + %llu " , addr_load_addr - func_load_addr ) ;
else if ( addr_load_addr < func_load_addr )
s . Printf ( " - %llu " , func_load_addr - addr_load_addr ) ;
var_success = true ;
}
}
2010-09-19 10:33:57 +08:00
}
}
else
{
2010-10-04 09:05:56 +08:00
Target * target = Target : : GetTargetFromContexts ( exe_ctx , sc ) ;
2010-09-19 10:33:57 +08:00
addr_t vaddr = LLDB_INVALID_ADDRESS ;
2010-10-04 09:05:56 +08:00
if ( exe_ctx & & ! target - > GetSectionLoadList ( ) . IsEmpty ( ) )
vaddr = format_addr . GetLoadAddress ( target ) ;
2010-09-19 10:33:57 +08:00
if ( vaddr = = LLDB_INVALID_ADDRESS )
vaddr = format_addr . GetFileAddress ( ) ;
if ( vaddr ! = LLDB_INVALID_ADDRESS )
2010-10-04 09:05:56 +08:00
{
2011-02-16 05:59:32 +08:00
int addr_width = target - > GetArchitecture ( ) . GetAddressByteSize ( ) * 2 ;
2010-11-19 12:16:11 +08:00
if ( addr_width = = 0 )
addr_width = 16 ;
s . Printf ( " 0x%*.*llx " , addr_width , addr_width , vaddr ) ;
2010-10-04 09:05:56 +08:00
var_success = true ;
}
2010-09-19 10:33:57 +08:00
}
}
}
if ( var_success = = false )
success = false ;
}
p = var_name_end ;
}
else
break ;
}
else
{
// We got a dollar sign with no '{' after it, it must just be a dollar sign
s . PutChar ( * p ) ;
}
}
else if ( * p = = ' \\ ' )
{
+ + p ; // skip the slash
switch ( * p )
{
case ' a ' : s . PutChar ( ' \a ' ) ; break ;
case ' b ' : s . PutChar ( ' \b ' ) ; break ;
case ' f ' : s . PutChar ( ' \f ' ) ; break ;
case ' n ' : s . PutChar ( ' \n ' ) ; break ;
case ' r ' : s . PutChar ( ' \r ' ) ; break ;
case ' t ' : s . PutChar ( ' \t ' ) ; break ;
case ' v ' : s . PutChar ( ' \v ' ) ; break ;
case ' \' ' : s . PutChar ( ' \' ' ) ; break ;
case ' \\ ' : s . PutChar ( ' \\ ' ) ; break ;
case ' 0 ' :
// 1 to 3 octal chars
{
2010-10-04 09:05:56 +08:00
// Make a string that can hold onto the initial zero char,
// up to 3 octal digits, and a terminating NULL.
char oct_str [ 5 ] = { 0 , 0 , 0 , 0 , 0 } ;
int i ;
for ( i = 0 ; ( p [ i ] > = ' 0 ' & & p [ i ] < = ' 7 ' ) & & i < 4 ; + + i )
oct_str [ i ] = p [ i ] ;
// We don't want to consume the last octal character since
// the main for loop will do this for us, so we advance p by
// one less than i (even if i is zero)
p + = i - 1 ;
unsigned long octal_value = : : strtoul ( oct_str , NULL , 8 ) ;
if ( octal_value < = UINT8_MAX )
2010-09-19 10:33:57 +08:00
{
2010-10-04 09:05:56 +08:00
char octal_char = octal_value ;
s . Write ( & octal_char , 1 ) ;
2010-09-19 10:33:57 +08:00
}
}
break ;
case ' x ' :
// hex number in the format
2010-10-04 09:05:56 +08:00
if ( isxdigit ( p [ 1 ] ) )
2010-09-19 10:33:57 +08:00
{
2010-10-04 09:05:56 +08:00
+ + p ; // Skip the 'x'
2010-09-19 10:33:57 +08:00
2010-10-04 09:05:56 +08:00
// Make a string that can hold onto two hex chars plus a
// NULL terminator
char hex_str [ 3 ] = { 0 , 0 , 0 } ;
hex_str [ 0 ] = * p ;
if ( isxdigit ( p [ 1 ] ) )
2010-09-19 10:33:57 +08:00
{
2010-10-04 09:05:56 +08:00
+ + p ; // Skip the first of the two hex chars
hex_str [ 1 ] = * p ;
2010-09-19 10:33:57 +08:00
}
2010-10-04 09:05:56 +08:00
unsigned long hex_value = strtoul ( hex_str , NULL , 16 ) ;
if ( hex_value < = UINT8_MAX )
s . PutChar ( hex_value ) ;
}
else
{
s . PutChar ( ' x ' ) ;
2010-09-19 10:33:57 +08:00
}
break ;
default :
2010-10-04 09:05:56 +08:00
// Just desensitize any other character by just printing what
// came after the '\'
s < < * p ;
2010-09-19 10:33:57 +08:00
break ;
}
}
}
if ( end )
* end = p ;
return success ;
}
# pragma mark Debugger::SettingsController
2010-09-04 08:03:46 +08:00
//--------------------------------------------------
2010-09-19 10:33:57 +08:00
// class Debugger::SettingsController
2010-09-04 08:03:46 +08:00
//--------------------------------------------------
2010-09-19 10:33:57 +08:00
Debugger : : SettingsController : : SettingsController ( ) :
2011-09-17 16:33:22 +08:00
UserSettingsController ( " " , UserSettingsControllerSP ( ) )
2010-09-04 08:03:46 +08:00
{
}
2010-09-19 10:33:57 +08:00
Debugger : : SettingsController : : ~ SettingsController ( )
2010-09-04 08:03:46 +08:00
{
}
2011-09-17 16:33:22 +08:00
InstanceSettingsSP
2010-09-19 10:33:57 +08:00
Debugger : : SettingsController : : CreateInstanceSettings ( const char * instance_name )
2010-09-04 08:03:46 +08:00
{
2012-01-30 15:41:31 +08:00
InstanceSettingsSP new_settings_sp ( new DebuggerInstanceSettings ( GetSettingsController ( ) ,
false ,
instance_name ) ) ;
2010-09-04 08:03:46 +08:00
return new_settings_sp ;
}
2010-09-19 10:33:57 +08:00
# pragma mark DebuggerInstanceSettings
2010-09-04 08:03:46 +08:00
//--------------------------------------------------
// class DebuggerInstanceSettings
//--------------------------------------------------
2010-09-18 09:14:36 +08:00
DebuggerInstanceSettings : : DebuggerInstanceSettings
(
2012-01-30 15:41:31 +08:00
const UserSettingsControllerSP & m_owner_sp ,
2010-09-18 09:14:36 +08:00
bool live_instance ,
const char * name
) :
2012-01-30 15:41:31 +08:00
InstanceSettings ( m_owner_sp , name ? name : InstanceSettings : : InvalidName ( ) . AsCString ( ) , live_instance ) ,
2010-09-18 09:14:36 +08:00
m_term_width ( 80 ) ,
2011-11-22 05:44:34 +08:00
m_stop_source_before_count ( 3 ) ,
m_stop_source_after_count ( 3 ) ,
m_stop_disassembly_count ( 4 ) ,
m_stop_disassembly_display ( eStopDisassemblyTypeNoSource ) ,
2010-09-04 08:03:46 +08:00
m_prompt ( ) ,
2010-10-04 09:05:56 +08:00
m_frame_format ( ) ,
m_thread_format ( ) ,
2010-09-21 04:44:43 +08:00
m_script_lang ( ) ,
2010-10-05 06:44:14 +08:00
m_use_external_editor ( false ) ,
m_auto_confirm_on ( false )
2010-09-04 08:03:46 +08:00
{
2010-09-10 02:26:37 +08:00
// CopyInstanceSettings is a pure virtual function in InstanceSettings; it therefore cannot be called
// until the vtables for DebuggerInstanceSettings are properly set up, i.e. AFTER all the initializers.
// For this reason it has to be called here, rather than in the initializer or in the parent constructor.
2010-09-17 03:05:55 +08:00
// The same is true of CreateInstanceName().
if ( GetInstanceName ( ) = = InstanceSettings : : InvalidName ( ) )
{
ChangeInstanceName ( std : : string ( CreateInstanceName ( ) . AsCString ( ) ) ) ;
2012-01-30 15:41:31 +08:00
m_owner_sp - > RegisterInstanceSettings ( this ) ;
2010-09-17 03:05:55 +08:00
}
2010-09-10 02:26:37 +08:00
if ( live_instance )
2010-09-04 08:03:46 +08:00
{
2012-01-30 15:41:31 +08:00
const InstanceSettingsSP & pending_settings = m_owner_sp - > FindPendingSettings ( m_instance_name ) ;
2010-09-04 08:03:46 +08:00
CopyInstanceSettings ( pending_settings , false ) ;
}
}
DebuggerInstanceSettings : : DebuggerInstanceSettings ( const DebuggerInstanceSettings & rhs ) :
2012-01-30 15:41:31 +08:00
InstanceSettings ( Debugger : : GetSettingsController ( ) , CreateInstanceName ( ) . AsCString ( ) ) ,
2010-09-04 08:03:46 +08:00
m_prompt ( rhs . m_prompt ) ,
2010-10-04 09:05:56 +08:00
m_frame_format ( rhs . m_frame_format ) ,
m_thread_format ( rhs . m_thread_format ) ,
2010-09-21 04:44:43 +08:00
m_script_lang ( rhs . m_script_lang ) ,
2010-10-05 06:44:14 +08:00
m_use_external_editor ( rhs . m_use_external_editor ) ,
m_auto_confirm_on ( rhs . m_auto_confirm_on )
2010-09-04 08:03:46 +08:00
{
2012-01-30 15:41:31 +08:00
UserSettingsControllerSP owner_sp ( m_owner_wp . lock ( ) ) ;
if ( owner_sp )
{
CopyInstanceSettings ( owner_sp - > FindPendingSettings ( m_instance_name ) , false ) ;
owner_sp - > RemovePendingSettings ( m_instance_name ) ;
}
2010-09-04 08:03:46 +08:00
}
DebuggerInstanceSettings : : ~ DebuggerInstanceSettings ( )
{
}
DebuggerInstanceSettings &
DebuggerInstanceSettings : : operator = ( const DebuggerInstanceSettings & rhs )
{
if ( this ! = & rhs )
{
2010-09-19 10:33:57 +08:00
m_term_width = rhs . m_term_width ;
2010-09-04 08:03:46 +08:00
m_prompt = rhs . m_prompt ;
2010-10-04 09:05:56 +08:00
m_frame_format = rhs . m_frame_format ;
m_thread_format = rhs . m_thread_format ;
2010-09-04 08:03:46 +08:00
m_script_lang = rhs . m_script_lang ;
2010-09-21 04:44:43 +08:00
m_use_external_editor = rhs . m_use_external_editor ;
2010-10-05 06:44:14 +08:00
m_auto_confirm_on = rhs . m_auto_confirm_on ;
2010-09-04 08:03:46 +08:00
}
return * this ;
}
2010-09-19 10:33:57 +08:00
bool
DebuggerInstanceSettings : : ValidTermWidthValue ( const char * value , Error err )
{
bool valid = false ;
// Verify we have a value string.
if ( value = = NULL | | value [ 0 ] = = ' \0 ' )
{
2011-10-26 08:56:27 +08:00
err . SetErrorString ( " missing value, can't set terminal width without a value " ) ;
2010-09-19 10:33:57 +08:00
}
else
{
char * end = NULL ;
const uint32_t width = : : strtoul ( value , & end , 0 ) ;
2010-09-21 00:36:43 +08:00
if ( end & & end [ 0 ] = = ' \0 ' )
2010-09-19 10:33:57 +08:00
{
2010-09-21 01:04:41 +08:00
if ( width > = 10 & & width < = 1024 )
2010-09-19 10:33:57 +08:00
valid = true ;
else
2011-10-26 08:56:27 +08:00
err . SetErrorString ( " invalid term-width value; value must be between 10 and 1024 " ) ;
2010-09-19 10:33:57 +08:00
}
else
2011-10-26 08:56:27 +08:00
err . SetErrorStringWithFormat ( " '%s' is not a valid unsigned integer string " , value ) ;
2010-09-19 10:33:57 +08:00
}
return valid ;
}
2010-09-04 08:03:46 +08:00
void
DebuggerInstanceSettings : : UpdateInstanceSettingsVariable ( const ConstString & var_name ,
const char * index_value ,
const char * value ,
const ConstString & instance_name ,
const SettingEntry & entry ,
2011-03-25 05:19:54 +08:00
VarSetOperationType op ,
2010-09-04 08:03:46 +08:00
Error & err ,
bool pending )
{
2010-10-04 09:05:56 +08:00
if ( var_name = = TermWidthVarName ( ) )
{
if ( ValidTermWidthValue ( value , err ) )
{
m_term_width = : : strtoul ( value , NULL , 0 ) ;
}
}
else if ( var_name = = PromptVarName ( ) )
2010-09-04 08:03:46 +08:00
{
2010-09-09 14:25:08 +08:00
UserSettingsController : : UpdateStringVariable ( op , m_prompt , value , err ) ;
2010-09-04 08:03:46 +08:00
if ( ! pending )
{
2010-09-08 02:35:40 +08:00
// 'instance_name' is actually (probably) in the form '[<instance_name>]'; if so, we need to
// strip off the brackets before passing it to BroadcastPromptChange.
std : : string tmp_instance_name ( instance_name . AsCString ( ) ) ;
if ( ( tmp_instance_name [ 0 ] = = ' [ ' )
& & ( tmp_instance_name [ instance_name . GetLength ( ) - 1 ] = = ' ] ' ) )
tmp_instance_name = tmp_instance_name . substr ( 1 , instance_name . GetLength ( ) - 2 ) ;
ConstString new_name ( tmp_instance_name . c_str ( ) ) ;
BroadcastPromptChange ( new_name , m_prompt . c_str ( ) ) ;
2010-09-04 08:03:46 +08:00
}
}
2010-10-04 09:05:56 +08:00
else if ( var_name = = GetFrameFormatName ( ) )
{
UserSettingsController : : UpdateStringVariable ( op , m_frame_format , value , err ) ;
}
else if ( var_name = = GetThreadFormatName ( ) )
{
UserSettingsController : : UpdateStringVariable ( op , m_thread_format , value , err ) ;
}
2010-09-04 08:03:46 +08:00
else if ( var_name = = ScriptLangVarName ( ) )
{
bool success ;
m_script_lang = Args : : StringToScriptLanguage ( value , eScriptLanguageDefault ,
& success ) ;
}
2010-09-21 04:44:43 +08:00
else if ( var_name = = UseExternalEditorVarName ( ) )
{
2011-04-22 11:55:06 +08:00
UserSettingsController : : UpdateBooleanVariable ( op , m_use_external_editor , value , false , err ) ;
2010-09-21 04:44:43 +08:00
}
2010-10-05 06:44:14 +08:00
else if ( var_name = = AutoConfirmName ( ) )
{
2011-04-22 11:55:06 +08:00
UserSettingsController : : UpdateBooleanVariable ( op , m_auto_confirm_on , value , false , err ) ;
2010-10-05 06:44:14 +08:00
}
2011-11-22 05:44:34 +08:00
else if ( var_name = = StopSourceContextBeforeName ( ) )
{
uint32_t new_value = Args : : StringToUInt32 ( value , UINT32_MAX , 10 , NULL ) ;
if ( new_value ! = UINT32_MAX )
m_stop_source_before_count = new_value ;
else
err . SetErrorStringWithFormat ( " invalid unsigned string value '%s' for the '%s' setting " , value , StopSourceContextAfterName ( ) . GetCString ( ) ) ;
}
else if ( var_name = = StopSourceContextAfterName ( ) )
{
uint32_t new_value = Args : : StringToUInt32 ( value , UINT32_MAX , 10 , NULL ) ;
if ( new_value ! = UINT32_MAX )
m_stop_source_after_count = new_value ;
else
err . SetErrorStringWithFormat ( " invalid unsigned string value '%s' for the '%s' setting " , value , StopSourceContextBeforeName ( ) . GetCString ( ) ) ;
}
else if ( var_name = = StopDisassemblyCountName ( ) )
{
uint32_t new_value = Args : : StringToUInt32 ( value , UINT32_MAX , 10 , NULL ) ;
if ( new_value ! = UINT32_MAX )
m_stop_disassembly_count = new_value ;
else
err . SetErrorStringWithFormat ( " invalid unsigned string value '%s' for the '%s' setting " , value , StopDisassemblyCountName ( ) . GetCString ( ) ) ;
}
else if ( var_name = = StopDisassemblyDisplayName ( ) )
{
int new_value ;
UserSettingsController : : UpdateEnumVariable ( g_show_disassembly_enum_values , & new_value , value , err ) ;
if ( err . Success ( ) )
m_stop_disassembly_display = ( StopDisassemblyType ) new_value ;
}
2010-09-04 08:03:46 +08:00
}
2010-09-21 05:37:42 +08:00
bool
2010-09-04 08:03:46 +08:00
DebuggerInstanceSettings : : GetInstanceSettingsValue ( const SettingEntry & entry ,
const ConstString & var_name ,
2010-09-21 04:44:43 +08:00
StringList & value ,
2010-09-21 05:37:42 +08:00
Error * err )
2010-09-04 08:03:46 +08:00
{
if ( var_name = = PromptVarName ( ) )
{
2010-10-04 09:05:56 +08:00
value . AppendString ( m_prompt . c_str ( ) , m_prompt . size ( ) ) ;
2010-09-04 08:03:46 +08:00
}
else if ( var_name = = ScriptLangVarName ( ) )
{
value . AppendString ( ScriptInterpreter : : LanguageToString ( m_script_lang ) . c_str ( ) ) ;
}
2010-09-09 14:25:08 +08:00
else if ( var_name = = TermWidthVarName ( ) )
{
StreamString width_str ;
2011-11-22 05:44:34 +08:00
width_str . Printf ( " %u " , m_term_width ) ;
2010-09-09 14:25:08 +08:00
value . AppendString ( width_str . GetData ( ) ) ;
}
2010-10-04 09:05:56 +08:00
else if ( var_name = = GetFrameFormatName ( ) )
{
value . AppendString ( m_frame_format . c_str ( ) , m_frame_format . size ( ) ) ;
}
else if ( var_name = = GetThreadFormatName ( ) )
{
value . AppendString ( m_thread_format . c_str ( ) , m_thread_format . size ( ) ) ;
}
2010-09-21 04:44:43 +08:00
else if ( var_name = = UseExternalEditorVarName ( ) )
{
if ( m_use_external_editor )
value . AppendString ( " true " ) ;
else
value . AppendString ( " false " ) ;
}
2010-10-05 06:44:14 +08:00
else if ( var_name = = AutoConfirmName ( ) )
{
if ( m_auto_confirm_on )
value . AppendString ( " true " ) ;
else
value . AppendString ( " false " ) ;
}
2011-11-22 05:44:34 +08:00
else if ( var_name = = StopSourceContextAfterName ( ) )
{
StreamString strm ;
strm . Printf ( " %u " , m_stop_source_before_count ) ;
value . AppendString ( strm . GetData ( ) ) ;
}
else if ( var_name = = StopSourceContextBeforeName ( ) )
{
StreamString strm ;
strm . Printf ( " %u " , m_stop_source_after_count ) ;
value . AppendString ( strm . GetData ( ) ) ;
}
else if ( var_name = = StopDisassemblyCountName ( ) )
{
StreamString strm ;
strm . Printf ( " %u " , m_stop_disassembly_count ) ;
value . AppendString ( strm . GetData ( ) ) ;
}
else if ( var_name = = StopDisassemblyDisplayName ( ) )
{
if ( m_stop_disassembly_display > = eStopDisassemblyTypeNever & & m_stop_disassembly_display < = eStopDisassemblyTypeAlways )
value . AppendString ( g_show_disassembly_enum_values [ m_stop_disassembly_display ] . string_value ) ;
else
value . AppendString ( " <invalid> " ) ;
}
2010-09-21 04:44:43 +08:00
else
2010-09-21 05:37:42 +08:00
{
if ( err )
err - > SetErrorStringWithFormat ( " unrecognized variable name '%s' " , var_name . AsCString ( ) ) ;
return false ;
}
return true ;
2010-09-04 08:03:46 +08:00
}
void
2011-09-17 16:33:22 +08:00
DebuggerInstanceSettings : : CopyInstanceSettings ( const InstanceSettingsSP & new_settings ,
2010-09-04 08:03:46 +08:00
bool pending )
{
if ( new_settings . get ( ) = = NULL )
return ;
DebuggerInstanceSettings * new_debugger_settings = ( DebuggerInstanceSettings * ) new_settings . get ( ) ;
m_prompt = new_debugger_settings - > m_prompt ;
if ( ! pending )
2010-09-08 02:35:40 +08:00
{
// 'instance_name' is actually (probably) in the form '[<instance_name>]'; if so, we need to
// strip off the brackets before passing it to BroadcastPromptChange.
std : : string tmp_instance_name ( m_instance_name . AsCString ( ) ) ;
if ( ( tmp_instance_name [ 0 ] = = ' [ ' )
& & ( tmp_instance_name [ m_instance_name . GetLength ( ) - 1 ] = = ' ] ' ) )
tmp_instance_name = tmp_instance_name . substr ( 1 , m_instance_name . GetLength ( ) - 2 ) ;
ConstString new_name ( tmp_instance_name . c_str ( ) ) ;
BroadcastPromptChange ( new_name , m_prompt . c_str ( ) ) ;
}
2010-10-04 09:05:56 +08:00
m_frame_format = new_debugger_settings - > m_frame_format ;
m_thread_format = new_debugger_settings - > m_thread_format ;
2010-09-21 04:44:43 +08:00
m_term_width = new_debugger_settings - > m_term_width ;
2010-09-04 08:03:46 +08:00
m_script_lang = new_debugger_settings - > m_script_lang ;
2010-09-21 04:44:43 +08:00
m_use_external_editor = new_debugger_settings - > m_use_external_editor ;
2010-10-05 06:44:14 +08:00
m_auto_confirm_on = new_debugger_settings - > m_auto_confirm_on ;
2010-09-04 08:03:46 +08:00
}
bool
DebuggerInstanceSettings : : BroadcastPromptChange ( const ConstString & instance_name , const char * new_prompt )
{
std : : string tmp_prompt ;
if ( new_prompt ! = NULL )
{
tmp_prompt = new_prompt ;
int len = tmp_prompt . size ( ) ;
if ( len > 1
& & ( tmp_prompt [ 0 ] = = ' \' ' | | tmp_prompt [ 0 ] = = ' " ' )
& & ( tmp_prompt [ len - 1 ] = = tmp_prompt [ 0 ] ) )
{
tmp_prompt = tmp_prompt . substr ( 1 , len - 2 ) ;
}
len = tmp_prompt . size ( ) ;
if ( tmp_prompt [ len - 1 ] ! = ' ' )
tmp_prompt . append ( " " ) ;
}
EventSP new_event_sp ;
new_event_sp . reset ( new Event ( CommandInterpreter : : eBroadcastBitResetPrompt ,
new EventDataBytes ( tmp_prompt . c_str ( ) ) ) ) ;
if ( instance_name . GetLength ( ) ! = 0 )
{
// Set prompt for a particular instance.
Debugger * dbg = Debugger : : FindDebuggerWithInstanceName ( instance_name ) . get ( ) ;
if ( dbg ! = NULL )
{
dbg - > GetCommandInterpreter ( ) . BroadcastEvent ( new_event_sp ) ;
}
}
return true ;
}
const ConstString
DebuggerInstanceSettings : : CreateInstanceName ( )
{
static int instance_count = 1 ;
StreamString sstr ;
sstr . Printf ( " debugger_%d " , instance_count ) ;
+ + instance_count ;
const ConstString ret_val ( sstr . GetData ( ) ) ;
return ret_val ;
}
2010-10-05 06:44:14 +08:00
2010-09-04 08:03:46 +08:00
//--------------------------------------------------
2010-09-19 10:33:57 +08:00
// SettingsController Variable Tables
2010-09-04 08:03:46 +08:00
//--------------------------------------------------
SettingEntry
2010-09-19 10:33:57 +08:00
Debugger : : SettingsController : : global_settings_table [ ] =
2010-09-04 08:03:46 +08:00
{
//{ "var-name", var-type, "default", enum-table, init'd, hidden, "help-text"},
2010-09-09 14:25:08 +08:00
// The Debugger level global table should always be empty; all Debugger settable variables should be instance
// variables.
2010-09-04 08:03:46 +08:00
{ NULL , eSetVarTypeNone , NULL , NULL , 0 , 0 , NULL }
} ;
2010-10-04 10:44:26 +08:00
# define MODULE_WITH_FUNC "{ ${module.file.basename}{`${function.name}${function.pc-offset}}}"
2010-10-04 09:05:56 +08:00
# define FILE_AND_LINE "{ at ${line.file.basename}:${line.number}}"
2010-09-04 08:03:46 +08:00
2010-10-04 09:05:56 +08:00
# define DEFAULT_THREAD_FORMAT "thread #${thread.index}: tid = ${thread.id}"\
" {, ${frame.pc}} " \
MODULE_WITH_FUNC \
2010-10-05 01:04:23 +08:00
FILE_AND_LINE \
2010-10-04 09:05:56 +08:00
" {, stop reason = ${thread.stop-reason}} " \
2011-12-23 03:12:40 +08:00
" { \\ nReturn value: ${thread.return-value}} " \
2010-10-04 09:05:56 +08:00
" \\ n "
2010-11-02 09:53:21 +08:00
/ / # define DEFAULT_THREAD_FORMAT " thread #${thread.index}: tid = ${thread.id} " \
/ / " {, ${frame.pc}} " \
/ / MODULE_WITH_FUNC \
/ / FILE_AND_LINE \
/ / " {, stop reason = ${thread.stop-reason}} " \
/ / " {, name = ${thread.name}} " \
/ / " {, queue = ${thread.queue}} " \
// "\\n"
2010-10-04 09:05:56 +08:00
# define DEFAULT_FRAME_FORMAT "frame #${frame.index}: ${frame.pc}"\
MODULE_WITH_FUNC \
FILE_AND_LINE \
" \\ n "
2010-09-04 08:03:46 +08:00
SettingEntry
2010-09-19 10:33:57 +08:00
Debugger : : SettingsController : : instance_settings_table [ ] =
2010-09-04 08:03:46 +08:00
{
2010-10-04 09:05:56 +08:00
// NAME Setting variable type Default Enum Init'd Hidden Help
// ======================= ======================= ====================== ==== ====== ====== ======================
{ " frame-format " , eSetVarTypeString , DEFAULT_FRAME_FORMAT , NULL , false , false , " The default frame format string to use when displaying thread information. " } ,
2010-10-23 05:15:00 +08:00
{ " prompt " , eSetVarTypeString , " (lldb) " , NULL , false , false , " The debugger command line prompt displayed for the user. " } ,
2010-10-05 06:44:14 +08:00
{ " script-lang " , eSetVarTypeString , " python " , NULL , false , false , " The script language to be used for evaluating user-written scripts. " } ,
{ " term-width " , eSetVarTypeInt , " 80 " , NULL , false , false , " The maximum number of columns to use for displaying text. " } ,
2010-10-04 09:05:56 +08:00
{ " thread-format " , eSetVarTypeString , DEFAULT_THREAD_FORMAT , NULL , false , false , " The default thread format string to use when displaying thread information. " } ,
2011-11-22 05:44:34 +08:00
{ " use-external-editor " , eSetVarTypeBoolean , " false " , NULL , false , false , " Whether to use an external editor or not. " } ,
{ " auto-confirm " , eSetVarTypeBoolean , " false " , NULL , false , false , " If true all confirmation prompts will receive their default reply. " } ,
{ " stop-line-count-before " , eSetVarTypeInt , " 3 " , NULL , false , false , " The number of sources lines to display that come before the current source line when displaying a stopped context. " } ,
{ " stop-line-count-after " , eSetVarTypeInt , " 3 " , NULL , false , false , " The number of sources lines to display that come after the current source line when displaying a stopped context. " } ,
{ " stop-disassembly-count " , eSetVarTypeInt , " 0 " , NULL , false , false , " The number of disassembly lines to show when displaying a stopped context. " } ,
{ " stop-disassembly-display " , eSetVarTypeEnum , " no-source " , g_show_disassembly_enum_values , false , false , " Control when to display disassembly when displaying a stopped context. " } ,
2010-10-04 09:05:56 +08:00
{ NULL , eSetVarTypeNone , NULL , NULL , false , false , NULL }
2010-09-04 08:03:46 +08:00
} ;