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