lldb 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +43 -4
  3. data/README.md +86 -2
  4. data/Rakefile +36 -0
  5. data/bindings/constants.yml +137 -0
  6. data/bindings/surface.yml +3072 -0
  7. data/ext/lldb/discovery.rb +101 -0
  8. data/ext/lldb/extconf.rb +206 -88
  9. data/ext/lldb/lldb_wrapper.cpp +7934 -877
  10. data/ext/lldb/lldb_wrapper.h +596 -333
  11. data/lib/lldb/address.rb +81 -0
  12. data/lib/lldb/api_support.rb +23 -6
  13. data/lib/lldb/attach_info.rb +122 -0
  14. data/lib/lldb/block.rb +121 -0
  15. data/lib/lldb/breakpoint.rb +11 -6
  16. data/lib/lldb/breakpoint_location.rb +20 -5
  17. data/lib/lldb/broadcaster.rb +79 -0
  18. data/lib/lldb/command_interpreter.rb +9 -4
  19. data/lib/lldb/command_return_object.rb +24 -5
  20. data/lib/lldb/compile_unit.rb +64 -0
  21. data/lib/lldb/context.rb +81 -0
  22. data/lib/lldb/debugger.rb +55 -12
  23. data/lib/lldb/error.rb +50 -3
  24. data/lib/lldb/event.rb +109 -0
  25. data/lib/lldb/expression_options.rb +124 -0
  26. data/lib/lldb/ffi_bindings.rb +313 -31
  27. data/lib/lldb/file_spec.rb +90 -0
  28. data/lib/lldb/file_spec_list.rb +78 -0
  29. data/lib/lldb/frame.rb +109 -17
  30. data/lib/lldb/function.rb +121 -0
  31. data/lib/lldb/instruction.rb +83 -0
  32. data/lib/lldb/instruction_list.rb +68 -0
  33. data/lib/lldb/launch_info.rb +145 -19
  34. data/lib/lldb/line_entry.rb +75 -0
  35. data/lib/lldb/listener.rb +96 -0
  36. data/lib/lldb/memory_region_info.rb +8 -3
  37. data/lib/lldb/module.rb +46 -5
  38. data/lib/lldb/native.rb +36 -0
  39. data/lib/lldb/native_buffer.rb +32 -0
  40. data/lib/lldb/native_handle.rb +60 -0
  41. data/lib/lldb/native_lifecycle.rb +64 -0
  42. data/lib/lldb/native_string_array.rb +34 -0
  43. data/lib/lldb/process.rb +102 -40
  44. data/lib/lldb/symbol.rb +117 -0
  45. data/lib/lldb/symbol_context.rb +9 -4
  46. data/lib/lldb/target.rb +69 -67
  47. data/lib/lldb/thread.rb +51 -18
  48. data/lib/lldb/type.rb +40 -3
  49. data/lib/lldb/type_member.rb +67 -0
  50. data/lib/lldb/types.rb +69 -4
  51. data/lib/lldb/value.rb +27 -17
  52. data/lib/lldb/value_list.rb +9 -5
  53. data/lib/lldb/version.rb +1 -1
  54. data/lib/lldb/watchpoint.rb +26 -9
  55. data/lib/lldb.rb +78 -10
  56. data/lldb.gemspec +4 -1
  57. data/rbs_collection.yaml +1 -1
  58. data/script/check_bindings +259 -0
  59. data/script/guard_c_exports +139 -0
  60. data/sig/lldb/ffi_bindings.rbs +247 -21
  61. data/sig/lldb/weak_ref.rbs +7 -0
  62. metadata +30 -6
  63. data/ext/lldb/Makefile +0 -24
  64. data/ext/lldb/liblldb_wrapper.dylib +0 -0
  65. data/ext/lldb/lldb_wrapper.o +0 -0
  66. data/ext/lldb/mkmf.log +0 -24
data/lib/lldb/process.rb CHANGED
@@ -4,16 +4,30 @@
4
4
 
5
5
  module LLDB
6
6
  class Process
7
- # @rbs return: Target
7
+ prepend NativeLifecycle
8
+
9
+ module BroadcastBit
10
+ STATE_CHANGED = 1 << 0
11
+ INTERRUPT = 1 << 1
12
+ STDOUT = 1 << 2
13
+ STDERR = 1 << 3
14
+ PROFILE_DATA = 1 << 4
15
+ STRUCTURED_DATA = 1 << 5
16
+ end
17
+
18
+ # @rbs return: Target?
8
19
  attr_reader :target
9
20
 
10
21
  # @rbs ptr: FFI::Pointer
11
- # @rbs target: Target
22
+ # @rbs target: Target?
12
23
  # @rbs return: void
13
- def initialize(ptr, target:)
14
- @ptr = ptr # : FFI::Pointer
24
+ def initialize(ptr, target: nil, context: target&.context)
15
25
  @target = target
16
- ObjectSpace.define_finalizer(self, self.class.release(@ptr))
26
+ initialize_native_object(
27
+ ptr,
28
+ release: ->(released) { FFIBindings.lldb_process_destroy(released) },
29
+ context: context
30
+ )
17
31
  end
18
32
 
19
33
  # @rbs ptr: FFI::Pointer
@@ -27,32 +41,34 @@ module LLDB
27
41
  !@ptr.null? && FFIBindings.lldb_process_is_valid(@ptr) != 0
28
42
  end
29
43
 
30
- # @rbs return: bool
44
+ # @rbs return: true
31
45
  def continue
32
46
  raise InvalidObjectError, 'Process is not valid' unless valid?
33
47
 
34
- FFIBindings.lldb_process_continue(@ptr) != 0
48
+ native_operation('process.continue') do |error|
49
+ FFIBindings.lldb_process_continue(@ptr, error.to_ptr)
50
+ end
35
51
  end
36
52
 
37
- # @rbs return: bool
53
+ # @rbs return: true
38
54
  def stop
39
55
  raise InvalidObjectError, 'Process is not valid' unless valid?
40
56
 
41
- FFIBindings.lldb_process_stop(@ptr) != 0
57
+ native_operation('process.stop') { |error| FFIBindings.lldb_process_stop(@ptr, error.to_ptr) }
42
58
  end
43
59
 
44
- # @rbs return: bool
60
+ # @rbs return: true
45
61
  def kill
46
62
  raise InvalidObjectError, 'Process is not valid' unless valid?
47
63
 
48
- FFIBindings.lldb_process_kill(@ptr) != 0
64
+ native_operation('process.kill') { |error| FFIBindings.lldb_process_kill(@ptr, error.to_ptr) }
49
65
  end
50
66
 
51
- # @rbs return: bool
67
+ # @rbs return: true
52
68
  def detach
53
69
  raise InvalidObjectError, 'Process is not valid' unless valid?
54
70
 
55
- FFIBindings.lldb_process_detach(@ptr) != 0
71
+ native_operation('process.detach') { |error| FFIBindings.lldb_process_detach(@ptr, error.to_ptr) }
56
72
  end
57
73
 
58
74
  # @rbs return: Integer
@@ -102,7 +118,7 @@ module LLDB
102
118
  thread_ptr = FFIBindings.lldb_process_get_thread_at_index(@ptr, index)
103
119
  return nil if thread_ptr.nil? || thread_ptr.null?
104
120
 
105
- Thread.new(thread_ptr, process: self)
121
+ Thread.new(thread_ptr, process: self, context: context)
106
122
  end
107
123
 
108
124
  # @rbs return: Thread?
@@ -112,7 +128,7 @@ module LLDB
112
128
  thread_ptr = FFIBindings.lldb_process_get_selected_thread(@ptr)
113
129
  return nil if thread_ptr.nil? || thread_ptr.null?
114
130
 
115
- Thread.new(thread_ptr, process: self)
131
+ Thread.new(thread_ptr, process: self, context: context)
116
132
  end
117
133
 
118
134
  # @rbs thread_id: Integer
@@ -151,19 +167,23 @@ module LLDB
151
167
  FFIBindings.lldb_process_get_exit_description(@ptr)
152
168
  end
153
169
 
154
- # @rbs return: bool
170
+ # @rbs return: true
155
171
  def destroy
156
172
  raise InvalidObjectError, 'Process is not valid' unless valid?
157
173
 
158
- FFIBindings.lldb_process_destroy_process(@ptr) != 0
174
+ native_operation('process.destroy') do |error|
175
+ FFIBindings.lldb_process_destroy_process(@ptr, error.to_ptr)
176
+ end
159
177
  end
160
178
 
161
179
  # @rbs signal: Integer
162
- # @rbs return: bool
180
+ # @rbs return: true
163
181
  def signal(signal)
164
182
  raise InvalidObjectError, 'Process is not valid' unless valid?
165
183
 
166
- FFIBindings.lldb_process_signal(@ptr, signal) != 0
184
+ native_operation('process.signal') do |error|
185
+ FFIBindings.lldb_process_signal(@ptr, signal, error.to_ptr)
186
+ end
167
187
  end
168
188
 
169
189
  # @rbs thread_id: Integer
@@ -175,7 +195,7 @@ module LLDB
175
195
  thread_ptr = FFIBindings.lldb_process_get_thread_by_id(@ptr, thread_id)
176
196
  return nil if thread_ptr.nil? || thread_ptr.null?
177
197
 
178
- Thread.new(thread_ptr, process: self)
198
+ Thread.new(thread_ptr, process: self, context: context)
179
199
  end
180
200
 
181
201
  # @rbs index_id: Integer
@@ -186,7 +206,7 @@ module LLDB
186
206
  thread_ptr = FFIBindings.lldb_process_get_thread_by_index_id(@ptr, index_id)
187
207
  return nil if thread_ptr.nil? || thread_ptr.null?
188
208
 
189
- Thread.new(thread_ptr, process: self)
209
+ Thread.new(thread_ptr, process: self, context: context)
190
210
  end
191
211
 
192
212
  # @rbs index_id: Integer
@@ -208,8 +228,8 @@ module LLDB
208
228
  error = Error.new
209
229
  bytes_read = FFIBindings.lldb_process_read_memory(@ptr, address, buffer, size, error.to_ptr)
210
230
 
211
- error.raise_if_error!
212
- buffer.read_string(bytes_read)
231
+ error.raise_if_error!('process.read_memory')
232
+ buffer.get_bytes(0, bytes_read)
213
233
  end
214
234
 
215
235
  # @rbs address: Integer
@@ -219,11 +239,12 @@ module LLDB
219
239
  raise InvalidObjectError, 'Process is not valid' unless valid?
220
240
  APISupport.require_method!(:lldb_process_write_memory, 'write_memory')
221
241
 
222
- buffer = FFI::MemoryPointer.from_string(data)
242
+ buffer = FFI::MemoryPointer.new(:uint8, [data.bytesize, 1].max)
243
+ buffer.put_bytes(0, data)
223
244
  error = Error.new
224
245
  bytes_written = FFIBindings.lldb_process_write_memory(@ptr, address, buffer, data.bytesize, error.to_ptr)
225
246
 
226
- error.raise_if_error!
247
+ error.raise_if_error!('process.write_memory')
227
248
  bytes_written
228
249
  end
229
250
 
@@ -236,16 +257,18 @@ module LLDB
236
257
  error = Error.new
237
258
  address = FFIBindings.lldb_process_allocate_memory(@ptr, size, permissions, error.to_ptr)
238
259
 
239
- error.raise_if_error!
260
+ error.raise_if_error!('process.allocate_memory')
240
261
  address
241
262
  end
242
263
 
243
264
  # @rbs address: Integer
244
- # @rbs return: bool
265
+ # @rbs return: true
245
266
  def deallocate_memory(address)
246
267
  raise InvalidObjectError, 'Process is not valid' unless valid?
247
268
 
248
- FFIBindings.lldb_process_deallocate_memory(@ptr, address) != 0
269
+ native_operation('process.deallocate_memory') do |error|
270
+ FFIBindings.lldb_process_deallocate_memory(@ptr, address, error.to_ptr)
271
+ end
249
272
  end
250
273
 
251
274
  # @rbs address: Integer
@@ -253,13 +276,21 @@ module LLDB
253
276
  # @rbs return: String
254
277
  def read_cstring_from_memory(address, max_size = 1024)
255
278
  raise InvalidObjectError, 'Process is not valid' unless valid?
279
+ raise ArgumentError, 'max_size must be non-negative' if max_size.negative?
256
280
 
257
- buffer = FFI::MemoryPointer.new(:uint8, max_size)
281
+ buffer = FFI::MemoryPointer.new(:uint8, [max_size, 1].max)
258
282
  error = Error.new
259
- FFIBindings.lldb_process_read_cstring_from_memory(@ptr, address, buffer, max_size, error.to_ptr)
283
+ bytes_read = FFIBindings.lldb_process_read_cstring_from_memory(
284
+ @ptr,
285
+ address,
286
+ buffer,
287
+ max_size,
288
+ error.to_ptr
289
+ )
260
290
 
261
- error.raise_if_error!
262
- buffer.read_string
291
+ error.raise_if_error!('process.read_cstring_from_memory')
292
+ bytes = buffer.get_bytes(0, [bytes_read, max_size].min)
293
+ bytes.delete_suffix("\0")
263
294
  end
264
295
 
265
296
  # @rbs max_size: Integer
@@ -269,7 +300,7 @@ module LLDB
269
300
 
270
301
  buffer = FFI::MemoryPointer.new(:uint8, max_size)
271
302
  bytes_read = FFIBindings.lldb_process_get_stdout(@ptr, buffer, max_size)
272
- buffer.read_string(bytes_read)
303
+ buffer.get_bytes(0, bytes_read)
273
304
  end
274
305
 
275
306
  # @rbs max_size: Integer
@@ -279,7 +310,7 @@ module LLDB
279
310
 
280
311
  buffer = FFI::MemoryPointer.new(:uint8, max_size)
281
312
  bytes_read = FFIBindings.lldb_process_get_stderr(@ptr, buffer, max_size)
282
- buffer.read_string(bytes_read)
313
+ buffer.get_bytes(0, bytes_read)
283
314
  end
284
315
 
285
316
  # @rbs data: String
@@ -287,22 +318,42 @@ module LLDB
287
318
  def put_stdin(data)
288
319
  raise InvalidObjectError, 'Process is not valid' unless valid?
289
320
 
290
- FFIBindings.lldb_process_put_stdin(@ptr, data, data.bytesize)
321
+ buffer = FFI::MemoryPointer.new(:uint8, [data.bytesize, 1].max)
322
+ buffer.put_bytes(0, data)
323
+ FFIBindings.lldb_process_put_stdin(@ptr, buffer, data.bytesize)
291
324
  end
292
325
 
293
- # @rbs return: bool
326
+ # @rbs return: nil
294
327
  def send_async_interrupt
295
328
  raise InvalidObjectError, 'Process is not valid' unless valid?
296
329
 
297
- FFIBindings.lldb_process_send_async_interrupt(@ptr) != 0
330
+ FFIBindings.lldb_process_send_async_interrupt(@ptr)
331
+ nil
332
+ end
333
+
334
+ # @rbs return: Broadcaster
335
+ def broadcaster
336
+ raise InvalidObjectError, 'Process is not valid' unless valid?
337
+
338
+ broadcaster_ptr = FFIBindings.lldb_process_get_broadcaster(@ptr)
339
+ raise LLDBError, 'Failed to get process broadcaster' if broadcaster_ptr.nil? || broadcaster_ptr.null?
340
+
341
+ Broadcaster.from_ptr(broadcaster_ptr, context: context)
298
342
  end
299
343
 
300
344
  # @rbs return: Integer
301
345
  def num_supported_hardware_watchpoints
302
346
  return 0 unless valid?
303
347
 
348
+ result = FFI::MemoryPointer.new(:uint32)
304
349
  error = Error.new
305
- FFIBindings.lldb_process_get_num_supported_hardware_watchpoints(@ptr, error.to_ptr)
350
+ status = FFIBindings.lldb_process_get_num_supported_hardware_watchpoints(
351
+ @ptr,
352
+ result,
353
+ error.to_ptr
354
+ )
355
+ Native.check_status!(status, 'process.num_supported_hardware_watchpoints', error)
356
+ result.read_uint32
306
357
  end
307
358
 
308
359
  # @rbs return: Integer
@@ -324,15 +375,26 @@ module LLDB
324
375
  error = Error.new
325
376
  info_ptr = FFIBindings.lldb_process_get_memory_region_info(@ptr, address, error.to_ptr)
326
377
 
327
- error.raise_if_error!
378
+ error.raise_if_error!('process.get_memory_region_info')
328
379
  return nil if info_ptr.nil? || info_ptr.null?
329
380
 
330
- MemoryRegionInfo.new(info_ptr)
381
+ MemoryRegionInfo.new(info_ptr, context: context)
331
382
  end
332
383
 
333
384
  # @rbs return: FFI::Pointer
334
385
  def to_ptr
335
386
  @ptr
336
387
  end
388
+
389
+ private
390
+
391
+ # @rbs operation: String
392
+ # @rbs &block: (Error) -> Integer
393
+ # @rbs return: true
394
+ def native_operation(operation, &block)
395
+ error = Error.new
396
+ Native.check_status!(yield(error), operation, error)
397
+ true
398
+ end
337
399
  end
338
400
  end
@@ -0,0 +1,117 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rbs_inline: enabled
4
+
5
+ module LLDB
6
+ class Symbol
7
+ prepend NativeLifecycle
8
+
9
+ # @rbs target: Target?
10
+ # @rbs context: Context?
11
+ # @rbs return: void
12
+ def initialize(ptr, target: nil, context: nil)
13
+ @target = target
14
+ initialize_native_object(
15
+ ptr,
16
+ release: ->(released) { FFIBindings.lldb_symbol_destroy(released) },
17
+ context: context || target&.context
18
+ )
19
+ end
20
+
21
+ # @rbs return: bool
22
+ def valid?
23
+ !@ptr.null? && FFIBindings.lldb_symbol_is_valid(@ptr) != 0
24
+ end
25
+
26
+ # @rbs return: String?
27
+ def name
28
+ return nil unless valid?
29
+
30
+ FFIBindings.lldb_symbol_get_name(@ptr)
31
+ end
32
+
33
+ # @rbs return: String?
34
+ def display_name
35
+ return nil unless valid?
36
+
37
+ FFIBindings.lldb_symbol_get_display_name(@ptr)
38
+ end
39
+
40
+ # @rbs return: String?
41
+ def mangled_name
42
+ return nil unless valid?
43
+
44
+ FFIBindings.lldb_symbol_get_mangled_name(@ptr)
45
+ end
46
+
47
+ # @rbs return: String?
48
+ def base_name
49
+ return nil unless valid?
50
+
51
+ FFIBindings.lldb_symbol_get_base_name(@ptr)
52
+ end
53
+
54
+ # @rbs return: Address?
55
+ def start_address
56
+ address_at(:lldb_symbol_get_start_address)
57
+ end
58
+
59
+ # @rbs return: Address?
60
+ def end_address
61
+ address_at(:lldb_symbol_get_end_address)
62
+ end
63
+
64
+ # @rbs return: Integer
65
+ def value
66
+ return INVALID_ADDRESS unless valid?
67
+
68
+ FFIBindings.lldb_symbol_get_value(@ptr)
69
+ end
70
+
71
+ # @rbs return: Integer
72
+ def size
73
+ return 0 unless valid?
74
+
75
+ FFIBindings.lldb_symbol_get_size(@ptr)
76
+ end
77
+
78
+ # @rbs return: Integer
79
+ def prologue_byte_size
80
+ return 0 unless valid?
81
+
82
+ FFIBindings.lldb_symbol_get_prologue_byte_size(@ptr)
83
+ end
84
+
85
+ # @rbs return: Integer
86
+ def type
87
+ return 0 unless valid?
88
+
89
+ FFIBindings.lldb_symbol_get_type(@ptr)
90
+ end
91
+
92
+ # @rbs return: Integer
93
+ def id
94
+ return 0 unless valid?
95
+
96
+ FFIBindings.lldb_symbol_get_id(@ptr)
97
+ end
98
+
99
+ # @rbs return: FFI::Pointer
100
+ def to_ptr
101
+ @ptr
102
+ end
103
+
104
+ private
105
+
106
+ # @rbs method_name: ::Symbol
107
+ # @rbs return: Address?
108
+ def address_at(method_name)
109
+ return nil unless valid?
110
+
111
+ ptr = FFIBindings.public_send(method_name, @ptr)
112
+ return nil if ptr.nil? || ptr.null?
113
+
114
+ Address.from_ptr(ptr, target: @target, context: context)
115
+ end
116
+ end
117
+ end
@@ -4,16 +4,21 @@
4
4
 
5
5
  module LLDB
6
6
  class SymbolContext
7
+ prepend NativeLifecycle
8
+
7
9
  # @rbs return: Frame
8
10
  attr_reader :parent
9
11
 
10
12
  # @rbs ptr: FFI::Pointer
11
13
  # @rbs parent: Frame
12
14
  # @rbs return: void
13
- def initialize(ptr, parent:)
14
- @ptr = ptr # : FFI::Pointer
15
+ def initialize(ptr, parent:, context: parent.context)
15
16
  @parent = parent
16
- ObjectSpace.define_finalizer(self, self.class.release(@ptr))
17
+ initialize_native_object(
18
+ ptr,
19
+ release: ->(released) { FFIBindings.lldb_symbol_context_destroy(released) },
20
+ context: context
21
+ )
17
22
  end
18
23
 
19
24
  # @rbs ptr: FFI::Pointer
@@ -34,7 +39,7 @@ module LLDB
34
39
  mod_ptr = FFIBindings.lldb_symbol_context_get_module(@ptr)
35
40
  return nil if mod_ptr.nil? || mod_ptr.null?
36
41
 
37
- Module.new(mod_ptr, target: nil)
42
+ Module.new(mod_ptr, target: nil, context: context)
38
43
  end
39
44
 
40
45
  # @rbs return: String?