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