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