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