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