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