1 //===-- StopInfo.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 #include "lldb/Target/StopInfo.h" 11 12 // C Includes 13 // C++ Includes 14 #include <string> 15 16 // Other libraries and framework includes 17 // Project includes 18 #include "lldb/Core/Log.h" 19 #include "lldb/Breakpoint/Breakpoint.h" 20 #include "lldb/Breakpoint/BreakpointLocation.h" 21 #include "lldb/Breakpoint/StoppointCallbackContext.h" 22 #include "lldb/Core/StreamString.h" 23 #include "lldb/Target/Thread.h" 24 #include "lldb/Target/ThreadPlan.h" 25 #include "lldb/Target/Process.h" 26 #include "lldb/Target/UnixSignals.h" 27 28 using namespace lldb; 29 using namespace lldb_private; 30 31 StopInfo::StopInfo (Thread &thread, uint64_t value) : 32 m_thread (thread), 33 m_stop_id (thread.GetProcess().GetStopID()), 34 m_value (value) 35 { 36 } 37 38 bool 39 StopInfo::IsValid () const 40 { 41 return m_thread.GetProcess().GetStopID() == m_stop_id; 42 } 43 44 void 45 StopInfo::MakeStopInfoValid () 46 { 47 m_stop_id = m_thread.GetProcess().GetStopID(); 48 } 49 50 //---------------------------------------------------------------------- 51 // StopInfoBreakpoint 52 //---------------------------------------------------------------------- 53 54 class StopInfoBreakpoint : public StopInfo 55 { 56 public: 57 58 StopInfoBreakpoint (Thread &thread, break_id_t break_id) : 59 StopInfo (thread, break_id), 60 m_description(), 61 m_should_stop (false), 62 m_should_stop_is_valid (false), 63 m_should_perform_action (true) 64 { 65 } 66 67 StopInfoBreakpoint (Thread &thread, break_id_t break_id, bool should_stop) : 68 StopInfo (thread, break_id), 69 m_description(), 70 m_should_stop (should_stop), 71 m_should_stop_is_valid (true), 72 m_should_perform_action (true) 73 { 74 } 75 76 virtual ~StopInfoBreakpoint () 77 { 78 } 79 80 virtual StopReason 81 GetStopReason () const 82 { 83 return eStopReasonBreakpoint; 84 } 85 86 virtual bool 87 ShouldStop (Event *event_ptr) 88 { 89 if (!m_should_stop_is_valid) 90 { 91 // Only check once if we should stop at a breakpoint 92 BreakpointSiteSP bp_site_sp (m_thread.GetProcess().GetBreakpointSiteList().FindByID (m_value)); 93 if (bp_site_sp) 94 { 95 StoppointCallbackContext context (event_ptr, 96 &m_thread.GetProcess(), 97 &m_thread, 98 m_thread.GetStackFrameAtIndex(0).get(), 99 true); 100 101 m_should_stop = bp_site_sp->ShouldStop (&context); 102 } 103 else 104 { 105 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); 106 107 if (log) 108 log->Printf ("Process::%s could not find breakpoint site id: %lld...", __FUNCTION__, m_value); 109 110 m_should_stop = true; 111 } 112 m_should_stop_is_valid = true; 113 } 114 return m_should_stop; 115 } 116 117 virtual void 118 PerformAction (Event *event_ptr) 119 { 120 if (!m_should_perform_action) 121 return; 122 m_should_perform_action = false; 123 124 BreakpointSiteSP bp_site_sp (m_thread.GetProcess().GetBreakpointSiteList().FindByID (m_value)); 125 if (bp_site_sp) 126 { 127 size_t num_owners = bp_site_sp->GetNumberOfOwners(); 128 for (size_t j = 0; j < num_owners; j++) 129 { 130 // The breakpoint action is an asynchronous breakpoint callback. If we ever need to have both 131 // callbacks and actions on the same breakpoint, we'll have to split this into two. 132 lldb::BreakpointLocationSP bp_loc_sp = bp_site_sp->GetOwnerAtIndex(j); 133 StoppointCallbackContext context (event_ptr, 134 &m_thread.GetProcess(), 135 &m_thread, 136 m_thread.GetStackFrameAtIndex(0).get(), 137 false); 138 bp_loc_sp->InvokeCallback (&context); 139 } 140 } 141 else 142 { 143 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); 144 145 if (log) 146 log->Printf ("Process::%s could not find breakpoint site id: %lld...", __FUNCTION__, m_value); 147 } 148 } 149 150 virtual bool 151 ShouldNotify (Event *event_ptr) 152 { 153 BreakpointSiteSP bp_site_sp (m_thread.GetProcess().GetBreakpointSiteList().FindByID (m_value)); 154 if (bp_site_sp) 155 { 156 bool all_internal = true; 157 158 for (uint32_t i = 0; i < bp_site_sp->GetNumberOfOwners(); i++) 159 { 160 if (!bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint().IsInternal()) 161 { 162 all_internal = false; 163 break; 164 } 165 } 166 return all_internal == false; 167 } 168 return true; 169 } 170 171 virtual const char * 172 GetDescription () 173 { 174 if (m_description.empty()) 175 { 176 BreakpointSiteSP bp_site_sp (m_thread.GetProcess().GetBreakpointSiteList().FindByID (m_value)); 177 if (bp_site_sp) 178 { 179 StreamString strm; 180 strm.Printf("breakpoint "); 181 bp_site_sp->GetDescription(&strm, eDescriptionLevelBrief); 182 m_description.swap (strm.GetString()); 183 } 184 else 185 { 186 StreamString strm; 187 strm.Printf("breakpoint site %lli", m_value); 188 m_description.swap (strm.GetString()); 189 } 190 } 191 return m_description.c_str(); 192 } 193 194 private: 195 std::string m_description; 196 bool m_should_stop; 197 bool m_should_stop_is_valid; 198 bool m_should_perform_action; // Since we are trying to preserve the "state" of the system even if we run functions 199 // etc. behind the users backs, we need to make sure we only REALLY perform the action once. 200 }; 201 202 203 //---------------------------------------------------------------------- 204 // StopInfoWatchpoint 205 //---------------------------------------------------------------------- 206 207 class StopInfoWatchpoint : public StopInfo 208 { 209 public: 210 211 StopInfoWatchpoint (Thread &thread, break_id_t watch_id) : 212 StopInfo (thread, watch_id), 213 m_description() 214 { 215 } 216 217 virtual ~StopInfoWatchpoint () 218 { 219 } 220 221 virtual StopReason 222 GetStopReason () const 223 { 224 return eStopReasonWatchpoint; 225 } 226 227 virtual const char * 228 GetDescription () 229 { 230 if (m_description.empty()) 231 { 232 StreamString strm; 233 strm.Printf("watchpoint %lli", m_value); 234 m_description.swap (strm.GetString()); 235 } 236 return m_description.c_str(); 237 } 238 239 240 241 private: 242 std::string m_description; 243 }; 244 245 246 247 //---------------------------------------------------------------------- 248 // StopInfoUnixSignal 249 //---------------------------------------------------------------------- 250 251 class StopInfoUnixSignal : public StopInfo 252 { 253 public: 254 255 StopInfoUnixSignal (Thread &thread, int signo) : 256 StopInfo (thread, signo), 257 m_description() 258 { 259 } 260 261 virtual ~StopInfoUnixSignal () 262 { 263 } 264 265 266 virtual StopReason 267 GetStopReason () const 268 { 269 return eStopReasonSignal; 270 } 271 272 virtual bool 273 ShouldStop (Event *event_ptr) 274 { 275 return m_thread.GetProcess().GetUnixSignals().GetShouldStop (m_value); 276 } 277 278 279 // If should stop returns false, check if we should notify of this event 280 virtual bool 281 ShouldNotify (Event *event_ptr) 282 { 283 return m_thread.GetProcess().GetUnixSignals().GetShouldNotify (m_value); 284 } 285 286 287 virtual void 288 WillResume (lldb::StateType resume_state) 289 { 290 if (m_thread.GetProcess().GetUnixSignals().GetShouldSuppress(m_value) == false) 291 m_thread.SetResumeSignal(m_value); 292 } 293 294 virtual const char * 295 GetDescription () 296 { 297 if (m_description.empty()) 298 { 299 StreamString strm; 300 const char *signal_name = m_thread.GetProcess().GetUnixSignals().GetSignalAsCString (m_value); 301 if (signal_name) 302 strm.Printf("signal %s", signal_name); 303 else 304 strm.Printf("signal %lli", m_value); 305 m_description.swap (strm.GetString()); 306 } 307 return m_description.c_str(); 308 } 309 310 private: 311 std::string m_description; 312 }; 313 314 //---------------------------------------------------------------------- 315 // StopInfoTrace 316 //---------------------------------------------------------------------- 317 318 class StopInfoTrace : public StopInfo 319 { 320 public: 321 322 StopInfoTrace (Thread &thread) : 323 StopInfo (thread, LLDB_INVALID_UID) 324 { 325 } 326 327 virtual ~StopInfoTrace () 328 { 329 } 330 331 virtual StopReason 332 GetStopReason () const 333 { 334 return eStopReasonTrace; 335 } 336 337 virtual const char * 338 GetDescription () 339 { 340 return "trace"; 341 } 342 }; 343 344 345 //---------------------------------------------------------------------- 346 // StopInfoThreadPlan 347 //---------------------------------------------------------------------- 348 349 class StopInfoThreadPlan : public StopInfo 350 { 351 public: 352 353 StopInfoThreadPlan (ThreadPlanSP &plan_sp) : 354 StopInfo (plan_sp->GetThread(), LLDB_INVALID_UID), 355 m_plan_sp (plan_sp) 356 { 357 } 358 359 virtual ~StopInfoThreadPlan () 360 { 361 } 362 363 virtual StopReason 364 GetStopReason () const 365 { 366 return eStopReasonPlanComplete; 367 } 368 369 virtual const char * 370 GetDescription () 371 { 372 if (m_description.empty()) 373 { 374 StreamString strm; 375 m_plan_sp->GetDescription (&strm, eDescriptionLevelBrief); 376 m_description.swap (strm.GetString()); 377 } 378 return m_description.c_str(); 379 } 380 381 private: 382 ThreadPlanSP m_plan_sp; 383 std::string m_description; 384 }; 385 386 StopInfoSP 387 StopInfo::CreateStopReasonWithBreakpointSiteID (Thread &thread, break_id_t break_id) 388 { 389 return StopInfoSP (new StopInfoBreakpoint (thread, break_id)); 390 } 391 392 StopInfoSP 393 StopInfo::CreateStopReasonWithBreakpointSiteID (Thread &thread, break_id_t break_id, bool should_stop) 394 { 395 return StopInfoSP (new StopInfoBreakpoint (thread, break_id, should_stop)); 396 } 397 398 StopInfoSP 399 StopInfo::CreateStopReasonWithWatchpointID (Thread &thread, break_id_t watch_id) 400 { 401 return StopInfoSP (new StopInfoWatchpoint (thread, watch_id)); 402 } 403 404 StopInfoSP 405 StopInfo::CreateStopReasonWithSignal (Thread &thread, int signo) 406 { 407 return StopInfoSP (new StopInfoUnixSignal (thread, signo)); 408 } 409 410 StopInfoSP 411 StopInfo::CreateStopReasonToTrace (Thread &thread) 412 { 413 return StopInfoSP (new StopInfoTrace (thread)); 414 } 415 416 StopInfoSP 417 StopInfo::CreateStopReasonWithPlan (ThreadPlanSP &plan_sp) 418 { 419 return StopInfoSP (new StopInfoThreadPlan (plan_sp)); 420 } 421