static bool SkinnyMachOFileContainsArchAndUUID ( const FileSpec &file_spec, const ArchSpec *arch, const lldb_private::UUID *uuid, // the UUID we are looking for off_t file_offset, DataExtractor& data, uint32_t data_offset, const uint32_t magic ) { assert(magic == HeaderMagic32 || magic == HeaderMagic32Swapped || magic == HeaderMagic64 || magic == HeaderMagic64Swapped); if (magic == HeaderMagic32 || magic == HeaderMagic64) data.SetByteOrder (lldb::endian::InlHostByteOrder()); else if (lldb::endian::InlHostByteOrder() == eByteOrderBig) data.SetByteOrder (eByteOrderLittle); else data.SetByteOrder (eByteOrderBig); uint32_t i; const uint32_t cputype = data.GetU32(&data_offset); // cpu specifier const uint32_t cpusubtype = data.GetU32(&data_offset); // machine specifier data_offset+=4; // Skip mach file type const uint32_t ncmds = data.GetU32(&data_offset); // number of load commands const uint32_t sizeofcmds = data.GetU32(&data_offset); // the size of all the load commands data_offset+=4; // Skip flags // Check the architecture if we have a valid arch pointer if (arch) { ArchSpec file_arch(eArchTypeMachO, cputype, cpusubtype); if (!file_arch.IsCompatibleMatch(*arch)) return false; } // The file exists, and if a valid arch pointer was passed in we know // if already matches, so we can return if we aren't looking for a specific // UUID if (uuid == NULL) return true; if (magic == HeaderMagic64Swapped || magic == HeaderMagic64) data_offset += 4; // Skip reserved field for in mach_header_64 // Make sure we have enough data for all the load commands if (magic == HeaderMagic64Swapped || magic == HeaderMagic64) { if (data.GetByteSize() < sizeof(struct mach_header_64) + sizeofcmds) { DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset, sizeof(struct mach_header_64) + sizeofcmds)); data.SetData (data_buffer_sp); } } else { if (data.GetByteSize() < sizeof(struct mach_header) + sizeofcmds) { DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset, sizeof(struct mach_header) + sizeofcmds)); data.SetData (data_buffer_sp); } } for (i=0; i<ncmds; i++) { const uint32_t cmd_offset = data_offset; // Save this data_offset in case parsing of the segment goes awry! uint32_t cmd = data.GetU32(&data_offset); uint32_t cmd_size = data.GetU32(&data_offset); if (cmd == LoadCommandUUID) { lldb_private::UUID file_uuid (data.GetData(&data_offset, 16), 16); if (file_uuid == *uuid) return true; // Emit some warning messages since the UUIDs do not match! char path_buf[PATH_MAX]; path_buf[0] = '\0'; const char *path = file_spec.GetPath(path_buf, PATH_MAX) ? path_buf : file_spec.GetFilename().AsCString(); StreamString ss_m_uuid, ss_o_uuid; uuid->Dump(&ss_m_uuid); file_uuid.Dump(&ss_o_uuid); Host::SystemLog (Host::eSystemLogWarning, "warning: UUID mismatch detected between binary (%s) and:\n\t'%s' (%s)\n", ss_m_uuid.GetData(), path, ss_o_uuid.GetData()); return false; } data_offset = cmd_offset + cmd_size; } return false; }
FileSourceFactory::FileSourceFactory(const FileSpec & fileSpec) : _fileName(fileSpec.getFileName()) { }
bool UniversalMachOFileContainsArchAndUUID ( const FileSpec &file_spec, const ArchSpec *arch, const lldb_private::UUID *uuid, off_t file_offset, DataExtractor& data, uint32_t data_offset, const uint32_t magic ) { assert(magic == UniversalMagic || magic == UniversalMagicSwapped); // Universal mach-o files always have their headers encoded as BIG endian data.SetByteOrder(eByteOrderBig); uint32_t i; const uint32_t nfat_arch = data.GetU32(&data_offset); // number of structs that follow const uint32_t fat_header_and_arch_size = sizeof(struct fat_header) + nfat_arch * sizeof(struct fat_arch); if (data.GetByteSize() < fat_header_and_arch_size) { DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset, fat_header_and_arch_size)); data.SetData (data_buffer_sp); } for (i=0; i<nfat_arch; i++) { cpu_type_t arch_cputype = data.GetU32(&data_offset); // cpu specifier (int) cpu_subtype_t arch_cpusubtype = data.GetU32(&data_offset); // machine specifier (int) uint32_t arch_offset = data.GetU32(&data_offset); // file offset to this object file // uint32_t arch_size = data.GetU32(&data_offset); // size of this object file // uint32_t arch_align = data.GetU32(&data_offset); // alignment as a power of 2 data_offset += 8; // Skip size and align as we don't need those // Only process this slice if the cpu type/subtype matches if (arch) { ArchSpec fat_arch(eArchTypeMachO, arch_cputype, arch_cpusubtype); if (!fat_arch.IsExactMatch(*arch)) continue; } // Create a buffer with only the arch slice date in it DataExtractor arch_data; DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset + arch_offset, 0x1000)); arch_data.SetData(data_buffer_sp); uint32_t arch_data_offset = 0; uint32_t arch_magic = arch_data.GetU32(&arch_data_offset); switch (arch_magic) { case HeaderMagic32: case HeaderMagic32Swapped: case HeaderMagic64: case HeaderMagic64Swapped: if (SkinnyMachOFileContainsArchAndUUID (file_spec, arch, uuid, file_offset + arch_offset, arch_data, arch_data_offset, arch_magic)) return true; break; } } return false; }
void SourceManager::File::CommonInitializer(const FileSpec &file_spec, Target *target) { if (!m_mod_time.IsValid()) { if (target) { m_source_map_mod_id = target->GetSourcePathMap().GetModificationID(); if (!file_spec.GetDirectory() && file_spec.GetFilename()) { // If this is just a file name, lets see if we can find it in the // target: bool check_inlines = false; SymbolContextList sc_list; size_t num_matches = target->GetImages().ResolveSymbolContextForFilePath( file_spec.GetFilename().AsCString(), 0, check_inlines, lldb::eSymbolContextModule | lldb::eSymbolContextCompUnit, sc_list); bool got_multiple = false; if (num_matches != 0) { if (num_matches > 1) { SymbolContext sc; FileSpec *test_cu_spec = NULL; for (unsigned i = 0; i < num_matches; i++) { sc_list.GetContextAtIndex(i, sc); if (sc.comp_unit) { if (test_cu_spec) { if (test_cu_spec != static_cast<FileSpec *>(sc.comp_unit)) got_multiple = true; break; } else test_cu_spec = sc.comp_unit; } } } if (!got_multiple) { SymbolContext sc; sc_list.GetContextAtIndex(0, sc); m_file_spec = sc.comp_unit; m_mod_time = m_file_spec.GetModificationTime(); } } } // Try remapping if m_file_spec does not correspond to an existing file. if (!m_file_spec.Exists()) { FileSpec new_file_spec; // Check target specific source remappings first, then fall back to // modules objects can have individual path remappings that were // detected // when the debug info for a module was found. // then if (target->GetSourcePathMap().FindFile(m_file_spec, new_file_spec) || target->GetImages().FindSourceFile(m_file_spec, new_file_spec)) { m_file_spec = new_file_spec; m_mod_time = m_file_spec.GetModificationTime(); } } } } if (m_mod_time.IsValid()) m_data_sp = m_file_spec.ReadFileContents(); }
bool HostInfoBase::GetLLDBPath(lldb::PathType type, FileSpec &file_spec) { file_spec.Clear(); #if defined(LLDB_DISABLE_PYTHON) if (type == lldb::ePathTypePythonDir) return false; #endif FileSpec *result = nullptr; switch (type) { case lldb::ePathTypeLLDBShlibDir: { static std::once_flag g_once_flag; static bool success = false; std::call_once(g_once_flag, []() { success = HostInfo::ComputeSharedLibraryDirectory (g_fields->m_lldb_so_dir); Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); if (log) log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBShlibDir) => '%s'", g_fields->m_lldb_so_dir.GetPath().c_str()); }); if (success) result = &g_fields->m_lldb_so_dir; } break; case lldb::ePathTypeSupportExecutableDir: { static std::once_flag g_once_flag; static bool success = false; std::call_once(g_once_flag, []() { success = HostInfo::ComputeSupportExeDirectory (g_fields->m_lldb_support_exe_dir); Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); if (log) log->Printf("HostInfoBase::GetLLDBPath(ePathTypeSupportExecutableDir) => '%s'", g_fields->m_lldb_support_exe_dir.GetPath().c_str()); }); if (success) result = &g_fields->m_lldb_support_exe_dir; } break; case lldb::ePathTypeHeaderDir: { static std::once_flag g_once_flag; static bool success = false; std::call_once(g_once_flag, []() { success = HostInfo::ComputeHeaderDirectory (g_fields->m_lldb_headers_dir); Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); if (log) log->Printf("HostInfoBase::GetLLDBPath(ePathTypeHeaderDir) => '%s'", g_fields->m_lldb_headers_dir.GetPath().c_str()); }); if (success) result = &g_fields->m_lldb_headers_dir; } break; case lldb::ePathTypePythonDir: { static std::once_flag g_once_flag; static bool success = false; std::call_once(g_once_flag, []() { success = HostInfo::ComputePythonDirectory (g_fields->m_lldb_python_dir); Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); if (log) log->Printf("HostInfoBase::GetLLDBPath(ePathTypePythonDir) => '%s'", g_fields->m_lldb_python_dir.GetPath().c_str()); }); if (success) result = &g_fields->m_lldb_python_dir; } break; case lldb::ePathTypeClangDir: { static std::once_flag g_once_flag; static bool success = false; std::call_once(g_once_flag, []() { success = HostInfo::ComputeClangDirectory (g_fields->m_lldb_clang_resource_dir); Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); if (log) log->Printf("HostInfoBase::GetLLDBPath(ePathTypeClangResourceDir) => '%s'", g_fields->m_lldb_clang_resource_dir.GetPath().c_str()); }); if (success) result = &g_fields->m_lldb_clang_resource_dir; } break; case lldb::ePathTypeLLDBSystemPlugins: { static std::once_flag g_once_flag; static bool success = false; std::call_once(g_once_flag, []() { success = HostInfo::ComputeSystemPluginsDirectory (g_fields->m_lldb_system_plugin_dir); Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); if (log) log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBSystemPlugins) => '%s'", g_fields->m_lldb_system_plugin_dir.GetPath().c_str()); }); if (success) result = &g_fields->m_lldb_system_plugin_dir; } break; case lldb::ePathTypeLLDBUserPlugins: { static std::once_flag g_once_flag; static bool success = false; std::call_once(g_once_flag, []() { success = HostInfo::ComputeUserPluginsDirectory (g_fields->m_lldb_user_plugin_dir); Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); if (log) log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBUserPlugins) => '%s'", g_fields->m_lldb_user_plugin_dir.GetPath().c_str()); }); if (success) result = &g_fields->m_lldb_user_plugin_dir; } break; case lldb::ePathTypeLLDBTempSystemDir: { static std::once_flag g_once_flag; static bool success = false; std::call_once(g_once_flag, []() { success = HostInfo::ComputeProcessTempFileDirectory (g_fields->m_lldb_process_tmp_dir); Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); if (log) log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBTempSystemDir) => '%s'", g_fields->m_lldb_process_tmp_dir.GetPath().c_str()); }); if (success) result = &g_fields->m_lldb_process_tmp_dir; } break; case lldb::ePathTypeGlobalLLDBTempSystemDir: { static std::once_flag g_once_flag; static bool success = false; std::call_once(g_once_flag, []() { success = HostInfo::ComputeGlobalTempFileDirectory (g_fields->m_lldb_global_tmp_dir); Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); if (log) log->Printf("HostInfoBase::GetLLDBPath(ePathTypeGlobalLLDBTempSystemDir) => '%s'", g_fields->m_lldb_global_tmp_dir.GetPath().c_str()); }); if (success) result = &g_fields->m_lldb_global_tmp_dir; } break; } if (!result) return false; file_spec = *result; return true; }
bool Host::GetBundleDirectory (const FileSpec &file, FileSpec &bundle) { bundle.Clear(); return false; }
Error TargetList::CreateTarget ( Debugger &debugger, const FileSpec& file, const ArchSpec& specified_arch, bool get_dependent_files, PlatformSP &platform_sp, TargetSP &target_sp ) { Timer scoped_timer (__PRETTY_FUNCTION__, "TargetList::CreateTarget (file = '%s/%s', arch = '%s')", file.GetDirectory().AsCString(), file.GetFilename().AsCString(), specified_arch.GetArchitectureName()); Error error; ArchSpec arch(specified_arch); if (platform_sp) { if (arch.IsValid()) { if (!platform_sp->IsCompatibleArchitecture(arch)) platform_sp = Platform::GetPlatformForArchitecture(specified_arch, &arch); } } else if (arch.IsValid()) { platform_sp = Platform::GetPlatformForArchitecture(specified_arch, &arch); } if (!platform_sp) platform_sp = debugger.GetPlatformList().GetSelectedPlatform(); if (!arch.IsValid()) arch = specified_arch; if (file) { ModuleSP exe_module_sp; FileSpec resolved_file(file); if (platform_sp) { FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths()); error = platform_sp->ResolveExecutable (file, arch, 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%s%s\" doesn't contain architecture %s", file.GetDirectory().AsCString(), file.GetDirectory() ? "/" : "", file.GetFilename().AsCString(), arch.GetArchitectureName()); } else { error.SetErrorStringWithFormat("unsupported file type \"%s%s%s\"", file.GetDirectory().AsCString(), file.GetDirectory() ? "/" : "", file.GetFilename().AsCString()); } return error; } target_sp.reset(new Target(debugger, arch, platform_sp)); target_sp->SetExecutableModule (exe_module_sp, get_dependent_files); } } 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)); } if (target_sp) { target_sp->UpdateInstanceName(); Mutex::Locker locker(m_target_list_mutex); m_selected_target_idx = m_target_list.size(); m_target_list.push_back(target_sp); } return error; }
bool FileSystem::GetFileExists(const FileSpec &file_spec) { return file_spec.Exists(); }
Error ModuleList::GetSharedModule ( const FileSpec& in_file_spec, const ArchSpec& arch, const lldb_private::UUID *uuid_ptr, const ConstString *object_name_ptr, off_t object_offset, ModuleSP &module_sp, 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]; char uuid_cstr[64]; Error error; module_sp.reset(); if (did_create_ptr) *did_create_ptr = false; if (old_module_sp_ptr) old_module_sp_ptr->reset(); // First just try and get the file where it purports to be (path in // in_file_spec), then check and uuid. if (in_file_spec) { // 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 == false) { ModuleList matching_module_list; const size_t num_matching_modules = shared_module_list.FindModules (&in_file_spec, &arch, NULL, object_name_ptr, matching_module_list); if (num_matching_modules > 0) { for (uint32_t module_idx = 0; module_idx < num_matching_modules; ++module_idx) { module_sp = matching_module_list.GetModuleAtIndex(module_idx); if (uuid_ptr && uuid_ptr->IsValid()) { // We found the module we were looking for. if (module_sp->GetUUID() == *uuid_ptr) return error; } else { // 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! TimeValue file_spec_mod_time(in_file_spec.GetModificationTime()); if (file_spec_mod_time.IsValid()) { if (file_spec_mod_time == module_sp->GetModificationTime()) return error; } } if (old_module_sp_ptr && !old_module_sp_ptr->get()) *old_module_sp_ptr = module_sp; shared_module_list.Remove (module_sp); module_sp.reset(); } } } if (module_sp) return error; else { #if defined ENABLE_MODULE_SP_LOGGING ModuleSP logging_module_sp (new Module (in_file_spec, arch, object_name_ptr, object_offset), ModuleSharedPtrLogger, (void *)ConstString("a.out").GetCString()); module_sp = logging_module_sp; #else module_sp.reset (new Module (in_file_spec, arch, object_name_ptr, object_offset)); #endif // 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 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 (did_create_ptr) *did_create_ptr = true; shared_module_list.Append(module_sp); return error; } } } } // 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. FileSpec file_spec = Symbols::LocateExecutableObjectFile (in_file_spec ? &in_file_spec : NULL, arch.IsValid() ? &arch : NULL, uuid_ptr); // Don't look for the file if it appears to be the same one we already // checked for above... if (file_spec != in_file_spec) { if (!file_spec.Exists()) { file_spec.GetPath(path, sizeof(path)); if (file_spec.Exists()) { if (uuid_ptr && uuid_ptr->IsValid()) uuid_ptr->GetAsCString(uuid_cstr, sizeof (uuid_cstr)); else uuid_cstr[0] = '\0'; if (arch.IsValid()) { if (uuid_cstr[0]) error.SetErrorStringWithFormat("'%s' does not contain the %s architecture and UUID %s", path, arch.GetArchitectureName(), uuid_cstr); else error.SetErrorStringWithFormat("'%s' does not contain the %s architecture.", path, arch.GetArchitectureName()); } } else { error.SetErrorStringWithFormat("'%s' does not exist", path); } 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. ModuleList matching_module_list; if (shared_module_list.FindModules (&file_spec, &arch, uuid_ptr, object_name_ptr, 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 (uuid_ptr == NULL) { TimeValue file_spec_mod_time(file_spec.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.get() == NULL) { #if defined ENABLE_MODULE_SP_LOGGING ModuleSP logging_module_sp (new Module (file_spec, arch, object_name_ptr, object_offset), ModuleSharedPtrLogger, 0); module_sp = logging_module_sp; #else module_sp.reset (new Module (file_spec, arch, object_name_ptr, object_offset)); #endif // 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 (did_create_ptr) *did_create_ptr = true; shared_module_list.Append(module_sp); } else { file_spec.GetPath(path, sizeof(path)); if (file_spec) { if (arch.IsValid()) error.SetErrorStringWithFormat("unable to open %s architecture in '%s'", arch.GetArchitectureName(), path); else error.SetErrorStringWithFormat("unable to open '%s'", path); } else { if (uuid_ptr && uuid_ptr->IsValid()) uuid_ptr->GetAsCString(uuid_cstr, sizeof (uuid_cstr)); else uuid_cstr[0] = '\0'; if (uuid_cstr[0]) error.SetErrorStringWithFormat("cannot locate a module for UUID '%s'", uuid_cstr); else error.SetErrorStringWithFormat("cannot locate a module"); } } } } return error; }
static bool SkinnyMachOFileContainsArchAndUUID ( const FileSpec &file_spec, const ArchSpec *arch, const lldb_private::UUID *uuid, // the UUID we are looking for off_t file_offset, DataExtractor& data, lldb::offset_t data_offset, const uint32_t magic ) { assert(magic == MH_MAGIC || magic == MH_CIGAM || magic == MH_MAGIC_64 || magic == MH_CIGAM_64); if (magic == MH_MAGIC || magic == MH_MAGIC_64) data.SetByteOrder (lldb::endian::InlHostByteOrder()); else if (lldb::endian::InlHostByteOrder() == eByteOrderBig) data.SetByteOrder (eByteOrderLittle); else data.SetByteOrder (eByteOrderBig); uint32_t i; const uint32_t cputype = data.GetU32(&data_offset); // cpu specifier const uint32_t cpusubtype = data.GetU32(&data_offset); // machine specifier data_offset+=4; // Skip mach file type const uint32_t ncmds = data.GetU32(&data_offset); // number of load commands const uint32_t sizeofcmds = data.GetU32(&data_offset); // the size of all the load commands data_offset+=4; // Skip flags // Check the architecture if we have a valid arch pointer if (arch) { ArchSpec file_arch(eArchTypeMachO, cputype, cpusubtype); if (!file_arch.IsCompatibleMatch(*arch)) return false; } // The file exists, and if a valid arch pointer was passed in we know // if already matches, so we can return if we aren't looking for a specific // UUID if (uuid == NULL) return true; if (magic == MH_CIGAM_64 || magic == MH_MAGIC_64) data_offset += 4; // Skip reserved field for in mach_header_64 // Make sure we have enough data for all the load commands if (magic == MH_CIGAM_64 || magic == MH_MAGIC_64) { if (data.GetByteSize() < sizeof(struct mach_header_64) + sizeofcmds) { DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset, sizeof(struct mach_header_64) + sizeofcmds)); data.SetData (data_buffer_sp); } } else { if (data.GetByteSize() < sizeof(struct mach_header) + sizeofcmds) { DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset, sizeof(struct mach_header) + sizeofcmds)); data.SetData (data_buffer_sp); } } for (i=0; i<ncmds; i++) { const lldb::offset_t cmd_offset = data_offset; // Save this data_offset in case parsing of the segment goes awry! uint32_t cmd = data.GetU32(&data_offset); uint32_t cmd_size = data.GetU32(&data_offset); if (cmd == LC_UUID) { lldb_private::UUID file_uuid (data.GetData(&data_offset, 16), 16); if (file_uuid == *uuid) return true; return false; } data_offset = cmd_offset + cmd_size; } return false; }
lldb::user_id_t FileSystem::GetFileSize(const FileSpec &file_spec) { return file_spec.GetByteSize(); }
Error TargetList::CreateTarget ( Debugger &debugger, const FileSpec& file, const ArchSpec& arch, const UUID *uuid_ptr, bool get_dependent_files, TargetSP &target_sp ) { Timer scoped_timer (__PRETTY_FUNCTION__, "TargetList::CreateTarget (file = '%s/%s', arch = '%s', uuid = %p)", file.GetDirectory().AsCString(), file.GetFilename().AsCString(), arch.AsCString(), uuid_ptr); ModuleSP exe_module_sp; FileSpec resolved_file(file); if (!Host::ResolveExecutableInBundle (&resolved_file)) resolved_file = file; Error error = ModuleList::GetSharedModule(resolved_file, arch, uuid_ptr, NULL, 0, exe_module_sp, NULL, NULL); if (exe_module_sp) { target_sp.reset(new Target(debugger)); target_sp->SetExecutableModule (exe_module_sp, get_dependent_files); if (target_sp.get()) { Mutex::Locker locker(m_target_list_mutex); m_current_target_idx = m_target_list.size(); m_target_list.push_back(target_sp); } // target_sp.reset(new Target); // // Let the target resolve any funky bundle paths before we try and get // // the object file... // target_sp->SetExecutableModule (exe_module_sp, get_dependent_files); // if (exe_module_sp->GetObjectFile() == NULL) // { // error.SetErrorStringWithFormat("%s%s%s: doesn't contain architecture %s", // file.GetDirectory().AsCString(), // file.GetDirectory() ? "/" : "", // file.GetFilename().AsCString(), // arch.AsCString()); // } // else // { // if (target_sp.get()) // { // error.Clear(); // Mutex::Locker locker(m_target_list_mutex); // m_current_target_idx = m_target_list.size(); // m_target_list.push_back(target_sp); // } // } } else { target_sp.reset(); } return error; }
bool StringList::ReadFileLines (FileSpec &input_file) { return input_file.ReadFileLines (m_strings); }
Error PlatformRemoteiOS::ResolveExecutable (const FileSpec &exe_file, const ArchSpec &exe_arch, 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 FileSpec resolved_exe_file (exe_file); // 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_exe_file); if (resolved_exe_file.Exists()) { if (exe_arch.IsValid()) { ModuleSpec module_spec (resolved_exe_file, exe_arch); error = ModuleList::GetSharedModule (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, platform_arch); ++idx) { ModuleSpec module_spec (resolved_exe_file, platform_arch); error = ModuleList::GetSharedModule (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) { error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s", exe_file.GetPath().c_str(), GetPluginName().GetCString(), arch_names.GetString().c_str()); } } else { error.SetErrorStringWithFormat ("'%s' does not exist", exe_file.GetPath().c_str()); } return error; }
Error PlatformWindows::ResolveExecutable (const FileSpec &exe_file, const ArchSpec &exe_arch, 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]; FileSpec resolved_exe_file (exe_file); if (IsHost()) { // if we cant resolve the executable loation based on the current path variables if (!resolved_exe_file.Exists()) { exe_file.GetPath(exe_path, sizeof(exe_path)); resolved_exe_file.SetFile(exe_path, true); } if (!resolved_exe_file.Exists()) resolved_exe_file.ResolveExecutableLocation (); if (resolved_exe_file.Exists()) error.Clear(); else { exe_file.GetPath(exe_path, sizeof(exe_path)); error.SetErrorStringWithFormat("unable to find executable for '%s'", exe_path); } } else { if (m_remote_platform_sp) { error = m_remote_platform_sp->ResolveExecutable (exe_file, exe_arch, exe_module_sp, NULL); } else { // We may connect to a process and use the provided executable (Don't use local $PATH). if (resolved_exe_file.Exists()) error.Clear(); else error.SetErrorStringWithFormat("the platform is not currently connected, and '%s' doesn't exist in the system root.", exe_path); } } if (error.Success()) { ModuleSpec module_spec (resolved_exe_file, exe_arch); if (exe_arch.IsValid()) { error = ModuleList::GetSharedModule (module_spec, exe_module_sp, NULL, NULL, NULL); if (!exe_module_sp && exe_module_sp->GetObjectFile() == NULL) { exe_module_sp.reset(); error.SetErrorStringWithFormat ("'%s' doesn't contain the architecture %s", exe_file.GetPath().c_str(), exe_arch.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, module_spec.GetArchitecture()); ++idx) { error = ModuleList::GetSharedModule (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 (module_spec.GetArchitecture().GetArchitectureName()); } if (error.Fail() || !exe_module_sp) { error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s", exe_file.GetPath().c_str(), GetPluginName().GetCString(), arch_names.GetString().c_str()); } } } return error; }
bool Host::GetLLDBPath (PathType path_type, FileSpec &file_spec) { // To get paths related to LLDB we get the path to the executable that // contains this function. On MacOSX this will be "LLDB.framework/.../LLDB", // on linux this is assumed to be the "lldb" main executable. If LLDB on // linux is actually in a shared library (lldb.so??) then this function will // need to be modified to "do the right thing". switch (path_type) { case ePathTypeLLDBShlibDir: { static ConstString g_lldb_so_dir; if (!g_lldb_so_dir) { FileSpec lldb_file_spec (Host::GetModuleFileSpecForHostAddress ((void *)Host::GetLLDBPath)); g_lldb_so_dir = lldb_file_spec.GetDirectory(); } file_spec.GetDirectory() = g_lldb_so_dir; return file_spec.GetDirectory(); } break; case ePathTypeSupportExecutableDir: { static ConstString g_lldb_support_exe_dir; if (!g_lldb_support_exe_dir) { FileSpec lldb_file_spec; if (GetLLDBPath (ePathTypeLLDBShlibDir, lldb_file_spec)) { char raw_path[PATH_MAX]; char resolved_path[PATH_MAX]; lldb_file_spec.GetPath(raw_path, sizeof(raw_path)); #if defined (__APPLE__) char *framework_pos = ::strstr (raw_path, "LLDB.framework"); if (framework_pos) { framework_pos += strlen("LLDB.framework"); #if !defined (__arm__) ::strncpy (framework_pos, "/Resources", PATH_MAX - (framework_pos - raw_path)); #endif } #endif FileSpec::Resolve (raw_path, resolved_path, sizeof(resolved_path)); g_lldb_support_exe_dir.SetCString(resolved_path); } } file_spec.GetDirectory() = g_lldb_support_exe_dir; return file_spec.GetDirectory(); } break; case ePathTypeHeaderDir: { static ConstString g_lldb_headers_dir; if (!g_lldb_headers_dir) { #if defined (__APPLE__) FileSpec lldb_file_spec; if (GetLLDBPath (ePathTypeLLDBShlibDir, lldb_file_spec)) { char raw_path[PATH_MAX]; char resolved_path[PATH_MAX]; lldb_file_spec.GetPath(raw_path, sizeof(raw_path)); char *framework_pos = ::strstr (raw_path, "LLDB.framework"); if (framework_pos) { framework_pos += strlen("LLDB.framework"); ::strncpy (framework_pos, "/Headers", PATH_MAX - (framework_pos - raw_path)); } FileSpec::Resolve (raw_path, resolved_path, sizeof(resolved_path)); g_lldb_headers_dir.SetCString(resolved_path); } #else // TODO: Anyone know how we can determine this for linux? Other systems?? g_lldb_headers_dir.SetCString ("/opt/local/include/lldb"); #endif } file_spec.GetDirectory() = g_lldb_headers_dir; return file_spec.GetDirectory(); } break; case ePathTypePythonDir: { // TODO: Anyone know how we can determine this for linux? Other systems? // For linux and FreeBSD we are currently assuming the // location of the lldb binary that contains this function is // the directory that will contain a python directory which // has our lldb module. This is how files get placed when // compiling with Makefiles. static ConstString g_lldb_python_dir; if (!g_lldb_python_dir) { FileSpec lldb_file_spec; if (GetLLDBPath (ePathTypeLLDBShlibDir, lldb_file_spec)) { char raw_path[PATH_MAX]; char resolved_path[PATH_MAX]; lldb_file_spec.GetPath(raw_path, sizeof(raw_path)); #if defined (__APPLE__) char *framework_pos = ::strstr (raw_path, "LLDB.framework"); if (framework_pos) { framework_pos += strlen("LLDB.framework"); ::strncpy (framework_pos, "/Resources/Python", PATH_MAX - (framework_pos - raw_path)); } #else // We may get our string truncated. Should we protect // this with an assert? ::strncat(raw_path, "/python", sizeof(raw_path) - strlen(raw_path) - 1); #endif FileSpec::Resolve (raw_path, resolved_path, sizeof(resolved_path)); g_lldb_python_dir.SetCString(resolved_path); } } file_spec.GetDirectory() = g_lldb_python_dir; return file_spec.GetDirectory(); } break; case ePathTypeLLDBSystemPlugins: // System plug-ins directory { #if defined (__APPLE__) static ConstString g_lldb_system_plugin_dir; static bool g_lldb_system_plugin_dir_located = false; if (!g_lldb_system_plugin_dir_located) { g_lldb_system_plugin_dir_located = true; FileSpec lldb_file_spec; if (GetLLDBPath (ePathTypeLLDBShlibDir, lldb_file_spec)) { char raw_path[PATH_MAX]; char resolved_path[PATH_MAX]; lldb_file_spec.GetPath(raw_path, sizeof(raw_path)); char *framework_pos = ::strstr (raw_path, "LLDB.framework"); if (framework_pos) { framework_pos += strlen("LLDB.framework"); ::strncpy (framework_pos, "/Resources/PlugIns", PATH_MAX - (framework_pos - raw_path)); FileSpec::Resolve (raw_path, resolved_path, sizeof(resolved_path)); g_lldb_system_plugin_dir.SetCString(resolved_path); } return false; } } if (g_lldb_system_plugin_dir) { file_spec.GetDirectory() = g_lldb_system_plugin_dir; return true; } #endif // TODO: where would system LLDB plug-ins be located on linux? Other systems? return false; } break; case ePathTypeLLDBUserPlugins: // User plug-ins directory { #if defined (__APPLE__) static ConstString g_lldb_user_plugin_dir; if (!g_lldb_user_plugin_dir) { char user_plugin_path[PATH_MAX]; if (FileSpec::Resolve ("~/Library/Application Support/LLDB/PlugIns", user_plugin_path, sizeof(user_plugin_path))) { g_lldb_user_plugin_dir.SetCString(user_plugin_path); } } file_spec.GetDirectory() = g_lldb_user_plugin_dir; return file_spec.GetDirectory(); #endif // TODO: where would user LLDB plug-ins be located on linux? Other systems? return false; } default: assert (!"Unhandled PathType"); break; } return false; }
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.IsRelativeToCurrentWorkingDirectory() && 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; }
uint32_t CompileUnit::ResolveSymbolContext ( const FileSpec& file_spec, uint32_t line, bool check_inlines, bool exact, uint32_t resolve_scope, SymbolContextList &sc_list ) { // First find all of the file indexes that match our "file_spec". If // "file_spec" has an empty directory, then only compare the basenames // when finding file indexes std::vector<uint32_t> file_indexes; const bool full_match = (bool)file_spec.GetDirectory(); const bool remove_backup_dots = true; bool file_spec_matches_cu_file_spec = FileSpec::Equal(file_spec, *this, full_match, remove_backup_dots); // If we are not looking for inlined functions and our file spec doesn't // match then we are done... if (file_spec_matches_cu_file_spec == false && check_inlines == false) return 0; uint32_t file_idx = GetSupportFiles().FindFileIndex (1, file_spec, true, remove_backup_dots); while (file_idx != UINT32_MAX) { file_indexes.push_back (file_idx); file_idx = GetSupportFiles().FindFileIndex (file_idx + 1, file_spec, true, remove_backup_dots); } const size_t num_file_indexes = file_indexes.size(); if (num_file_indexes == 0) return 0; const uint32_t prev_size = sc_list.GetSize(); SymbolContext sc(GetModule()); sc.comp_unit = this; if (line != 0) { LineTable *line_table = sc.comp_unit->GetLineTable(); if (line_table != nullptr) { uint32_t found_line; uint32_t line_idx; if (num_file_indexes == 1) { // We only have a single support file that matches, so use // the line table function that searches for a line entries // that match a single support file index LineEntry line_entry; line_idx = line_table->FindLineEntryIndexByFileIndex (0, file_indexes.front(), line, exact, &line_entry); // If "exact == true", then "found_line" will be the same // as "line". If "exact == false", the "found_line" will be the // closest line entry with a line number greater than "line" and // we will use this for our subsequent line exact matches below. found_line = line_entry.line; while (line_idx != UINT32_MAX) { // If they only asked for the line entry, then we're done, we can just copy that over. // But if they wanted more than just the line number, fill it in. if (resolve_scope == eSymbolContextLineEntry) { sc.line_entry = line_entry; } else { line_entry.range.GetBaseAddress().CalculateSymbolContext(&sc, resolve_scope); } sc_list.Append(sc); line_idx = line_table->FindLineEntryIndexByFileIndex (line_idx + 1, file_indexes.front(), found_line, true, &line_entry); } } else { // We found multiple support files that match "file_spec" so use // the line table function that searches for a line entries // that match a multiple support file indexes. LineEntry line_entry; line_idx = line_table->FindLineEntryIndexByFileIndex (0, file_indexes, line, exact, &line_entry); // If "exact == true", then "found_line" will be the same // as "line". If "exact == false", the "found_line" will be the // closest line entry with a line number greater than "line" and // we will use this for our subsequent line exact matches below. found_line = line_entry.line; while (line_idx != UINT32_MAX) { if (resolve_scope == eSymbolContextLineEntry) { sc.line_entry = line_entry; } else { line_entry.range.GetBaseAddress().CalculateSymbolContext(&sc, resolve_scope); } sc_list.Append(sc); line_idx = line_table->FindLineEntryIndexByFileIndex (line_idx + 1, file_indexes, found_line, true, &line_entry); } } } } else if (file_spec_matches_cu_file_spec && !check_inlines) { // only append the context if we aren't looking for inline call sites // by file and line and if the file spec matches that of the compile unit sc_list.Append(sc); } return sc_list.GetSize() - prev_size; }
Error PlatformRemoteiOS::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; }
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(); }
Error TargetList::CreateTarget (Debugger &debugger, const FileSpec& file, const char *triple_cstr, bool get_dependent_files, const OptionGroupPlatform *platform_options, TargetSP &target_sp) { Error error; PlatformSP platform_sp; // This is purposely left empty unless it is specified by triple_cstr. // If not initialized via triple_cstr, then the currently selected platform // will set the architecture correctly. const ArchSpec arch(triple_cstr); if (triple_cstr && triple_cstr[0]) { if (!arch.IsValid()) { error.SetErrorStringWithFormat("invalid triple '%s'", triple_cstr); return error; } } ArchSpec platform_arch(arch); CommandInterpreter &interpreter = debugger.GetCommandInterpreter(); if (platform_options) { if (platform_options->PlatformWasSpecified ()) { const bool select_platform = true; platform_sp = platform_options->CreatePlatformWithOptions (interpreter, arch, select_platform, error, platform_arch); if (!platform_sp) return error; } } if (!platform_sp) { // Get the current platform and make sure it is compatible with the // current architecture if we have a valid architecture. platform_sp = debugger.GetPlatformList().GetSelectedPlatform (); if (arch.IsValid() && !platform_sp->IsCompatibleArchitecture(arch, &platform_arch)) { platform_sp = Platform::GetPlatformForArchitecture(arch, &platform_arch); } } if (!platform_arch.IsValid()) platform_arch = arch; error = TargetList::CreateTarget (debugger, file, platform_arch, get_dependent_files, platform_sp, target_sp); if (target_sp) { if (file.GetDirectory()) { FileSpec file_dir; file_dir.GetDirectory() = file.GetDirectory(); target_sp->GetExecutableSearchPaths ().Append (file_dir); } } return error; }
bool SearchFilterByModule::ModulePasses(const FileSpec &spec) { // Do a full match only if "spec" has a directory const bool full_match = (bool)spec.GetDirectory(); return FileSpec::Equal(spec, m_module_spec, full_match); }
Error PlatformLinux::ResolveExecutable (const FileSpec &exe_file, const ArchSpec &exe_arch, 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]; FileSpec resolved_exe_file (exe_file); if (IsHost()) { // If we have "ls" as the exe_file, resolve the executable location based on // the current path variables if (!resolved_exe_file.Exists()) { exe_file.GetPath(exe_path, sizeof(exe_path)); resolved_exe_file.SetFile(exe_path, true); } if (!resolved_exe_file.Exists()) resolved_exe_file.ResolveExecutableLocation (); if (resolved_exe_file.Exists()) error.Clear(); else { exe_file.GetPath(exe_path, sizeof(exe_path)); error.SetErrorStringWithFormat("unable to find executable for '%s'", exe_path); } } else { if (m_remote_platform_sp) { error = m_remote_platform_sp->ResolveExecutable (exe_file, exe_arch, exe_module_sp, NULL); } else { // We may connect to a process and use the provided executable (Don't use local $PATH). if (resolved_exe_file.Exists()) error.Clear(); else error.SetErrorStringWithFormat("the platform is not currently connected, and '%s' doesn't exist in the system root.", exe_path); } } if (error.Success()) { ModuleSpec module_spec (resolved_exe_file, exe_arch); if (exe_arch.IsValid()) { error = ModuleList::GetSharedModule (module_spec, exe_module_sp, NULL, NULL, NULL); if (error.Fail()) { // If we failed, it may be because the vendor and os aren't known. If that is the // case, try setting them to the host architecture and give it another try. llvm::Triple &module_triple = module_spec.GetArchitecture().GetTriple(); bool is_vendor_specified = (module_triple.getVendor() != llvm::Triple::UnknownVendor); bool is_os_specified = (module_triple.getOS() != llvm::Triple::UnknownOS); if (!is_vendor_specified || !is_os_specified) { const llvm::Triple &host_triple = Host::GetArchitecture (Host::eSystemDefaultArchitecture).GetTriple(); if (!is_vendor_specified) module_triple.setVendorName (host_triple.getVendorName()); if (!is_os_specified) module_triple.setOSName (host_triple.getOSName()); error = ModuleList::GetSharedModule (module_spec, exe_module_sp, NULL, NULL, NULL); } } // TODO find out why exe_module_sp might be NULL if (!exe_module_sp || exe_module_sp->GetObjectFile() == NULL) { exe_module_sp.reset(); error.SetErrorStringWithFormat ("'%s' doesn't contain the architecture %s", exe_file.GetPath().c_str(), exe_arch.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, module_spec.GetArchitecture()); ++idx) { error = ModuleList::GetSharedModule (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 (module_spec.GetArchitecture().GetArchitectureName()); } if (error.Fail() || !exe_module_sp) { error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s", exe_file.GetPath().c_str(), GetPluginName().GetCString(), arch_names.GetString().c_str()); } } } return error; }
bool HostInfoPosix::ComputeHeaderDirectory(FileSpec &file_spec) { FileSpec temp_file("/opt/local/include/lldb", false); file_spec.GetDirectory().SetCString(temp_file.GetPath().c_str()); return true; }
Error GDBRemoteCommunication::StartDebugserverProcess (const char *hostname, uint16_t in_port, ProcessLaunchInfo &launch_info, uint16_t &out_port) { Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS)); if (log) log->Printf ("GDBRemoteCommunication::%s(hostname=%s, in_port=%" PRIu16 ", out_port=%" PRIu16, __FUNCTION__, hostname ? hostname : "<empty>", in_port, out_port); out_port = in_port; Error error; // If we locate debugserver, keep that located version around static FileSpec g_debugserver_file_spec; char debugserver_path[PATH_MAX]; FileSpec &debugserver_file_spec = launch_info.GetExecutableFile(); // Always check to see if we have an environment override for the path // to the debugserver to use and use it if we do. const char *env_debugserver_path = getenv("LLDB_DEBUGSERVER_PATH"); if (env_debugserver_path) { debugserver_file_spec.SetFile (env_debugserver_path, false); if (log) log->Printf ("GDBRemoteCommunication::%s() gdb-remote stub exe path set from environment variable: %s", __FUNCTION__, env_debugserver_path); } else debugserver_file_spec = g_debugserver_file_spec; bool debugserver_exists = debugserver_file_spec.Exists(); if (!debugserver_exists) { // The debugserver binary is in the LLDB.framework/Resources // directory. if (HostInfo::GetLLDBPath(ePathTypeSupportExecutableDir, debugserver_file_spec)) { debugserver_file_spec.AppendPathComponent (DEBUGSERVER_BASENAME); debugserver_exists = debugserver_file_spec.Exists(); if (debugserver_exists) { if (log) log->Printf ("GDBRemoteCommunication::%s() found gdb-remote stub exe '%s'", __FUNCTION__, debugserver_file_spec.GetPath ().c_str ()); g_debugserver_file_spec = debugserver_file_spec; } else { if (log) log->Printf ("GDBRemoteCommunication::%s() could not find gdb-remote stub exe '%s'", __FUNCTION__, debugserver_file_spec.GetPath ().c_str ()); g_debugserver_file_spec.Clear(); debugserver_file_spec.Clear(); } } } if (debugserver_exists) { debugserver_file_spec.GetPath (debugserver_path, sizeof(debugserver_path)); Args &debugserver_args = launch_info.GetArguments(); debugserver_args.Clear(); char arg_cstr[PATH_MAX]; // Start args with "debugserver /file/path -r --" debugserver_args.AppendArgument(debugserver_path); #if !defined(__APPLE__) // First argument to lldb-server must be mode in which to run. debugserver_args.AppendArgument("gdbserver"); #endif // If a host and port is supplied then use it char host_and_port[128]; if (hostname) { snprintf (host_and_port, sizeof(host_and_port), "%s:%u", hostname, in_port); debugserver_args.AppendArgument(host_and_port); } else { host_and_port[0] = '\0'; } // use native registers, not the GDB registers debugserver_args.AppendArgument("--native-regs"); if (launch_info.GetLaunchInSeparateProcessGroup()) { debugserver_args.AppendArgument("--setsid"); } llvm::SmallString<PATH_MAX> named_pipe_path; Pipe port_pipe; bool listen = false; if (host_and_port[0]) { // Create a temporary file to get the stdout/stderr and redirect the // output of the command into this file. We will later read this file // if all goes well and fill the data into "command_output_ptr" if (in_port == 0) { // Binding to port zero, we need to figure out what port it ends up // using using a named pipe... error = port_pipe.CreateWithUniqueName("debugserver-named-pipe", false, named_pipe_path); if (error.Success()) { debugserver_args.AppendArgument("--named-pipe"); debugserver_args.AppendArgument(named_pipe_path.c_str()); } else { if (log) log->Printf("GDBRemoteCommunication::%s() " "named pipe creation failed: %s", __FUNCTION__, error.AsCString()); // let's try an unnamed pipe error = port_pipe.CreateNew(true); if (error.Fail()) { if (log) log->Printf("GDBRemoteCommunication::%s() " "unnamed pipe creation failed: %s", __FUNCTION__, error.AsCString()); return error; } int write_fd = port_pipe.GetWriteFileDescriptor(); debugserver_args.AppendArgument("--pipe"); debugserver_args.AppendArgument(std::to_string(write_fd).c_str()); launch_info.AppendCloseFileAction(port_pipe.GetReadFileDescriptor()); } } else { listen = true; } } else { // No host and port given, so lets listen on our end and make the debugserver // connect to us.. error = StartListenThread ("127.0.0.1", 0); if (error.Fail()) return error; ConnectionFileDescriptor *connection = (ConnectionFileDescriptor *)GetConnection (); // Wait for 10 seconds to resolve the bound port out_port = connection->GetListeningPort(10); if (out_port > 0) { char port_cstr[32]; snprintf(port_cstr, sizeof(port_cstr), "127.0.0.1:%i", out_port); // Send the host and port down that debugserver and specify an option // so that it connects back to the port we are listening to in this process debugserver_args.AppendArgument("--reverse-connect"); debugserver_args.AppendArgument(port_cstr); } else { error.SetErrorString ("failed to bind to port 0 on 127.0.0.1"); return error; } } const char *env_debugserver_log_file = getenv("LLDB_DEBUGSERVER_LOG_FILE"); if (env_debugserver_log_file) { ::snprintf (arg_cstr, sizeof(arg_cstr), "--log-file=%s", env_debugserver_log_file); debugserver_args.AppendArgument(arg_cstr); } const char *env_debugserver_log_flags = getenv("LLDB_DEBUGSERVER_LOG_FLAGS"); if (env_debugserver_log_flags) { ::snprintf (arg_cstr, sizeof(arg_cstr), "--log-flags=%s", env_debugserver_log_flags); debugserver_args.AppendArgument(arg_cstr); } // Add additional args, starting with LLDB_DEBUGSERVER_EXTRA_ARG_1 until an env var doesn't come back. uint32_t env_var_index = 1; bool has_env_var; do { char env_var_name[64]; snprintf (env_var_name, sizeof (env_var_name), "LLDB_DEBUGSERVER_EXTRA_ARG_%" PRIu32, env_var_index++); const char *extra_arg = getenv(env_var_name); has_env_var = extra_arg != nullptr; if (has_env_var) { debugserver_args.AppendArgument (extra_arg); if (log) log->Printf ("GDBRemoteCommunication::%s adding env var %s contents to stub command line (%s)", __FUNCTION__, env_var_name, extra_arg); } } while (has_env_var); // Close STDIN, STDOUT and STDERR. launch_info.AppendCloseFileAction (STDIN_FILENO); launch_info.AppendCloseFileAction (STDOUT_FILENO); launch_info.AppendCloseFileAction (STDERR_FILENO); // Redirect STDIN, STDOUT and STDERR to "/dev/null". launch_info.AppendSuppressFileAction (STDIN_FILENO, true, false); launch_info.AppendSuppressFileAction (STDOUT_FILENO, false, true); launch_info.AppendSuppressFileAction (STDERR_FILENO, false, true); error = Host::LaunchProcess(launch_info); if (error.Success() && launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) { if (named_pipe_path.size() > 0) { error = port_pipe.OpenAsReader(named_pipe_path, false); if (error.Fail()) if (log) log->Printf("GDBRemoteCommunication::%s() " "failed to open named pipe %s for reading: %s", __FUNCTION__, named_pipe_path.c_str(), error.AsCString()); } if (port_pipe.CanWrite()) port_pipe.CloseWriteFileDescriptor(); if (port_pipe.CanRead()) { char port_cstr[256]; port_cstr[0] = '\0'; size_t num_bytes = sizeof(port_cstr); // Read port from pipe with 10 second timeout. error = port_pipe.ReadWithTimeout(port_cstr, num_bytes, std::chrono::seconds{10}, num_bytes); if (error.Success()) { assert(num_bytes > 0 && port_cstr[num_bytes-1] == '\0'); out_port = StringConvert::ToUInt32(port_cstr, 0); if (log) log->Printf("GDBRemoteCommunication::%s() " "debugserver listens %u port", __FUNCTION__, out_port); } else { if (log) log->Printf("GDBRemoteCommunication::%s() " "failed to read a port value from pipe %s: %s", __FUNCTION__, named_pipe_path.c_str(), error.AsCString()); } port_pipe.Close(); } if (named_pipe_path.size() > 0) { const auto err = port_pipe.Delete(named_pipe_path); if (err.Fail()) { if (log) log->Printf ("GDBRemoteCommunication::%s failed to delete pipe %s: %s", __FUNCTION__, named_pipe_path.c_str(), err.AsCString()); } } // Make sure we actually connect with the debugserver... JoinListenThread(); } } else { error.SetErrorStringWithFormat ("unable to locate " DEBUGSERVER_BASENAME ); } return error; }
GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_qModuleInfo (StringExtractorGDBRemote &packet) { packet.SetFilePos(::strlen ("qModuleInfo:")); std::string module_path; packet.GetHexByteStringTerminatedBy(module_path, ';'); if (module_path.empty()) return SendErrorResponse (1); if (packet.GetChar() != ';') return SendErrorResponse (2); std::string triple; packet.GetHexByteString(triple); ArchSpec arch(triple.c_str()); const FileSpec req_module_path_spec(module_path.c_str(), true); const FileSpec module_path_spec = FindModuleFile(req_module_path_spec.GetPath(), arch); const ModuleSpec module_spec(module_path_spec, arch); ModuleSpecList module_specs; if (!ObjectFile::GetModuleSpecifications(module_path_spec, 0, 0, module_specs)) return SendErrorResponse (3); ModuleSpec matched_module_spec; if (!module_specs.FindMatchingModuleSpec(module_spec, matched_module_spec)) return SendErrorResponse (4); const auto file_offset = matched_module_spec.GetObjectOffset(); const auto file_size = matched_module_spec.GetObjectSize(); const auto uuid_str = matched_module_spec.GetUUID().GetAsString(""); StreamGDBRemote response; if (uuid_str.empty()) { std::string md5_hash; if (!FileSystem::CalculateMD5AsString(matched_module_spec.GetFileSpec(), file_offset, file_size, md5_hash)) return SendErrorResponse (5); response.PutCString ("md5:"); response.PutCStringAsRawHex8(md5_hash.c_str()); } else{ response.PutCString ("uuid:"); response.PutCStringAsRawHex8(uuid_str.c_str()); } response.PutChar(';'); const auto &module_arch = matched_module_spec.GetArchitecture(); response.PutCString("triple:"); response.PutCStringAsRawHex8( module_arch.GetTriple().getTriple().c_str()); response.PutChar(';'); response.PutCString("file_path:"); response.PutCStringAsRawHex8(module_path_spec.GetCString()); response.PutChar(';'); response.PutCString("file_offset:"); response.PutHex64(file_offset); response.PutChar(';'); response.PutCString("file_size:"); response.PutHex64(file_size); response.PutChar(';'); return SendPacketNoLock(response.GetData(), response.GetSize()); }