<rdar://problem/12973809> 

Fixed an issue with the auto loading of script resources in debug info files. Any platform can add support for this, and on MacOSX we allow dSYM files to contain python modules that get automatically loaded when a dSYM file is associated with an executable or shared library. 

The modifications will now:
- Let the module locate the symbol file naturally instead of using a function that only works in certain cases. This helps us to locate the script resources as long as the dSYM file can be found.
- Don't try and do any of this if the script interpreter has scripting disabled.
- Allow more than one scripting resource to be found in a symbol file by returning the list
- Load the scripting resources when a symbol file is added via the "target symbols add" command.
- Be smarter about matching the dSYM mach-o file to an existing executable in the target images by stripping extensions on the symfile basname if needed.



git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@172275 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Commands/CommandObjectTarget.cpp b/source/Commands/CommandObjectTarget.cpp
index 1a6f3be..badea45 100644
--- a/source/Commands/CommandObjectTarget.cpp
+++ b/source/Commands/CommandObjectTarget.cpp
@@ -4272,7 +4272,24 @@
             // current target, so we need to find that module in the
             // target
             ModuleList matching_module_list;
-            const size_t num_matches = target->GetImages().FindModules (module_spec, matching_module_list);
+            size_t num_matches = target->GetImages().FindModules (module_spec, matching_module_list);
+            while (num_matches == 0)
+            {
+                ConstString filename_no_extension(module_spec.GetFileSpec().GetFileNameStrippingExtension());
+                // Empty string returned, lets bail
+                if (!filename_no_extension)
+                    break;
+                
+                // Check if there was no extension to strip and the basename is the same
+                if (filename_no_extension == module_spec.GetFileSpec().GetFilename())
+                    break;
+                
+                // Replace basename with one less extension
+                module_spec.GetFileSpec().GetFilename() = filename_no_extension;
+                
+                num_matches = target->GetImages().FindModules (module_spec, matching_module_list);
+            }
+
             if (num_matches > 1)
             {
                 result.AppendErrorWithFormat ("multiple modules match symbol file '%s', use the --uuid option to resolve the ambiguity.\n", symfile_path);
@@ -4309,6 +4326,12 @@
                             ModuleList module_list;
                             module_list.Append (module_sp);
                             target->ModulesDidLoad (module_list);
+                            
+                            // Make sure we load any scripting resources that may be embedded
+                            // in the debug info files in case the platform supports that.
+                            Error error;
+                            module_sp->LoadScriptingResourceInTarget (target, error);
+
                             flush = true;
                             result.SetStatus (eReturnStatusSuccessFinishResult);
                             return true;
@@ -4317,7 +4340,6 @@
                 }
                 // Clear the symbol file spec if anything went wrong
                 module_sp->SetSymbolFileFileSpec (FileSpec());
-
             }
 
             if (module_spec.GetUUID().IsValid())
diff --git a/source/Core/Module.cpp b/source/Core/Module.cpp
index 69fccfc..82abbae 100644
--- a/source/Core/Module.cpp
+++ b/source/Core/Module.cpp
@@ -1180,29 +1180,45 @@
         return false;
     }
     
-    PlatformSP platform_sp(target->GetPlatform());
-    
-    if (!platform_sp)
+    Debugger &debugger = target->GetDebugger();
+    const ScriptLanguage script_language = debugger.GetScriptLanguage();
+    if (script_language != eScriptLanguageNone)
     {
-        error.SetErrorString("invalid Platform");
-        return false;
-    }
+        
+        PlatformSP platform_sp(target->GetPlatform());
+        
+        if (!platform_sp)
+        {
+            error.SetErrorString("invalid Platform");
+            return false;
+        }
 
-    ModuleSpec module_spec(GetFileSpec());
-    FileSpec scripting_fspec = platform_sp->LocateExecutableScriptingResource(module_spec);
-    Debugger &debugger(target->GetDebugger());
-    if (scripting_fspec && scripting_fspec.Exists())
-    {
         ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter();
         if (script_interpreter)
         {
-            StreamString scripting_stream;
-            scripting_fspec.Dump(&scripting_stream);
-            const bool can_reload = false;
-            const bool init_lldb_globals = false;
-            bool did_load = script_interpreter->LoadScriptingModule(scripting_stream.GetData(), can_reload, init_lldb_globals, error);
-            if (!did_load)
-                return false;
+            FileSpecList file_specs = platform_sp->LocateExecutableScriptingResources (target,
+                                                                                       *this);
+            
+            
+            const uint32_t num_specs = file_specs.GetSize();
+            if (num_specs)
+            {
+                for (uint32_t i=0; i<num_specs; ++i)
+                {
+                    FileSpec scripting_fspec (file_specs.GetFileSpecAtIndex(i));
+                    if (scripting_fspec && scripting_fspec.Exists())
+                    {
+
+                        StreamString scripting_stream;
+                        scripting_fspec.Dump(&scripting_stream);
+                        const bool can_reload = false;
+                        const bool init_lldb_globals = false;
+                        bool did_load = script_interpreter->LoadScriptingModule(scripting_stream.GetData(), can_reload, init_lldb_globals, error);
+                        if (!did_load)
+                            return false;
+                    }
+                }
+            }
         }
         else
         {
diff --git a/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp b/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
index c0f12cd..8e15f3b 100644
--- a/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
+++ b/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
@@ -24,6 +24,8 @@
 #include "lldb/Host/Host.h"
 #include "lldb/Host/Symbols.h"
 #include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SymbolFile.h"
+#include "lldb/Symbol/SymbolVendor.h"
 #include "lldb/Target/Target.h"
 
 using namespace lldb;
@@ -50,87 +52,56 @@
 {
 }
 
-FileSpec
-PlatformDarwin::LocateExecutableScriptingResource (const ModuleSpec &module_spec)
+FileSpecList
+PlatformDarwin::LocateExecutableScriptingResources (Target *target,
+                                                    Module &module)
 {
-    const FileSpec *exec_fspec = module_spec.GetFileSpecPtr();
-    // APIs such as NSLinkModule() allow us to attach a library without a filename
-    // make sure we do not crash under those circumstances
-    if (!exec_fspec)
-        return FileSpec();
-
-    // if the arch and uuid are ever used for anything other than display purposes
-    // make sure they are not NULL before proceeding
-    const ArchSpec *arch = module_spec.GetArchitecturePtr();
-    const UUID *uuid = module_spec.GetUUIDPtr();
-    
-    const char* module_directory = exec_fspec->GetDirectory().GetCString();
-
-    // NB some extensions might be meaningful and should not be stripped - "this.binary.file"
-    // should not lose ".file" but GetFileNameStrippingExtension() will do precisely that.
-    // Ideally, we should have a per-platform list of extensions (".exe", ".app", ".dSYM", ".framework")
-    // which should be stripped while leaving "this.binary.file" as-is.
-    const char* module_basename = exec_fspec->GetFileNameStrippingExtension().GetCString();
-    
-    if (!module_directory || !module_basename)
-        return FileSpec();
-    
-    Timer scoped_timer (__PRETTY_FUNCTION__,
-                        "LocateExecutableScriptingResource (file = %s, arch = %s, uuid = %p)",
-                        exec_fspec ? exec_fspec->GetFilename().AsCString ("<NULL>") : "<NULL>",
-                        arch ? arch->GetArchitectureName() : "<NULL>",
-                        uuid);
-    
-    // FIXME: for Python, we cannot allow dots in the middle of the filenames we import.
-    // Theoretically, different scripting languages may have different sets of
-    // forbidden tokens in filenames, and that should be dealt with by each ScriptInterpreter.
-    // For now, we just replace dots with underscores, but if we ever support anything
-    // other than Python we will need to rework this
-    std::auto_ptr<char> module_basename_fixed_ap(new char[strlen(module_basename)+1]);
-    char* module_basename_fixed = module_basename_fixed_ap.get();
-    strcpy(module_basename_fixed, module_basename);
-    while (*module_basename_fixed)
+    FileSpecList file_list;
+    if (target && target->GetDebugger().GetScriptLanguage() == eScriptLanguagePython)
     {
-        if (*module_basename_fixed == '.')
-            *module_basename_fixed = '_';
-        module_basename_fixed++;
-    }
-    module_basename_fixed = module_basename_fixed_ap.get();
-    
-    FileSpec symbol_fspec (Symbols::LocateExecutableSymbolFile(module_spec));
-    
-    FileSpec script_fspec;
-    
-    StreamString path_string;
-    
-    if (symbol_fspec && symbol_fspec.Exists())
-    {
-        // for OSX we are going to be in .dSYM/Contents/Resources/DWARF/<basename>
-        // let us go to .dSYM/Contents/Resources/Python/<basename>.py and see if the file exists
-        path_string.Printf("%s/../Python/%s.py",symbol_fspec.GetDirectory().AsCString(""),module_basename_fixed);
-        script_fspec.SetFile(path_string.GetData(), true);
-        if (!script_fspec.Exists())
-            script_fspec.Clear();
-    }
-    
-    // no symbols or symbols did not have a scripting resource
-    if (!symbol_fspec || !script_fspec)
-    {
-        path_string.Clear();
-        path_string.Printf("%s.framework",module_basename);
-        if (module_directory && strstr(module_directory, path_string.GetData()))
+        // NB some extensions might be meaningful and should not be stripped - "this.binary.file"
+        // should not lose ".file" but GetFileNameStrippingExtension() will do precisely that.
+        // Ideally, we should have a per-platform list of extensions (".exe", ".app", ".dSYM", ".framework")
+        // which should be stripped while leaving "this.binary.file" as-is.
+        std::string module_basename (module.GetFileSpec().GetFileNameStrippingExtension().AsCString(""));
+        if (!module_basename.empty())
         {
-            // we are going to be in foo.framework/Versions/X/foo
-            path_string.Clear();
-            // let's go to foo.framework/Versions/X/Resources/Python/foo.py
-            path_string.Printf("%s/Resources/Python/%s.py",module_directory,module_basename_fixed);
-            script_fspec.SetFile(path_string.GetData(), true);
-            if (!script_fspec.Exists())
-                script_fspec.Clear();
+            // FIXME: for Python, we cannot allow certain characters in module
+            // filenames we import. Theoretically, different scripting languages may
+            // have different sets of forbidden tokens in filenames, and that should
+            // be dealt with by each ScriptInterpreter. For now, we just replace dots
+            // with underscores, but if we ever support anything other than Python
+            // we will need to rework this
+            std::replace(module_basename.begin(), module_basename.end(), '.', '_');
+            std::replace(module_basename.begin(), module_basename.end(), ' ', '_');
+            std::replace(module_basename.begin(), module_basename.end(), '-', '_');
+        
+            SymbolVendor *symbols = module.GetSymbolVendor ();
+            if (symbols)
+            {
+                SymbolFile *symfile = symbols->GetSymbolFile();
+                if (symfile)
+                {
+                    ObjectFile *objfile = symfile->GetObjectFile();
+                    if (objfile)
+                    {
+                        FileSpec symfile_spec (objfile->GetFileSpec());
+                        if (symfile_spec && symfile_spec.Exists())
+                        {
+                            StreamString path_string;
+                            // for OSX we are going to be in .dSYM/Contents/Resources/DWARF/<basename>
+                            // let us go to .dSYM/Contents/Resources/Python/<basename>.py and see if the file exists
+                            path_string.Printf("%s/../Python/%s.py",symfile_spec.GetDirectory().GetCString(), module_basename.c_str());
+                            FileSpec script_fspec(path_string.GetData(), true);
+                            if (script_fspec.Exists())
+                                file_list.Append (script_fspec);
+                        }
+                    }
+                }
+            }
         }
     }
-    
-    return script_fspec;
+    return file_list;
 }
 
 Error
diff --git a/source/Plugins/Platform/MacOSX/PlatformDarwin.h b/source/Plugins/Platform/MacOSX/PlatformDarwin.h
index ddb3ead..a37ae29 100644
--- a/source/Plugins/Platform/MacOSX/PlatformDarwin.h
+++ b/source/Plugins/Platform/MacOSX/PlatformDarwin.h
@@ -38,8 +38,9 @@
                        const lldb_private::ModuleSpec &sym_spec,
                        lldb_private::FileSpec &sym_file);
 
-    lldb_private::FileSpec
-    LocateExecutableScriptingResource (const lldb_private::ModuleSpec &module_spec);
+    lldb_private::FileSpecList
+    LocateExecutableScriptingResources (lldb_private::Target *target,
+                                        lldb_private::Module &module);
     
     virtual lldb_private::Error
     GetSharedModule (const lldb_private::ModuleSpec &module_spec,
diff --git a/source/Target/Platform.cpp b/source/Target/Platform.cpp
index 6dbdcb2..6b197bc 100644
--- a/source/Target/Platform.cpp
+++ b/source/Target/Platform.cpp
@@ -89,10 +89,10 @@
     return Error();
 }
 
-FileSpec
-Platform::LocateExecutableScriptingResource (const ModuleSpec &module_spec)
+FileSpecList
+Platform::LocateExecutableScriptingResources (Target *target, Module &module)
 {
-    return FileSpec();
+    return FileSpecList();
 }
 
 Error