Class: LLDB::Target

Inherits:
Object
  • Object
show all
Includes:
NativeLifecycle
Defined in:
lib/lldb/target.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from NativeLifecycle

#close, #closed?, #context, #context!, #ensure_open!, #initialize_native_object

Constructor Details

#initialize(ptr, debugger:, context: debugger.context) ⇒ Target

Returns a new instance of Target.

RBS:

  • ptr: FFI::Pointer

  • debugger: Debugger

  • return: void



15
16
17
18
19
20
21
22
23
24
25
# File 'lib/lldb/target.rb', line 15

def initialize(ptr, debugger:, context: debugger.context)
  @debugger = debugger
  @breakpoints = [] # : Array[Breakpoint]
  @watchpoints = [] # : Array[Watchpoint]
  @process = nil # : Process?
  initialize_native_object(
    ptr,
    release: ->(released) { FFIBindings.lldb_target_destroy(released) },
    context: context
  )
end

Instance Attribute Details

#debuggerObject (readonly)

RBS:

  • return: Debugger



10
11
12
# File 'lib/lldb/target.rb', line 10

def debugger
  @debugger
end

Class Method Details

.release(ptr) ⇒ Object

RBS:

  • ptr: FFI::Pointer

  • return: ^(Integer) -> void



29
30
31
# File 'lib/lldb/target.rb', line 29

def self.release(ptr)
  ->(_id) { FFIBindings.lldb_target_destroy(ptr) unless ptr.null? }
end

Instance Method Details

#address_byte_sizeObject

RBS:

  • return: Integer



342
343
344
345
346
# File 'lib/lldb/target.rb', line 342

def address_byte_size
  return 0 unless valid?

  FFIBindings.lldb_target_get_address_byte_size(@ptr)
end

#attach(pid:) ⇒ Object

RBS:

  • pid: Integer

  • return: Process

Raises:



70
71
72
73
74
75
76
77
78
79
80
# File 'lib/lldb/target.rb', line 70

def attach(pid:)
  raise InvalidObjectError, 'Target is not valid' unless valid?

  error = Error.new
  process_ptr = FFIBindings.lldb_target_attach_to_process_with_id(@ptr, pid, error.to_ptr)

  error.raise_if_error!
  raise AttachError, "Failed to attach to process #{pid}" if process_ptr.nil? || process_ptr.null?

  @process = Process.new(process_ptr, target: self, context: context)
end

#attach_with_info(attach_info) ⇒ Object

RBS:

  • attach_info: AttachInfo

  • return: Process

Raises:



84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/lldb/target.rb', line 84

def attach_with_info(attach_info)
  raise InvalidObjectError, 'Target is not valid' unless valid?
  raise ArgumentError, 'attach_info is required' unless attach_info.is_a?(AttachInfo)

  error = Error.new
  process_ptr = FFIBindings.lldb_target_attach_with_info(@ptr, attach_info.to_ptr, error.to_ptr)

  error.raise_if_error!('target.attach')
  raise AttachError, 'Failed to attach using attach info' if process_ptr.nil? || process_ptr.null?

  @process = Process.new(process_ptr, target: self, context: context)
end

#attach_with_name(name, wait_for: false) ⇒ Object

RBS:

  • name: String

  • wait_for: bool

  • return: Process

Raises:



240
241
242
243
244
245
246
247
248
249
250
# File 'lib/lldb/target.rb', line 240

def attach_with_name(name, wait_for: false)
  raise InvalidObjectError, 'Target is not valid' unless valid?

  error = Error.new
  process_ptr = FFIBindings.lldb_target_attach_to_process_with_name(@ptr, name, wait_for ? 1 : 0, error.to_ptr)

  error.raise_if_error!
  raise AttachError, "Failed to attach to process '#{name}'" if process_ptr.nil? || process_ptr.null?

  @process = Process.new(process_ptr, target: self, context: context)
end

#breakpoint_at_index(index) ⇒ Object

RBS:

  • index: Integer

  • return: Breakpoint?

Raises:



173
174
175
176
177
178
179
180
# File 'lib/lldb/target.rb', line 173

def breakpoint_at_index(index)
  raise InvalidObjectError, 'Target is not valid' unless valid?

  bp_ptr = FFIBindings.lldb_target_get_breakpoint_at_index(@ptr, index)
  return nil if bp_ptr.nil? || bp_ptr.null?

  Breakpoint.new(bp_ptr, target: self, context: context)
end

#breakpoint_create_by_address(address) ⇒ Object

RBS:

  • address: Integer

  • return: Breakpoint

Raises:



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/lldb/target.rb', line 127

def breakpoint_create_by_address(address)
  raise InvalidObjectError, 'Target is not valid' unless valid?
  APISupport.require_method!(:lldb_target_breakpoint_create_by_address,
                             'breakpoint_create_by_address')

  bp_ptr = FFIBindings.lldb_target_breakpoint_create_by_address(@ptr, address)
  if bp_ptr.nil? || bp_ptr.null?
    raise BreakpointError,
          "Failed to create breakpoint at address 0x#{address.to_s(16)}"
  end

  bp = Breakpoint.new(bp_ptr, target: self, context: context)
  @breakpoints << bp
  bp
end

#breakpoint_create_by_location(file, line) ⇒ Object

RBS:

  • file: String

  • line: Integer

  • return: Breakpoint

Raises:



114
115
116
117
118
119
120
121
122
123
# File 'lib/lldb/target.rb', line 114

def breakpoint_create_by_location(file, line)
  raise InvalidObjectError, 'Target is not valid' unless valid?

  bp_ptr = FFIBindings.lldb_target_breakpoint_create_by_location(@ptr, file, line)
  raise BreakpointError, "Failed to create breakpoint at #{file}:#{line}" if bp_ptr.nil? || bp_ptr.null?

  bp = Breakpoint.new(bp_ptr, target: self, context: context)
  @breakpoints << bp
  bp
end

#breakpoint_create_by_name(symbol_name, module_name: nil) ⇒ Object

RBS:

  • symbol_name: String

  • module_name: String?

  • return: Breakpoint

Raises:



100
101
102
103
104
105
106
107
108
109
# File 'lib/lldb/target.rb', line 100

def breakpoint_create_by_name(symbol_name, module_name: nil)
  raise InvalidObjectError, 'Target is not valid' unless valid?

  bp_ptr = FFIBindings.lldb_target_breakpoint_create_by_name(@ptr, symbol_name, module_name)
  raise BreakpointError, "Failed to create breakpoint for '#{symbol_name}'" if bp_ptr.nil? || bp_ptr.null?

  bp = Breakpoint.new(bp_ptr, target: self, context: context)
  @breakpoints << bp
  bp
end

#breakpoint_create_by_regex(regex, module_name: nil) ⇒ Object

RBS:

  • regex: String

  • module_name: String?

  • return: Breakpoint

Raises:



255
256
257
258
259
260
261
262
263
264
265
266
# File 'lib/lldb/target.rb', line 255

def breakpoint_create_by_regex(regex, module_name: nil)
  raise InvalidObjectError, 'Target is not valid' unless valid?
  APISupport.require_method!(:lldb_target_breakpoint_create_by_regex,
                             'breakpoint_create_by_regex')

  bp_ptr = FFIBindings.lldb_target_breakpoint_create_by_regex(@ptr, regex, module_name)
  raise BreakpointError, "Failed to create breakpoint for regex '#{regex}'" if bp_ptr.nil? || bp_ptr.null?

  bp = Breakpoint.new(bp_ptr, target: self, context: context)
  @breakpoints << bp
  bp
end

#breakpoint_create_by_source_regex(regex, source_file: nil) ⇒ Object

RBS:

  • regex: String

  • source_file: String?

  • return: Breakpoint

Raises:



271
272
273
274
275
276
277
278
279
280
# File 'lib/lldb/target.rb', line 271

def breakpoint_create_by_source_regex(regex, source_file: nil)
  raise InvalidObjectError, 'Target is not valid' unless valid?

  bp_ptr = FFIBindings.lldb_target_breakpoint_create_by_source_regex(@ptr, regex, source_file)
  raise BreakpointError, "Failed to create breakpoint for source regex '#{regex}'" if bp_ptr.nil? || bp_ptr.null?

  bp = Breakpoint.new(bp_ptr, target: self, context: context)
  @breakpoints << bp
  bp
end

#breakpointsObject

RBS:

  • return: Array[Breakpoint]



183
184
185
# File 'lib/lldb/target.rb', line 183

def breakpoints
  (0...num_breakpoints).map { |i| breakpoint_at_index(i) }.compact
end

#delete_all_breakpointsObject

RBS:

  • return: bool

Raises:



283
284
285
286
287
288
289
# File 'lib/lldb/target.rb', line 283

def delete_all_breakpoints
  raise InvalidObjectError, 'Target is not valid' unless valid?

  result = FFIBindings.lldb_target_delete_all_breakpoints(@ptr) != 0
  @breakpoints.clear if result
  result
end

#delete_all_watchpointsObject

RBS:

  • return: bool

Raises:



385
386
387
388
389
390
391
# File 'lib/lldb/target.rb', line 385

def delete_all_watchpoints
  raise InvalidObjectError, 'Target is not valid' unless valid?

  result = FFIBindings.lldb_target_delete_all_watchpoints(@ptr) != 0
  @watchpoints.clear if result
  result
end

#delete_breakpoint(breakpoint_id) ⇒ Object

RBS:

  • breakpoint_id: Integer

  • return: bool

Raises:



145
146
147
148
149
150
151
# File 'lib/lldb/target.rb', line 145

def delete_breakpoint(breakpoint_id)
  raise InvalidObjectError, 'Target is not valid' unless valid?

  result = FFIBindings.lldb_target_delete_breakpoint(@ptr, breakpoint_id)
  @breakpoints.reject! { |bp| bp.id == breakpoint_id } if result != 0
  result != 0
end

#delete_watchpoint(watchpoint_id) ⇒ Object

RBS:

  • watchpoint_id: Integer

  • return: bool

Raises:



376
377
378
379
380
381
382
# File 'lib/lldb/target.rb', line 376

def delete_watchpoint(watchpoint_id)
  raise InvalidObjectError, 'Target is not valid' unless valid?

  result = FFIBindings.lldb_target_delete_watchpoint(@ptr, watchpoint_id)
  @watchpoints.reject! { |wp| wp.id == watchpoint_id } if result != 0
  result != 0
end

#disable_all_breakpointsObject

RBS:

  • return: bool

Raises:



299
300
301
302
303
# File 'lib/lldb/target.rb', line 299

def disable_all_breakpoints
  raise InvalidObjectError, 'Target is not valid' unless valid?

  FFIBindings.lldb_target_disable_all_breakpoints(@ptr) != 0
end

#enable_all_breakpointsObject

RBS:

  • return: bool

Raises:



292
293
294
295
296
# File 'lib/lldb/target.rb', line 292

def enable_all_breakpoints
  raise InvalidObjectError, 'Target is not valid' unless valid?

  FFIBindings.lldb_target_enable_all_breakpoints(@ptr) != 0
end

#evaluate_expression(expression, options: nil) ⇒ Object

RBS:

  • expression: String

  • options: ExpressionOptions?

  • return: Value?

Raises:



308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
# File 'lib/lldb/target.rb', line 308

def evaluate_expression(expression, options: nil)
  raise InvalidObjectError, 'Target is not valid' unless valid?

  value_ptr = if options
                unless options.is_a?(ExpressionOptions)
                  raise ArgumentError, 'options must be an ExpressionOptions'
                end

                FFIBindings.lldb_target_evaluate_expression_with_options(
                  @ptr, expression, options.to_ptr
                )
              else
                FFIBindings.lldb_target_evaluate_expression(@ptr, expression)
              end
  return nil if value_ptr.nil? || value_ptr.null?

  Value.new(value_ptr, parent: self, context: context)
end

#executable_fileObject

RBS:

  • return: FileSpec?

Raises:



205
206
207
208
209
210
211
212
# File 'lib/lldb/target.rb', line 205

def executable_file
  raise InvalidObjectError, 'Target is not valid' unless valid?

  file_ptr = FFIBindings.lldb_target_get_executable_file(@ptr)
  return nil if file_ptr.nil? || file_ptr.null?

  FileSpec.from_ptr(file_ptr, context: context)
end

#executable_pathObject

RBS:

  • return: String?

Raises:



198
199
200
201
202
# File 'lib/lldb/target.rb', line 198

def executable_path
  raise InvalidObjectError, 'Target is not valid' unless valid?

  executable_file&.path
end

#find_breakpoint_by_id(id) ⇒ Object

RBS:

  • id: Integer

  • return: Breakpoint?

Raises:



155
156
157
158
159
160
161
162
# File 'lib/lldb/target.rb', line 155

def find_breakpoint_by_id(id)
  raise InvalidObjectError, 'Target is not valid' unless valid?

  bp_ptr = FFIBindings.lldb_target_find_breakpoint_by_id(@ptr, id)
  return nil if bp_ptr.nil? || bp_ptr.null?

  Breakpoint.new(bp_ptr, target: self, context: context)
end

#find_watchpoint_by_id(id) ⇒ Object

RBS:

  • id: Integer

  • return: Watchpoint?

Raises:



395
396
397
398
399
400
401
402
# File 'lib/lldb/target.rb', line 395

def find_watchpoint_by_id(id)
  raise InvalidObjectError, 'Target is not valid' unless valid?

  wp_ptr = FFIBindings.lldb_target_find_watchpoint_by_id(@ptr, id)
  return nil if wp_ptr.nil? || wp_ptr.null?

  Watchpoint.new(wp_ptr, target: self, context: context)
end

#launch(args: nil, env: nil, working_dir: nil, launch_flags: nil) ⇒ Object

RBS:

  • args: Array[String]?

  • env: Hash[String, String]?

  • working_dir: String?

  • launch_flags: Integer?

  • return: Process

Raises:



43
44
45
46
47
48
49
50
51
# File 'lib/lldb/target.rb', line 43

def launch(args: nil, env: nil, working_dir: nil, launch_flags: nil)
  raise InvalidObjectError, 'Target is not valid' unless valid?

  launch_info = LaunchInfo.new(args, context: context)
  launch_info.launch_flags = launch_flags unless launch_flags.nil?
  launch_info.working_directory = working_dir if working_dir
  launch_info.set_environment(env) if env
  launch_with_info(launch_info)
end

#launch_with_info(launch_info) ⇒ Object

RBS:

  • launch_info: LaunchInfo

  • return: Process

Raises:



55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/lldb/target.rb', line 55

def launch_with_info(launch_info)
  raise InvalidObjectError, 'Target is not valid' unless valid?
  raise ArgumentError, 'launch_info is required' unless launch_info

  error = Error.new
  process_ptr = FFIBindings.lldb_target_launch(@ptr, launch_info.to_ptr, error.to_ptr)

  error.raise_if_error!('target.launch')
  raise LaunchError, 'Failed to launch process' if process_ptr.nil? || process_ptr.null?

  @process = Process.new(process_ptr, target: self, context: context)
end

#module_at_index(index) ⇒ Object

RBS:

  • index: Integer

  • return: Module?

Raises:



223
224
225
226
227
228
229
230
# File 'lib/lldb/target.rb', line 223

def module_at_index(index)
  raise InvalidObjectError, 'Target is not valid' unless valid?

  mod_ptr = FFIBindings.lldb_target_get_module_at_index(@ptr, index)
  return nil if mod_ptr.nil? || mod_ptr.null?

  Module.new(mod_ptr, target: self, context: context)
end

#modulesObject

RBS:

  • return: Array[Module]



233
234
235
# File 'lib/lldb/target.rb', line 233

def modules
  (0...num_modules).map { |i| module_at_index(i) }.compact
end

#num_breakpointsObject

RBS:

  • return: Integer



165
166
167
168
169
# File 'lib/lldb/target.rb', line 165

def num_breakpoints
  return 0 unless valid?

  FFIBindings.lldb_target_get_num_breakpoints(@ptr)
end

#num_modulesObject

RBS:

  • return: Integer



215
216
217
218
219
# File 'lib/lldb/target.rb', line 215

def num_modules
  return 0 unless valid?

  FFIBindings.lldb_target_get_num_modules(@ptr)
end

#num_watchpointsObject

RBS:

  • return: Integer



405
406
407
408
409
# File 'lib/lldb/target.rb', line 405

def num_watchpoints
  return 0 unless valid?

  FFIBindings.lldb_target_get_num_watchpoints(@ptr)
end

#processObject

RBS:

  • return: Process?

Raises:



188
189
190
191
192
193
194
195
# File 'lib/lldb/target.rb', line 188

def process
  raise InvalidObjectError, 'Target is not valid' unless valid?

  process_ptr = FFIBindings.lldb_target_get_process(@ptr)
  return nil if process_ptr.nil? || process_ptr.null?

  Process.new(process_ptr, target: self, context: context)
end

#read_memory(address, size) ⇒ Object

RBS:

  • address: Integer

  • size: Integer

  • return: String

Raises:



330
331
332
333
334
335
336
337
338
339
# File 'lib/lldb/target.rb', line 330

def read_memory(address, size)
  raise InvalidObjectError, 'Target is not valid' unless valid?

  buffer = FFI::MemoryPointer.new(:uint8, size)
  error = Error.new
  bytes_read = FFIBindings.lldb_target_read_memory(@ptr, address, buffer, size, error.to_ptr)

  error.raise_if_error!
  buffer.read_string(bytes_read)
end

#to_ptrObject

RBS:

  • return: FFI::Pointer



428
429
430
# File 'lib/lldb/target.rb', line 428

def to_ptr
  @ptr
end

#tripleObject

RBS:

  • return: String?



349
350
351
352
353
# File 'lib/lldb/target.rb', line 349

def triple
  return nil unless valid?

  FFIBindings.lldb_target_get_triple(@ptr)
end

#valid?Boolean

RBS:

  • return: bool

Returns:

  • (Boolean)


34
35
36
# File 'lib/lldb/target.rb', line 34

def valid?
  !@ptr.null? && FFIBindings.lldb_target_is_valid(@ptr) != 0
end

#watch_address(address, size, read: false, write: true) ⇒ Object

RBS:

  • address: Integer

  • size: Integer

  • read: bool

  • write: bool

  • return: Watchpoint

Raises:



360
361
362
363
364
365
366
367
368
369
370
371
372
# File 'lib/lldb/target.rb', line 360

def watch_address(address, size, read: false, write: true)
  raise InvalidObjectError, 'Target is not valid' unless valid?

  error = Error.new
  wp_ptr = FFIBindings.lldb_target_watch_address(@ptr, address, size, read ? 1 : 0, write ? 1 : 0, error.to_ptr)

  error.raise_if_error!
  raise LLDBError, "Failed to create watchpoint at address 0x#{address.to_s(16)}" if wp_ptr.nil? || wp_ptr.null?

  wp = Watchpoint.new(wp_ptr, target: self, context: context)
  @watchpoints << wp
  wp
end

#watchpoint_at_index(index) ⇒ Object

RBS:

  • index: Integer

  • return: Watchpoint?

Raises:



413
414
415
416
417
418
419
420
# File 'lib/lldb/target.rb', line 413

def watchpoint_at_index(index)
  raise InvalidObjectError, 'Target is not valid' unless valid?

  wp_ptr = FFIBindings.lldb_target_get_watchpoint_at_index(@ptr, index)
  return nil if wp_ptr.nil? || wp_ptr.null?

  Watchpoint.new(wp_ptr, target: self, context: context)
end

#watchpointsObject

RBS:

  • return: Array[Watchpoint]



423
424
425
# File 'lib/lldb/target.rb', line 423

def watchpoints
  (0...num_watchpoints).map { |i| watchpoint_at_index(i) }.compact
end