[Lldb-commits] [lldb] r154609 - in /lldb/branches/lldb-platform-work: ./ examples/darwin/heap_find/ include/lldb/Target/ source/Expression/ source/Plugins/Process/FreeBSD/ source/Plugins/Process/Linux/ source/Plugins/Process/POSIX/ source/Plugins/Process/gdb-remote/ source/Target/

Johnny Chen johnny.chen at apple.com
Thu Apr 12 13:08:47 PDT 2012


Author: johnny
Date: Thu Apr 12 15:08:46 2012
New Revision: 154609

URL: http://llvm.org/viewvc/llvm-project?rev=154609&view=rev
Log:
Merge goodies from ToT, and resolved some conflicts:

1. source/Plugins/Process/POSIX/ProcessPOSIX.cpp
2. source/Plugins/Process/POSIX/ProcessPOSIX.h
3. source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp

FreeBSD folks: if I resolved the conflicts wrong, please let me know.  Thanks!

svn merge -r 154573:154603 https://johnny@llvm.org/svn/llvm-project/lldb/trunk .

Modified:
    lldb/branches/lldb-platform-work/   (props changed)
    lldb/branches/lldb-platform-work/examples/darwin/heap_find/heap.py
    lldb/branches/lldb-platform-work/examples/darwin/heap_find/heap_find.cpp
    lldb/branches/lldb-platform-work/include/lldb/Target/Process.h
    lldb/branches/lldb-platform-work/source/Expression/ClangExpressionDeclMap.cpp
    lldb/branches/lldb-platform-work/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp
    lldb/branches/lldb-platform-work/source/Plugins/Process/Linux/ProcessLinux.cpp
    lldb/branches/lldb-platform-work/source/Plugins/Process/Linux/ProcessLinux.h
    lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessPOSIX.cpp
    lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessPOSIX.h
    lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
    lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
    lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
    lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
    lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
    lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
    lldb/branches/lldb-platform-work/source/Target/Process.cpp

Propchange: lldb/branches/lldb-platform-work/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Thu Apr 12 15:08:46 2012
@@ -1 +1 @@
-/lldb/trunk:154224-154573
+/lldb/trunk:154224-154603

Modified: lldb/branches/lldb-platform-work/examples/darwin/heap_find/heap.py
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/examples/darwin/heap_find/heap.py?rev=154609&r1=154608&r2=154609&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/examples/darwin/heap_find/heap.py (original)
+++ lldb/branches/lldb-platform-work/examples/darwin/heap_find/heap.py Thu Apr 12 15:08:46 2012
@@ -23,11 +23,16 @@
 
 def heap_search(options, arg_str):
     expr = None
+    arg_str_description = arg_str
     if options.type == 'pointer':
-        ptr = int(arg_str, 0)
-        expr = 'find_pointer_in_heap(0x%x)' % ptr
+        expr = 'find_pointer_in_heap(%s)' % arg_str
+        arg_str_description = 'malloc block containing pointer %s' % arg_str
     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(%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
@@ -48,73 +53,81 @@
                 # If the type is still 'void *' then we weren't able to figure
                 # out a dynamic type for the malloc_addr
                 type_name = dynamic_value.type.name
+                description = '[%u] %s: addr = 0x%x' % (i, arg_str_description, malloc_addr)
+                if offset != 0:
+                    description += ' + %u' % (offset)
+                description += ', size = %u' % (malloc_size)
                 if 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!':
-                            print 'found %s %s: block = 0x%x, size = %u, offset = %u, type = (autorelease object pool)' % (options.type, arg_str, malloc_addr, malloc_size, offset)
+                            description += ', type = (AUTORELEASE!)'
+                            print description
                             continue
-                
-                print 'found %s %s: block = 0x%x, size = %u, offset = %u, type = \'%s\'' % (options.type, arg_str, malloc_addr, malloc_size, offset, type_name),
-                derefed_dynamic_value = dynamic_value.deref
-                ivar_member = None
-                if derefed_dynamic_value:
-                    derefed_dynamic_type = derefed_dynamic_value.type
-                    member = derefed_dynamic_type.GetFieldAtIndex(0)
-                    search_bases = False
-                    if member:
-                        if member.GetOffsetInBytes() <= offset:
-                            for field_idx in range (derefed_dynamic_type.GetNumberOfFields()):
-                                member = derefed_dynamic_type.GetFieldAtIndex(field_idx)
-                                member_byte_offset = member.GetOffsetInBytes()
-                                if member_byte_offset == offset:
-                                    ivar_member = member
-                                    break
+                else:
+                    description += ', type = %s' % (type_name)
+                    derefed_dynamic_value = dynamic_value.deref
+                    ivar_member = None
+                    if derefed_dynamic_value:
+                        derefed_dynamic_type = derefed_dynamic_value.type
+                        member = derefed_dynamic_type.GetFieldAtIndex(0)
+                        search_bases = False
+                        if member:
+                            if member.GetOffsetInBytes() <= offset:
+                                for field_idx in range (derefed_dynamic_type.GetNumberOfFields()):
+                                    member = derefed_dynamic_type.GetFieldAtIndex(field_idx)
+                                    member_byte_offset = member.GetOffsetInBytes()
+                                    if member_byte_offset == offset:
+                                        ivar_member = member
+                                        break
+                            else:
+                                search_bases = True
                         else:
                             search_bases = True
-                    else:
-                        search_bases = True
 
-                    if not ivar_member and search_bases:
-                        for field_idx in range (derefed_dynamic_type.GetNumberOfDirectBaseClasses()):
-                            member = derefed_dynamic_type.GetDirectBaseClassAtIndex(field_idx)
-                            member_byte_offset = member.GetOffsetInBytes()
-                            if member_byte_offset == offset:
-                                ivar_member = member
-                                break
-                        if not ivar_member:
-                            for field_idx in range (derefed_dynamic_type.GetNumberOfVirtualBaseClasses()):
-                                member = derefed_dynamic_type.GetVirtualBaseClassAtIndex(field_idx)
+                        if not ivar_member and search_bases:
+                            for field_idx in range (derefed_dynamic_type.GetNumberOfDirectBaseClasses()):
+                                member = derefed_dynamic_type.GetDirectBaseClassAtIndex(field_idx)
                                 member_byte_offset = member.GetOffsetInBytes()
                                 if member_byte_offset == offset:
                                     ivar_member = member
                                     break
+                            if not ivar_member:
+                                for field_idx in range (derefed_dynamic_type.GetNumberOfVirtualBaseClasses()):
+                                    member = derefed_dynamic_type.GetVirtualBaseClassAtIndex(field_idx)
+                                    member_byte_offset = member.GetOffsetInBytes()
+                                    if member_byte_offset == offset:
+                                        ivar_member = member
+                                        break
                     if ivar_member:
-                        print ", ivar = %s" % ivar_member.name,
-                    print "\n", dynamic_value.deref
-                else:
-                    print
-                if options.print_object_description:
-                    desc = dynamic_value.GetObjectDescription()
-                    if desc:
-                        print '  (%s) 0x%x %s\n' % (type_name, malloc_addr, desc)
+                        description +=', ivar = %s' % (ivar_member.name)
+
+                    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)
         else:
             print '%s %s was not found in any malloc blocks' % (options.type, arg_str)
     else:
-        print expr_sbvalue.error        
+        print expr_sbvalue.error
+    print     
     
-def heap_ptr_refs(debugger, command, result, dict):
+def ptr_refs(debugger, command, result, dict):
     command_args = shlex.split(command)
-    usage = "usage: %prog [options] <PATH> [PATH ...]"
+    usage = "usage: %prog [options] <PTR> [PTR ...]"
     description='''Searches the heap for pointer references on darwin user space programs. 
     
     Any matches that were found will dump the malloc blocks that contain the pointers 
     and might be able to print what kind of objects the pointers are contained in using 
-    dynamic type information from the program.'''
-    parser = optparse.OptionParser(description=description, prog='heap_ptr_refs',usage=usage)
+    dynamic type information in the program.'''
+    parser = optparse.OptionParser(description=description, prog='ptr_refs',usage=usage)
     parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', 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='show_memory', help='dump the memory for each matching block', default=False)
     try:
         (options, args) = parser.parse_args(command_args)
     except:
@@ -129,17 +142,18 @@
     else:
         print 'error: no pointer arguments were given'
 
-def heap_cstr_refs(debugger, command, result, dict):
+def cstr_refs(debugger, command, result, dict):
     command_args = shlex.split(command)
-    usage = "usage: %prog [options] <PATH> [PATH ...]"
+    usage = "usage: %prog [options] <CSTR> [CSTR ...]"
     description='''Searches the heap for C string references on darwin user space programs. 
     
     Any matches that were found will dump the malloc blocks that contain the C strings 
     and might be able to print what kind of objects the pointers are contained in using 
-    dynamic type information from the program.'''
-    parser = optparse.OptionParser(description=description, prog='heap_cstr_refs',usage=usage)
+    dynamic type information in the program.'''
+    parser = optparse.OptionParser(description=description, prog='cstr_refs',usage=usage)
     parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', 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='show_memory', help='dump the memory for each matching block', default=False)
     try:
         (options, args) = parser.parse_args(command_args)
     except:
@@ -154,14 +168,41 @@
     else:
         print 'error: no c string arguments were given to search for'
 
+def malloc_info(debugger, command, result, dict):
+    command_args = shlex.split(command)
+    usage = "usage: %prog [options] <ADDR> [ADDR ...]"
+    description='''Searches the heap a malloc block that contains the addresses specified as arguments. 
+
+    Any matches that were found will dump the malloc blocks that match or contain
+    the specified address. The matching blocks might be able to show what kind 
+    of objects they are using dynamic type information in the program.'''
+    parser = optparse.OptionParser(description=description, prog='cstr_refs',usage=usage)
+    parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', 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='show_memory', help='dump the memory for each matching block', default=False)
+    try:
+        (options, args) = parser.parse_args(command_args)
+    except:
+        return
+
+    options.type = 'addr'
+
+    if args:
+
+        for data in args:
+            heap_search (options, data)
+    else:
+        print 'error: no c string arguments were given to search for'
+
 def __lldb_init_module (debugger, dict):
     # This initializer is being run from LLDB in the embedded command interpreter
     # Add any commands contained in this module to LLDB
     libheap_dylib_path = os.path.dirname(__file__) + '/libheap.dylib'
     debugger.HandleCommand('process load "%s"' % libheap_dylib_path)
-    debugger.HandleCommand('command script add -f heap.heap_ptr_refs heap_ptr_refs')
-    debugger.HandleCommand('command script add -f heap.heap_cstr_refs heap_cstr_refs')
-    print '"heap_ptr_refs" and "heap_cstr_refs" commands have been installed, use the "--help" options on these commands for detailed help.'
+    debugger.HandleCommand('command script add -f heap.ptr_refs ptr_refs')
+    debugger.HandleCommand('command script add -f heap.cstr_refs cstr_refs')
+    debugger.HandleCommand('command script add -f heap.malloc_info malloc_info')
+    print '"ptr_refs", "cstr_refs", and "malloc_info" commands have been installed, use the "--help" options on these commands for detailed help.'
 
 
 

Modified: lldb/branches/lldb-platform-work/examples/darwin/heap_find/heap_find.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/examples/darwin/heap_find/heap_find.cpp?rev=154609&r1=154608&r2=154609&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/examples/darwin/heap_find/heap_find.cpp (original)
+++ lldb/branches/lldb-platform-work/examples/darwin/heap_find/heap_find.cpp Thu Apr 12 15:08:46 2012
@@ -73,8 +73,6 @@
 #include <stdlib.h>
 #include <vector>
 
-struct range_callback_info_t;
-
 typedef void range_callback_t (task_t task, void *baton, unsigned type, uint64_t ptr_addr, uint64_t ptr_size);
 typedef void zone_callback_t (void *info, const malloc_zone_t *zone);
 
@@ -87,18 +85,28 @@
 
 enum data_type_t
 {
-    eDataTypeBytes,
-    eDataTypeCStr,
-    eDataTypeInteger
+    eDataTypeAddress,
+    eDataTypeContainsData
+};
+
+struct aligned_data_t
+{
+    const uint8_t *buffer;
+    uint32_t size;
+    uint32_t align;
 };
 
 struct range_contains_data_callback_info_t
 {
-    const uint8_t *data;
-    const size_t data_len;
-    const uint32_t align;
-    const data_type_t data_type;
+    data_type_t type;
+    const void *lookup_addr;
+    union
+    {
+        uintptr_t addr;
+        aligned_data_t data;
+    };
     uint32_t match_count;
+    bool done;
 };
 
 struct malloc_match
@@ -109,7 +117,15 @@
 };
 
 std::vector<malloc_match> g_matches;
+const void *g_lookup_addr = 0;
 
+//----------------------------------------------------------------------
+// task_peek
+//
+// Reads memory from this tasks address space. This callback is needed
+// by the code that iterates through all of the malloc blocks to read
+// the memory in this process.
+//----------------------------------------------------------------------
 static kern_return_t
 task_peek (task_t task, vm_address_t remote_address, vm_size_t size, void **local_memory)
 {
@@ -121,7 +137,6 @@
 static const void
 foreach_zone_in_this_process (range_callback_info_t *info)
 {
-    //printf ("foreach_zone_in_this_process ( info->zone_callback = %p, info->range_callback = %p, info->baton = %p)", info->zone_callback, info->range_callback, info->baton);
     if (info == NULL || info->zone_callback == NULL)
         return;
 
@@ -138,8 +153,14 @@
     }
 }
 
+//----------------------------------------------------------------------
+// dump_malloc_block_callback
+//
+// A simple callback that will dump each malloc block and all available
+// info from the enumeration callback perpective.
+//----------------------------------------------------------------------
 static void
-range_callback (task_t task, void *baton, unsigned type, uint64_t ptr_addr, uint64_t ptr_size)
+dump_malloc_block_callback (task_t task, void *baton, unsigned type, uint64_t ptr_addr, uint64_t ptr_size)
 {
     printf ("task = 0x%4.4x: baton = %p, type = %u, ptr_addr = 0x%llx + 0x%llu\n", task, baton, type, ptr_addr, ptr_size);
 }
@@ -168,89 +189,77 @@
                                       ranges_callback);    
 }
 
-const void
-foreach_range_in_this_process (range_callback_t *callback, void *baton)
-{
-    range_callback_info_t info = { enumerate_range_in_zone, callback ? callback : range_callback, baton };
-    foreach_zone_in_this_process (&info);
-}
-
-
 static void
-range_contains_ptr_callback (task_t task, void *baton, unsigned type, uint64_t ptr_addr, uint64_t ptr_size)
+range_info_callback (task_t task, void *baton, unsigned type, uint64_t ptr_addr, uint64_t ptr_size)
 {
-    uint8_t *data = NULL;
-    range_contains_data_callback_info_t *data_info = (range_contains_data_callback_info_t *)baton;
-    if (data_info->data_len <= 0)
+    const uint64_t end_addr = ptr_addr + ptr_size;
+    
+    range_contains_data_callback_info_t *info = (range_contains_data_callback_info_t *)baton;
+    switch (info->type)
     {
-        printf ("error: invalid data size: %zu\n", data_info->data_len);
-    }
-    else if (data_info->data_len > ptr_size)
-    {
-        // This block is too short to contain the data we are looking for...
-        return;
-    }
-    else if (task_peek (task, ptr_addr, ptr_size, (void **)&data) == KERN_SUCCESS)
-    {
-        assert (data);
-        const uint64_t end_addr = ptr_addr + ptr_size;
-        for (uint64_t addr = ptr_addr; 
-             addr < end_addr && ((end_addr - addr) >= data_info->data_len);
-             addr += data_info->align, data += data_info->align)
+    case eDataTypeAddress:
+        if (ptr_addr <= info->addr && info->addr < end_addr)
         {
-            if (memcmp (data_info->data, data, data_info->data_len) == 0)
+            ++info->match_count;
+            malloc_match match = { (void *)ptr_addr, ptr_size, info->addr - ptr_addr };
+            g_matches.push_back(match);            
+        }
+        break;
+    
+    case eDataTypeContainsData:
+        {
+            const uint32_t size = info->data.size;
+            if (size < ptr_size) // Make sure this block can contain this data
             {
-                ++data_info->match_count;
-                malloc_match match = { (void *)ptr_addr, ptr_size, addr - ptr_addr };
-                g_matches.push_back(match);
-                // printf ("0x%llx: ", addr);
-                // uint32_t i;
-                // switch (data_info->data_type)
-                // {
-                // case eDataTypeInteger:
-                //     {
-                //         // NOTE: little endian specific, but all darwin platforms are little endian now..
-                //         for (i=0; i<data_info->data_len; ++i)
-                //             printf (i ? "%2.2x" : "0x%2.2x", data[data_info->data_len - (i + 1)]);
-                //     }
-                //     break;
-                // case eDataTypeBytes:
-                //     {
-                //         for (i=0; i<data_info->data_len; ++i)
-                //             printf (" %2.2x", data[i]);
-                //     }
-                //     break;
-                // case eDataTypeCStr:
-                //     {
-                //         putchar ('"');
-                //         for (i=0; i<data_info->data_len; ++i)
-                //         {
-                //             if (isprint (data[i]))
-                //                 putchar (data[i]);
-                //             else
-                //                 printf ("\\x%2.2x", data[i]);
-                //         }
-                //         putchar ('"');
-                //     }
-                //     break;
-                //     
-                // }
-                // printf (" found in malloc block 0x%llx + %llu (malloc_size = %llu)\n", ptr_addr, addr - ptr_addr, ptr_size);
+                uint8_t *ptr_data = NULL;
+                if (task_peek (task, ptr_addr, ptr_size, (void **)&ptr_data) == KERN_SUCCESS)
+                {
+                    const void *buffer = info->data.buffer;
+                    assert (ptr_data);
+                    const uint32_t align = info->data.align;
+                    for (uint64_t addr = ptr_addr; 
+                         addr < end_addr && ((end_addr - addr) >= size);
+                         addr += align, ptr_data += align)
+                    {
+                        if (memcmp (buffer, ptr_data, size) == 0)
+                        {
+                            ++info->match_count;
+                            malloc_match match = { (void *)ptr_addr, ptr_size, addr - ptr_addr };
+                            g_matches.push_back(match);
+                        }
+                    }
+                }
+                else
+                {
+                    printf ("0x%llx: error: couldn't read %llu bytes\n", ptr_addr, ptr_size);
+                }   
             }
         }
+        break;
     }
-    else
-    {
-        printf ("0x%llx: error: couldn't read %llu bytes\n", ptr_addr, ptr_size);
-    }   
 }
 
+//----------------------------------------------------------------------
+// find_pointer_in_heap
+//
+// Finds a pointer value inside one or more currently valid malloc
+// blocks.
+//----------------------------------------------------------------------
 malloc_match *
-find_pointer_in_heap (intptr_t addr)
+find_pointer_in_heap (const void * addr)
 {
     g_matches.clear();
-    range_contains_data_callback_info_t data_info = { (uint8_t *)&addr, sizeof(addr), sizeof(addr), eDataTypeInteger, 0};
-    range_callback_info_t info = { enumerate_range_in_zone, range_contains_ptr_callback, &data_info };
+    // 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_callback_info_t info = { enumerate_range_in_zone, range_info_callback, &data_info };
     foreach_zone_in_this_process (&info);
     if (g_matches.empty())
         return NULL;
@@ -260,24 +269,61 @@
 }
 
 
+//----------------------------------------------------------------------
+// find_cstring_in_heap
+//
+// Finds a C string inside one or more currently valid malloc blocks.
+//----------------------------------------------------------------------
 malloc_match *
 find_cstring_in_heap (const char *s)
 {
-    if (s && s[0])
-    {
-        g_matches.clear();
-        range_contains_data_callback_info_t data_info = { (uint8_t *)s, strlen(s), 1, eDataTypeCStr, 0};
-        range_callback_info_t info = { enumerate_range_in_zone, range_contains_ptr_callback, &data_info };
-        foreach_zone_in_this_process (&info);
-        if (g_matches.empty())
-            return NULL;
-        malloc_match match = { NULL, 0, 0 };
-        g_matches.push_back(match);
-        return g_matches.data();
-    }
-    else
+    g_matches.clear();
+    if (s == NULL || s[0] == '\0')
     {
         printf ("error: invalid argument (empty cstring)\n");
+        return NULL;
     }
-    return 0;
+    // Setup "info" to look for a malloc block that contains data
+    // that is the C string passed in aligned on a 1 byte boundary
+    range_contains_data_callback_info_t data_info;
+    data_info.type = eDataTypeContainsData;  // Check each block for data
+    g_lookup_addr = s;               // If an expression was used, then fill in the resolved address we are looking up
+    data_info.data.buffer = (uint8_t *)s;    // What data? The C string passed in
+    data_info.data.size = strlen(s);         // How many bytes? The length of the C string
+    data_info.data.align = 1;                // Data doesn't need to be aligned, so set the alignment to 1
+    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_callback_info_t info = { enumerate_range_in_zone, range_info_callback, &data_info };
+    foreach_zone_in_this_process (&info);
+    if (g_matches.empty())
+        return NULL;
+    malloc_match match = { NULL, 0, 0 };
+    g_matches.push_back(match);
+    return g_matches.data();
+}
+
+//----------------------------------------------------------------------
+// find_block_for_address
+//
+// Find the malloc block that whose address range contains "addr".
+//----------------------------------------------------------------------
+malloc_match *
+find_block_for_address (const void *addr)
+{
+    g_matches.clear();
+    // Setup "info" to look for a malloc block that contains data
+    // that is the C string passed in aligned on a 1 byte boundary
+    range_contains_data_callback_info_t data_info;
+    g_lookup_addr = addr;               // If an expression was used, then fill in the resolved address we are looking up
+    data_info.type = eDataTypeAddress;  // Check each block to see if the block contains the address passed in
+    data_info.addr = (uintptr_t)addr;   // What data? The C string passed in
+    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_callback_info_t info = { enumerate_range_in_zone, range_info_callback, &data_info };
+    foreach_zone_in_this_process (&info);
+    if (g_matches.empty())
+        return NULL;
+    malloc_match match = { NULL, 0, 0 };
+    g_matches.push_back(match);
+    return g_matches.data();
 }

Modified: lldb/branches/lldb-platform-work/include/lldb/Target/Process.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/include/lldb/Target/Process.h?rev=154609&r1=154608&r2=154609&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/include/lldb/Target/Process.h (original)
+++ lldb/branches/lldb-platform-work/include/lldb/Target/Process.h Thu Apr 12 15:08:46 2012
@@ -3255,6 +3255,17 @@
     //------------------------------------------------------------------
     typedef std::map<lldb::LanguageType, lldb::LanguageRuntimeSP> LanguageRuntimeCollection;
 
+    struct PreResumeCallbackAndBaton
+    {
+        bool (*callback) (void *);
+        void *baton;
+        PreResumeCallbackAndBaton (PreResumeActionCallback in_callback, void *in_baton) :
+            callback (in_callback),
+            baton (in_baton)
+        {
+        }
+    };
+    
     //------------------------------------------------------------------
     // Member variables
     //------------------------------------------------------------------
@@ -3290,18 +3301,6 @@
     bool                        m_should_detach;   /// Should we detach if the process object goes away with an explicit call to Kill or Detach?
     LanguageRuntimeCollection 	m_language_runtimes;
     std::auto_ptr<NextEventAction> m_next_event_action_ap;
-    
-    struct PreResumeCallbackAndBaton
-    {
-        bool (*callback) (void *);
-        void *baton;
-        PreResumeCallbackAndBaton (PreResumeActionCallback in_callback, void *in_baton) :
-            callback (in_callback),
-            baton (in_baton)
-        {
-        }
-    };
-    
     std::vector<PreResumeCallbackAndBaton> m_pre_resume_actions;
     ReadWriteLock               m_run_lock;
 

Modified: lldb/branches/lldb-platform-work/source/Expression/ClangExpressionDeclMap.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Expression/ClangExpressionDeclMap.cpp?rev=154609&r1=154608&r2=154609&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Expression/ClangExpressionDeclMap.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Expression/ClangExpressionDeclMap.cpp Thu Apr 12 15:08:46 2012
@@ -634,7 +634,8 @@
     
     if (!member_sp ||
         !member_sp->m_parser_vars.get() ||
-        !member_sp->m_jit_vars.get())
+        !member_sp->m_jit_vars.get() ||
+        !member_sp->GetValueObject())
         return false;
     
     decl = member_sp->m_parser_vars->m_named_decl;

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp?rev=154609&r1=154608&r2=154609&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp Thu Apr 12 15:08:46 2012
@@ -138,8 +138,6 @@
     if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
         log->Printf ("ProcessFreeBSD::%s() (pid = %i)", __FUNCTION__, GetID());
 
-    bool has_updated = false;
-
     const tid_t tid = Host::GetCurrentThreadID();
     const lldb::pid_t pid = GetID();
     // Update the process thread list with this new thread.
@@ -149,7 +147,6 @@
     if (!thread_sp) {
         ProcessSP me = this->shared_from_this();
         thread_sp.reset(new POSIXThread(me, pid));
-        has_updated = true;
     }
 
     if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
@@ -157,5 +154,5 @@
 
     new_thread_list.AddThread(thread_sp);
 
-    return has_updated; // the list has been updated
+    return new_thread_list.GetSize(false) > 0;
 }

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Linux/ProcessLinux.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Linux/ProcessLinux.cpp?rev=154609&r1=154608&r2=154609&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Linux/ProcessLinux.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Linux/ProcessLinux.cpp Thu Apr 12 15:08:46 2012
@@ -94,7 +94,7 @@
 }
 
 
-uint32_t
+bool
 ProcessLinux::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list)
 {
     LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
@@ -114,7 +114,7 @@
         log->Printf ("ProcessLinux::%s() updated pid = %i", __FUNCTION__, GetID());
     new_thread_list.AddThread(thread_sp);
 
-    return new_thread_list.GetSize(false);
+    return new_thread_list.GetSize(false) > 0;
 }
 
 

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/Linux/ProcessLinux.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/Linux/ProcessLinux.h?rev=154609&r1=154608&r2=154609&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/Linux/ProcessLinux.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/Linux/ProcessLinux.h Thu Apr 12 15:08:46 2012
@@ -53,7 +53,7 @@
     ProcessLinux(lldb_private::Target& target,
                  lldb_private::Listener &listener);
 
-    virtual uint32_t
+    virtual bool
     UpdateThreadList(lldb_private::ThreadList &old_thread_list, lldb_private::ThreadList &new_thread_list);
     //------------------------------------------------------------------
     // PluginInterface protocol

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessPOSIX.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessPOSIX.cpp?rev=154609&r1=154608&r2=154609&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessPOSIX.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessPOSIX.cpp Thu Apr 12 15:08:46 2012
@@ -482,6 +482,13 @@
     return DisableSoftwareBreakpoint(bp_site);
 }
 
+uint32_t
+ProcessPOSIX::UpdateThreadListIfNeeded()
+{
+    // Do not allow recursive updates.
+    return m_thread_list.GetSize(false);
+}
+
 bool
 ProcessPOSIX::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list)
 {
@@ -489,7 +496,6 @@
     if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
         log->Printf ("ProcessPOSIX::%s() (pid = %i)", __FUNCTION__, GetID());
 
-    bool has_updated = false;
     // Update the process thread list with this new thread.
     // FIXME: We should be using tid, not pid.
     assert(m_monitor);
@@ -497,14 +503,13 @@
     if (!thread_sp) {
         ProcessSP me = this->shared_from_this();
         thread_sp.reset(new POSIXThread(me, GetID()));
-        has_updated = true;
     }
 
     if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
         log->Printf ("ProcessPOSIX::%s() updated pid = %i", __FUNCTION__, GetID());
     new_thread_list.AddThread(thread_sp);
 
-    return has_updated; // the list has been updated
+    return new_thread_list.GetSize(false) > 0;
 }
 
 ByteOrder

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessPOSIX.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessPOSIX.h?rev=154609&r1=154608&r2=154609&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessPOSIX.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/POSIX/ProcessPOSIX.h Thu Apr 12 15:08:46 2012
@@ -102,9 +102,11 @@
     virtual lldb_private::Error
     DisableBreakpoint(lldb_private::BreakpointSite *bp_site);
 
-    // This method returns true if the list was actually updated or false otherwise.
+    virtual uint32_t
+    UpdateThreadListIfNeeded();
+
     virtual bool
-    UpdateThreadList(lldb_private::ThreadList &old_thread_list,
+    UpdateThreadList(lldb_private::ThreadList &old_thread_list, 
                      lldb_private::ThreadList &new_thread_list) = 0;
 
     virtual lldb::ByteOrder

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp?rev=154609&r1=154608&r2=154609&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp Thu Apr 12 15:08:46 2012
@@ -229,14 +229,9 @@
 }
 
 bool
-GDBRemoteCommunication::GetSequenceMutex (Mutex::Locker& locker, uint32_t usec_timeout)
+GDBRemoteCommunication::GetSequenceMutex (Mutex::Locker& locker)
 {
-    if (usec_timeout == 0)
-        return locker.TryLock (m_sequence_mutex.GetMutex());
-    
-    // Wait for the lock
-    locker.Lock (m_sequence_mutex.GetMutex());
-    return true;
+    return locker.TryLock (m_sequence_mutex.GetMutex());
 }
 
 

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h?rev=154609&r1=154608&r2=154609&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h Thu Apr 12 15:08:46 2012
@@ -59,7 +59,7 @@
                         size_t payload_length);
 
     bool
-    GetSequenceMutex (lldb_private::Mutex::Locker& locker, uint32_t usec_timeout);
+    GetSequenceMutex (lldb_private::Mutex::Locker& locker);
 
     bool
     CheckForPacket (const uint8_t *src, 

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp?rev=154609&r1=154608&r2=154609&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp Thu Apr 12 15:08:46 2012
@@ -260,7 +260,7 @@
     Mutex::Locker locker;
     LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
     size_t response_len = 0;
-    if (GetSequenceMutex (locker, 0))
+    if (GetSequenceMutex (locker))
     {
         if (SendPacketNoLock (payload, payload_length))
            response_len = WaitForPacketWithTimeoutMicroSecondsNoLock (response, GetPacketTimeoutInMicroSeconds ());
@@ -351,7 +351,7 @@
         else
         {
             if (log) 
-                log->Printf("error: packet mutex taken and send_async == false, not sending packet '%*s'", (int) payload_length, payload);
+                log->Printf("error: failed to get packet sequence mutex, not sending packet '%*s'", (int) payload_length, payload);
         }
     }
     if (response_len == 0)
@@ -649,7 +649,7 @@
     if (IsRunning())
     {
         // Only send an interrupt if our debugserver is running...
-        if (GetSequenceMutex (locker, 0))
+        if (GetSequenceMutex (locker))
         {
             if (log)
                 log->Printf ("SendInterrupt () - got sequence mutex without having to interrupt");
@@ -1844,7 +1844,7 @@
     Mutex::Locker locker;
     thread_ids.clear();
     
-    if (GetSequenceMutex (locker, 0))
+    if (GetSequenceMutex (locker))
     {
         sequence_mutex_unavailable = false;
         StringExtractorGDBRemote response;
@@ -1873,6 +1873,9 @@
     }
     else
     {
+        LogSP log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_PROCESS | GDBR_LOG_PACKETS));
+        if (log)
+            log->Printf("error: failed to get packet sequence mutex, not sending packet 'qfThreadInfo'");
         sequence_mutex_unavailable = true;
     }
     return thread_ids.size();

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp?rev=154609&r1=154608&r2=154609&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp Thu Apr 12 15:08:46 2012
@@ -21,6 +21,7 @@
 // Project includes
 #include "Utility/StringExtractorGDBRemote.h"
 #include "ProcessGDBRemote.h"
+#include "ProcessGDBRemoteLog.h"
 #include "ThreadGDBRemote.h"
 #include "Utility/ARM_GCC_Registers.h"
 #include "Utility/ARM_DWARF_Registers.h"
@@ -181,7 +182,7 @@
     if (!m_reg_valid[reg])
     {
         Mutex::Locker locker;
-        if (gdb_comm.GetSequenceMutex (locker, 0))
+        if (gdb_comm.GetSequenceMutex (locker))
         {
             const bool thread_suffix_supported = gdb_comm.GetThreadSuffixSupported();
             ProcessSP process_sp (m_thread.GetProcess());
@@ -241,6 +242,12 @@
                 }
             }
         }
+        else
+        {
+            LogSP log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_THREAD | GDBR_LOG_PACKETS));
+            if (log)
+                log->Printf("error: failed to get packet sequence mutex, not sending read register for \"%s\"", reg_info->name);
+        }
 
         // Make sure we got a valid register value after reading it
         if (!m_reg_valid[reg])
@@ -331,7 +338,7 @@
                                   m_reg_data.GetByteOrder()))   // dst byte order
     {
         Mutex::Locker locker;
-        if (gdb_comm.GetSequenceMutex (locker, 0))
+        if (gdb_comm.GetSequenceMutex (locker))
         {
             const bool thread_suffix_supported = gdb_comm.GetThreadSuffixSupported();
             ProcessSP process_sp (m_thread.GetProcess());
@@ -420,6 +427,12 @@
                 }
             }
         }
+        else
+        {
+            LogSP log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_THREAD | GDBR_LOG_PACKETS));
+            if (log)
+                log->Printf("error: failed to get packet sequence mutex, not sending write register for \"%s\"", reg_info->name);
+        }
     }
     return false;
 }
@@ -440,7 +453,7 @@
     StringExtractorGDBRemote response;
 
     Mutex::Locker locker;
-    if (gdb_comm.GetSequenceMutex (locker, 0))
+    if (gdb_comm.GetSequenceMutex (locker))
     {
         char packet[32];
         const bool thread_suffix_supported = gdb_comm.GetThreadSuffixSupported();
@@ -475,6 +488,13 @@
             }
         }
     }
+    else
+    {
+        LogSP log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_THREAD | GDBR_LOG_PACKETS));
+        if (log)
+            log->Printf("error: failed to get packet sequence mutex, not sending read all registers");
+    }
+
     data_sp.reset();
     return false;
 }
@@ -496,7 +516,7 @@
 
     StringExtractorGDBRemote response;
     Mutex::Locker locker;
-    if (gdb_comm.GetSequenceMutex (locker, 0))
+    if (gdb_comm.GetSequenceMutex (locker))
     {
         const bool thread_suffix_supported = gdb_comm.GetThreadSuffixSupported();
         ProcessSP process_sp (m_thread.GetProcess());
@@ -592,6 +612,12 @@
             }
         }
     }
+    else
+    {
+        LogSP log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_THREAD | GDBR_LOG_PACKETS));
+        if (log)
+            log->Printf("error: failed to get packet sequence mutex, not sending write all registers");
+    }
     return false;
 }
 

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp?rev=154609&r1=154608&r2=154609&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp Thu Apr 12 15:08:46 2012
@@ -175,6 +175,7 @@
 {
     m_async_broadcaster.SetEventName (eBroadcastBitAsyncThreadShouldExit,   "async thread should exit");
     m_async_broadcaster.SetEventName (eBroadcastBitAsyncContinue,           "async thread continue");
+    m_async_broadcaster.SetEventName (eBroadcastBitAsyncThreadDidExit,      "async thread did exit");
 }
 
 //----------------------------------------------------------------------
@@ -927,6 +928,8 @@
     Listener listener ("gdb-remote.resume-packet-sent");
     if (listener.StartListeningForEvents (&m_gdb_comm, GDBRemoteCommunication::eBroadcastBitRunPacketSent))
     {
+        listener.StartListeningForEvents (&m_async_broadcaster, ProcessGDBRemote::eBroadcastBitAsyncThreadDidExit);
+        
         StreamString continue_packet;
         bool continue_packet_error = false;
         if (m_gdb_comm.HasAnyVContSupport ())
@@ -1122,10 +1125,29 @@
             TimeValue timeout;
             timeout = TimeValue::Now();
             timeout.OffsetWithSeconds (5);
+            if (!IS_VALID_LLDB_HOST_THREAD(m_async_thread))
+            {
+                error.SetErrorString ("Trying to resume but the async thread is dead.");
+                if (log)
+                    log->Printf ("ProcessGDBRemote::DoResume: Trying to resume but the async thread is dead.");
+                return error;
+            }
+            
             m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue, new EventDataBytes (continue_packet.GetData(), continue_packet.GetSize()));
 
             if (listener.WaitForEvent (&timeout, event_sp) == false)
+            {
                 error.SetErrorString("Resume timed out.");
+                if (log)
+                    log->Printf ("ProcessGDBRemote::DoResume: Resume timed out.");
+            }
+            else if (event_sp->BroadcasterIs (&m_async_broadcaster))
+            {
+                error.SetErrorString ("Broadcast continue, but the async thread was killed before we got an ack back.");
+                if (log)
+                    log->Printf ("ProcessGDBRemote::DoResume: Broadcast continue, but the async thread was killed before we got an ack back.");
+                return error;
+            }
         }
     }
 

Modified: lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h?rev=154609&r1=154608&r2=154609&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h Thu Apr 12 15:08:46 2012
@@ -293,7 +293,8 @@
     enum
     {
         eBroadcastBitAsyncContinue                  = (1 << 0),
-        eBroadcastBitAsyncThreadShouldExit          = (1 << 1)
+        eBroadcastBitAsyncThreadShouldExit          = (1 << 1),
+        eBroadcastBitAsyncThreadDidExit             = (1 << 2)
     };
 
     lldb_private::Flags m_flags;            // Process specific flags (see eFlags enums)

Modified: lldb/branches/lldb-platform-work/source/Target/Process.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Target/Process.cpp?rev=154609&r1=154608&r2=154609&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Target/Process.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Target/Process.cpp Thu Apr 12 15:08:46 2012
@@ -2465,8 +2465,7 @@
         case eStateCrashed:
             {
                 // During attach, prior to sending the eStateStopped event, 
-                // lldb_private::Process subclasses must set the process must set
-                // the new process ID.
+                // lldb_private::Process subclasses must set the new process ID.
                 assert (m_process->GetID() != LLDB_INVALID_PROCESS_ID);
                 if (m_exec_count > 0)
                 {
@@ -2943,6 +2942,11 @@
             m_target.GetDebugger().PopInputReader (m_process_input_reader);
         if (m_process_input_reader)
             m_process_input_reader.reset();
+            
+        // If we have been interrupted (to kill us) in the middle of running, we may not end up propagating
+        // the last events through the event system, in which case we might strand the write lock.  Unlock
+        // it here so when we do to tear down the process we don't get an error destroying the lock.
+        m_run_lock.WriteUnlock();
     }
     return error;
 }
@@ -3133,12 +3137,18 @@
 {
     if (PrivateStateThreadIsValid ())
         ControlPrivateStateThread (eBroadcastInternalStateControlStop);
+    else
+    {
+        LogSP log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+        if (log)
+            printf ("Went to stop the private state thread, but it was already invalid.");
+    }
 }
 
 void
 Process::ControlPrivateStateThread (uint32_t signal)
 {
-    LogSP log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS));
+    LogSP log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
 
     assert (signal == eBroadcastInternalStateControlStop ||
             signal == eBroadcastInternalStateControlPause ||
@@ -3160,19 +3170,36 @@
 
         timeout_time = TimeValue::Now();
         timeout_time.OffsetWithSeconds(2);
+        if (log)
+            log->Printf ("Sending control event of type: %d.", signal);
         m_private_state_control_wait.WaitForValueEqualTo (true, &timeout_time, &timed_out);
         m_private_state_control_wait.SetValue (false, eBroadcastNever);
 
         if (signal == eBroadcastInternalStateControlStop)
         {
             if (timed_out)
-                Host::ThreadCancel (private_state_thread, NULL);
+            {
+                Error error;
+                Host::ThreadCancel (private_state_thread, &error);
+                if (log)
+                    log->Printf ("Timed out responding to the control event, cancel got error: \"%s\".", error.AsCString());
+            }
+            else
+            {
+                if (log)
+                    log->Printf ("The control event killed the private state thread without having to cancel.");
+            }
 
             thread_result_t result = NULL;
             Host::ThreadJoin (private_state_thread, &result, NULL);
             m_private_state_thread = LLDB_INVALID_HOST_THREAD;
         }
     }
+    else
+    {
+        if (log)
+            log->Printf ("Private state thread already dead, no need to signal it to stop.");
+    }
 }
 
 void
@@ -3258,7 +3285,7 @@
 Process::RunPrivateStateThread ()
 {
     bool control_only = true;
-    m_private_state_control_wait.SetValue (true, eBroadcastNever);
+    m_private_state_control_wait.SetValue (false, eBroadcastNever);
 
     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
     if (log)
@@ -3271,11 +3298,13 @@
         WaitForEventsPrivate (NULL, event_sp, control_only);
         if (event_sp->BroadcasterIs(&m_private_state_control_broadcaster))
         {
+            if (log)
+                log->Printf ("Process::%s (arg = %p, pid = %llu) got a control event: %d", __FUNCTION__, this, GetID(), event_sp->GetType());
+
             switch (event_sp->GetType())
             {
             case eBroadcastInternalStateControlStop:
                 exit_now = true;
-                continue;   // Go to next loop iteration so we exit without
                 break;      // doing any internal state managment below
 
             case eBroadcastInternalStateControlPause:
@@ -3287,9 +3316,6 @@
                 break;
             }
             
-            if (log)
-                log->Printf ("Process::%s (arg = %p, pid = %llu) got a control event: %d", __FUNCTION__, this, GetID(), event_sp->GetType());
-
             m_private_state_control_wait.SetValue (true, eBroadcastAlways);
             continue;
         }





More information about the lldb-commits mailing list