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; }
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 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; }
Status FileSystem::Readlink(const FileSpec &src, FileSpec &dst) { Status error; std::wstring wsrc; if (!llvm::ConvertUTF8toWide(src.GetCString(), wsrc)) { error.SetErrorString(PATH_CONVERSION_ERROR); return error; } HANDLE h = ::CreateFileW(wsrc.c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT, NULL); if (h == INVALID_HANDLE_VALUE) { error.SetError(::GetLastError(), lldb::eErrorTypeWin32); return error; } std::vector<wchar_t> buf(PATH_MAX + 1); // Subtract 1 from the path length since this function does not add a null // terminator. DWORD result = ::GetFinalPathNameByHandleW( h, buf.data(), buf.size() - 1, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); std::string path; if (result == 0) error.SetError(::GetLastError(), lldb::eErrorTypeWin32); else if (!llvm::convertWideToUTF8(buf.data(), path)) error.SetErrorString(PATH_CONVERSION_ERROR); else dst.SetFile(path, false); ::CloseHandle(h); return error; }
Error HostProcessPosix::GetMainModule(FileSpec &file_spec) const { Error error; // Use special code here because proc/[pid]/exe is a symbolic link. char link_path[PATH_MAX]; char exe_path[PATH_MAX] = ""; if (snprintf (link_path, PATH_MAX, "/proc/%" PRIu64 "/exe", m_pid) <= 0) { error.SetErrorString("Unable to build /proc/<pid>/exe string"); return error; } error = FileSystem::Readlink(link_path, exe_path, llvm::array_lengthof(exe_path)); if (!error.Success()) return error; const ssize_t len = strlen(exe_path); // If the binary has been deleted, the link name has " (deleted)" appended. // Remove if there. static const ssize_t deleted_len = strlen(" (deleted)"); if (len > deleted_len && !strcmp(exe_path + len - deleted_len, " (deleted)")) { exe_path[len - deleted_len] = 0; } file_spec.SetFile(exe_path, false); 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; }
FileSpec Host::GetProgramFileSpec () { static FileSpec g_program_filespec; if (!g_program_filespec) { #if defined (__APPLE__) char program_fullpath[PATH_MAX]; // If DST is NULL, then return the number of bytes needed. uint32_t len = sizeof(program_fullpath); int err = _NSGetExecutablePath (program_fullpath, &len); if (err == 0) g_program_filespec.SetFile (program_fullpath, false); else if (err == -1) { char *large_program_fullpath = (char *)::malloc (len + 1); err = _NSGetExecutablePath (large_program_fullpath, &len); if (err == 0) g_program_filespec.SetFile (large_program_fullpath, false); ::free (large_program_fullpath); } #elif defined (__linux__) char exe_path[PATH_MAX]; ssize_t len = readlink("/proc/self/exe", exe_path, sizeof(exe_path) - 1); if (len > 0) { exe_path[len] = 0; g_program_filespec.SetFile(exe_path, false); } #elif defined (__FreeBSD__) int exe_path_mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, getpid() }; size_t exe_path_size; if (sysctl(exe_path_mib, 4, NULL, &exe_path_size, NULL, 0) == 0) { char *exe_path = new char[exe_path_size]; if (sysctl(exe_path_mib, 4, exe_path, &exe_path_size, NULL, 0) == 0) g_program_filespec.SetFile(exe_path, false); delete[] exe_path; } #endif } return g_program_filespec; }
Error File::GetFileSpec (FileSpec &file_spec) const { Error error; #ifdef LLDB_CONFIG_FCNTL_GETPATH_SUPPORTED if (IsValid ()) { char path[PATH_MAX]; if (::fcntl(GetDescriptor(), F_GETPATH, path) == -1) error.SetErrorToErrno(); else file_spec.SetFile (path, false); } else { error.SetErrorString("invalid file handle"); } #elif defined(__linux__) char proc[64]; char path[PATH_MAX]; if (::snprintf(proc, sizeof(proc), "/proc/self/fd/%d", GetDescriptor()) < 0) error.SetErrorString ("cannot resolve file descriptor"); else { ssize_t len; if ((len = ::readlink(proc, path, sizeof(path) - 1)) == -1) error.SetErrorToErrno(); else { path[len] = '\0'; file_spec.SetFile (path, false); } } #else error.SetErrorString ("File::GetFileSpec is not supported on this platform"); #endif if (error.Fail()) file_spec.Clear(); return error; }
FileSpec HostInfoFreeBSD::GetProgramFileSpec() { static FileSpec g_program_filespec; if (!g_program_filespec) { int exe_path_mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, getpid()}; size_t exe_path_size; if (sysctl(exe_path_mib, 4, NULL, &exe_path_size, NULL, 0) == 0) { char *exe_path = new char[exe_path_size]; if (sysctl(exe_path_mib, 4, exe_path, &exe_path_size, NULL, 0) == 0) g_program_filespec.SetFile(exe_path, false); delete[] exe_path; } } return g_program_filespec; }
Error HostProcessWindows::GetMainModule(FileSpec &file_spec) const { Error error; if (m_process == nullptr) error.SetError(ERROR_INVALID_HANDLE, lldb::eErrorTypeWin32); std::vector<wchar_t> wpath(PATH_MAX); if (::GetProcessImageFileNameW(m_process, wpath.data(), wpath.size())) { std::string path; if (llvm::convertWideToUTF8(wpath.data(), path)) file_spec.SetFile(path, false); else error.SetErrorString("Error converting path to UTF-8"); } else error.SetError(::GetLastError(), lldb::eErrorTypeWin32); return error; }
FileSpec HostInfoLinux::GetProgramFileSpec() { static FileSpec g_program_filespec; if (!g_program_filespec) { char exe_path[PATH_MAX]; ssize_t len = readlink("/proc/self/exe", exe_path, sizeof(exe_path) - 1); if (len > 0) { exe_path[len] = 0; g_program_filespec.SetFile(exe_path, false); } } return g_program_filespec; }
bool ObjectFile::SplitArchivePathWithObject (const char *path_with_object, FileSpec &archive_file, ConstString &archive_object) { RegularExpression g_object_regex("(.*)\\(([^\\)]+)\\)$"); if (g_object_regex.Execute (path_with_object, 2)) { std::string path; std::string obj; if (g_object_regex.GetMatchAtIndex (path_with_object, 1, path) && g_object_regex.GetMatchAtIndex (path_with_object, 2, obj)) { archive_file.SetFile (path.c_str(), false); archive_object.SetCString(obj.c_str()); return true; } } return false; }
bool ObjectFile::SplitArchivePathWithObject(const char *path_with_object, FileSpec &archive_file, ConstString &archive_object, bool must_exist) { RegularExpression g_object_regex(llvm::StringRef("(.*)\\(([^\\)]+)\\)$")); RegularExpression::Match regex_match(2); if (g_object_regex.Execute(llvm::StringRef::withNullAsEmpty(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; }
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 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; }
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(); }