1 //===-- SBBreakpoint.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/API/SBBreakpoint.h" 11 #include "lldb/API/SBBreakpointLocation.h" 12 #include "lldb/API/SBDebugger.h" 13 #include "lldb/API/SBEvent.h" 14 #include "lldb/API/SBProcess.h" 15 #include "lldb/API/SBStream.h" 16 #include "lldb/API/SBThread.h" 17 18 #include "lldb/Breakpoint/Breakpoint.h" 19 #include "lldb/Breakpoint/BreakpointLocation.h" 20 #include "lldb/Breakpoint/StoppointCallbackContext.h" 21 #include "lldb/Core/Address.h" 22 #include "lldb/Core/Stream.h" 23 #include "lldb/Core/StreamFile.h" 24 #include "lldb/Target/Process.h" 25 #include "lldb/Target/Target.h" 26 #include "lldb/Target/Thread.h" 27 #include "lldb/Target/ThreadSpec.h" 28 29 30 #include "lldb/lldb-enumerations.h" 31 32 using namespace lldb; 33 using namespace lldb_private; 34 35 struct CallbackData 36 { 37 SBBreakpoint::BreakpointHitCallback callback; 38 void *callback_baton; 39 }; 40 41 class SBBreakpointCallbackBaton : public Baton 42 { 43 public: 44 45 SBBreakpointCallbackBaton (SBBreakpoint::BreakpointHitCallback callback, void *baton) : 46 Baton (new CallbackData) 47 { 48 CallbackData *data = (CallbackData *)m_data; 49 data->callback = callback; 50 data->callback_baton = baton; 51 } 52 53 virtual ~SBBreakpointCallbackBaton() 54 { 55 CallbackData *data = (CallbackData *)m_data; 56 57 if (data) 58 { 59 delete data; 60 m_data = NULL; 61 } 62 } 63 }; 64 65 66 SBBreakpoint::SBBreakpoint () : 67 m_opaque_sp () 68 { 69 } 70 71 SBBreakpoint::SBBreakpoint (const SBBreakpoint& rhs) : 72 m_opaque_sp (rhs.m_opaque_sp) 73 { 74 } 75 76 77 SBBreakpoint::SBBreakpoint (const lldb::BreakpointSP &bp_sp) : 78 m_opaque_sp (bp_sp) 79 { 80 } 81 82 SBBreakpoint::~SBBreakpoint() 83 { 84 } 85 86 const SBBreakpoint & 87 SBBreakpoint::operator = (const SBBreakpoint& rhs) 88 { 89 if (this != &rhs) 90 { 91 m_opaque_sp = rhs.m_opaque_sp; 92 } 93 return *this; 94 } 95 96 break_id_t 97 SBBreakpoint::GetID () const 98 { 99 if (m_opaque_sp) 100 return m_opaque_sp->GetID(); 101 return LLDB_INVALID_BREAK_ID; 102 } 103 104 105 bool 106 SBBreakpoint::IsValid() const 107 { 108 return m_opaque_sp; 109 } 110 111 void 112 SBBreakpoint::ClearAllBreakpointSites () 113 { 114 if (m_opaque_sp) 115 m_opaque_sp->ClearAllBreakpointSites (); 116 } 117 118 SBBreakpointLocation 119 SBBreakpoint::FindLocationByAddress (addr_t vm_addr) 120 { 121 SBBreakpointLocation sb_bp_location; 122 123 if (m_opaque_sp) 124 { 125 if (vm_addr != LLDB_INVALID_ADDRESS) 126 { 127 Address address; 128 Target &target = m_opaque_sp->GetTarget(); 129 if (target.GetSectionLoadList().ResolveLoadAddress (vm_addr, address) == false) 130 { 131 address.SetSection (NULL); 132 address.SetOffset (vm_addr); 133 } 134 sb_bp_location.SetLocation (m_opaque_sp->FindLocationByAddress (address)); 135 } 136 } 137 return sb_bp_location; 138 } 139 140 break_id_t 141 SBBreakpoint::FindLocationIDByAddress (addr_t vm_addr) 142 { 143 break_id_t lldb_id = (break_id_t) 0; 144 145 if (m_opaque_sp) 146 { 147 if (vm_addr != LLDB_INVALID_ADDRESS) 148 { 149 Address address; 150 Target &target = m_opaque_sp->GetTarget(); 151 if (target.GetSectionLoadList().ResolveLoadAddress (vm_addr, address) == false) 152 { 153 address.SetSection (NULL); 154 address.SetOffset (vm_addr); 155 } 156 lldb_id = m_opaque_sp->FindLocationIDByAddress (address); 157 } 158 } 159 160 return lldb_id; 161 } 162 163 SBBreakpointLocation 164 SBBreakpoint::FindLocationByID (break_id_t bp_loc_id) 165 { 166 SBBreakpointLocation sb_bp_location; 167 168 if (m_opaque_sp) 169 sb_bp_location.SetLocation (m_opaque_sp->FindLocationByID (bp_loc_id)); 170 171 return sb_bp_location; 172 } 173 174 SBBreakpointLocation 175 SBBreakpoint::GetLocationAtIndex (uint32_t index) 176 { 177 SBBreakpointLocation sb_bp_location; 178 179 if (m_opaque_sp) 180 sb_bp_location.SetLocation (m_opaque_sp->GetLocationAtIndex (index)); 181 182 return sb_bp_location; 183 } 184 185 void 186 SBBreakpoint::SetEnabled (bool enable) 187 { 188 if (m_opaque_sp) 189 m_opaque_sp->SetEnabled (enable); 190 } 191 192 bool 193 SBBreakpoint::IsEnabled () 194 { 195 if (m_opaque_sp) 196 return m_opaque_sp->IsEnabled(); 197 else 198 return false; 199 } 200 201 void 202 SBBreakpoint::SetIgnoreCount (uint32_t count) 203 { 204 if (m_opaque_sp) 205 m_opaque_sp->SetIgnoreCount (count); 206 } 207 208 void 209 SBBreakpoint::SetCondition (const char *condition) 210 { 211 m_opaque_sp->SetCondition (condition); 212 } 213 214 const char * 215 SBBreakpoint::GetCondition () 216 { 217 return m_opaque_sp->GetConditionText (); 218 } 219 220 uint32_t 221 SBBreakpoint::GetHitCount () const 222 { 223 if (m_opaque_sp) 224 return m_opaque_sp->GetHitCount(); 225 else 226 return 0; 227 } 228 229 uint32_t 230 SBBreakpoint::GetIgnoreCount () const 231 { 232 if (m_opaque_sp) 233 return m_opaque_sp->GetIgnoreCount(); 234 else 235 return 0; 236 } 237 238 void 239 SBBreakpoint::SetThreadID (tid_t sb_thread_id) 240 { 241 if (m_opaque_sp) 242 m_opaque_sp->SetThreadID (sb_thread_id); 243 } 244 245 tid_t 246 SBBreakpoint::GetThreadID () 247 { 248 tid_t lldb_thread_id = LLDB_INVALID_THREAD_ID; 249 if (m_opaque_sp) 250 lldb_thread_id = m_opaque_sp->GetThreadID(); 251 252 return lldb_thread_id; 253 } 254 255 void 256 SBBreakpoint::SetThreadIndex (uint32_t index) 257 { 258 if (m_opaque_sp) 259 m_opaque_sp->GetOptions()->GetThreadSpec()->SetIndex (index); 260 } 261 262 uint32_t 263 SBBreakpoint::GetThreadIndex() const 264 { 265 if (m_opaque_sp) 266 { 267 const ThreadSpec *thread_spec = m_opaque_sp->GetOptions()->GetThreadSpec(); 268 if (thread_spec == NULL) 269 return 0; 270 else 271 return thread_spec->GetIndex(); 272 } 273 return 0; 274 } 275 276 277 void 278 SBBreakpoint::SetThreadName (const char *thread_name) 279 { 280 if (m_opaque_sp) 281 m_opaque_sp->GetOptions()->GetThreadSpec()->SetName (thread_name); 282 } 283 284 const char * 285 SBBreakpoint::GetThreadName () const 286 { 287 if (m_opaque_sp) 288 { 289 const ThreadSpec *thread_spec = m_opaque_sp->GetOptions()->GetThreadSpec(); 290 if (thread_spec == NULL) 291 return NULL; 292 else 293 return thread_spec->GetName(); 294 } 295 return NULL; 296 } 297 298 void 299 SBBreakpoint::SetQueueName (const char *queue_name) 300 { 301 if (m_opaque_sp) 302 m_opaque_sp->GetOptions()->GetThreadSpec()->SetQueueName (queue_name); 303 } 304 305 const char * 306 SBBreakpoint::GetQueueName () const 307 { 308 if (m_opaque_sp) 309 { 310 const ThreadSpec *thread_spec = m_opaque_sp->GetOptions()->GetThreadSpec(); 311 if (thread_spec == NULL) 312 return NULL; 313 else 314 return thread_spec->GetQueueName(); 315 } 316 return NULL; 317 } 318 319 size_t 320 SBBreakpoint::GetNumResolvedLocations() const 321 { 322 if (m_opaque_sp) 323 return m_opaque_sp->GetNumResolvedLocations(); 324 else 325 return 0; 326 } 327 328 size_t 329 SBBreakpoint::GetNumLocations() const 330 { 331 if (m_opaque_sp) 332 return m_opaque_sp->GetNumLocations(); 333 else 334 return 0; 335 } 336 337 bool 338 SBBreakpoint::GetDescription (SBStream &s) 339 { 340 if (m_opaque_sp) 341 { 342 s.Printf("SBBreakpoint: id = %i, ", m_opaque_sp->GetID()); 343 m_opaque_sp->GetResolverDescription (s.get()); 344 m_opaque_sp->GetFilterDescription (s.get()); 345 const size_t num_locations = m_opaque_sp->GetNumLocations (); 346 s.Printf(", locations = %zu", num_locations); 347 return true; 348 } 349 s.Printf ("No value"); 350 return false; 351 } 352 353 bool 354 SBBreakpoint::PrivateBreakpointHitCallback 355 ( 356 void *baton, 357 StoppointCallbackContext *ctx, 358 lldb::user_id_t break_id, 359 lldb::user_id_t break_loc_id 360 ) 361 { 362 BreakpointSP bp_sp(ctx->exe_ctx.target->GetBreakpointList().FindBreakpointByID(break_id)); 363 if (baton && bp_sp) 364 { 365 CallbackData *data = (CallbackData *)baton; 366 lldb_private::Breakpoint *bp = bp_sp.get(); 367 if (bp && data->callback) 368 { 369 if (ctx->exe_ctx.process) 370 { 371 SBProcess sb_process (ctx->exe_ctx.process->GetSP()); 372 SBThread sb_thread; 373 SBBreakpointLocation sb_location; 374 assert (bp_sp); 375 sb_location.SetLocation (bp_sp->FindLocationByID (break_loc_id)); 376 if (ctx->exe_ctx.thread) 377 sb_thread.SetThread(ctx->exe_ctx.thread->GetSP()); 378 379 return data->callback (data->callback_baton, 380 sb_process, 381 sb_thread, 382 sb_location); 383 } 384 } 385 } 386 return true; // Return true if we should stop at this breakpoint 387 } 388 389 void 390 SBBreakpoint::SetCallback (BreakpointHitCallback callback, void *baton) 391 { 392 if (m_opaque_sp.get()) 393 { 394 BatonSP baton_sp(new SBBreakpointCallbackBaton (callback, baton)); 395 m_opaque_sp->SetCallback (SBBreakpoint::PrivateBreakpointHitCallback, baton_sp, false); 396 } 397 } 398 399 400 lldb_private::Breakpoint * 401 SBBreakpoint::operator->() const 402 { 403 return m_opaque_sp.get(); 404 } 405 406 lldb_private::Breakpoint * 407 SBBreakpoint::get() const 408 { 409 return m_opaque_sp.get(); 410 } 411 412 lldb::BreakpointSP & 413 SBBreakpoint::operator *() 414 { 415 return m_opaque_sp; 416 } 417 418 const lldb::BreakpointSP & 419 SBBreakpoint::operator *() const 420 { 421 return m_opaque_sp; 422 } 423 424 BreakpointEventType 425 SBBreakpoint::GetBreakpointEventTypeFromEvent (const SBEvent& event) 426 { 427 if (event.IsValid()) 428 return Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent (event.GetSP()); 429 return eBreakpointEventTypeInvalidType; 430 } 431 432 SBBreakpoint 433 SBBreakpoint::GetBreakpointFromEvent (const lldb::SBEvent& event) 434 { 435 SBBreakpoint sb_breakpoint; 436 if (event.IsValid()) 437 sb_breakpoint.m_opaque_sp = Breakpoint::BreakpointEventData::GetBreakpointFromEvent (event.GetSP()); 438 return sb_breakpoint; 439 } 440 441 SBBreakpointLocation 442 SBBreakpoint::GetBreakpointLocationAtIndexFromEvent (const lldb::SBEvent& event, uint32_t loc_idx) 443 { 444 SBBreakpointLocation sb_breakpoint_loc; 445 if (event.IsValid()) 446 sb_breakpoint_loc.SetLocation (Breakpoint::BreakpointEventData::GetBreakpointLocationAtIndexFromEvent (event.GetSP(), loc_idx)); 447 return sb_breakpoint_loc; 448 } 449 450 451