[Lldb-commits] [lldb] r235737 - Look for both .debug and dsym debugging symbol information for stripped executable.

Robert Flack flackr at gmail.com
Fri Apr 24 11:09:54 PDT 2015


Author: flackr
Date: Fri Apr 24 13:09:54 2015
New Revision: 235737

URL: http://llvm.org/viewvc/llvm-project?rev=235737&view=rev
Log:
Look for both .debug and dsym debugging symbol information for stripped executable.

Currently Symbols::LocateExecutableSymbolFile on MacOSX only looks for external
dsym debugging information, however if running on a stripped dwarf executable it
should also check for a .debug file as well.

Test Plan:
./dotest.py $DOTEST_OPTS -t -p TestSharedLibStrippedSymbols.py
This test now passes when running a remote Mac -> Linux test, and still passes
running locally on Mac or locally on Linux.

Differential Revision: http://reviews.llvm.org/D9174

Modified:
    lldb/trunk/source/Host/common/Symbols.cpp
    lldb/trunk/source/Host/macosx/Symbols.cpp

Modified: lldb/trunk/source/Host/common/Symbols.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/common/Symbols.cpp?rev=235737&r1=235736&r2=235737&view=diff
==============================================================================
--- lldb/trunk/source/Host/common/Symbols.cpp (original)
+++ lldb/trunk/source/Host/common/Symbols.cpp Fri Apr 24 13:09:54 2015
@@ -18,139 +18,253 @@
 #include "lldb/Core/UUID.h"
 #include "lldb/Symbol/ObjectFile.h"
 #include "lldb/Target/Target.h"
+#include "lldb/Utility/SafeMachO.h"
 
 #include "llvm/Support/FileSystem.h"
 
+// From MacOSX system header "mach/machine.h"
+typedef int cpu_type_t;
+typedef int cpu_subtype_t;
+
 using namespace lldb;
 using namespace lldb_private;
+using namespace llvm::MachO;
+
+#if defined(__APPLE__)
+
+// Forward declaration of method defined in source/Host/macosx/Symbols.cpp
+int
+LocateMacOSXFilesUsingDebugSymbols
+(
+    const ModuleSpec &module_spec,
+    FileSpec *out_exec_fspec,   // If non-NULL, try and find the executable
+    FileSpec *out_dsym_fspec    // If non-NULL try and find the debug symbol file
+);
+
+#else
+
+int
+LocateMacOSXFilesUsingDebugSymbols
+(
+    const ModuleSpec &module_spec,
+    FileSpec *out_exec_fspec,   // If non-NULL, try and find the executable
+    FileSpec *out_dsym_fspec    // If non-NULL try and find the debug symbol file
+) {
+    // Cannot find MacOSX files using debug symbols on non MacOSX.
+    return 0;
+}
+
+#endif
+
+static bool
+LocateDSYMInVincinityOfExecutable (const ModuleSpec &module_spec, FileSpec &dsym_fspec)
+{
+    const FileSpec *exec_fspec = module_spec.GetFileSpecPtr();
+    if (exec_fspec)
+    {
+        char path[PATH_MAX];
+        if (exec_fspec->GetPath(path, sizeof(path)))
+        {
+            // Make sure the module isn't already just a dSYM file...
+            if (strcasestr(path, ".dSYM/Contents/Resources/DWARF") == NULL)
+            {
+                size_t obj_file_path_length = strlen(path);
+                ::strncat(path, ".dSYM/Contents/Resources/DWARF/", sizeof(path) - strlen(path) - 1);
+                ::strncat(path, exec_fspec->GetFilename().AsCString(), sizeof(path) - strlen(path) - 1);
+
+                dsym_fspec.SetFile(path, false);
+
+                ModuleSpecList module_specs;
+                ModuleSpec matched_module_spec;
+                if (dsym_fspec.Exists() &&
+                    ObjectFile::GetModuleSpecifications(dsym_fspec, 0, 0, module_specs) &&
+                    module_specs.FindMatchingModuleSpec(module_spec, matched_module_spec))
+                {
+                    return true;
+                }
+                else
+                {
+                    path[obj_file_path_length] = '\0';
+
+                    char *last_dot = strrchr(path, '.');
+                    while (last_dot != NULL && last_dot[0])
+                    {
+                        char *next_slash = strchr(last_dot, '/');
+                        if (next_slash != NULL)
+                        {
+                            *next_slash = '\0';
+                            ::strncat(path, ".dSYM/Contents/Resources/DWARF/", sizeof(path) - strlen(path) - 1);
+                            ::strncat(path, exec_fspec->GetFilename().AsCString(), sizeof(path) - strlen(path) - 1);
+                            dsym_fspec.SetFile(path, false);
+                            if (dsym_fspec.Exists() &&
+                                ObjectFile::GetModuleSpecifications(dsym_fspec, 0, 0, module_specs) &&
+                                module_specs.FindMatchingModuleSpec(module_spec, matched_module_spec))
+                            {
+                                return true;
+                            }
+                            else
+                            {
+                                *last_dot = '\0';
+                                char *prev_slash = strrchr(path, '/');
+                                if (prev_slash != NULL)
+                                    *prev_slash = '\0';
+                                else
+                                    break;
+                            }
+                        }
+                        else
+                        {
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+    }
+    dsym_fspec.Clear();
+    return false;
+}
 
-#if defined (__linux__) || defined (__FreeBSD__)
+FileSpec
+LocateExecutableSymbolFileDsym (const ModuleSpec &module_spec)
+{
+    const FileSpec *exec_fspec = module_spec.GetFileSpecPtr();
+    const ArchSpec *arch = module_spec.GetArchitecturePtr();
+    const UUID *uuid = module_spec.GetUUIDPtr();
+
+    Timer scoped_timer (__PRETTY_FUNCTION__,
+                        "LocateExecutableSymbolFileDsym (file = %s, arch = %s, uuid = %p)",
+                        exec_fspec ? exec_fspec->GetFilename().AsCString ("<NULL>") : "<NULL>",
+                        arch ? arch->GetArchitectureName() : "<NULL>",
+                        uuid);
+
+    FileSpec symbol_fspec;
+    // First try and find the dSYM in the same directory as the executable or in
+    // an appropriate parent directory
+    if (LocateDSYMInVincinityOfExecutable (module_spec, symbol_fspec) == false)
+    {
+        // We failed to easily find the dSYM above, so use DebugSymbols
+        LocateMacOSXFilesUsingDebugSymbols (module_spec, NULL, &symbol_fspec);
+    }
+    return symbol_fspec;
+}
 
 FileSpec
 Symbols::LocateExecutableObjectFile (const ModuleSpec &module_spec)
 {
-    // FIXME
-    return FileSpec();
+    const FileSpec *exec_fspec = module_spec.GetFileSpecPtr();
+    const ArchSpec *arch = module_spec.GetArchitecturePtr();
+    const UUID *uuid = module_spec.GetUUIDPtr();
+    Timer scoped_timer (__PRETTY_FUNCTION__,
+                        "LocateExecutableObjectFile (file = %s, arch = %s, uuid = %p)",
+                        exec_fspec ? exec_fspec->GetFilename().AsCString ("<NULL>") : "<NULL>",
+                        arch ? arch->GetArchitectureName() : "<NULL>",
+                        uuid);
+
+    FileSpec objfile_fspec;
+    ModuleSpecList module_specs;
+    ModuleSpec matched_module_spec;
+    if (exec_fspec &&
+        ObjectFile::GetModuleSpecifications(*exec_fspec, 0, 0, module_specs) &&
+        module_specs.FindMatchingModuleSpec(module_spec, matched_module_spec))
+    {
+        objfile_fspec = exec_fspec;
+    }
+    else
+    {
+        LocateMacOSXFilesUsingDebugSymbols (module_spec, &objfile_fspec, NULL);
+    }
+    return objfile_fspec;
 }
 
 FileSpec
 Symbols::LocateExecutableSymbolFile (const ModuleSpec &module_spec)
 {
     const char *symbol_filename = module_spec.GetSymbolFileSpec().GetFilename().AsCString();
-    if (!symbol_filename || !symbol_filename[0])
-        return FileSpec();
-
-    FileSpecList debug_file_search_paths (Target::GetDefaultDebugFileSearchPaths());
-
-    // Add module directory.
-    const ConstString &file_dir = module_spec.GetFileSpec().GetDirectory();
-    debug_file_search_paths.AppendIfUnique (FileSpec(file_dir.AsCString("."), true));
+    if (symbol_filename && symbol_filename[0])
+    {
+        FileSpecList debug_file_search_paths (Target::GetDefaultDebugFileSearchPaths());
 
-    // Add current working directory.
-    debug_file_search_paths.AppendIfUnique (FileSpec(".", true));
+        // Add module directory.
+        const ConstString &file_dir = module_spec.GetFileSpec().GetDirectory();
+        debug_file_search_paths.AppendIfUnique (FileSpec(file_dir.AsCString("."), true));
 
-    // Add /usr/lib/debug directory.
-    debug_file_search_paths.AppendIfUnique (FileSpec("/usr/lib/debug", true));
+        // Add current working directory.
+        debug_file_search_paths.AppendIfUnique (FileSpec(".", true));
 
-    std::string uuid_str;
-    const UUID &module_uuid = module_spec.GetUUID();
-    if (module_uuid.IsValid())
-    {
-        // Some debug files are stored in the .build-id directory like this:
-        //   /usr/lib/debug/.build-id/ff/e7fe727889ad82bb153de2ad065b2189693315.debug
-        uuid_str = module_uuid.GetAsString("");
-        uuid_str.insert (2, 1, '/');
-        uuid_str = uuid_str + ".debug";
-    }
+        // Add /usr/lib/debug directory.
+        debug_file_search_paths.AppendIfUnique (FileSpec("/usr/lib/debug", true));
 
-    // Get directory of our module. Needed to check debug files like this:
-    //   /usr/lib/debug/usr/lib/library.so.debug
-    std::string module_directory = module_spec.GetFileSpec().GetDirectory().AsCString();
+        std::string uuid_str;
+        const UUID &module_uuid = module_spec.GetUUID();
+        if (module_uuid.IsValid())
+        {
+            // Some debug files are stored in the .build-id directory like this:
+            //   /usr/lib/debug/.build-id/ff/e7fe727889ad82bb153de2ad065b2189693315.debug
+            uuid_str = module_uuid.GetAsString("");
+            uuid_str.insert (2, 1, '/');
+            uuid_str = uuid_str + ".debug";
+        }
 
-    size_t num_directories = debug_file_search_paths.GetSize();
-    for (size_t idx = 0; idx < num_directories; ++idx)
-    {
-        FileSpec dirspec = debug_file_search_paths.GetFileSpecAtIndex (idx);
-        dirspec.ResolvePath();
-        if (!dirspec.Exists() || !dirspec.IsDirectory())
-            continue;
-
-        std::vector<std::string> files;
-        std::string dirname = dirspec.GetPath();
-
-        files.push_back (dirname + "/" + symbol_filename);
-        files.push_back (dirname + "/.debug/" + symbol_filename);
-        files.push_back (dirname + "/.build-id/" + uuid_str);
-        files.push_back (dirname + module_directory + "/" + symbol_filename);
+        // Get directory of our module. Needed to check debug files like this:
+        //   /usr/lib/debug/usr/lib/library.so.debug
+        std::string module_directory = module_spec.GetFileSpec().GetDirectory().AsCString();
 
-        const uint32_t num_files = files.size();
-        for (size_t idx_file = 0; idx_file < num_files; ++idx_file)
+        size_t num_directories = debug_file_search_paths.GetSize();
+        for (size_t idx = 0; idx < num_directories; ++idx)
         {
-            const std::string &filename = files[idx_file];
-            FileSpec file_spec (filename.c_str(), true);
-
-            if (llvm::sys::fs::equivalent (file_spec.GetPath(), module_spec.GetFileSpec().GetPath()))
+            FileSpec dirspec = debug_file_search_paths.GetFileSpecAtIndex (idx);
+            dirspec.ResolvePath();
+            if (!dirspec.Exists() || !dirspec.IsDirectory())
                 continue;
 
-            if (file_spec.Exists())
+            std::vector<std::string> files;
+            std::string dirname = dirspec.GetPath();
+
+            files.push_back (dirname + "/" + symbol_filename);
+            files.push_back (dirname + "/.debug/" + symbol_filename);
+            files.push_back (dirname + "/.build-id/" + uuid_str);
+            files.push_back (dirname + module_directory + "/" + symbol_filename);
+
+            const uint32_t num_files = files.size();
+            for (size_t idx_file = 0; idx_file < num_files; ++idx_file)
             {
-                lldb_private::ModuleSpecList specs;
-                const size_t num_specs = ObjectFile::GetModuleSpecifications (file_spec, 0, 0, specs);
-                assert (num_specs <= 1 && "Symbol Vendor supports only a single architecture");
-                if (num_specs == 1)
+                const std::string &filename = files[idx_file];
+                FileSpec file_spec (filename.c_str(), true);
+
+                if (llvm::sys::fs::equivalent (file_spec.GetPath(), module_spec.GetFileSpec().GetPath()))
+                    continue;
+
+                if (file_spec.Exists())
                 {
-                    ModuleSpec mspec;
-                    if (specs.GetModuleSpecAtIndex (0, mspec))
+                    lldb_private::ModuleSpecList specs;
+                    const size_t num_specs = ObjectFile::GetModuleSpecifications (file_spec, 0, 0, specs);
+                    assert (num_specs <= 1 && "Symbol Vendor supports only a single architecture");
+                    if (num_specs == 1)
                     {
-                        if (mspec.GetUUID() == module_uuid)
-                            return file_spec;
+                        ModuleSpec mspec;
+                        if (specs.GetModuleSpecAtIndex (0, mspec))
+                        {
+                            if (mspec.GetUUID() == module_uuid)
+                                return file_spec;
+                        }
                     }
                 }
             }
         }
     }
 
-    return FileSpec();
+    return LocateExecutableSymbolFileDsym(module_spec);
 }
 
-FileSpec
-Symbols::FindSymbolFileInBundle (const FileSpec& symfile_bundle,
-                                 const lldb_private::UUID *uuid,
-                                 const ArchSpec *arch)
-{
-    // FIXME
-    return FileSpec();
-}
-
-bool
-Symbols::DownloadObjectAndSymbolFile (ModuleSpec &module_spec, bool force_lookup)
-{
-    // Fill in the module_spec.GetFileSpec() for the object file and/or the
-    // module_spec.GetSymbolFileSpec() for the debug symbols file.
-    return false;
-}
-
-#elif !defined (__APPLE__)
-
-FileSpec
-Symbols::LocateExecutableObjectFile (const ModuleSpec &module_spec)
-{
-    // FIXME
-    return FileSpec();
-}
-
-FileSpec
-Symbols::LocateExecutableSymbolFile (const ModuleSpec &module_spec)
-{
-    // FIXME
-    return FileSpec();
-}
+#if !defined (__APPLE__)
 
 FileSpec
 Symbols::FindSymbolFileInBundle (const FileSpec& symfile_bundle,
                                  const lldb_private::UUID *uuid,
                                  const ArchSpec *arch)
 {
+    // FIXME
     return FileSpec();
 }
 

Modified: lldb/trunk/source/Host/macosx/Symbols.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/macosx/Symbols.cpp?rev=235737&r1=235736&r2=235737&view=diff
==============================================================================
--- lldb/trunk/source/Host/macosx/Symbols.cpp (original)
+++ lldb/trunk/source/Host/macosx/Symbols.cpp Fri Apr 24 13:09:54 2015
@@ -29,6 +29,7 @@
 #include "lldb/Core/UUID.h"
 #include "lldb/Host/Endian.h"
 #include "lldb/Host/Host.h"
+#include "lldb/Symbol/ObjectFile.h"
 #include "lldb/Utility/CleanUp.h"
 #include "Host/macosx/cfcpp/CFCBundle.h"
 #include "Host/macosx/cfcpp/CFCData.h"
@@ -36,7 +37,6 @@
 #include "Host/macosx/cfcpp/CFCString.h"
 #include "mach/machine.h"
 
-
 using namespace lldb;
 using namespace lldb_private;
 using namespace llvm::MachO;
@@ -50,234 +50,7 @@ CFDictionaryRef DBGCopyDSYMPropertyLists
 }
 #endif
 
-static bool
-SkinnyMachOFileContainsArchAndUUID
-(
-    const FileSpec &file_spec,
-    const ArchSpec *arch,
-    const lldb_private::UUID *uuid,   // the UUID we are looking for
-    off_t file_offset,
-    DataExtractor& data,
-    lldb::offset_t data_offset,
-    const uint32_t magic
-)
-{
-    assert(magic == MH_MAGIC || magic == MH_CIGAM || magic == MH_MAGIC_64 || magic == MH_CIGAM_64);
-    if (magic == MH_MAGIC || magic == MH_MAGIC_64)
-        data.SetByteOrder (lldb::endian::InlHostByteOrder());
-    else if (lldb::endian::InlHostByteOrder() == eByteOrderBig)
-        data.SetByteOrder (eByteOrderLittle);
-    else
-        data.SetByteOrder (eByteOrderBig);
-
-    uint32_t i;
-    const uint32_t cputype      = data.GetU32(&data_offset);    // cpu specifier
-    const uint32_t cpusubtype   = data.GetU32(&data_offset);    // machine specifier
-    data_offset+=4; // Skip mach file type
-    const uint32_t ncmds        = data.GetU32(&data_offset);    // number of load commands
-    const uint32_t sizeofcmds   = data.GetU32(&data_offset);    // the size of all the load commands
-    data_offset+=4; // Skip flags
-
-    // Check the architecture if we have a valid arch pointer
-    if (arch)
-    {
-        ArchSpec file_arch(eArchTypeMachO, cputype, cpusubtype);
-
-        if (!file_arch.IsCompatibleMatch(*arch))
-            return false;
-    }
-
-    // The file exists, and if a valid arch pointer was passed in we know
-    // if already matches, so we can return if we aren't looking for a specific
-    // UUID
-    if (uuid == NULL)
-        return true;
-
-    if (magic == MH_CIGAM_64 || magic == MH_MAGIC_64)
-        data_offset += 4;   // Skip reserved field for in mach_header_64
-
-    // Make sure we have enough data for all the load commands
-    if (magic == MH_CIGAM_64 || magic == MH_MAGIC_64)
-    {
-        if (data.GetByteSize() < sizeof(struct mach_header_64) + sizeofcmds)
-        {
-            DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset, sizeof(struct mach_header_64) + sizeofcmds));
-            data.SetData (data_buffer_sp);
-        }
-    }
-    else
-    {
-        if (data.GetByteSize() < sizeof(struct mach_header) + sizeofcmds)
-        {
-            DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset, sizeof(struct mach_header) + sizeofcmds));
-            data.SetData (data_buffer_sp);
-        }
-    }
-
-    for (i=0; i<ncmds; i++)
-    {
-        const lldb::offset_t cmd_offset = data_offset;    // Save this data_offset in case parsing of the segment goes awry!
-        uint32_t cmd        = data.GetU32(&data_offset);
-        uint32_t cmd_size   = data.GetU32(&data_offset);
-        if (cmd == LC_UUID)
-        {
-            lldb_private::UUID file_uuid (data.GetData(&data_offset, 16), 16);
-            if (file_uuid == *uuid)
-                return true;
-            return false;
-        }
-        data_offset = cmd_offset + cmd_size;
-    }
-    return false;
-}
-
-bool
-UniversalMachOFileContainsArchAndUUID
-(
-    const FileSpec &file_spec,
-    const ArchSpec *arch,
-    const lldb_private::UUID *uuid,
-    off_t file_offset,
-    DataExtractor& data,
-    lldb::offset_t data_offset,
-    const uint32_t magic
-)
-{
-    assert(magic == FAT_MAGIC || magic == FAT_CIGAM);
-
-    // Universal mach-o files always have their headers encoded as BIG endian
-    data.SetByteOrder(eByteOrderBig);
-
-    uint32_t i;
-    const uint32_t nfat_arch = data.GetU32(&data_offset);   // number of structs that follow
-    const uint32_t fat_header_and_arch_size = sizeof(struct fat_header) + nfat_arch * sizeof(struct fat_arch);
-    if (data.GetByteSize() < fat_header_and_arch_size)
-    {
-        DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset, fat_header_and_arch_size));
-        data.SetData (data_buffer_sp);
-    }
-
-    for (i=0; i<nfat_arch; i++)
-    {
-        cpu_type_t      arch_cputype        = data.GetU32(&data_offset);    // cpu specifier (int)
-        cpu_subtype_t   arch_cpusubtype     = data.GetU32(&data_offset);    // machine specifier (int)
-        uint32_t        arch_offset         = data.GetU32(&data_offset);    // file offset to this object file
-    //  uint32_t        arch_size           = data.GetU32(&data_offset);    // size of this object file
-    //  uint32_t        arch_align          = data.GetU32(&data_offset);    // alignment as a power of 2
-        data_offset += 8;   // Skip size and align as we don't need those
-        // Only process this slice if the cpu type/subtype matches
-        if (arch)
-        {
-            ArchSpec fat_arch(eArchTypeMachO, arch_cputype, arch_cpusubtype);
-            if (!fat_arch.IsExactMatch(*arch))
-                continue;
-        }
-
-        // Create a buffer with only the arch slice date in it
-        DataExtractor arch_data;
-        DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset + arch_offset, 0x1000));
-        arch_data.SetData(data_buffer_sp);
-        lldb::offset_t arch_data_offset = 0;
-        uint32_t arch_magic = arch_data.GetU32(&arch_data_offset);
-
-        switch (arch_magic)
-        {
-        case MH_MAGIC:
-        case MH_CIGAM:
-        case MH_MAGIC_64:
-        case MH_CIGAM_64:
-            if (SkinnyMachOFileContainsArchAndUUID (file_spec, arch, uuid, file_offset + arch_offset, arch_data, arch_data_offset, arch_magic))
-                return true;
-            break;
-        }
-    }
-    return false;
-}
-
-static bool
-FileAtPathContainsArchAndUUID
-(
-    const FileSpec &file_spec,
-    const ArchSpec *arch,
-    const lldb_private::UUID *uuid
-)
-{
-    DataExtractor data;
-    off_t file_offset = 0;
-    DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset, 0x1000));
-
-    if (data_buffer_sp && data_buffer_sp->GetByteSize() > 0)
-    {
-        data.SetData(data_buffer_sp);
-
-        lldb::offset_t data_offset = 0;
-        uint32_t magic = data.GetU32(&data_offset);
-
-        switch (magic)
-        {
-        // 32 bit mach-o file
-        case MH_MAGIC:
-        case MH_CIGAM:
-        case MH_MAGIC_64:
-        case MH_CIGAM_64:
-            return SkinnyMachOFileContainsArchAndUUID (file_spec, arch, uuid, file_offset, data, data_offset, magic);
-
-        // fat mach-o file
-        case FAT_MAGIC:
-        case FAT_CIGAM:
-            return UniversalMachOFileContainsArchAndUUID (file_spec, arch, uuid, file_offset, data, data_offset, magic);
-
-        default:
-            break;
-        }
-    }
-    return false;
-}
-
-FileSpec
-Symbols::FindSymbolFileInBundle (const FileSpec& dsym_bundle_fspec,
-                                 const lldb_private::UUID *uuid,
-                                 const ArchSpec *arch)
-{
-    char path[PATH_MAX];
-
-    FileSpec dsym_fspec;
-
-    if (dsym_bundle_fspec.GetPath(path, sizeof(path)))
-    {
-        ::strncat (path, "/Contents/Resources/DWARF", sizeof(path) - strlen(path) - 1);
-
-        lldb_utility::CleanUp <DIR *, int> dirp (opendir(path), NULL, closedir);
-        if (dirp.is_valid())
-        {
-            dsym_fspec.GetDirectory().SetCString(path);
-            struct dirent* dp;
-            while ((dp = readdir(dirp.get())) != NULL)
-            {
-                // Only search directories
-                if (dp->d_type == DT_DIR || dp->d_type == DT_UNKNOWN)
-                {
-                    if (dp->d_namlen == 1 && dp->d_name[0] == '.')
-                        continue;
-
-                    if (dp->d_namlen == 2 && dp->d_name[0] == '.' && dp->d_name[1] == '.')
-                        continue;
-                }
-
-                if (dp->d_type == DT_REG || dp->d_type == DT_UNKNOWN)
-                {
-                    dsym_fspec.GetFilename().SetCString(dp->d_name);
-                    if (FileAtPathContainsArchAndUUID (dsym_fspec, arch, uuid))
-                        return dsym_fspec;
-                }
-            }
-        }
-    }
-    dsym_fspec.Clear();
-    return dsym_fspec;
-}
-
-static int
+int
 LocateMacOSXFilesUsingDebugSymbols
 (
     const ModuleSpec &module_spec,
@@ -415,6 +188,8 @@ LocateMacOSXFilesUsingDebugSymbols
                                 {
                                     *dsym_extension_pos = '\0';
                                     FileSpec file_spec (path, true);
+                                    ModuleSpecList module_specs;
+                                    ModuleSpec matched_module_spec;
                                     switch (file_spec.GetFileType())
                                     {
                                         case FileSpec::eFileTypeDirectory:  // Bundle directory?
@@ -426,8 +201,9 @@ LocateMacOSXFilesUsingDebugSymbols
                                                     if (::CFURLGetFileSystemRepresentation (bundle_exe_url.get(), true, (UInt8*)path, sizeof(path)-1))
                                                     {
                                                         FileSpec bundle_exe_file_spec (path, true);
-                                                        
-                                                        if (FileAtPathContainsArchAndUUID (bundle_exe_file_spec, arch, uuid))
+                                                        if (ObjectFile::GetModuleSpecifications(bundle_exe_file_spec, 0, 0, module_specs) &&
+                                                            module_specs.FindMatchingModuleSpec(module_spec, matched_module_spec))
+
                                                         {
                                                             ++items_found;
                                                             *out_exec_fspec = bundle_exe_file_spec;
@@ -436,7 +212,7 @@ LocateMacOSXFilesUsingDebugSymbols
                                                 }
                                             }
                                             break;
-                                            
+
                                         case FileSpec::eFileTypePipe:       // Forget pipes
                                         case FileSpec::eFileTypeSocket:     // We can't process socket files
                                         case FileSpec::eFileTypeInvalid:    // File doesn't exist...
@@ -446,7 +222,9 @@ LocateMacOSXFilesUsingDebugSymbols
                                         case FileSpec::eFileTypeRegular:
                                         case FileSpec::eFileTypeSymbolicLink:
                                         case FileSpec::eFileTypeOther:
-                                            if (FileAtPathContainsArchAndUUID (file_spec, arch, uuid))
+                                            if (ObjectFile::GetModuleSpecifications(file_spec, 0, 0, module_specs) &&
+                                                module_specs.FindMatchingModuleSpec(module_spec, matched_module_spec))
+
                                             {
                                                 ++items_found;
                                                 *out_exec_fspec = file_spec;
@@ -466,112 +244,61 @@ LocateMacOSXFilesUsingDebugSymbols
     return items_found;
 }
 
-static bool
-LocateDSYMInVincinityOfExecutable (const ModuleSpec &module_spec, FileSpec &dsym_fspec)
+FileSpec
+Symbols::FindSymbolFileInBundle (const FileSpec& dsym_bundle_fspec,
+                                 const lldb_private::UUID *uuid,
+                                 const ArchSpec *arch)
 {
-    const FileSpec *exec_fspec = module_spec.GetFileSpecPtr();
-    if (exec_fspec)
+    char path[PATH_MAX];
+
+    FileSpec dsym_fspec;
+
+    if (dsym_bundle_fspec.GetPath(path, sizeof(path)))
     {
-        char path[PATH_MAX];
-        if (exec_fspec->GetPath(path, sizeof(path)))
+        ::strncat (path, "/Contents/Resources/DWARF", sizeof(path) - strlen(path) - 1);
+
+        lldb_utility::CleanUp <DIR *, int> dirp (opendir(path), NULL, closedir);
+        if (dirp.is_valid())
         {
-            // Make sure the module isn't already just a dSYM file...
-            if (strcasestr(path, ".dSYM/Contents/Resources/DWARF") == NULL)
+            dsym_fspec.GetDirectory().SetCString(path);
+            struct dirent* dp;
+            while ((dp = readdir(dirp.get())) != NULL)
             {
-                size_t obj_file_path_length = strlen(path);
-                strlcat(path, ".dSYM/Contents/Resources/DWARF/", sizeof(path));
-                strlcat(path, exec_fspec->GetFilename().AsCString(), sizeof(path));
-
-                dsym_fspec.SetFile(path, false);
-
-                if (dsym_fspec.Exists() && FileAtPathContainsArchAndUUID (dsym_fspec, module_spec.GetArchitecturePtr(), module_spec.GetUUIDPtr()))
+                // Only search directories
+                if (dp->d_type == DT_DIR || dp->d_type == DT_UNKNOWN)
                 {
-                    return true;
+                    if (dp->d_namlen == 1 && dp->d_name[0] == '.')
+                        continue;
+
+                    if (dp->d_namlen == 2 && dp->d_name[0] == '.' && dp->d_name[1] == '.')
+                        continue;
                 }
-                else
-                {
-                    path[obj_file_path_length] = '\0';
 
-                    char *last_dot = strrchr(path, '.');
-                    while (last_dot != NULL && last_dot[0])
+                if (dp->d_type == DT_REG || dp->d_type == DT_UNKNOWN)
+                {
+                    dsym_fspec.GetFilename().SetCString(dp->d_name);
+                    ModuleSpecList module_specs;
+                    if (ObjectFile::GetModuleSpecifications(dsym_fspec, 0, 0, module_specs))
                     {
-                        char *next_slash = strchr(last_dot, '/');
-                        if (next_slash != NULL)
+                        ModuleSpec spec;
+                        for (size_t i = 0; i < module_specs.GetSize(); ++i)
                         {
-                            *next_slash = '\0';
-                            strlcat(path, ".dSYM/Contents/Resources/DWARF/", sizeof(path));
-                            strlcat(path, exec_fspec->GetFilename().AsCString(), sizeof(path));
-                            dsym_fspec.SetFile(path, false);
-                            if (dsym_fspec.Exists() && FileAtPathContainsArchAndUUID (dsym_fspec, module_spec.GetArchitecturePtr(), module_spec.GetUUIDPtr()))
-                                return true;
-                            else
+                            assert(module_specs.GetModuleSpecAtIndex(i, spec));
+                            if ((uuid == NULL || (spec.GetUUIDPtr() && spec.GetUUID() == *uuid)) &&
+                                (arch == NULL || (spec.GetArchitecturePtr() && spec.GetArchitecture().IsCompatibleMatch(*arch))))
                             {
-                                *last_dot = '\0';
-                                char *prev_slash = strrchr(path, '/');
-                                if (prev_slash != NULL)
-                                    *prev_slash = '\0';
-                                else
-                                    break;
+                                return dsym_fspec;
                             }
                         }
-                        else
-                        {
-                            break;
-                        }
                     }
                 }
             }
         }
     }
     dsym_fspec.Clear();
-    return false;
-}
-
-FileSpec
-Symbols::LocateExecutableObjectFile (const ModuleSpec &module_spec)
-{
-    const FileSpec *exec_fspec = module_spec.GetFileSpecPtr();
-    const ArchSpec *arch = module_spec.GetArchitecturePtr();
-    const UUID *uuid = module_spec.GetUUIDPtr();
-    Timer scoped_timer (__PRETTY_FUNCTION__,
-                        "LocateExecutableObjectFile (file = %s, arch = %s, uuid = %p)",
-                        exec_fspec ? exec_fspec->GetFilename().AsCString ("<NULL>") : "<NULL>",
-                        arch ? arch->GetArchitectureName() : "<NULL>",
-                        uuid);
-
-    FileSpec objfile_fspec;
-    if (exec_fspec && FileAtPathContainsArchAndUUID (exec_fspec, arch, uuid))
-        objfile_fspec = exec_fspec;
-    else
-        LocateMacOSXFilesUsingDebugSymbols (module_spec, &objfile_fspec, NULL);
-    return objfile_fspec;
-}
-
-FileSpec
-Symbols::LocateExecutableSymbolFile (const ModuleSpec &module_spec)
-{
-    const FileSpec *exec_fspec = module_spec.GetFileSpecPtr();
-    const ArchSpec *arch = module_spec.GetArchitecturePtr();
-    const UUID *uuid = module_spec.GetUUIDPtr();
-
-    Timer scoped_timer (__PRETTY_FUNCTION__,
-                        "LocateExecutableSymbolFile (file = %s, arch = %s, uuid = %p)",
-                        exec_fspec ? exec_fspec->GetFilename().AsCString ("<NULL>") : "<NULL>",
-                        arch ? arch->GetArchitectureName() : "<NULL>",
-                        uuid);
-
-    FileSpec symbol_fspec;
-    // First try and find the dSYM in the same directory as the executable or in
-    // an appropriate parent directory
-    if (LocateDSYMInVincinityOfExecutable (module_spec, symbol_fspec) == false)
-    {
-        // We failed to easily find the dSYM above, so use DebugSymbols
-        LocateMacOSXFilesUsingDebugSymbols (module_spec, NULL, &symbol_fspec);
-    }
-    return symbol_fspec;
+    return dsym_fspec;
 }
 
-
 static bool
 GetModuleSpecInfoFromUUIDDictionary (CFDictionaryRef uuid_dict, ModuleSpec &module_spec)
 {





More information about the lldb-commits mailing list