1use crate::{
8 lldb_addr_t, sys, DescriptionLevel, MatchType, SBAddress, SBAttachInfo, SBBreakpoint,
9 SBBroadcaster, SBDebugger, SBError, SBEvent, SBExpressionOptions, SBFileSpec, SBLaunchInfo,
10 SBModule, SBModuleSpec, SBPlatform, SBProcess, SBStream, SBSymbolContextList, SBValue,
11 SBWatchpoint, SymbolType,
12};
13use lldb_sys::ByteOrder;
14use std::ffi::{CStr, CString};
15use std::fmt;
16
17pub struct SBTarget {
69 pub raw: sys::SBTargetRef,
71}
72
73impl SBTarget {
74 pub(crate) fn wrap(raw: sys::SBTargetRef) -> SBTarget {
76 SBTarget { raw }
77 }
78
79 pub(crate) fn maybe_wrap(raw: sys::SBTargetRef) -> Option<SBTarget> {
81 if unsafe { sys::SBTargetIsValid(raw) } {
82 Some(SBTarget { raw })
83 } else {
84 None
85 }
86 }
87
88 pub fn is_valid(&self) -> bool {
90 unsafe { sys::SBTargetIsValid(self.raw) }
91 }
92
93 #[allow(missing_docs)]
94 pub fn broadcaster_class_name() -> &'static str {
95 unsafe {
96 match CStr::from_ptr(sys::SBTargetGetBroadcasterClassName()).to_str() {
97 Ok(s) => s,
98 _ => panic!("Invalid string?"),
99 }
100 }
101 }
102
103 pub fn platform(&self) -> SBPlatform {
107 unsafe {
108 SBPlatform {
109 raw: sys::SBTargetGetPlatform(self.raw),
110 }
111 }
112 }
113
114 pub fn process(&self) -> SBProcess {
116 unsafe {
117 SBProcess {
118 raw: sys::SBTargetGetProcess(self.raw),
119 }
120 }
121 }
122
123 pub fn launch(&self, launch_info: SBLaunchInfo) -> Result<SBProcess, SBError> {
125 let error: SBError = SBError::default();
126 let process =
127 SBProcess::wrap(unsafe { sys::SBTargetLaunch2(self.raw, launch_info.raw, error.raw) });
128 if error.is_success() {
129 Ok(process)
130 } else {
131 Err(error)
132 }
133 }
134
135 #[allow(missing_docs)]
136 pub fn load_core(&self, core_file: &str) -> Result<SBProcess, SBError> {
137 let error: SBError = SBError::default();
138 let core_file = CString::new(core_file).unwrap();
139 let process = SBProcess::wrap(unsafe {
140 sys::SBTargetLoadCore(self.raw, core_file.as_ptr(), error.raw)
141 });
142 if error.is_success() {
143 Ok(process)
144 } else {
145 Err(error)
146 }
147 }
148
149 #[allow(missing_docs)]
150 pub fn attach(&self, attach_info: SBAttachInfo) -> Result<SBProcess, SBError> {
151 let error: SBError = SBError::default();
152 let process =
153 SBProcess::wrap(unsafe { sys::SBTargetAttach(self.raw, attach_info.raw, error.raw) });
154 if error.is_success() {
155 Ok(process)
156 } else {
157 Err(error)
158 }
159 }
160
161 pub fn executable(&self) -> Option<SBFileSpec> {
163 SBFileSpec::maybe_wrap(unsafe { sys::SBTargetGetExecutable(self.raw) })
164 }
165
166 pub fn add_module(&self, module: &SBModule) -> bool {
168 unsafe { sys::SBTargetAddModule(self.raw, module.raw) }
169 }
170
171 pub fn add_module_spec(&self, module_spec: &SBModuleSpec) -> Option<SBModule> {
173 SBModule::maybe_wrap(unsafe { sys::SBTargetAddModuleSpec(self.raw, module_spec.raw) })
174 }
175
176 pub fn remove_module(&self, module: &SBModule) -> bool {
178 unsafe { sys::SBTargetRemoveModule(self.raw, module.raw) }
179 }
180
181 pub fn debugger(&self) -> SBDebugger {
183 SBDebugger {
184 raw: unsafe { sys::SBTargetGetDebugger(self.raw) },
185 }
186 }
187
188 pub fn modules(&self) -> SBTargetModuleIter {
192 SBTargetModuleIter {
193 target: self,
194 idx: 0,
195 }
196 }
197
198 pub fn find_module(&self, file_spec: &SBFileSpec) -> Option<SBModule> {
200 SBModule::maybe_wrap(unsafe { sys::SBTargetFindModule(self.raw, file_spec.raw) })
201 }
202
203 pub fn resolve_file_address(&self, file_addr: lldb_addr_t) -> Option<SBAddress> {
205 SBAddress::maybe_wrap(unsafe { sys::SBTargetResolveFileAddress(self.raw, file_addr) })
206 }
207
208 pub fn resolve_load_address(&self, vm_addr: lldb_addr_t) -> Option<SBAddress> {
213 SBAddress::maybe_wrap(unsafe { sys::SBTargetResolveLoadAddress(self.raw, vm_addr) })
214 }
215
216 #[allow(missing_docs)]
217 pub fn delete_breakpoint(&self, break_id: i32) {
218 unsafe { sys::SBTargetBreakpointDelete(self.raw, break_id) };
219 }
220
221 #[allow(missing_docs)]
222 pub fn find_breakpoint_by_id(&self, break_id: i32) -> Option<SBBreakpoint> {
223 SBBreakpoint::maybe_wrap(unsafe { sys::SBTargetFindBreakpointByID(self.raw, break_id) })
224 }
225
226 #[allow(missing_docs)]
227 pub fn enable_all_breakpoints(&self) {
228 unsafe { sys::SBTargetEnableAllBreakpoints(self.raw) };
229 }
230
231 #[allow(missing_docs)]
232 pub fn disable_all_breakpoints(&self) {
233 unsafe { sys::SBTargetDisableAllBreakpoints(self.raw) };
234 }
235
236 #[allow(missing_docs)]
237 pub fn delete_all_breakpoints(&self) {
238 unsafe { sys::SBTargetDeleteAllBreakpoints(self.raw) };
239 }
240
241 #[allow(missing_docs)]
242 pub fn breakpoint_create_by_location(&self, file: &str, line: u32) -> SBBreakpoint {
243 let file = CString::new(file).unwrap();
244 SBBreakpoint::wrap(unsafe {
245 sys::SBTargetBreakpointCreateByLocation(self.raw, file.as_ptr(), line)
246 })
247 }
248
249 #[allow(missing_docs)]
250 pub fn breakpoint_create_by_address(&self, address: lldb_addr_t) -> SBBreakpoint {
251 SBBreakpoint::wrap(unsafe { sys::SBTargetBreakpointCreateByAddress(self.raw, address) })
252 }
253
254 #[allow(missing_docs)]
255 pub fn breakpoint_create_by_sbaddress(&self, address: SBAddress) -> SBBreakpoint {
256 SBBreakpoint::wrap(unsafe {
257 sys::SBTargetBreakpointCreateBySBAddress(self.raw, address.raw)
258 })
259 }
260
261 #[allow(missing_docs)]
262 pub fn breakpoints(&self) -> SBTargetBreakpointIter {
263 SBTargetBreakpointIter {
264 target: self,
265 idx: 0,
266 }
267 }
268
269 #[allow(missing_docs)]
270 pub fn delete_watchpoint(&self, watch_id: i32) {
271 unsafe { sys::SBTargetDeleteWatchpoint(self.raw, watch_id) };
272 }
273
274 #[allow(missing_docs)]
275 pub fn find_watchpoint_by_id(&self, watch_id: i32) -> Option<SBWatchpoint> {
276 SBWatchpoint::maybe_wrap(unsafe { sys::SBTargetFindWatchpointByID(self.raw, watch_id) })
277 }
278
279 #[allow(missing_docs)]
280 pub fn enable_all_watchpoints(&self) {
281 unsafe { sys::SBTargetEnableAllWatchpoints(self.raw) };
282 }
283
284 #[allow(missing_docs)]
285 pub fn disable_all_watchpoints(&self) {
286 unsafe { sys::SBTargetDisableAllWatchpoints(self.raw) };
287 }
288
289 #[allow(missing_docs)]
290 pub fn delete_all_watchpoints(&self) {
291 unsafe { sys::SBTargetDeleteAllWatchpoints(self.raw) };
292 }
293
294 #[allow(missing_docs)]
295 pub fn watch_address(
296 &self,
297 addr: lldb_addr_t,
298 size: usize,
299 read: bool,
300 write: bool,
301 ) -> Result<SBWatchpoint, SBError> {
302 let error: SBError = SBError::default();
303 let watchpoint =
304 unsafe { sys::SBTargetWatchAddress(self.raw, addr, size, read, write, error.raw) };
305 if error.is_success() {
306 Ok(SBWatchpoint::wrap(watchpoint))
307 } else {
308 Err(error)
309 }
310 }
311
312 #[allow(missing_docs)]
313 pub fn watchpoints(&self) -> SBTargetWatchpointIter {
314 SBTargetWatchpointIter {
315 target: self,
316 idx: 0,
317 }
318 }
319
320 #[allow(missing_docs)]
321 pub fn broadcaster(&self) -> SBBroadcaster {
322 SBBroadcaster::wrap(unsafe { sys::SBTargetGetBroadcaster(self.raw) })
323 }
324
325 #[allow(missing_docs)]
326 pub fn find_functions(&self, name: &str, name_type_mask: u32) -> SBSymbolContextList {
327 let name = CString::new(name).unwrap();
328 SBSymbolContextList::wrap(unsafe {
329 sys::SBTargetFindFunctions(self.raw, name.as_ptr(), name_type_mask)
330 })
331 }
332
333 #[allow(missing_docs)]
334 pub fn find_global_functions(
335 &self,
336 name: &str,
337 max_matches: u32,
338 matchtype: MatchType,
339 ) -> SBSymbolContextList {
340 let name = CString::new(name).unwrap();
341 SBSymbolContextList::wrap(unsafe {
342 sys::SBTargetFindGlobalFunctions(self.raw, name.as_ptr(), max_matches, matchtype)
343 })
344 }
345
346 #[allow(missing_docs)]
347 pub fn find_symbols(&self, name: &str, symbol_type: SymbolType) -> SBSymbolContextList {
348 let name = CString::new(name).unwrap();
349 SBSymbolContextList::wrap(unsafe {
350 sys::SBTargetFindSymbols(self.raw, name.as_ptr(), symbol_type)
351 })
352 }
353
354 pub fn evaluate_expression(&self, expression: &str, options: &SBExpressionOptions) -> SBValue {
356 let expression = CString::new(expression).unwrap();
357 SBValue::wrap(unsafe {
358 sys::SBTargetEvaluateExpression(self.raw, expression.as_ptr(), options.raw)
359 })
360 }
361
362 #[allow(missing_docs)]
363 pub fn event_as_target_event(event: &SBEvent) -> Option<SBTargetEvent> {
364 if unsafe { sys::SBTargetEventIsTargetEvent(event.raw) } {
365 Some(SBTargetEvent::new(event))
366 } else {
367 None
368 }
369 }
370
371 #[allow(missing_docs)]
372 pub fn get_stack_red_zone_size(&self) -> lldb_addr_t {
373 unsafe { sys::SBTargetGetStackRedZoneSize(self.raw) }
374 }
375
376 #[allow(missing_docs)]
377 pub fn is_loaded(&self, module: &SBModule) -> bool {
378 unsafe { sys::SBTargetIsLoaded(self.raw, module.raw) }
379 }
380
381 #[allow(missing_docs)]
382 pub fn get_launch_info(&self) -> SBLaunchInfo {
383 SBLaunchInfo::wrap(unsafe { sys::SBTargetGetLaunchInfo(self.raw) })
384 }
385
386 #[allow(missing_docs)]
387 pub fn set_launch_info(&self, launch_info: SBLaunchInfo) {
388 unsafe { sys::SBTargetSetLaunchInfo(self.raw, launch_info.raw) };
389 }
390
391 pub fn byte_order(&self) -> ByteOrder {
393 unsafe { sys::SBTargetGetByteOrder(self.raw) }
394 }
395
396 pub fn get_address_byte_size(&self) -> u32 {
398 unsafe { sys::SBTargetGetAddressByteSize(self.raw) }
399 }
400}
401
402impl Clone for SBTarget {
403 fn clone(&self) -> SBTarget {
404 SBTarget {
405 raw: unsafe { sys::CloneSBTarget(self.raw) },
406 }
407 }
408}
409
410impl fmt::Debug for SBTarget {
411 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
412 let stream = SBStream::new();
413 unsafe { sys::SBTargetGetDescription(self.raw, stream.raw, DescriptionLevel::Brief) };
414 write!(fmt, "SBTarget {{ {} }}", stream.data())
415 }
416}
417
418impl Drop for SBTarget {
419 fn drop(&mut self) {
420 unsafe { sys::DisposeSBTarget(self.raw) };
421 }
422}
423
424unsafe impl Send for SBTarget {}
425unsafe impl Sync for SBTarget {}
426
427pub struct SBTargetBreakpointIter<'d> {
432 target: &'d SBTarget,
433 idx: usize,
434}
435
436impl Iterator for SBTargetBreakpointIter<'_> {
437 type Item = SBBreakpoint;
438
439 fn next(&mut self) -> Option<SBBreakpoint> {
440 if self.idx < unsafe { sys::SBTargetGetNumBreakpoints(self.target.raw) as usize } {
441 let r = Some(SBBreakpoint::wrap(unsafe {
442 sys::SBTargetGetBreakpointAtIndex(self.target.raw, self.idx as u32)
443 }));
444 self.idx += 1;
445 r
446 } else {
447 None
448 }
449 }
450
451 fn size_hint(&self) -> (usize, Option<usize>) {
452 let sz = unsafe { sys::SBTargetGetNumBreakpoints(self.target.raw) } as usize;
453 (sz - self.idx, Some(sz))
454 }
455}
456
457impl ExactSizeIterator for SBTargetBreakpointIter<'_> {}
458
459pub struct SBTargetWatchpointIter<'d> {
464 target: &'d SBTarget,
465 idx: usize,
466}
467
468impl Iterator for SBTargetWatchpointIter<'_> {
469 type Item = SBWatchpoint;
470
471 fn next(&mut self) -> Option<SBWatchpoint> {
472 if self.idx < unsafe { sys::SBTargetGetNumWatchpoints(self.target.raw) as usize } {
473 let r = Some(SBWatchpoint::wrap(unsafe {
474 sys::SBTargetGetWatchpointAtIndex(self.target.raw, self.idx as u32)
475 }));
476 self.idx += 1;
477 r
478 } else {
479 None
480 }
481 }
482
483 fn size_hint(&self) -> (usize, Option<usize>) {
484 let sz = unsafe { sys::SBTargetGetNumWatchpoints(self.target.raw) } as usize;
485 (sz - self.idx, Some(sz))
486 }
487}
488
489impl ExactSizeIterator for SBTargetWatchpointIter<'_> {}
490
491#[allow(missing_docs)]
492pub struct SBTargetEvent<'e> {
493 event: &'e SBEvent,
494}
495
496#[allow(missing_docs)]
497impl<'e> SBTargetEvent<'e> {
498 pub fn new(event: &'e SBEvent) -> Self {
499 SBTargetEvent { event }
500 }
501
502 pub fn target(&self) -> SBTarget {
503 SBTarget::wrap(unsafe { sys::SBTargetGetTargetFromEvent(self.event.raw) })
504 }
505
506 pub fn modules(&self) -> SBTargetEventModuleIter {
507 SBTargetEventModuleIter {
508 event: self,
509 idx: 0,
510 }
511 }
512}
513
514pub struct SBTargetEventModuleIter<'d> {
519 event: &'d SBTargetEvent<'d>,
520 idx: usize,
521}
522
523impl Iterator for SBTargetEventModuleIter<'_> {
524 type Item = SBModule;
525
526 fn next(&mut self) -> Option<SBModule> {
527 if self.idx < unsafe { sys::SBTargetGetNumModulesFromEvent(self.event.event.raw) as usize }
528 {
529 let r = Some(SBModule::wrap(unsafe {
530 sys::SBTargetGetModuleAtIndexFromEvent(self.idx as u32, self.event.event.raw)
531 }));
532 self.idx += 1;
533 r
534 } else {
535 None
536 }
537 }
538
539 fn size_hint(&self) -> (usize, Option<usize>) {
540 let sz = unsafe { sys::SBTargetGetNumModulesFromEvent(self.event.event.raw) } as usize;
541 (sz - self.idx, Some(sz))
542 }
543}
544
545impl ExactSizeIterator for SBTargetEventModuleIter<'_> {}
546
547pub struct SBTargetModuleIter<'d> {
552 target: &'d SBTarget,
553 idx: u32,
554}
555
556impl Iterator for SBTargetModuleIter<'_> {
557 type Item = SBModule;
558
559 fn next(&mut self) -> Option<SBModule> {
560 if self.idx < unsafe { sys::SBTargetGetNumModules(self.target.raw) } {
561 let r = Some(SBModule::wrap(unsafe {
562 sys::SBTargetGetModuleAtIndex(self.target.raw, self.idx)
563 }));
564 self.idx += 1;
565 r
566 } else {
567 None
568 }
569 }
570
571 fn size_hint(&self) -> (usize, Option<usize>) {
572 let sz = unsafe { sys::SBTargetGetNumModules(self.target.raw) } as usize;
573 (sz - self.idx as usize, Some(sz))
574 }
575}
576
577impl ExactSizeIterator for SBTargetModuleIter<'_> {}
578
579#[cfg(feature = "graphql")]
580#[juniper::graphql_object]
581impl SBTarget {
582 fn platform() -> SBPlatform {
583 self.platform()
584 }
585
586 fn process() -> SBProcess {
587 self.process()
588 }
589
590 fn executable() -> Option<SBFileSpec> {
591 self.executable()
592 }
593
594 fn debugger() -> SBDebugger {
595 self.debugger()
596 }
597
598 fn breakpoints() -> Vec<SBBreakpoint> {
599 self.breakpoints().collect()
600 }
601
602 fn watchpoints() -> Vec<SBWatchpoint> {
603 self.watchpoints().collect()
604 }
605}