[Lldb-commits] [lldb] r160119 - in /lldb/branches/apple/python-GIL: ./ examples/darwin/heap_find/ examples/darwin/heap_find/heap/ include/lldb/Core/ include/lldb/Symbol/ include/lldb/Target/ source/Commands/ source/Core/ source/Interpreter/ source/Plugins/ABI/MacOSX-arm/ source/Plugins/Process/gdb-remote/ source/Symbol/ source/Target/ tools/driver/

Filipe Cabecinhas me at filcab.net
Thu Jul 12 02:33:45 PDT 2012


Author: filcab
Date: Thu Jul 12 04:33:44 2012
New Revision: 160119

URL: http://llvm.org/viewvc/llvm-project?rev=160119&view=rev
Log:
Merge changes from ToT trunk.

Modified:
    lldb/branches/apple/python-GIL/   (props changed)
    lldb/branches/apple/python-GIL/examples/darwin/heap_find/heap.py
    lldb/branches/apple/python-GIL/examples/darwin/heap_find/heap/heap_find.cpp
    lldb/branches/apple/python-GIL/include/lldb/Core/Address.h
    lldb/branches/apple/python-GIL/include/lldb/Core/ConnectionFileDescriptor.h
    lldb/branches/apple/python-GIL/include/lldb/Symbol/DWARFCallFrameInfo.h
    lldb/branches/apple/python-GIL/include/lldb/Symbol/UnwindTable.h
    lldb/branches/apple/python-GIL/include/lldb/Target/StackFrame.h
    lldb/branches/apple/python-GIL/include/lldb/Target/StackFrameList.h
    lldb/branches/apple/python-GIL/include/lldb/Target/Thread.h
    lldb/branches/apple/python-GIL/source/Commands/CommandObjectFrame.cpp
    lldb/branches/apple/python-GIL/source/Commands/CommandObjectMemory.cpp
    lldb/branches/apple/python-GIL/source/Commands/CommandObjectTarget.cpp
    lldb/branches/apple/python-GIL/source/Core/Address.cpp
    lldb/branches/apple/python-GIL/source/Core/ConnectionFileDescriptor.cpp
    lldb/branches/apple/python-GIL/source/Core/DataExtractor.cpp
    lldb/branches/apple/python-GIL/source/Core/Debugger.cpp
    lldb/branches/apple/python-GIL/source/Core/Listener.cpp
    lldb/branches/apple/python-GIL/source/Interpreter/CommandInterpreter.cpp
    lldb/branches/apple/python-GIL/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp
    lldb/branches/apple/python-GIL/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
    lldb/branches/apple/python-GIL/source/Symbol/DWARFCallFrameInfo.cpp
    lldb/branches/apple/python-GIL/source/Symbol/UnwindTable.cpp
    lldb/branches/apple/python-GIL/source/Target/Process.cpp
    lldb/branches/apple/python-GIL/source/Target/StackFrame.cpp
    lldb/branches/apple/python-GIL/source/Target/StackFrameList.cpp
    lldb/branches/apple/python-GIL/source/Target/Thread.cpp
    lldb/branches/apple/python-GIL/tools/driver/IOChannel.cpp

Propchange: lldb/branches/apple/python-GIL/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Thu Jul 12 04:33:44 2012
@@ -1 +1 @@
-/lldb/trunk:156467-159975
+/lldb/trunk:156467-160100

Modified: lldb/branches/apple/python-GIL/examples/darwin/heap_find/heap.py
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/apple/python-GIL/examples/darwin/heap_find/heap.py?rev=160119&r1=160118&r2=160119&view=diff
==============================================================================
--- lldb/branches/apple/python-GIL/examples/darwin/heap_find/heap.py (original)
+++ lldb/branches/apple/python-GIL/examples/darwin/heap_find/heap.py Thu Jul 12 04:33:44 2012
@@ -13,6 +13,7 @@
 import optparse
 import os
 import os.path
+import re
 import shlex
 import string
 import tempfile
@@ -112,14 +113,24 @@
                 member_list.append(member)
                 get_member_types_for_offset (member.type, offset - member_byte_offset, member_list)
                 return
+
+def append_regex_callback(option, opt, value, parser):
+    try:
+        ivar_regex = re.compile(value)
+        parser.values.ivar_regex_blacklist.append(ivar_regex)
+    except:
+        print 'error: an exception was thrown when compiling the ivar regular expression for "%s"' % value
     
 def add_common_options(parser):
     parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False)
+    parser.add_option('-t', '--type', action='store_true', dest='print_type', help='print the full value of the type for each matching malloc block', default=False)
     parser.add_option('-o', '--po', action='store_true', dest='print_object_description', help='print the object descriptions for any matches', default=False)
     parser.add_option('-m', '--memory', action='store_true', dest='memory', help='dump the memory for each matching block', default=False)
     parser.add_option('-f', '--format', type='string', dest='format', help='the format to use when dumping memory if --memory is specified', default=None)
+    parser.add_option('-I', '--omit-ivar-regex', type='string', action='callback', callback=append_regex_callback, dest='ivar_regex_blacklist', default=[], help='specify one or more regular expressions used to backlist any matches that are in ivars')
     parser.add_option('-s', '--stack', action='store_true', dest='stack', help='gets the stack that allocated each malloc block if MallocStackLogging is enabled', default=False)
     parser.add_option('-S', '--stack-history', action='store_true', dest='stack_history', help='gets the stack history for all allocations whose start address matches each malloc block if MallocStackLogging is enabled', default=False)
+    parser.add_option('-M', '--max-matches', type='int', dest='max_matches', help='the maximum number of matches to print', default=256)
 
 def dump_stack_history_entry(stack_history_entry, idx):
     address = int(stack_history_entry.address)
@@ -172,43 +183,21 @@
                 dump_stack_history_entry(stack_history_entry, idx)
                 idx = idx + 1
                 stack_history_entry = expr_value[idx]
-        else:
-            print 'error: expression returned => %s' % (expr_sbvalue)
     else:
         print 'error: expression failed "%s" => %s' % (expr, expr_sbvalue.error)
     
-    
-def heap_search(options, arg_str):
-    dylid_load_err = load_dylib()
-    if dylid_load_err:
-        print dylid_load_err
-        return
-    expr = None
-    arg_str_description = arg_str
-    default_memory_format = "Y" # 'Y' is "bytes with ASCII" format
-    #memory_chunk_size = 1
-    if options.type == 'pointer':
-        expr = 'find_pointer_in_heap((void *)%s)' % (arg_str)
-        arg_str_description = 'malloc block containing pointer %s' % arg_str
-        default_memory_format = "A" # 'A' is "address" format
-        #memory_chunk_size = lldb.process.GetAddressByteSize()
-    elif options.type == 'cstr':
-        expr = 'find_cstring_in_heap("%s")' % arg_str
-        arg_str_description = 'malloc block containing "%s"' % arg_str
-    elif options.type == 'addr':
-        expr = 'find_block_for_address((void *)%s)' % arg_str
-        arg_str_description = 'malloc block for %s' % arg_str
-    else:
-        print 'error: invalid type "%s"\nvalid values are "pointer", "cstr"' % options.type
-        return
-    
-    expr_sbvalue = lldb.frame.EvaluateExpression (expr)
+
+def display_match_results (options, arg_str_description, expr_sbvalue, print_no_matches = True):
     if expr_sbvalue.error.Success():
         if expr_sbvalue.unsigned:
             match_value = lldb.value(expr_sbvalue)  
             i = 0
             while 1:
+                print_entry = True
                 match_entry = match_value[i]; i += 1
+                if i >= options.max_matches:
+                    print 'error: the max number of matches (%u) was reached, use the --max-matches option to get more results' % (options.max_matches)
+                    break
                 malloc_addr = match_entry.addr.sbvalue.unsigned
                 if malloc_addr == 0:
                     break
@@ -220,13 +209,13 @@
                 if offset != 0:
                     description += ' + %u' % (offset)
                 description += ', size = %u' % (malloc_size)
+                derefed_dynamic_value = None
                 if dynamic_value.type.name == 'void *':
                     if options.type == 'pointer' and malloc_size == 4096:
                         error = lldb.SBError()
                         data = bytearray(lldb.process.ReadMemory(malloc_addr, 16, error))
                         if data == '\xa1\xa1\xa1\xa1AUTORELEASE!':
                             description += ', type = (AUTORELEASE!)'
-                    print description
                 else:
                     derefed_dynamic_value = dynamic_value.deref
                     if derefed_dynamic_value:                        
@@ -246,32 +235,61 @@
                                             member_path += '.'
                                         member_path += member_name
                                 if member_path:
+                                    if options.ivar_regex_blacklist:
+                                        for ivar_regex in options.ivar_regex_blacklist:
+                                            if ivar_regex.match(member_path):
+                                                print_entry = False
                                     description += ', ivar = %s' % (member_path)
-                            print description
-                            if derefed_dynamic_value:
-                                print derefed_dynamic_value
-                            if options.print_object_description:
-                                desc = dynamic_value.GetObjectDescription()
-                                if desc:
-                                    print '  (%s) 0x%x %s\n' % (type_name, malloc_addr, desc)
-                if options.memory:
-                    memory_format = options.format
-                    if not memory_format:
-                        memory_format = default_memory_format
-                    cmd_result = lldb.SBCommandReturnObject()
-                    #count = malloc_size / memory_chunk_size
-                    memory_command = "memory read -f %s 0x%x 0x%x" % (memory_format, malloc_addr, malloc_addr + malloc_size)
-                    lldb.debugger.GetCommandInterpreter().HandleCommand(memory_command, cmd_result)
-                    print cmd_result.GetOutput()
-                if options.stack_history:
-                    dump_stack_history_entries(malloc_addr, 1)
-                elif options.stack:
-                    dump_stack_history_entries(malloc_addr, 0)
-        else:
-            print '%s %s was not found in any malloc blocks' % (options.type, arg_str)
+                if print_entry:
+                    if description:
+                        print description
+                        if options.print_type and derefed_dynamic_value:
+                            print derefed_dynamic_value
+                        if options.print_object_description and dynamic_value:
+                            desc = dynamic_value.GetObjectDescription()
+                            if desc:
+                                print '  (%s) 0x%x %s\n' % (type_name, malloc_addr, desc)
+                    if options.memory:
+                        cmd_result = lldb.SBCommandReturnObject()
+                        memory_command = "memory read -f %s 0x%x 0x%x" % (options.format, malloc_addr, malloc_addr + malloc_size)
+                        lldb.debugger.GetCommandInterpreter().HandleCommand(memory_command, cmd_result)
+                        print cmd_result.GetOutput()
+                    if options.stack_history:
+                        dump_stack_history_entries(malloc_addr, 1)
+                    elif options.stack:
+                        dump_stack_history_entries(malloc_addr, 0)
+            return i
+        elif print_no_matches:
+            print 'no matches found for %s' % (arg_str_description)
     else:
         print expr_sbvalue.error
-    print     
+    return 0
+    
+def heap_search(options, arg_str):
+    dylid_load_err = load_dylib()
+    if dylid_load_err:
+        print dylid_load_err
+        return
+    expr = None
+    arg_str_description = arg_str
+    if options.format == None: 
+        options.format = "Y" # 'Y' is "bytes with ASCII" format
+    if options.type == 'pointer':
+        expr = 'find_pointer_in_heap((void *)%s)' % (arg_str)
+        arg_str_description = 'malloc block containing pointer %s' % arg_str
+        if options.format == None: 
+            options.format = "A" # 'A' is "address" format
+    elif options.type == 'cstr':
+        expr = 'find_cstring_in_heap("%s")' % arg_str
+        arg_str_description = 'malloc block containing "%s"' % arg_str
+    elif options.type == 'addr':
+        expr = 'find_block_for_address((void *)%s)' % arg_str
+        arg_str_description = 'malloc block for %s' % arg_str
+    else:
+        print 'error: invalid type "%s"\nvalid values are "pointer", "cstr"' % options.type
+        return
+    
+    display_match_results (options, arg_str_description, lldb.frame.EvaluateExpression (expr))
     
 def ptr_refs(debugger, command, result, dict):
     command_args = shlex.split(command)
@@ -366,6 +384,52 @@
         else:
             print 'error: no address expressions were specified'
 
+def section_ptr_refs(debugger, command, result, dict):
+    command_args = shlex.split(command)
+    usage = "usage: %prog [options] <EXPR> [EXPR ...]"
+    description='''Searches section contents for pointer values in darwin user space programs.'''
+    parser = optparse.OptionParser(description=description, prog='section_ptr_refs',usage=usage)
+    add_common_options(parser)
+    parser.add_option('--section', action='append', type='string', dest='section_names', help='section name to search', default=list())
+    try:
+        (options, args) = parser.parse_args(command_args)
+    except:
+        return
+
+    options.type = 'pointer'
+    
+    sections = list()
+    section_modules = list()
+    if not options.section_names:
+        print 'error: at least one section must be specified with the --section option'
+        return
+
+    for module in lldb.target.modules:
+        for section_name in options.section_names:
+            section = module.section[section_name]
+            if section:
+                sections.append (section)
+                section_modules.append (module)
+    if sections:
+        dylid_load_err = load_dylib()
+        if dylid_load_err:
+            print dylid_load_err
+            return
+        for expr_str in args:
+            for (idx, section) in enumerate(sections):
+                expr = 'find_pointer_in_memory(0x%xllu, %ullu, (void *)%s)' % (section.addr.load_addr, section.size, expr_str)
+                arg_str_description = 'section %s.%s containing "%s"' % (section_modules[idx].file.fullpath, section.name, expr_str)
+                num_matches = display_match_results (options, arg_str_description, lldb.frame.EvaluateExpression (expr), False)
+                if num_matches:
+                    if num_matches < options.max_matches:
+                        options.max_matches = options.max_matches - num_matches
+                    else:
+                        options.max_matches = 0
+                if options.max_matches == 0:
+                    return
+    else:
+        print 'error: no sections were found that match any of %s' % (', '.join(options.section_names))
+
 if __name__ == '__main__':
     lldb.debugger = lldb.SBDebugger.Create()
 
@@ -375,7 +439,8 @@
 lldb.debugger.HandleCommand('command script add -f lldb.macosx.heap.cstr_refs cstr_refs')
 lldb.debugger.HandleCommand('command script add -f lldb.macosx.heap.malloc_info malloc_info')
 lldb.debugger.HandleCommand('command script add -f lldb.macosx.heap.malloc_history malloc_history')
-print '"ptr_refs", "cstr_refs", "malloc_info", and "malloc_history" commands have been installed, use the "--help" options on these commands for detailed help.'
+lldb.debugger.HandleCommand('command script add -f lldb.macosx.heap.section_ptr_refs section_ptr_refs')
+print '"ptr_refs", "cstr_refs", "malloc_info", "malloc_history" and "section_ptr_refs" commands have been installed, use the "--help" options on these commands for detailed help.'
 
 
 

Modified: lldb/branches/apple/python-GIL/examples/darwin/heap_find/heap/heap_find.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/apple/python-GIL/examples/darwin/heap_find/heap/heap_find.cpp?rev=160119&r1=160118&r2=160119&view=diff
==============================================================================
--- lldb/branches/apple/python-GIL/examples/darwin/heap_find/heap/heap_find.cpp (original)
+++ lldb/branches/apple/python-GIL/examples/darwin/heap_find/heap/heap_find.cpp Thu Jul 12 04:33:44 2012
@@ -416,6 +416,33 @@
     return g_matches.data();
 }
 
+//----------------------------------------------------------------------
+// find_pointer_in_memory
+//
+// Finds a pointer value inside one or more currently valid malloc
+// blocks.
+//----------------------------------------------------------------------
+malloc_match *
+find_pointer_in_memory (uint64_t memory_addr, uint64_t memory_size, const void * addr)
+{
+    g_matches.clear();
+    // Setup "info" to look for a malloc block that contains data
+    // that is the a pointer 
+    range_contains_data_callback_info_t data_info;
+    data_info.type = eDataTypeContainsData;      // Check each block for data
+    g_lookup_addr = addr;
+    data_info.data.buffer = (uint8_t *)&addr;    // What data? The pointer value passed in
+    data_info.data.size = sizeof(addr);          // How many bytes? The byte size of a pointer
+    data_info.data.align = sizeof(addr);         // Align to a pointer byte size
+    data_info.match_count = 0;                   // Initialize the match count to zero
+    data_info.done = false;                      // Set done to false so searching doesn't stop
+    range_info_callback (mach_task_self(), &data_info, stack_logging_type_generic, memory_addr, memory_size);
+    if (g_matches.empty())
+        return NULL;
+    malloc_match match = { NULL, 0, 0 };
+    g_matches.push_back(match);
+    return g_matches.data();
+}
 
 //----------------------------------------------------------------------
 // find_cstring_in_heap

Modified: lldb/branches/apple/python-GIL/include/lldb/Core/Address.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/apple/python-GIL/include/lldb/Core/Address.h?rev=160119&r1=160118&r2=160119&view=diff
==============================================================================
--- lldb/branches/apple/python-GIL/include/lldb/Core/Address.h (original)
+++ lldb/branches/apple/python-GIL/include/lldb/Core/Address.h Thu Jul 12 04:33:44 2012
@@ -86,8 +86,10 @@
                                         ///< and file and line), to information about what the pointer points to
                                         ///< if the address is in a section (section of pointers, c strings, etc).
         DumpStyleResolvedDescriptionNoModule,
-        DumpStyleDetailedSymbolContext  ///< Detailed symbol context information for an address for all symbol
+        DumpStyleDetailedSymbolContext, ///< Detailed symbol context information for an address for all symbol
                                         ///< context members.
+        DumpStyleResolvedPointerDescription ///< Dereference a pointer at the current address and then lookup the
+                                             ///< dereferenced address using DumpStyleResolvedDescription
     } DumpStyle;
 
     //------------------------------------------------------------------

Modified: lldb/branches/apple/python-GIL/include/lldb/Core/ConnectionFileDescriptor.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/apple/python-GIL/include/lldb/Core/ConnectionFileDescriptor.h?rev=160119&r1=160118&r2=160119&view=diff
==============================================================================
--- lldb/branches/apple/python-GIL/include/lldb/Core/ConnectionFileDescriptor.h (original)
+++ lldb/branches/apple/python-GIL/include/lldb/Core/ConnectionFileDescriptor.h Thu Jul 12 04:33:44 2012
@@ -20,6 +20,7 @@
 // Project includes
 #include "lldb/Core/Connection.h"
 #include "lldb/Host/Mutex.h"
+#include "lldb/Host/Predicate.h"
 #include "lldb/Host/SocketAddress.h"
 
 namespace lldb_private {
@@ -70,6 +71,12 @@
 
 protected:
     
+    void
+    InitializeCommandFileDescriptor ();
+    
+    void
+    CloseCommandFileDescriptor ();
+
     lldb::ConnectionStatus
     BytesAvailable (uint32_t timeout_usec, Error *error_ptr);
     
@@ -105,6 +112,8 @@
     SocketAddress m_udp_send_sockaddr;
     bool m_should_close_fd; // True if this class should close the file descriptor when it goes away.
     uint32_t m_socket_timeout_usec;
+    int m_command_fd_send;        // A pipe that we select on the reading end of along with
+    int m_command_fd_receive;     // m_fd_recv so we can force ourselves out of the select.
     Mutex m_mutex;
     
     static in_port_t

Modified: lldb/branches/apple/python-GIL/include/lldb/Symbol/DWARFCallFrameInfo.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/apple/python-GIL/include/lldb/Symbol/DWARFCallFrameInfo.h?rev=160119&r1=160118&r2=160119&view=diff
==============================================================================
--- lldb/branches/apple/python-GIL/include/lldb/Symbol/DWARFCallFrameInfo.h (original)
+++ lldb/branches/apple/python-GIL/include/lldb/Symbol/DWARFCallFrameInfo.h Thu Jul 12 04:33:44 2012
@@ -18,6 +18,7 @@
 #include "lldb/Core/AddressRange.h"
 #include "lldb/Core/VMRange.h"
 #include "lldb/Core/dwarf.h"
+#include "lldb/Host/Mutex.h"
 #include "lldb/Symbol/UnwindPlan.h"
 #include "lldb/Symbol/ObjectFile.h"
 
@@ -128,6 +129,7 @@
 
     std::vector<FDEEntry>       m_fde_index;
     bool                        m_fde_index_initialized;  // only scan the section for FDEs once
+    Mutex                       m_fde_index_mutex;        // and isolate the thread that does it
 
     bool                        m_is_eh_frame;
 

Modified: lldb/branches/apple/python-GIL/include/lldb/Symbol/UnwindTable.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/apple/python-GIL/include/lldb/Symbol/UnwindTable.h?rev=160119&r1=160118&r2=160119&view=diff
==============================================================================
--- lldb/branches/apple/python-GIL/include/lldb/Symbol/UnwindTable.h (original)
+++ lldb/branches/apple/python-GIL/include/lldb/Symbol/UnwindTable.h Thu Jul 12 04:33:44 2012
@@ -33,6 +33,15 @@
     lldb::FuncUnwindersSP
     GetFuncUnwindersContainingAddress (const Address& addr, SymbolContext &sc);
 
+// Normally when we create a new FuncUnwinders object we track it in this UnwindTable so it can
+// be reused later.  But for the target modules show-unwind we want to create brand new 
+// UnwindPlans for the function of interest - so ignore any existing FuncUnwinders for that
+// function and don't add this new one to our UnwindTable.
+// This FuncUnwinders object does have a reference to the UnwindTable but the lifetime of this
+// uncached FuncUnwinders is expected to be short so in practice this will not be a problem.
+    lldb::FuncUnwindersSP
+    GetUncachedFuncUnwindersContainingAddress (const Address& addr, SymbolContext &sc);
+
 private:
     void
     Dump (Stream &s);

Modified: lldb/branches/apple/python-GIL/include/lldb/Target/StackFrame.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/apple/python-GIL/include/lldb/Target/StackFrame.h?rev=160119&r1=160118&r2=160119&view=diff
==============================================================================
--- lldb/branches/apple/python-GIL/include/lldb/Target/StackFrame.h (original)
+++ lldb/branches/apple/python-GIL/include/lldb/Target/StackFrame.h Thu Jul 12 04:33:44 2012
@@ -167,9 +167,7 @@
     bool
     GetStatus (Stream &strm,
                bool show_frame_info,
-               bool show_source,
-               uint32_t source_lines_before,
-               uint32_t source_lines_after);
+               bool show_source);
     
 protected:
     friend class StackFrameList;

Modified: lldb/branches/apple/python-GIL/include/lldb/Target/StackFrameList.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/apple/python-GIL/include/lldb/Target/StackFrameList.h?rev=160119&r1=160118&r2=160119&view=diff
==============================================================================
--- lldb/branches/apple/python-GIL/include/lldb/Target/StackFrameList.h (original)
+++ lldb/branches/apple/python-GIL/include/lldb/Target/StackFrameList.h Thu Jul 12 04:33:44 2012
@@ -76,9 +76,7 @@
                uint32_t first_frame,
                uint32_t num_frames,
                bool show_frame_info,
-               uint32_t num_frames_with_source,
-               uint32_t source_lines_before,
-               uint32_t source_lines_after);
+               uint32_t num_frames_with_source);
     
 protected:
 

Modified: lldb/branches/apple/python-GIL/include/lldb/Target/Thread.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/apple/python-GIL/include/lldb/Target/Thread.h?rev=160119&r1=160118&r2=160119&view=diff
==============================================================================
--- lldb/branches/apple/python-GIL/include/lldb/Target/Thread.h (original)
+++ lldb/branches/apple/python-GIL/include/lldb/Target/Thread.h Thu Jul 12 04:33:44 2012
@@ -762,9 +762,7 @@
                          uint32_t first_frame,
                          uint32_t num_frames,
                          bool show_frame_info,
-                         uint32_t num_frames_with_source,
-                         uint32_t source_lines_before,
-                         uint32_t source_lines_after);
+                         uint32_t num_frames_with_source);
 
     // We need a way to verify that even though we have a thread in a shared
     // pointer that the object itself is still valid. Currently this won't be

Modified: lldb/branches/apple/python-GIL/source/Commands/CommandObjectFrame.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/apple/python-GIL/source/Commands/CommandObjectFrame.cpp?rev=160119&r1=160118&r2=160119&view=diff
==============================================================================
--- lldb/branches/apple/python-GIL/source/Commands/CommandObjectFrame.cpp (original)
+++ lldb/branches/apple/python-GIL/source/Commands/CommandObjectFrame.cpp Thu Jul 12 04:33:44 2012
@@ -282,14 +282,7 @@
 
                     bool show_frame_info = true;
                     bool show_source = !already_shown;
-                    Debugger &debugger = m_interpreter.GetDebugger();
-                    const uint32_t source_lines_before = debugger.GetStopSourceLineCount(true);
-                    const uint32_t source_lines_after = debugger.GetStopSourceLineCount(false);
-                    if (frame->GetStatus (result.GetOutputStream(),
-                                          show_frame_info,
-                                          show_source,
-                                          source_lines_before,
-                                          source_lines_after))
+                    if (frame->GetStatus (result.GetOutputStream(), show_frame_info, show_source))
                     {
                         result.SetStatus (eReturnStatusSuccessFinishResult);
                         return result.Succeeded();

Modified: lldb/branches/apple/python-GIL/source/Commands/CommandObjectMemory.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/apple/python-GIL/source/Commands/CommandObjectMemory.cpp?rev=160119&r1=160118&r2=160119&view=diff
==============================================================================
--- lldb/branches/apple/python-GIL/source/Commands/CommandObjectMemory.cpp (original)
+++ lldb/branches/apple/python-GIL/source/Commands/CommandObjectMemory.cpp Thu Jul 12 04:33:44 2012
@@ -398,19 +398,52 @@
             uint32_t reference_count = 0;
             uint32_t pointer_count = 0;
             size_t idx;
-            static const char *g_keywords[] = { "const", "volatile", "restrict", "struct", "class", "union"};
-            static size_t g_num_keywords = sizeof(g_keywords)/sizeof(const char *);
+            
+#define ALL_KEYWORDS        \
+    KEYWORD("const")        \
+    KEYWORD("volatile")     \
+    KEYWORD("restrict")     \
+    KEYWORD("struct")       \
+    KEYWORD("class")        \
+    KEYWORD("union")
+            
+#define KEYWORD(s) s,
+            static const char *g_keywords[] =
+            {
+                ALL_KEYWORDS
+            };
+#undef KEYWORD
+
+#define KEYWORD(s) (sizeof(s) - 1),
+            static const int g_keyword_lengths[] =
+            {
+                ALL_KEYWORDS
+            };
+#undef KEYWORD
+            
+#undef ALL_KEYWORDS
+            
+            static size_t g_num_keywords = sizeof(g_keywords) / sizeof(const char *);
             std::string type_str(view_as_type_cstr);
             
             // Remove all instances of g_keywords that are followed by spaces
             for (size_t i = 0; i < g_num_keywords; ++i)
             {
                 const char *keyword = g_keywords[i];
-                int keyword_len = ::strlen (keyword);
-                while ((idx = type_str.find (keyword)) != std::string::npos)
+                int keyword_len = g_keyword_lengths[i];
+                
+                idx = 0;
+                while ((idx = type_str.find (keyword, idx)) != std::string::npos)
                 {
                     if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t')
+                    {
                         type_str.erase(idx, keyword_len+1);
+                        idx = 0;
+                    }
+                    else
+                    {
+                        idx += keyword_len;
+                    }
                 }
             }
             bool done = type_str.empty();

Modified: lldb/branches/apple/python-GIL/source/Commands/CommandObjectTarget.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/apple/python-GIL/source/Commands/CommandObjectTarget.cpp?rev=160119&r1=160118&r2=160119&view=diff
==============================================================================
--- lldb/branches/apple/python-GIL/source/Commands/CommandObjectTarget.cpp (original)
+++ lldb/branches/apple/python-GIL/source/Commands/CommandObjectTarget.cpp Thu Jul 12 04:33:44 2012
@@ -34,10 +34,12 @@
 #include "lldb/Interpreter/OptionGroupUInt64.h"
 #include "lldb/Interpreter/OptionGroupUUID.h"
 #include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
+#include "lldb/Symbol/FuncUnwinders.h"
 #include "lldb/Symbol/LineTable.h"
 #include "lldb/Symbol/ObjectFile.h"
 #include "lldb/Symbol/SymbolFile.h"
 #include "lldb/Symbol/SymbolVendor.h"
+#include "lldb/Symbol/UnwindPlan.h"
 #include "lldb/Symbol/VariableList.h"
 #include "lldb/Target/Process.h"
 #include "lldb/Target/StackFrame.h"
@@ -1743,27 +1745,7 @@
     
     const size_t initial_size = module_list.GetSize ();
 
-    size_t num_matches = 0;
-    
-    if (target)
-    {
-        num_matches = target->GetImages().FindModules (module_spec, module_list);
-    
-        // Not found in our module list for our target, check the main
-        // shared module list in case it is a extra file used somewhere
-        // else
-        if (num_matches == 0)
-        {
-            module_spec.GetArchitecture() = target->GetArchitecture();
-            num_matches = ModuleList::FindSharedModules (module_spec, module_list);
-        }
-    }
-    else
-    {
-        num_matches = ModuleList::FindSharedModules (module_spec,module_list);
-    }
-    
-    if (check_global_list && num_matches == 0)
+    if (check_global_list)
     {
         // Check the global list
         Mutex::Locker locker(Module::GetAllocationModuleCollectionMutex());
@@ -1783,6 +1765,27 @@
             }
         }
     }
+    else
+    {
+        if (target)
+        {
+            const size_t num_matches = target->GetImages().FindModules (module_spec, module_list);
+        
+            // Not found in our module list for our target, check the main
+            // shared module list in case it is a extra file used somewhere
+            // else
+            if (num_matches == 0)
+            {
+                module_spec.GetArchitecture() = target->GetArchitecture();
+                ModuleList::FindSharedModules (module_spec, module_list);
+            }
+        }
+        else
+        {
+            ModuleList::FindSharedModules (module_spec,module_list);
+        }
+    }
+    
     return module_list.GetSize () - initial_size;
 }
 
@@ -3205,7 +3208,241 @@
     { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
 };
 
+#pragma mark CommandObjectTargetModulesShowUnwind
 
+//----------------------------------------------------------------------
+// Lookup unwind information in images
+//----------------------------------------------------------------------
+
+class CommandObjectTargetModulesShowUnwind : public CommandObjectParsed
+{
+public:
+
+    enum
+    {
+        eLookupTypeInvalid = -1,
+        eLookupTypeAddress = 0,
+        eLookupTypeSymbol,
+        eLookupTypeFunction,
+        eLookupTypeFunctionOrSymbol,
+        kNumLookupTypes
+    };
+
+    class CommandOptions : public Options
+    {
+    public:
+
+        CommandOptions (CommandInterpreter &interpreter) :
+        Options(interpreter),
+        m_type(eLookupTypeInvalid),
+        m_str(),
+        m_addr(LLDB_INVALID_ADDRESS)
+        {
+        }
+
+        virtual
+        ~CommandOptions ()
+        {
+        }
+
+        virtual Error
+        SetOptionValue (uint32_t option_idx, const char *option_arg)
+        {
+            Error error;
+
+            char short_option = (char) m_getopt_table[option_idx].val;
+
+            switch (short_option)
+            {
+                case 'a':
+                    m_type = eLookupTypeAddress;
+                    m_addr = Args::StringToUInt64(option_arg, LLDB_INVALID_ADDRESS);
+                    if (m_addr == LLDB_INVALID_ADDRESS)
+                        error.SetErrorStringWithFormat ("invalid address string '%s'", option_arg);
+                    break;
+
+                case 'n':
+                    m_str = option_arg;
+                    m_type = eLookupTypeFunctionOrSymbol;
+                    break;
+            }
+
+            return error;
+        }
+
+        void
+        OptionParsingStarting ()
+        {
+            m_type = eLookupTypeInvalid;
+            m_str.clear();
+            m_addr = LLDB_INVALID_ADDRESS;
+        }
+
+        const OptionDefinition*
+        GetDefinitions ()
+        {
+            return g_option_table;
+        }
+
+        // Options table: Required for subclasses of Options.
+
+        static OptionDefinition g_option_table[];
+
+        // Instance variables to hold the values for command options.
+
+        int             m_type;         // Should be a eLookupTypeXXX enum after parsing options
+        std::string     m_str;          // Holds name lookup
+        lldb::addr_t    m_addr;         // Holds the address to lookup
+    };
+    
+    CommandObjectTargetModulesShowUnwind (CommandInterpreter &interpreter) :
+        CommandObjectParsed (interpreter,
+                             "target modules show-unwind",
+                             "Show synthesized unwind instructions for a function.",
+                             NULL),
+        m_options (interpreter)
+    {
+    }
+    
+    virtual
+    ~CommandObjectTargetModulesShowUnwind ()
+    {
+    }
+    
+    virtual
+    Options *
+    GetOptions ()
+    {
+        return &m_options;
+    }
+
+protected:
+    bool
+    DoExecute (Args& command,
+             CommandReturnObject &result)
+    {
+        Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
+        if (!target)
+        {
+            result.AppendError ("invalid target, create a debug target using the 'target create' command");
+            result.SetStatus (eReturnStatusFailed);
+            return false;
+        }
+
+        ExecutionContext exe_ctx = m_interpreter.GetDebugger().GetSelectedExecutionContext();
+        Process *process = exe_ctx.GetProcessPtr();
+        ABI *abi = NULL;
+        if (process)
+          abi = process->GetABI().get();
+
+        if (process == NULL)
+        {
+            result.AppendError ("You must have a process running to use this command.");
+            result.SetStatus (eReturnStatusFailed);
+            return false;
+        }
+
+        ThreadList threads(process->GetThreadList());
+        if (threads.GetSize() == 0)
+        {
+            result.AppendError ("The process must be paused to use this command.");
+            result.SetStatus (eReturnStatusFailed);
+            return false;
+        }
+
+        ThreadSP thread(threads.GetThreadAtIndex(0));
+        if (thread.get() == NULL)
+        {
+            result.AppendError ("The process must be paused to use this command.");
+            result.SetStatus (eReturnStatusFailed);
+            return false;
+        }
+
+        if (m_options.m_type == eLookupTypeFunctionOrSymbol)
+        {
+            SymbolContextList sc_list;
+            uint32_t num_matches;
+            ConstString function_name (m_options.m_str.c_str());
+            num_matches = target->GetImages().FindFunctions (function_name, eFunctionNameTypeAuto, true, false, true, sc_list);
+            for (uint32_t idx = 0; idx < num_matches; idx++)
+            {
+                SymbolContext sc;
+                sc_list.GetContextAtIndex(idx, sc);
+                if (sc.symbol == NULL && sc.function == NULL)
+                    continue;
+                if (sc.module_sp.get() == NULL || sc.module_sp->GetObjectFile() == NULL)
+                    continue;
+                AddressRange range;
+                if (!sc.GetAddressRange (eSymbolContextFunction | eSymbolContextSymbol, 0, false, range))
+                    continue;
+                if (!range.GetBaseAddress().IsValid())
+                    continue;
+                ConstString funcname(sc.GetFunctionName());
+                if (funcname.IsEmpty())
+                    continue;
+                addr_t start_addr = range.GetBaseAddress().GetLoadAddress(target);
+                if (abi)
+                    start_addr = abi->FixCodeAddress(start_addr);
+
+                FuncUnwindersSP func_unwinders_sp (sc.module_sp->GetObjectFile()->GetUnwindTable().GetUncachedFuncUnwindersContainingAddress(start_addr, sc));
+                if (func_unwinders_sp.get() == NULL)
+                    continue;
+
+                Address first_non_prologue_insn (func_unwinders_sp->GetFirstNonPrologueInsn(*target));
+                if (first_non_prologue_insn.IsValid())
+                {
+                    result.GetOutputStream().Printf("First non-prologue instruction is at address 0x%llx or offset %lld into the function.\n", first_non_prologue_insn.GetLoadAddress(target), first_non_prologue_insn.GetLoadAddress(target) - start_addr);
+                    result.GetOutputStream().Printf ("\n");
+                }
+
+                UnwindPlanSP non_callsite_unwind_plan = func_unwinders_sp->GetUnwindPlanAtNonCallSite(*thread.get());
+                if (non_callsite_unwind_plan.get())
+                {
+                    result.GetOutputStream().Printf("Asynchronous (not restricted to call-sites) UnwindPlan for %s`%s (start addr 0x%llx):\n", sc.module_sp->GetPlatformFileSpec().GetFilename().AsCString(), funcname.AsCString(), start_addr);
+                    non_callsite_unwind_plan->Dump(result.GetOutputStream(), thread.get(), LLDB_INVALID_ADDRESS);
+                    result.GetOutputStream().Printf ("\n");
+                }
+
+                UnwindPlanSP callsite_unwind_plan = func_unwinders_sp->GetUnwindPlanAtCallSite(-1);
+                if (callsite_unwind_plan.get())
+                {
+                    result.GetOutputStream().Printf("Synchronous (restricted to call-sites) UnwindPlan for %s`%s (start addr 0x%llx):\n", sc.module_sp->GetPlatformFileSpec().GetFilename().AsCString(), funcname.AsCString(), start_addr);
+                    callsite_unwind_plan->Dump(result.GetOutputStream(), thread.get(), LLDB_INVALID_ADDRESS);
+                    result.GetOutputStream().Printf ("\n");
+                }
+
+                UnwindPlanSP arch_default_unwind_plan = func_unwinders_sp->GetUnwindPlanArchitectureDefault(*thread.get());
+                if (arch_default_unwind_plan.get())
+                {
+                    result.GetOutputStream().Printf("Architecture default UnwindPlan for %s`%s (start addr 0x%llx):\n", sc.module_sp->GetPlatformFileSpec().GetFilename().AsCString(), funcname.AsCString(), start_addr);
+                    arch_default_unwind_plan->Dump(result.GetOutputStream(), thread.get(), LLDB_INVALID_ADDRESS);
+                    result.GetOutputStream().Printf ("\n");
+                }
+
+                UnwindPlanSP fast_unwind_plan = func_unwinders_sp->GetUnwindPlanFastUnwind(*thread.get());
+                if (fast_unwind_plan.get())
+                {
+                    result.GetOutputStream().Printf("Fast UnwindPlan for %s`%s (start addr 0x%llx):\n", sc.module_sp->GetPlatformFileSpec().GetFilename().AsCString(), funcname.AsCString(), start_addr);
+                    fast_unwind_plan->Dump(result.GetOutputStream(), thread.get(), LLDB_INVALID_ADDRESS);
+                    result.GetOutputStream().Printf ("\n");
+                }
+
+
+                result.GetOutputStream().Printf ("\n");
+            }
+        }
+        return result.Succeeded();
+    }
+
+    CommandOptions m_options;
+};
+
+OptionDefinition
+CommandObjectTargetModulesShowUnwind::CommandOptions::g_option_table[] =
+{
+    { LLDB_OPT_SET_1,   true,  "name",       'n', required_argument, NULL, 0, eArgTypeFunctionName, "Lookup a function or symbol by name in one or more target modules."},
+    { 0,                false, NULL,           0, 0,                 NULL, 0, eArgTypeNone, NULL }
+};
 
 //----------------------------------------------------------------------
 // Lookup information in images
@@ -3720,6 +3957,7 @@
         LoadSubCommand ("list",         CommandObjectSP (new CommandObjectTargetModulesList (interpreter)));
         LoadSubCommand ("lookup",       CommandObjectSP (new CommandObjectTargetModulesLookup (interpreter)));
         LoadSubCommand ("search-paths", CommandObjectSP (new CommandObjectTargetModulesImageSearchPaths (interpreter)));
+        LoadSubCommand ("show-unwind",  CommandObjectSP (new CommandObjectTargetModulesShowUnwind (interpreter)));
 
     }
     virtual

Modified: lldb/branches/apple/python-GIL/source/Core/Address.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/apple/python-GIL/source/Core/Address.cpp?rev=160119&r1=160118&r2=160119&view=diff
==============================================================================
--- lldb/branches/apple/python-GIL/source/Core/Address.cpp (original)
+++ lldb/branches/apple/python-GIL/source/Core/Address.cpp Thu Jul 12 04:33:44 2012
@@ -354,9 +354,10 @@
 bool
 Address::Dump (Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, DumpStyle fallback_style, uint32_t addr_size) const
 {
-    // If the section was NULL, only load address is going to work.
+    // If the section was NULL, only load address is going to work unless we are
+    // trying to deref a pointer
     SectionSP section_sp (GetSection());
-    if (!section_sp)
+    if (!section_sp && style != DumpStyleResolvedPointerDescription)
         style = DumpStyleLoadAddress;
 
     ExecutionContext exe_ctx (exe_scope);
@@ -728,6 +729,37 @@
             return false;
         }
         break;
+    case DumpStyleResolvedPointerDescription:
+        {
+            Process *process = exe_ctx.GetProcessPtr();
+            if (process)
+            {
+                addr_t load_addr = GetLoadAddress (target);
+                if (load_addr != LLDB_INVALID_ADDRESS)
+                {
+                    Error memory_error;
+                    addr_t dereferenced_load_addr = process->ReadPointerFromMemory(load_addr, memory_error);
+                    if (dereferenced_load_addr != LLDB_INVALID_ADDRESS)
+                    {
+                        Address dereferenced_addr;
+                        if (dereferenced_addr.SetLoadAddress(dereferenced_load_addr, target))
+                        {
+                            StreamString strm;
+                            if (dereferenced_addr.Dump (&strm, exe_scope, DumpStyleResolvedDescription, DumpStyleInvalid, addr_size))
+                            {
+                                s->Address (dereferenced_load_addr, addr_size, " -> ", " ");
+                                s->Write(strm.GetData(), strm.GetSize());
+                                return true;
+                            }
+                        }
+                    }
+                }
+            }
+            if (fallback_style != DumpStyleInvalid)
+                return Dump (s, exe_scope, fallback_style, DumpStyleInvalid, addr_size);
+            return false;
+        }
+        break;
     }
 
     return true;

Modified: lldb/branches/apple/python-GIL/source/Core/ConnectionFileDescriptor.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/apple/python-GIL/source/Core/ConnectionFileDescriptor.cpp?rev=160119&r1=160118&r2=160119&view=diff
==============================================================================
--- lldb/branches/apple/python-GIL/source/Core/ConnectionFileDescriptor.cpp (original)
+++ lldb/branches/apple/python-GIL/source/Core/ConnectionFileDescriptor.cpp Thu Jul 12 04:33:44 2012
@@ -21,6 +21,7 @@
 #include <sys/types.h>
 #include <string.h>
 #include <stdlib.h>
+#include <unistd.h>
 
 // C++ Includes
 // Other libraries and framework includes
@@ -74,6 +75,8 @@
     m_udp_send_sockaddr (),
     m_should_close_fd (false), 
     m_socket_timeout_usec(0),
+    m_command_fd_send(-1),
+    m_command_fd_receive(-1),
     m_mutex (Mutex::eMutexTypeRecursive)
 {
     LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION |  LIBLLDB_LOG_OBJECT));
@@ -90,6 +93,8 @@
     m_udp_send_sockaddr (),
     m_should_close_fd (owns_fd),
     m_socket_timeout_usec(0),
+    m_command_fd_send(-1),
+    m_command_fd_receive(-1),
     m_mutex (Mutex::eMutexTypeRecursive)
 {
     LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION |  LIBLLDB_LOG_OBJECT));
@@ -104,6 +109,46 @@
     if (log)
         log->Printf ("%p ConnectionFileDescriptor::~ConnectionFileDescriptor ()", this);
     Disconnect (NULL);
+    CloseCommandFileDescriptor ();
+}
+
+void
+ConnectionFileDescriptor::InitializeCommandFileDescriptor ()
+{
+    CloseCommandFileDescriptor();
+    
+    LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION |  LIBLLDB_LOG_OBJECT));
+    // Make the command file descriptor here:
+    int filedes[2];
+    int result = pipe (filedes);
+    if (result != 0)
+    {
+        if (log)
+            log->Printf ("%p ConnectionFileDescriptor::ConnectionFileDescriptor () - could not make pipe: %s",
+                         this,
+                         strerror(errno));
+    }
+    else
+    {
+        m_command_fd_receive = filedes[0];
+        m_command_fd_send    = filedes[1];
+    }
+}
+
+void
+ConnectionFileDescriptor::CloseCommandFileDescriptor ()
+{
+    if (m_command_fd_receive != -1)
+    {
+        close (m_command_fd_receive);
+        m_command_fd_receive = -1;
+    }
+    
+    if (m_command_fd_send != -1)
+    {
+        close (m_command_fd_send);
+        m_command_fd_send = -1;
+    }
 }
 
 bool
@@ -120,6 +165,8 @@
     if (log)
         log->Printf ("%p ConnectionFileDescriptor::Connect (url = '%s')", this, s);
 
+    InitializeCommandFileDescriptor();
+    
     if (s && s[0])
     {
         char *end = NULL;
@@ -157,7 +204,7 @@
             if (success)
             {
                 // We have what looks to be a valid file descriptor, but we 
-                // should make it is. We currently are doing this by trying to
+                // should make sure it is. We currently are doing this by trying to
                 // get the flags from the file descriptor and making sure it 
                 // isn't a bad fd.
                 errno = 0;
@@ -239,32 +286,44 @@
     LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
     if (log)
         log->Printf ("%p ConnectionFileDescriptor::Disconnect ()", this);
-    if (m_should_close_fd == false)
-    {
-        m_fd_send = m_fd_recv = -1;
-        return eConnectionStatusSuccess;
-    }
+
     ConnectionStatus status = eConnectionStatusSuccess;
+
     if (m_fd_send >= 0 || m_fd_recv >= 0)
     {
-        if (m_fd_send == m_fd_recv)
+        if (m_should_close_fd == false)
         {
-            // Both file descriptors are the same, only close one
-            m_fd_recv = -1;
-            status = Close (m_fd_send, error_ptr);
+            m_fd_send = m_fd_recv = -1;
         }
         else
         {
-            // File descriptors are the different, close both if needed
-            if (m_fd_send >= 0)
+            if (m_fd_send == m_fd_recv)
+            {
+                // Both file descriptors are the same, only close one
+                m_fd_recv = -1;
                 status = Close (m_fd_send, error_ptr);
-            if (m_fd_recv >= 0)
+            }
+            else
             {
-                ConnectionStatus recv_status = Close (m_fd_recv, error_ptr);
-                if (status == eConnectionStatusSuccess)
-                    status = recv_status;
+                // File descriptors are the different, close both if needed
+                if (m_fd_send >= 0)
+                    status = Close (m_fd_send, error_ptr);
+                if (m_fd_recv >= 0)
+                {
+                    ConnectionStatus recv_status = Close (m_fd_recv, error_ptr);
+                    if (status == eConnectionStatusSuccess)
+                        status = recv_status;
+                }
             }
         }
+        
+        // Now write a byte to the command pipe to wake our Reader if it is stuck in read.
+        if (m_command_fd_send != -1 )
+        {
+            write (m_command_fd_send, "q", 1);
+            close (m_command_fd_send);
+            m_command_fd_send = -1;
+        }
     }
     return status;
 }
@@ -283,42 +342,13 @@
 
     ssize_t bytes_read = 0;
 
-    switch (m_fd_recv_type)
+    status = BytesAvailable (timeout_usec, error_ptr);
+    if (status == eConnectionStatusSuccess)
     {
-    case eFDTypeFile:       // Other FD requireing read/write
-        status = BytesAvailable (timeout_usec, error_ptr);
-        if (status == eConnectionStatusSuccess)
+        do
         {
-            do
-            {
-                bytes_read = ::read (m_fd_recv, dst, dst_len);
-            } while (bytes_read < 0 && errno == EINTR);
-        }
-        break;
-
-    case eFDTypeSocket:     // Socket requiring send/recv
-        if (SetSocketReceiveTimeout (timeout_usec))
-        {
-            status = eConnectionStatusSuccess;
-            do
-            {
-                bytes_read = ::recv (m_fd_recv, dst, dst_len, 0);
-            } while (bytes_read < 0 && errno == EINTR);
-        }
-        break;
-
-    case eFDTypeSocketUDP:  // Unconnected UDP socket requiring sendto/recvfrom
-        if (SetSocketReceiveTimeout (timeout_usec))
-        {
-            status = eConnectionStatusSuccess;
-            SocketAddress from (m_udp_send_sockaddr);
-            socklen_t from_len = m_udp_send_sockaddr.GetLength();
-            do
-            {
-                bytes_read = ::recvfrom (m_fd_recv, dst, dst_len, 0, (struct sockaddr *)&from, &from_len);
-            } while (bytes_read < 0 && errno == EINTR);
-        }
-        break;
+            bytes_read = ::read (m_fd_recv, dst, dst_len);
+        } while (bytes_read < 0 && errno == EINTR);
     }
 
     if (status != eConnectionStatusSuccess)
@@ -546,7 +576,9 @@
         fd_set read_fds;
         FD_ZERO (&read_fds);
         FD_SET (m_fd_recv, &read_fds);
-        int nfds = m_fd_recv + 1;
+        if (m_command_fd_receive != -1)
+            FD_SET (m_command_fd_receive, &read_fds);
+        int nfds = (m_fd_recv > m_command_fd_receive ? m_fd_recv : m_command_fd_receive) + 1;
         
         Error error;
 
@@ -594,7 +626,26 @@
         }
         else if (num_set_fds > 0)
         {
-            return eConnectionStatusSuccess;
+            if (m_command_fd_receive != -1 && FD_ISSET(m_command_fd_receive, &read_fds))
+            {
+                // We got a command to exit.  Read the data from that pipe:
+                char buffer[16];
+                ssize_t bytes_read;
+                
+                do
+                {
+                    bytes_read = ::read (m_command_fd_receive, buffer, sizeof(buffer));
+                } while (bytes_read < 0 && errno == EINTR);
+                assert (bytes_read == 1 && buffer[0] == 'q');
+                
+                if (log)
+                    log->Printf("%p ConnectionFileDescriptor::BytesAvailable() got data: %*s from the command channel.",
+                                this, (int) bytes_read, buffer);
+                
+                return eConnectionStatusEndOfFile;
+            }
+            else
+                return eConnectionStatusSuccess;
         }
     }
 

Modified: lldb/branches/apple/python-GIL/source/Core/DataExtractor.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/apple/python-GIL/source/Core/DataExtractor.cpp?rev=160119&r1=160118&r2=160119&view=diff
==============================================================================
--- lldb/branches/apple/python-GIL/source/Core/DataExtractor.cpp (original)
+++ lldb/branches/apple/python-GIL/source/Core/DataExtractor.cpp Thu Jul 12 04:33:44 2012
@@ -1737,14 +1737,21 @@
                 {
                     TargetSP target_sp (exe_scope->CalculateTarget());
                     lldb_private::Address so_addr;
-                    if (target_sp && target_sp->GetSectionLoadList().ResolveLoadAddress(addr, so_addr))
+                    if (target_sp)
                     {
-                        s->PutChar(' ');
-                        so_addr.Dump (s, 
-                                      exe_scope, 
-                                      Address::DumpStyleResolvedDescription, 
-                                      Address::DumpStyleModuleWithFileAddress);
-                        break;
+                        if (target_sp->GetSectionLoadList().ResolveLoadAddress(addr, so_addr))
+                        {
+                            s->PutChar(' ');
+                            so_addr.Dump (s,
+                                          exe_scope,
+                                          Address::DumpStyleResolvedDescription,
+                                          Address::DumpStyleModuleWithFileAddress);
+                        }
+                        else
+                        {
+                            so_addr.SetOffset(addr);
+                            so_addr.Dump (s, exe_scope, Address::DumpStyleResolvedPointerDescription);
+                        }
                     }
                 }
             }

Modified: lldb/branches/apple/python-GIL/source/Core/Debugger.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/apple/python-GIL/source/Core/Debugger.cpp?rev=160119&r1=160118&r2=160119&view=diff
==============================================================================
--- lldb/branches/apple/python-GIL/source/Core/Debugger.cpp (original)
+++ lldb/branches/apple/python-GIL/source/Core/Debugger.cpp Thu Jul 12 04:33:44 2012
@@ -2630,7 +2630,7 @@
         if (new_value != UINT32_MAX)
             m_stop_source_before_count = new_value;
         else
-            err.SetErrorStringWithFormat("invalid unsigned string value '%s' for the '%s' setting", value, StopSourceContextAfterName ().GetCString());
+            err.SetErrorStringWithFormat("invalid unsigned string value '%s' for the '%s' setting", value, StopSourceContextBeforeName ().GetCString());
     }
     else if (var_name == StopSourceContextAfterName ())
     {
@@ -2638,7 +2638,7 @@
         if (new_value != UINT32_MAX)
             m_stop_source_after_count = new_value;
         else
-            err.SetErrorStringWithFormat("invalid unsigned string value '%s' for the '%s' setting", value, StopSourceContextBeforeName ().GetCString());
+            err.SetErrorStringWithFormat("invalid unsigned string value '%s' for the '%s' setting", value, StopSourceContextAfterName ().GetCString());
     }
     else if (var_name == StopDisassemblyCountName ())
     {
@@ -2703,13 +2703,13 @@
     else if (var_name == StopSourceContextAfterName ())
     {
         StreamString strm;
-        strm.Printf ("%u", m_stop_source_before_count);
+        strm.Printf ("%u", m_stop_source_after_count);
         value.AppendString (strm.GetData());
     }
     else if (var_name == StopSourceContextBeforeName ())
     {
         StreamString strm;
-        strm.Printf ("%u", m_stop_source_after_count);
+        strm.Printf ("%u", m_stop_source_before_count);
         value.AppendString (strm.GetData());
     }
     else if (var_name == StopDisassemblyCountName ())

Modified: lldb/branches/apple/python-GIL/source/Core/Listener.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/apple/python-GIL/source/Core/Listener.cpp?rev=160119&r1=160118&r2=160119&view=diff
==============================================================================
--- lldb/branches/apple/python-GIL/source/Core/Listener.cpp (original)
+++ lldb/branches/apple/python-GIL/source/Core/Listener.cpp Thu Jul 12 04:33:44 2012
@@ -304,7 +304,11 @@
         // it so it should be okay to get the next event off the queue here - and it might
         // be useful to do that in the "DoOnRemoval".
         lock.Unlock();
-        event_sp->DoOnRemoval();
+        
+        // Don't call DoOnRemoval if you aren't removing the event...
+        if (remove)
+            event_sp->DoOnRemoval();
+            
         return true;
     }
 

Modified: lldb/branches/apple/python-GIL/source/Interpreter/CommandInterpreter.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/apple/python-GIL/source/Interpreter/CommandInterpreter.cpp?rev=160119&r1=160118&r2=160119&view=diff
==============================================================================
--- lldb/branches/apple/python-GIL/source/Interpreter/CommandInterpreter.cpp (original)
+++ lldb/branches/apple/python-GIL/source/Interpreter/CommandInterpreter.cpp Thu Jul 12 04:33:44 2012
@@ -2390,6 +2390,16 @@
 ScriptInterpreter *
 CommandInterpreter::GetScriptInterpreter ()
 {
+    // <rdar://problem/11751427>
+    // we need to protect the initialization of the script interpreter
+    // otherwise we could end up with two threads both trying to create
+    // their instance of it, and for some languages (e.g. Python)
+    // this is a bulletproof recipe for disaster!
+    // this needs to be a function-level static because multiple Debugger instances living in the same process
+    // still need to be isolated and not try to initialize Python concurrently
+    static Mutex g_interpreter_mutex(Mutex::eMutexTypeRecursive);
+    Mutex::Locker interpreter_lock(g_interpreter_mutex);
+    
     if (m_script_interpreter_ap.get() != NULL)
         return m_script_interpreter_ap.get();
     

Modified: lldb/branches/apple/python-GIL/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/apple/python-GIL/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp?rev=160119&r1=160118&r2=160119&view=diff
==============================================================================
--- lldb/branches/apple/python-GIL/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp (original)
+++ lldb/branches/apple/python-GIL/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp Thu Jul 12 04:33:44 2012
@@ -555,7 +555,6 @@
 ABIMacOSX_arm::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
 {
     uint32_t fp_reg_num = dwarf_r7; // apple uses r7 for all frames. Normal arm uses r11;
-    uint32_t sp_reg_num = dwarf_sp;
     uint32_t pc_reg_num = dwarf_pc;
     
     UnwindPlan::Row row;    

Modified: lldb/branches/apple/python-GIL/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/apple/python-GIL/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp?rev=160119&r1=160118&r2=160119&view=diff
==============================================================================
--- lldb/branches/apple/python-GIL/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp (original)
+++ lldb/branches/apple/python-GIL/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp Thu Jul 12 04:33:44 2012
@@ -1423,17 +1423,18 @@
                                 // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread,
                                 // we can just report no reason.  We don't need to worry about stepping over the breakpoint here, that
                                 // will be taken care of when the thread resumes and notices that there's a breakpoint under the pc.
+                                handled = true;
                                 if (bp_site_sp->ValidForThisThread (gdb_thread))
                                 {
                                     gdb_thread->SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID (*thread_sp, bp_site_sp->GetID()));
-                                    handled = true;
+                                }
+                                else
+                                {
+                                    StopInfoSP invalid_stop_info_sp;
+                                    gdb_thread->SetStopInfo (invalid_stop_info_sp);
                                 }
                             }
                             
-                            if (!handled)
-                            {
-                                gdb_thread->SetStopInfo (StopInfo::CreateStopReasonToTrace (*thread_sp));
-                            }
                         }
                         else if (reason.compare("trap") == 0)
                         {
@@ -1459,8 +1460,10 @@
                         {
                             // Currently we are going to assume SIGTRAP means we are either
                             // hitting a breakpoint or hardware single stepping. 
+                            handled = true;
                             addr_t pc = gdb_thread->GetRegisterContext()->GetPC();
                             lldb::BreakpointSiteSP bp_site_sp = gdb_thread->GetProcess()->GetBreakpointSiteList().FindByAddress(pc);
+                            
                             if (bp_site_sp)
                             {
                                 // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread,
@@ -1469,15 +1472,18 @@
                                 if (bp_site_sp->ValidForThisThread (gdb_thread))
                                 {
                                     gdb_thread->SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID (*thread_sp, bp_site_sp->GetID()));
-                                    handled = true;
+                                }
+                                else
+                                {
+                                    StopInfoSP invalid_stop_info_sp;
+                                    gdb_thread->SetStopInfo (invalid_stop_info_sp);
                                 }
                             }
-                            if (!handled)
+                            else
                             {
                                 // TODO: check for breakpoint or trap opcode in case there is a hard 
                                 // coded software trap
                                 gdb_thread->SetStopInfo (StopInfo::CreateStopReasonToTrace (*thread_sp));
-                                handled = true;
                             }
                         }
                         if (!handled)

Modified: lldb/branches/apple/python-GIL/source/Symbol/DWARFCallFrameInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/apple/python-GIL/source/Symbol/DWARFCallFrameInfo.cpp?rev=160119&r1=160118&r2=160119&view=diff
==============================================================================
--- lldb/branches/apple/python-GIL/source/Symbol/DWARFCallFrameInfo.cpp (original)
+++ lldb/branches/apple/python-GIL/source/Symbol/DWARFCallFrameInfo.cpp Thu Jul 12 04:33:44 2012
@@ -293,9 +293,14 @@
 {
     if (m_section_sp.get() == NULL || m_section_sp->IsEncrypted())
         return;
+    
     if (m_fde_index_initialized)
         return;
-
+    
+    Mutex::Locker locker(m_fde_index_mutex);
+    
+    if (m_fde_index_initialized) // if two threads hit the locker
+        return;
 
     dw_offset_t offset = 0;
     if (m_cfi_data_initialized == false)

Modified: lldb/branches/apple/python-GIL/source/Symbol/UnwindTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/apple/python-GIL/source/Symbol/UnwindTable.cpp?rev=160119&r1=160118&r2=160119&view=diff
==============================================================================
--- lldb/branches/apple/python-GIL/source/Symbol/UnwindTable.cpp (original)
+++ lldb/branches/apple/python-GIL/source/Symbol/UnwindTable.cpp Thu Jul 12 04:33:44 2012
@@ -107,6 +107,31 @@
     return func_unwinder_sp;
 }
 
+// Ignore any existing FuncUnwinders for this function, create a new one and don't add it to the
+// UnwindTable.  This is intended for use by target modules show-unwind where we want to create 
+// new UnwindPlans, not re-use existing ones.
+
+FuncUnwindersSP
+UnwindTable::GetUncachedFuncUnwindersContainingAddress (const Address& addr, SymbolContext &sc)
+{
+    FuncUnwindersSP no_unwind_found;
+    Initialize();
+
+    AddressRange range;
+    if (!sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, 0, false, range) || !range.GetBaseAddress().IsValid())
+    {
+        // Does the eh_frame unwind info has a function bounds for this addr?
+        if (m_eh_frame == NULL || !m_eh_frame->GetAddressRange (addr, range))
+        {
+            return no_unwind_found;
+        }
+    }
+
+    FuncUnwindersSP func_unwinder_sp(new FuncUnwinders(*this, m_assembly_profiler, range));
+    return func_unwinder_sp;
+}
+
+
 void
 UnwindTable::Dump (Stream &s)
 {

Modified: lldb/branches/apple/python-GIL/source/Target/Process.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/apple/python-GIL/source/Target/Process.cpp?rev=160119&r1=160118&r2=160119&view=diff
==============================================================================
--- lldb/branches/apple/python-GIL/source/Target/Process.cpp (original)
+++ lldb/branches/apple/python-GIL/source/Target/Process.cpp Thu Jul 12 04:33:44 2012
@@ -4143,546 +4143,565 @@
     
     Listener listener("lldb.process.listener.run-thread-plan");
     
-    // This process event hijacker Hijacks the Public events and its destructor makes sure that the process events get 
-    // restored on exit to the function.
+    lldb::EventSP event_to_broadcast_sp;
     
-    ProcessEventHijacker run_thread_plan_hijacker (*this, &listener);
-        
-    if (log)
     {
-        StreamString s;
-        thread_plan_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose);
-        log->Printf ("Process::RunThreadPlan(): Resuming thread %u - 0x%4.4llx to run thread plan \"%s\".",  
-                     thread->GetIndexID(), 
-                     thread->GetID(), 
-                     s.GetData());
-    }
-    
-    bool got_event;
-    lldb::EventSP event_sp;
-    lldb::StateType stop_state = lldb::eStateInvalid;
-    
-    TimeValue* timeout_ptr = NULL;
-    TimeValue real_timeout;
-    
-    bool first_timeout = true;
-    bool do_resume = true;
-    
-    while (1)
-    {
-        // We usually want to resume the process if we get to the top of the loop.
-        // The only exception is if we get two running events with no intervening
-        // stop, which can happen, we will just wait for then next stop event.
+        // This process event hijacker Hijacks the Public events and its destructor makes sure that the process events get
+        // restored on exit to the function.
+        //
+        // If the event needs to propagate beyond the hijacker (e.g., the process exits during execution), then the event
+        // is put into event_to_broadcast_sp for rebroadcasting.
         
-        if (do_resume)
+        ProcessEventHijacker run_thread_plan_hijacker (*this, &listener);
+            
+        if (log)
         {
-            // Do the initial resume and wait for the running event before going further.
-    
-            Error resume_error = PrivateResume ();
-            if (!resume_error.Success())
-            {
-                errors.Printf("Error resuming inferior: \"%s\".\n", resume_error.AsCString());
-                return_value = eExecutionSetupError;
-                break;
-            }
-    
-            real_timeout = TimeValue::Now();
-            real_timeout.OffsetWithMicroSeconds(500000);
-            timeout_ptr = &real_timeout;
+            StreamString s;
+            thread_plan_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose);
+            log->Printf ("Process::RunThreadPlan(): Resuming thread %u - 0x%4.4llx to run thread plan \"%s\".",  
+                         thread->GetIndexID(), 
+                         thread->GetID(), 
+                         s.GetData());
+        }
+        
+        bool got_event;
+        lldb::EventSP event_sp;
+        lldb::StateType stop_state = lldb::eStateInvalid;
+        
+        TimeValue* timeout_ptr = NULL;
+        TimeValue real_timeout;
+        
+        bool first_timeout = true;
+        bool do_resume = true;
+        
+        while (1)
+        {
+            // We usually want to resume the process if we get to the top of the loop.
+            // The only exception is if we get two running events with no intervening
+            // stop, which can happen, we will just wait for then next stop event.
             
-            got_event = listener.WaitForEvent(timeout_ptr, event_sp);
-            if (!got_event)
+            if (do_resume)
             {
-                if (log)
-                    log->PutCString("Process::RunThreadPlan(): didn't get any event after initial resume, exiting.");
+                // Do the initial resume and wait for the running event before going further.
+        
+                Error resume_error = PrivateResume ();
+                if (!resume_error.Success())
+                {
+                    errors.Printf("Error resuming inferior: \"%s\".\n", resume_error.AsCString());
+                    return_value = eExecutionSetupError;
+                    break;
+                }
+        
+                real_timeout = TimeValue::Now();
+                real_timeout.OffsetWithMicroSeconds(500000);
+                timeout_ptr = &real_timeout;
+                
+                got_event = listener.WaitForEvent(timeout_ptr, event_sp);
+                if (!got_event)
+                {
+                    if (log)
+                        log->PutCString("Process::RunThreadPlan(): didn't get any event after initial resume, exiting.");
 
-                errors.Printf("Didn't get any event after initial resume, exiting.");
-                return_value = eExecutionSetupError;
-                break;
-            }
+                    errors.Printf("Didn't get any event after initial resume, exiting.");
+                    return_value = eExecutionSetupError;
+                    break;
+                }
+                
+                stop_state = Process::ProcessEventData::GetStateFromEvent(event_sp.get());
+                if (stop_state != eStateRunning)
+                {
+                    if (log)
+                        log->Printf("Process::RunThreadPlan(): didn't get running event after initial resume, got %s instead.", StateAsCString(stop_state));
+
+                    errors.Printf("Didn't get running event after initial resume, got %s instead.", StateAsCString(stop_state));
+                    return_value = eExecutionSetupError;
+                    break;
+                }
             
-            stop_state = Process::ProcessEventData::GetStateFromEvent(event_sp.get());
-            if (stop_state != eStateRunning)
-            {
                 if (log)
-                    log->Printf("Process::RunThreadPlan(): didn't get running event after initial resume, got %s instead.", StateAsCString(stop_state));
-
-                errors.Printf("Didn't get running event after initial resume, got %s instead.", StateAsCString(stop_state));
-                return_value = eExecutionSetupError;
-                break;
+                    log->PutCString ("Process::RunThreadPlan(): resuming succeeded.");
+                // We need to call the function synchronously, so spin waiting for it to return.
+                // If we get interrupted while executing, we're going to lose our context, and
+                // won't be able to gather the result at this point.
+                // We set the timeout AFTER the resume, since the resume takes some time and we
+                // don't want to charge that to the timeout.
+                
+                if (single_thread_timeout_usec != 0)
+                {
+                    real_timeout = TimeValue::Now();
+                    real_timeout.OffsetWithMicroSeconds(single_thread_timeout_usec);
+                        
+                    timeout_ptr = &real_timeout;
+                }
             }
-        
-            if (log)
-                log->PutCString ("Process::RunThreadPlan(): resuming succeeded.");
-            // We need to call the function synchronously, so spin waiting for it to return.
-            // If we get interrupted while executing, we're going to lose our context, and
-            // won't be able to gather the result at this point.
-            // We set the timeout AFTER the resume, since the resume takes some time and we
-            // don't want to charge that to the timeout.
-            
-            if (single_thread_timeout_usec != 0)
+            else
             {
-                real_timeout = TimeValue::Now();
-                real_timeout.OffsetWithMicroSeconds(single_thread_timeout_usec);
-                    
-                timeout_ptr = &real_timeout;
+                if (log)
+                    log->PutCString ("Process::RunThreadPlan(): handled an extra running event.");
+                do_resume = true;
             }
-        }
-        else
-        {
-            if (log)
-                log->PutCString ("Process::RunThreadPlan(): handled an extra running event.");
-            do_resume = true;
-        }
-        
-        // Now wait for the process to stop again:
-        stop_state = lldb::eStateInvalid;
-        event_sp.reset();
+            
+            // Now wait for the process to stop again:
+            stop_state = lldb::eStateInvalid;
+            event_sp.reset();
 
-        if (log)
-        {
-            if (timeout_ptr)
-            {
-                StreamString s;
-                s.Printf ("about to wait - timeout is:\n   ");
-                timeout_ptr->Dump (&s, 120);
-                s.Printf ("\nNow is:\n    ");
-                TimeValue::Now().Dump (&s, 120);
-                log->Printf ("Process::RunThreadPlan(): %s", s.GetData());
-            }
-            else
+            if (log)
             {
-                log->Printf ("Process::RunThreadPlan(): about to wait forever.");
+                if (timeout_ptr)
+                {
+                    StreamString s;
+                    s.Printf ("about to wait - timeout is:\n   ");
+                    timeout_ptr->Dump (&s, 120);
+                    s.Printf ("\nNow is:\n    ");
+                    TimeValue::Now().Dump (&s, 120);
+                    log->Printf ("Process::RunThreadPlan(): %s", s.GetData());
+                }
+                else
+                {
+                    log->Printf ("Process::RunThreadPlan(): about to wait forever.");
+                }
             }
-        }
-        
-        got_event = listener.WaitForEvent (timeout_ptr, event_sp);
-        
-        if (got_event)
-        {
-            if (event_sp.get())
+            
+            got_event = listener.WaitForEvent (timeout_ptr, event_sp);
+            
+            if (got_event)
             {
-                bool keep_going = false;
-                stop_state = Process::ProcessEventData::GetStateFromEvent(event_sp.get());
-                if (log)
-                    log->Printf("Process::RunThreadPlan(): in while loop, got event: %s.", StateAsCString(stop_state));
-                    
-                switch (stop_state)
+                if (event_sp.get())
                 {
-                case lldb::eStateStopped:
+                    bool keep_going = false;
+                    stop_state = Process::ProcessEventData::GetStateFromEvent(event_sp.get());
+                    if (log)
+                        log->Printf("Process::RunThreadPlan(): in while loop, got event: %s.", StateAsCString(stop_state));
+                        
+                    switch (stop_state)
                     {
-                        // Yay, we're done.  Now make sure that our thread plan actually completed.
-                        ThreadSP thread_sp = GetThreadList().FindThreadByIndexID (thread_idx_id);
-                        if (!thread_sp)
+                    case lldb::eStateStopped:
                         {
-                            // Ooh, our thread has vanished.  Unlikely that this was successful execution...
-                            if (log)
-                                log->Printf ("Process::RunThreadPlan(): execution completed but our thread (index-id=%u) has vanished.", thread_idx_id);
-                            return_value = eExecutionInterrupted;
-                        }
-                        else
-                        {
-                            StopInfoSP stop_info_sp (thread_sp->GetStopInfo ());
-                            StopReason stop_reason = eStopReasonInvalid;
-                            if (stop_info_sp)
-                                 stop_reason = stop_info_sp->GetStopReason();
-                            if (stop_reason == eStopReasonPlanComplete)
+                            // Yay, we're done.  Now make sure that our thread plan actually completed.
+                            ThreadSP thread_sp = GetThreadList().FindThreadByIndexID (thread_idx_id);
+                            if (!thread_sp)
                             {
+                                // Ooh, our thread has vanished.  Unlikely that this was successful execution...
                                 if (log)
-                                    log->PutCString ("Process::RunThreadPlan(): execution completed successfully.");
-                                // Now mark this plan as private so it doesn't get reported as the stop reason
-                                // after this point.  
-                                if (thread_plan_sp)
-                                    thread_plan_sp->SetPrivate (orig_plan_private);
-                                return_value = eExecutionCompleted;
+                                    log->Printf ("Process::RunThreadPlan(): execution completed but our thread (index-id=%u) has vanished.", thread_idx_id);
+                                return_value = eExecutionInterrupted;
                             }
                             else
                             {
-                                if (log)
-                                    log->PutCString ("Process::RunThreadPlan(): thread plan didn't successfully complete.");
+                                StopInfoSP stop_info_sp (thread_sp->GetStopInfo ());
+                                StopReason stop_reason = eStopReasonInvalid;
+                                if (stop_info_sp)
+                                     stop_reason = stop_info_sp->GetStopReason();
+                                if (stop_reason == eStopReasonPlanComplete)
+                                {
+                                    if (log)
+                                        log->PutCString ("Process::RunThreadPlan(): execution completed successfully.");
+                                    // Now mark this plan as private so it doesn't get reported as the stop reason
+                                    // after this point.  
+                                    if (thread_plan_sp)
+                                        thread_plan_sp->SetPrivate (orig_plan_private);
+                                    return_value = eExecutionCompleted;
+                                }
+                                else
+                                {
+                                    if (log)
+                                        log->PutCString ("Process::RunThreadPlan(): thread plan didn't successfully complete.");
 
-                                return_value = eExecutionInterrupted;
+                                    return_value = eExecutionInterrupted;
+                                }
                             }
-                        }
-                    }        
-                    break;
+                        }        
+                        break;
 
-                case lldb::eStateCrashed:
-                    if (log)
-                        log->PutCString ("Process::RunThreadPlan(): execution crashed.");
-                    return_value = eExecutionInterrupted;
-                    break;
+                    case lldb::eStateCrashed:
+                        if (log)
+                            log->PutCString ("Process::RunThreadPlan(): execution crashed.");
+                        return_value = eExecutionInterrupted;
+                        break;
 
-                case lldb::eStateRunning:
-                    do_resume = false;
-                    keep_going = true;
-                    break;
+                    case lldb::eStateRunning:
+                        do_resume = false;
+                        keep_going = true;
+                        break;
 
-                default:
+                    default:
+                        if (log)
+                            log->Printf("Process::RunThreadPlan(): execution stopped with unexpected state: %s.", StateAsCString(stop_state));
+                            
+                        if (stop_state == eStateExited)
+                            event_to_broadcast_sp = event_sp;
+                            
+                        errors.Printf ("Execution stopped with unexpected state.");
+                        return_value = eExecutionInterrupted;
+                        break;
+                    }
+                    if (keep_going)
+                        continue;
+                    else
+                        break;
+                } 
+                else
+                {
                     if (log)
-                        log->Printf("Process::RunThreadPlan(): execution stopped with unexpected state: %s.", StateAsCString(stop_state));
-                        
-                    errors.Printf ("Execution stopped with unexpected state.");
+                        log->PutCString ("Process::RunThreadPlan(): got_event was true, but the event pointer was null.  How odd...");
                     return_value = eExecutionInterrupted;
                     break;
                 }
-                if (keep_going)
-                    continue;
-                else
-                    break;
-            } 
+            }
             else
             {
-                if (log)
-                    log->PutCString ("Process::RunThreadPlan(): got_event was true, but the event pointer was null.  How odd...");
-                return_value = eExecutionInterrupted;
-                break;
-            }
-        }
-        else
-        {
-            // If we didn't get an event that means we've timed out...
-            // We will interrupt the process here.  Depending on what we were asked to do we will
-            // either exit, or try with all threads running for the same timeout.
-            // Not really sure what to do if Halt fails here...
-            
-            if (log) {
-                if (try_all_threads)
-                {
-                    if (first_timeout)
-                        log->Printf ("Process::RunThreadPlan(): Running function with timeout: %d timed out, "
-                                     "trying with all threads enabled.",
-                                     single_thread_timeout_usec);
+                // If we didn't get an event that means we've timed out...
+                // We will interrupt the process here.  Depending on what we were asked to do we will
+                // either exit, or try with all threads running for the same timeout.
+                // Not really sure what to do if Halt fails here...
+                
+                if (log) {
+                    if (try_all_threads)
+                    {
+                        if (first_timeout)
+                            log->Printf ("Process::RunThreadPlan(): Running function with timeout: %d timed out, "
+                                         "trying with all threads enabled.",
+                                         single_thread_timeout_usec);
+                        else
+                            log->Printf ("Process::RunThreadPlan(): Restarting function with all threads enabled "
+                                         "and timeout: %d timed out.",
+                                         single_thread_timeout_usec);
+                    }
                     else
-                        log->Printf ("Process::RunThreadPlan(): Restarting function with all threads enabled "
-                                     "and timeout: %d timed out.",
+                        log->Printf ("Process::RunThreadPlan(): Running function with timeout: %d timed out, "
+                                     "halt and abandoning execution.", 
                                      single_thread_timeout_usec);
                 }
-                else
-                    log->Printf ("Process::RunThreadPlan(): Running function with timeout: %d timed out, "
-                                 "halt and abandoning execution.", 
-                                 single_thread_timeout_usec);
-            }
-            
-            Error halt_error = Halt();
-            if (halt_error.Success())
-            {
-                if (log)
-                    log->PutCString ("Process::RunThreadPlan(): Halt succeeded.");
-                    
-                // If halt succeeds, it always produces a stopped event.  Wait for that:
-                
-                real_timeout = TimeValue::Now();
-                real_timeout.OffsetWithMicroSeconds(500000);
-
-                got_event = listener.WaitForEvent(&real_timeout, event_sp);
                 
-                if (got_event)
+                Error halt_error = Halt();
+                if (halt_error.Success())
                 {
-                    stop_state = Process::ProcessEventData::GetStateFromEvent(event_sp.get());
                     if (log)
-                    {
-                        log->Printf ("Process::RunThreadPlan(): Stopped with event: %s", StateAsCString(stop_state));
-                        if (stop_state == lldb::eStateStopped 
-                            && Process::ProcessEventData::GetInterruptedFromEvent(event_sp.get()))
-                            log->PutCString ("    Event was the Halt interruption event.");
-                    }
-                    
-                    if (stop_state == lldb::eStateStopped)
-                    {
-                        // Between the time we initiated the Halt and the time we delivered it, the process could have
-                        // already finished its job.  Check that here:
+                        log->PutCString ("Process::RunThreadPlan(): Halt succeeded.");
                         
-                        if (thread->IsThreadPlanDone (thread_plan_sp.get()))
-                        {
-                            if (log)
-                                log->PutCString ("Process::RunThreadPlan(): Even though we timed out, the call plan was done.  "
-                                             "Exiting wait loop.");
-                            return_value = eExecutionCompleted;
-                            break;
-                        }
+                    // If halt succeeds, it always produces a stopped event.  Wait for that:
+                    
+                    real_timeout = TimeValue::Now();
+                    real_timeout.OffsetWithMicroSeconds(500000);
 
-                        if (!try_all_threads)
+                    got_event = listener.WaitForEvent(&real_timeout, event_sp);
+                    
+                    if (got_event)
+                    {
+                        stop_state = Process::ProcessEventData::GetStateFromEvent(event_sp.get());
+                        if (log)
                         {
-                            if (log)
-                                log->PutCString ("Process::RunThreadPlan(): try_all_threads was false, we stopped so now we're quitting.");
-                            return_value = eExecutionInterrupted;
-                            break;
+                            log->Printf ("Process::RunThreadPlan(): Stopped with event: %s", StateAsCString(stop_state));
+                            if (stop_state == lldb::eStateStopped 
+                                && Process::ProcessEventData::GetInterruptedFromEvent(event_sp.get()))
+                                log->PutCString ("    Event was the Halt interruption event.");
                         }
                         
-                        if (first_timeout)
+                        if (stop_state == lldb::eStateStopped)
                         {
-                            // Set all the other threads to run, and return to the top of the loop, which will continue;
-                            first_timeout = false;
-                            thread_plan_sp->SetStopOthers (false);
-                            if (log)
-                                log->PutCString ("Process::RunThreadPlan(): about to resume.");
+                            // Between the time we initiated the Halt and the time we delivered it, the process could have
+                            // already finished its job.  Check that here:
+                            
+                            if (thread->IsThreadPlanDone (thread_plan_sp.get()))
+                            {
+                                if (log)
+                                    log->PutCString ("Process::RunThreadPlan(): Even though we timed out, the call plan was done.  "
+                                                 "Exiting wait loop.");
+                                return_value = eExecutionCompleted;
+                                break;
+                            }
 
-                            continue;
-                        }
-                        else
-                        {
-                            // Running all threads failed, so return Interrupted.
-                            if (log)
-                                log->PutCString("Process::RunThreadPlan(): running all threads timed out.");
-                            return_value = eExecutionInterrupted;
-                            break;
+                            if (!try_all_threads)
+                            {
+                                if (log)
+                                    log->PutCString ("Process::RunThreadPlan(): try_all_threads was false, we stopped so now we're quitting.");
+                                return_value = eExecutionInterrupted;
+                                break;
+                            }
+                            
+                            if (first_timeout)
+                            {
+                                // Set all the other threads to run, and return to the top of the loop, which will continue;
+                                first_timeout = false;
+                                thread_plan_sp->SetStopOthers (false);
+                                if (log)
+                                    log->PutCString ("Process::RunThreadPlan(): about to resume.");
+
+                                continue;
+                            }
+                            else
+                            {
+                                // Running all threads failed, so return Interrupted.
+                                if (log)
+                                    log->PutCString("Process::RunThreadPlan(): running all threads timed out.");
+                                return_value = eExecutionInterrupted;
+                                break;
+                            }
                         }
                     }
-                }
-                else
-                {   if (log)
-                        log->PutCString("Process::RunThreadPlan(): halt said it succeeded, but I got no event.  "
-                                "I'm getting out of here passing Interrupted.");
-                    return_value = eExecutionInterrupted;
-                    break;
-                }
-            }
-            else
-            {
-                // This branch is to work around some problems with gdb-remote's Halt.  It is a little racy, and can return 
-                // an error from halt, but if you wait a bit you'll get a stopped event anyway.
-                if (log)
-                    log->Printf ("Process::RunThreadPlan(): halt failed: error = \"%s\", I'm just going to wait a little longer and see if I get a stopped event.", 
-                                 halt_error.AsCString());                
-                real_timeout = TimeValue::Now();
-                real_timeout.OffsetWithMicroSeconds(500000);
-                timeout_ptr = &real_timeout;
-                got_event = listener.WaitForEvent(&real_timeout, event_sp);
-                if (!got_event || event_sp.get() == NULL)
-                {
-                    // This is not going anywhere, bag out.
-                    if (log)
-                        log->PutCString ("Process::RunThreadPlan(): halt failed: and waiting for the stopped event failed.");
-                    return_value = eExecutionInterrupted;
-                    break;                
+                    else
+                    {   if (log)
+                            log->PutCString("Process::RunThreadPlan(): halt said it succeeded, but I got no event.  "
+                                    "I'm getting out of here passing Interrupted.");
+                        return_value = eExecutionInterrupted;
+                        break;
+                    }
                 }
                 else
                 {
-                    stop_state = Process::ProcessEventData::GetStateFromEvent(event_sp.get());
+                    // This branch is to work around some problems with gdb-remote's Halt.  It is a little racy, and can return 
+                    // an error from halt, but if you wait a bit you'll get a stopped event anyway.
                     if (log)
-                        log->PutCString ("Process::RunThreadPlan(): halt failed: but then I got a stopped event.  Whatever...");
-                    if (stop_state == lldb::eStateStopped)
+                        log->Printf ("Process::RunThreadPlan(): halt failed: error = \"%s\", I'm just going to wait a little longer and see if I get a stopped event.", 
+                                     halt_error.AsCString());                
+                    real_timeout = TimeValue::Now();
+                    real_timeout.OffsetWithMicroSeconds(500000);
+                    timeout_ptr = &real_timeout;
+                    got_event = listener.WaitForEvent(&real_timeout, event_sp);
+                    if (!got_event || event_sp.get() == NULL)
                     {
-                        // Between the time we initiated the Halt and the time we delivered it, the process could have
-                        // already finished its job.  Check that here:
-                        
-                        if (thread->IsThreadPlanDone (thread_plan_sp.get()))
+                        // This is not going anywhere, bag out.
+                        if (log)
+                            log->PutCString ("Process::RunThreadPlan(): halt failed: and waiting for the stopped event failed.");
+                        return_value = eExecutionInterrupted;
+                        break;                
+                    }
+                    else
+                    {
+                        stop_state = Process::ProcessEventData::GetStateFromEvent(event_sp.get());
+                        if (log)
+                            log->PutCString ("Process::RunThreadPlan(): halt failed: but then I got a stopped event.  Whatever...");
+                        if (stop_state == lldb::eStateStopped)
                         {
-                            if (log)
-                                log->PutCString ("Process::RunThreadPlan(): Even though we timed out, the call plan was done.  "
-                                             "Exiting wait loop.");
-                            return_value = eExecutionCompleted;
-                            break;
-                        }
+                            // Between the time we initiated the Halt and the time we delivered it, the process could have
+                            // already finished its job.  Check that here:
+                            
+                            if (thread->IsThreadPlanDone (thread_plan_sp.get()))
+                            {
+                                if (log)
+                                    log->PutCString ("Process::RunThreadPlan(): Even though we timed out, the call plan was done.  "
+                                                 "Exiting wait loop.");
+                                return_value = eExecutionCompleted;
+                                break;
+                            }
 
-                        if (first_timeout)
-                        {
-                            // Set all the other threads to run, and return to the top of the loop, which will continue;
-                            first_timeout = false;
-                            thread_plan_sp->SetStopOthers (false);
-                            if (log)
-                                log->PutCString ("Process::RunThreadPlan(): About to resume.");
+                            if (first_timeout)
+                            {
+                                // Set all the other threads to run, and return to the top of the loop, which will continue;
+                                first_timeout = false;
+                                thread_plan_sp->SetStopOthers (false);
+                                if (log)
+                                    log->PutCString ("Process::RunThreadPlan(): About to resume.");
 
-                            continue;
+                                continue;
+                            }
+                            else
+                            {
+                                // Running all threads failed, so return Interrupted.
+                                if (log)
+                                    log->PutCString ("Process::RunThreadPlan(): running all threads timed out.");
+                                return_value = eExecutionInterrupted;
+                                break;
+                            }
                         }
                         else
                         {
-                            // Running all threads failed, so return Interrupted.
                             if (log)
-                                log->PutCString ("Process::RunThreadPlan(): running all threads timed out.");
+                                log->Printf ("Process::RunThreadPlan(): halt failed, I waited and didn't get"
+                                             " a stopped event, instead got %s.", StateAsCString(stop_state));
                             return_value = eExecutionInterrupted;
-                            break;
+                            break;                
                         }
                     }
-                    else
-                    {
-                        if (log)
-                            log->Printf ("Process::RunThreadPlan(): halt failed, I waited and didn't get"
-                                         " a stopped event, instead got %s.", StateAsCString(stop_state));
-                        return_value = eExecutionInterrupted;
-                        break;                
-                    }
                 }
-            }
 
-        }
+            }
+            
+        }  // END WAIT LOOP
         
-    }  // END WAIT LOOP
-    
-    // If we had to start up a temporary private state thread to run this thread plan, shut it down now.
-    if (IS_VALID_LLDB_HOST_THREAD(backup_private_state_thread))
-    {
-        StopPrivateStateThread();
-        Error error;
-        m_private_state_thread = backup_private_state_thread;
-        if (stopper_base_plan_sp != NULL)
+        // If we had to start up a temporary private state thread to run this thread plan, shut it down now.
+        if (IS_VALID_LLDB_HOST_THREAD(backup_private_state_thread))
         {
-            thread->DiscardThreadPlansUpToPlan(stopper_base_plan_sp);
-        }
-        m_public_state.SetValueNoLock(old_state);
-
-    }
-    
-    
-    // Now do some processing on the results of the run:
-    if (return_value == eExecutionInterrupted)
-    {
-        if (log)
-        {
-            StreamString s;
-            if (event_sp)
-                event_sp->Dump (&s);
-            else
+            StopPrivateStateThread();
+            Error error;
+            m_private_state_thread = backup_private_state_thread;
+            if (stopper_base_plan_sp != NULL)
             {
-                log->PutCString ("Process::RunThreadPlan(): Stop event that interrupted us is NULL.");
+                thread->DiscardThreadPlansUpToPlan(stopper_base_plan_sp);
             }
+            m_public_state.SetValueNoLock(old_state);
 
-            StreamString ts;
-
-            const char *event_explanation = NULL;                
-            
-            do 
+        }
+        
+        
+        // Now do some processing on the results of the run:
+        if (return_value == eExecutionInterrupted)
+        {
+            if (log)
             {
-                const Process::ProcessEventData *event_data = Process::ProcessEventData::GetEventDataFromEvent (event_sp.get());
-
-                if (!event_data)
+                StreamString s;
+                if (event_sp)
+                    event_sp->Dump (&s);
+                else
                 {
-                    event_explanation = "<no event data>";
-                    break;
+                    log->PutCString ("Process::RunThreadPlan(): Stop event that interrupted us is NULL.");
                 }
-                
-                Process *process = event_data->GetProcessSP().get();
 
-                if (!process)
-                {
-                    event_explanation = "<no process>";
-                    break;
-                }
-                
-                ThreadList &thread_list = process->GetThreadList();
-                
-                uint32_t num_threads = thread_list.GetSize();
-                uint32_t thread_index;
-                
-                ts.Printf("<%u threads> ", num_threads);
+                StreamString ts;
+
+                const char *event_explanation = NULL;                
                 
-                for (thread_index = 0;
-                     thread_index < num_threads;
-                     ++thread_index)
+                do 
                 {
-                    Thread *thread = thread_list.GetThreadAtIndex(thread_index).get();
+                    const Process::ProcessEventData *event_data = Process::ProcessEventData::GetEventDataFromEvent (event_sp.get());
+
+                    if (!event_data)
+                    {
+                        event_explanation = "<no event data>";
+                        break;
+                    }
                     
-                    if (!thread)
+                    Process *process = event_data->GetProcessSP().get();
+
+                    if (!process)
                     {
-                        ts.Printf("<?> ");
-                        continue;
+                        event_explanation = "<no process>";
+                        break;
                     }
                     
-                    ts.Printf("<0x%4.4llx ", thread->GetID());
-                    RegisterContext *register_context = thread->GetRegisterContext().get();
+                    ThreadList &thread_list = process->GetThreadList();
                     
-                    if (register_context)
-                        ts.Printf("[ip 0x%llx] ", register_context->GetPC());
-                    else
-                        ts.Printf("[ip unknown] ");
+                    uint32_t num_threads = thread_list.GetSize();
+                    uint32_t thread_index;
+                    
+                    ts.Printf("<%u threads> ", num_threads);
                     
-                    lldb::StopInfoSP stop_info_sp = thread->GetStopInfo();
-                    if (stop_info_sp)
+                    for (thread_index = 0;
+                         thread_index < num_threads;
+                         ++thread_index)
                     {
-                        const char *stop_desc = stop_info_sp->GetDescription();
-                        if (stop_desc)
-                            ts.PutCString (stop_desc);
+                        Thread *thread = thread_list.GetThreadAtIndex(thread_index).get();
+                        
+                        if (!thread)
+                        {
+                            ts.Printf("<?> ");
+                            continue;
+                        }
+                        
+                        ts.Printf("<0x%4.4llx ", thread->GetID());
+                        RegisterContext *register_context = thread->GetRegisterContext().get();
+                        
+                        if (register_context)
+                            ts.Printf("[ip 0x%llx] ", register_context->GetPC());
+                        else
+                            ts.Printf("[ip unknown] ");
+                        
+                        lldb::StopInfoSP stop_info_sp = thread->GetStopInfo();
+                        if (stop_info_sp)
+                        {
+                            const char *stop_desc = stop_info_sp->GetDescription();
+                            if (stop_desc)
+                                ts.PutCString (stop_desc);
+                        }
+                        ts.Printf(">");
                     }
-                    ts.Printf(">");
-                }
+                    
+                    event_explanation = ts.GetData();
+                } while (0);
                 
-                event_explanation = ts.GetData();
-            } while (0);
-            
-            if (log)
-            {
-                if (event_explanation)
-                    log->Printf("Process::RunThreadPlan(): execution interrupted: %s %s", s.GetData(), event_explanation);
+                if (log)
+                {
+                    if (event_explanation)
+                        log->Printf("Process::RunThreadPlan(): execution interrupted: %s %s", s.GetData(), event_explanation);
+                    else
+                        log->Printf("Process::RunThreadPlan(): execution interrupted: %s", s.GetData());
+                }                
+                    
+                if (discard_on_error && thread_plan_sp)
+                {
+                    if (log)
+                        log->Printf ("Process::RunThreadPlan: ExecutionInterrupted - discarding thread plans up to %p.", thread_plan_sp.get());
+                    thread->DiscardThreadPlansUpToPlan (thread_plan_sp);
+                    thread_plan_sp->SetPrivate (orig_plan_private);
+                }
                 else
-                    log->Printf("Process::RunThreadPlan(): execution interrupted: %s", s.GetData());
-            }                
+                {
+                    if (log)
+                        log->Printf ("Process::RunThreadPlan: ExecutionInterrupted - for plan: %p not discarding.", thread_plan_sp.get());
+
+                }
+            }
+        }
+        else if (return_value == eExecutionSetupError)
+        {
+            if (log)
+                log->PutCString("Process::RunThreadPlan(): execution set up error.");
                 
             if (discard_on_error && thread_plan_sp)
             {
-                if (log)
-                    log->Printf ("Process::RunThreadPlan: ExecutionInterrupted - discarding thread plans up to %p.", thread_plan_sp.get());
                 thread->DiscardThreadPlansUpToPlan (thread_plan_sp);
                 thread_plan_sp->SetPrivate (orig_plan_private);
             }
+        }
+        else
+        {
+            if (thread->IsThreadPlanDone (thread_plan_sp.get()))
+            {
+                if (log)
+                    log->PutCString("Process::RunThreadPlan(): thread plan is done");
+                return_value = eExecutionCompleted;
+            }
+            else if (thread->WasThreadPlanDiscarded (thread_plan_sp.get()))
+            {
+                if (log)
+                    log->PutCString("Process::RunThreadPlan(): thread plan was discarded");
+                return_value = eExecutionDiscarded;
+            }
             else
             {
                 if (log)
-                    log->Printf ("Process::RunThreadPlan: ExecutionInterrupted - for plan: %p not discarding.", thread_plan_sp.get());
-
+                    log->PutCString("Process::RunThreadPlan(): thread plan stopped in mid course");
+                if (discard_on_error && thread_plan_sp)
+                {
+                    if (log)
+                        log->PutCString("Process::RunThreadPlan(): discarding thread plan 'cause discard_on_error is set.");
+                    thread->DiscardThreadPlansUpToPlan (thread_plan_sp);
+                    thread_plan_sp->SetPrivate (orig_plan_private);
+                }
             }
         }
-    }
-    else if (return_value == eExecutionSetupError)
-    {
-        if (log)
-            log->PutCString("Process::RunThreadPlan(): execution set up error.");
-            
-        if (discard_on_error && thread_plan_sp)
-        {
-            thread->DiscardThreadPlansUpToPlan (thread_plan_sp);
-            thread_plan_sp->SetPrivate (orig_plan_private);
-        }
-    }
-    else
-    {
-        if (thread->IsThreadPlanDone (thread_plan_sp.get()))
+                    
+        // Thread we ran the function in may have gone away because we ran the target
+        // Check that it's still there, and if it is put it back in the context.  Also restore the
+        // frame in the context if it is still present.
+        thread = GetThreadList().FindThreadByIndexID(thread_idx_id, true).get();
+        if (thread)
         {
-            if (log)
-                log->PutCString("Process::RunThreadPlan(): thread plan is done");
-            return_value = eExecutionCompleted;
+            exe_ctx.SetFrameSP (thread->GetFrameWithStackID (ctx_frame_id));
         }
-        else if (thread->WasThreadPlanDiscarded (thread_plan_sp.get()))
-        {
-            if (log)
-                log->PutCString("Process::RunThreadPlan(): thread plan was discarded");
-            return_value = eExecutionDiscarded;
-        }
-        else
+        
+        // Also restore the current process'es selected frame & thread, since this function calling may
+        // be done behind the user's back.
+        
+        if (selected_tid != LLDB_INVALID_THREAD_ID)
         {
-            if (log)
-                log->PutCString("Process::RunThreadPlan(): thread plan stopped in mid course");
-            if (discard_on_error && thread_plan_sp)
+            if (GetThreadList().SetSelectedThreadByIndexID (selected_tid) && selected_stack_id.IsValid())
             {
-                if (log)
-                    log->PutCString("Process::RunThreadPlan(): discarding thread plan 'cause discard_on_error is set.");
-                thread->DiscardThreadPlansUpToPlan (thread_plan_sp);
-                thread_plan_sp->SetPrivate (orig_plan_private);
+                // We were able to restore the selected thread, now restore the frame:
+                StackFrameSP old_frame_sp = GetThreadList().GetSelectedThread()->GetFrameWithStackID(selected_stack_id);
+                if (old_frame_sp)
+                    GetThreadList().GetSelectedThread()->SetSelectedFrame(old_frame_sp.get());
             }
         }
     }
-                
-    // Thread we ran the function in may have gone away because we ran the target
-    // Check that it's still there, and if it is put it back in the context.  Also restore the
-    // frame in the context if it is still present.
-    thread = GetThreadList().FindThreadByIndexID(thread_idx_id, true).get();
-    if (thread)
-    {
-        exe_ctx.SetFrameSP (thread->GetFrameWithStackID (ctx_frame_id));
-    }
     
-    // Also restore the current process'es selected frame & thread, since this function calling may
-    // be done behind the user's back.
+    // If the process exited during the run of the thread plan, notify everyone.
     
-    if (selected_tid != LLDB_INVALID_THREAD_ID)
+    if (event_to_broadcast_sp)
     {
-        if (GetThreadList().SetSelectedThreadByIndexID (selected_tid) && selected_stack_id.IsValid())
-        {
-            // We were able to restore the selected thread, now restore the frame:
-            StackFrameSP old_frame_sp = GetThreadList().GetSelectedThread()->GetFrameWithStackID(selected_stack_id);
-            if (old_frame_sp)
-                GetThreadList().GetSelectedThread()->SetSelectedFrame(old_frame_sp.get());
-        }
+        if (log)
+            log->PutCString("Process::RunThreadPlan(): rebroadcasting event.");
+        BroadcastEvent(event_to_broadcast_sp);
     }
     
     return return_value;

Modified: lldb/branches/apple/python-GIL/source/Target/StackFrame.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/apple/python-GIL/source/Target/StackFrame.cpp?rev=160119&r1=160118&r2=160119&view=diff
==============================================================================
--- lldb/branches/apple/python-GIL/source/Target/StackFrame.cpp (original)
+++ lldb/branches/apple/python-GIL/source/Target/StackFrame.cpp Thu Jul 12 04:33:44 2012
@@ -1296,10 +1296,9 @@
 bool
 StackFrame::GetStatus (Stream& strm,
                        bool show_frame_info,
-                       bool show_source,
-                       uint32_t source_lines_before,
-                       uint32_t source_lines_after)
+                       bool show_source)
 {
+    
     if (show_frame_info)
     {
         strm.Indent();
@@ -1312,56 +1311,62 @@
         bool have_source = false;
         DebuggerInstanceSettings::StopDisassemblyType disasm_display = DebuggerInstanceSettings::eStopDisassemblyTypeNever;
         Target *target = exe_ctx.GetTargetPtr();
-        if (target && (source_lines_before || source_lines_after))
+        if (target)
         {
-            GetSymbolContext(eSymbolContextCompUnit | eSymbolContextLineEntry);
+            Debugger &debugger = target->GetDebugger();
+            const uint32_t source_lines_before = debugger.GetStopSourceLineCount(true);
+            const uint32_t source_lines_after = debugger.GetStopSourceLineCount(false);
+            disasm_display = debugger.GetStopDisassemblyDisplay ();
 
-            if (m_sc.comp_unit && m_sc.line_entry.IsValid())
+            if (source_lines_before > 0 || source_lines_after > 0)
             {
-                if (target->GetSourceManager().DisplaySourceLinesWithLineNumbers (m_sc.line_entry.file,
-                                                                                  m_sc.line_entry.line,
-                                                                                  source_lines_before,
-                                                                                  source_lines_after,
-                                                                                  "->",
-                                                                                  &strm))
+                GetSymbolContext(eSymbolContextCompUnit | eSymbolContextLineEntry);
+
+                if (m_sc.comp_unit && m_sc.line_entry.IsValid())
                 {
-                    have_source = true;
+                    if (target->GetSourceManager().DisplaySourceLinesWithLineNumbers (m_sc.line_entry.file,
+                                                                                      m_sc.line_entry.line,
+                                                                                      source_lines_before,
+                                                                                      source_lines_after,
+                                                                                      "->",
+                                                                                      &strm))
+                    {
+                        have_source = true;
+                    }
                 }
             }
-            disasm_display = target->GetDebugger().GetStopDisassemblyDisplay ();
-        }
-        
-        switch (disasm_display)
-        {
-        case DebuggerInstanceSettings::eStopDisassemblyTypeNever:
-            break;
-
-        case DebuggerInstanceSettings::eStopDisassemblyTypeNoSource:
-            if (have_source)
-                break;
-            // Fall through to next case
-        case DebuggerInstanceSettings::eStopDisassemblyTypeAlways:
-            if (target)
+            switch (disasm_display)
             {
-                const uint32_t disasm_lines = target->GetDebugger().GetDisassemblyLineCount();
-                if (disasm_lines > 0)
+            case DebuggerInstanceSettings::eStopDisassemblyTypeNever:
+                break;
+                
+            case DebuggerInstanceSettings::eStopDisassemblyTypeNoSource:
+                if (have_source)
+                    break;
+                // Fall through to next case
+            case DebuggerInstanceSettings::eStopDisassemblyTypeAlways:
+                if (target)
                 {
-                    const ArchSpec &target_arch = target->GetArchitecture();
-                    AddressRange pc_range;
-                    pc_range.GetBaseAddress() = GetFrameCodeAddress();
-                    pc_range.SetByteSize(disasm_lines * target_arch.GetMaximumOpcodeByteSize());
-                    Disassembler::Disassemble (target->GetDebugger(),
-                                               target_arch,
-                                               NULL,
-                                               exe_ctx,
-                                               pc_range,
-                                               disasm_lines,
-                                               0,
-                                               Disassembler::eOptionMarkPCAddress,
-                                               strm);
+                    const uint32_t disasm_lines = debugger.GetDisassemblyLineCount();
+                    if (disasm_lines > 0)
+                    {
+                        const ArchSpec &target_arch = target->GetArchitecture();
+                        AddressRange pc_range;
+                        pc_range.GetBaseAddress() = GetFrameCodeAddress();
+                        pc_range.SetByteSize(disasm_lines * target_arch.GetMaximumOpcodeByteSize());
+                        Disassembler::Disassemble (target->GetDebugger(),
+                                                   target_arch,
+                                                   NULL,
+                                                   exe_ctx,
+                                                   pc_range,
+                                                   disasm_lines,
+                                                   0,
+                                                   Disassembler::eOptionMarkPCAddress,
+                                                   strm);
+                    }
                 }
+                break;
             }
-            break;
         }
     }
     return true;

Modified: lldb/branches/apple/python-GIL/source/Target/StackFrameList.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/apple/python-GIL/source/Target/StackFrameList.cpp?rev=160119&r1=160118&r2=160119&view=diff
==============================================================================
--- lldb/branches/apple/python-GIL/source/Target/StackFrameList.cpp (original)
+++ lldb/branches/apple/python-GIL/source/Target/StackFrameList.cpp Thu Jul 12 04:33:44 2012
@@ -587,9 +587,7 @@
                            uint32_t first_frame,
                            uint32_t num_frames,
                            bool show_frame_info,
-                           uint32_t num_frames_with_source,
-                           uint32_t source_lines_before,
-                           uint32_t source_lines_after)
+                           uint32_t num_frames_with_source)
 {
     size_t num_frames_displayed = 0;
     
@@ -614,9 +612,7 @@
         
         if (!frame_sp->GetStatus (strm,
                                   show_frame_info,
-                                  num_frames_with_source > first_frame - frame_idx,
-                                  source_lines_before,
-                                  source_lines_after))
+                                  num_frames_with_source > (first_frame - frame_idx)))
             break;
         ++num_frames_displayed;
     }

Modified: lldb/branches/apple/python-GIL/source/Target/Thread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/apple/python-GIL/source/Target/Thread.cpp?rev=160119&r1=160118&r2=160119&view=diff
==============================================================================
--- lldb/branches/apple/python-GIL/source/Target/Thread.cpp (original)
+++ lldb/branches/apple/python-GIL/source/Target/Thread.cpp Thu Jul 12 04:33:44 2012
@@ -1321,16 +1321,12 @@
         strm.IndentMore();
         
         const bool show_frame_info = true;
-        const uint32_t source_lines_before = 3;
-        const uint32_t source_lines_after = 3;
         strm.IndentMore ();
         num_frames_shown = GetStackFrameList ()->GetStatus (strm,
                                                             start_frame, 
                                                             num_frames, 
                                                             show_frame_info, 
-                                                            num_frames_with_source,
-                                                            source_lines_before,
-                                                            source_lines_after);
+                                                            num_frames_with_source);
         strm.IndentLess();
         strm.IndentLess();
     }
@@ -1342,17 +1338,13 @@
                              uint32_t first_frame,
                              uint32_t num_frames,
                              bool show_frame_info,
-                             uint32_t num_frames_with_source,
-                             uint32_t source_lines_before,
-                             uint32_t source_lines_after)
+                             uint32_t num_frames_with_source)
 {
     return GetStackFrameList()->GetStatus (strm,
                                            first_frame,
                                            num_frames,
                                            show_frame_info,
-                                           num_frames_with_source,
-                                           source_lines_before,
-                                           source_lines_after);
+                                           num_frames_with_source);
 }
 
 bool

Modified: lldb/branches/apple/python-GIL/tools/driver/IOChannel.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/apple/python-GIL/tools/driver/IOChannel.cpp?rev=160119&r1=160118&r2=160119&view=diff
==============================================================================
--- lldb/branches/apple/python-GIL/tools/driver/IOChannel.cpp (original)
+++ lldb/branches/apple/python-GIL/tools/driver/IOChannel.cpp Thu Jul 12 04:33:44 2012
@@ -212,6 +212,7 @@
     el_set (m_edit_line, EL_BIND, m_completion_key, "lldb_complete", NULL);
     el_set (m_edit_line, EL_BIND, "^r", "em-inc-search-prev", NULL);  // Cycle through backwards search, entering string
     el_set (m_edit_line, EL_BIND, "^w", "ed-delete-prev-word", NULL); // Delete previous word, behave like bash does.
+    el_set (m_edit_line, EL_BIND, "\e[3~", "ed-delete-next-char", NULL); // Fix the delete key.
     el_set (m_edit_line, EL_CLIENTDATA, this);
 
     // Source $PWD/.editrc then $HOME/.editrc





More information about the lldb-commits mailing list