static 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 ) { int items_found = 0; if (out_exec_fspec) out_exec_fspec->Clear(); if (out_dsym_fspec) out_dsym_fspec->Clear(); #if !defined (__arm__) // No DebugSymbols on the iOS devices const UUID *uuid = module_spec.GetUUIDPtr(); const ArchSpec *arch = module_spec.GetArchitecturePtr(); if (uuid && uuid->IsValid()) { // Try and locate the dSYM file using DebugSymbols first const UInt8 *module_uuid = (const UInt8 *)uuid->GetBytes(); if (module_uuid != NULL) { CFCReleaser<CFUUIDRef> module_uuid_ref(::CFUUIDCreateWithBytes (NULL, module_uuid[0], module_uuid[1], module_uuid[2], module_uuid[3], module_uuid[4], module_uuid[5], module_uuid[6], module_uuid[7], module_uuid[8], module_uuid[9], module_uuid[10], module_uuid[11], module_uuid[12], module_uuid[13], module_uuid[14], module_uuid[15])); if (module_uuid_ref.get()) { CFCReleaser<CFURLRef> exec_url; const FileSpec *exec_fspec = module_spec.GetFileSpecPtr(); if (exec_fspec) { char exec_cf_path[PATH_MAX]; if (exec_fspec->GetPath(exec_cf_path, sizeof(exec_cf_path))) exec_url.reset(::CFURLCreateFromFileSystemRepresentation (NULL, (const UInt8 *)exec_cf_path, strlen(exec_cf_path), FALSE)); } CFCReleaser<CFURLRef> dsym_url (::DBGCopyFullDSYMURLForUUID(module_uuid_ref.get(), exec_url.get())); char path[PATH_MAX]; if (dsym_url.get()) { if (out_dsym_fspec) { if (::CFURLGetFileSystemRepresentation (dsym_url.get(), true, (UInt8*)path, sizeof(path)-1)) { out_dsym_fspec->SetFile(path, path[0] == '~'); if (out_dsym_fspec->GetFileType () == FileSpec::eFileTypeDirectory) { *out_dsym_fspec = Symbols::FindSymbolFileInBundle (*out_dsym_fspec, uuid, arch); if (*out_dsym_fspec) ++items_found; } else { ++items_found; } } } CFCReleaser<CFDictionaryRef> dict(::DBGCopyDSYMPropertyLists (dsym_url.get())); CFDictionaryRef uuid_dict = NULL; if (dict.get()) { CFCString uuid_cfstr (uuid->GetAsString().c_str()); uuid_dict = static_cast<CFDictionaryRef>(::CFDictionaryGetValue (dict.get(), uuid_cfstr.get())); if (uuid_dict) { CFStringRef actual_src_cfpath = static_cast<CFStringRef>(::CFDictionaryGetValue (uuid_dict, CFSTR("DBGSourcePath"))); if (actual_src_cfpath) { CFStringRef build_src_cfpath = static_cast<CFStringRef>(::CFDictionaryGetValue (uuid_dict, CFSTR("DBGBuildSourcePath"))); if (build_src_cfpath) { char actual_src_path[PATH_MAX]; char build_src_path[PATH_MAX]; ::CFStringGetFileSystemRepresentation (actual_src_cfpath, actual_src_path, sizeof(actual_src_path)); ::CFStringGetFileSystemRepresentation (build_src_cfpath, build_src_path, sizeof(build_src_path)); if (actual_src_path[0] == '~') { FileSpec resolved_source_path(actual_src_path, true); resolved_source_path.GetPath(actual_src_path, sizeof(actual_src_path)); } module_spec.GetSourceMappingList().Append (ConstString(build_src_path), ConstString(actual_src_path), true); } } } } if (out_exec_fspec) { bool success = false; if (uuid_dict) { CFStringRef exec_cf_path = static_cast<CFStringRef>(::CFDictionaryGetValue (uuid_dict, CFSTR("DBGSymbolRichExecutable"))); if (exec_cf_path && ::CFStringGetFileSystemRepresentation (exec_cf_path, path, sizeof(path))) { ++items_found; out_exec_fspec->SetFile(path, path[0] == '~'); if (out_exec_fspec->Exists()) success = true; } } if (!success) { // No dictionary, check near the dSYM bundle for an executable that matches... if (::CFURLGetFileSystemRepresentation (dsym_url.get(), true, (UInt8*)path, sizeof(path)-1)) { char *dsym_extension_pos = ::strstr (path, ".dSYM"); if (dsym_extension_pos) { *dsym_extension_pos = '\0'; FileSpec file_spec (path, true); switch (file_spec.GetFileType()) { case FileSpec::eFileTypeDirectory: // Bundle directory? { CFCBundle bundle (path); CFCReleaser<CFURLRef> bundle_exe_url (bundle.CopyExecutableURL ()); if (bundle_exe_url.get()) { 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)) { ++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... break; case FileSpec::eFileTypeUnknown: case FileSpec::eFileTypeRegular: case FileSpec::eFileTypeSymbolicLink: case FileSpec::eFileTypeOther: if (FileAtPathContainsArchAndUUID (file_spec, arch, uuid)) { ++items_found; *out_exec_fspec = file_spec; } break; } } } } } } } } } #endif // #if !defined (__arm__) return items_found; }
Error PlatformRemoteGDBServer::ResolveExecutable (const ModuleSpec &module_spec, lldb::ModuleSP &exe_module_sp, const FileSpecList *module_search_paths_ptr) { // copied from PlatformRemoteiOS Error error; // Nothing special to do here, just use the actual file and architecture ModuleSpec resolved_module_spec(module_spec); // Resolve any executable within an apk on Android? //Host::ResolveExecutableInBundle (resolved_module_spec.GetFileSpec()); if (resolved_module_spec.GetFileSpec().Exists() || module_spec.GetUUID().IsValid()) { if (resolved_module_spec.GetArchitecture().IsValid() || resolved_module_spec.GetUUID().IsValid()) { error = ModuleList::GetSharedModule (resolved_module_spec, exe_module_sp, module_search_paths_ptr, NULL, NULL); if (exe_module_sp && exe_module_sp->GetObjectFile()) return error; exe_module_sp.reset(); } // No valid architecture was specified or the exact arch wasn't // found so ask the platform for the architectures that we should be // using (in the correct order) and see if we can find a match that way StreamString arch_names; for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, resolved_module_spec.GetArchitecture()); ++idx) { error = ModuleList::GetSharedModule (resolved_module_spec, exe_module_sp, module_search_paths_ptr, NULL, NULL); // Did we find an executable using one of the if (error.Success()) { if (exe_module_sp && exe_module_sp->GetObjectFile()) break; else error.SetErrorToGenericError(); } if (idx > 0) arch_names.PutCString (", "); arch_names.PutCString (resolved_module_spec.GetArchitecture().GetArchitectureName()); } if (error.Fail() || !exe_module_sp) { if (resolved_module_spec.GetFileSpec().Readable()) { error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s", resolved_module_spec.GetFileSpec().GetPath().c_str(), GetPluginName().GetCString(), arch_names.GetString().c_str()); } else { error.SetErrorStringWithFormat("'%s' is not readable", resolved_module_spec.GetFileSpec().GetPath().c_str()); } } } else { error.SetErrorStringWithFormat ("'%s' does not exist", resolved_module_spec.GetFileSpec().GetPath().c_str()); } return error; }
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() && FileAtPathContainsArchAndUUID(dsym_fspec, module_spec.GetArchitecturePtr(), module_spec.GetUUIDPtr())) { 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() && FileAtPathContainsArchAndUUID(dsym_fspec, module_spec.GetArchitecturePtr(), module_spec.GetUUIDPtr())) { 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; }
Error ModuleCache::GetAndPut (const FileSpec &root_dir_spec, const char *hostname, const ModuleSpec &module_spec, const ModuleDownloader &module_downloader, const SymfileDownloader &symfile_downloader, lldb::ModuleSP &cached_module_sp, bool *did_create_ptr) { const auto module_spec_dir = GetModuleDirectory (root_dir_spec, module_spec.GetUUID ()); auto error = MakeDirectory (module_spec_dir); if (error.Fail ()) return error; // Open lock file. const auto lock_file_spec = JoinPath (module_spec_dir, kLockFileName); File lock_file (lock_file_spec, File::eOpenOptionWrite | File::eOpenOptionCanCreate | File::eOpenOptionCloseOnExec); if (!lock_file) { error.SetErrorToErrno (); return Error("Failed to open lock file %s: %s", lock_file_spec.GetPath ().c_str (), error.AsCString ()); } LockFile lock (lock_file.GetDescriptor ()); error = lock.WriteLock (0, 1); if (error.Fail ()) return Error("Failed to lock file %s:%s", lock_file_spec.GetPath ().c_str (), error.AsCString ()); // Check local cache for a module. error = Get (root_dir_spec, hostname, module_spec, cached_module_sp, did_create_ptr); if (error.Success ()) return error; const auto tmp_download_file_spec = JoinPath (module_spec_dir, kTempFileName); error = module_downloader (module_spec, tmp_download_file_spec); llvm::FileRemover tmp_file_remover (tmp_download_file_spec.GetPath ().c_str ()); if (error.Fail ()) return Error("Failed to download module: %s", error.AsCString ()); // Put downloaded file into local module cache. error = Put (root_dir_spec, hostname, module_spec, tmp_download_file_spec, module_spec.GetFileSpec ()); if (error.Fail ()) return Error ("Failed to put module into cache: %s", error.AsCString ()); tmp_file_remover.releaseFile (); error = Get (root_dir_spec, hostname, module_spec, cached_module_sp, did_create_ptr); if (error.Fail ()) return error; // Fetching a symbol file for the module const auto tmp_download_sym_file_spec = JoinPath (module_spec_dir, kTempSymFileName); error = symfile_downloader (cached_module_sp, tmp_download_sym_file_spec); llvm::FileRemover tmp_symfile_remover (tmp_download_sym_file_spec.GetPath ().c_str ()); if (error.Fail ()) // Failed to download a symfile but fetching the module was successful. The module might // contain the neccessary symbols and the debugging is also possible without a symfile. return Error (); FileSpec symfile_spec = GetSymbolFileSpec (cached_module_sp->GetFileSpec ()); error = Put (root_dir_spec, hostname, module_spec, tmp_download_sym_file_spec, symfile_spec); if (error.Fail ()) return Error ("Failed to put symbol file into cache: %s", error.AsCString ()); tmp_symfile_remover.releaseFile(); cached_module_sp->SetSymbolFileFileSpec (symfile_spec); return Error (); }
Error ModuleList::GetSharedModule(const ModuleSpec &module_spec, ModuleSP &module_sp, const FileSpecList *module_search_paths_ptr, ModuleSP *old_module_sp_ptr, bool *did_create_ptr, bool always_create) { ModuleList &shared_module_list = GetSharedModuleList (); Mutex::Locker locker(shared_module_list.m_modules_mutex); char path[PATH_MAX]; Error error; module_sp.reset(); if (did_create_ptr) *did_create_ptr = false; if (old_module_sp_ptr) old_module_sp_ptr->reset(); const UUID *uuid_ptr = module_spec.GetUUIDPtr(); const FileSpec &module_file_spec = module_spec.GetFileSpec(); const ArchSpec &arch = module_spec.GetArchitecture(); // Make sure no one else can try and get or create a module while this // function is actively working on it by doing an extra lock on the // global mutex list. if (!always_create) { ModuleList matching_module_list; const size_t num_matching_modules = shared_module_list.FindModules (module_spec, matching_module_list); if (num_matching_modules > 0) { for (size_t module_idx = 0; module_idx < num_matching_modules; ++module_idx) { module_sp = matching_module_list.GetModuleAtIndex(module_idx); // Make sure the file for the module hasn't been modified if (module_sp->FileHasChanged()) { if (old_module_sp_ptr && !*old_module_sp_ptr) *old_module_sp_ptr = module_sp; Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_MODULES)); if (log != nullptr) log->Printf("module changed: %p, removing from global module list", static_cast<void*>(module_sp.get())); shared_module_list.Remove (module_sp); module_sp.reset(); } else { // The module matches and the module was not modified from // when it was last loaded. return error; } } } } if (module_sp) return error; module_sp.reset (new Module (module_spec)); // Make sure there are a module and an object file since we can specify // a valid file path with an architecture that might not be in that file. // By getting the object file we can guarantee that the architecture matches if (module_sp->GetObjectFile()) { // If we get in here we got the correct arch, now we just need // to verify the UUID if one was given if (uuid_ptr && *uuid_ptr != module_sp->GetUUID()) { module_sp.reset(); } else { if (module_sp->GetObjectFile() && module_sp->GetObjectFile()->GetType() == ObjectFile::eTypeStubLibrary) { module_sp.reset(); } else { if (did_create_ptr) { *did_create_ptr = true; } shared_module_list.ReplaceEquivalent(module_sp); return error; } } } else { module_sp.reset(); } if (module_search_paths_ptr) { const auto num_directories = module_search_paths_ptr->GetSize(); for (size_t idx = 0; idx < num_directories; ++idx) { auto search_path_spec = module_search_paths_ptr->GetFileSpecAtIndex(idx); if (!search_path_spec.ResolvePath()) continue; if (!search_path_spec.Exists() || !search_path_spec.IsDirectory()) continue; search_path_spec.AppendPathComponent(module_spec.GetFileSpec().GetFilename().AsCString()); if (!search_path_spec.Exists()) continue; auto resolved_module_spec(module_spec); resolved_module_spec.GetFileSpec() = search_path_spec; module_sp.reset (new Module (resolved_module_spec)); if (module_sp->GetObjectFile()) { // If we get in here we got the correct arch, now we just need // to verify the UUID if one was given if (uuid_ptr && *uuid_ptr != module_sp->GetUUID()) { module_sp.reset(); } else { if (module_sp->GetObjectFile()->GetType() == ObjectFile::eTypeStubLibrary) { module_sp.reset(); } else { if (did_create_ptr) *did_create_ptr = true; shared_module_list.ReplaceEquivalent(module_sp); return Error(); } } } else { module_sp.reset(); } } } // Either the file didn't exist where at the path, or no path was given, so // we now have to use more extreme measures to try and find the appropriate // module. // Fixup the incoming path in case the path points to a valid file, yet // the arch or UUID (if one was passed in) don't match. ModuleSpec located_binary_modulespec = Symbols::LocateExecutableObjectFile (module_spec); // Don't look for the file if it appears to be the same one we already // checked for above... if (located_binary_modulespec.GetFileSpec() != module_file_spec) { if (!located_binary_modulespec.GetFileSpec().Exists()) { located_binary_modulespec.GetFileSpec().GetPath(path, sizeof(path)); if (path[0] == '\0') module_file_spec.GetPath(path, sizeof(path)); // How can this check ever be true? This branch it is false, and we haven't modified file_spec. if (located_binary_modulespec.GetFileSpec().Exists()) { std::string uuid_str; if (uuid_ptr && uuid_ptr->IsValid()) uuid_str = uuid_ptr->GetAsString(); if (arch.IsValid()) { if (!uuid_str.empty()) error.SetErrorStringWithFormat("'%s' does not contain the %s architecture and UUID %s", path, arch.GetArchitectureName(), uuid_str.c_str()); else error.SetErrorStringWithFormat("'%s' does not contain the %s architecture.", path, arch.GetArchitectureName()); } } else { error.SetErrorStringWithFormat("'%s' does not exist", path); } if (error.Fail()) module_sp.reset(); return error; } // Make sure no one else can try and get or create a module while this // function is actively working on it by doing an extra lock on the // global mutex list. ModuleSpec platform_module_spec(module_spec); platform_module_spec.GetFileSpec() = located_binary_modulespec.GetFileSpec(); platform_module_spec.GetPlatformFileSpec() = located_binary_modulespec.GetFileSpec(); platform_module_spec.GetSymbolFileSpec() = located_binary_modulespec.GetSymbolFileSpec(); ModuleList matching_module_list; if (shared_module_list.FindModules (platform_module_spec, matching_module_list) > 0) { module_sp = matching_module_list.GetModuleAtIndex(0); // If we didn't have a UUID in mind when looking for the object file, // then we should make sure the modification time hasn't changed! if (platform_module_spec.GetUUIDPtr() == nullptr) { TimeValue file_spec_mod_time(located_binary_modulespec.GetFileSpec().GetModificationTime()); if (file_spec_mod_time.IsValid()) { if (file_spec_mod_time != module_sp->GetModificationTime()) { if (old_module_sp_ptr) *old_module_sp_ptr = module_sp; shared_module_list.Remove (module_sp); module_sp.reset(); } } } } if (!module_sp) { module_sp.reset (new Module (platform_module_spec)); // Make sure there are a module and an object file since we can specify // a valid file path with an architecture that might not be in that file. // By getting the object file we can guarantee that the architecture matches if (module_sp && module_sp->GetObjectFile()) { if (module_sp->GetObjectFile()->GetType() == ObjectFile::eTypeStubLibrary) { module_sp.reset(); } else { if (did_create_ptr) *did_create_ptr = true; shared_module_list.ReplaceEquivalent(module_sp); } } else { located_binary_modulespec.GetFileSpec().GetPath(path, sizeof(path)); if (located_binary_modulespec.GetFileSpec()) { if (arch.IsValid()) error.SetErrorStringWithFormat("unable to open %s architecture in '%s'", arch.GetArchitectureName(), path); else error.SetErrorStringWithFormat("unable to open '%s'", path); } else { std::string uuid_str; if (uuid_ptr && uuid_ptr->IsValid()) uuid_str = uuid_ptr->GetAsString(); if (!uuid_str.empty()) error.SetErrorStringWithFormat("cannot locate a module for UUID '%s'", uuid_str.c_str()); else error.SetErrorStringWithFormat("cannot locate a module"); } } } } return error; }
static bool LocateDSYMInVincinityOfExecutable(const ModuleSpec &module_spec, FileSpec &dsym_fspec) { Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); 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) { if (log) { if (module_spec.GetUUIDPtr() && module_spec.GetUUIDPtr()->IsValid()) { log->Printf( "Searching for dSYM bundle next to executable %s, UUID %s", path, module_spec.GetUUIDPtr()->GetAsString().c_str()); } else { log->Printf("Searching for dSYM bundle next to executable %s", 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() && FileAtPathContainsArchAndUUID(dsym_fspec, module_spec.GetArchitecturePtr(), module_spec.GetUUIDPtr())) { if (log) { log->Printf("dSYM with matching UUID & arch found at %s", path); } return true; } else { FileSpec parent_dirs = exec_fspec; // Remove the binary name from the FileSpec parent_dirs.RemoveLastPathComponent(); // Add a ".dSYM" name to each directory component of the path, // stripping off components. e.g. we may have a binary like // /S/L/F/Foundation.framework/Versions/A/Foundation // and // /S/L/F/Foundation.framework.dSYM // // so we'll need to start with /S/L/F/Foundation.framework/Versions/A, // add the .dSYM part to the "A", and if that doesn't exist, strip off // the "A" and try it again with "Versions", etc., until we find a // dSYM bundle or we've stripped off enough path components that // there's no need to continue. for (int i = 0; i < 4; i++) { // Does this part of the path have a "." character - could it be a // bundle's top level directory? const char *fn = parent_dirs.GetFilename().AsCString(); if (fn == nullptr) break; if (::strchr(fn, '.') != nullptr) { dsym_fspec = parent_dirs; dsym_fspec.RemoveLastPathComponent(); // If the current directory name is "Foundation.framework", see if // "Foundation.framework.dSYM/Contents/Resources/DWARF/Foundation" // exists & has the right uuid. std::string dsym_fn = fn; dsym_fn += ".dSYM"; dsym_fspec.AppendPathComponent(dsym_fn.c_str()); dsym_fspec.AppendPathComponent("Contents"); dsym_fspec.AppendPathComponent("Resources"); dsym_fspec.AppendPathComponent("DWARF"); dsym_fspec.AppendPathComponent( exec_fspec->GetFilename().AsCString()); if (dsym_fspec.Exists() && FileAtPathContainsArchAndUUID( dsym_fspec, module_spec.GetArchitecturePtr(), module_spec.GetUUIDPtr())) { if (log) { log->Printf("dSYM with matching UUID & arch found at %s", dsym_fspec.GetPath().c_str()); } return true; } } parent_dirs.RemoveLastPathComponent(); } } } } } dsym_fspec.Clear(); return false; }
FileSpec Symbols::LocateExecutableSymbolFile(const ModuleSpec &module_spec) { FileSpec symbol_file_spec = module_spec.GetSymbolFileSpec(); if (symbol_file_spec.IsAbsolute() && symbol_file_spec.Exists()) return symbol_file_spec; const char *symbol_filename = symbol_file_spec.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)); #ifndef LLVM_ON_WIN32 // Add /usr/lib/debug directory. debug_file_search_paths.AppendIfUnique(FileSpec("/usr/lib/debug", true)); #endif // LLVM_ON_WIN32 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); // Some debug files may stored in the module directory like this: // /usr/lib/debug/usr/lib/library.so.debug if (!file_dir.IsEmpty()) files.push_back(dirname + file_dir.AsCString() + "/" + 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, 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); }
Error ModuleCache::GetAndPut(const FileSpec &root_dir_spec, const char *hostname, const ModuleSpec &module_spec, const ModuleDownloader &module_downloader, const SymfileDownloader &symfile_downloader, lldb::ModuleSP &cached_module_sp, bool *did_create_ptr) { const auto module_spec_dir = GetModuleDirectory(root_dir_spec, module_spec.GetUUID()); auto error = MakeDirectory(module_spec_dir); if (error.Fail()) return error; ModuleLock lock(root_dir_spec, module_spec.GetUUID(), error); if (error.Fail()) return Error("Failed to lock module %s: %s", module_spec.GetUUID().GetAsString().c_str(), error.AsCString()); const auto escaped_hostname(GetEscapedHostname(hostname)); // Check local cache for a module. error = Get(root_dir_spec, escaped_hostname.c_str(), module_spec, cached_module_sp, did_create_ptr); if (error.Success()) return error; const auto tmp_download_file_spec = JoinPath(module_spec_dir, kTempFileName); error = module_downloader(module_spec, tmp_download_file_spec); llvm::FileRemover tmp_file_remover(tmp_download_file_spec.GetPath().c_str()); if (error.Fail()) return Error("Failed to download module: %s", error.AsCString()); // Put downloaded file into local module cache. error = Put(root_dir_spec, escaped_hostname.c_str(), module_spec, tmp_download_file_spec, module_spec.GetFileSpec()); if (error.Fail()) return Error("Failed to put module into cache: %s", error.AsCString()); tmp_file_remover.releaseFile(); error = Get(root_dir_spec, escaped_hostname.c_str(), module_spec, cached_module_sp, did_create_ptr); if (error.Fail()) return error; // Fetching a symbol file for the module const auto tmp_download_sym_file_spec = JoinPath(module_spec_dir, kTempSymFileName); error = symfile_downloader(cached_module_sp, tmp_download_sym_file_spec); llvm::FileRemover tmp_symfile_remover( tmp_download_sym_file_spec.GetPath().c_str()); if (error.Fail()) // Failed to download a symfile but fetching the module was successful. The // module might // contain the necessary symbols and the debugging is also possible without // a symfile. return Error(); error = Put(root_dir_spec, escaped_hostname.c_str(), module_spec, tmp_download_sym_file_spec, GetSymbolFileSpec(module_spec.GetFileSpec())); if (error.Fail()) return Error("Failed to put symbol file into cache: %s", error.AsCString()); tmp_symfile_remover.releaseFile(); FileSpec symfile_spec = GetSymbolFileSpec(cached_module_sp->GetFileSpec()); cached_module_sp->SetSymbolFileFileSpec(symfile_spec); return Error(); }
Error PlatformRemoteiOS::GetSharedModule (const ModuleSpec &module_spec, Process* process, ModuleSP &module_sp, const FileSpecList *module_search_paths_ptr, ModuleSP *old_module_sp_ptr, bool *did_create_ptr) { // For iOS, the SDK files are all cached locally on the host // system. So first we ask for the file in the cached SDK, // then we attempt to get a shared module for the right architecture // with the right UUID. const FileSpec &platform_file = module_spec.GetFileSpec(); Error error; char platform_file_path[PATH_MAX]; if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) { ModuleSpec platform_module_spec(module_spec); UpdateSDKDirectoryInfosIfNeeded(); const uint32_t num_sdk_infos = m_sdk_directory_infos.size(); // If we are connected we migth be able to correctly deduce the SDK directory // using the OS build. const uint32_t connected_sdk_idx = GetConnectedSDKIndex (); if (connected_sdk_idx < num_sdk_infos) { if (GetFileInSDK (platform_file_path, connected_sdk_idx, platform_module_spec.GetFileSpec())) { module_sp.reset(); error = ResolveExecutable (platform_module_spec, module_sp, NULL); if (module_sp) { m_last_module_sdk_idx = connected_sdk_idx; error.Clear(); return error; } } } // Try the last SDK index if it is set as most files from an SDK // will tend to be valid in that same SDK. if (m_last_module_sdk_idx < num_sdk_infos) { if (GetFileInSDK (platform_file_path, m_last_module_sdk_idx, platform_module_spec.GetFileSpec())) { module_sp.reset(); error = ResolveExecutable (platform_module_spec, module_sp, NULL); if (module_sp) { error.Clear(); return error; } } } // First try for an exact match of major, minor and update: // If a particalar SDK version was specified via --version or --build, look for a match on disk. const SDKDirectoryInfo *current_sdk_info = GetSDKDirectoryForCurrentOSVersion(); const uint32_t current_sdk_idx = GetSDKIndexBySDKDirectoryInfo(current_sdk_info); if (current_sdk_idx < num_sdk_infos && current_sdk_idx != m_last_module_sdk_idx) { if (GetFileInSDK (platform_file_path, current_sdk_idx, platform_module_spec.GetFileSpec())) { module_sp.reset(); error = ResolveExecutable (platform_module_spec, module_sp, NULL); if (module_sp) { m_last_module_sdk_idx = current_sdk_idx; error.Clear(); return error; } } } // Second try all SDKs that were found. for (uint32_t sdk_idx=0; sdk_idx<num_sdk_infos; ++sdk_idx) { if (m_last_module_sdk_idx == sdk_idx) { // Skip the last module SDK index if we already searched // it above continue; } if (GetFileInSDK (platform_file_path, sdk_idx, platform_module_spec.GetFileSpec())) { //printf ("sdk[%u]: '%s'\n", sdk_idx, local_file.GetPath().c_str()); error = ResolveExecutable (platform_module_spec, module_sp, NULL); if (module_sp) { // Remember the index of the last SDK that we found a file // in in case the wrong SDK was selected. m_last_module_sdk_idx = sdk_idx; error.Clear(); return error; } } } } // Not the module we are looking for... Nothing to see here... module_sp.reset(); // This may not be an SDK-related module. Try whether we can bring in the thing to our local cache. error = GetSharedModuleWithLocalCache(module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr, did_create_ptr); if (error.Success()) return error; const bool always_create = false; error = ModuleList::GetSharedModule (module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr, did_create_ptr, always_create); if (module_sp) module_sp->SetPlatformFileSpec(platform_file); return error; }
FileSpec PlatformDarwin::LocateExecutableScriptingResource (const ModuleSpec &module_spec) { const FileSpec *exec_fspec = module_spec.GetFileSpecPtr(); const ArchSpec *arch = module_spec.GetArchitecturePtr(); const UUID *uuid = module_spec.GetUUIDPtr(); const char* module_directory = exec_fspec->GetDirectory().GetCString(); // NB some extensions might be meaningful and should not be stripped - "this.binary.file" // should not lose ".file" but GetFileNameStrippingExtension() will do precisely that. // Ideally, we should have a per-platform list of extensions (".exe", ".app", ".dSYM", ".framework") // which should be stripped while leaving "this.binary.file" as-is. const char* module_basename = exec_fspec->GetFileNameStrippingExtension().GetCString(); if (!module_directory || !module_basename) return FileSpec(); Timer scoped_timer (__PRETTY_FUNCTION__, "LocateExecutableScriptingResource (file = %s, arch = %s, uuid = %p)", exec_fspec ? exec_fspec->GetFilename().AsCString ("<NULL>") : "<NULL>", arch ? arch->GetArchitectureName() : "<NULL>", uuid); // FIXME: for Python, we cannot allow dots in the middle of the filenames we import. // Theoretically, different scripting languages may have different sets of // forbidden tokens in filenames, and that should be dealt with by each ScriptInterpreter. // For now, we just replace dots with underscores, but if we ever support anything // other than Python we will need to rework this std::auto_ptr<char> module_basename_fixed_ap(new char[strlen(module_basename)+1]); char* module_basename_fixed = module_basename_fixed_ap.get(); strcpy(module_basename_fixed, module_basename); while (*module_basename_fixed) { if (*module_basename_fixed == '.') *module_basename_fixed = '_'; module_basename_fixed++; } module_basename_fixed = module_basename_fixed_ap.get(); FileSpec symbol_fspec (Symbols::LocateExecutableSymbolFile(module_spec)); FileSpec script_fspec; StreamString path_string; if (symbol_fspec && symbol_fspec.Exists()) { // for OSX we are going to be in .dSYM/Contents/Resources/DWARF/<basename> // let us go to .dSYM/Contents/Resources/Python/<basename>.py and see if the file exists path_string.Printf("%s/../Python/%s.py",symbol_fspec.GetDirectory().AsCString(""),module_basename_fixed); script_fspec.SetFile(path_string.GetData(), true); if (!script_fspec.Exists()) script_fspec.Clear(); } // no symbols or symbols did not have a scripting resource if (!symbol_fspec || !script_fspec) { path_string.Clear(); path_string.Printf("%s.framework",module_basename); if (module_directory && strstr(module_directory, path_string.GetData())) { // we are going to be in foo.framework/Versions/X/foo path_string.Clear(); // let's go to foo.framework/Versions/X/Resources/Python/foo.py path_string.Printf("%s/Resources/Python/%s.py",module_directory,module_basename_fixed); script_fspec.SetFile(path_string.GetData(), true); if (!script_fspec.Exists()) script_fspec.Clear(); } } return script_fspec; }
Error PlatformDarwin::GetSharedModule (const ModuleSpec &module_spec, ModuleSP &module_sp, const FileSpecList *module_search_paths_ptr, ModuleSP *old_module_sp_ptr, bool *did_create_ptr) { Error error; module_sp.reset(); if (IsRemote()) { // If we have a remote platform always, let it try and locate // the shared module first. if (m_remote_platform_sp) { error = m_remote_platform_sp->GetSharedModule (module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr, did_create_ptr); } } if (!module_sp) { // Fall back to the local platform and find the file locally error = Platform::GetSharedModule (module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr, did_create_ptr); const FileSpec &platform_file = module_spec.GetFileSpec(); if (!module_sp && module_search_paths_ptr && platform_file) { // We can try to pull off part of the file path up to the bundle // directory level and try any module search paths... FileSpec bundle_directory; if (Host::GetBundleDirectory (platform_file, bundle_directory)) { char platform_path[PATH_MAX]; char bundle_dir[PATH_MAX]; platform_file.GetPath (platform_path, sizeof(platform_path)); const size_t bundle_directory_len = bundle_directory.GetPath (bundle_dir, sizeof(bundle_dir)); char new_path[PATH_MAX]; size_t num_module_search_paths = module_search_paths_ptr->GetSize(); for (size_t i=0; i<num_module_search_paths; ++i) { const size_t search_path_len = module_search_paths_ptr->GetFileSpecAtIndex(i).GetPath(new_path, sizeof(new_path)); if (search_path_len < sizeof(new_path)) { snprintf (new_path + search_path_len, sizeof(new_path) - search_path_len, "/%s", platform_path + bundle_directory_len); FileSpec new_file_spec (new_path, false); if (new_file_spec.Exists()) { ModuleSpec new_module_spec (module_spec); new_module_spec.GetFileSpec() = new_file_spec; Error new_error (Platform::GetSharedModule (new_module_spec, module_sp, NULL, old_module_sp_ptr, did_create_ptr)); if (module_sp) { module_sp->SetPlatformFileSpec(new_file_spec); return new_error; } } } } } } } if (module_sp) module_sp->SetPlatformFileSpec(module_spec.GetFileSpec()); return error; }
Error PlatformRemoteiOS::GetSharedModule (const ModuleSpec &module_spec, ModuleSP &module_sp, const FileSpecList *module_search_paths_ptr, ModuleSP *old_module_sp_ptr, bool *did_create_ptr) { // For iOS, the SDK files are all cached locally on the host // system. So first we ask for the file in the cached SDK, // then we attempt to get a shared module for the right architecture // with the right UUID. const FileSpec &platform_file = module_spec.GetFileSpec(); FileSpec local_file; const UUID *module_uuid_ptr = module_spec.GetUUIDPtr(); Error error (GetSymbolFile (platform_file, module_uuid_ptr, local_file)); if (error.Success()) { error = ResolveExecutable (local_file, module_spec.GetArchitecture(), module_sp, NULL); if (module_sp && ((module_uuid_ptr == NULL) || (module_sp->GetUUID() == *module_uuid_ptr))) { //printf ("found in user specified SDK\n"); error.Clear(); return error; } char platform_file_path[PATH_MAX]; if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) { FileSpec local_file; const uint32_t num_sdk_infos = m_sdk_directory_infos.size(); // Try the last SDK index if it is set as most files from an SDK // will tend to be valid in that same SDK. if (m_last_module_sdk_idx < num_sdk_infos) { if (GetFileInSDK (platform_file_path, m_last_module_sdk_idx, local_file)) { //printf ("sdk[%u] last: '%s'\n", m_last_module_sdk_idx, local_file.GetPath().c_str()); module_sp.reset(); error = ResolveExecutable (local_file, module_spec.GetArchitecture(), module_sp, NULL); if (module_sp && ((module_uuid_ptr == NULL) || (module_sp->GetUUID() == *module_uuid_ptr))) { //printf ("sdk[%u] last found\n", m_last_module_sdk_idx); error.Clear(); return error; } } } // First try for an exact match of major, minor and update for (uint32_t sdk_idx=0; sdk_idx<num_sdk_infos; ++sdk_idx) { if (m_last_module_sdk_idx == sdk_idx) { // Skip the last module SDK index if we already searched // it above continue; } if (GetFileInSDK (platform_file_path, sdk_idx, local_file)) { //printf ("sdk[%u]: '%s'\n", sdk_idx, local_file.GetPath().c_str()); error = ResolveExecutable (local_file, module_spec.GetArchitecture(), module_sp, NULL); if (module_sp && ((module_uuid_ptr == NULL) || (module_sp->GetUUID() == *module_uuid_ptr))) { // Remember the index of the last SDK that we found a file // in in case the wrong SDK was selected. m_last_module_sdk_idx = sdk_idx; //printf ("sdk[%u]: found (setting last to %u)\n", sdk_idx, m_last_module_sdk_idx); error.Clear(); return error; } } } } // Not the module we are looking for... Nothing to see here... module_sp.reset(); } else { // This may not be an SDK-related module. Try whether we can bring in the thing to our local cache. error = GetSharedModuleWithLocalCache(module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr, did_create_ptr); if (error.Success()) return error; else error.Clear(); // Clear the error and fall-through. } const bool always_create = false; error = ModuleList::GetSharedModule (module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr, did_create_ptr, always_create); if (module_sp) module_sp->SetPlatformFileSpec(platform_file); return error; }
Error PlatformDarwinKernel::GetSharedModule (const ModuleSpec &module_spec, Process *process, ModuleSP &module_sp, const FileSpecList *module_search_paths_ptr, ModuleSP *old_module_sp_ptr, bool *did_create_ptr) { Error error; module_sp.reset(); const FileSpec &platform_file = module_spec.GetFileSpec(); // Treat the file's path as a kext bundle ID (e.g. "com.apple.driver.AppleIRController") and search our kext index. std::string kext_bundle_id = platform_file.GetPath(); if (!kext_bundle_id.empty()) { ConstString kext_bundle_cs(kext_bundle_id.c_str()); if (m_name_to_kext_path_map.count(kext_bundle_cs) > 0) { for (BundleIDToKextIterator it = m_name_to_kext_path_map.begin (); it != m_name_to_kext_path_map.end (); ++it) { if (it->first == kext_bundle_cs) { error = ExamineKextForMatchingUUID (it->second, module_spec.GetUUID(), module_spec.GetArchitecture(), module_sp); if (module_sp.get()) { return error; } } } } } if (kext_bundle_id.compare("mach_kernel") == 0 && module_spec.GetUUID().IsValid()) { for (auto possible_kernel : m_kernel_binaries) { if (possible_kernel.Exists()) { ModuleSpec kern_spec (possible_kernel); kern_spec.GetUUID() = module_spec.GetUUID(); ModuleSP module_sp (new Module (kern_spec)); if (module_sp && module_sp->GetObjectFile() && module_sp->MatchesModuleSpec (kern_spec)) { // module_sp is an actual kernel binary we want to add. if (process) { process->GetTarget().GetImages().AppendIfNeeded (module_sp); error.Clear(); return error; } else { error = ModuleList::GetSharedModule (kern_spec, module_sp, NULL, NULL, NULL); if (module_sp && module_sp->GetObjectFile() && module_sp->GetObjectFile()->GetType() != ObjectFile::Type::eTypeCoreFile) { return error; } module_sp.reset(); } } } } } // Else fall back to treating the file's path as an actual file path - defer to PlatformDarwin's GetSharedModule. return PlatformDarwin::GetSharedModule (module_spec, process, module_sp, module_search_paths_ptr, old_module_sp_ptr, did_create_ptr); }
Error PlatformRemoteAppleWatch::GetSharedModule (const ModuleSpec &module_spec, lldb_private::Process* process, ModuleSP &module_sp, const FileSpecList *module_search_paths_ptr, ModuleSP *old_module_sp_ptr, bool *did_create_ptr) { // For Apple Watch, the SDK files are all cached locally on the host // system. So first we ask for the file in the cached SDK, // then we attempt to get a shared module for the right architecture // with the right UUID. const FileSpec &platform_file = module_spec.GetFileSpec(); Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST | LIBLLDB_LOG_VERBOSE); Error error; char platform_file_path[PATH_MAX]; if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) { ModuleSpec platform_module_spec(module_spec); UpdateSDKDirectoryInfosIfNeeded(); const uint32_t num_sdk_infos = m_sdk_directory_infos.size(); // If we are connected we migth be able to correctly deduce the SDK directory // using the OS build. const uint32_t connected_sdk_idx = GetConnectedSDKIndex (); if (connected_sdk_idx < num_sdk_infos) { if (log) { log->Printf ("Searching for %s in sdk path %s", platform_file_path, m_sdk_directory_infos[connected_sdk_idx].directory.GetPath().c_str()); } if (GetFileInSDK (platform_file_path, connected_sdk_idx, platform_module_spec.GetFileSpec())) { module_sp.reset(); error = ResolveExecutable(platform_module_spec, module_sp, nullptr); if (module_sp) { m_last_module_sdk_idx = connected_sdk_idx; error.Clear(); return error; } } } // Try the last SDK index if it is set as most files from an SDK // will tend to be valid in that same SDK. if (m_last_module_sdk_idx < num_sdk_infos) { if (log) { log->Printf ("Searching for %s in sdk path %s", platform_file_path, m_sdk_directory_infos[m_last_module_sdk_idx].directory.GetPath().c_str()); } if (GetFileInSDK (platform_file_path, m_last_module_sdk_idx, platform_module_spec.GetFileSpec())) { module_sp.reset(); error = ResolveExecutable(platform_module_spec, module_sp, nullptr); if (module_sp) { error.Clear(); return error; } } } // First try for an exact match of major, minor and update for (uint32_t sdk_idx=0; sdk_idx<num_sdk_infos; ++sdk_idx) { if (m_last_module_sdk_idx == sdk_idx) { // Skip the last module SDK index if we already searched // it above continue; } if (log) { log->Printf ("Searching for %s in sdk path %s", platform_file_path, m_sdk_directory_infos[sdk_idx].directory.GetPath().c_str()); } if (GetFileInSDK (platform_file_path, sdk_idx, platform_module_spec.GetFileSpec())) { //printf ("sdk[%u]: '%s'\n", sdk_idx, local_file.GetPath().c_str()); error = ResolveExecutable(platform_module_spec, module_sp, nullptr); if (module_sp) { // Remember the index of the last SDK that we found a file // in in case the wrong SDK was selected. m_last_module_sdk_idx = sdk_idx; error.Clear(); return error; } } } } // Not the module we are looking for... Nothing to see here... module_sp.reset(); // This may not be an SDK-related module. Try whether we can bring in the thing to our local cache. error = GetSharedModuleWithLocalCache(module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr, did_create_ptr); if (error.Success()) return error; const bool always_create = false; error = ModuleList::GetSharedModule (module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr, did_create_ptr, always_create); if (module_sp) module_sp->SetPlatformFileSpec(platform_file); return error; }
bool Symbols::DownloadObjectAndSymbolFile (ModuleSpec &module_spec, bool force_lookup) { bool success = false; const UUID *uuid_ptr = module_spec.GetUUIDPtr(); const FileSpec *file_spec_ptr = module_spec.GetFileSpecPtr(); // It's expensive to check for the DBGShellCommands defaults setting, only do it once per // lldb run and cache the result. static bool g_have_checked_for_dbgshell_command = false; static const char *g_dbgshell_command = NULL; if (g_have_checked_for_dbgshell_command == false) { g_have_checked_for_dbgshell_command = true; CFTypeRef defaults_setting = CFPreferencesCopyAppValue (CFSTR ("DBGShellCommands"), CFSTR ("com.apple.DebugSymbols")); if (defaults_setting && CFGetTypeID (defaults_setting) == CFStringGetTypeID()) { char cstr_buf[PATH_MAX]; if (CFStringGetCString ((CFStringRef) defaults_setting, cstr_buf, sizeof (cstr_buf), kCFStringEncodingUTF8)) { g_dbgshell_command = strdup (cstr_buf); // this malloc'ed memory will never be freed } } if (defaults_setting) { CFRelease (defaults_setting); } } // When g_dbgshell_command is NULL, the user has not enabled the use of an external program // to find the symbols, don't run it for them. if (force_lookup == false && g_dbgshell_command == NULL) { return false; } if (uuid_ptr || (file_spec_ptr && file_spec_ptr->Exists())) { static bool g_located_dsym_for_uuid_exe = false; static bool g_dsym_for_uuid_exe_exists = false; static char g_dsym_for_uuid_exe_path[PATH_MAX]; if (!g_located_dsym_for_uuid_exe) { g_located_dsym_for_uuid_exe = true; const char *dsym_for_uuid_exe_path_cstr = getenv("LLDB_APPLE_DSYMFORUUID_EXECUTABLE"); FileSpec dsym_for_uuid_exe_spec; if (dsym_for_uuid_exe_path_cstr) { dsym_for_uuid_exe_spec.SetFile(dsym_for_uuid_exe_path_cstr, true); g_dsym_for_uuid_exe_exists = dsym_for_uuid_exe_spec.Exists(); } if (!g_dsym_for_uuid_exe_exists) { dsym_for_uuid_exe_spec.SetFile("/usr/local/bin/dsymForUUID", false); g_dsym_for_uuid_exe_exists = dsym_for_uuid_exe_spec.Exists(); if (!g_dsym_for_uuid_exe_exists) { long bufsize; if ((bufsize = sysconf(_SC_GETPW_R_SIZE_MAX)) != -1) { char buffer[bufsize]; struct passwd pwd; struct passwd *tilde_rc = NULL; // we are a library so we need to use the reentrant version of getpwnam() if (getpwnam_r ("rc", &pwd, buffer, bufsize, &tilde_rc) == 0 && tilde_rc && tilde_rc->pw_dir) { std::string dsymforuuid_path(tilde_rc->pw_dir); dsymforuuid_path += "/bin/dsymForUUID"; dsym_for_uuid_exe_spec.SetFile(dsymforuuid_path.c_str(), false); g_dsym_for_uuid_exe_exists = dsym_for_uuid_exe_spec.Exists(); } } } } if (!g_dsym_for_uuid_exe_exists && g_dbgshell_command != NULL) { dsym_for_uuid_exe_spec.SetFile(g_dbgshell_command, true); g_dsym_for_uuid_exe_exists = dsym_for_uuid_exe_spec.Exists(); } if (g_dsym_for_uuid_exe_exists) dsym_for_uuid_exe_spec.GetPath (g_dsym_for_uuid_exe_path, sizeof(g_dsym_for_uuid_exe_path)); } if (g_dsym_for_uuid_exe_exists) { std::string uuid_str; char file_path[PATH_MAX]; file_path[0] = '\0'; if (uuid_ptr) uuid_str = uuid_ptr->GetAsString(); if (file_spec_ptr) file_spec_ptr->GetPath(file_path, sizeof(file_path)); StreamString command; if (!uuid_str.empty()) command.Printf("%s --ignoreNegativeCache --copyExecutable %s", g_dsym_for_uuid_exe_path, uuid_str.c_str()); else if (file_path && file_path[0]) command.Printf("%s --ignoreNegativeCache --copyExecutable %s", g_dsym_for_uuid_exe_path, file_path); if (!command.GetString().empty()) { int exit_status = -1; int signo = -1; std::string command_output; Error error = Host::RunShellCommand (command.GetData(), NULL, // current working directory &exit_status, // Exit status &signo, // Signal int * &command_output, // Command output 30, // Large timeout to allow for long dsym download times NULL); // Don't run in a shell (we don't need shell expansion) if (error.Success() && exit_status == 0 && !command_output.empty()) { CFCData data (CFDataCreateWithBytesNoCopy (NULL, (const UInt8 *)command_output.data(), command_output.size(), kCFAllocatorNull)); CFCReleaser<CFDictionaryRef> plist((CFDictionaryRef)::CFPropertyListCreateFromXMLData (NULL, data.get(), kCFPropertyListImmutable, NULL)); if (plist.get() && CFGetTypeID (plist.get()) == CFDictionaryGetTypeID ()) { if (!uuid_str.empty()) { CFCString uuid_cfstr(uuid_str.c_str()); CFDictionaryRef uuid_dict = (CFDictionaryRef)CFDictionaryGetValue (plist.get(), uuid_cfstr.get()); success = GetModuleSpecInfoFromUUIDDictionary (uuid_dict, module_spec); } else { const CFIndex num_values = ::CFDictionaryGetCount(plist.get()); if (num_values > 0) { std::vector<CFStringRef> keys (num_values, NULL); std::vector<CFDictionaryRef> values (num_values, NULL); ::CFDictionaryGetKeysAndValues(plist.get(), NULL, (const void **)&values[0]); if (num_values == 1) { return GetModuleSpecInfoFromUUIDDictionary (values[0], module_spec); } else { for (CFIndex i=0; i<num_values; ++i) { ModuleSpec curr_module_spec; if (GetModuleSpecInfoFromUUIDDictionary (values[i], curr_module_spec)) { if (module_spec.GetArchitecture().IsCompatibleMatch(curr_module_spec.GetArchitecture())) { module_spec = curr_module_spec; return true; } } } } } } } } } } } return success; }
static bool GetModuleSpecInfoFromUUIDDictionary(CFDictionaryRef uuid_dict, ModuleSpec &module_spec) { Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); bool success = false; if (uuid_dict != NULL && CFGetTypeID(uuid_dict) == CFDictionaryGetTypeID()) { std::string str; CFStringRef cf_str; CFDictionaryRef cf_dict; cf_str = (CFStringRef)CFDictionaryGetValue( (CFDictionaryRef)uuid_dict, CFSTR("DBGSymbolRichExecutable")); if (cf_str && CFGetTypeID(cf_str) == CFStringGetTypeID()) { if (CFCString::FileSystemRepresentation(cf_str, str)) { module_spec.GetFileSpec().SetFile(str.c_str(), true); if (log) { log->Printf( "From dsymForUUID plist: Symbol rich executable is at '%s'", str.c_str()); } } } cf_str = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)uuid_dict, CFSTR("DBGDSYMPath")); if (cf_str && CFGetTypeID(cf_str) == CFStringGetTypeID()) { if (CFCString::FileSystemRepresentation(cf_str, str)) { module_spec.GetSymbolFileSpec().SetFile(str.c_str(), true); success = true; if (log) { log->Printf("From dsymForUUID plist: dSYM is at '%s'", str.c_str()); } } } cf_str = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)uuid_dict, CFSTR("DBGArchitecture")); if (cf_str && CFGetTypeID(cf_str) == CFStringGetTypeID()) { if (CFCString::FileSystemRepresentation(cf_str, str)) module_spec.GetArchitecture().SetTriple(str.c_str()); } std::string DBGBuildSourcePath; std::string DBGSourcePath; cf_str = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)uuid_dict, CFSTR("DBGBuildSourcePath")); if (cf_str && CFGetTypeID(cf_str) == CFStringGetTypeID()) { CFCString::FileSystemRepresentation(cf_str, DBGBuildSourcePath); } cf_str = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)uuid_dict, CFSTR("DBGSourcePath")); if (cf_str && CFGetTypeID(cf_str) == CFStringGetTypeID()) { CFCString::FileSystemRepresentation(cf_str, DBGSourcePath); } if (!DBGBuildSourcePath.empty() && !DBGSourcePath.empty()) { if (DBGSourcePath[0] == '~') { FileSpec resolved_source_path(DBGSourcePath.c_str(), true); DBGSourcePath = resolved_source_path.GetPath(); } module_spec.GetSourceMappingList().Append( ConstString(DBGBuildSourcePath.c_str()), ConstString(DBGSourcePath.c_str()), true); } cf_dict = (CFDictionaryRef)CFDictionaryGetValue( (CFDictionaryRef)uuid_dict, CFSTR("DBGSourcePathRemapping")); if (cf_dict && CFGetTypeID(cf_dict) == CFDictionaryGetTypeID()) { // If we see DBGVersion with a value of 2 or higher, this is a new style // DBGSourcePathRemapping dictionary bool new_style_source_remapping_dictionary = false; std::string original_DBGSourcePath_value = DBGSourcePath; cf_str = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)uuid_dict, CFSTR("DBGVersion")); if (cf_str && CFGetTypeID(cf_str) == CFStringGetTypeID()) { std::string version; CFCString::FileSystemRepresentation(cf_str, version); if (!version.empty() && isdigit(version[0])) { int version_number = atoi(version.c_str()); if (version_number > 1) { new_style_source_remapping_dictionary = true; } } } CFIndex kv_pair_count = CFDictionaryGetCount((CFDictionaryRef)uuid_dict); if (kv_pair_count > 0) { CFStringRef *keys = (CFStringRef *)malloc(kv_pair_count * sizeof(CFStringRef)); CFStringRef *values = (CFStringRef *)malloc(kv_pair_count * sizeof(CFStringRef)); if (keys != nullptr && values != nullptr) { CFDictionaryGetKeysAndValues((CFDictionaryRef)uuid_dict, (const void **)keys, (const void **)values); } for (CFIndex i = 0; i < kv_pair_count; i++) { DBGBuildSourcePath.clear(); DBGSourcePath.clear(); if (keys[i] && CFGetTypeID(keys[i]) == CFStringGetTypeID()) { CFCString::FileSystemRepresentation(keys[i], DBGBuildSourcePath); } if (values[i] && CFGetTypeID(values[i]) == CFStringGetTypeID()) { CFCString::FileSystemRepresentation(values[i], DBGSourcePath); } if (!DBGBuildSourcePath.empty() && !DBGSourcePath.empty()) { // In the "old style" DBGSourcePathRemapping dictionary, the // DBGSourcePath values // (the "values" half of key-value path pairs) were wrong. Ignore // them and use the // universal DBGSourcePath string from earlier. if (new_style_source_remapping_dictionary == true && !original_DBGSourcePath_value.empty()) { DBGSourcePath = original_DBGSourcePath_value; } if (DBGSourcePath[0] == '~') { FileSpec resolved_source_path(DBGSourcePath.c_str(), true); DBGSourcePath = resolved_source_path.GetPath(); } module_spec.GetSourceMappingList().Append( ConstString(DBGBuildSourcePath.c_str()), ConstString(DBGSourcePath.c_str()), true); } } if (keys) free(keys); if (values) free(values); } } } return success; }
Error PlatformRemoteAppleWatch::GetSharedModule( const ModuleSpec &module_spec, lldb_private::Process *process, ModuleSP &module_sp, const FileSpecList *module_search_paths_ptr, ModuleSP *old_module_sp_ptr, bool *did_create_ptr) { // For Apple Watch, the SDK files are all cached locally on the host // system. So first we ask for the file in the cached SDK, // then we attempt to get a shared module for the right architecture // with the right UUID. const FileSpec &platform_file = module_spec.GetFileSpec(); Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST | LIBLLDB_LOG_VERBOSE); Error error; char platform_file_path[PATH_MAX]; if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) { ModuleSpec platform_module_spec(module_spec); UpdateSDKDirectoryInfosIfNeeded(); const uint32_t num_sdk_infos = m_sdk_directory_infos.size(); // If we are connected we migth be able to correctly deduce the SDK // directory // using the OS build. const uint32_t connected_sdk_idx = GetConnectedSDKIndex(); if (connected_sdk_idx < num_sdk_infos) { if (log) { log->Printf("Searching for %s in sdk path %s", platform_file_path, m_sdk_directory_infos[connected_sdk_idx] .directory.GetPath() .c_str()); } if (GetFileInSDK(platform_file_path, connected_sdk_idx, platform_module_spec.GetFileSpec())) { module_sp.reset(); error = ResolveExecutable(platform_module_spec, module_sp, nullptr); if (module_sp) { m_last_module_sdk_idx = connected_sdk_idx; error.Clear(); return error; } } } // Try the last SDK index if it is set as most files from an SDK // will tend to be valid in that same SDK. if (m_last_module_sdk_idx < num_sdk_infos) { if (log) { log->Printf("Searching for %s in sdk path %s", platform_file_path, m_sdk_directory_infos[m_last_module_sdk_idx] .directory.GetPath() .c_str()); } if (GetFileInSDK(platform_file_path, m_last_module_sdk_idx, platform_module_spec.GetFileSpec())) { module_sp.reset(); error = ResolveExecutable(platform_module_spec, module_sp, nullptr); if (module_sp) { error.Clear(); return error; } } } // First try for an exact match of major, minor and update for (uint32_t sdk_idx = 0; sdk_idx < num_sdk_infos; ++sdk_idx) { if (m_last_module_sdk_idx == sdk_idx) { // Skip the last module SDK index if we already searched // it above continue; } if (log) { log->Printf("Searching for %s in sdk path %s", platform_file_path, m_sdk_directory_infos[sdk_idx].directory.GetPath().c_str()); } if (GetFileInSDK(platform_file_path, sdk_idx, platform_module_spec.GetFileSpec())) { // printf ("sdk[%u]: '%s'\n", sdk_idx, local_file.GetPath().c_str()); error = ResolveExecutable(platform_module_spec, module_sp, nullptr); if (module_sp) { // Remember the index of the last SDK that we found a file // in in case the wrong SDK was selected. m_last_module_sdk_idx = sdk_idx; error.Clear(); return error; } } } } // Not the module we are looking for... Nothing to see here... module_sp.reset(); // This may not be an SDK-related module. Try whether we can bring in the // thing to our local cache. error = GetSharedModuleWithLocalCache(module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr, did_create_ptr); if (error.Success()) return error; // See if the file is present in any of the module_search_paths_ptr // directories. if (!module_sp && module_search_paths_ptr && platform_file) { // create a vector of all the file / directory names in platform_file // e.g. this might be // /System/Library/PrivateFrameworks/UIFoundation.framework/UIFoundation // // We'll need to look in the module_search_paths_ptr directories for // both "UIFoundation" and "UIFoundation.framework" -- most likely the // latter will be the one we find there. FileSpec platform_pull_apart(platform_file); std::vector<std::string> path_parts; ConstString unix_root_dir("/"); while (true) { ConstString part = platform_pull_apart.GetLastPathComponent(); platform_pull_apart.RemoveLastPathComponent(); if (part.IsEmpty() || part == unix_root_dir) break; path_parts.push_back(part.AsCString()); } const size_t path_parts_size = path_parts.size(); size_t num_module_search_paths = module_search_paths_ptr->GetSize(); for (size_t i = 0; i < num_module_search_paths; ++i) { // Create a new FileSpec with this module_search_paths_ptr // plus just the filename ("UIFoundation"), then the parent // dir plus filename ("UIFoundation.framework/UIFoundation") // etc - up to four names (to handle "Foo.framework/Contents/MacOS/Foo") for (size_t j = 0; j < 4 && j < path_parts_size - 1; ++j) { FileSpec path_to_try(module_search_paths_ptr->GetFileSpecAtIndex(i)); // Add the components backwards. For // .../PrivateFrameworks/UIFoundation.framework/UIFoundation // path_parts is // [0] UIFoundation // [1] UIFoundation.framework // [2] PrivateFrameworks // // and if 'j' is 2, we want to append path_parts[1] and then // path_parts[0], aka // 'UIFoundation.framework/UIFoundation', to the module_search_paths_ptr // path. for (int k = j; k >= 0; --k) { path_to_try.AppendPathComponent(path_parts[k]); } if (path_to_try.Exists()) { ModuleSpec new_module_spec(module_spec); new_module_spec.GetFileSpec() = path_to_try; Error new_error(Platform::GetSharedModule( new_module_spec, process, module_sp, NULL, old_module_sp_ptr, did_create_ptr)); if (module_sp) { module_sp->SetPlatformFileSpec(path_to_try); return new_error; } } } } } const bool always_create = false; error = ModuleList::GetSharedModule( module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr, did_create_ptr, always_create); if (module_sp) module_sp->SetPlatformFileSpec(platform_file); return error; }
int LocateMacOSXFilesUsingDebugSymbols(const ModuleSpec &module_spec, ModuleSpec &return_module_spec) { return_module_spec = module_spec; return_module_spec.GetFileSpec().Clear(); return_module_spec.GetSymbolFileSpec().Clear(); int items_found = 0; #if !defined(__arm__) && !defined(__arm64__) && \ !defined(__aarch64__) // No DebugSymbols on the iOS devices const UUID *uuid = module_spec.GetUUIDPtr(); const ArchSpec *arch = module_spec.GetArchitecturePtr(); if (uuid && uuid->IsValid()) { // Try and locate the dSYM file using DebugSymbols first const UInt8 *module_uuid = (const UInt8 *)uuid->GetBytes(); if (module_uuid != NULL) { CFCReleaser<CFUUIDRef> module_uuid_ref(::CFUUIDCreateWithBytes( NULL, module_uuid[0], module_uuid[1], module_uuid[2], module_uuid[3], module_uuid[4], module_uuid[5], module_uuid[6], module_uuid[7], module_uuid[8], module_uuid[9], module_uuid[10], module_uuid[11], module_uuid[12], module_uuid[13], module_uuid[14], module_uuid[15])); if (module_uuid_ref.get()) { CFCReleaser<CFURLRef> exec_url; const FileSpec *exec_fspec = module_spec.GetFileSpecPtr(); Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); if (exec_fspec) { char exec_cf_path[PATH_MAX]; if (exec_fspec->GetPath(exec_cf_path, sizeof(exec_cf_path))) exec_url.reset(::CFURLCreateFromFileSystemRepresentation( NULL, (const UInt8 *)exec_cf_path, strlen(exec_cf_path), FALSE)); } CFCReleaser<CFURLRef> dsym_url( ::DBGCopyFullDSYMURLForUUID(module_uuid_ref.get(), exec_url.get())); char path[PATH_MAX]; if (dsym_url.get()) { if (::CFURLGetFileSystemRepresentation( dsym_url.get(), true, (UInt8 *)path, sizeof(path) - 1)) { if (log) { log->Printf("DebugSymbols framework returned dSYM path of %s for " "UUID %s -- looking for the dSYM", path, uuid->GetAsString().c_str()); } FileSpec dsym_filespec(path, path[0] == '~'); if (dsym_filespec.GetFileType() == FileSpec::eFileTypeDirectory) { dsym_filespec = Symbols::FindSymbolFileInBundle(dsym_filespec, uuid, arch); ++items_found; } else { ++items_found; } return_module_spec.GetSymbolFileSpec() = dsym_filespec; } bool success = false; if (log) { if (::CFURLGetFileSystemRepresentation( dsym_url.get(), true, (UInt8 *)path, sizeof(path) - 1)) { log->Printf("DebugSymbols framework returned dSYM path of %s for " "UUID %s -- looking for an exec file", path, uuid->GetAsString().c_str()); } } CFCReleaser<CFDictionaryRef> dict( ::DBGCopyDSYMPropertyLists(dsym_url.get())); CFDictionaryRef uuid_dict = NULL; if (dict.get()) { CFCString uuid_cfstr(uuid->GetAsString().c_str()); uuid_dict = static_cast<CFDictionaryRef>( ::CFDictionaryGetValue(dict.get(), uuid_cfstr.get())); } if (uuid_dict) { CFStringRef exec_cf_path = static_cast<CFStringRef>(::CFDictionaryGetValue( uuid_dict, CFSTR("DBGSymbolRichExecutable"))); if (exec_cf_path && ::CFStringGetFileSystemRepresentation( exec_cf_path, path, sizeof(path))) { if (log) { log->Printf("plist bundle has exec path of %s for UUID %s", path, uuid->GetAsString().c_str()); } ++items_found; FileSpec exec_filespec(path, path[0] == '~'); if (exec_filespec.Exists()) { success = true; return_module_spec.GetFileSpec() = exec_filespec; } } } if (!success) { // No dictionary, check near the dSYM bundle for an executable that // matches... if (::CFURLGetFileSystemRepresentation( dsym_url.get(), true, (UInt8 *)path, sizeof(path) - 1)) { char *dsym_extension_pos = ::strstr(path, ".dSYM"); if (dsym_extension_pos) { *dsym_extension_pos = '\0'; if (log) { log->Printf("Looking for executable binary next to dSYM " "bundle with name with name %s", path); } FileSpec file_spec(path, true); ModuleSpecList module_specs; ModuleSpec matched_module_spec; switch (file_spec.GetFileType()) { case FileSpec::eFileTypeDirectory: // Bundle directory? { CFCBundle bundle(path); CFCReleaser<CFURLRef> bundle_exe_url( bundle.CopyExecutableURL()); if (bundle_exe_url.get()) { 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)) { ++items_found; return_module_spec.GetFileSpec() = bundle_exe_file_spec; if (log) { log->Printf("Executable binary %s next to dSYM is " "compatible; using", path); } } } } } break; case FileSpec::eFileTypePipe: // Forget pipes case FileSpec::eFileTypeSocket: // We can't process socket files case FileSpec::eFileTypeInvalid: // File doesn't exist... break; case FileSpec::eFileTypeUnknown: case FileSpec::eFileTypeRegular: case FileSpec::eFileTypeSymbolicLink: case FileSpec::eFileTypeOther: if (ObjectFile::GetModuleSpecifications(file_spec, 0, 0, module_specs) && module_specs.FindMatchingModuleSpec(module_spec, matched_module_spec)) { ++items_found; return_module_spec.GetFileSpec() = file_spec; if (log) { log->Printf("Executable binary %s next to dSYM is " "compatible; using", path); } } break; } } } } } } } } #endif // #if !defined (__arm__) && !defined (__arm64__) && !defined // (__aarch64__) return items_found; }
Error PlatformFreeBSD::ResolveExecutable (const ModuleSpec &module_spec, lldb::ModuleSP &exe_module_sp, const FileSpecList *module_search_paths_ptr) { Error error; // Nothing special to do here, just use the actual file and architecture char exe_path[PATH_MAX]; ModuleSpec resolved_module_spec(module_spec); if (IsHost()) { // If we have "ls" as the module_spec's file, resolve the executable location based on // the current path variables if (!resolved_module_spec.GetFileSpec().Exists()) { module_spec.GetFileSpec().GetPath(exe_path, sizeof(exe_path)); resolved_module_spec.GetFileSpec().SetFile(exe_path, true); } if (!resolved_module_spec.GetFileSpec().Exists()) resolved_module_spec.GetFileSpec().ResolveExecutableLocation (); if (resolved_module_spec.GetFileSpec().Exists()) error.Clear(); else { error.SetErrorStringWithFormat("unable to find executable for '%s'", resolved_module_spec.GetFileSpec().GetPath().c_str()); } } else { if (m_remote_platform_sp) { error = GetCachedExecutable (resolved_module_spec, exe_module_sp, module_search_paths_ptr, *m_remote_platform_sp); } else { // We may connect to a process and use the provided executable (Don't use local $PATH). // Resolve any executable within a bundle on MacOSX Host::ResolveExecutableInBundle (resolved_module_spec.GetFileSpec()); if (resolved_module_spec.GetFileSpec().Exists()) { error.Clear(); } else { error.SetErrorStringWithFormat("the platform is not currently connected, and '%s' doesn't exist in the system root.", resolved_module_spec.GetFileSpec().GetPath().c_str()); } } } if (error.Success()) { if (resolved_module_spec.GetArchitecture().IsValid()) { error = ModuleList::GetSharedModule (resolved_module_spec, exe_module_sp, module_search_paths_ptr, NULL, NULL); if (!exe_module_sp || exe_module_sp->GetObjectFile() == NULL) { exe_module_sp.reset(); error.SetErrorStringWithFormat ("'%s' doesn't contain the architecture %s", resolved_module_spec.GetFileSpec().GetPath().c_str(), resolved_module_spec.GetArchitecture().GetArchitectureName()); } } else { // No valid architecture was specified, ask the platform for // the architectures that we should be using (in the correct order) // and see if we can find a match that way StreamString arch_names; for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, resolved_module_spec.GetArchitecture()); ++idx) { error = ModuleList::GetSharedModule (resolved_module_spec, exe_module_sp, module_search_paths_ptr, NULL, NULL); // Did we find an executable using one of the if (error.Success()) { if (exe_module_sp && exe_module_sp->GetObjectFile()) break; else error.SetErrorToGenericError(); } if (idx > 0) arch_names.PutCString (", "); arch_names.PutCString (resolved_module_spec.GetArchitecture().GetArchitectureName()); } if (error.Fail() || !exe_module_sp) { if (resolved_module_spec.GetFileSpec().Readable()) { error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s", resolved_module_spec.GetFileSpec().GetPath().c_str(), GetPluginName().GetCString(), arch_names.GetString().c_str()); } else { error.SetErrorStringWithFormat("'%s' is not readable", resolved_module_spec.GetFileSpec().GetPath().c_str()); } } } } return error; }
Error PlatformiOSSimulator::ResolveExecutable( const ModuleSpec &module_spec, lldb::ModuleSP &exe_module_sp, const FileSpecList *module_search_paths_ptr) { Error error; // Nothing special to do here, just use the actual file and architecture ModuleSpec resolved_module_spec(module_spec); // If we have "ls" as the exe_file, resolve the executable loation based on // the current path variables // TODO: resolve bare executables in the Platform SDK // if (!resolved_exe_file.Exists()) // resolved_exe_file.ResolveExecutableLocation (); // Resolve any executable within a bundle on MacOSX // TODO: verify that this handles shallow bundles, if not then implement one // ourselves Host::ResolveExecutableInBundle(resolved_module_spec.GetFileSpec()); if (resolved_module_spec.GetFileSpec().Exists()) { if (resolved_module_spec.GetArchitecture().IsValid()) { error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp, NULL, NULL, NULL); if (exe_module_sp && exe_module_sp->GetObjectFile()) return error; exe_module_sp.reset(); } // No valid architecture was specified or the exact ARM slice wasn't // found so ask the platform for the architectures that we should be // using (in the correct order) and see if we can find a match that way StreamString arch_names; ArchSpec platform_arch; for (uint32_t idx = 0; GetSupportedArchitectureAtIndex( idx, resolved_module_spec.GetArchitecture()); ++idx) { // Only match x86 with x86 and x86_64 with x86_64... if (!module_spec.GetArchitecture().IsValid() || module_spec.GetArchitecture().GetCore() == resolved_module_spec.GetArchitecture().GetCore()) { error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp, NULL, NULL, NULL); // Did we find an executable using one of the if (error.Success()) { if (exe_module_sp && exe_module_sp->GetObjectFile()) break; else error.SetErrorToGenericError(); } if (idx > 0) arch_names.PutCString(", "); arch_names.PutCString(platform_arch.GetArchitectureName()); } } if (error.Fail() || !exe_module_sp) { if (resolved_module_spec.GetFileSpec().Readable()) { error.SetErrorStringWithFormat( "'%s' doesn't contain any '%s' platform architectures: %s", resolved_module_spec.GetFileSpec().GetPath().c_str(), GetPluginName().GetCString(), arch_names.GetString().c_str()); } else { error.SetErrorStringWithFormat( "'%s' is not readable", resolved_module_spec.GetFileSpec().GetPath().c_str()); } } } else { error.SetErrorStringWithFormat("'%s' does not exist", module_spec.GetFileSpec().GetPath().c_str()); } return error; }
static bool LocateDSYMInVincinityOfExecutable(const ModuleSpec &module_spec, FileSpec &dsym_fspec) { Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); 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) { if (log) { if (module_spec.GetUUIDPtr() && module_spec.GetUUIDPtr()->IsValid()) { log->Printf( "Searching for dSYM bundle next to executable %s, UUID %s", path, module_spec.GetUUIDPtr()->GetAsString().c_str()); } else { log->Printf("Searching for dSYM bundle next to executable %s", path); } } 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() && FileAtPathContainsArchAndUUID(dsym_fspec, module_spec.GetArchitecturePtr(), module_spec.GetUUIDPtr())) { if (log) { log->Printf("dSYM with matching UUID & arch found at %s", path); } 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() && FileAtPathContainsArchAndUUID( dsym_fspec, module_spec.GetArchitecturePtr(), module_spec.GetUUIDPtr())) { if (log) { log->Printf("dSYM with matching UUID & arch found at %s", path); } 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; }
static bool GetModuleSpecInfoFromUUIDDictionary(CFDictionaryRef uuid_dict, ModuleSpec &module_spec) { Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); bool success = false; if (uuid_dict != NULL && CFGetTypeID(uuid_dict) == CFDictionaryGetTypeID()) { std::string str; CFStringRef cf_str; CFDictionaryRef cf_dict; cf_str = (CFStringRef)CFDictionaryGetValue( (CFDictionaryRef)uuid_dict, CFSTR("DBGSymbolRichExecutable")); if (cf_str && CFGetTypeID(cf_str) == CFStringGetTypeID()) { if (CFCString::FileSystemRepresentation(cf_str, str)) { module_spec.GetFileSpec().SetFile(str.c_str(), FileSpec::Style::native); FileSystem::Instance().Resolve(module_spec.GetFileSpec()); if (log) { log->Printf( "From dsymForUUID plist: Symbol rich executable is at '%s'", str.c_str()); } } } cf_str = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)uuid_dict, CFSTR("DBGDSYMPath")); if (cf_str && CFGetTypeID(cf_str) == CFStringGetTypeID()) { if (CFCString::FileSystemRepresentation(cf_str, str)) { module_spec.GetSymbolFileSpec().SetFile(str.c_str(), FileSpec::Style::native); FileSystem::Instance().Resolve(module_spec.GetFileSpec()); success = true; if (log) { log->Printf("From dsymForUUID plist: dSYM is at '%s'", str.c_str()); } } } cf_str = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)uuid_dict, CFSTR("DBGArchitecture")); if (cf_str && CFGetTypeID(cf_str) == CFStringGetTypeID()) { if (CFCString::FileSystemRepresentation(cf_str, str)) module_spec.GetArchitecture().SetTriple(str.c_str()); } std::string DBGBuildSourcePath; std::string DBGSourcePath; // If DBGVersion 1 or DBGVersion missing, ignore DBGSourcePathRemapping. // If DBGVersion 2, strip last two components of path remappings from // entries to fix an issue with a specific set of // DBGSourcePathRemapping entries that lldb worked // with. // If DBGVersion 3, trust & use the source path remappings as-is. // cf_dict = (CFDictionaryRef)CFDictionaryGetValue( (CFDictionaryRef)uuid_dict, CFSTR("DBGSourcePathRemapping")); if (cf_dict && CFGetTypeID(cf_dict) == CFDictionaryGetTypeID()) { // If we see DBGVersion with a value of 2 or higher, this is a new style // DBGSourcePathRemapping dictionary bool new_style_source_remapping_dictionary = false; bool do_truncate_remapping_names = false; std::string original_DBGSourcePath_value = DBGSourcePath; cf_str = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)uuid_dict, CFSTR("DBGVersion")); if (cf_str && CFGetTypeID(cf_str) == CFStringGetTypeID()) { std::string version; CFCString::FileSystemRepresentation(cf_str, version); if (!version.empty() && isdigit(version[0])) { int version_number = atoi(version.c_str()); if (version_number > 1) { new_style_source_remapping_dictionary = true; } if (version_number == 2) { do_truncate_remapping_names = true; } } } CFIndex kv_pair_count = CFDictionaryGetCount((CFDictionaryRef)uuid_dict); if (kv_pair_count > 0) { CFStringRef *keys = (CFStringRef *)malloc(kv_pair_count * sizeof(CFStringRef)); CFStringRef *values = (CFStringRef *)malloc(kv_pair_count * sizeof(CFStringRef)); if (keys != nullptr && values != nullptr) { CFDictionaryGetKeysAndValues((CFDictionaryRef)uuid_dict, (const void **)keys, (const void **)values); } for (CFIndex i = 0; i < kv_pair_count; i++) { DBGBuildSourcePath.clear(); DBGSourcePath.clear(); if (keys[i] && CFGetTypeID(keys[i]) == CFStringGetTypeID()) { CFCString::FileSystemRepresentation(keys[i], DBGBuildSourcePath); } if (values[i] && CFGetTypeID(values[i]) == CFStringGetTypeID()) { CFCString::FileSystemRepresentation(values[i], DBGSourcePath); } if (!DBGBuildSourcePath.empty() && !DBGSourcePath.empty()) { // In the "old style" DBGSourcePathRemapping dictionary, the // DBGSourcePath values (the "values" half of key-value path pairs) // were wrong. Ignore them and use the universal DBGSourcePath // string from earlier. if (new_style_source_remapping_dictionary && !original_DBGSourcePath_value.empty()) { DBGSourcePath = original_DBGSourcePath_value; } if (DBGSourcePath[0] == '~') { FileSpec resolved_source_path(DBGSourcePath.c_str()); FileSystem::Instance().Resolve(resolved_source_path); DBGSourcePath = resolved_source_path.GetPath(); } // With version 2 of DBGSourcePathRemapping, we can chop off the // last two filename parts from the source remapping and get a more // general source remapping that still works. Add this as another // option in addition to the full source path remap. module_spec.GetSourceMappingList().Append( ConstString(DBGBuildSourcePath.c_str()), ConstString(DBGSourcePath.c_str()), true); if (do_truncate_remapping_names) { FileSpec build_path(DBGBuildSourcePath.c_str()); FileSpec source_path(DBGSourcePath.c_str()); build_path.RemoveLastPathComponent(); build_path.RemoveLastPathComponent(); source_path.RemoveLastPathComponent(); source_path.RemoveLastPathComponent(); module_spec.GetSourceMappingList().Append( ConstString(build_path.GetPath().c_str()), ConstString(source_path.GetPath().c_str()), true); } } } if (keys) free(keys); if (values) free(values); } } // If we have a DBGBuildSourcePath + DBGSourcePath pair, append them to the // source remappings list. cf_str = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)uuid_dict, CFSTR("DBGBuildSourcePath")); if (cf_str && CFGetTypeID(cf_str) == CFStringGetTypeID()) { CFCString::FileSystemRepresentation(cf_str, DBGBuildSourcePath); } cf_str = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)uuid_dict, CFSTR("DBGSourcePath")); if (cf_str && CFGetTypeID(cf_str) == CFStringGetTypeID()) { CFCString::FileSystemRepresentation(cf_str, DBGSourcePath); } if (!DBGBuildSourcePath.empty() && !DBGSourcePath.empty()) { if (DBGSourcePath[0] == '~') { FileSpec resolved_source_path(DBGSourcePath.c_str()); FileSystem::Instance().Resolve(resolved_source_path); DBGSourcePath = resolved_source_path.GetPath(); } module_spec.GetSourceMappingList().Append( ConstString(DBGBuildSourcePath.c_str()), ConstString(DBGSourcePath.c_str()), true); } } return success; }