lldb 0.1.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.
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rbs_inline: enabled
4
+
5
+ module LLDB
6
+ # Launch flags for process launching
7
+ module LaunchFlags
8
+ NONE = 0
9
+ EXEC = (1 << 0)
10
+ DEBUG = (1 << 1)
11
+ STOP_AT_ENTRY = (1 << 2)
12
+ DISABLE_ASLR = (1 << 3)
13
+ DISABLE_STDIO = (1 << 4)
14
+ LAUNCH_IN_TTY = (1 << 5)
15
+ LAUNCH_IN_SHELL = (1 << 6)
16
+ LAUNCH_IN_SEPARATE_PROCESS_GROUP = (1 << 7)
17
+ DONT_SET_EXIT_STATUS = (1 << 8)
18
+ DETACH_ON_ERROR = (1 << 9)
19
+ SHELL_EXPAND_ARGUMENTS = (1 << 10)
20
+ CLOSE_TTY_ON_EXIT = (1 << 11)
21
+ INHERIT_TCC_FROM_PARENT = (1 << 12)
22
+ end
23
+
24
+ class LaunchInfo
25
+ # @rbs args: Array[String]?
26
+ # @rbs return: void
27
+ def initialize(args = nil)
28
+ argv = nil
29
+ if args && !args.empty?
30
+ argv = FFI::MemoryPointer.new(:pointer, args.length + 1)
31
+ args.each_with_index do |arg, i|
32
+ argv[i].put_pointer(0, FFI::MemoryPointer.from_string(arg))
33
+ end
34
+ argv[args.length].put_pointer(0, nil)
35
+ end
36
+
37
+ @ptr = FFIBindings.lldb_launch_info_create(argv) # : FFI::Pointer
38
+ ObjectSpace.define_finalizer(self, self.class.release(@ptr))
39
+ end
40
+
41
+ # @rbs ptr: FFI::Pointer
42
+ # @rbs return: ^(Integer) -> void
43
+ def self.release(ptr)
44
+ ->(_id) { FFIBindings.lldb_launch_info_destroy(ptr) unless ptr.null? }
45
+ end
46
+
47
+ # @rbs dir: String
48
+ # @rbs return: void
49
+ def working_directory=(dir)
50
+ FFIBindings.lldb_launch_info_set_working_directory(@ptr, dir)
51
+ end
52
+
53
+ # @rbs env: Hash[String, String]
54
+ # @rbs append: bool
55
+ # @rbs return: void
56
+ def set_environment(env, append: true)
57
+ return unless env && !env.empty?
58
+
59
+ env_strings = env.map { |k, v| "#{k}=#{v}" }
60
+ envp = FFI::MemoryPointer.new(:pointer, env_strings.length + 1)
61
+ env_strings.each_with_index do |e, i|
62
+ envp[i].put_pointer(0, FFI::MemoryPointer.from_string(e))
63
+ end
64
+ envp[env_strings.length].put_pointer(0, nil)
65
+
66
+ FFIBindings.lldb_launch_info_set_environment_entries(@ptr, envp, append ? 1 : 0)
67
+ end
68
+
69
+ # @rbs return: Integer
70
+ def launch_flags
71
+ FFIBindings.lldb_launch_info_get_launch_flags(@ptr)
72
+ end
73
+
74
+ # @rbs flags: Integer
75
+ # @rbs return: void
76
+ def launch_flags=(flags)
77
+ FFIBindings.lldb_launch_info_set_launch_flags(@ptr, flags)
78
+ end
79
+
80
+ # @rbs return: FFI::Pointer
81
+ def to_ptr
82
+ @ptr
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rbs_inline: enabled
4
+
5
+ module LLDB
6
+ class Module
7
+ # @rbs return: Target?
8
+ attr_reader :target
9
+
10
+ # @rbs ptr: FFI::Pointer
11
+ # @rbs target: Target?
12
+ # @rbs return: void
13
+ def initialize(ptr, target:)
14
+ @ptr = ptr # : FFI::Pointer
15
+ @target = target
16
+ ObjectSpace.define_finalizer(self, self.class.release(@ptr))
17
+ end
18
+
19
+ # @rbs ptr: FFI::Pointer
20
+ # @rbs return: ^(Integer) -> void
21
+ def self.release(ptr)
22
+ ->(_id) { FFIBindings.lldb_module_destroy(ptr) unless ptr.null? }
23
+ end
24
+
25
+ # @rbs return: bool
26
+ def valid?
27
+ !@ptr.null? && FFIBindings.lldb_module_is_valid(@ptr) != 0
28
+ end
29
+
30
+ # @rbs return: String?
31
+ def file_path
32
+ return nil unless valid?
33
+
34
+ FFIBindings.lldb_module_get_file_path(@ptr)
35
+ end
36
+
37
+ # @rbs return: String?
38
+ def platform_file_path
39
+ return nil unless valid?
40
+
41
+ FFIBindings.lldb_module_get_platform_file_path(@ptr)
42
+ end
43
+
44
+ # @rbs return: Integer
45
+ def num_symbols
46
+ return 0 unless valid?
47
+
48
+ FFIBindings.lldb_module_get_num_symbols(@ptr)
49
+ end
50
+
51
+ # @rbs return: String
52
+ def to_s
53
+ file_path || '(unknown module)'
54
+ end
55
+
56
+ # @rbs return: FFI::Pointer
57
+ def to_ptr
58
+ @ptr
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,317 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rbs_inline: enabled
4
+
5
+ module LLDB
6
+ class Process
7
+ # @rbs return: Target
8
+ attr_reader :target
9
+
10
+ # @rbs ptr: FFI::Pointer
11
+ # @rbs target: Target
12
+ # @rbs return: void
13
+ def initialize(ptr, target:)
14
+ @ptr = ptr # : FFI::Pointer
15
+ @target = target
16
+ ObjectSpace.define_finalizer(self, self.class.release(@ptr))
17
+ end
18
+
19
+ # @rbs ptr: FFI::Pointer
20
+ # @rbs return: ^(Integer) -> void
21
+ def self.release(ptr)
22
+ ->(_id) { FFIBindings.lldb_process_destroy(ptr) unless ptr.null? }
23
+ end
24
+
25
+ # @rbs return: bool
26
+ def valid?
27
+ !@ptr.null? && FFIBindings.lldb_process_is_valid(@ptr) != 0
28
+ end
29
+
30
+ # @rbs return: bool
31
+ def continue
32
+ raise InvalidObjectError, 'Process is not valid' unless valid?
33
+
34
+ FFIBindings.lldb_process_continue(@ptr) != 0
35
+ end
36
+
37
+ # @rbs return: bool
38
+ def stop
39
+ raise InvalidObjectError, 'Process is not valid' unless valid?
40
+
41
+ FFIBindings.lldb_process_stop(@ptr) != 0
42
+ end
43
+
44
+ # @rbs return: bool
45
+ def kill
46
+ raise InvalidObjectError, 'Process is not valid' unless valid?
47
+
48
+ FFIBindings.lldb_process_kill(@ptr) != 0
49
+ end
50
+
51
+ # @rbs return: bool
52
+ def detach
53
+ raise InvalidObjectError, 'Process is not valid' unless valid?
54
+
55
+ FFIBindings.lldb_process_detach(@ptr) != 0
56
+ end
57
+
58
+ # @rbs return: Integer
59
+ def state
60
+ return State::INVALID unless valid?
61
+
62
+ FFIBindings.lldb_process_get_state(@ptr)
63
+ end
64
+
65
+ # @rbs return: String
66
+ def state_name
67
+ State.name(state)
68
+ end
69
+
70
+ # @rbs return: bool
71
+ def stopped?
72
+ state == State::STOPPED
73
+ end
74
+
75
+ # @rbs return: bool
76
+ def running?
77
+ state == State::RUNNING
78
+ end
79
+
80
+ # @rbs return: bool
81
+ def exited?
82
+ state == State::EXITED
83
+ end
84
+
85
+ # @rbs return: bool
86
+ def crashed?
87
+ state == State::CRASHED
88
+ end
89
+
90
+ # @rbs return: Integer
91
+ def num_threads
92
+ return 0 unless valid?
93
+
94
+ FFIBindings.lldb_process_get_num_threads(@ptr)
95
+ end
96
+
97
+ # @rbs index: Integer
98
+ # @rbs return: Thread?
99
+ def thread_at_index(index)
100
+ raise InvalidObjectError, 'Process is not valid' unless valid?
101
+
102
+ thread_ptr = FFIBindings.lldb_process_get_thread_at_index(@ptr, index)
103
+ return nil if thread_ptr.nil? || thread_ptr.null?
104
+
105
+ Thread.new(thread_ptr, process: self)
106
+ end
107
+
108
+ # @rbs return: Thread?
109
+ def selected_thread
110
+ raise InvalidObjectError, 'Process is not valid' unless valid?
111
+
112
+ thread_ptr = FFIBindings.lldb_process_get_selected_thread(@ptr)
113
+ return nil if thread_ptr.nil? || thread_ptr.null?
114
+
115
+ Thread.new(thread_ptr, process: self)
116
+ end
117
+
118
+ # @rbs thread_id: Integer
119
+ # @rbs return: bool
120
+ def select_thread_by_id(thread_id)
121
+ raise InvalidObjectError, 'Process is not valid' unless valid?
122
+
123
+ FFIBindings.lldb_process_set_selected_thread_by_id(@ptr, thread_id) != 0
124
+ end
125
+
126
+ # @rbs return: Array[Thread]
127
+ def threads
128
+ (0...num_threads).map { |i| thread_at_index(i) }.compact
129
+ end
130
+
131
+ # @rbs return: Integer
132
+ def process_id
133
+ return 0 unless valid?
134
+
135
+ FFIBindings.lldb_process_get_process_id(@ptr)
136
+ end
137
+
138
+ alias pid process_id
139
+
140
+ # @rbs return: Integer
141
+ def exit_status
142
+ raise InvalidObjectError, 'Process is not valid' unless valid?
143
+
144
+ FFIBindings.lldb_process_get_exit_status(@ptr)
145
+ end
146
+
147
+ # @rbs return: String?
148
+ def exit_description
149
+ raise InvalidObjectError, 'Process is not valid' unless valid?
150
+
151
+ FFIBindings.lldb_process_get_exit_description(@ptr)
152
+ end
153
+
154
+ # @rbs return: bool
155
+ def destroy
156
+ raise InvalidObjectError, 'Process is not valid' unless valid?
157
+
158
+ FFIBindings.lldb_process_destroy_process(@ptr) != 0
159
+ end
160
+
161
+ # @rbs signal: Integer
162
+ # @rbs return: bool
163
+ def signal(signal)
164
+ raise InvalidObjectError, 'Process is not valid' unless valid?
165
+
166
+ FFIBindings.lldb_process_signal(@ptr, signal) != 0
167
+ end
168
+
169
+ # @rbs thread_id: Integer
170
+ # @rbs return: Thread?
171
+ def thread_by_id(thread_id)
172
+ raise InvalidObjectError, 'Process is not valid' unless valid?
173
+
174
+ thread_ptr = FFIBindings.lldb_process_get_thread_by_id(@ptr, thread_id)
175
+ return nil if thread_ptr.nil? || thread_ptr.null?
176
+
177
+ Thread.new(thread_ptr, process: self)
178
+ end
179
+
180
+ # @rbs index_id: Integer
181
+ # @rbs return: Thread?
182
+ def thread_by_index_id(index_id)
183
+ raise InvalidObjectError, 'Process is not valid' unless valid?
184
+
185
+ thread_ptr = FFIBindings.lldb_process_get_thread_by_index_id(@ptr, index_id)
186
+ return nil if thread_ptr.nil? || thread_ptr.null?
187
+
188
+ Thread.new(thread_ptr, process: self)
189
+ end
190
+
191
+ # @rbs index_id: Integer
192
+ # @rbs return: bool
193
+ def select_thread_by_index_id(index_id)
194
+ raise InvalidObjectError, 'Process is not valid' unless valid?
195
+
196
+ FFIBindings.lldb_process_set_selected_thread_by_index_id(@ptr, index_id) != 0
197
+ end
198
+
199
+ # @rbs address: Integer
200
+ # @rbs size: Integer
201
+ # @rbs return: String
202
+ def read_memory(address, size)
203
+ raise InvalidObjectError, 'Process is not valid' unless valid?
204
+
205
+ buffer = FFI::MemoryPointer.new(:uint8, size)
206
+ error = Error.new
207
+ bytes_read = FFIBindings.lldb_process_read_memory(@ptr, address, buffer, size, error.to_ptr)
208
+
209
+ error.raise_if_error!
210
+ buffer.read_string(bytes_read)
211
+ end
212
+
213
+ # @rbs address: Integer
214
+ # @rbs data: String
215
+ # @rbs return: Integer
216
+ def write_memory(address, data)
217
+ raise InvalidObjectError, 'Process is not valid' unless valid?
218
+
219
+ buffer = FFI::MemoryPointer.from_string(data)
220
+ error = Error.new
221
+ bytes_written = FFIBindings.lldb_process_write_memory(@ptr, address, buffer, data.bytesize, error.to_ptr)
222
+
223
+ error.raise_if_error!
224
+ bytes_written
225
+ end
226
+
227
+ # @rbs size: Integer
228
+ # @rbs permissions: Integer
229
+ # @rbs return: Integer
230
+ def allocate_memory(size, permissions)
231
+ raise InvalidObjectError, 'Process is not valid' unless valid?
232
+
233
+ error = Error.new
234
+ address = FFIBindings.lldb_process_allocate_memory(@ptr, size, permissions, error.to_ptr)
235
+
236
+ error.raise_if_error!
237
+ address
238
+ end
239
+
240
+ # @rbs address: Integer
241
+ # @rbs return: bool
242
+ def deallocate_memory(address)
243
+ raise InvalidObjectError, 'Process is not valid' unless valid?
244
+
245
+ FFIBindings.lldb_process_deallocate_memory(@ptr, address) != 0
246
+ end
247
+
248
+ # @rbs address: Integer
249
+ # @rbs max_size: Integer
250
+ # @rbs return: String
251
+ def read_cstring_from_memory(address, max_size = 1024)
252
+ raise InvalidObjectError, 'Process is not valid' unless valid?
253
+
254
+ buffer = FFI::MemoryPointer.new(:uint8, max_size)
255
+ error = Error.new
256
+ FFIBindings.lldb_process_read_cstring_from_memory(@ptr, address, buffer, max_size, error.to_ptr)
257
+
258
+ error.raise_if_error!
259
+ buffer.read_string
260
+ end
261
+
262
+ # @rbs max_size: Integer
263
+ # @rbs return: String
264
+ def get_stdout(max_size = 4096)
265
+ raise InvalidObjectError, 'Process is not valid' unless valid?
266
+
267
+ buffer = FFI::MemoryPointer.new(:uint8, max_size)
268
+ bytes_read = FFIBindings.lldb_process_get_stdout(@ptr, buffer, max_size)
269
+ buffer.read_string(bytes_read)
270
+ end
271
+
272
+ # @rbs max_size: Integer
273
+ # @rbs return: String
274
+ def get_stderr(max_size = 4096)
275
+ raise InvalidObjectError, 'Process is not valid' unless valid?
276
+
277
+ buffer = FFI::MemoryPointer.new(:uint8, max_size)
278
+ bytes_read = FFIBindings.lldb_process_get_stderr(@ptr, buffer, max_size)
279
+ buffer.read_string(bytes_read)
280
+ end
281
+
282
+ # @rbs data: String
283
+ # @rbs return: Integer
284
+ def put_stdin(data)
285
+ raise InvalidObjectError, 'Process is not valid' unless valid?
286
+
287
+ FFIBindings.lldb_process_put_stdin(@ptr, data, data.bytesize)
288
+ end
289
+
290
+ # @rbs return: bool
291
+ def send_async_interrupt
292
+ raise InvalidObjectError, 'Process is not valid' unless valid?
293
+
294
+ FFIBindings.lldb_process_send_async_interrupt(@ptr) != 0
295
+ end
296
+
297
+ # @rbs return: Integer
298
+ def num_supported_hardware_watchpoints
299
+ return 0 unless valid?
300
+
301
+ error = Error.new
302
+ FFIBindings.lldb_process_get_num_supported_hardware_watchpoints(@ptr, error.to_ptr)
303
+ end
304
+
305
+ # @rbs return: Integer
306
+ def unique_id
307
+ return 0 unless valid?
308
+
309
+ FFIBindings.lldb_process_get_unique_id(@ptr)
310
+ end
311
+
312
+ # @rbs return: FFI::Pointer
313
+ def to_ptr
314
+ @ptr
315
+ end
316
+ end
317
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rbs_inline: enabled
4
+
5
+ module LLDB
6
+ class SymbolContext
7
+ # @rbs return: Frame
8
+ attr_reader :parent
9
+
10
+ # @rbs ptr: FFI::Pointer
11
+ # @rbs parent: Frame
12
+ # @rbs return: void
13
+ def initialize(ptr, parent:)
14
+ @ptr = ptr # : FFI::Pointer
15
+ @parent = parent
16
+ ObjectSpace.define_finalizer(self, self.class.release(@ptr))
17
+ end
18
+
19
+ # @rbs ptr: FFI::Pointer
20
+ # @rbs return: ^(Integer) -> void
21
+ def self.release(ptr)
22
+ ->(_id) { FFIBindings.lldb_symbol_context_destroy(ptr) unless ptr.null? }
23
+ end
24
+
25
+ # @rbs return: bool
26
+ def valid?
27
+ !@ptr.null? && FFIBindings.lldb_symbol_context_is_valid(@ptr) != 0
28
+ end
29
+
30
+ # @rbs return: Module?
31
+ def module
32
+ return nil unless valid?
33
+
34
+ mod_ptr = FFIBindings.lldb_symbol_context_get_module(@ptr)
35
+ return nil if mod_ptr.nil? || mod_ptr.null?
36
+
37
+ Module.new(mod_ptr, target: nil)
38
+ end
39
+
40
+ # @rbs return: String?
41
+ def function_name
42
+ return nil unless valid?
43
+
44
+ FFIBindings.lldb_symbol_context_get_function_name(@ptr)
45
+ end
46
+
47
+ # @rbs return: FFI::Pointer
48
+ def to_ptr
49
+ @ptr
50
+ end
51
+ end
52
+ end