#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 (__linux__) || defined (__FreeBSD__)
-
-FileSpec
-Symbols::LocateExecutableObjectFile (const ModuleSpec &module_spec)
-{
- // FIXME
- return FileSpec();
-}
-
-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());
+#if defined(__APPLE__)
- // Add module directory.
- const ConstString &file_dir = module_spec.GetFileSpec().GetDirectory();
- debug_file_search_paths.AppendIfUnique (FileSpec(file_dir.AsCString("."), true));
+// 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
+);
- // Add current working directory.
- debug_file_search_paths.AppendIfUnique (FileSpec(".", true));
+#else
- // Add /usr/lib/debug directory.
- debug_file_search_paths.AppendIfUnique (FileSpec("/usr/lib/debug", 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";
- }
+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;
+}
- // 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();
+#endif
- size_t num_directories = debug_file_search_paths.GetSize();
- for (size_t idx = 0; idx < num_directories; ++idx)
+static bool
+LocateDSYMInVincinityOfExecutable (const ModuleSpec &module_spec, FileSpec &dsym_fspec)
+{
+ const FileSpec *exec_fspec = module_spec.GetFileSpecPtr();
+ if (exec_fspec)
{
- 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);
-
- const uint32_t num_files = files.size();
- for (size_t idx_file = 0; idx_file < num_files; ++idx_file)
+ char path[PATH_MAX];
+ if (exec_fspec->GetPath(path, sizeof(path)))
{
- const std::string &filename = files[idx_file];
- FileSpec file_spec (filename.c_str(), true);
+ // 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);
- if (llvm::sys::fs::equivalent (file_spec.GetPath(), module_spec.GetFileSpec().GetPath()))
- continue;
+ dsym_fspec.SetFile(path, false);
- if (file_spec.Exists())
- {
- 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)
+ 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
{
- ModuleSpec mspec;
- if (specs.GetModuleSpecAtIndex (0, mspec))
+ path[obj_file_path_length] = '\0';
+
+ char *last_dot = strrchr(path, '.');
+ while (last_dot != NULL && last_dot[0])
{
- if (mspec.GetUUID() == module_uuid)
- return file_spec;
+ 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;
+ }
}
}
}
}
}
-
- return FileSpec();
+ dsym_fspec.Clear();
+ return false;
}
FileSpec
-Symbols::FindSymbolFileInBundle (const FileSpec& symfile_bundle,
- const lldb_private::UUID *uuid,
- const ArchSpec *arch)
+LocateExecutableSymbolFileDsym (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();
-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;
-}
+ 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);
-#elif !defined (__APPLE__)
+ 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)
{
- // FIXME
- return FileSpec();
+ const char *symbol_filename = module_spec.GetSymbolFileSpec().GetFilename().AsCString();
+ if (symbol_filename && symbol_filename[0])
+ {
+ 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));
+
+ // Add current working directory.
+ debug_file_search_paths.AppendIfUnique (FileSpec(".", true));
+
+ // Add /usr/lib/debug directory.
+ debug_file_search_paths.AppendIfUnique (FileSpec("/usr/lib/debug", 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";
+ }
+
+ // 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();
+
+ 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);
+
+ const uint32_t num_files = files.size();
+ for (size_t idx_file = 0; idx_file < num_files; ++idx_file)
+ {
+ 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())
+ {
+ 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)
+ {
+ ModuleSpec mspec;
+ if (specs.GetModuleSpecAtIndex (0, mspec))
+ {
+ if (mspec.GetUUID() == module_uuid)
+ return file_spec;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return LocateExecutableSymbolFileDsym(module_spec);
}
+#if !defined (__APPLE__)
+
FileSpec
Symbols::FindSymbolFileInBundle (const FileSpec& symfile_bundle,
const lldb_private::UUID *uuid,
const ArchSpec *arch)
{
+ // FIXME
return FileSpec();
}
#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"
#include "Host/macosx/cfcpp/CFCString.h"
#include "mach/machine.h"
-
using namespace lldb;
using namespace lldb_private;
using namespace llvm::MachO;
}
#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,
{
*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?
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;
}
}
break;
-
+
case FileSpec::eFileTypePipe: // Forget pipes
case FileSpec::eFileTypeSocket: // We can't process socket files
case FileSpec::eFileTypeInvalid: // File doesn't exist...
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;
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)
{