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