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

llvm-svn: 235737
This commit is contained in:
Robert Flack 2015-04-24 18:09:54 +00:00
parent f8aca46512
commit 31870e15fa
2 changed files with 251 additions and 410 deletions

View File

@ -18,101 +18,247 @@
#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__)
#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;
}
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));
// 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())
if (symbol_filename && symbol_filename[0])
{
// 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";
}
FileSpecList debug_file_search_paths (Target::GetDefaultDebugFileSearchPaths());
// 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();
// Add module directory.
const ConstString &file_dir = module_spec.GetFileSpec().GetDirectory();
debug_file_search_paths.AppendIfUnique (FileSpec(file_dir.AsCString("."), true));
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;
// Add current working directory.
debug_file_search_paths.AppendIfUnique (FileSpec(".", true));
std::vector<std::string> files;
std::string dirname = dirspec.GetPath();
// Add /usr/lib/debug directory.
debug_file_search_paths.AppendIfUnique (FileSpec("/usr/lib/debug", true));
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)
std::string uuid_str;
const UUID &module_uuid = module_spec.GetUUID();
if (module_uuid.IsValid())
{
const std::string &filename = files[idx_file];
FileSpec file_spec (filename.c_str(), true);
// 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";
}
if (llvm::sys::fs::equivalent (file_spec.GetPath(), module_spec.GetFileSpec().GetPath()))
// 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;
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);
}
#if !defined (__APPLE__)
FileSpec
Symbols::FindSymbolFileInBundle (const FileSpec& symfile_bundle,
const lldb_private::UUID *uuid,
@ -130,36 +276,4 @@ Symbols::DownloadObjectAndSymbolFile (ModuleSpec &module_spec, bool force_lookup
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();
}
FileSpec
Symbols::FindSymbolFileInBundle (const FileSpec& symfile_bundle,
const lldb_private::UUID *uuid,
const ArchSpec *arch)
{
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;
}
#endif

View File

@ -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 (CFURLRef dsym_url);
}
#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 (ObjectFile::GetModuleSpecifications(bundle_exe_file_spec, 0, 0, module_specs) &&
module_specs.FindMatchingModuleSpec(module_spec, matched_module_spec))
if (FileAtPathContainsArchAndUUID (bundle_exe_file_spec, arch, uuid))
{
++items_found;
*out_exec_fspec = bundle_exe_file_spec;
@ -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;
return dsym_fspec;
}
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;
}
static bool
GetModuleSpecInfoFromUUIDDictionary (CFDictionaryRef uuid_dict, ModuleSpec &module_spec)
{