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.
//
//===----------------------------------------------------------------------===//
2012-12-05 08:20:57 +08:00
# include "lldb/lldb-python.h"
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"
2014-06-13 10:37:02 +08:00
# include "llvm/ADT/StringRef.h"
2011-06-30 06:27:15 +08:00
2010-06-09 00:52:24 +08:00
# include "lldb/lldb-private.h"
<rdar://problem/11757916>
Make breakpoint setting by file and line much more efficient by only looking for inlined breakpoint locations if we are setting a breakpoint in anything but a source implementation file. Implementing this complex for a many reasons. Turns out that parsing compile units lazily had some issues with respect to how we need to do things with DWARF in .o files. So the fixes in the checkin for this makes these changes:
- Add a new setting called "target.inline-breakpoint-strategy" which can be set to "never", "always", or "headers". "never" will never try and set any inlined breakpoints (fastest). "always" always looks for inlined breakpoint locations (slowest, but most accurate). "headers", which is the default setting, will only look for inlined breakpoint locations if the breakpoint is set in what are consudered to be header files, which is realy defined as "not in an implementation source file".
- modify the breakpoint setting by file and line to check the current "target.inline-breakpoint-strategy" setting and act accordingly
- Modify compile units to be able to get their language and other info lazily. This allows us to create compile units from the debug map and not have to fill all of the details in, and then lazily discover this information as we go on debuggging. This is needed to avoid parsing all .o files when setting breakpoints in implementation only files (no inlines). Otherwise we would need to parse the .o file, the object file (mach-o in our case) and the symbol file (DWARF in the object file) just to see what the compile unit was.
- modify the "SymbolFileDWARFDebugMap" to subclass lldb_private::Module so that the virtual "GetObjectFile()" and "GetSymbolVendor()" functions can be intercepted when the .o file contenst are later lazilly needed. Prior to this fix, when we first instantiated the "SymbolFileDWARFDebugMap" class, we would also make modules, object files and symbol files for every .o file in the debug map because we needed to fix up the sections in the .o files with information that is in the executable debug map. Now we lazily do this in the DebugMapModule::GetObjectFile()
Cleaned up header includes a bit as well.
llvm-svn: 162860
2012-08-30 05:13:06 +08:00
# include "lldb/Core/Module.h"
2012-10-20 02:02:49 +08:00
# include "lldb/Core/PluginManager.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"
2012-02-21 10:23:08 +08:00
# include "lldb/Core/StreamCallback.h"
2014-01-28 07:43:24 +08:00
# include "lldb/Core/StreamFile.h"
2010-09-19 10:33:57 +08:00
# include "lldb/Core/StreamString.h"
2014-06-13 10:37:02 +08:00
# include "lldb/Core/StructuredData.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"
2013-01-29 07:47:25 +08:00
# include "lldb/DataFormatters/DataVisualization.h"
# include "lldb/DataFormatters/FormatManager.h"
2014-03-26 06:03:52 +08:00
# include "lldb/DataFormatters/TypeSummary.h"
2014-10-07 05:22:36 +08:00
# include "lldb/Host/ConnectionFileDescriptor.h"
2014-08-22 01:29:12 +08:00
# include "lldb/Host/HostInfo.h"
2011-02-08 07:24:47 +08:00
# include "lldb/Host/Terminal.h"
2014-09-10 04:54:56 +08:00
# include "lldb/Host/ThreadLauncher.h"
2010-06-23 09:19:29 +08:00
# include "lldb/Interpreter/CommandInterpreter.h"
2012-08-23 01:17:09 +08:00
# include "lldb/Interpreter/OptionValueSInt64.h"
# include "lldb/Interpreter/OptionValueString.h"
<rdar://problem/11757916>
Make breakpoint setting by file and line much more efficient by only looking for inlined breakpoint locations if we are setting a breakpoint in anything but a source implementation file. Implementing this complex for a many reasons. Turns out that parsing compile units lazily had some issues with respect to how we need to do things with DWARF in .o files. So the fixes in the checkin for this makes these changes:
- Add a new setting called "target.inline-breakpoint-strategy" which can be set to "never", "always", or "headers". "never" will never try and set any inlined breakpoints (fastest). "always" always looks for inlined breakpoint locations (slowest, but most accurate). "headers", which is the default setting, will only look for inlined breakpoint locations if the breakpoint is set in what are consudered to be header files, which is realy defined as "not in an implementation source file".
- modify the breakpoint setting by file and line to check the current "target.inline-breakpoint-strategy" setting and act accordingly
- Modify compile units to be able to get their language and other info lazily. This allows us to create compile units from the debug map and not have to fill all of the details in, and then lazily discover this information as we go on debuggging. This is needed to avoid parsing all .o files when setting breakpoints in implementation only files (no inlines). Otherwise we would need to parse the .o file, the object file (mach-o in our case) and the symbol file (DWARF in the object file) just to see what the compile unit was.
- modify the "SymbolFileDWARFDebugMap" to subclass lldb_private::Module so that the virtual "GetObjectFile()" and "GetSymbolVendor()" functions can be intercepted when the .o file contenst are later lazilly needed. Prior to this fix, when we first instantiated the "SymbolFileDWARFDebugMap" class, we would also make modules, object files and symbol files for every .o file in the debug map because we needed to fix up the sections in the .o files with information that is in the executable debug map. Now we lazily do this in the DebugMapModule::GetObjectFile()
Cleaned up header includes a bit as well.
llvm-svn: 162860
2012-08-30 05:13:06 +08:00
# include "lldb/Symbol/ClangASTContext.h"
# include "lldb/Symbol/CompileUnit.h"
# include "lldb/Symbol/Function.h"
# include "lldb/Symbol/Symbol.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"
2014-10-11 07:07:36 +08:00
# include "lldb/Target/CPPLanguageRuntime.h"
# include "lldb/Target/ObjCLanguageRuntime.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"
2013-12-03 03:35:49 +08:00
# include "lldb/Target/SectionLoadList.h"
2010-09-19 10:33:57 +08:00
# include "lldb/Target/StopInfo.h"
2013-05-21 06:29:23 +08:00
# include "lldb/Target/Target.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
2014-08-28 04:15:09 +08:00
# include "llvm/Support/DynamicLibrary.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 ;
2014-10-25 06:06:29 +08:00
static size_t g_debugger_event_thread_stack_bytes = 8 * 1024 * 1024 ;
2010-07-01 00:22:25 +08:00
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
2014-06-27 10:42:12 +08:00
// global init constructors
2010-09-19 10:33:57 +08:00
static DebuggerList g_list ;
return g_list ;
}
2012-08-23 01:17:09 +08:00
OptionEnumValueElement
g_show_disassembly_enum_values [ ] =
{
{ Debugger : : eStopDisassemblyTypeNever , " never " , " Never show disassembly when displaying a stop context. " } ,
{ Debugger : : eStopDisassemblyTypeNoSource , " no-source " , " Show disassembly when there is no source information, or the source file is missing when displaying a stop context. " } ,
{ Debugger : : eStopDisassemblyTypeAlways , " always " , " Always show disassembly when displaying a stop context. " } ,
{ 0 , NULL , NULL }
} ;
OptionEnumValueElement
g_language_enumerators [ ] =
{
{ eScriptLanguageNone , " none " , " Disable scripting languages. " } ,
{ eScriptLanguagePython , " python " , " Select python as the default scripting language. " } ,
{ eScriptLanguageDefault , " default " , " Select the lldb default as the default scripting language. " } ,
2012-09-14 07:03:20 +08:00
{ 0 , NULL , NULL }
2012-08-23 01:17:09 +08:00
} ;
# define MODULE_WITH_FUNC "{ ${module.file.basename}{`${function.name-with-args}${function.pc-offset}}}"
# define FILE_AND_LINE "{ at ${line.file.basename}:${line.number}}"
2013-07-31 00:44:36 +08:00
# define DEFAULT_THREAD_FORMAT "thread #${thread.index}: tid = ${thread.id%tid}"\
2012-08-23 01:17:09 +08:00
" {, ${frame.pc}} " \
MODULE_WITH_FUNC \
FILE_AND_LINE \
2013-07-31 00:44:36 +08:00
" {, name = '${thread.name}'} " \
" {, queue = '${thread.queue}'} " \
2014-06-13 10:37:02 +08:00
" {, activity = '${thread.info.activity.name}'} " \
" {, ${thread.info.trace_messages} messages} " \
2012-08-23 01:17:09 +08:00
" {, stop reason = ${thread.stop-reason}} " \
" { \\ nReturn value: ${thread.return-value}} " \
2014-07-08 09:07:32 +08:00
" { \\ nCompleted expression: ${thread.completed-expression}} " \
2012-08-23 01:17:09 +08:00
" \\ n "
# define DEFAULT_FRAME_FORMAT "frame #${frame.index}: ${frame.pc}"\
MODULE_WITH_FUNC \
FILE_AND_LINE \
" \\ n "
2014-12-02 08:26:21 +08:00
# define DEFAULT_DISASSEMBLY_FORMAT "${current-pc-arrow}${addr-file-or-load}{ <${function.name-without-args}${function.concrete-only-addr-offset-no-padding}>}: "
2012-08-23 01:17:09 +08:00
2012-08-23 08:22:02 +08:00
static PropertyDefinition
g_properties [ ] =
2012-08-23 01:17:09 +08:00
{
{ " auto-confirm " , OptionValue : : eTypeBoolean , true , false , NULL , NULL , " If true all confirmation prompts will receive their default reply. " } ,
2014-10-11 07:07:36 +08:00
{ " disassembly-format " , OptionValue : : eTypeString , true , 0 , DEFAULT_DISASSEMBLY_FORMAT , NULL , " The default disassembly format string to use when disassembling instruction sequences. " } ,
2012-08-23 01:17:09 +08:00
{ " frame-format " , OptionValue : : eTypeString , true , 0 , DEFAULT_FRAME_FORMAT , NULL , " The default frame format string to use when displaying stack frame information for threads. " } ,
{ " notify-void " , OptionValue : : eTypeBoolean , true , false , NULL , NULL , " Notify the user explicitly if an expression returns void (default: false). " } ,
2012-09-01 08:38:36 +08:00
{ " prompt " , OptionValue : : eTypeString , true , OptionValueString : : eOptionEncodeCharacterEscapeSequences , " (lldb) " , NULL , " The debugger command line prompt displayed for the user. " } ,
2012-08-23 01:17:09 +08:00
{ " script-lang " , OptionValue : : eTypeEnum , true , eScriptLanguagePython , NULL , g_language_enumerators , " The script language to be used for evaluating user-written scripts. " } ,
{ " stop-disassembly-count " , OptionValue : : eTypeSInt64 , true , 4 , NULL , NULL , " The number of disassembly lines to show when displaying a stopped context. " } ,
{ " stop-disassembly-display " , OptionValue : : eTypeEnum , true , Debugger : : eStopDisassemblyTypeNoSource , NULL , g_show_disassembly_enum_values , " Control when to display disassembly when displaying a stopped context. " } ,
{ " stop-line-count-after " , OptionValue : : eTypeSInt64 , true , 3 , NULL , NULL , " The number of sources lines to display that come after the current source line when displaying a stopped context. " } ,
{ " stop-line-count-before " , OptionValue : : eTypeSInt64 , true , 3 , NULL , NULL , " The number of sources lines to display that come before the current source line when displaying a stopped context. " } ,
{ " term-width " , OptionValue : : eTypeSInt64 , true , 80 , NULL , NULL , " The maximum number of columns to use for displaying text. " } ,
{ " thread-format " , OptionValue : : eTypeString , true , 0 , DEFAULT_THREAD_FORMAT , NULL , " The default thread format string to use when displaying thread information. " } ,
{ " use-external-editor " , OptionValue : : eTypeBoolean , true , false , NULL , NULL , " Whether to use an external editor or not. " } ,
2013-05-24 04:47:45 +08:00
{ " use-color " , OptionValue : : eTypeBoolean , true , true , NULL , NULL , " Whether to use Ansi color codes or not. " } ,
2014-11-06 05:20:48 +08:00
{ " auto-one-line-summaries " , OptionValue : : eTypeBoolean , true , true , NULL , NULL , " If true, LLDB will automatically display small structs in one-liner format (default: true). " } ,
{ " escape-non-printables " , OptionValue : : eTypeBoolean , true , true , NULL , NULL , " If true, LLDB will automatically escape non-printable and escape characters when formatting strings. " } ,
2012-10-20 02:02:49 +08:00
{ NULL , OptionValue : : eTypeInvalid , true , 0 , NULL , NULL , NULL }
2012-08-23 01:17:09 +08:00
} ;
2010-09-19 10:33:57 +08:00
2012-08-23 01:17:09 +08:00
enum
{
ePropertyAutoConfirm = 0 ,
2014-10-11 07:07:36 +08:00
ePropertyDisassemblyFormat ,
2012-08-23 01:17:09 +08:00
ePropertyFrameFormat ,
ePropertyNotiftVoid ,
ePropertyPrompt ,
ePropertyScriptLanguage ,
ePropertyStopDisassemblyCount ,
ePropertyStopDisassemblyDisplay ,
ePropertyStopLineCountAfter ,
ePropertyStopLineCountBefore ,
ePropertyTerminalWidth ,
ePropertyThreadFormat ,
2013-05-24 04:47:45 +08:00
ePropertyUseExternalEditor ,
ePropertyUseColor ,
2014-11-06 05:20:48 +08:00
ePropertyAutoOneLineSummaries ,
ePropertyEscapeNonPrintables
2012-08-23 01:17:09 +08:00
} ;
2010-09-19 10:33:57 +08:00
2013-12-03 03:35:49 +08:00
Debugger : : LoadPluginCallbackType Debugger : : g_load_plugin_callback = NULL ;
2012-09-01 08:38:36 +08:00
Error
Debugger : : SetPropertyValue ( const ExecutionContext * exe_ctx ,
VarSetOperationType op ,
const char * property_path ,
const char * value )
{
2013-05-21 06:29:23 +08:00
bool is_load_script = strcmp ( property_path , " target.load-script-from-symbol-file " ) = = 0 ;
2014-11-06 05:20:48 +08:00
bool is_escape_non_printables = strcmp ( property_path , " escape-non-printables " ) = = 0 ;
2013-05-21 06:29:23 +08:00
TargetSP target_sp ;
2013-05-22 04:13:34 +08:00
LoadScriptFromSymFile load_script_old_value ;
2013-05-21 06:29:23 +08:00
if ( is_load_script & & exe_ctx - > GetTargetSP ( ) )
{
target_sp = exe_ctx - > GetTargetSP ( ) ;
load_script_old_value = target_sp - > TargetProperties : : GetLoadScriptFromSymbolFile ( ) ;
}
2012-09-01 08:38:36 +08:00
Error error ( Properties : : SetPropertyValue ( exe_ctx , op , property_path , value ) ) ;
if ( error . Success ( ) )
{
2013-05-21 06:29:23 +08:00
// FIXME it would be nice to have "on-change" callbacks for properties
2012-09-01 08:38:36 +08:00
if ( strcmp ( property_path , g_properties [ ePropertyPrompt ] . name ) = = 0 )
{
const char * new_prompt = GetPrompt ( ) ;
2013-05-24 04:47:45 +08:00
std : : string str = lldb_utility : : ansi : : FormatAnsiTerminalCodes ( new_prompt , GetUseColor ( ) ) ;
if ( str . length ( ) )
new_prompt = str . c_str ( ) ;
2014-01-28 07:43:24 +08:00
GetCommandInterpreter ( ) . UpdatePrompt ( new_prompt ) ;
2012-09-01 08:38:36 +08:00
EventSP prompt_change_event_sp ( new Event ( CommandInterpreter : : eBroadcastBitResetPrompt , new EventDataBytes ( new_prompt ) ) ) ;
GetCommandInterpreter ( ) . BroadcastEvent ( prompt_change_event_sp ) ;
}
2013-05-24 04:47:45 +08:00
else if ( strcmp ( property_path , g_properties [ ePropertyUseColor ] . name ) = = 0 )
{
// use-color changed. Ping the prompt so it can reset the ansi terminal codes.
SetPrompt ( GetPrompt ( ) ) ;
}
2013-05-22 04:13:34 +08:00
else if ( is_load_script & & target_sp & & load_script_old_value = = eLoadScriptFromSymFileWarn )
2013-05-21 06:29:23 +08:00
{
2013-05-22 04:13:34 +08:00
if ( target_sp - > TargetProperties : : GetLoadScriptFromSymbolFile ( ) = = eLoadScriptFromSymFileTrue )
2013-05-21 06:29:23 +08:00
{
std : : list < Error > errors ;
2013-05-21 08:00:30 +08:00
StreamString feedback_stream ;
if ( ! target_sp - > LoadScriptingResources ( errors , & feedback_stream ) )
2013-05-21 06:29:23 +08:00
{
2014-01-28 07:43:24 +08:00
StreamFileSP stream_sp ( GetErrorFile ( ) ) ;
if ( stream_sp )
2013-05-21 06:29:23 +08:00
{
2014-01-28 07:43:24 +08:00
for ( auto error : errors )
{
stream_sp - > Printf ( " %s \n " , error . AsCString ( ) ) ;
}
if ( feedback_stream . GetSize ( ) )
stream_sp - > Printf ( " %s " , feedback_stream . GetData ( ) ) ;
2013-05-21 06:29:23 +08:00
}
}
}
}
2014-11-06 05:20:48 +08:00
else if ( is_escape_non_printables )
{
DataVisualization : : ForceUpdate ( ) ;
}
2012-09-01 08:38:36 +08:00
}
return error ;
}
2012-08-23 01:17:09 +08:00
bool
Debugger : : GetAutoConfirm ( ) const
2011-11-22 05:44:34 +08:00
{
2012-08-23 01:17:09 +08:00
const uint32_t idx = ePropertyAutoConfirm ;
2012-08-23 08:22:02 +08:00
return m_collection_sp - > GetPropertyAtIndexAsBoolean ( NULL , idx , g_properties [ idx ] . default_uint_value ! = 0 ) ;
2011-11-22 05:44:34 +08:00
}
2014-10-11 07:07:36 +08:00
const char *
Debugger : : GetDisassemblyFormat ( ) const
{
const uint32_t idx = ePropertyDisassemblyFormat ;
return m_collection_sp - > GetPropertyAtIndexAsString ( NULL , idx , g_properties [ idx ] . default_cstr_value ) ;
}
2012-08-23 01:17:09 +08:00
const char *
Debugger : : GetFrameFormat ( ) const
2012-08-10 02:18:47 +08:00
{
2012-08-23 01:17:09 +08:00
const uint32_t idx = ePropertyFrameFormat ;
2012-08-23 08:22:02 +08:00
return m_collection_sp - > GetPropertyAtIndexAsString ( NULL , idx , g_properties [ idx ] . default_cstr_value ) ;
2012-08-10 02:18:47 +08:00
}
2012-08-23 01:17:09 +08:00
bool
Debugger : : GetNotifyVoid ( ) const
2011-11-22 05:44:34 +08:00
{
2012-08-23 01:17:09 +08:00
const uint32_t idx = ePropertyNotiftVoid ;
2012-08-23 08:22:02 +08:00
return m_collection_sp - > GetPropertyAtIndexAsBoolean ( NULL , idx , g_properties [ idx ] . default_uint_value ! = 0 ) ;
2011-11-22 05:44:34 +08:00
}
2012-08-23 01:17:09 +08:00
const char *
Debugger : : GetPrompt ( ) const
2011-11-22 05:44:34 +08:00
{
2012-08-23 01:17:09 +08:00
const uint32_t idx = ePropertyPrompt ;
2012-08-23 08:22:02 +08:00
return m_collection_sp - > GetPropertyAtIndexAsString ( NULL , idx , g_properties [ idx ] . default_cstr_value ) ;
2011-11-22 05:44:34 +08:00
}
2012-08-23 01:17:09 +08:00
void
Debugger : : SetPrompt ( const char * p )
2011-11-22 05:44:34 +08:00
{
2012-08-23 01:17:09 +08:00
const uint32_t idx = ePropertyPrompt ;
m_collection_sp - > SetPropertyAtIndexAsString ( NULL , idx , p ) ;
const char * new_prompt = GetPrompt ( ) ;
2013-05-24 04:47:45 +08:00
std : : string str = lldb_utility : : ansi : : FormatAnsiTerminalCodes ( new_prompt , GetUseColor ( ) ) ;
if ( str . length ( ) )
new_prompt = str . c_str ( ) ;
2014-01-28 07:43:24 +08:00
GetCommandInterpreter ( ) . UpdatePrompt ( new_prompt ) ;
2011-11-22 05:44:34 +08:00
}
2012-08-23 01:17:09 +08:00
const char *
Debugger : : GetThreadFormat ( ) const
2011-11-22 05:44:34 +08:00
{
2012-08-23 01:17:09 +08:00
const uint32_t idx = ePropertyThreadFormat ;
2012-08-23 08:22:02 +08:00
return m_collection_sp - > GetPropertyAtIndexAsString ( NULL , idx , g_properties [ idx ] . default_cstr_value ) ;
2011-11-22 05:44:34 +08:00
}
2012-08-23 01:17:09 +08:00
lldb : : ScriptLanguage
Debugger : : GetScriptLanguage ( ) const
2011-11-22 05:44:34 +08:00
{
2012-08-23 01:17:09 +08:00
const uint32_t idx = ePropertyScriptLanguage ;
2012-08-23 08:22:02 +08:00
return ( lldb : : ScriptLanguage ) m_collection_sp - > GetPropertyAtIndexAsEnumeration ( NULL , idx , g_properties [ idx ] . default_uint_value ) ;
2011-11-22 05:44:34 +08:00
}
2012-08-23 01:17:09 +08:00
bool
Debugger : : SetScriptLanguage ( lldb : : ScriptLanguage script_lang )
2011-11-22 05:44:34 +08:00
{
2012-08-23 01:17:09 +08:00
const uint32_t idx = ePropertyScriptLanguage ;
return m_collection_sp - > SetPropertyAtIndexAsEnumeration ( NULL , idx , script_lang ) ;
2011-11-22 05:44:34 +08:00
}
2012-08-23 01:17:09 +08:00
uint32_t
Debugger : : GetTerminalWidth ( ) const
2011-11-22 05:44:34 +08:00
{
2012-08-23 01:17:09 +08:00
const uint32_t idx = ePropertyTerminalWidth ;
2012-08-23 08:22:02 +08:00
return m_collection_sp - > GetPropertyAtIndexAsSInt64 ( NULL , idx , g_properties [ idx ] . default_uint_value ) ;
2011-11-22 05:44:34 +08:00
}
2012-08-23 01:17:09 +08:00
bool
Debugger : : SetTerminalWidth ( uint32_t term_width )
2011-11-22 05:44:34 +08:00
{
2012-08-23 01:17:09 +08:00
const uint32_t idx = ePropertyTerminalWidth ;
return m_collection_sp - > SetPropertyAtIndexAsSInt64 ( NULL , idx , term_width ) ;
2011-11-22 05:44:34 +08:00
}
2012-08-23 01:17:09 +08:00
bool
Debugger : : GetUseExternalEditor ( ) const
2011-11-22 05:44:34 +08:00
{
2012-08-23 01:17:09 +08:00
const uint32_t idx = ePropertyUseExternalEditor ;
2012-08-23 08:22:02 +08:00
return m_collection_sp - > GetPropertyAtIndexAsBoolean ( NULL , idx , g_properties [ idx ] . default_uint_value ! = 0 ) ;
2011-11-22 05:44:34 +08:00
}
2012-08-23 01:17:09 +08:00
bool
Debugger : : SetUseExternalEditor ( bool b )
2011-11-22 05:44:34 +08:00
{
2012-08-23 01:17:09 +08:00
const uint32_t idx = ePropertyUseExternalEditor ;
return m_collection_sp - > SetPropertyAtIndexAsBoolean ( NULL , idx , b ) ;
2011-11-22 05:44:34 +08:00
}
2013-05-24 04:47:45 +08:00
bool
Debugger : : GetUseColor ( ) const
{
const uint32_t idx = ePropertyUseColor ;
return m_collection_sp - > GetPropertyAtIndexAsBoolean ( NULL , idx , g_properties [ idx ] . default_uint_value ! = 0 ) ;
}
bool
Debugger : : SetUseColor ( bool b )
{
const uint32_t idx = ePropertyUseColor ;
bool ret = m_collection_sp - > SetPropertyAtIndexAsBoolean ( NULL , idx , b ) ;
SetPrompt ( GetPrompt ( ) ) ;
return ret ;
}
2012-08-23 01:17:09 +08:00
uint32_t
Debugger : : GetStopSourceLineCount ( bool before ) const
2011-11-22 05:44:34 +08:00
{
2012-08-23 01:17:09 +08:00
const uint32_t idx = before ? ePropertyStopLineCountBefore : ePropertyStopLineCountAfter ;
2012-08-23 08:22:02 +08:00
return m_collection_sp - > GetPropertyAtIndexAsSInt64 ( NULL , idx , g_properties [ idx ] . default_uint_value ) ;
2012-08-23 01:17:09 +08:00
}
2011-11-22 05:44:34 +08:00
2012-08-23 01:17:09 +08:00
Debugger : : StopDisassemblyType
Debugger : : GetStopDisassemblyDisplay ( ) const
{
const uint32_t idx = ePropertyStopDisassemblyDisplay ;
2012-08-23 08:22:02 +08:00
return ( Debugger : : StopDisassemblyType ) m_collection_sp - > GetPropertyAtIndexAsEnumeration ( NULL , idx , g_properties [ idx ] . default_uint_value ) ;
2012-08-23 01:17:09 +08:00
}
2011-11-22 05:44:34 +08:00
2012-08-23 01:17:09 +08:00
uint32_t
Debugger : : GetDisassemblyLineCount ( ) const
{
const uint32_t idx = ePropertyStopDisassemblyCount ;
2012-08-23 08:22:02 +08:00
return m_collection_sp - > GetPropertyAtIndexAsSInt64 ( NULL , idx , g_properties [ idx ] . default_uint_value ) ;
2012-08-23 01:17:09 +08:00
}
2011-11-22 05:44:34 +08:00
2013-10-26 07:09:40 +08:00
bool
2013-11-01 05:01:07 +08:00
Debugger : : GetAutoOneLineSummaries ( ) const
2013-10-26 07:09:40 +08:00
{
2013-11-01 05:01:07 +08:00
const uint32_t idx = ePropertyAutoOneLineSummaries ;
2013-10-26 07:09:40 +08:00
return m_collection_sp - > GetPropertyAtIndexAsBoolean ( NULL , idx , true ) ;
2014-11-06 05:20:48 +08:00
}
2013-10-26 07:09:40 +08:00
2014-11-06 05:20:48 +08:00
bool
Debugger : : GetEscapeNonPrintables ( ) const
{
const uint32_t idx = ePropertyEscapeNonPrintables ;
return m_collection_sp - > GetPropertyAtIndexAsBoolean ( NULL , idx , true ) ;
2013-10-26 07:09:40 +08:00
}
2010-09-19 10:33:57 +08:00
# pragma mark Debugger
2012-08-23 01:17:09 +08:00
//const DebuggerPropertiesSP &
//Debugger::GetSettings() const
//{
// return m_properties_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
2013-12-03 03:35:49 +08:00
Debugger : : Initialize ( LoadPluginCallbackType load_plugin_callback )
2010-06-09 00:52:24 +08:00
{
2013-12-03 03:35:49 +08:00
g_load_plugin_callback = load_plugin_callback ;
2012-03-31 04:53:46 +08:00
if ( g_shared_debugger_refcount + + = = 0 )
2010-11-19 11:46:01 +08:00
lldb_private : : Initialize ( ) ;
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 ( )
{
2012-08-23 02:39:03 +08:00
Target : : SettingsInitialize ( ) ;
2011-03-11 06:14:10 +08:00
}
void
Debugger : : SettingsTerminate ( )
{
2012-08-23 02:39:03 +08:00
Target : : SettingsTerminate ( ) ;
2011-03-11 06:14:10 +08:00
}
2012-09-29 07:57:51 +08:00
bool
2013-04-25 05:29:08 +08:00
Debugger : : LoadPlugin ( const FileSpec & spec , Error & error )
2012-09-29 07:57:51 +08:00
{
2013-12-03 03:35:49 +08:00
if ( g_load_plugin_callback )
2013-04-25 05:29:08 +08:00
{
2014-08-28 04:15:09 +08:00
llvm : : sys : : DynamicLibrary dynlib = g_load_plugin_callback ( shared_from_this ( ) , spec , error ) ;
if ( dynlib . isValid ( ) )
2013-12-03 03:35:49 +08:00
{
2014-08-28 04:15:09 +08:00
m_loaded_plugins . push_back ( dynlib ) ;
2013-12-03 03:35:49 +08:00
return true ;
}
2013-04-25 05:29:08 +08:00
}
2013-12-03 03:35:49 +08:00
else
2012-09-29 07:57:51 +08:00
{
2013-12-03 03:35:49 +08:00
// The g_load_plugin_callback is registered in SBDebugger::Initialize()
// and if the public API layer isn't available (code is linking against
// all of the internal LLDB static libraries), then we can't load plugins
error . SetErrorString ( " Public API layer is not available " ) ;
2012-09-29 07:57:51 +08:00
}
return false ;
}
static FileSpec : : EnumerateDirectoryResult
LoadPluginCallback
(
void * baton ,
FileSpec : : FileType file_type ,
const FileSpec & file_spec
)
{
Error error ;
static ConstString g_dylibext ( " dylib " ) ;
2013-07-17 08:26:30 +08:00
static ConstString g_solibext ( " so " ) ;
2012-09-29 07:57:51 +08:00
if ( ! baton )
return FileSpec : : eEnumerateDirectoryResultQuit ;
Debugger * debugger = ( Debugger * ) baton ;
// If we have a regular file, a symbolic link or unknown file type, try
// and process the file. We must handle unknown as sometimes the directory
// enumeration might be enumerating a file system that doesn't have correct
// file type information.
if ( file_type = = FileSpec : : eFileTypeRegular | |
file_type = = FileSpec : : eFileTypeSymbolicLink | |
file_type = = FileSpec : : eFileTypeUnknown )
{
FileSpec plugin_file_spec ( file_spec ) ;
plugin_file_spec . ResolvePath ( ) ;
2013-07-17 08:26:30 +08:00
if ( plugin_file_spec . GetFileNameExtension ( ) ! = g_dylibext & &
plugin_file_spec . GetFileNameExtension ( ) ! = g_solibext )
{
2012-09-29 07:57:51 +08:00
return FileSpec : : eEnumerateDirectoryResultNext ;
2013-07-17 08:26:30 +08:00
}
2012-09-29 07:57:51 +08:00
2013-04-25 05:29:08 +08:00
Error plugin_load_error ;
debugger - > LoadPlugin ( plugin_file_spec , plugin_load_error ) ;
2012-09-29 07:57:51 +08:00
return FileSpec : : eEnumerateDirectoryResultNext ;
}
else if ( file_type = = FileSpec : : eFileTypeUnknown | |
file_type = = FileSpec : : eFileTypeDirectory | |
file_type = = FileSpec : : eFileTypeSymbolicLink )
{
// Try and recurse into anything that a directory or symbolic link.
// We must also do this for unknown as sometimes the directory enumeration
2014-06-27 10:42:12 +08:00
// might be enumerating a file system that doesn't have correct file type
2012-09-29 07:57:51 +08:00
// information.
return FileSpec : : eEnumerateDirectoryResultEnter ;
}
return FileSpec : : eEnumerateDirectoryResultNext ;
}
void
Debugger : : InstanceInitialize ( )
{
FileSpec dir_spec ;
const bool find_directories = true ;
const bool find_files = true ;
const bool find_other = true ;
char dir_path [ PATH_MAX ] ;
2014-08-22 01:29:12 +08:00
if ( HostInfo : : GetLLDBPath ( ePathTypeLLDBSystemPlugins , dir_spec ) )
2012-09-29 07:57:51 +08:00
{
if ( dir_spec . Exists ( ) & & dir_spec . GetPath ( dir_path , sizeof ( dir_path ) ) )
{
FileSpec : : EnumerateDirectory ( dir_path ,
find_directories ,
find_files ,
find_other ,
LoadPluginCallback ,
this ) ;
}
}
2014-08-22 01:29:12 +08:00
if ( HostInfo : : GetLLDBPath ( ePathTypeLLDBUserPlugins , dir_spec ) )
2012-09-29 07:57:51 +08:00
{
if ( dir_spec . Exists ( ) & & dir_spec . GetPath ( dir_path , sizeof ( dir_path ) ) )
{
FileSpec : : EnumerateDirectory ( dir_path ,
find_directories ,
find_files ,
find_other ,
LoadPluginCallback ,
this ) ;
}
}
2012-10-20 02:02:49 +08:00
PluginManager : : DebuggerInitialize ( * this ) ;
2012-09-29 07:57:51 +08:00
}
2010-06-23 09:19:29 +08:00
DebuggerSP
2012-02-21 10:23:08 +08:00
Debugger : : CreateInstance ( lldb : : LogOutputCallback log_callback , void * baton )
2010-06-23 09:19:29 +08:00
{
2012-02-21 10:23:08 +08:00
DebuggerSP debugger_sp ( new Debugger ( log_callback , baton ) ) ;
2012-03-31 04:53:46 +08:00
if ( g_shared_debugger_refcount > 0 )
2010-06-23 09:19:29 +08:00
{
Mutex : : Locker locker ( GetDebuggerListMutex ( ) ) ;
GetDebuggerList ( ) . push_back ( debugger_sp ) ;
}
2012-09-29 07:57:51 +08:00
debugger_sp - > InstanceInitialize ( ) ;
2010-06-23 09:19:29 +08:00
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 ( ) ;
2012-03-31 04:53:46 +08:00
if ( g_shared_debugger_refcount > 0 )
2011-01-22 09:02:07 +08:00
{
2012-03-31 04:53: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 )
2011-01-22 09:02:07 +08:00
{
2012-03-31 04:53:46 +08:00
if ( ( * pos ) . get ( ) = = debugger_sp . get ( ) )
{
debugger_list . erase ( pos ) ;
return ;
}
2011-01-22 09:02:07 +08:00
}
}
}
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 ;
2012-08-23 02:39:03 +08:00
if ( g_shared_debugger_refcount > 0 )
{
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 ;
}
}
}
2010-09-04 08:03:46 +08:00
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 ;
2012-03-31 04:53:46 +08:00
if ( g_shared_debugger_refcount > 0 )
2010-06-23 09:19:29 +08:00
{
2012-03-31 04:53: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 )
{
target_sp = ( * pos ) - > GetTargetList ( ) . FindTargetWithProcessID ( pid ) ;
if ( target_sp )
break ;
}
2010-06-23 09:19:29 +08:00
}
return target_sp ;
}
2011-11-16 13:37:56 +08:00
TargetSP
Debugger : : FindTargetWithProcess ( Process * process )
{
TargetSP target_sp ;
2012-03-31 04:53:46 +08:00
if ( g_shared_debugger_refcount > 0 )
2011-11-16 13:37:56 +08:00
{
2012-03-31 04:53: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 )
{
target_sp = ( * pos ) - > GetTargetList ( ) . FindTargetWithProcess ( process ) ;
if ( target_sp )
break ;
}
2011-11-16 13:37:56 +08:00
}
return target_sp ;
}
2014-09-12 09:50:46 +08:00
Debugger : : Debugger ( lldb : : LogOutputCallback log_callback , void * baton ) :
UserID ( g_unique_id + + ) ,
Properties ( OptionValuePropertiesSP ( new OptionValueProperties ( ) ) ) ,
m_input_file_sp ( new StreamFile ( stdin , false ) ) ,
m_output_file_sp ( new StreamFile ( stdout , false ) ) ,
m_error_file_sp ( new StreamFile ( stderr , false ) ) ,
m_terminal_state ( ) ,
m_target_list ( * this ) ,
m_platform_list ( ) ,
m_listener ( " lldb.Debugger " ) ,
m_source_manager_ap ( ) ,
m_source_file_cache ( ) ,
m_command_interpreter_ap ( new CommandInterpreter ( * this , eScriptLanguageDefault , false ) ) ,
m_input_reader_stack ( ) ,
m_instance_name ( ) ,
2014-12-02 06:41:27 +08:00
m_loaded_plugins ( ) ,
m_event_handler_thread ( ) ,
m_io_handler_thread ( ) ,
m_sync_broadcaster ( NULL , " lldb.debugger.sync " )
2010-06-09 00:52:24 +08:00
{
2012-08-23 01:17:09 +08:00
char instance_cstr [ 256 ] ;
snprintf ( instance_cstr , sizeof ( instance_cstr ) , " debugger_%d " , ( int ) GetID ( ) ) ;
m_instance_name . SetCString ( instance_cstr ) ;
2012-02-21 10:23:08 +08:00
if ( log_callback )
m_log_callback_stream_sp . reset ( new StreamCallback ( log_callback , baton ) ) ;
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
2014-09-20 04:11:50 +08:00
PlatformSP default_platform_sp ( Platform : : GetHostPlatform ( ) ) ;
2011-03-19 09:12:21 +08:00
assert ( default_platform_sp . get ( ) ) ;
m_platform_list . Append ( default_platform_sp , true ) ;
2012-08-23 01:17:09 +08:00
2012-08-23 08:22:02 +08:00
m_collection_sp - > Initialize ( g_properties ) ;
2012-08-23 01:17:09 +08:00
m_collection_sp - > AppendProperty ( ConstString ( " target " ) ,
ConstString ( " Settings specify to debugging targets. " ) ,
true ,
Target : : GetGlobalProperties ( ) - > GetValueProperties ( ) ) ;
2012-08-23 08:22:02 +08:00
if ( m_command_interpreter_ap . get ( ) )
{
m_collection_sp - > AppendProperty ( ConstString ( " interpreter " ) ,
ConstString ( " Settings specify to the debugger's command interpreter. " ) ,
true ,
m_command_interpreter_ap - > GetValueProperties ( ) ) ;
}
2012-08-23 01:17:09 +08:00
OptionValueSInt64 * term_width = m_collection_sp - > GetPropertyAtIndexAsOptionValueSInt64 ( NULL , ePropertyTerminalWidth ) ;
term_width - > SetMinimumValue ( 10 ) ;
term_width - > SetMaximumValue ( 1024 ) ;
2013-05-24 04:47:45 +08:00
// Turn off use-color if this is a dumb terminal.
const char * term = getenv ( " TERM " ) ;
if ( term & & ! strcmp ( term , " dumb " ) )
SetUseColor ( false ) ;
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
{
2014-01-28 07:43:24 +08:00
ClearIOHandlers ( ) ;
StopIOHandlerThread ( ) ;
StopEventHandlerThread ( ) ;
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 )
2013-02-28 03:13:05 +08:00
process_sp - > Finalize ( ) ;
2012-01-15 01:04:19 +08:00
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 ( ) ;
2012-05-16 08:11:54 +08:00
// Close the input file _before_ we close the input read communications class
// as it does NOT own the input file, our m_input_file does.
2012-12-01 04:23:19 +08:00
m_terminal_state . Clear ( ) ;
2014-01-28 07:43:24 +08:00
if ( m_input_file_sp )
m_input_file_sp - > GetFile ( ) . Close ( ) ;
2014-04-25 08:35:14 +08:00
m_command_interpreter_ap - > Clear ( ) ;
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
{
2014-01-28 07:43:24 +08:00
// return m_input_comm.GetCloseOnEOF();
return false ;
2011-05-29 12:06:55 +08:00
}
void
Debugger : : SetCloseInputOnEOF ( bool b )
{
2014-01-28 07:43:24 +08:00
// m_input_comm.SetCloseOnEOF(b);
2011-05-29 12:06:55 +08:00
}
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 )
{
2014-01-28 07:43:24 +08:00
if ( m_input_file_sp )
m_input_file_sp - > GetFile ( ) . SetStream ( fh , tranfer_ownership ) ;
else
m_input_file_sp . reset ( new StreamFile ( fh , tranfer_ownership ) ) ;
File & in_file = m_input_file_sp - > GetFile ( ) ;
2011-02-09 09:08:52 +08:00
if ( in_file . IsValid ( ) = = false )
in_file . SetStream ( stdin , true ) ;
2010-06-09 00:52:24 +08:00
2012-12-01 04:23:19 +08:00
// Save away the terminal state if that is relevant, so that we can restore it in RestoreInputState.
SaveInputTerminalState ( ) ;
2010-06-09 00:52:24 +08:00
}
void
Debugger : : SetOutputFileHandle ( FILE * fh , bool tranfer_ownership )
{
2014-01-28 07:43:24 +08:00
if ( m_output_file_sp )
m_output_file_sp - > GetFile ( ) . SetStream ( fh , tranfer_ownership ) ;
else
m_output_file_sp . reset ( new StreamFile ( fh , tranfer_ownership ) ) ;
File & out_file = m_output_file_sp - > GetFile ( ) ;
2011-02-09 09:08:52 +08:00
if ( out_file . IsValid ( ) = = false )
out_file . SetStream ( stdout , false ) ;
2011-01-14 08:29:16 +08:00
2012-10-30 05:18:03 +08:00
// do not create the ScriptInterpreter just for setting the output file handle
// as the constructor will know how to do the right thing on its own
const bool can_create = false ;
ScriptInterpreter * script_interpreter = GetCommandInterpreter ( ) . GetScriptInterpreter ( can_create ) ;
if ( script_interpreter )
script_interpreter - > ResetOutputFileHandle ( fh ) ;
2010-06-09 00:52:24 +08:00
}
void
Debugger : : SetErrorFileHandle ( FILE * fh , bool tranfer_ownership )
{
2014-01-28 07:43:24 +08:00
if ( m_error_file_sp )
m_error_file_sp - > GetFile ( ) . SetStream ( fh , tranfer_ownership ) ;
else
m_error_file_sp . reset ( new StreamFile ( fh , tranfer_ownership ) ) ;
File & err_file = m_error_file_sp - > GetFile ( ) ;
2011-02-09 09:08:52 +08:00
if ( err_file . IsValid ( ) = = false )
err_file . SetStream ( stderr , false ) ;
2010-06-09 00:52:24 +08:00
}
2012-12-01 04:23:19 +08:00
void
Debugger : : SaveInputTerminalState ( )
{
2014-01-28 07:43:24 +08:00
if ( m_input_file_sp )
{
File & in_file = m_input_file_sp - > GetFile ( ) ;
if ( in_file . GetDescriptor ( ) ! = File : : kInvalidDescriptor )
m_terminal_state . Save ( in_file . GetDescriptor ( ) , true ) ;
}
2012-12-01 04:23:19 +08:00
}
void
Debugger : : RestoreInputTerminalState ( )
{
m_terminal_state . Restore ( ) ;
}
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 ;
}
2010-11-20 04:47:54 +08:00
void
Debugger : : DispatchInputInterrupt ( )
{
2014-01-28 07:43:24 +08:00
Mutex : : Locker locker ( m_input_reader_stack . GetMutex ( ) ) ;
IOHandlerSP reader_sp ( m_input_reader_stack . Top ( ) ) ;
2011-02-10 09:15:13 +08:00
if ( reader_sp )
2014-01-28 07:43:24 +08:00
reader_sp - > Interrupt ( ) ;
2010-11-20 04:47:54 +08:00
}
void
Debugger : : DispatchInputEndOfFile ( )
{
2014-01-28 07:43:24 +08:00
Mutex : : Locker locker ( m_input_reader_stack . GetMutex ( ) ) ;
IOHandlerSP reader_sp ( m_input_reader_stack . Top ( ) ) ;
2011-02-10 09:15:13 +08:00
if ( reader_sp )
2014-01-28 07:43:24 +08:00
reader_sp - > GotEOF ( ) ;
2010-11-20 04:47:54 +08:00
}
2010-12-21 02:35:50 +08:00
void
2014-01-28 07:43:24 +08:00
Debugger : : ClearIOHandlers ( )
2010-12-21 02:35:50 +08:00
{
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.
2014-01-28 07:43:24 +08:00
Mutex : : Locker locker ( m_input_reader_stack . GetMutex ( ) ) ;
2011-06-03 03:18:55 +08:00
while ( m_input_reader_stack . GetSize ( ) > 1 )
2010-12-21 02:35:50 +08:00
{
2014-01-28 07:43:24 +08:00
IOHandlerSP reader_sp ( m_input_reader_stack . Top ( ) ) ;
2010-12-21 02:35:50 +08:00
if ( reader_sp )
{
2014-01-28 07:43:24 +08:00
m_input_reader_stack . Pop ( ) ;
reader_sp - > SetIsDone ( true ) ;
2014-02-25 06:50:57 +08:00
reader_sp - > Cancel ( ) ;
2010-12-21 02:35:50 +08:00
}
}
}
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
2014-01-28 07:43:24 +08:00
Debugger : : ExecuteIOHanders ( )
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
{
2014-01-28 07:43:24 +08:00
while ( 1 )
{
IOHandlerSP reader_sp ( m_input_reader_stack . Top ( ) ) ;
if ( ! reader_sp )
break ;
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
2014-01-28 07:43:24 +08:00
reader_sp - > Activate ( ) ;
reader_sp - > Run ( ) ;
reader_sp - > Deactivate ( ) ;
// Remove all input readers that are done from the top of the stack
while ( 1 )
{
IOHandlerSP top_reader_sp = m_input_reader_stack . Top ( ) ;
if ( top_reader_sp & & top_reader_sp - > GetIsDone ( ) )
m_input_reader_stack . Pop ( ) ;
else
break ;
}
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
}
2014-01-28 07:43:24 +08:00
ClearIOHandlers ( ) ;
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
}
2011-05-10 07:06:58 +08:00
bool
2014-01-28 07:43:24 +08:00
Debugger : : IsTopIOHandler ( const lldb : : IOHandlerSP & reader_sp )
2011-05-10 07:06:58 +08:00
{
2014-01-28 07:43:24 +08:00
return m_input_reader_stack . IsTop ( reader_sp ) ;
}
2011-05-10 07:06:58 +08:00
2014-01-28 07:43:24 +08:00
ConstString
Debugger : : GetTopIOHandlerControlSequence ( char ch )
{
return m_input_reader_stack . GetTopIOHandlerControlSequence ( ch ) ;
2011-05-10 07:06:58 +08:00
}
2010-06-09 00:52:24 +08:00
void
2014-01-28 07:43:24 +08:00
Debugger : : RunIOHandler ( const IOHandlerSP & reader_sp )
2010-06-09 00:52:24 +08:00
{
2014-01-28 07:43:24 +08:00
PushIOHandler ( reader_sp ) ;
2014-06-20 08:23:57 +08:00
IOHandlerSP top_reader_sp = reader_sp ;
while ( top_reader_sp )
{
top_reader_sp - > Activate ( ) ;
top_reader_sp - > Run ( ) ;
top_reader_sp - > Deactivate ( ) ;
if ( top_reader_sp . get ( ) = = reader_sp . get ( ) )
{
if ( PopIOHandler ( reader_sp ) )
break ;
}
while ( 1 )
{
top_reader_sp = m_input_reader_stack . Top ( ) ;
if ( top_reader_sp & & top_reader_sp - > GetIsDone ( ) )
m_input_reader_stack . Pop ( ) ;
else
break ;
}
}
2014-01-28 07:43:24 +08:00
}
2010-06-09 00:52:24 +08:00
2014-01-28 07:43:24 +08:00
void
Debugger : : AdoptTopIOHandlerFilesIfInvalid ( StreamFileSP & in , StreamFileSP & out , StreamFileSP & err )
{
// Before an IOHandler runs, it must have in/out/err streams.
// This function is called when one ore more of the streams
// are NULL. We use the top input reader's in/out/err streams,
// or fall back to the debugger file handles, or we fall back
// onto stdin/stdout/stderr as a last resort.
Mutex : : Locker locker ( m_input_reader_stack . GetMutex ( ) ) ;
IOHandlerSP top_reader_sp ( m_input_reader_stack . Top ( ) ) ;
// If no STDIN has been set, then set it appropriately
if ( ! in )
2010-06-09 00:52:24 +08:00
{
2014-01-28 07:43:24 +08:00
if ( top_reader_sp )
in = top_reader_sp - > GetInputStreamFile ( ) ;
2010-06-09 00:52:24 +08:00
else
2014-01-28 07:43:24 +08:00
in = GetInputFile ( ) ;
// If there is nothing, use stdin
if ( ! in )
in = StreamFileSP ( new StreamFile ( stdin , false ) ) ;
}
// If no STDOUT has been set, then set it appropriately
if ( ! out )
{
if ( top_reader_sp )
out = top_reader_sp - > GetOutputStreamFile ( ) ;
else
out = GetOutputFile ( ) ;
// If there is nothing, use stdout
if ( ! out )
out = StreamFileSP ( new StreamFile ( stdout , false ) ) ;
}
// If no STDERR has been set, then set it appropriately
if ( ! err )
{
if ( top_reader_sp )
err = top_reader_sp - > GetErrorStreamFile ( ) ;
else
err = GetErrorFile ( ) ;
// If there is nothing, use stderr
if ( ! err )
err = StreamFileSP ( new StreamFile ( stdout , false ) ) ;
2010-06-09 00:52:24 +08:00
}
}
void
2014-01-28 07:43:24 +08:00
Debugger : : PushIOHandler ( const IOHandlerSP & reader_sp )
2010-06-09 00:52:24 +08:00
{
if ( ! reader_sp )
return ;
2011-02-10 09:15:13 +08:00
2014-01-28 07:43:24 +08:00
// Got the current top input reader...
IOHandlerSP top_reader_sp ( m_input_reader_stack . Top ( ) ) ;
2011-02-10 09:15:13 +08:00
2014-03-01 02:22:24 +08:00
// Don't push the same IO handler twice...
if ( reader_sp . get ( ) ! = top_reader_sp . get ( ) )
{
// Push our new input reader
m_input_reader_stack . Push ( reader_sp ) ;
2014-01-28 07:43:24 +08:00
2014-03-01 02:22:24 +08:00
// Interrupt the top input reader to it will exit its Run() function
// and let this new input reader take over
if ( top_reader_sp )
top_reader_sp - > Deactivate ( ) ;
}
2010-06-09 00:52:24 +08:00
}
bool
2014-01-28 07:43:24 +08:00
Debugger : : PopIOHandler ( const IOHandlerSP & pop_reader_sp )
2010-06-09 00:52:24 +08:00
{
bool result = false ;
2014-01-28 07:43:24 +08:00
Mutex : : Locker locker ( m_input_reader_stack . GetMutex ( ) ) ;
2010-06-09 00:52:24 +08:00
// The reader on the stop of the stack is done, so let the next
2014-06-27 10:42:12 +08:00
// read on the stack refresh 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
{
2014-01-28 07:43:24 +08:00
IOHandlerSP 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 ( ) )
{
2014-01-28 07:43:24 +08:00
reader_sp - > Deactivate ( ) ;
2014-03-01 02:22:24 +08:00
reader_sp - > Cancel ( ) ;
2011-06-03 03:18:55 +08:00
m_input_reader_stack . Pop ( ) ;
2014-01-28 07:43:24 +08:00
reader_sp = m_input_reader_stack . Top ( ) ;
if ( reader_sp )
reader_sp - > Activate ( ) ;
2010-06-09 00:52:24 +08:00
2014-01-28 07:43:24 +08:00
result = true ;
2010-06-09 00:52:24 +08:00
}
}
return result ;
}
bool
2014-01-28 07:43:24 +08:00
Debugger : : HideTopIOHandler ( )
2010-06-09 00:52:24 +08:00
{
2014-01-28 07:43:24 +08:00
Mutex : : Locker locker ;
if ( locker . TryLock ( m_input_reader_stack . GetMutex ( ) ) )
2010-06-09 00:52:24 +08:00
{
2014-01-28 07:43:24 +08:00
IOHandlerSP reader_sp ( m_input_reader_stack . Top ( ) ) ;
if ( reader_sp )
reader_sp - > Hide ( ) ;
return true ;
2010-06-09 00:52:24 +08:00
}
2014-01-28 07:43:24 +08:00
return false ;
2010-06-09 00:52:24 +08:00
}
void
2014-01-28 07:43:24 +08:00
Debugger : : RefreshTopIOHandler ( )
2010-06-09 00:52:24 +08:00
{
2014-01-28 07:43:24 +08:00
IOHandlerSP reader_sp ( m_input_reader_stack . Top ( ) ) ;
if ( reader_sp )
reader_sp - > Refresh ( ) ;
2010-06-09 00:52:24 +08:00
}
2010-06-23 09:19:29 +08:00
2014-01-28 07:43:24 +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 ) ) ;
}
2013-01-26 02:06:21 +08:00
size_t
2012-02-15 10:34:21 +08:00
Debugger : : GetNumDebuggers ( )
{
2012-03-31 04:53:46 +08:00
if ( g_shared_debugger_refcount > 0 )
{
Mutex : : Locker locker ( GetDebuggerListMutex ( ) ) ;
return GetDebuggerList ( ) . size ( ) ;
}
return 0 ;
2012-02-15 10:34:21 +08:00
}
lldb : : DebuggerSP
2013-01-26 02:06:21 +08:00
Debugger : : GetDebuggerAtIndex ( size_t index )
2012-02-15 10:34:21 +08:00
{
DebuggerSP debugger_sp ;
2012-03-31 04:53:46 +08:00
if ( g_shared_debugger_refcount > 0 )
{
Mutex : : Locker locker ( GetDebuggerListMutex ( ) ) ;
DebuggerList & debugger_list = GetDebuggerList ( ) ;
2012-02-15 10:34:21 +08:00
2012-03-31 04:53:46 +08:00
if ( index < debugger_list . size ( ) )
debugger_sp = debugger_list [ index ] ;
}
2012-02-15 10:34:21 +08:00
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
2012-03-31 04:53:46 +08:00
if ( g_shared_debugger_refcount > 0 )
2010-07-01 00:22:25 +08:00
{
2012-03-31 04:53: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 )
2010-07-01 00:22:25 +08:00
{
2012-03-31 04:53:46 +08:00
if ( ( * pos ) . get ( ) - > GetID ( ) = = id )
{
debugger_sp = * pos ;
break ;
}
2010-07-01 00:22:25 +08:00
}
}
return debugger_sp ;
}
2010-09-04 08:03:46 +08:00
2014-03-20 14:08:21 +08:00
#if 0
2010-09-19 10:33:57 +08:00
static void
2013-11-04 17:33:30 +08:00
TestPromptFormats ( StackFrame * frame )
2010-09-19 10:33:57 +08:00
{
if ( frame = = NULL )
return ;
StreamString s ;
const char * prompt_format =
" {addr = '${addr}' \n } "
2014-10-11 07:07:36 +08:00
" {addr-file-or-load = '${addr-file-or-load}' \n } "
" {current-pc-arrow = '${current-pc-arrow}' \n } "
2010-09-19 10:33:57 +08:00
" {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 } "
2014-10-11 07:07:36 +08:00
" {function.changed = '${function.changed}' \n } "
" {function.initial-function = '${function.initial-function}' \n } "
2010-09-19 10:33:57 +08:00
" {function.name = '${function.name}' \n } "
2014-10-11 07:07:36 +08:00
" {function.name-without-args = '${function.name-without-args}' \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 } "
2014-10-11 07:07:36 +08:00
" {function.concrete-only-addr-offset-no-padding = '${function.concrete-only-addr-offset-no-padding}' \n } "
2010-09-19 10:33:57 +08:00
" {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 ) ;
2013-05-24 04:47:45 +08:00
if ( Debugger : : FormatPrompt ( prompt_format , & sc , & exe_ctx , & sc . line_entry . range . GetBaseAddress ( ) , s ) )
2010-09-19 10:33:57 +08:00
{
printf ( " %s \n " , s . GetData ( ) ) ;
}
else
{
printf ( " what we got: %s \n " , s . GetData ( ) ) ;
}
}
2014-03-20 14:08:21 +08:00
# endif
2010-09-19 10:33:57 +08:00
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
{
2013-03-28 07:08:40 +08:00
Log * 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 )
2012-10-18 06:23:56 +08:00
log - > Printf ( " [ScanFormatDescriptor] 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 ;
2013-05-07 01:18:22 +08:00
std : : string format_name ( * var_name_final + 1 , var_name_end - * var_name_final - 1 ) ;
2011-07-23 01:03:19 +08:00
if ( log )
2013-06-19 02:23:07 +08:00
log - > Printf ( " [ScanFormatDescriptor] parsing %s as a format descriptor " , format_name . c_str ( ) ) ;
2013-05-07 01:18:22 +08:00
if ( ! FormatManager : : GetFormatFromCString ( format_name . c_str ( ) ,
2011-07-06 10:13:41 +08:00
true ,
* custom_format ) )
{
2011-07-23 01:03:19 +08:00
if ( log )
2013-06-19 02:23:07 +08:00
log - > Printf ( " [ScanFormatDescriptor] %s is an unknown format " , format_name . c_str ( ) ) ;
2013-05-07 01:18:22 +08:00
switch ( format_name . front ( ) )
{
case ' @ ' : // if this is an @ sign, print ObjC description
* val_obj_display = ValueObject : : eValueObjectRepresentationStyleLanguageSpecific ;
break ;
case ' V ' : // if this is a V, print the value using the default format
* val_obj_display = ValueObject : : eValueObjectRepresentationStyleValue ;
break ;
case ' L ' : // if this is an L, print the location of the value
* val_obj_display = ValueObject : : eValueObjectRepresentationStyleLocation ;
break ;
case ' S ' : // if this is an S, print the summary after all
* val_obj_display = ValueObject : : eValueObjectRepresentationStyleSummary ;
break ;
case ' # ' : // if this is a '#', print the number of children
* val_obj_display = ValueObject : : eValueObjectRepresentationStyleChildrenCount ;
break ;
case ' T ' : // if this is a 'T', print the type
* val_obj_display = ValueObject : : eValueObjectRepresentationStyleType ;
break ;
2013-06-21 08:04:51 +08:00
case ' N ' : // if this is a 'N', print the name
* val_obj_display = ValueObject : : eValueObjectRepresentationStyleName ;
break ;
case ' > ' : // if this is a '>', print the name
* val_obj_display = ValueObject : : eValueObjectRepresentationStyleExpressionPath ;
break ;
2013-05-07 01:18:22 +08:00
default :
2013-05-16 02:27:08 +08:00
if ( log )
log - > Printf ( " ScanFormatDescriptor] %s is an error, leaving the previous value alone " , format_name . c_str ( ) ) ;
2013-05-07 01:18:22 +08:00
break ;
}
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 )
2013-06-19 02:23:07 +08:00
log - > Printf ( " [ScanFormatDescriptor] will display value for this VO " ) ;
2012-03-20 06:58:49 +08:00
* val_obj_display = ValueObject : : eValueObjectRepresentationStyleValue ;
2011-07-23 01:03:19 +08:00
}
2011-07-06 10:13:41 +08:00
}
2011-07-23 01:03:19 +08:00
if ( log )
2013-06-19 02:23:07 +08:00
log - > Printf ( " [ScanFormatDescriptor] final format description outcome: custom_format = %d, val_obj_display = %d " ,
2011-07-23 01:03:19 +08:00
* 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
{
2013-03-28 07:08:40 +08:00
Log * 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 )
2012-10-18 06:23:56 +08:00
log - > Printf ( " [ScanBracketedRange] '[]' 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 )
2012-11-30 05:49:15 +08:00
log - > Printf ( " [ScanBracketedRange] [% " PRId64 " ] 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 )
2012-11-30 05:49:15 +08:00
log - > Printf ( " [ScanBracketedRange] [% " PRId64 " -% " PRId64 " ] detected " , * index_lower , * index_higher ) ;
2011-07-06 10:13:41 +08:00
}
else
2011-07-23 01:03:19 +08:00
{
if ( log )
2012-10-18 06:23:56 +08:00
log - > Printf ( " [ScanBracketedRange] 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 )
2012-10-18 06:23:56 +08:00
log - > Printf ( " [ScanBracketedRange] swapping indices " ) ;
2013-01-26 02:06:21 +08:00
int64_t temp = * index_lower ;
2011-07-06 10:13:41 +08:00
* index_lower = * index_higher ;
* index_higher = temp ;
}
}
2011-07-23 01:03:19 +08:00
else if ( log )
2012-10-18 06:23:56 +08:00
log - > Printf ( " [ScanBracketedRange] no bracketed range, skipping entirely " ) ;
2011-07-06 10:13:41 +08:00
return true ;
}
2013-07-31 00:44:36 +08:00
template < typename T >
static bool RunScriptFormatKeyword ( Stream & s , ScriptInterpreter * script_interpreter , T t , const std : : string & script_name )
{
if ( script_interpreter )
{
Error script_error ;
std : : string script_output ;
if ( script_interpreter - > RunScriptFormatKeyword ( script_name . c_str ( ) , t , script_output , script_error ) & & script_error . Success ( ) )
{
s . Printf ( " %s " , script_output . c_str ( ) ) ;
return true ;
}
else
{
s . Printf ( " <error: %s> " , script_error . AsCString ( ) ) ;
}
}
return false ;
}
2011-07-06 10:13:41 +08:00
static ValueObjectSP
2011-08-23 08:32:52 +08:00
ExpandIndexedExpression ( ValueObject * valobj ,
2013-01-26 02:06:21 +08:00
size_t index ,
2013-11-04 17:33:30 +08:00
StackFrame * frame ,
2011-08-23 08:32:52 +08:00
bool deref_pointer )
2011-07-06 10:13:41 +08:00
{
2013-03-28 07:08:40 +08:00
Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_TYPES ) ) ;
2011-07-08 10:51:01 +08:00
const char * ptr_deref_format = " [%d] " ;
2013-02-02 07:59:44 +08:00
std : : string ptr_deref_buffer ( 10 , 0 ) ;
: : sprintf ( & ptr_deref_buffer [ 0 ] , ptr_deref_format , index ) ;
2011-07-23 01:03:19 +08:00
if ( log )
2013-02-02 07:59:44 +08:00
log - > Printf ( " [ExpandIndexedExpression] name to deref: %s " , ptr_deref_buffer . c_str ( ) ) ;
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 ;
2012-03-20 06:58:49 +08:00
ValueObject : : ExpressionPathAftermath what_next = ( deref_pointer ? ValueObject : : eExpressionPathAftermathDereference : ValueObject : : eExpressionPathAftermathNothing ) ;
2013-02-02 07:59:44 +08:00
ValueObjectSP item = valobj - > GetValueForExpressionPath ( ptr_deref_buffer . c_str ( ) ,
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 )
2012-10-18 06:23:56 +08:00
log - > Printf ( " [ExpandIndexedExpression] ERROR: unparsed portion = %s, why stopping = %d, "
2011-07-23 01:03:19 +08:00
" 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 )
2012-10-18 06:23:56 +08:00
log - > Printf ( " [ExpandIndexedExpression] ALL RIGHT: unparsed portion = %s, why stopping = %d, "
2011-07-23 01:03:19 +08:00
" 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 ;
}
2013-07-31 00:44:36 +08:00
static inline bool
IsToken ( const char * var_name_begin , const char * var )
{
return ( : : strncmp ( var_name_begin , var , strlen ( var ) ) = = 0 ) ;
}
static bool
IsTokenWithFormat ( const char * var_name_begin , const char * var , std : : string & format , const char * default_format ,
const ExecutionContext * exe_ctx_ptr , const SymbolContext * sc_ptr )
{
int var_len = strlen ( var ) ;
if ( : : strncmp ( var_name_begin , var , var_len ) = = 0 )
{
var_name_begin + = var_len ;
if ( * var_name_begin = = ' } ' )
{
format = default_format ;
return true ;
}
else if ( * var_name_begin = = ' % ' )
{
// Allow format specifiers: x|X|u with optional width specifiers.
// ${thread.id%x} ; hex
// ${thread.id%X} ; uppercase hex
// ${thread.id%u} ; unsigned decimal
// ${thread.id%8.8X} ; width.precision + specifier
// ${thread.id%tid} ; unsigned on FreeBSD/Linux, otherwise default_format (0x%4.4x for thread.id)
int dot_count = 0 ;
const char * specifier = NULL ;
int width_precision_length = 0 ;
const char * width_precision = + + var_name_begin ;
while ( isdigit ( * var_name_begin ) | | * var_name_begin = = ' . ' )
{
dot_count + = ( * var_name_begin = = ' . ' ) ;
if ( dot_count > 1 )
break ;
var_name_begin + + ;
width_precision_length + + ;
}
if ( IsToken ( var_name_begin , " tid} " ) )
{
Target * target = Target : : GetTargetFromContexts ( exe_ctx_ptr , sc_ptr ) ;
if ( target )
{
ArchSpec arch ( target - > GetArchitecture ( ) ) ;
llvm : : Triple : : OSType ostype = arch . IsValid ( ) ? arch . GetTriple ( ) . getOS ( ) : llvm : : Triple : : UnknownOS ;
if ( ( ostype = = llvm : : Triple : : FreeBSD ) | | ( ostype = = llvm : : Triple : : Linux ) )
specifier = PRIu64 ;
}
if ( ! specifier )
{
format = default_format ;
return true ;
}
}
else if ( IsToken ( var_name_begin , " x} " ) )
specifier = PRIx64 ;
else if ( IsToken ( var_name_begin , " X} " ) )
specifier = PRIX64 ;
else if ( IsToken ( var_name_begin , " u} " ) )
specifier = PRIu64 ;
if ( specifier )
{
format = " % " ;
if ( width_precision_length )
format + = std : : string ( width_precision , width_precision_length ) ;
format + = specifier ;
return true ;
}
}
}
return false ;
}
2014-06-13 10:37:02 +08:00
// Find information for the "thread.info.*" specifiers in a format string
static bool
FormatThreadExtendedInfoRecurse
(
const char * var_name_begin ,
StructuredData : : ObjectSP thread_info_dictionary ,
const SymbolContext * sc ,
const ExecutionContext * exe_ctx ,
Stream & s
)
{
bool var_success = false ;
std : : string token_format ;
llvm : : StringRef var_name ( var_name_begin ) ;
size_t percent_idx = var_name . find ( ' % ' ) ;
size_t close_curly_idx = var_name . find ( ' } ' ) ;
llvm : : StringRef path = var_name ;
llvm : : StringRef formatter = var_name ;
// 'path' will be the dot separated list of objects to transverse up until we hit
// a close curly brace, a percent sign, or an end of string.
if ( percent_idx ! = llvm : : StringRef : : npos | | close_curly_idx ! = llvm : : StringRef : : npos )
{
if ( percent_idx ! = llvm : : StringRef : : npos & & close_curly_idx ! = llvm : : StringRef : : npos )
{
if ( percent_idx < close_curly_idx )
{
path = var_name . slice ( 0 , percent_idx ) ;
formatter = var_name . substr ( percent_idx ) ;
}
else
{
path = var_name . slice ( 0 , close_curly_idx ) ;
formatter = var_name . substr ( close_curly_idx ) ;
}
}
else if ( percent_idx ! = llvm : : StringRef : : npos )
{
path = var_name . slice ( 0 , percent_idx ) ;
formatter = var_name . substr ( percent_idx ) ;
}
else if ( close_curly_idx ! = llvm : : StringRef : : npos )
{
path = var_name . slice ( 0 , close_curly_idx ) ;
formatter = var_name . substr ( close_curly_idx ) ;
}
}
StructuredData : : ObjectSP value = thread_info_dictionary - > GetObjectForDotSeparatedPath ( path ) ;
if ( value . get ( ) )
{
if ( value - > GetType ( ) = = StructuredData : : Type : : eTypeInteger )
{
if ( IsTokenWithFormat ( formatter . str ( ) . c_str ( ) , " " , token_format , " 0x%4.4 " PRIx64 , exe_ctx , sc ) )
{
s . Printf ( token_format . c_str ( ) , value - > GetAsInteger ( ) - > GetValue ( ) ) ;
var_success = true ;
}
}
else if ( value - > GetType ( ) = = StructuredData : : Type : : eTypeFloat )
{
s . Printf ( " %f " , value - > GetAsFloat ( ) - > GetValue ( ) ) ;
var_success = true ;
}
else if ( value - > GetType ( ) = = StructuredData : : Type : : eTypeString )
{
s . Printf ( " %s " , value - > GetAsString ( ) - > GetValue ( ) . c_str ( ) ) ;
var_success = true ;
}
else if ( value - > GetType ( ) = = StructuredData : : Type : : eTypeArray )
{
if ( value - > GetAsArray ( ) - > GetSize ( ) > 0 )
{
s . Printf ( " %zu " , value - > GetAsArray ( ) - > GetSize ( ) ) ;
var_success = true ;
}
}
else if ( value - > GetType ( ) = = StructuredData : : Type : : eTypeDictionary )
{
s . Printf ( " %zu " , value - > GetAsDictionary ( ) - > GetKeys ( ) - > GetAsArray ( ) - > GetSize ( ) ) ;
var_success = true ;
}
}
return var_success ;
}
2013-05-24 04:47:45 +08:00
static bool
FormatPromptRecurse
2010-09-19 10:33:57 +08:00
(
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 ,
2014-10-11 07:07:36 +08:00
ValueObject * valobj ,
bool function_changed ,
bool initial_function
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 ;
2013-03-28 07:08:40 +08:00
Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_TYPES ) ) ;
2013-05-24 04:47:45 +08:00
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 '{'
2013-05-24 04:47:45 +08:00
2014-10-11 07:07:36 +08:00
if ( FormatPromptRecurse ( p , sc , exe_ctx , addr , sub_strm , & p , valobj , function_changed , initial_function ) )
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 ;
2013-07-31 00:44:36 +08:00
std : : string token_format ;
2010-09-19 10:33:57 +08:00
Address format_addr ;
2014-10-11 07:07:36 +08:00
// normally "addr" means print a raw address but
// "file-addr-or-load-addr" means print a module + file addr if there's no load addr
bool print_file_addr_or_load_addr = false ;
bool addr_offset_concrete_func_only = false ;
bool addr_offset_print_with_no_padding = false ;
2010-09-19 10:33:57 +08:00
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 ;
2012-03-20 06:58:49 +08:00
ValueObject : : ExpressionPathScanEndReason reason_to_stop = ValueObject : : eExpressionPathScanEndReasonEndOfString ;
ValueObject : : ExpressionPathEndResultType final_value_type = ValueObject : : eExpressionPathEndResultTypePlain ;
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 )
2012-10-18 06:23:56 +08:00
log - > Printf ( " [Debugger::FormatPrompt] initial string: %s " , var_name_begin ) ;
2011-08-03 01:27:39 +08:00
2011-07-30 03:53:35 +08:00
// check for *var and *svar
if ( * var_name_begin = = ' * ' )
{
do_deref_pointer = true ;
var_name_begin + + ;
2013-06-19 02:23:07 +08:00
if ( log )
log - > Printf ( " [Debugger::FormatPrompt] found a deref, new string is: %s " , var_name_begin ) ;
2011-07-30 03:53:35 +08:00
}
2011-08-03 01:27:39 +08:00
2011-07-30 03:53:35 +08:00
if ( * var_name_begin = = ' s ' )
{
2012-03-27 10:35:13 +08:00
if ( ! valobj - > IsSynthetic ( ) )
valobj = valobj - > GetSyntheticValue ( ) . get ( ) ;
2012-03-20 06:58:49 +08:00
if ( ! valobj )
break ;
2011-07-30 03:53:35 +08:00
var_name_begin + + ;
2013-06-19 02:23:07 +08:00
if ( log )
log - > Printf ( " [Debugger::FormatPrompt] found a synthetic, new string is: %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 )
2013-06-19 02:23:07 +08:00
log - > Printf ( " [Debugger::FormatPrompt] string I am working with: %s " , var_name_begin ) ;
2011-08-03 01:27:39 +08:00
2011-07-08 10:51:01 +08:00
ValueObject : : ExpressionPathAftermath what_next = ( do_deref_pointer ?
2012-03-20 06:58:49 +08:00
ValueObject : : eExpressionPathAftermathDereference : ValueObject : : eExpressionPathAftermathNothing ) ;
2011-07-08 10:51:01 +08:00
ValueObject : : GetValueForExpressionPathOptions options ;
2011-08-12 01:08:01 +08:00
options . DontCheckDotVsArrowSyntax ( ) . DoAllowBitfieldSyntax ( ) . DoAllowFragileIVar ( ) . DoAllowSyntheticChildren ( ) ;
2012-03-20 06:58:49 +08:00
ValueObject : : ValueObjectRepresentationStyle val_obj_display = ValueObject : : eValueObjectRepresentationStyleSummary ;
2011-07-06 12:07:21 +08:00
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 ;
2012-05-09 05:49:57 +08:00
bool was_var_indexed = 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
2013-07-31 00:44:36 +08:00
if ( IsToken ( var_name_begin , " var} " ) )
2011-07-06 12:07:21 +08:00
{
2011-08-19 00:38:26 +08:00
was_plain_var = true ;
2011-08-18 06:13:59 +08:00
target = valobj ;
2012-03-20 06:58:49 +08:00
val_obj_display = ValueObject : : eValueObjectRepresentationStyleValue ;
2011-07-06 12:07:21 +08:00
}
2014-10-29 05:07:00 +08:00
else if ( IsToken ( var_name_begin , " var.script: " ) )
{
var_name_begin + = : : strlen ( " var.script: " ) ;
std : : string script_name ( var_name_begin , var_name_end ) ;
ScriptInterpreter * script_interpreter = valobj - > GetTargetSP ( ) - > GetDebugger ( ) . GetCommandInterpreter ( ) . GetScriptInterpreter ( ) ;
if ( RunScriptFormatKeyword ( s , script_interpreter , valobj , script_name ) )
var_success = true ;
break ;
}
2013-07-31 00:44:36 +08:00
else if ( IsToken ( var_name_begin , " var% " ) )
2011-07-06 12:07:21 +08:00
{
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 ;
2012-03-20 06:58:49 +08:00
val_obj_display = ValueObject : : eValueObjectRepresentationStyleValue ;
2011-07-06 12:07:21 +08:00
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
2013-07-31 00:44:36 +08:00
else if ( IsToken ( var_name_begin , " var " ) )
2011-06-30 06:27:15 +08:00
{
2013-07-31 00:44:36 +08:00
if ( IsToken ( var_name_begin , " var[ " ) )
2012-05-09 05:49:57 +08:00
was_var_indexed = true ;
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 ;
2013-02-02 07:59:44 +08:00
std : : string expr_path ( var_name_final - var_name_begin - 1 , 0 ) ;
memcpy ( & expr_path [ 0 ] , var_name_begin + 3 , var_name_final - var_name_begin - 3 ) ;
2011-07-23 01:03:19 +08:00
if ( log )
2013-02-02 07:59:44 +08:00
log - > Printf ( " [Debugger::FormatPrompt] symbol to expand: %s " , expr_path . c_str ( ) ) ;
2011-07-08 10:51:01 +08:00
2013-02-02 07:59:44 +08:00
target = valobj - > GetValueForExpressionPath ( expr_path . c_str ( ) ,
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 )
2012-10-18 06:23:56 +08:00
log - > Printf ( " [Debugger::FormatPrompt] ERROR: unparsed portion = %s, why stopping = %d, "
2011-07-23 01:03:19 +08:00
" 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 )
2012-10-18 06:23:56 +08:00
log - > Printf ( " [Debugger::FormatPrompt] ALL RIGHT: unparsed portion = %s, why stopping = %d, "
2011-07-23 01:03:19 +08:00
" final_value_type %d " ,
2011-07-08 10:51:01 +08:00
first_unparsed , reason_to_stop , final_value_type ) ;
2014-10-23 04:14:09 +08:00
target = target - > GetQualifiedRepresentationIfAvailable ( target - > GetDynamicValueType ( ) , true ) . get ( ) ;
2011-07-08 10:51:01 +08:00
}
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
2012-03-20 06:58:49 +08:00
is_array_range = ( final_value_type = = ValueObject : : eExpressionPathEndResultTypeBoundedRange | |
final_value_type = = ValueObject : : eExpressionPathEndResultTypeUnboundedRange ) ;
2011-07-08 10:51:01 +08:00
2012-03-20 06:58:49 +08:00
do_deref_pointer = ( what_next = = ValueObject : : eExpressionPathAftermathDereference ) ;
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 )
2012-10-18 06:23:56 +08:00
log - > Printf ( " [Debugger::FormatPrompt] ERROR: %s \n " , error . AsCString ( " unknown " ) ) ; \
2011-08-23 08:32:52 +08:00
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
2014-03-12 02:17:23 +08:00
if ( ! target )
{
if ( log )
log - > Printf ( " [Debugger::FormatPrompt] could not calculate target for prompt expression " ) ;
break ;
}
2012-05-09 05:49:57 +08:00
// we do not want to use the summary for a bitfield of type T:n
// if we were originally dealing with just a T - that would get
// us into an endless recursion
if ( target - > IsBitfield ( ) & & was_var_indexed )
{
// TODO: check for a (T:n)-specific summary - we should still obey that
StreamString bitfield_name ;
bitfield_name . Printf ( " %s:%d " , target - > GetTypeName ( ) . AsCString ( ) , target - > GetBitfieldBitSize ( ) ) ;
lldb : : TypeNameSpecifierImplSP type_sp ( new TypeNameSpecifierImpl ( bitfield_name . GetData ( ) , false ) ) ;
if ( ! DataVisualization : : GetSummaryForType ( type_sp ) )
val_obj_display = ValueObject : : eValueObjectRepresentationStyleValue ;
}
2011-08-19 00:38:26 +08:00
// TODO use flags for these
2013-07-12 06:46:58 +08:00
const uint32_t type_info_flags = target - > GetClangType ( ) . GetTypeInfo ( NULL ) ;
2014-10-22 04:52:14 +08:00
bool is_array = ( type_info_flags & eTypeIsArray ) ! = 0 ;
bool is_pointer = ( type_info_flags & eTypeIsPointer ) ! = 0 ;
2013-07-12 06:46:58 +08:00
bool is_aggregate = target - > GetClangType ( ) . IsAggregateType ( ) ;
2011-07-13 06:56:10 +08:00
2012-03-20 06:58:49 +08:00
if ( ( is_array | | is_pointer ) & & ( ! is_array_range ) & & val_obj_display = = ValueObject : : eValueObjectRepresentationStyleValue ) // this should be wrong, but there are some exceptions
2011-07-13 06:56:10 +08:00
{
2011-08-19 00:38:26 +08:00
StreamString str_temp ;
2011-07-23 01:03:19 +08:00
if ( log )
2012-10-18 06:23:56 +08:00
log - > Printf ( " [Debugger::FormatPrompt] I am into array || pointer && !range " ) ;
2011-08-20 05:13:46 +08:00
2013-03-26 05:06:13 +08:00
if ( target - > HasSpecialPrintableRepresentation ( 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 )
2012-10-18 06:23:56 +08:00
log - > Printf ( " [Debugger::FormatPrompt] special cases did%s match " , var_success ? " " : " n't " ) ;
2011-08-20 05:13:46 +08:00
// should not happen
2013-03-26 05:06:13 +08:00
if ( var_success )
2011-08-20 05:13:46 +08:00
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
{
2012-07-17 11:23:13 +08:00
target - > DumpPrintableRepresentation ( s ,
val_obj_display ,
custom_format ,
ValueObject : : ePrintableRepresentationSpecialCasesDisable ) ;
2011-08-24 05:26:09 +08:00
}
2011-08-20 05:13:46 +08:00
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
2012-03-20 06:58:49 +08:00
if ( is_aggregate & & ( ( was_var_format & & val_obj_display = = ValueObject : : eValueObjectRepresentationStyleValue ) ) )
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 )
2012-10-18 06:23:56 +08:00
log - > Printf ( " [Debugger::FormatPrompt] 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 )
2012-10-18 06:23:56 +08:00
log - > Printf ( " [Debugger::FormatPrompt] 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 )
2012-10-18 06:23:56 +08:00
log - > Printf ( " [Debugger::FormatPrompt] 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
2012-02-17 15:49:44 +08:00
uint32_t max_num_children = target - > GetTargetSP ( ) - > GetMaximumNumberOfChildrenToDisplay ( ) ;
2011-08-12 10:00:06 +08:00
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 )
2012-11-30 05:49:15 +08:00
log - > Printf ( " [Debugger::FormatPrompt] ERROR in getting child item at index % " PRId64 , index_lower ) ;
2011-07-08 10:51:01 +08:00
}
else
{
2011-07-23 01:03:19 +08:00
if ( log )
2012-10-18 06:23:56 +08:00
log - > Printf ( " [Debugger::FormatPrompt] 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
2014-10-11 07:07:36 +08:00
var_success & = FormatPromptRecurse ( special_directions , sc , exe_ctx , addr , s , NULL , item , function_changed , initial_function ) ;
2011-07-06 12:07:21 +08:00
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 ' :
2014-10-11 07:07:36 +08:00
if ( IsToken ( var_name_begin , " addr-file-or-load} " ) )
{
print_file_addr_or_load_addr = true ;
}
if ( IsToken ( var_name_begin , " addr} " )
| | IsToken ( var_name_begin , " addr-file-or-load} " ) )
2010-09-19 10:33:57 +08:00
{
if ( addr & & addr - > IsValid ( ) )
{
var_success = true ;
format_addr = * addr ;
}
}
break ;
case ' p ' :
2013-07-31 00:44:36 +08:00
if ( IsToken ( var_name_begin , " process. " ) )
2010-09-19 10:33:57 +08:00
{
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. " ) ;
2013-07-31 00:44:36 +08:00
if ( IsTokenWithFormat ( var_name_begin , " id " , token_format , " % " PRIu64 , exe_ctx , sc ) )
2010-09-19 10:33:57 +08:00
{
2013-07-31 00:44:36 +08:00
s . Printf ( token_format . c_str ( ) , process - > GetID ( ) ) ;
2011-09-22 12:58:26 +08:00
var_success = true ;
}
2013-07-31 00:44:36 +08:00
else if ( ( IsToken ( var_name_begin , " name} " ) ) | |
( IsToken ( var_name_begin , " file.basename} " ) ) | |
( IsToken ( var_name_begin , " file.fullpath} " ) ) )
2011-09-22 12:58:26 +08:00
{
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 ( ) ;
2013-10-05 05:35:29 +08:00
var_success = ( bool ) format_file_spec ;
2011-09-22 12:58:26 +08:00
}
else
{
format_file_spec = exe_module - > GetFileSpec ( ) ;
2013-10-05 05:35:29 +08:00
var_success = ( bool ) format_file_spec ;
2011-09-22 12:58:26 +08:00
}
2010-09-19 10:33:57 +08:00
}
}
2013-07-31 00:44:36 +08:00
else if ( IsToken ( var_name_begin , " script: " ) )
2013-06-21 07:40:21 +08:00
{
var_name_begin + = : : strlen ( " script: " ) ;
std : : string script_name ( var_name_begin , var_name_end ) ;
ScriptInterpreter * script_interpreter = process - > GetTarget ( ) . GetDebugger ( ) . GetCommandInterpreter ( ) . GetScriptInterpreter ( ) ;
2013-07-31 00:44:36 +08:00
if ( RunScriptFormatKeyword ( s , script_interpreter , process , script_name ) )
var_success = true ;
2013-06-21 07:40:21 +08:00
}
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 ' :
2013-07-31 00:44:36 +08:00
if ( IsToken ( var_name_begin , " thread. " ) )
2010-09-19 10:33:57 +08:00
{
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. " ) ;
2013-07-31 00:44:36 +08:00
if ( IsTokenWithFormat ( var_name_begin , " id " , token_format , " 0x%4.4 " PRIx64 , exe_ctx , sc ) )
2010-09-19 10:33:57 +08:00
{
2013-07-31 00:44:36 +08:00
s . Printf ( token_format . c_str ( ) , thread - > GetID ( ) ) ;
2011-09-22 12:58:26 +08:00
var_success = true ;
}
2013-07-31 00:44:36 +08:00
else if ( IsTokenWithFormat ( var_name_begin , " protocol_id " , token_format , " 0x%4.4 " PRIx64 , exe_ctx , sc ) )
2013-05-02 05:54:04 +08:00
{
2013-07-31 00:44:36 +08:00
s . Printf ( token_format . c_str ( ) , thread - > GetProtocolID ( ) ) ;
2013-05-02 05:54:04 +08:00
var_success = true ;
}
2013-07-31 00:44:36 +08:00
else if ( IsTokenWithFormat ( var_name_begin , " index " , token_format , " % " PRIu64 , exe_ctx , sc ) )
2011-09-22 12:58:26 +08:00
{
2013-07-31 00:44:36 +08:00
s . Printf ( token_format . c_str ( ) , ( uint64_t ) thread - > GetIndexID ( ) ) ;
2011-09-22 12:58:26 +08:00
var_success = true ;
}
2013-07-31 00:44:36 +08:00
else if ( IsToken ( var_name_begin , " name} " ) )
2011-09-22 12:58:26 +08:00
{
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
}
2013-07-31 00:44:36 +08:00
else if ( IsToken ( var_name_begin , " queue} " ) )
2011-09-22 12:58:26 +08:00
{
cstr = thread - > GetQueueName ( ) ;
var_success = cstr & & cstr [ 0 ] ;
if ( var_success )
s . PutCString ( cstr ) ;
}
2013-07-31 00:44:36 +08:00
else if ( IsToken ( var_name_begin , " stop-reason} " ) )
2011-09-22 12:58:26 +08:00
{
StopInfoSP stop_info_sp = thread - > GetStopInfo ( ) ;
2012-10-16 08:09:33 +08:00
if ( stop_info_sp & & stop_info_sp - > IsValid ( ) )
2011-09-22 12:58:26 +08:00
{
cstr = stop_info_sp - > GetDescription ( ) ;
if ( cstr & & cstr [ 0 ] )
{
s . PutCString ( cstr ) ;
var_success = true ;
}
2010-09-19 10:33:57 +08:00
}
}
2013-07-31 00:44:36 +08:00
else if ( IsToken ( var_name_begin , " return-value} " ) )
2011-12-17 09:35:57 +08:00
{
StopInfoSP stop_info_sp = thread - > GetStopInfo ( ) ;
2012-10-16 08:09:33 +08:00
if ( stop_info_sp & & stop_info_sp - > IsValid ( ) )
2011-12-17 09:35:57 +08:00
{
ValueObjectSP return_valobj_sp = StopInfo : : GetReturnValueObject ( stop_info_sp ) ;
if ( return_valobj_sp )
{
<rdar://problem/14393032>
DumpValueObject() 2.0
This checkin restores pre-Xcode5 functionality to the "po" (expr -O) command:
- expr now has a new --description-verbosity (-v) argument, which takes either compact or full as a value (-v is the same as -vfull)
When the full mode is on, "po" will show the extended output with type name, persistent variable name and value, as in
(lldb) expr -O -v -- foo
(id) $0 = 0x000000010010baf0 {
1 = 2;
2 = 3;
}
When -v is omitted, or -vcompact is passed, the Xcode5-style output will be shown, as in
(lldb) expr -O -- foo
{
1 = 2;
2 = 3;
}
- for a non-ObjectiveC object, LLDB will still try to retrieve a summary and/or value to display
(lldb) po 5
5
-v also works in this mode
(lldb) expr -O -vfull -- 5
(int) $4 = 5
On top of that, this is a major refactoring of the ValueObject printing code. The functionality is now factored into a ValueObjectPrinter class for easier maintenance in the future
DumpValueObject() was turned into an instance method ValueObject::Dump() which simply calls through to the printer code, Dump_Impl has been removed
Test case to follow
llvm-svn: 191694
2013-10-01 03:11:51 +08:00
return_valobj_sp - > Dump ( s ) ;
2011-12-23 03:12:40 +08:00
var_success = true ;
2011-12-17 09:35:57 +08:00
}
}
}
2014-07-08 09:07:32 +08:00
else if ( IsToken ( var_name_begin , " completed-expression} " ) )
{
StopInfoSP stop_info_sp = thread - > GetStopInfo ( ) ;
if ( stop_info_sp & & stop_info_sp - > IsValid ( ) )
{
ClangExpressionVariableSP expression_var_sp = StopInfo : : GetExpressionVariable ( stop_info_sp ) ;
if ( expression_var_sp & & expression_var_sp - > GetValueObject ( ) )
{
expression_var_sp - > GetValueObject ( ) - > Dump ( s ) ;
var_success = true ;
}
}
}
2013-07-31 00:44:36 +08:00
else if ( IsToken ( var_name_begin , " script: " ) )
2013-06-21 07:40:21 +08:00
{
var_name_begin + = : : strlen ( " script: " ) ;
std : : string script_name ( var_name_begin , var_name_end ) ;
ScriptInterpreter * script_interpreter = thread - > GetProcess ( ) - > GetTarget ( ) . GetDebugger ( ) . GetCommandInterpreter ( ) . GetScriptInterpreter ( ) ;
2013-07-31 00:44:36 +08:00
if ( RunScriptFormatKeyword ( s , script_interpreter , thread , script_name ) )
var_success = true ;
2013-06-21 07:40:21 +08:00
}
2014-06-13 10:37:02 +08:00
else if ( IsToken ( var_name_begin , " info. " ) )
{
var_name_begin + = : : strlen ( " info. " ) ;
StructuredData : : ObjectSP object_sp = thread - > GetExtendedInfo ( ) ;
if ( object_sp & & object_sp - > GetType ( ) = = StructuredData : : Type : : eTypeDictionary )
{
var_success = FormatThreadExtendedInfoRecurse ( var_name_begin , object_sp , sc , exe_ctx , s ) ;
}
}
2010-09-19 10:33:57 +08:00
}
}
}
2013-07-31 00:44:36 +08:00
else if ( IsToken ( var_name_begin , " target. " ) )
2010-09-19 10:33:57 +08:00
{
2012-08-23 01:17:09 +08:00
// TODO: hookup properties
// if (!target_properties_sp)
// {
// Target *target = Target::GetTargetFromContexts (exe_ctx, sc);
// if (target)
// target_properties_sp = target->GetProperties();
// }
//
// if (target_properties_sp)
// {
// var_name_begin += ::strlen ("target.");
// const char *end_property = strchr(var_name_begin, '}');
// if (end_property)
// {
// ConstString property_name(var_name_begin, end_property - var_name_begin);
// std::string property_value (target_properties_sp->GetPropertyValue(property_name));
// if (!property_value.empty())
// {
// s.PutCString (property_value.c_str());
// var_success = true;
// }
// }
// }
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. " ) ;
2013-07-31 00:44:36 +08:00
if ( IsToken ( var_name_begin , " arch} " ) )
2010-09-19 10:33:57 +08:00
{
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 ;
}
}
2013-07-31 00:44:36 +08:00
else if ( IsToken ( var_name_begin , " script: " ) )
2013-06-21 07:40:21 +08:00
{
var_name_begin + = : : strlen ( " script: " ) ;
std : : string script_name ( var_name_begin , var_name_end ) ;
ScriptInterpreter * script_interpreter = target - > GetDebugger ( ) . GetCommandInterpreter ( ) . GetScriptInterpreter ( ) ;
2013-07-31 00:44:36 +08:00
if ( RunScriptFormatKeyword ( s , script_interpreter , target , script_name ) )
var_success = true ;
2013-06-21 07:40:21 +08:00
}
2012-08-23 01:17:09 +08:00
}
2010-09-19 10:33:57 +08:00
}
break ;
2014-10-11 07:07:36 +08:00
2010-09-19 10:33:57 +08:00
case ' m ' :
2013-07-31 00:44:36 +08:00
if ( IsToken ( var_name_begin , " module. " ) )
2010-09-19 10:33:57 +08:00
{
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. " ) ;
2013-07-31 00:44:36 +08:00
if ( IsToken ( var_name_begin , " file. " ) )
2010-09-19 10:33:57 +08:00
{
if ( module - > GetFileSpec ( ) )
{
var_name_begin + = : : strlen ( " file. " ) ;
2013-07-31 00:44:36 +08:00
if ( IsToken ( var_name_begin , " basename} " ) )
2010-09-19 10:33:57 +08:00
{
format_file_spec . GetFilename ( ) = module - > GetFileSpec ( ) . GetFilename ( ) ;
2013-10-05 05:35:29 +08:00
var_success = ( bool ) format_file_spec ;
2010-09-19 10:33:57 +08:00
}
2013-07-31 00:44:36 +08:00
else if ( IsToken ( var_name_begin , " fullpath} " ) )
2010-09-19 10:33:57 +08:00
{
format_file_spec = module - > GetFileSpec ( ) ;
2013-10-05 05:35:29 +08:00
var_success = ( bool ) format_file_spec ;
2010-09-19 10:33:57 +08:00
}
}
}
}
}
break ;
case ' f ' :
2013-07-31 00:44:36 +08:00
if ( IsToken ( var_name_begin , " file. " ) )
2010-09-19 10:33:57 +08:00
{
if ( sc & & sc - > comp_unit ! = NULL )
{
var_name_begin + = : : strlen ( " file. " ) ;
2013-07-31 00:44:36 +08:00
if ( IsToken ( var_name_begin , " basename} " ) )
2010-09-19 10:33:57 +08:00
{
format_file_spec . GetFilename ( ) = sc - > comp_unit - > GetFilename ( ) ;
2013-10-05 05:35:29 +08:00
var_success = ( bool ) format_file_spec ;
2010-09-19 10:33:57 +08:00
}
2013-07-31 00:44:36 +08:00
else if ( IsToken ( var_name_begin , " fullpath} " ) )
2010-09-19 10:33:57 +08:00
{
format_file_spec = * sc - > comp_unit ;
2013-10-05 05:35:29 +08:00
var_success = ( bool ) format_file_spec ;
2010-09-19 10:33:57 +08:00
}
}
}
2013-07-31 00:44:36 +08:00
else if ( IsToken ( var_name_begin , " frame. " ) )
2010-09-19 10:33:57 +08:00
{
2011-09-22 12:58:26 +08:00
if ( exe_ctx )
2010-09-19 10:33:57 +08:00
{
2013-11-04 17:33:30 +08:00
StackFrame * frame = exe_ctx - > GetFramePtr ( ) ;
2011-09-22 12:58:26 +08:00
if ( frame )
2010-09-19 10:33:57 +08:00
{
2011-09-22 12:58:26 +08:00
var_name_begin + = : : strlen ( " frame. " ) ;
2013-07-31 00:44:36 +08:00
if ( IsToken ( var_name_begin , " index} " ) )
2011-09-22 12:58:26 +08:00
{
s . Printf ( " %u " , frame - > GetFrameIndex ( ) ) ;
var_success = true ;
}
2013-07-31 00:44:36 +08:00
else if ( IsToken ( var_name_begin , " pc} " ) )
2011-09-22 12:58:26 +08:00
{
reg_kind = eRegisterKindGeneric ;
reg_num = LLDB_REGNUM_GENERIC_PC ;
var_success = true ;
}
2013-07-31 00:44:36 +08:00
else if ( IsToken ( var_name_begin , " sp} " ) )
2011-09-22 12:58:26 +08:00
{
reg_kind = eRegisterKindGeneric ;
reg_num = LLDB_REGNUM_GENERIC_SP ;
var_success = true ;
}
2013-07-31 00:44:36 +08:00
else if ( IsToken ( var_name_begin , " fp} " ) )
2011-09-22 12:58:26 +08:00
{
reg_kind = eRegisterKindGeneric ;
reg_num = LLDB_REGNUM_GENERIC_FP ;
var_success = true ;
}
2013-07-31 00:44:36 +08:00
else if ( IsToken ( var_name_begin , " flags} " ) )
2011-09-22 12:58:26 +08:00
{
reg_kind = eRegisterKindGeneric ;
reg_num = LLDB_REGNUM_GENERIC_FLAGS ;
var_success = true ;
}
2013-07-31 00:44:36 +08:00
else if ( IsToken ( var_name_begin , " reg. " ) )
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
}
}
2013-07-31 00:44:36 +08:00
else if ( IsToken ( var_name_begin , " script: " ) )
2013-06-21 07:40:21 +08:00
{
var_name_begin + = : : strlen ( " script: " ) ;
std : : string script_name ( var_name_begin , var_name_end ) ;
ScriptInterpreter * script_interpreter = frame - > GetThread ( ) - > GetProcess ( ) - > GetTarget ( ) . GetDebugger ( ) . GetCommandInterpreter ( ) . GetScriptInterpreter ( ) ;
2013-07-31 00:44:36 +08:00
if ( RunScriptFormatKeyword ( s , script_interpreter , frame , script_name ) )
var_success = true ;
2013-06-21 07:40:21 +08:00
}
2010-09-19 10:33:57 +08:00
}
}
}
2013-07-31 00:44:36 +08:00
else if ( IsToken ( var_name_begin , " function. " ) )
2010-09-19 10:33:57 +08:00
{
if ( sc & & ( sc - > function ! = NULL | | sc - > symbol ! = NULL ) )
{
var_name_begin + = : : strlen ( " function. " ) ;
2013-07-31 00:44:36 +08:00
if ( IsToken ( var_name_begin , " id} " ) )
2010-09-19 10:33:57 +08:00
{
if ( sc - > function )
2012-11-30 05:49:15 +08:00
s . Printf ( " function{0x%8.8 " PRIx64 " } " , sc - > function - > GetID ( ) ) ;
2010-09-19 10:33:57 +08:00
else
s . Printf ( " symbol[%u] " , sc - > symbol - > GetID ( ) ) ;
var_success = true ;
}
2014-10-11 07:07:36 +08:00
if ( IsToken ( var_name_begin , " changed} " ) & & function_changed )
{
var_success = true ;
}
if ( IsToken ( var_name_begin , " initial-function} " ) & & initial_function )
{
var_success = true ;
}
2013-07-31 00:44:36 +08:00
else if ( IsToken ( var_name_begin , " name} " ) )
2010-09-19 10:33:57 +08:00
{
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 ;
}
}
2014-10-11 07:07:36 +08:00
else if ( IsToken ( var_name_begin , " name-without-args} " ) )
{
ConstString name ;
if ( sc - > function )
name = sc - > function - > GetMangled ( ) . GetName ( Mangled : : ePreferDemangledWithoutArguments ) ;
else if ( sc - > symbol )
name = sc - > symbol - > GetMangled ( ) . GetName ( Mangled : : ePreferDemangledWithoutArguments ) ;
if ( name )
{
s . PutCString ( name . GetCString ( ) ) ;
var_success = true ;
}
}
2013-07-31 00:44:36 +08:00
else if ( IsToken ( var_name_begin , " name-with-args} " ) )
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
{
// 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 )
2013-05-09 04:27:37 +08:00
variable_list_sp - > AppendVariablesWithScope ( eValueTypeVariableArgument , args ) ;
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
if ( args . GetSize ( ) > 0 )
{
const char * open_paren = strchr ( cstr , ' ( ' ) ;
2014-08-16 08:56:04 +08:00
const char * close_paren = nullptr ;
const char * generic = strchr ( cstr , ' < ' ) ;
// if before the arguments list begins there is a template sign
// then scan to the end of the generic args before you try to find
// the arguments list
if ( generic & & open_paren & & generic < open_paren )
{
int generic_depth = 1 ;
+ + generic ;
for ( ;
* generic & & generic_depth > 0 ;
generic + + )
{
if ( * generic = = ' < ' )
generic_depth + + ;
if ( * generic = = ' > ' )
generic_depth - - ;
}
if ( * generic )
open_paren = strchr ( generic , ' ( ' ) ;
else
open_paren = nullptr ;
}
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
if ( open_paren )
2013-03-26 09:45:43 +08:00
{
2013-07-31 00:44:36 +08:00
if ( IsToken ( open_paren , " (anonymous namespace) " ) )
2013-03-26 09:45:43 +08:00
{
open_paren = strchr ( open_paren + strlen ( " (anonymous namespace) " ) , ' ( ' ) ;
if ( open_paren )
close_paren = strchr ( open_paren , ' ) ' ) ;
}
else
close_paren = strchr ( open_paren , ' ) ' ) ;
}
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
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 )
{
2014-03-26 06:03:52 +08:00
std : : string buffer ;
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
VariableSP var_sp ( args . GetVariableAtIndex ( arg_idx ) ) ;
ValueObjectSP var_value_sp ( ValueObjectVariable : : Create ( exe_scope , var_sp ) ) ;
2014-03-26 06:03:52 +08:00
const char * var_representation = nullptr ;
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
const char * var_name = var_value_sp - > GetName ( ) . GetCString ( ) ;
2014-03-26 06:03:52 +08:00
if ( var_value_sp - > GetClangType ( ) . IsAggregateType ( ) & &
DataVisualization : : ShouldPrintAsOneLiner ( * var_value_sp . get ( ) ) )
{
static StringSummaryFormat format ( TypeSummaryImpl : : Flags ( )
. SetHideItemNames ( false )
. SetShowMembersOneLiner ( true ) ,
" " ) ;
2014-11-07 05:55:30 +08:00
format . FormatObject ( var_value_sp . get ( ) , buffer , TypeSummaryOptions ( ) ) ;
2014-03-26 06:03:52 +08:00
var_representation = buffer . c_str ( ) ;
}
else
var_representation = var_value_sp - > GetValueAsCString ( ) ;
2012-12-11 06:26:34 +08:00
if ( arg_idx > 0 )
s . PutCString ( " , " ) ;
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
if ( var_value_sp - > GetError ( ) . Success ( ) )
2013-05-09 04:27:37 +08:00
{
2014-03-26 06:03:52 +08:00
if ( var_representation )
s . Printf ( " %s=%s " , var_name , var_representation ) ;
2013-05-09 04:27:37 +08:00
else
s . Printf ( " %s=%s at %s " , var_name , var_value_sp - > GetTypeName ( ) . GetCString ( ) , var_value_sp - > GetLocationAsCString ( ) ) ;
}
2012-12-11 06:26:34 +08:00
else
s . Printf ( " %s=<unavailable> " , var_name ) ;
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
}
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 ;
}
}
}
2014-10-11 07:07:36 +08:00
else if ( IsToken ( var_name_begin , " addr-offset} " )
| | IsToken ( var_name_begin , " concrete-only-addr-offset-no-padding} " ) )
2010-09-19 10:33:57 +08:00
{
2014-10-11 07:07:36 +08:00
if ( IsToken ( var_name_begin , " concrete-only-addr-offset-no-padding} " ) )
{
addr_offset_print_with_no_padding = true ;
addr_offset_concrete_func_only = true ;
}
2010-09-19 10:33:57 +08:00
var_success = addr ! = NULL ;
if ( var_success )
{
format_addr = * addr ;
calculate_format_addr_function_offset = true ;
}
}
2013-07-31 00:44:36 +08:00
else if ( IsToken ( var_name_begin , " line-offset} " ) )
2010-09-19 10:33:57 +08:00
{
var_success = sc - > line_entry . range . GetBaseAddress ( ) . IsValid ( ) ;
if ( var_success )
{
format_addr = sc - > line_entry . range . GetBaseAddress ( ) ;
calculate_format_addr_function_offset = true ;
}
}
2013-07-31 00:44:36 +08:00
else if ( IsToken ( var_name_begin , " pc-offset} " ) )
2010-09-19 10:33:57 +08:00
{
2013-11-04 17:33:30 +08:00
StackFrame * frame = exe_ctx - > GetFramePtr ( ) ;
2011-09-22 12:58:26 +08:00
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 ' :
2013-07-31 00:44:36 +08:00
if ( IsToken ( var_name_begin , " line. " ) )
2010-09-19 10:33:57 +08:00
{
if ( sc & & sc - > line_entry . IsValid ( ) )
{
var_name_begin + = : : strlen ( " line. " ) ;
2013-07-31 00:44:36 +08:00
if ( IsToken ( var_name_begin , " file. " ) )
2010-09-19 10:33:57 +08:00
{
var_name_begin + = : : strlen ( " file. " ) ;
2013-07-31 00:44:36 +08:00
if ( IsToken ( var_name_begin , " basename} " ) )
2010-09-19 10:33:57 +08:00
{
format_file_spec . GetFilename ( ) = sc - > line_entry . file . GetFilename ( ) ;
2013-10-05 05:35:29 +08:00
var_success = ( bool ) format_file_spec ;
2010-09-19 10:33:57 +08:00
}
2013-07-31 00:44:36 +08:00
else if ( IsToken ( var_name_begin , " fullpath} " ) )
2010-09-19 10:33:57 +08:00
{
format_file_spec = sc - > line_entry . file ;
2013-10-05 05:35:29 +08:00
var_success = ( bool ) format_file_spec ;
2010-09-19 10:33:57 +08:00
}
}
2013-07-31 00:44:36 +08:00
else if ( IsTokenWithFormat ( var_name_begin , " number " , token_format , " % " PRIu64 , exe_ctx , sc ) )
2010-09-19 10:33:57 +08:00
{
var_success = true ;
2013-07-31 00:44:36 +08:00
s . Printf ( token_format . c_str ( ) , ( uint64_t ) sc - > line_entry . line ) ;
2010-09-19 10:33:57 +08:00
}
2013-07-31 00:44:36 +08:00
else if ( ( IsToken ( var_name_begin , " start-addr} " ) ) | |
( IsToken ( var_name_begin , " end-addr} " ) ) )
2010-09-19 10:33:57 +08:00
{
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 ;
2014-10-11 07:07:36 +08:00
case ' c ' :
if ( IsToken ( var_name_begin , " current-pc-arrow " ) )
{
if ( addr & & exe_ctx & & exe_ctx - > GetFramePtr ( ) )
{
RegisterContextSP reg_ctx = exe_ctx - > GetFramePtr ( ) - > GetRegisterContextSP ( ) ;
if ( reg_ctx . get ( ) )
{
addr_t pc_loadaddr = reg_ctx - > GetPC ( ) ;
if ( pc_loadaddr ! = LLDB_INVALID_ADDRESS )
{
Address pc ;
pc . SetLoadAddress ( pc_loadaddr , exe_ctx - > GetTargetPtr ( ) ) ;
if ( pc = = * addr )
{
2014-12-02 08:26:21 +08:00
s . Printf ( " -> " ) ;
2014-10-11 07:07:36 +08:00
var_success = true ;
}
}
}
2014-12-02 08:26:21 +08:00
if ( var_success = = false )
{
s . Printf ( " " ) ;
var_success = true ;
}
2014-10-11 07:07:36 +08:00
}
2014-12-02 08:26:21 +08:00
var_success = true ;
2014-10-11 07:07:36 +08:00
}
break ;
2010-09-19 10:33:57 +08:00
}
if ( var_success )
{
// If format addr is valid, then we need to print an address
if ( reg_num ! = LLDB_INVALID_REGNUM )
{
2013-11-04 17:33:30 +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 ( ) ;
2014-10-11 07:07:36 +08:00
if ( sc - > block & & addr_offset_concrete_func_only = = false )
2010-10-05 01:26:49 +08:00
{
// 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 ( ) ;
}
}
2012-03-08 05:03:09 +08:00
else if ( sc - > symbol & & sc - > symbol - > ValueIsAddress ( ) )
func_addr = sc - > symbol - > GetAddress ( ) ;
2010-10-04 09:05:56 +08:00
}
if ( func_addr . IsValid ( ) )
2010-09-19 10:33:57 +08:00
{
2014-10-11 07:07:36 +08:00
const char * addr_offset_padding = " " ;
if ( addr_offset_print_with_no_padding )
{
addr_offset_padding = " " ;
}
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 )
2014-10-11 07:07:36 +08:00
s . Printf ( " %s+%s% " PRIu64 , addr_offset_padding , addr_offset_padding , addr_file_addr - func_file_addr ) ;
2010-09-19 10:33:57 +08:00
else if ( addr_file_addr < func_file_addr )
2014-10-11 07:07:36 +08:00
s . Printf ( " %s-%s% " PRIu64 , addr_offset_padding , addr_offset_padding , 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 )
2014-10-11 07:07:36 +08:00
s . Printf ( " %s+%s% " PRIu64 , addr_offset_padding , addr_offset_padding , addr_load_addr - func_load_addr ) ;
2010-10-04 09:05:56 +08:00
else if ( addr_load_addr < func_load_addr )
2014-10-11 07:07:36 +08:00
s . Printf ( " %s-%s% " PRIu64 , addr_offset_padding , addr_offset_padding , func_load_addr - addr_load_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 ) ;
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
{
2014-10-11 07:07:36 +08:00
int addr_width = 0 ;
if ( exe_ctx & & target )
{
2014-10-11 08:04:42 +08:00
addr_width = target - > GetArchitecture ( ) . GetAddressByteSize ( ) * 2 ;
2014-10-11 07:07:36 +08:00
}
2010-11-19 12:16:11 +08:00
if ( addr_width = = 0 )
addr_width = 16 ;
2014-10-11 07:07:36 +08:00
if ( print_file_addr_or_load_addr )
{
format_addr . Dump ( & s , exe_ctx ? exe_ctx - > GetBestExecutionContextScope ( ) : NULL , Address : : DumpStyleLoadAddress , Address : : DumpStyleModuleWithFileAddress , 0 ) ;
}
else
{
s . Printf ( " 0x%*.* " PRIx64 , 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
{
2013-01-26 02:06:21 +08:00
s . PutChar ( ( char ) octal_value ) ;
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 )
2013-01-26 02:06:21 +08:00
s . PutChar ( ( char ) hex_value ) ;
2010-10-04 09:05:56 +08:00
}
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 ;
}
2013-05-24 04:47:45 +08:00
bool
Debugger : : FormatPrompt
(
const char * format ,
const SymbolContext * sc ,
const ExecutionContext * exe_ctx ,
const Address * addr ,
Stream & s ,
ValueObject * valobj
)
{
bool use_color = exe_ctx ? exe_ctx - > GetTargetRef ( ) . GetDebugger ( ) . GetUseColor ( ) : true ;
std : : string format_str = lldb_utility : : ansi : : FormatAnsiTerminalCodes ( format , use_color ) ;
if ( format_str . length ( ) )
format = format_str . c_str ( ) ;
2014-10-11 07:07:36 +08:00
return FormatPromptRecurse ( format , sc , exe_ctx , addr , s , NULL , valobj , false , false ) ;
}
bool
Debugger : : FormatDisassemblerAddress ( const char * format ,
const SymbolContext * sc ,
const SymbolContext * prev_sc ,
const ExecutionContext * exe_ctx ,
const Address * addr ,
Stream & s )
{
if ( format = = NULL & & exe_ctx ! = NULL & & exe_ctx - > HasTargetScope ( ) )
{
format = exe_ctx - > GetTargetRef ( ) . GetDebugger ( ) . GetDisassemblyFormat ( ) ;
}
bool function_changed = false ;
bool initial_function = false ;
if ( prev_sc & & ( prev_sc - > function | | prev_sc - > symbol ) )
{
if ( sc & & ( sc - > function | | sc - > symbol ) )
{
if ( prev_sc - > symbol & & sc - > symbol )
{
if ( ! sc - > symbol - > Compare ( prev_sc - > symbol - > GetName ( ) , prev_sc - > symbol - > GetType ( ) ) )
{
function_changed = true ;
}
}
else if ( prev_sc - > function & & sc - > function )
{
if ( prev_sc - > function - > GetMangled ( ) ! = sc - > function - > GetMangled ( ) )
{
function_changed = true ;
}
}
}
}
// The first context on a list of instructions will have a prev_sc that
// has no Function or Symbol -- if SymbolContext had an IsValid() method, it
// would return false. But we do get a prev_sc pointer.
if ( ( sc & & ( sc - > function | | sc - > symbol ) )
& & prev_sc & & ( prev_sc - > function = = NULL & & prev_sc - > symbol = = NULL ) )
{
initial_function = true ;
}
return FormatPromptRecurse ( format , sc , exe_ctx , addr , s , NULL , NULL , function_changed , initial_function ) ;
2013-05-24 04:47:45 +08:00
}
2014-10-11 07:07:36 +08:00
2012-02-21 10:23:08 +08:00
void
Debugger : : SetLoggingCallback ( lldb : : LogOutputCallback log_callback , void * baton )
{
2012-02-23 06:49:20 +08:00
// For simplicity's sake, I am not going to deal with how to close down any
// open logging streams, I just redirect everything from here on out to the
// callback.
2012-02-21 10:23:08 +08:00
m_log_callback_stream_sp . reset ( new StreamCallback ( log_callback , baton ) ) ;
}
bool
Debugger : : EnableLog ( const char * channel , const char * * categories , const char * log_file , uint32_t log_options , Stream & error_stream )
{
Log : : Callbacks log_callbacks ;
StreamSP log_stream_sp ;
2012-08-09 08:50:26 +08:00
if ( m_log_callback_stream_sp )
2012-02-21 10:23:08 +08:00
{
log_stream_sp = m_log_callback_stream_sp ;
// For now when using the callback mode you always get thread & timestamp.
log_options | = LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_THREAD_NAME ;
}
else if ( log_file = = NULL | | * log_file = = ' \0 ' )
{
2014-01-28 07:43:24 +08:00
log_stream_sp = GetOutputFile ( ) ;
2012-02-21 10:23:08 +08:00
}
else
{
LogStreamMap : : iterator pos = m_log_streams . find ( log_file ) ;
2013-01-08 08:01:36 +08:00
if ( pos ! = m_log_streams . end ( ) )
log_stream_sp = pos - > second . lock ( ) ;
if ( ! log_stream_sp )
2012-02-21 10:23:08 +08:00
{
log_stream_sp . reset ( new StreamFile ( log_file ) ) ;
m_log_streams [ log_file ] = log_stream_sp ;
}
}
assert ( log_stream_sp . get ( ) ) ;
if ( log_options = = 0 )
log_options = LLDB_LOG_OPTION_PREPEND_THREAD_NAME | LLDB_LOG_OPTION_THREADSAFE ;
2013-05-11 05:47:16 +08:00
if ( Log : : GetLogChannelCallbacks ( ConstString ( channel ) , log_callbacks ) )
2012-02-21 10:23:08 +08:00
{
log_callbacks . enable ( log_stream_sp , log_options , categories , & error_stream ) ;
return true ;
}
else
{
LogChannelSP log_channel_sp ( LogChannel : : FindPlugin ( channel ) ) ;
if ( log_channel_sp )
{
if ( log_channel_sp - > Enable ( log_stream_sp , log_options , & error_stream , categories ) )
{
return true ;
}
else
{
error_stream . Printf ( " Invalid log channel '%s'. \n " , channel ) ;
return false ;
}
}
else
{
error_stream . Printf ( " Invalid log channel '%s'. \n " , channel ) ;
return false ;
}
}
return false ;
}
2013-03-19 08:20:55 +08:00
SourceManager &
Debugger : : GetSourceManager ( )
{
if ( m_source_manager_ap . get ( ) = = NULL )
m_source_manager_ap . reset ( new SourceManager ( shared_from_this ( ) ) ) ;
return * m_source_manager_ap ;
}
2014-01-28 07:43:24 +08:00
// This function handles events that were broadcast by the process.
void
Debugger : : HandleBreakpointEvent ( const EventSP & event_sp )
{
using namespace lldb ;
const uint32_t event_type = Breakpoint : : BreakpointEventData : : GetBreakpointEventTypeFromEvent ( event_sp ) ;
// if (event_type & eBreakpointEventTypeAdded
// || event_type & eBreakpointEventTypeRemoved
// || event_type & eBreakpointEventTypeEnabled
// || event_type & eBreakpointEventTypeDisabled
// || event_type & eBreakpointEventTypeCommandChanged
// || event_type & eBreakpointEventTypeConditionChanged
// || event_type & eBreakpointEventTypeIgnoreChanged
// || event_type & eBreakpointEventTypeLocationsResolved)
// {
// // Don't do anything about these events, since the breakpoint commands already echo these actions.
// }
//
if ( event_type & eBreakpointEventTypeLocationsAdded )
{
uint32_t num_new_locations = Breakpoint : : BreakpointEventData : : GetNumBreakpointLocationsFromEvent ( event_sp ) ;
if ( num_new_locations > 0 )
{
BreakpointSP breakpoint = Breakpoint : : BreakpointEventData : : GetBreakpointFromEvent ( event_sp ) ;
StreamFileSP output_sp ( GetOutputFile ( ) ) ;
if ( output_sp )
{
output_sp - > Printf ( " %d location%s added to breakpoint %d \n " ,
num_new_locations ,
num_new_locations = = 1 ? " " : " s " ,
breakpoint - > GetID ( ) ) ;
RefreshTopIOHandler ( ) ;
}
}
}
// else if (event_type & eBreakpointEventTypeLocationsRemoved)
// {
// // These locations just get disabled, not sure it is worth spamming folks about this on the command line.
// }
// else if (event_type & eBreakpointEventTypeLocationsResolved)
// {
// // This might be an interesting thing to note, but I'm going to leave it quiet for now, it just looked noisy.
// }
}
size_t
Debugger : : GetProcessSTDOUT ( Process * process , Stream * stream )
{
size_t total_bytes = 0 ;
if ( stream = = NULL )
stream = GetOutputFile ( ) . get ( ) ;
if ( stream )
{
// The process has stuff waiting for stdout; get it and write it out to the appropriate place.
if ( process = = NULL )
{
TargetSP target_sp = GetTargetList ( ) . GetSelectedTarget ( ) ;
if ( target_sp )
process = target_sp - > GetProcessSP ( ) . get ( ) ;
}
if ( process )
{
Error error ;
size_t len ;
char stdio_buffer [ 1024 ] ;
while ( ( len = process - > GetSTDOUT ( stdio_buffer , sizeof ( stdio_buffer ) , error ) ) > 0 )
{
stream - > Write ( stdio_buffer , len ) ;
total_bytes + = len ;
}
}
stream - > Flush ( ) ;
}
return total_bytes ;
}
size_t
Debugger : : GetProcessSTDERR ( Process * process , Stream * stream )
{
size_t total_bytes = 0 ;
if ( stream = = NULL )
stream = GetOutputFile ( ) . get ( ) ;
if ( stream )
{
// The process has stuff waiting for stderr; get it and write it out to the appropriate place.
if ( process = = NULL )
{
TargetSP target_sp = GetTargetList ( ) . GetSelectedTarget ( ) ;
if ( target_sp )
process = target_sp - > GetProcessSP ( ) . get ( ) ;
}
if ( process )
{
Error error ;
size_t len ;
char stdio_buffer [ 1024 ] ;
while ( ( len = process - > GetSTDERR ( stdio_buffer , sizeof ( stdio_buffer ) , error ) ) > 0 )
{
stream - > Write ( stdio_buffer , len ) ;
total_bytes + = len ;
}
}
stream - > Flush ( ) ;
}
return total_bytes ;
}
2014-10-21 09:00:42 +08:00
2014-01-28 07:43:24 +08:00
// This function handles events that were broadcast by the process.
void
Debugger : : HandleProcessEvent ( const EventSP & event_sp )
{
using namespace lldb ;
const uint32_t event_type = event_sp - > GetType ( ) ;
ProcessSP process_sp = Process : : ProcessEventData : : GetProcessFromEvent ( event_sp . get ( ) ) ;
2014-10-21 09:00:42 +08:00
2014-03-01 02:22:24 +08:00
StreamString output_stream ;
StreamString error_stream ;
2014-01-28 07:43:24 +08:00
const bool gui_enabled = IsForwardingEvents ( ) ;
2014-03-01 02:22:24 +08:00
if ( ! gui_enabled )
2014-01-28 07:43:24 +08:00
{
2014-03-01 02:22:24 +08:00
bool pop_process_io_handler = false ;
assert ( process_sp ) ;
2014-10-21 09:00:42 +08:00
2014-03-01 02:22:24 +08:00
if ( event_type & Process : : eBroadcastBitSTDOUT | | event_type & Process : : eBroadcastBitStateChanged )
{
GetProcessSTDOUT ( process_sp . get ( ) , & output_stream ) ;
}
2014-10-21 09:00:42 +08:00
2014-03-01 02:22:24 +08:00
if ( event_type & Process : : eBroadcastBitSTDERR | | event_type & Process : : eBroadcastBitStateChanged )
{
GetProcessSTDERR ( process_sp . get ( ) , & error_stream ) ;
}
2014-10-21 09:00:42 +08:00
2014-03-01 02:22:24 +08:00
if ( event_type & Process : : eBroadcastBitStateChanged )
2014-01-28 07:43:24 +08:00
{
2014-10-21 09:00:42 +08:00
Process : : HandleProcessStateChangedEvent ( event_sp , & output_stream , pop_process_io_handler ) ;
2014-01-28 07:43:24 +08:00
}
2014-10-21 09:00:42 +08:00
2014-03-01 02:22:24 +08:00
if ( output_stream . GetSize ( ) | | error_stream . GetSize ( ) )
{
StreamFileSP error_stream_sp ( GetOutputFile ( ) ) ;
2014-03-04 03:15:20 +08:00
bool top_io_handler_hid = false ;
2014-10-21 09:00:42 +08:00
2014-03-04 03:15:20 +08:00
if ( process_sp - > ProcessIOHandlerIsActive ( ) = = false )
top_io_handler_hid = HideTopIOHandler ( ) ;
2014-03-01 02:22:24 +08:00
if ( output_stream . GetSize ( ) )
{
StreamFileSP output_stream_sp ( GetOutputFile ( ) ) ;
if ( output_stream_sp )
output_stream_sp - > Write ( output_stream . GetData ( ) , output_stream . GetSize ( ) ) ;
}
if ( error_stream . GetSize ( ) )
{
StreamFileSP error_stream_sp ( GetErrorFile ( ) ) ;
if ( error_stream_sp )
error_stream_sp - > Write ( error_stream . GetData ( ) , error_stream . GetSize ( ) ) ;
}
if ( top_io_handler_hid )
RefreshTopIOHandler ( ) ;
}
if ( pop_process_io_handler )
process_sp - > PopProcessIOHandler ( ) ;
}
2014-01-28 07:43:24 +08:00
}
void
Debugger : : HandleThreadEvent ( const EventSP & event_sp )
{
// At present the only thread event we handle is the Frame Changed event,
// and all we do for that is just reprint the thread status for that thread.
using namespace lldb ;
const uint32_t event_type = event_sp - > GetType ( ) ;
if ( event_type = = Thread : : eBroadcastBitStackChanged | |
event_type = = Thread : : eBroadcastBitThreadSelected )
{
ThreadSP thread_sp ( Thread : : ThreadEventData : : GetThreadFromEvent ( event_sp . get ( ) ) ) ;
if ( thread_sp )
{
HideTopIOHandler ( ) ;
StreamFileSP stream_sp ( GetOutputFile ( ) ) ;
thread_sp - > GetStatus ( * stream_sp , 0 , 1 , 1 ) ;
RefreshTopIOHandler ( ) ;
}
}
}
bool
Debugger : : IsForwardingEvents ( )
{
return ( bool ) m_forward_listener_sp ;
}
void
Debugger : : EnableForwardEvents ( const ListenerSP & listener_sp )
{
m_forward_listener_sp = listener_sp ;
}
void
Debugger : : CancelForwardEvents ( const ListenerSP & listener_sp )
{
m_forward_listener_sp . reset ( ) ;
}
void
Debugger : : DefaultEventHandler ( )
{
Listener & listener ( GetListener ( ) ) ;
ConstString broadcaster_class_target ( Target : : GetStaticBroadcasterClass ( ) ) ;
ConstString broadcaster_class_process ( Process : : GetStaticBroadcasterClass ( ) ) ;
ConstString broadcaster_class_thread ( Thread : : GetStaticBroadcasterClass ( ) ) ;
BroadcastEventSpec target_event_spec ( broadcaster_class_target ,
Target : : eBroadcastBitBreakpointChanged ) ;
BroadcastEventSpec process_event_spec ( broadcaster_class_process ,
Process : : eBroadcastBitStateChanged |
Process : : eBroadcastBitSTDOUT |
Process : : eBroadcastBitSTDERR ) ;
BroadcastEventSpec thread_event_spec ( broadcaster_class_thread ,
Thread : : eBroadcastBitStackChanged |
Thread : : eBroadcastBitThreadSelected ) ;
listener . StartListeningForEventSpec ( * this , target_event_spec ) ;
listener . StartListeningForEventSpec ( * this , process_event_spec ) ;
listener . StartListeningForEventSpec ( * this , thread_event_spec ) ;
listener . StartListeningForEvents ( m_command_interpreter_ap . get ( ) ,
CommandInterpreter : : eBroadcastBitQuitCommandReceived |
CommandInterpreter : : eBroadcastBitAsynchronousOutputData |
CommandInterpreter : : eBroadcastBitAsynchronousErrorData ) ;
2014-12-02 06:41:27 +08:00
// Let the thread that spawned us know that we have started up and
// that we are now listening to all required events so no events get missed
m_sync_broadcaster . BroadcastEvent ( eBroadcastBitEventThreadIsListening ) ;
2014-01-28 07:43:24 +08:00
bool done = false ;
while ( ! done )
{
EventSP event_sp ;
if ( listener . WaitForEvent ( NULL , event_sp ) )
{
if ( event_sp )
{
Broadcaster * broadcaster = event_sp - > GetBroadcaster ( ) ;
if ( broadcaster )
{
uint32_t event_type = event_sp - > GetType ( ) ;
ConstString broadcaster_class ( broadcaster - > GetBroadcasterClass ( ) ) ;
if ( broadcaster_class = = broadcaster_class_process )
{
HandleProcessEvent ( event_sp ) ;
}
else if ( broadcaster_class = = broadcaster_class_target )
{
if ( Breakpoint : : BreakpointEventData : : GetEventDataFromEvent ( event_sp . get ( ) ) )
{
HandleBreakpointEvent ( event_sp ) ;
}
}
else if ( broadcaster_class = = broadcaster_class_thread )
{
HandleThreadEvent ( event_sp ) ;
}
else if ( broadcaster = = m_command_interpreter_ap . get ( ) )
{
if ( event_type & CommandInterpreter : : eBroadcastBitQuitCommandReceived )
{
done = true ;
}
else if ( event_type & CommandInterpreter : : eBroadcastBitAsynchronousErrorData )
{
const char * data = reinterpret_cast < const char * > ( EventDataBytes : : GetBytesFromEvent ( event_sp . get ( ) ) ) ;
if ( data & & data [ 0 ] )
{
StreamFileSP error_sp ( GetErrorFile ( ) ) ;
if ( error_sp )
{
HideTopIOHandler ( ) ;
error_sp - > PutCString ( data ) ;
error_sp - > Flush ( ) ;
RefreshTopIOHandler ( ) ;
}
}
}
else if ( event_type & CommandInterpreter : : eBroadcastBitAsynchronousOutputData )
{
const char * data = reinterpret_cast < const char * > ( EventDataBytes : : GetBytesFromEvent ( event_sp . get ( ) ) ) ;
if ( data & & data [ 0 ] )
{
StreamFileSP output_sp ( GetOutputFile ( ) ) ;
if ( output_sp )
{
HideTopIOHandler ( ) ;
output_sp - > PutCString ( data ) ;
output_sp - > Flush ( ) ;
RefreshTopIOHandler ( ) ;
}
}
}
}
}
if ( m_forward_listener_sp )
m_forward_listener_sp - > AddEvent ( event_sp ) ;
}
}
}
}
lldb : : thread_result_t
Debugger : : EventHandlerThread ( lldb : : thread_arg_t arg )
{
( ( Debugger * ) arg ) - > DefaultEventHandler ( ) ;
return NULL ;
}
bool
Debugger : : StartEventHandlerThread ( )
{
2014-09-24 02:32:09 +08:00
if ( ! m_event_handler_thread . IsJoinable ( ) )
2014-10-16 02:03:59 +08:00
{
2014-12-02 06:41:27 +08:00
// We must synchronize with the DefaultEventHandler() thread to ensure
// it is up and running and listening to events before we return from
// this function. We do this by listening to events for the
// eBroadcastBitEventThreadIsListening from the m_sync_broadcaster
Listener listener ( " lldb.debugger.event-handler " ) ;
listener . StartListeningForEvents ( & m_sync_broadcaster , eBroadcastBitEventThreadIsListening ) ;
2014-10-25 06:06:29 +08:00
// Use larger 8MB stack for this thread
2014-12-02 06:41:27 +08:00
m_event_handler_thread = ThreadLauncher : : LaunchThread ( " lldb.debugger.event-handler " , EventHandlerThread ,
this ,
NULL ,
2014-10-25 06:06:29 +08:00
g_debugger_event_thread_stack_bytes ) ;
2014-12-02 06:41:27 +08:00
// Make sure DefaultEventHandler() is running and listening to events before we return
// from this function. We are only listening for events of type
// eBroadcastBitEventThreadIsListening so we don't need to check the event, we just need
// to wait an infinite amount of time for it (NULL timeout as the first parameter)
lldb : : EventSP event_sp ;
listener . WaitForEvent ( NULL , event_sp ) ;
2014-10-16 02:03:59 +08:00
}
2014-09-24 02:32:09 +08:00
return m_event_handler_thread . IsJoinable ( ) ;
2014-01-28 07:43:24 +08:00
}
void
Debugger : : StopEventHandlerThread ( )
{
2014-09-24 02:32:09 +08:00
if ( m_event_handler_thread . IsJoinable ( ) )
2014-01-28 07:43:24 +08:00
{
GetCommandInterpreter ( ) . BroadcastEvent ( CommandInterpreter : : eBroadcastBitQuitCommandReceived ) ;
2014-09-10 04:54:56 +08:00
m_event_handler_thread . Join ( nullptr ) ;
2014-01-28 07:43:24 +08:00
}
}
lldb : : thread_result_t
Debugger : : IOHandlerThread ( lldb : : thread_arg_t arg )
{
Debugger * debugger = ( Debugger * ) arg ;
debugger - > ExecuteIOHanders ( ) ;
debugger - > StopEventHandlerThread ( ) ;
return NULL ;
}
bool
Debugger : : StartIOHandlerThread ( )
{
2014-09-24 02:32:09 +08:00
if ( ! m_io_handler_thread . IsJoinable ( ) )
2014-10-16 02:03:59 +08:00
m_io_handler_thread = ThreadLauncher : : LaunchThread ( " lldb.debugger.io-handler " ,
IOHandlerThread ,
this ,
NULL ,
8 * 1024 * 1024 ) ; // Use larger 8MB stack for this thread
2014-09-24 02:32:09 +08:00
return m_io_handler_thread . IsJoinable ( ) ;
2014-01-28 07:43:24 +08:00
}
void
Debugger : : StopIOHandlerThread ( )
{
2014-09-24 02:32:09 +08:00
if ( m_io_handler_thread . IsJoinable ( ) )
2014-01-28 07:43:24 +08:00
{
if ( m_input_file_sp )
m_input_file_sp - > GetFile ( ) . Close ( ) ;
2014-09-10 04:54:56 +08:00
m_io_handler_thread . Join ( nullptr ) ;
2014-01-28 07:43:24 +08:00
}
}
2014-11-22 09:42:44 +08:00
Target *
Debugger : : GetDummyTarget ( )
{
return m_target_list . GetDummyTarget ( * this ) . get ( ) ;
}
Target *
2014-12-06 09:28:03 +08:00
Debugger : : GetSelectedOrDummyTarget ( bool prefer_dummy )
2014-11-22 09:42:44 +08:00
{
2014-12-06 09:28:03 +08:00
Target * target = nullptr ;
if ( ! prefer_dummy )
{
target = m_target_list . GetSelectedTarget ( ) . get ( ) ;
if ( target )
return target ;
}
2014-11-22 09:42:44 +08:00
return GetDummyTarget ( ) ;
}
2014-01-28 07:43:24 +08:00