1 //===-- ProcessFreeBSD.cpp ----------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 // C Includes 11 #include <errno.h> 12 13 // C++ Includes 14 #include <mutex> 15 16 // Other libraries and framework includes 17 #include "lldb/Core/PluginManager.h" 18 #include "lldb/Core/State.h" 19 #include "lldb/Host/Host.h" 20 #include "lldb/Symbol/ObjectFile.h" 21 #include "lldb/Target/DynamicLoader.h" 22 #include "lldb/Target/Target.h" 23 24 #include "ProcessFreeBSD.h" 25 #include "ProcessPOSIXLog.h" 26 #include "Plugins/Process/Utility/InferiorCallPOSIX.h" 27 #include "Plugins/Process/Utility/FreeBSDSignals.h" 28 #include "ProcessMonitor.h" 29 #include "FreeBSDThread.h" 30 31 using namespace lldb; 32 using namespace lldb_private; 33 34 namespace 35 { 36 UnixSignalsSP& 37 GetFreeBSDSignals () 38 { 39 static UnixSignalsSP s_freebsd_signals_sp (new FreeBSDSignals ()); 40 return s_freebsd_signals_sp; 41 } 42 } 43 44 //------------------------------------------------------------------------------ 45 // Static functions. 46 47 lldb::ProcessSP 48 ProcessFreeBSD::CreateInstance(Target& target, 49 Listener &listener, 50 const FileSpec *crash_file_path) 51 { 52 lldb::ProcessSP process_sp; 53 if (crash_file_path == NULL) 54 process_sp.reset(new ProcessFreeBSD (target, listener)); 55 return process_sp; 56 } 57 58 void 59 ProcessFreeBSD::Initialize() 60 { 61 static std::once_flag g_once_flag; 62 63 std::call_once(g_once_flag, []() { 64 PluginManager::RegisterPlugin(GetPluginNameStatic(), 65 GetPluginDescriptionStatic(), 66 CreateInstance); 67 ProcessPOSIXLog::Initialize(GetPluginNameStatic()); 68 }); 69 } 70 71 lldb_private::ConstString 72 ProcessFreeBSD::GetPluginNameStatic() 73 { 74 static ConstString g_name("freebsd"); 75 return g_name; 76 } 77 78 const char * 79 ProcessFreeBSD::GetPluginDescriptionStatic() 80 { 81 return "Process plugin for FreeBSD"; 82 } 83 84 //------------------------------------------------------------------------------ 85 // ProcessInterface protocol. 86 87 lldb_private::ConstString 88 ProcessFreeBSD::GetPluginName() 89 { 90 return GetPluginNameStatic(); 91 } 92 93 uint32_t 94 ProcessFreeBSD::GetPluginVersion() 95 { 96 return 1; 97 } 98 99 void 100 ProcessFreeBSD::GetPluginCommandHelp(const char *command, Stream *strm) 101 { 102 } 103 104 Error 105 ProcessFreeBSD::ExecutePluginCommand(Args &command, Stream *strm) 106 { 107 return Error(1, eErrorTypeGeneric); 108 } 109 110 Log * 111 ProcessFreeBSD::EnablePluginLogging(Stream *strm, Args &command) 112 { 113 return NULL; 114 } 115 116 //------------------------------------------------------------------------------ 117 // Constructors and destructors. 118 119 ProcessFreeBSD::ProcessFreeBSD(Target& target, Listener &listener) 120 : ProcessPOSIX(target, listener, GetFreeBSDSignals ()), 121 m_resume_signo(0) 122 { 123 } 124 125 void 126 ProcessFreeBSD::Terminate() 127 { 128 } 129 130 Error 131 ProcessFreeBSD::DoDetach(bool keep_stopped) 132 { 133 Error error; 134 if (keep_stopped) 135 { 136 error.SetErrorString("Detaching with keep_stopped true is not currently supported on FreeBSD."); 137 return error; 138 } 139 140 error = m_monitor->Detach(GetID()); 141 142 if (error.Success()) 143 SetPrivateState(eStateDetached); 144 145 return error; 146 } 147 148 Error 149 ProcessFreeBSD::DoResume() 150 { 151 Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); 152 153 SetPrivateState(eStateRunning); 154 155 Mutex::Locker lock(m_thread_list.GetMutex()); 156 bool do_step = false; 157 158 for (tid_collection::const_iterator t_pos = m_run_tids.begin(), t_end = m_run_tids.end(); t_pos != t_end; ++t_pos) 159 { 160 m_monitor->ThreadSuspend(*t_pos, false); 161 } 162 for (tid_collection::const_iterator t_pos = m_step_tids.begin(), t_end = m_step_tids.end(); t_pos != t_end; ++t_pos) 163 { 164 m_monitor->ThreadSuspend(*t_pos, false); 165 do_step = true; 166 } 167 for (tid_collection::const_iterator t_pos = m_suspend_tids.begin(), t_end = m_suspend_tids.end(); t_pos != t_end; ++t_pos) 168 { 169 m_monitor->ThreadSuspend(*t_pos, true); 170 // XXX Cannot PT_CONTINUE properly with suspended threads. 171 do_step = true; 172 } 173 174 if (log) 175 log->Printf("process %" PRIu64 " resuming (%s)", GetID(), do_step ? "step" : "continue"); 176 if (do_step) 177 m_monitor->SingleStep(GetID(), m_resume_signo); 178 else 179 m_monitor->Resume(GetID(), m_resume_signo); 180 181 return Error(); 182 } 183 184 bool 185 ProcessFreeBSD::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list) 186 { 187 Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); 188 if (log) 189 log->Printf("ProcessFreeBSD::%s (pid = %" PRIu64 ")", __FUNCTION__, GetID()); 190 191 std::vector<lldb::pid_t> tds; 192 if (!GetMonitor().GetCurrentThreadIDs(tds)) 193 { 194 return false; 195 } 196 197 ThreadList old_thread_list_copy(old_thread_list); 198 for (size_t i = 0; i < tds.size(); ++i) 199 { 200 tid_t tid = tds[i]; 201 ThreadSP thread_sp (old_thread_list_copy.RemoveThreadByID(tid, false)); 202 if (!thread_sp) 203 { 204 thread_sp.reset(new FreeBSDThread(*this, tid)); 205 if (log) 206 log->Printf("ProcessFreeBSD::%s new tid = %" PRIu64, __FUNCTION__, tid); 207 } 208 else 209 { 210 if (log) 211 log->Printf("ProcessFreeBSD::%s existing tid = %" PRIu64, __FUNCTION__, tid); 212 } 213 new_thread_list.AddThread(thread_sp); 214 } 215 for (size_t i = 0; i < old_thread_list_copy.GetSize(false); ++i) 216 { 217 ThreadSP old_thread_sp(old_thread_list_copy.GetThreadAtIndex(i, false)); 218 if (old_thread_sp) 219 { 220 if (log) 221 log->Printf("ProcessFreeBSD::%s remove tid", __FUNCTION__); 222 } 223 } 224 225 return true; 226 } 227 228 Error 229 ProcessFreeBSD::WillResume() 230 { 231 m_resume_signo = 0; 232 m_suspend_tids.clear(); 233 m_run_tids.clear(); 234 m_step_tids.clear(); 235 return ProcessPOSIX::WillResume(); 236 } 237 238 void 239 ProcessFreeBSD::SendMessage(const ProcessMessage &message) 240 { 241 Mutex::Locker lock(m_message_mutex); 242 243 switch (message.GetKind()) 244 { 245 case ProcessMessage::eInvalidMessage: 246 return; 247 248 case ProcessMessage::eAttachMessage: 249 SetPrivateState(eStateStopped); 250 return; 251 252 case ProcessMessage::eLimboMessage: 253 case ProcessMessage::eExitMessage: 254 SetExitStatus(message.GetExitStatus(), NULL); 255 break; 256 257 case ProcessMessage::eSignalMessage: 258 case ProcessMessage::eSignalDeliveredMessage: 259 case ProcessMessage::eBreakpointMessage: 260 case ProcessMessage::eTraceMessage: 261 case ProcessMessage::eWatchpointMessage: 262 case ProcessMessage::eCrashMessage: 263 SetPrivateState(eStateStopped); 264 break; 265 266 case ProcessMessage::eNewThreadMessage: 267 assert(0 && "eNewThreadMessage unexpected on FreeBSD"); 268 break; 269 270 case ProcessMessage::eExecMessage: 271 SetPrivateState(eStateStopped); 272 break; 273 } 274 275 m_message_queue.push(message); 276 } 277