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); 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 { 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'; 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 { *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 PlatformiOSSimulator::GetSymbolFile(const FileSpec &platform_file, const UUID *uuid_ptr, FileSpec &local_file) { Error error; char platform_file_path[PATH_MAX]; if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) { char resolved_path[PATH_MAX]; const char *sdk_dir = GetSDKDirectoryAsCString(); if (sdk_dir) { ::snprintf(resolved_path, sizeof(resolved_path), "%s/%s", sdk_dir, platform_file_path); // First try in the SDK and see if the file is in there local_file.SetFile(resolved_path, true); if (local_file.Exists()) return error; // Else fall back to the actual path itself local_file.SetFile(platform_file_path, true); if (local_file.Exists()) return error; } error.SetErrorStringWithFormat( "unable to locate a platform file for '%s' in platform '%s'", platform_file_path, GetPluginName().GetCString()); } else { error.SetErrorString("invalid platform file argument"); } return error; }
Error PlatformRemoteAppleWatch::GetSymbolFile(const FileSpec &platform_file, const UUID *uuid_ptr, FileSpec &local_file) { Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); Error error; char platform_file_path[PATH_MAX]; if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) { char resolved_path[PATH_MAX]; const char *os_version_dir = GetDeviceSupportDirectoryForOSVersion(); if (os_version_dir) { ::snprintf(resolved_path, sizeof(resolved_path), "%s/%s", os_version_dir, platform_file_path); local_file.SetFile(resolved_path, true); if (local_file.Exists()) { if (log) { log->Printf("Found a copy of %s in the DeviceSupport dir %s", platform_file_path, os_version_dir); } return error; } ::snprintf(resolved_path, sizeof(resolved_path), "%s/Symbols.Internal/%s", os_version_dir, platform_file_path); local_file.SetFile(resolved_path, true); if (local_file.Exists()) { if (log) { log->Printf( "Found a copy of %s in the DeviceSupport dir %s/Symbols.Internal", platform_file_path, os_version_dir); } return error; } ::snprintf(resolved_path, sizeof(resolved_path), "%s/Symbols/%s", os_version_dir, platform_file_path); local_file.SetFile(resolved_path, true); if (local_file.Exists()) { if (log) { log->Printf("Found a copy of %s in the DeviceSupport dir %s/Symbols", platform_file_path, os_version_dir); } return error; } } local_file = platform_file; if (local_file.Exists()) return error; error.SetErrorStringWithFormat( "unable to locate a platform file for '%s' in platform '%s'", platform_file_path, GetPluginName().GetCString()); } else { error.SetErrorString("invalid platform file argument"); } return error; }
Error PlatformRemoteiOS::GetSymbolFile (const FileSpec &platform_file, const UUID *uuid_ptr, FileSpec &local_file) { Error error; char platform_file_path[PATH_MAX]; if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) { char resolved_path[PATH_MAX]; const char * os_version_dir = GetDeviceSupportDirectoryForOSVersion(); if (os_version_dir) { ::snprintf (resolved_path, sizeof(resolved_path), "%s/%s", os_version_dir, platform_file_path); local_file.SetFile(resolved_path, true); if (local_file.Exists()) return error; ::snprintf (resolved_path, sizeof(resolved_path), "%s/Symbols.Internal/%s", os_version_dir, platform_file_path); local_file.SetFile(resolved_path, true); if (local_file.Exists()) return error; ::snprintf (resolved_path, sizeof(resolved_path), "%s/Symbols/%s", os_version_dir, platform_file_path); local_file.SetFile(resolved_path, true); if (local_file.Exists()) return error; } local_file = platform_file; if (local_file.Exists()) return error; error.SetErrorStringWithFormat ("unable to locate a platform file for '%s' in platform '%s'", platform_file_path, GetPluginName().GetCString()); } else { error.SetErrorString ("invalid platform file argument"); } return error; }
bool PathMappingList::FindFile (const FileSpec &orig_spec, FileSpec &new_spec) const { if (!m_pairs.empty()) { char orig_path[PATH_MAX]; char new_path[PATH_MAX]; const size_t orig_path_len = orig_spec.GetPath (orig_path, sizeof(orig_path)); if (orig_path_len > 0) { const_iterator pos, end = m_pairs.end(); for (pos = m_pairs.begin(); pos != end; ++pos) { const size_t prefix_len = pos->first.GetLength(); if (orig_path_len >= prefix_len) { if (::strncmp (pos->first.GetCString(), orig_path, prefix_len) == 0) { const size_t new_path_len = snprintf(new_path, sizeof(new_path), "%s/%s", pos->second.GetCString(), orig_path + prefix_len); if (new_path_len < sizeof(new_path)) { new_spec.SetFile (new_path, true); if (new_spec.Exists()) return true; } } } } } } new_spec.Clear(); return false; }
void PlatformDarwinKernel::GetUserSpecifiedDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories) { FileSpecList user_dirs(GetGlobalProperties()->GetKextDirectories()); std::vector<FileSpec> possible_sdk_dirs; const uint32_t user_dirs_count = user_dirs.GetSize(); for (uint32_t i = 0; i < user_dirs_count; i++) { FileSpec dir = user_dirs.GetFileSpecAtIndex (i); dir.ResolvePath(); if (dir.Exists() && dir.IsDirectory()) { directories.push_back (dir); possible_sdk_dirs.push_back (dir); // does this directory have a *.sdk or *.kdk that we should look in? // Is there a "System/Library/Extensions" subdir of this directory? std::string dir_sle_path = dir.GetPath(); dir_sle_path.append ("/System/Library/Extensions"); FileSpec dir_sle(dir_sle_path.c_str(), true); if (dir_sle.Exists() && dir_sle.IsDirectory()) { directories.push_back (dir_sle); } } } SearchSDKsForKextDirectories (possible_sdk_dirs, directories); }
static llvm::sys::DynamicLibrary LoadPlugin (const lldb::DebuggerSP &debugger_sp, const FileSpec& spec, Error& error) { llvm::sys::DynamicLibrary dynlib = llvm::sys::DynamicLibrary::getPermanentLibrary(spec.GetPath().c_str()); if (dynlib.isValid()) { typedef bool (*LLDBCommandPluginInit) (lldb::SBDebugger& debugger); lldb::SBDebugger debugger_sb(debugger_sp); // This calls the bool lldb::PluginInitialize(lldb::SBDebugger debugger) function. // TODO: mangle this differently for your system - on OSX, the first underscore needs to be removed and the second one stays LLDBCommandPluginInit init_func = (LLDBCommandPluginInit)dynlib.getAddressOfSymbol("_ZN4lldb16PluginInitializeENS_10SBDebuggerE"); if (init_func) { if (init_func(debugger_sb)) return dynlib; else error.SetErrorString("plug-in refused to load (lldb::PluginInitialize(lldb::SBDebugger) returned false)"); } else { error.SetErrorString("plug-in is missing the required initialization: lldb::PluginInitialize(lldb::SBDebugger)"); } } else { if (spec.Exists()) error.SetErrorString("this file does not represent a loadable dylib"); else error.SetErrorString("no such file"); } return llvm::sys::DynamicLibrary(); }
Error PlatformDarwin::ResolveSymbolFile (Target &target, const ModuleSpec &sym_spec, FileSpec &sym_file) { Error error; sym_file = sym_spec.GetSymbolFileSpec(); if (sym_file.Exists()) { if (sym_file.GetFileType() == FileSpec::eFileTypeDirectory) { sym_file = Symbols::FindSymbolFileInBundle (sym_file, sym_spec.GetUUIDPtr(), sym_spec.GetArchitecturePtr()); } } else { if (sym_spec.GetUUID().IsValid()) { } } return error; }
bool PlatformPOSIX::GetFileExists (const FileSpec& file_spec) { if (IsHost()) return file_spec.Exists(); else if (m_remote_platform_sp) return m_remote_platform_sp->GetFileExists(file_spec); else return Platform::GetFileExists(file_spec); }
bool HostInfoLinux::ComputeSupportExeDirectory(FileSpec &file_spec) { if (HostInfoPosix::ComputeSupportExeDirectory(file_spec) && !file_spec.IsRelativeToCurrentWorkingDirectory() && file_spec.Exists()) return true; file_spec.GetDirectory() = GetProgramFileSpec().GetDirectory(); return !file_spec.GetDirectory().IsEmpty(); }
Error Platform::ResolveExecutable (const FileSpec &exe_file, const ArchSpec &exe_arch, lldb::ModuleSP &exe_module_sp) { Error error; if (exe_file.Exists()) { if (exe_arch.IsValid()) { error = ModuleList::GetSharedModule (exe_file, exe_arch, NULL, NULL, 0, exe_module_sp, NULL, NULL); } 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 ArchSpec platform_arch; for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, platform_arch); ++idx) { error = ModuleList::GetSharedModule (exe_file, platform_arch, NULL, NULL, 0, exe_module_sp, NULL, NULL); // Did we find an executable using one of the if (error.Success() && exe_module_sp) break; } } } else { error.SetErrorStringWithFormat ("'%s%s%s' does not exist", exe_file.GetDirectory().AsCString(""), exe_file.GetDirectory() ? "/" : "", exe_file.GetFilename().AsCString("")); } return error; }
Error Platform::ResolveExecutable (const FileSpec &exe_file, const ArchSpec &exe_arch, lldb::ModuleSP &exe_module_sp, const FileSpecList *module_search_paths_ptr) { Error error; if (exe_file.Exists()) { ModuleSpec module_spec (exe_file, exe_arch); if (module_spec.GetArchitecture().IsValid()) { error = ModuleList::GetSharedModule (module_spec, exe_module_sp, module_search_paths_ptr, NULL, NULL); } 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 for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, module_spec.GetArchitecture()); ++idx) { error = ModuleList::GetSharedModule (module_spec, exe_module_sp, module_search_paths_ptr, NULL, NULL); // Did we find an executable using one of the if (error.Success() && exe_module_sp) break; } } } else { error.SetErrorStringWithFormat ("'%s' does not exist", exe_file.GetPath().c_str()); } return error; }
FileSpec::EnumerateDirectoryResult PlatformDarwinKernel::GetKextsInDirectory (void *baton, FileSpec::FileType file_type, const FileSpec &file_spec) { if (file_type == FileSpec::eFileTypeDirectory && file_spec.GetFileNameExtension() == ConstString("kext")) { ((std::vector<lldb_private::FileSpec> *)baton)->push_back(file_spec); std::string kext_bundle_path = file_spec.GetPath(); std::string search_here_too; std::string contents_plugins_path = kext_bundle_path + "/Contents/PlugIns"; FileSpec contents_plugins (contents_plugins_path.c_str(), false); if (contents_plugins.Exists() && contents_plugins.IsDirectory()) { search_here_too = contents_plugins_path; } else { std::string plugins_path = kext_bundle_path + "/PlugIns"; FileSpec plugins (plugins_path.c_str(), false); if (plugins.Exists() && plugins.IsDirectory()) { search_here_too = plugins_path; } } if (!search_here_too.empty()) { const bool find_directories = true; const bool find_files = false; const bool find_other = false; FileSpec::EnumerateDirectory (search_here_too.c_str(), find_directories, find_files, find_other, GetKextsInDirectory, baton); } } return FileSpec::eEnumerateDirectoryResultNext; }
bool ObjectFile::SplitArchivePathWithObject (const char *path_with_object, FileSpec &archive_file, ConstString &archive_object, bool must_exist) { RegularExpression g_object_regex("(.*)\\(([^\\)]+)\\)$"); RegularExpression::Match regex_match(2); if (g_object_regex.Execute (path_with_object, ®ex_match)) { std::string path; std::string obj; if (regex_match.GetMatchAtIndex (path_with_object, 1, path) && regex_match.GetMatchAtIndex (path_with_object, 2, obj)) { archive_file.SetFile (path.c_str(), false); archive_object.SetCString(obj.c_str()); if (must_exist && !archive_file.Exists()) return false; return true; } } return false; }
bool FileSystem::GetFileExists(const FileSpec &file_spec) { return file_spec.Exists(); }
Error TargetList::CreateTargetInternal (Debugger &debugger, const char *user_exe_path, const ArchSpec& specified_arch, bool get_dependent_files, lldb::PlatformSP &platform_sp, lldb::TargetSP &target_sp, bool is_dummy_target) { Timer scoped_timer (__PRETTY_FUNCTION__, "TargetList::CreateTarget (file = '%s', arch = '%s')", user_exe_path, specified_arch.GetArchitectureName()); Error error; ArchSpec arch(specified_arch); if (arch.IsValid()) { if (!platform_sp || !platform_sp->IsCompatibleArchitecture(arch, false, NULL)) platform_sp = Platform::GetPlatformForArchitecture(specified_arch, &arch); } if (!platform_sp) platform_sp = debugger.GetPlatformList().GetSelectedPlatform(); if (!arch.IsValid()) arch = specified_arch; FileSpec file (user_exe_path, false); if (!file.Exists() && user_exe_path && user_exe_path[0] == '~') { // we want to expand the tilde but we don't want to resolve any symbolic links // so we can't use the FileSpec constructor's resolve flag llvm::SmallString<64> unglobbed_path(user_exe_path); FileSpec::ResolveUsername(unglobbed_path); if (unglobbed_path.empty()) file = FileSpec(user_exe_path, false); else file = FileSpec(unglobbed_path.c_str(), false); } bool user_exe_path_is_bundle = false; char resolved_bundle_exe_path[PATH_MAX]; resolved_bundle_exe_path[0] = '\0'; if (file) { if (file.GetFileType() == FileSpec::eFileTypeDirectory) user_exe_path_is_bundle = true; if (file.IsRelative() && user_exe_path) { // Ignore paths that start with "./" and "../" if (!((user_exe_path[0] == '.' && user_exe_path[1] == '/') || (user_exe_path[0] == '.' && user_exe_path[1] == '.' && user_exe_path[2] == '/'))) { char cwd[PATH_MAX]; if (getcwd (cwd, sizeof(cwd))) { std::string cwd_user_exe_path (cwd); cwd_user_exe_path += '/'; cwd_user_exe_path += user_exe_path; FileSpec cwd_file (cwd_user_exe_path.c_str(), false); if (cwd_file.Exists()) file = cwd_file; } } } ModuleSP exe_module_sp; if (platform_sp) { FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths()); ModuleSpec module_spec(file, arch); error = platform_sp->ResolveExecutable (module_spec, exe_module_sp, executable_search_paths.GetSize() ? &executable_search_paths : NULL); } if (error.Success() && exe_module_sp) { if (exe_module_sp->GetObjectFile() == NULL) { if (arch.IsValid()) { error.SetErrorStringWithFormat("\"%s\" doesn't contain architecture %s", file.GetPath().c_str(), arch.GetArchitectureName()); } else { error.SetErrorStringWithFormat("unsupported file type \"%s\"", file.GetPath().c_str()); } return error; } target_sp.reset(new Target(debugger, arch, platform_sp, is_dummy_target)); target_sp->SetExecutableModule (exe_module_sp, get_dependent_files); if (user_exe_path_is_bundle) exe_module_sp->GetFileSpec().GetPath(resolved_bundle_exe_path, sizeof(resolved_bundle_exe_path)); } } else { // No file was specified, just create an empty target with any arch // if a valid arch was specified target_sp.reset(new Target(debugger, arch, platform_sp, is_dummy_target)); } if (target_sp) { // Set argv0 with what the user typed, unless the user specified a // directory. If the user specified a directory, then it is probably a // bundle that was resolved and we need to use the resolved bundle path if (user_exe_path) { // Use exactly what the user typed as the first argument when we exec or posix_spawn if (user_exe_path_is_bundle && resolved_bundle_exe_path[0]) { target_sp->SetArg0 (resolved_bundle_exe_path); } else { // Use resolved path target_sp->SetArg0 (file.GetPath().c_str()); } } if (file.GetDirectory()) { FileSpec file_dir; file_dir.GetDirectory() = file.GetDirectory(); target_sp->GetExecutableSearchPaths ().Append (file_dir); } // Don't put the dummy target in the target list, it's held separately. if (!is_dummy_target) { Mutex::Locker locker(m_target_list_mutex); m_selected_target_idx = m_target_list.size(); m_target_list.push_back(target_sp); // Now prime this from the dummy target: target_sp->PrimeFromDummyTarget(debugger.GetDummyTarget()); } else { m_dummy_target_sp = target_sp; } } return error; }
ConstString PlatformMacOSX::GetSDKDirectory (lldb_private::Target &target) { ModuleSP exe_module_sp (target.GetExecutableModule()); if (exe_module_sp) { ObjectFile *objfile = exe_module_sp->GetObjectFile(); if (objfile) { std::string xcode_contents_path; std::string default_xcode_sdk; FileSpec fspec; uint32_t versions[2]; if (objfile->GetSDKVersion(versions, sizeof(versions))) { if (HostInfo::GetLLDBPath(ePathTypeLLDBShlibDir, fspec)) { std::string path; xcode_contents_path = fspec.GetPath(); size_t pos = xcode_contents_path.find("/Xcode.app/Contents/"); if (pos != std::string::npos) { // LLDB.framework is inside an Xcode app bundle, we can locate the SDK from here xcode_contents_path.erase(pos + strlen("/Xcode.app/Contents/")); } else { xcode_contents_path.clear(); // Use the selected Xcode int status = 0; int signo = 0; std::string output; const char *command = "xcrun -sdk macosx --show-sdk-path"; lldb_private::Error error = RunShellCommand (command, // shell command to run NULL, // current working directory &status, // Put the exit status of the process in here &signo, // Put the signal that caused the process to exit in here &output, // Get the output from the command and place it in this string 3); // Timeout in seconds to wait for shell program to finish if (status == 0 && !output.empty()) { size_t first_non_newline = output.find_last_not_of("\r\n"); if (first_non_newline != std::string::npos) output.erase(first_non_newline+1); default_xcode_sdk = output; pos = default_xcode_sdk.find("/Xcode.app/Contents/"); if (pos != std::string::npos) xcode_contents_path = default_xcode_sdk.substr(0, pos + strlen("/Xcode.app/Contents/")); } } } if (!xcode_contents_path.empty()) { StreamString sdk_path; sdk_path.Printf("%sDeveloper/Platforms/MacOSX.platform/Developer/SDKs/MacOSX%u.%u.sdk", xcode_contents_path.c_str(), versions[0], versions[1]); fspec.SetFile(sdk_path.GetString().c_str(), false); if (fspec.Exists()) return ConstString(sdk_path.GetString().c_str()); } if (!default_xcode_sdk.empty()) { fspec.SetFile(default_xcode_sdk.c_str(), false); if (fspec.Exists()) return ConstString(default_xcode_sdk.c_str()); } } } } return ConstString(); }
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; }
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); }
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; }