Hi Robert, this change introduced a bit of a regression in Mac native lldb. It's not easy to spot on a Mac but in other environments it's a problem.
LocateDSYMInVincinityOfExecutable is a function in Host/common/Symbols.cpp. It takes a ModuleSpec (the details about the executable binary -- the filename, architecture, UUID, etc) and it looks for a dSYM bundle near that executable. It adds things on to the file path and if it finds a likely candidate, retrieves the ModuleSpecs for that dSYM (in the case of a multiple-architecture universal dSYM binary) and compares them to the original executable binary's ModuleSpec. The problem comes from using ModuleSpec::FindMatchingModuleSpec(). This calls ModuleSpec::Matches() and this method, among the things it checks, requires that the *filenames* match between the executable and the dSYM. As a reminder, an executable name might be /tmp/a.out. Its dSYM would be /tmp/a.out.dSYM/Contents/Resources/a.out. After r235737, LocateDSYMInVincinityOfExecutable() never matches anything. The only reason it escaped all of our notices is that lldb then asks the DebugSymbols framework to find the dSYM -- and it has usually been able to do that. But if the DebugSymbols framework is not available or not working, lldb is completely broken for automatically loading a dSYM next to a binary. The old version of LocateDSYMInVincinityOfExecutable() was written in very Mac specific terms, e.g. if (dsym_fspec.Exists() && FileAtPathContainsArchAndUUID (dsym_fspec, module_spec.GetArchitecturePtr(), module_spec.GetUUIDPtr())) { return true; } (and FileAtPathContainsArchAndUUID was very mac-only) so you had a bit of rewriting to do there in making it non-mac-specific. But I think using ModuleSpec::FindMatchingModuleSpec() in place of this is not correct. As a quick workaround I made this patch,
Index: source/Host/common/Symbols.cpp =================================================================== --- source/Host/common/Symbols.cpp (revision 237751) +++ source/Host/common/Symbols.cpp (working copy) @@ -76,9 +76,20 @@ ModuleSpecList module_specs; ModuleSpec matched_module_spec; + + ModuleSpec uuid_match_only_module_spec; + const ModuleSpec *module_spec_for_search = &module_spec; + + // If the ModuleSpec includes a UUID, only compare the UUID when looking at the + // dSYM binary. + if (module_spec.GetUUID().IsValid()) + { + uuid_match_only_module_spec.GetUUID() = module_spec.GetUUID(); + module_spec_for_search = &uuid_match_only_module_spec; + } if (dsym_fspec.Exists() && ObjectFile::GetModuleSpecifications(dsym_fspec, 0, 0, module_specs) && - module_specs.FindMatchingModuleSpec(module_spec, matched_module_spec)) + module_specs.FindMatchingModuleSpec(*module_spec_for_search, matched_module_spec)) { return true; } @@ -95,10 +106,20 @@ *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); + module_spec_for_search = &module_spec; + + // If the ModuleSpec includes a UUID, only compare the UUID when looking at the + // dSYM binary. + if (module_spec.GetUUID().IsValid()) + { + uuid_match_only_module_spec.GetUUID() = module_spec.GetUUID(); + module_spec_for_search = &uuid_match_only_module_spec; + } + 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)) + module_specs.FindMatchingModuleSpec(*module_spec_for_search, matched_module_spec)) { return true; }
which looks to see if the executable module has a UUID in its ModuleSpec -- and if so, it creates a new ModuleSpec with only that one field. That is always enough to disambiguate among a multi-architecture dSYM, and to ensure that we have the correct dSYM. (and on Mac, it's nigh impossible to get a binary that doesn't have a UUID in it--you never see them in practice.) Do you want to take another look at this function? Thanks! Jason > On Apr 24, 2015, at 11:09 AM, Robert Flack <fla...@gmail.com> wrote: > > 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) > { > > > _______________________________________________ > lldb-commits mailing list > lldb-commits@cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits
_______________________________________________ lldb-commits mailing list lldb-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits