[Lldb-commits] [lldb] r156218 - in /lldb/branches/lldb-platform-work: ./ examples/python/crashlog.py examples/python/symbolication.py source/Host/common/Host.cpp source/Host/common/Mutex.cpp source/Interpreter/ScriptInterpreterPython.cpp

Johnny Chen johnny.chen at apple.com
Fri May 4 15:40:47 PDT 2012


Author: johnny
Date: Fri May  4 17:40:46 2012
New Revision: 156218

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

Modified:
    lldb/branches/lldb-platform-work/   (props changed)
    lldb/branches/lldb-platform-work/examples/python/crashlog.py
    lldb/branches/lldb-platform-work/examples/python/symbolication.py
    lldb/branches/lldb-platform-work/source/Host/common/Host.cpp
    lldb/branches/lldb-platform-work/source/Host/common/Mutex.cpp
    lldb/branches/lldb-platform-work/source/Interpreter/ScriptInterpreterPython.cpp

Propchange: lldb/branches/lldb-platform-work/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Fri May  4 17:40:46 2012
@@ -1 +1 @@
-/lldb/trunk:154223-156116
+/lldb/trunk:154223-156201

Modified: lldb/branches/lldb-platform-work/examples/python/crashlog.py
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/examples/python/crashlog.py?rev=156218&r1=156217&r2=156218&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/examples/python/crashlog.py (original)
+++ lldb/branches/lldb-platform-work/examples/python/crashlog.py Fri May  4 17:40:46 2012
@@ -28,16 +28,19 @@
 
 import lldb
 import commands
+import cmd
+import glob
 import optparse
 import os
 import plistlib
 import pprint # pp = pprint.PrettyPrinter(indent=4); pp.pprint(command_args)
 import re
 import shlex
+import string
 import sys
 import time
 import uuid
-import lldb.utils.symbolication 
+from lldb.utils import symbolication
 
 PARSE_MODE_NORMAL = 0
 PARSE_MODE_THREAD = 1
@@ -45,7 +48,7 @@
 PARSE_MODE_THREGS = 3
 PARSE_MODE_SYSTEM = 4
 
-class CrashLog(lldb.utils.symbolication.Symbolicator):
+class CrashLog(symbolication.Symbolicator):
     """Class that does parses darwin crash logs"""
     thread_state_regex = re.compile('^Thread ([0-9]+) crashed with')
     thread_regex = re.compile('^Thread ([0-9]+)([^:]*):(.*)')
@@ -100,7 +103,7 @@
         def dump(self, prefix):
             print "%s%s" % (prefix, str(self))
     
-    class DarwinImage(lldb.utils.symbolication.Image):
+    class DarwinImage(symbolication.Image):
         """Class that represents a binary images in a darwin crash log"""
         dsymForUUIDBinary = os.path.expanduser('~rc/bin/dsymForUUID')
         if not os.path.exists(dsymForUUIDBinary):
@@ -109,8 +112,8 @@
         dwarfdump_uuid_regex = re.compile('UUID: ([-0-9a-fA-F]+) \(([^\(]+)\) .*')
         
         def __init__(self, text_addr_lo, text_addr_hi, identifier, version, uuid, path):
-            lldb.utils.symbolication.Image.__init__(self, path, uuid);
-            self.add_section (lldb.utils.symbolication.Section(text_addr_lo, text_addr_hi, "__TEXT"))
+            symbolication.Image.__init__(self, path, uuid);
+            self.add_section (symbolication.Section(text_addr_lo, text_addr_hi, "__TEXT"))
             self.identifier = identifier
             self.version = version
         
@@ -161,7 +164,7 @@
         
     def __init__(self, path):
         """CrashLog constructor that take a path to a darwin crash log file"""
-        lldb.utils.symbolication.Symbolicator.__init__(self);
+        symbolication.Symbolicator.__init__(self);
         self.path = os.path.expanduser(path);
         self.info_lines = list()
         self.system_profile = list()
@@ -316,7 +319,7 @@
     
     def create_target(self):
         #print 'crashlog.create_target()...'
-        target = lldb.utils.symbolication.Symbolicator.create_target(self)
+        target = symbolication.Symbolicator.create_target(self)
         if target:
             return target
         # We weren't able to open the main executable as, but we can still symbolicate
@@ -342,6 +345,101 @@
     print "Usage: lldb-symbolicate.py [-n name] executable-image"
     sys.exit(0)
 
+class Interactive(cmd.Cmd):
+    '''Interactive prompt for analyzing one or more Darwin crash logs, type "help" to see a list of supported commands.'''
+    image_option_parser = None
+    
+    def __init__(self, crash_logs):
+        cmd.Cmd.__init__(self)
+        self.intro = 'Interactive crashlogs prompt, type "help" to see a list of supported commands.'
+        self.crash_logs = crash_logs
+        self.prompt = '% '
+
+    def default(self, line):
+        '''Catch all for unknown command, which will exit the interpreter.'''
+        print "uknown command: %s" % line
+        return True
+
+    def do_q(self, line):
+        '''Quit command'''
+        return True
+
+    def do_quit(self, line):
+        '''Quit command'''
+        return True
+
+    def do_list(self, line=None):
+        '''Dump a list of all crash logs that are currently loaded.
+        
+        USAGE: list'''
+        print '%u crash logs are loaded:' % len(self.crash_logs)
+        for (crash_log_idx, crash_log) in enumerate(self.crash_logs):
+            print '[%u] = %s' % (crash_log_idx, crash_log.path)
+
+    def do_image(self, line):
+        '''Dump information about an image in the crash log given an image basename.
+        
+        USAGE: image <basename>'''
+        usage = "usage: %prog [options] <PATH> [PATH ...]"
+        description='''Dump information about one or more images in all crash logs. The <PATH>
+        can be a full path or a image basename.'''
+        command_args = shlex.split(line)
+        if not self.image_option_parser:
+            self.image_option_parser = optparse.OptionParser(description=description, prog='image',usage=usage)
+            self.image_option_parser.add_option('-a', '--all', action='store_true', help='show all images', default=False)
+        try:
+            (options, args) = self.image_option_parser.parse_args(command_args)
+        except:
+            return
+        
+        for image_path in args:
+            fullpath_search = image_path[0] == '/'
+            for crash_log in self.crash_logs:
+                matches_found = 0
+                for (image_idx, image) in enumerate(crash_log.images):
+                    if fullpath_search:
+                        if image.get_resolved_path() == image_path:
+                            matches_found += 1
+                            print image
+                    else:
+                        image_basename = image.get_resolved_path_basename()
+                        if image_basename == image_path:
+                            matches_found += 1
+                            print image
+                if matches_found == 0:
+                    for (image_idx, image) in enumerate(crash_log.images):
+                        if string.find(image.get_resolved_path(), image_path) >= 0:
+                            print image                            
+        return False
+
+
+def interactive_crashlogs(options, args):
+    crash_log_files = list()
+    for arg in args:
+        for resolved_path in glob.glob(arg):
+            crash_log_files.append(resolved_path)
+    
+    crash_logs = list();
+    for crash_log_file in crash_log_files:
+        #print 'crash_log_file = "%s"' % crash_log_file
+        crash_log = CrashLog(crash_log_file)
+        if crash_log.error:
+            print crash_log.error
+            continue
+        if options.verbose:
+            crash_log.dump()
+        if not crash_log.images:
+            print 'error: no images in crash log "%s"' % (crash_log)
+            continue
+        else:
+            crash_logs.append(crash_log)
+    
+    interpreter = Interactive(crash_logs)
+    # List all crash logs that were imported
+    interpreter.do_list()
+    interpreter.cmdloop()
+    
+        
 def Symbolicate(debugger, command, result, dict):
     try:
         SymbolicateCrashLog (shlex.split(command))
@@ -358,19 +456,17 @@
 created that has all of the shared libraries loaded at the load addresses found in the crash log file. This allows
 you to explore the program as if it were stopped at the locations described in the crash log and functions can 
 be disassembled and lookups can be performed using the addresses found in the crash log.'''
-    parser = optparse.OptionParser(description=description, prog='crashlog.py',usage=usage)
-    parser.add_option('--platform', type='string', metavar='platform', dest='platform', help='specify one platform by name')
+    parser = optparse.OptionParser(description=description, prog='crashlog',usage=usage)
     parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False)
-    parser.add_option('--no-images', action='store_false', dest='show_images', help='don\'t show images in stack frames', default=True)
     parser.add_option('-a', '--load-all', action='store_true', dest='load_all_images', help='load all executable images, not just the images found in the crashed stack frames', default=False)
-    parser.add_option('--image-list', action='store_true', dest='dump_image_list', help='show image list', default=False)
+    parser.add_option('--images', action='store_true', dest='dump_image_list', help='show image list', default=False)
     parser.add_option('-g', '--debug-delay', type='int', dest='debug_delay', metavar='NSEC', help='pause for NSEC seconds for debugger', default=0)
     parser.add_option('-c', '--crashed-only', action='store_true', dest='crashed_only', help='only symbolicate the crashed thread', default=False)
     parser.add_option('-d', '--disasm-depth', type='int', dest='disassemble_depth', help='set the depth in stack frames that should be disassembled (default is 1)', default=1)
     parser.add_option('-D', '--disasm-all', action='store_true', dest='disassemble_all_threads', help='enabled disassembly of frames on all threads (not just the crashed thread)', default=False)
     parser.add_option('-B', '--disasm-before', type='int', dest='disassemble_before', help='the number of instructions to disassemble before the frame PC', default=4)
     parser.add_option('-A', '--disasm-after', type='int', dest='disassemble_after', help='the number of instructions to disassemble after the frame PC', default=4)
-    loaded_addresses = False
+    parser.add_option('-i', '--interactive', action='store_true', help='parse all crash logs and enter interactive mode', default=False)
     try:
         (options, args) = parser.parse_args(command_args)
     except:
@@ -385,85 +481,89 @@
         print "Waiting %u seconds for debugger to attach..." % options.debug_delay
         time.sleep(options.debug_delay)
     error = lldb.SBError()
+        
     if args:
-        for crash_log_file in args:
-            crash_log = CrashLog(crash_log_file)
-            
-            #pp = pprint.PrettyPrinter(indent=4); pp.pprint(args)
-            if crash_log.error:
-                print crash_log.error
-                return
-            if options.verbose:
-                crash_log.dump()
-            if not crash_log.images:
-                print 'error: no images in crash log'
-                return
-
-            target = crash_log.create_target ()
-            if not target:
-                return
-            exe_module = target.GetModuleAtIndex(0)
-            images_to_load = list()
-            loaded_images = list()
-            if options.load_all_images:
-                # --load-all option was specified, load everything up
-                for image in crash_log.images:
-                    images_to_load.append(image)
-            else:
-                # Only load the images found in stack frames for the crashed threads
-                for ident in crash_log.idents:
-                    images = crash_log.find_images_with_identifier (ident)
-                    if images:
-                        for image in images:
-                            images_to_load.append(image)
-                    else:
-                        print 'error: can\'t find image for identifier "%s"' % ident
+        if options.interactive:
+            interactive_crashlogs(options, args)
+        else:
+            for crash_log_file in args:
+                crash_log = CrashLog(crash_log_file)
             
-            for image in images_to_load:
-                if image in loaded_images:
-                    print "warning: skipping %s loaded at %#16.16x duplicate entry (probably commpage)" % (image.path, image.text_addr_lo)
+                #pp = pprint.PrettyPrinter(indent=4); pp.pprint(args)
+                if crash_log.error:
+                    print crash_log.error
+                    return
+                if options.verbose:
+                    crash_log.dump()
+                if not crash_log.images:
+                    print 'error: no images in crash log'
+                    return
+
+                target = crash_log.create_target ()
+                if not target:
+                    return
+                exe_module = target.GetModuleAtIndex(0)
+                images_to_load = list()
+                loaded_images = list()
+                if options.load_all_images:
+                    # --load-all option was specified, load everything up
+                    for image in crash_log.images:
+                        images_to_load.append(image)
                 else:
-                    err = image.add_module (target)
-                    if err:
-                        print err
+                    # Only load the images found in stack frames for the crashed threads
+                    for ident in crash_log.idents:
+                        images = crash_log.find_images_with_identifier (ident)
+                        if images:
+                            for image in images:
+                                images_to_load.append(image)
+                        else:
+                            print 'error: can\'t find image for identifier "%s"' % ident
+            
+                for image in images_to_load:
+                    if image in loaded_images:
+                        print "warning: skipping %s loaded at %#16.16x duplicate entry (probably commpage)" % (image.path, image.text_addr_lo)
                     else:
-                        #print 'loaded %s' % image
-                        loaded_images.append(image)
+                        err = image.add_module (target)
+                        if err:
+                            print err
+                        else:
+                            #print 'loaded %s' % image
+                            loaded_images.append(image)
             
-            for thread in crash_log.threads:
-                this_thread_crashed = thread.did_crash()
-                if options.crashed_only and this_thread_crashed == False:
-                    continue
-                print "%s" % thread
-                #prev_frame_index = -1
-                for frame_idx, frame in enumerate(thread.frames):
-                    disassemble = (this_thread_crashed or options.disassemble_all_threads) and frame_idx < options.disassemble_depth;
-                    symbolicated_frame_addresses = crash_log.symbolicate (frame.pc)
-                    if symbolicated_frame_addresses:
-                        symbolicated_frame_address_idx = 0
-                        for symbolicated_frame_address in symbolicated_frame_addresses:
-                            print '[%3u] %s' % (frame_idx, symbolicated_frame_address)
+                for thread in crash_log.threads:
+                    this_thread_crashed = thread.did_crash()
+                    if options.crashed_only and this_thread_crashed == False:
+                        continue
+                    print "%s" % thread
+                    #prev_frame_index = -1
+                    for frame_idx, frame in enumerate(thread.frames):
+                        disassemble = (this_thread_crashed or options.disassemble_all_threads) and frame_idx < options.disassemble_depth;
+                        symbolicated_frame_addresses = crash_log.symbolicate (frame.pc)
+                        if symbolicated_frame_addresses:
+                            symbolicated_frame_address_idx = 0
+                            for symbolicated_frame_address in symbolicated_frame_addresses:
+                                print '[%3u] %s' % (frame_idx, symbolicated_frame_address)
                             
-                            if symbolicated_frame_address_idx == 0:
-                                if disassemble:
-                                    instructions = symbolicated_frame_address.get_instructions()
-                                    if instructions:
-                                        print
-                                        lldb.utils.symbolication.disassemble_instructions (target, 
-                                                                                           instructions, 
-                                                                                           frame.pc, 
-                                                                                           options.disassemble_before, 
-                                                                                           options.disassemble_after, frame.index > 0)
-                                        print
-                            symbolicated_frame_address_idx += 1
-                    else:
-                        print frame
-                print                
-
-            if options.dump_image_list:
-                print "Binary Images:"
-                for image in crash_log.images:
-                    print image
+                                if symbolicated_frame_address_idx == 0:
+                                    if disassemble:
+                                        instructions = symbolicated_frame_address.get_instructions()
+                                        if instructions:
+                                            print
+                                            symbolication.disassemble_instructions (target, 
+                                                                                    instructions, 
+                                                                                    frame.pc, 
+                                                                                    options.disassemble_before, 
+                                                                                    options.disassemble_after, frame.index > 0)
+                                            print
+                                symbolicated_frame_address_idx += 1
+                        else:
+                            print frame
+                    print                
+
+                if options.dump_image_list:
+                    print "Binary Images:"
+                    for image in crash_log.images:
+                        print image
 
 if __name__ == '__main__':
     # Create a new debugger instance

Modified: lldb/branches/lldb-platform-work/examples/python/symbolication.py
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/examples/python/symbolication.py?rev=156218&r1=156217&r2=156218&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/examples/python/symbolication.py (original)
+++ lldb/branches/lldb-platform-work/examples/python/symbolication.py Fri May  4 17:40:46 2012
@@ -206,7 +206,7 @@
         print "%s%s" % (prefix, self)
     
     def __str__(self):
-        s = "%s %s" % (self.get_uuid(), self.get_resolved_path())
+        s = "%s %s %s" % (self.get_uuid(), self.version, self.get_resolved_path())
         for section_info in self.section_infos:
             s += ", %s" % (section_info)
         if self.slide != None:

Modified: lldb/branches/lldb-platform-work/source/Host/common/Host.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Host/common/Host.cpp?rev=156218&r1=156217&r2=156218&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Host/common/Host.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Host/common/Host.cpp Fri May  4 17:40:46 2012
@@ -14,6 +14,7 @@
 #include "lldb/Core/Error.h"
 #include "lldb/Core/Log.h"
 #include "lldb/Core/StreamString.h"
+#include "lldb/Core/ThreadSafeSTLMap.h"
 #include "lldb/Host/Config.h"
 #include "lldb/Host/Endian.h"
 #include "lldb/Host/FileSpec.h"
@@ -610,6 +611,24 @@
     return err == 0;
 }
 
+// rdar://problem/8153284
+// Fixed a crasher where during shutdown, loggings attempted to access the
+// thread name but the static map instance had already been destructed.
+// So we are using a ThreadSafeSTLMap POINTER, initializing it with a
+// pthread_once action.  That map will get leaked.
+//
+// Another approach is to introduce a static guard object which monitors its
+// own destruction and raises a flag, but this incurs more overhead.
+
+static pthread_once_t g_thread_map_once = PTHREAD_ONCE_INIT;
+static ThreadSafeSTLMap<uint64_t, std::string> *g_thread_names_map_ptr;
+
+static void
+InitThreadNamesMap()
+{
+    g_thread_names_map_ptr = new ThreadSafeSTLMap<uint64_t, std::string>();
+}
+
 //------------------------------------------------------------------
 // Control access to a static file thread name map using a single
 // static function to avoid a static constructor.
@@ -617,31 +636,26 @@
 static const char *
 ThreadNameAccessor (bool get, lldb::pid_t pid, lldb::tid_t tid, const char *name)
 {
+    int success = ::pthread_once (&g_thread_map_once, InitThreadNamesMap);
+    if (success != 0)
+        return NULL;
+    
     uint64_t pid_tid = ((uint64_t)pid << 32) | (uint64_t)tid;
 
-    static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
-    Mutex::Locker locker(&g_mutex);
-
-    typedef std::map<uint64_t, std::string> thread_name_map;
-    // rdar://problem/8153284
-    // Fixed a crasher where during shutdown, loggings attempted to access the
-    // thread name but the static map instance had already been destructed.
-    // Another approach is to introduce a static guard object which monitors its
-    // own destruction and raises a flag, but this incurs more overhead.
-    static thread_name_map *g_thread_names_ptr = new thread_name_map();
-    thread_name_map &g_thread_names = *g_thread_names_ptr;
-
     if (get)
     {
         // See if the thread name exists in our thread name pool
-        thread_name_map::iterator pos = g_thread_names.find(pid_tid);
-        if (pos != g_thread_names.end())
-            return pos->second.c_str();
+        std::string value;
+        bool found_it = g_thread_names_map_ptr->GetValueForKey (pid_tid, value);
+        if (found_it)
+            return value.c_str();
+        else
+            return NULL;
     }
-    else
+    else if (name)
     {
         // Set the thread name
-        g_thread_names[pid_tid] = name;
+        g_thread_names_map_ptr->SetValueForKey (pid_tid, std::string(name));
     }
     return NULL;
 }

Modified: lldb/branches/lldb-platform-work/source/Host/common/Mutex.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Host/common/Mutex.cpp?rev=156218&r1=156217&r2=156218&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Host/common/Mutex.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Host/common/Mutex.cpp Fri May  4 17:40:46 2012
@@ -132,8 +132,7 @@
 Mutex::Locker::Locker (pthread_mutex_t *mutex_ptr) :
     m_mutex_ptr (NULL)
 {
-    if (m_mutex_ptr)
-        Lock (m_mutex_ptr);
+    Lock (mutex_ptr);
 }
 
 //----------------------------------------------------------------------

Modified: lldb/branches/lldb-platform-work/source/Interpreter/ScriptInterpreterPython.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Interpreter/ScriptInterpreterPython.cpp?rev=156218&r1=156217&r2=156218&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Interpreter/ScriptInterpreterPython.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Interpreter/ScriptInterpreterPython.cpp Fri May  4 17:40:46 2012
@@ -386,7 +386,10 @@
     // in some (rare) cases during cleanup Python may end up believing we have no thread state
     // and PyImport_AddModule will crash if that is the case - since that seems to only happen
     // when destroying the SBDebugger, we can make do without clearing up stdout and stderr
-    if (PyThreadState_Get())
+
+    // rdar://problem/11292882
+    // When the current thread state is NULL, PyThreadState_Get() issues a fatal error.
+    if (PyThreadState_GetDict())
     {
         PyObject *sysmod = PyImport_AddModule ("sys");
         PyObject *sysdict = PyModule_GetDict (sysmod);





More information about the lldb-commits mailing list