1 //===-- SaveCoreOptions.cpp -------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "lldb/Symbol/SaveCoreOptions.h" 10 #include "lldb/Core/PluginManager.h" 11 #include "lldb/Target/Process.h" 12 #include "lldb/Target/Thread.h" 13 14 using namespace lldb; 15 using namespace lldb_private; 16 17 Status SaveCoreOptions::SetPluginName(const char *name) { 18 Status error; 19 if (!name || !name[0]) { 20 m_plugin_name = std::nullopt; 21 return error; 22 } 23 24 if (!PluginManager::IsRegisteredObjectFilePluginName(name)) { 25 return Status::FromErrorStringWithFormat( 26 "plugin name '%s' is not a valid ObjectFile plugin name", name); 27 return error; 28 } 29 30 m_plugin_name = name; 31 return error; 32 } 33 34 void SaveCoreOptions::SetStyle(lldb::SaveCoreStyle style) { m_style = style; } 35 36 void SaveCoreOptions::SetOutputFile(FileSpec file) { m_file = file; } 37 38 std::optional<std::string> SaveCoreOptions::GetPluginName() const { 39 return m_plugin_name; 40 } 41 42 lldb::SaveCoreStyle SaveCoreOptions::GetStyle() const { 43 return m_style.value_or(lldb::eSaveCoreUnspecified); 44 } 45 46 const std::optional<lldb_private::FileSpec> 47 SaveCoreOptions::GetOutputFile() const { 48 return m_file; 49 } 50 51 Status SaveCoreOptions::SetProcess(lldb::ProcessSP process_sp) { 52 Status error; 53 if (!process_sp) { 54 ClearProcessSpecificData(); 55 m_process_sp.reset(); 56 return error; 57 } 58 59 if (!process_sp->IsValid()) { 60 error = Status::FromErrorString("Cannot assign an invalid process."); 61 return error; 62 } 63 64 // Don't clear any process specific data if the process is the same. 65 if (m_process_sp == process_sp) 66 return error; 67 68 ClearProcessSpecificData(); 69 m_process_sp = process_sp; 70 return error; 71 } 72 73 Status SaveCoreOptions::AddThread(lldb::ThreadSP thread_sp) { 74 Status error; 75 if (!thread_sp) { 76 error = Status::FromErrorString("invalid thread"); 77 return error; 78 } 79 80 if (m_process_sp) { 81 if (m_process_sp != thread_sp->GetProcess()) { 82 error = Status::FromErrorString( 83 "Cannot add a thread from a different process."); 84 return error; 85 } 86 } else { 87 m_process_sp = thread_sp->GetProcess(); 88 } 89 90 m_threads_to_save.insert(thread_sp->GetID()); 91 return error; 92 } 93 94 bool SaveCoreOptions::RemoveThread(lldb::ThreadSP thread_sp) { 95 return thread_sp && m_threads_to_save.erase(thread_sp->GetID()) > 0; 96 } 97 98 bool SaveCoreOptions::ShouldThreadBeSaved(lldb::tid_t tid) const { 99 // If the user specified no threads to save, then we save all threads. 100 if (m_threads_to_save.empty()) 101 return true; 102 return m_threads_to_save.count(tid) > 0; 103 } 104 105 bool SaveCoreOptions::HasSpecifiedThreads() const { 106 return !m_threads_to_save.empty(); 107 } 108 109 void SaveCoreOptions::AddMemoryRegionToSave( 110 const lldb_private::MemoryRegionInfo ®ion) { 111 m_regions_to_save.Insert(region.GetRange(), /*combine=*/true); 112 } 113 114 const MemoryRanges &SaveCoreOptions::GetCoreFileMemoryRanges() const { 115 return m_regions_to_save; 116 } 117 Status 118 SaveCoreOptions::EnsureValidConfiguration(lldb::ProcessSP process_sp) const { 119 Status error; 120 std::string error_str; 121 if (!m_threads_to_save.empty() && GetStyle() == lldb::eSaveCoreFull) 122 error_str += "Cannot save a full core with a subset of threads\n"; 123 124 if (m_process_sp && m_process_sp != process_sp) 125 error_str += "Cannot save core for process using supplied core options. " 126 "Options were constructed targeting a different process. \n"; 127 128 if (!error_str.empty()) 129 error = Status(error_str); 130 131 return error; 132 } 133 134 lldb_private::ThreadCollection::collection 135 SaveCoreOptions::GetThreadsToSave() const { 136 lldb_private::ThreadCollection::collection thread_collection; 137 // In cases where no process is set, such as when no threads are specified. 138 if (!m_process_sp) 139 return thread_collection; 140 141 ThreadList &thread_list = m_process_sp->GetThreadList(); 142 for (const auto &tid : m_threads_to_save) 143 thread_collection.push_back(thread_list.FindThreadByID(tid)); 144 145 return thread_collection; 146 } 147 148 void SaveCoreOptions::ClearProcessSpecificData() { 149 // Deliberately not following the formatter style here to indicate that 150 // this method will be expanded in the future. 151 m_threads_to_save.clear(); 152 } 153 154 void SaveCoreOptions::Clear() { 155 m_file = std::nullopt; 156 m_plugin_name = std::nullopt; 157 m_style = std::nullopt; 158 m_threads_to_save.clear(); 159 m_process_sp.reset(); 160 m_regions_to_save.Clear(); 161 } 162