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
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rbs_inline: enabled
4
+
5
+ module LLDB
6
+ class FileSpecList
7
+ prepend NativeLifecycle
8
+
9
+ # @rbs context: Context?
10
+ # @rbs return: void
11
+ def initialize(context: nil)
12
+ initialize_native_object(
13
+ FFIBindings.lldb_file_spec_list_create,
14
+ release: ->(released) { FFIBindings.lldb_file_spec_list_destroy(released) },
15
+ context: context
16
+ )
17
+ end
18
+
19
+ # @rbs return: bool
20
+ def valid?
21
+ !@ptr.null? && FFIBindings.lldb_file_spec_list_is_valid(@ptr) != 0
22
+ end
23
+
24
+ # @rbs return: Integer
25
+ def size
26
+ return 0 unless valid?
27
+
28
+ FFIBindings.lldb_file_spec_list_get_size(@ptr)
29
+ end
30
+
31
+ alias length size
32
+
33
+ # @rbs file_spec: FileSpec
34
+ # @rbs return: void
35
+ def append(file_spec)
36
+ ensure_open!
37
+ raise ArgumentError, 'file_spec must be a FileSpec' unless file_spec.is_a?(FileSpec)
38
+
39
+ FFIBindings.lldb_file_spec_list_append(@ptr, file_spec.to_ptr)
40
+ end
41
+
42
+ # @rbs file_spec: FileSpec
43
+ # @rbs return: bool
44
+ def append_if_unique(file_spec)
45
+ ensure_open!
46
+ raise ArgumentError, 'file_spec must be a FileSpec' unless file_spec.is_a?(FileSpec)
47
+
48
+ FFIBindings.lldb_file_spec_list_append_if_unique(@ptr, file_spec.to_ptr) != 0
49
+ end
50
+
51
+ # @rbs return: void
52
+ def clear
53
+ ensure_open!
54
+ FFIBindings.lldb_file_spec_list_clear(@ptr)
55
+ end
56
+
57
+ # @rbs index: Integer
58
+ # @rbs return: FileSpec?
59
+ def [](index)
60
+ return nil unless valid?
61
+
62
+ ptr = FFIBindings.lldb_file_spec_list_get_file_spec_at_index(@ptr, index)
63
+ return nil if ptr.nil? || ptr.null?
64
+
65
+ FileSpec.from_ptr(ptr, context: context)
66
+ end
67
+
68
+ # @rbs return: Array[FileSpec]
69
+ def to_a
70
+ (0...size).map { |index| self[index] }.compact
71
+ end
72
+
73
+ # @rbs return: FFI::Pointer
74
+ def to_ptr
75
+ @ptr
76
+ end
77
+ end
78
+ end
data/lib/lldb/frame.rb CHANGED
@@ -4,16 +4,21 @@
4
4
 
5
5
  module LLDB
6
6
  class Frame
7
+ prepend NativeLifecycle
8
+
7
9
  # @rbs return: Thread
8
10
  attr_reader :thread
9
11
 
10
12
  # @rbs ptr: FFI::Pointer
11
13
  # @rbs thread: Thread
12
14
  # @rbs return: void
13
- def initialize(ptr, thread:)
14
- @ptr = ptr # : FFI::Pointer
15
+ def initialize(ptr, thread:, context: thread.context)
15
16
  @thread = thread
16
- ObjectSpace.define_finalizer(self, self.class.release(@ptr))
17
+ initialize_native_object(
18
+ ptr,
19
+ release: ->(released) { FFIBindings.lldb_frame_destroy(released) },
20
+ context: context
21
+ )
17
22
  end
18
23
 
19
24
  # @rbs ptr: FFI::Pointer
@@ -52,7 +57,68 @@ module LLDB
52
57
  def file_path
53
58
  raise InvalidObjectError, 'Frame is not valid' unless valid?
54
59
 
55
- FFIBindings.lldb_frame_get_file_path(@ptr)
60
+ file_spec&.path
61
+ end
62
+
63
+ # @rbs return: FileSpec?
64
+ def file_spec
65
+ raise InvalidObjectError, 'Frame is not valid' unless valid?
66
+
67
+ file_ptr = FFIBindings.lldb_frame_get_file_spec(@ptr)
68
+ return nil if file_ptr.nil? || file_ptr.null?
69
+
70
+ FileSpec.from_ptr(file_ptr, context: context)
71
+ end
72
+
73
+ # @rbs return: LineEntry?
74
+ def line_entry
75
+ raise InvalidObjectError, 'Frame is not valid' unless valid?
76
+
77
+ line_ptr = FFIBindings.lldb_frame_get_line_entry(@ptr)
78
+ return nil if line_ptr.nil? || line_ptr.null?
79
+
80
+ target = @thread.process.target
81
+ LineEntry.new(line_ptr, target: target, context: context)
82
+ end
83
+
84
+ # @rbs return: Function?
85
+ def function
86
+ raise InvalidObjectError, 'Frame is not valid' unless valid?
87
+
88
+ function_ptr = FFIBindings.lldb_frame_get_function(@ptr)
89
+ return nil if function_ptr.nil? || function_ptr.null?
90
+
91
+ Function.new(function_ptr, target: @thread.process.target, context: context)
92
+ end
93
+
94
+ # @rbs return: Symbol?
95
+ def symbol
96
+ raise InvalidObjectError, 'Frame is not valid' unless valid?
97
+
98
+ symbol_ptr = FFIBindings.lldb_frame_get_symbol(@ptr)
99
+ return nil if symbol_ptr.nil? || symbol_ptr.null?
100
+
101
+ Symbol.new(symbol_ptr, target: @thread.process.target, context: context)
102
+ end
103
+
104
+ # @rbs return: CompileUnit?
105
+ def compile_unit
106
+ raise InvalidObjectError, 'Frame is not valid' unless valid?
107
+
108
+ unit_ptr = FFIBindings.lldb_frame_get_compile_unit(@ptr)
109
+ return nil if unit_ptr.nil? || unit_ptr.null?
110
+
111
+ CompileUnit.new(unit_ptr, target: @thread.process.target, context: context)
112
+ end
113
+
114
+ # @rbs return: Block?
115
+ def block
116
+ raise InvalidObjectError, 'Frame is not valid' unless valid?
117
+
118
+ block_ptr = FFIBindings.lldb_frame_get_block(@ptr)
119
+ return nil if block_ptr.nil? || block_ptr.null?
120
+
121
+ Block.new(block_ptr, target: @thread.process.target, context: context)
56
122
  end
57
123
 
58
124
  # @rbs return: Integer
@@ -64,21 +130,21 @@ module LLDB
64
130
 
65
131
  # @rbs return: Integer
66
132
  def pc
67
- return 0 unless valid?
133
+ return INVALID_ADDRESS unless valid?
68
134
 
69
135
  FFIBindings.lldb_frame_get_pc(@ptr)
70
136
  end
71
137
 
72
138
  # @rbs return: Integer
73
139
  def sp
74
- return 0 unless valid?
140
+ return INVALID_ADDRESS unless valid?
75
141
 
76
142
  FFIBindings.lldb_frame_get_sp(@ptr)
77
143
  end
78
144
 
79
145
  # @rbs return: Integer
80
146
  def fp
81
- return 0 unless valid?
147
+ return INVALID_ADDRESS unless valid?
82
148
 
83
149
  FFIBindings.lldb_frame_get_fp(@ptr)
84
150
  end
@@ -101,19 +167,30 @@ module LLDB
101
167
  value_ptr = FFIBindings.lldb_frame_find_variable(@ptr, name)
102
168
  return nil if value_ptr.nil? || value_ptr.null?
103
169
 
104
- Value.new(value_ptr, parent: self)
170
+ Value.new(value_ptr, parent: self, context: context)
105
171
  end
106
172
 
107
173
  # @rbs expression: String
174
+ # @rbs options: ExpressionOptions?
108
175
  # @rbs return: Value?
109
- def evaluate_expression(expression)
176
+ def evaluate_expression(expression, options: nil)
110
177
  raise InvalidObjectError, 'Frame is not valid' unless valid?
111
178
  APISupport.require_method!(:lldb_frame_evaluate_expression, 'evaluate_expression')
112
179
 
113
- value_ptr = FFIBindings.lldb_frame_evaluate_expression(@ptr, expression)
180
+ value_ptr = if options
181
+ unless options.is_a?(ExpressionOptions)
182
+ raise ArgumentError, 'options must be an ExpressionOptions'
183
+ end
184
+
185
+ FFIBindings.lldb_frame_evaluate_expression_with_options(
186
+ @ptr, expression, options.to_ptr
187
+ )
188
+ else
189
+ FFIBindings.lldb_frame_evaluate_expression(@ptr, expression)
190
+ end
114
191
  return nil if value_ptr.nil? || value_ptr.null?
115
192
 
116
- Value.new(value_ptr, parent: self)
193
+ Value.new(value_ptr, parent: self, context: context)
117
194
  end
118
195
 
119
196
  # @rbs path: String
@@ -124,7 +201,7 @@ module LLDB
124
201
  value_ptr = FFIBindings.lldb_frame_get_value_for_variable_path(@ptr, path)
125
202
  return nil if value_ptr.nil? || value_ptr.null?
126
203
 
127
- Value.new(value_ptr, parent: self)
204
+ Value.new(value_ptr, parent: self, context: context)
128
205
  end
129
206
 
130
207
  # @rbs scope: Integer
@@ -135,7 +212,7 @@ module LLDB
135
212
  ctx_ptr = FFIBindings.lldb_frame_get_symbol_context(@ptr, scope)
136
213
  return nil if ctx_ptr.nil? || ctx_ptr.null?
137
214
 
138
- SymbolContext.new(ctx_ptr, parent: self)
215
+ SymbolContext.new(ctx_ptr, parent: self, context: context)
139
216
  end
140
217
 
141
218
  # @rbs return: String
@@ -173,7 +250,7 @@ module LLDB
173
250
  )
174
251
  raise LLDBError, 'Failed to get variables' if list_ptr.nil? || list_ptr.null?
175
252
 
176
- ValueList.new(list_ptr, parent: self)
253
+ ValueList.new(list_ptr, parent: self, context: context)
177
254
  end
178
255
 
179
256
  # @rbs return: ValueList
@@ -184,7 +261,7 @@ module LLDB
184
261
  list_ptr = FFIBindings.lldb_frame_get_registers(@ptr)
185
262
  raise LLDBError, 'Failed to get registers' if list_ptr.nil? || list_ptr.null?
186
263
 
187
- ValueList.new(list_ptr, parent: self)
264
+ ValueList.new(list_ptr, parent: self, context: context)
188
265
  end
189
266
 
190
267
  # @rbs return: bool
@@ -201,6 +278,21 @@ module LLDB
201
278
  FFIBindings.lldb_frame_disassemble(@ptr)
202
279
  end
203
280
 
281
+ # @rbs return: InstructionList?
282
+ def instruction_list
283
+ raise InvalidObjectError, 'Frame is not valid' unless valid?
284
+
285
+ target = @thread.process.target
286
+ return nil unless target
287
+
288
+ list_ptr = FFIBindings.lldb_frame_get_instruction_list(@ptr, target.to_ptr)
289
+ return nil if list_ptr.nil? || list_ptr.null?
290
+
291
+ InstructionList.new(list_ptr, target: target, context: context)
292
+ end
293
+
294
+ alias instructions instruction_list
295
+
204
296
  # @rbs return: Module?
205
297
  def get_module
206
298
  raise InvalidObjectError, 'Frame is not valid' unless valid?
@@ -208,7 +300,7 @@ module LLDB
208
300
  mod_ptr = FFIBindings.lldb_frame_get_module(@ptr)
209
301
  return nil if mod_ptr.nil? || mod_ptr.null?
210
302
 
211
- Module.new(mod_ptr, target: @thread.process.target)
303
+ Module.new(mod_ptr, target: @thread.process.target, context: context)
212
304
  end
213
305
 
214
306
  # @rbs return: Thread?
@@ -218,7 +310,7 @@ module LLDB
218
310
  thread_ptr = FFIBindings.lldb_frame_get_thread(@ptr)
219
311
  return nil if thread_ptr.nil? || thread_ptr.null?
220
312
 
221
- Thread.new(thread_ptr, process: @thread.process)
313
+ Thread.new(thread_ptr, process: @thread.process, context: context)
222
314
  end
223
315
 
224
316
  # @rbs return: FFI::Pointer
@@ -0,0 +1,121 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rbs_inline: enabled
4
+
5
+ module LLDB
6
+ class Function
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_function_destroy(released) },
17
+ context: context || target&.context
18
+ )
19
+ end
20
+
21
+ # @rbs return: bool
22
+ def valid?
23
+ !@ptr.null? && FFIBindings.lldb_function_is_valid(@ptr) != 0
24
+ end
25
+
26
+ # @rbs return: String?
27
+ def name
28
+ return nil unless valid?
29
+
30
+ FFIBindings.lldb_function_get_name(@ptr)
31
+ end
32
+
33
+ # @rbs return: String?
34
+ def display_name
35
+ return nil unless valid?
36
+
37
+ FFIBindings.lldb_function_get_display_name(@ptr)
38
+ end
39
+
40
+ # @rbs return: String?
41
+ def mangled_name
42
+ return nil unless valid?
43
+
44
+ FFIBindings.lldb_function_get_mangled_name(@ptr)
45
+ end
46
+
47
+ # @rbs return: String?
48
+ def base_name
49
+ return nil unless valid?
50
+
51
+ FFIBindings.lldb_function_get_base_name(@ptr)
52
+ end
53
+
54
+ # @rbs return: Address?
55
+ def start_address
56
+ address_at(:lldb_function_get_start_address)
57
+ end
58
+
59
+ # @rbs return: Address?
60
+ def end_address
61
+ address_at(:lldb_function_get_end_address)
62
+ end
63
+
64
+ # @rbs return: Integer
65
+ def prologue_byte_size
66
+ return 0 unless valid?
67
+
68
+ FFIBindings.lldb_function_get_prologue_byte_size(@ptr)
69
+ end
70
+
71
+ # @rbs return: Type?
72
+ def type
73
+ return nil unless valid?
74
+
75
+ ptr = FFIBindings.lldb_function_get_type(@ptr)
76
+ return nil if ptr.nil? || ptr.null?
77
+
78
+ Type.new(ptr, context: context)
79
+ end
80
+
81
+ # @rbs return: Block?
82
+ def block
83
+ return nil unless valid?
84
+
85
+ ptr = FFIBindings.lldb_function_get_block(@ptr)
86
+ return nil if ptr.nil? || ptr.null?
87
+
88
+ Block.new(ptr, target: @target, context: context)
89
+ end
90
+
91
+ # @rbs return: bool
92
+ def optimized?
93
+ valid? && FFIBindings.lldb_function_is_optimized(@ptr) != 0
94
+ end
95
+
96
+ # @rbs return: Integer
97
+ def language
98
+ return 0 unless valid?
99
+
100
+ FFIBindings.lldb_function_get_language(@ptr)
101
+ end
102
+
103
+ # @rbs return: FFI::Pointer
104
+ def to_ptr
105
+ @ptr
106
+ end
107
+
108
+ private
109
+
110
+ # @rbs method_name: ::Symbol
111
+ # @rbs return: Address?
112
+ def address_at(method_name)
113
+ return nil unless valid?
114
+
115
+ ptr = FFIBindings.public_send(method_name, @ptr)
116
+ return nil if ptr.nil? || ptr.null?
117
+
118
+ Address.from_ptr(ptr, target: @target, context: context)
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rbs_inline: enabled
4
+
5
+ module LLDB
6
+ class Instruction
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_instruction_destroy(released) },
17
+ context: context || target&.context
18
+ )
19
+ end
20
+
21
+ # @rbs return: bool
22
+ def valid?
23
+ !@ptr.null? && FFIBindings.lldb_instruction_is_valid(@ptr) != 0
24
+ end
25
+
26
+ # @rbs return: Address?
27
+ def address
28
+ return nil unless valid?
29
+
30
+ ptr = FFIBindings.lldb_instruction_get_address(@ptr)
31
+ return nil if ptr.nil? || ptr.null?
32
+
33
+ Address.from_ptr(ptr, target: @target, context: context)
34
+ end
35
+
36
+ # @rbs return: String?
37
+ def mnemonic
38
+ return nil unless valid? && @target
39
+
40
+ FFIBindings.lldb_instruction_get_mnemonic(@ptr, @target.to_ptr)
41
+ end
42
+
43
+ # @rbs return: String?
44
+ def operands
45
+ return nil unless valid? && @target
46
+
47
+ FFIBindings.lldb_instruction_get_operands(@ptr, @target.to_ptr)
48
+ end
49
+
50
+ # @rbs return: String?
51
+ def comment
52
+ return nil unless valid? && @target
53
+
54
+ FFIBindings.lldb_instruction_get_comment(@ptr, @target.to_ptr)
55
+ end
56
+
57
+ # @rbs return: Integer
58
+ def byte_size
59
+ return 0 unless valid?
60
+
61
+ FFIBindings.lldb_instruction_get_byte_size(@ptr)
62
+ end
63
+
64
+ # @rbs return: String
65
+ def bytes
66
+ return ''.b unless valid? && @target
67
+
68
+ length = byte_size
69
+ return ''.b if length.zero?
70
+
71
+ buffer = FFI::MemoryPointer.new(:uint8, length)
72
+ written = FFIBindings.lldb_instruction_get_bytes(
73
+ @ptr, @target.to_ptr, buffer, length
74
+ )
75
+ buffer.get_bytes(0, [written, length].min).b
76
+ end
77
+
78
+ # @rbs return: FFI::Pointer
79
+ def to_ptr
80
+ @ptr
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rbs_inline: enabled
4
+
5
+ module LLDB
6
+ class InstructionList
7
+ prepend NativeLifecycle
8
+ include Enumerable #[Instruction]
9
+
10
+ # @rbs target: Target?
11
+ # @rbs context: Context?
12
+ # @rbs return: void
13
+ def initialize(ptr, target: nil, context: nil)
14
+ @target = target
15
+ initialize_native_object(
16
+ ptr,
17
+ release: ->(released) { FFIBindings.lldb_instruction_list_destroy(released) },
18
+ context: context || target&.context
19
+ )
20
+ end
21
+
22
+ # @rbs return: bool
23
+ def valid?
24
+ !@ptr.null? && FFIBindings.lldb_instruction_list_is_valid(@ptr) != 0
25
+ end
26
+
27
+ # @rbs return: Integer
28
+ def size
29
+ return 0 unless valid?
30
+
31
+ FFIBindings.lldb_instruction_list_get_size(@ptr)
32
+ end
33
+
34
+ alias length size
35
+
36
+ # @rbs index: Integer
37
+ # @rbs return: Instruction?
38
+ def [](index)
39
+ return nil unless valid?
40
+
41
+ ptr = FFIBindings.lldb_instruction_list_get_instruction_at_index(@ptr, index)
42
+ return nil if ptr.nil? || ptr.null?
43
+
44
+ Instruction.new(ptr, target: @target, context: context)
45
+ end
46
+
47
+ # @rbs &block: (Instruction) -> void
48
+ # @rbs return: Enumerator[Instruction, void] | void
49
+ def each(&block)
50
+ return enum_for(:each) unless block_given?
51
+
52
+ (0...size).each do |index|
53
+ instruction = self[index]
54
+ block.call(instruction) if instruction
55
+ end
56
+ end
57
+
58
+ # @rbs return: Array[Instruction]
59
+ def to_a
60
+ (0...size).map { |index| self[index] }.compact
61
+ end
62
+
63
+ # @rbs return: FFI::Pointer
64
+ def to_ptr
65
+ @ptr
66
+ end
67
+ end
68
+ end