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.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/CHANGELOG.md +7 -0
- data/LICENSE-APACHE +190 -0
- data/LICENSE-MIT +21 -0
- data/README.md +240 -0
- data/Rakefile +80 -0
- data/Steepfile +11 -0
- data/examples/basic_debug.rb +111 -0
- data/examples/breakpoints.rb +72 -0
- data/examples/expression_eval.rb +84 -0
- data/examples/test_program.c +14 -0
- data/ext/lldb/Makefile +24 -0
- data/ext/lldb/extconf.rb +160 -0
- data/ext/lldb/liblldb_wrapper.dylib +0 -0
- data/ext/lldb/lldb_wrapper.cpp +2051 -0
- data/ext/lldb/lldb_wrapper.h +424 -0
- data/ext/lldb/lldb_wrapper.o +0 -0
- data/ext/lldb/mkmf.log +24 -0
- data/lib/lldb/breakpoint.rb +233 -0
- data/lib/lldb/breakpoint_location.rb +117 -0
- data/lib/lldb/command_interpreter.rb +62 -0
- data/lib/lldb/command_return_object.rb +71 -0
- data/lib/lldb/debugger.rb +179 -0
- data/lib/lldb/error.rb +70 -0
- data/lib/lldb/ffi_bindings.rb +394 -0
- data/lib/lldb/frame.rb +226 -0
- data/lib/lldb/launch_info.rb +85 -0
- data/lib/lldb/module.rb +61 -0
- data/lib/lldb/process.rb +317 -0
- data/lib/lldb/symbol_context.rb +52 -0
- data/lib/lldb/target.rb +427 -0
- data/lib/lldb/thread.rb +226 -0
- data/lib/lldb/type.rb +215 -0
- data/lib/lldb/types.rb +190 -0
- data/lib/lldb/value.rb +334 -0
- data/lib/lldb/value_list.rb +88 -0
- data/lib/lldb/version.rb +7 -0
- data/lib/lldb/watchpoint.rb +145 -0
- data/lib/lldb.rb +64 -0
- data/lldb.gemspec +33 -0
- data/rbs_collection.lock.yaml +220 -0
- data/rbs_collection.yaml +19 -0
- data/sig/lldb/ffi_bindings.rbs +312 -0
- metadata +102 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# Breakpoint management example
|
|
5
|
+
#
|
|
6
|
+
# This example demonstrates:
|
|
7
|
+
# - Creating different types of breakpoints
|
|
8
|
+
# - Managing breakpoint properties
|
|
9
|
+
# - Conditional breakpoints
|
|
10
|
+
|
|
11
|
+
require_relative '../lib/lldb'
|
|
12
|
+
|
|
13
|
+
PROGRAM_PATH = File.expand_path('test_program', __dir__)
|
|
14
|
+
|
|
15
|
+
unless File.exist?(PROGRAM_PATH)
|
|
16
|
+
puts 'Please compile test_program.c first'
|
|
17
|
+
exit 1
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
LLDB.initialize
|
|
21
|
+
|
|
22
|
+
begin
|
|
23
|
+
debugger = LLDB::Debugger.create
|
|
24
|
+
target = debugger.create_target(PROGRAM_PATH)
|
|
25
|
+
|
|
26
|
+
puts '=== Breakpoint Types ==='
|
|
27
|
+
|
|
28
|
+
# Breakpoint by function name
|
|
29
|
+
bp1 = target.breakpoint_create_by_name('main')
|
|
30
|
+
puts "Breakpoint by name 'main': ID=#{bp1.id}, locations=#{bp1.num_locations}"
|
|
31
|
+
|
|
32
|
+
# Breakpoint by source location
|
|
33
|
+
bp2 = target.breakpoint_create_by_location('test_program.c', 4)
|
|
34
|
+
puts "Breakpoint by location: ID=#{bp2.id}"
|
|
35
|
+
|
|
36
|
+
puts "\n=== Breakpoint Properties ==="
|
|
37
|
+
|
|
38
|
+
# Disable a breakpoint
|
|
39
|
+
bp1.disable
|
|
40
|
+
puts "bp1 enabled? #{bp1.enabled?}"
|
|
41
|
+
|
|
42
|
+
# Enable it again
|
|
43
|
+
bp1.enable
|
|
44
|
+
puts "bp1 enabled after enable? #{bp1.enabled?}"
|
|
45
|
+
|
|
46
|
+
# Set condition
|
|
47
|
+
bp2.condition = 'a > 5'
|
|
48
|
+
puts "bp2 condition: #{bp2.condition}"
|
|
49
|
+
|
|
50
|
+
# Set ignore count
|
|
51
|
+
bp2.ignore_count = 2
|
|
52
|
+
puts "bp2 ignore count: #{bp2.ignore_count}"
|
|
53
|
+
|
|
54
|
+
# One-shot breakpoint
|
|
55
|
+
bp2.one_shot = true
|
|
56
|
+
puts "bp2 one-shot? #{bp2.one_shot?}"
|
|
57
|
+
|
|
58
|
+
puts "\n=== All Breakpoints ==="
|
|
59
|
+
target.breakpoints.each do |bp|
|
|
60
|
+
puts bp
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
puts "\n=== Finding Breakpoints ==="
|
|
64
|
+
found = target.find_breakpoint_by_id(bp1.id)
|
|
65
|
+
puts "Found breakpoint #{found.id}" if found
|
|
66
|
+
|
|
67
|
+
puts "\n=== Deleting Breakpoints ==="
|
|
68
|
+
bp1.delete
|
|
69
|
+
puts "Remaining breakpoints: #{target.num_breakpoints}"
|
|
70
|
+
ensure
|
|
71
|
+
LLDB.terminate
|
|
72
|
+
end
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# Expression evaluation example
|
|
5
|
+
#
|
|
6
|
+
# This example demonstrates:
|
|
7
|
+
# - Finding and inspecting variables
|
|
8
|
+
# - Evaluating expressions
|
|
9
|
+
# - Working with Value objects
|
|
10
|
+
|
|
11
|
+
require_relative '../lib/lldb'
|
|
12
|
+
|
|
13
|
+
PROGRAM_PATH = File.expand_path('test_program', __dir__)
|
|
14
|
+
|
|
15
|
+
unless File.exist?(PROGRAM_PATH)
|
|
16
|
+
puts 'Please compile test_program.c first'
|
|
17
|
+
exit 1
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
LLDB.initialize
|
|
21
|
+
|
|
22
|
+
begin
|
|
23
|
+
debugger = LLDB::Debugger.create
|
|
24
|
+
debugger.async = false
|
|
25
|
+
target = debugger.create_target(PROGRAM_PATH)
|
|
26
|
+
|
|
27
|
+
# Set breakpoint inside add function
|
|
28
|
+
target.breakpoint_create_by_name('add')
|
|
29
|
+
|
|
30
|
+
puts 'Launching process...'
|
|
31
|
+
process = target.launch
|
|
32
|
+
|
|
33
|
+
if process.stopped?
|
|
34
|
+
thread = process.selected_thread
|
|
35
|
+
frame = thread.selected_frame
|
|
36
|
+
|
|
37
|
+
puts "Stopped at: #{frame.function_name}"
|
|
38
|
+
puts "Location: #{frame.location}"
|
|
39
|
+
|
|
40
|
+
puts "\n=== Variables ==="
|
|
41
|
+
|
|
42
|
+
# Find individual variables
|
|
43
|
+
a = frame.find_variable('a')
|
|
44
|
+
b = frame.find_variable('b')
|
|
45
|
+
|
|
46
|
+
if a&.valid?
|
|
47
|
+
puts "Variable 'a':"
|
|
48
|
+
puts " Name: #{a.name}"
|
|
49
|
+
puts " Type: #{a.type_name}"
|
|
50
|
+
puts " Value: #{a.value}"
|
|
51
|
+
puts " As integer: #{a.to_i}"
|
|
52
|
+
puts " Byte size: #{a.byte_size}"
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
if b&.valid?
|
|
56
|
+
puts "\nVariable 'b':"
|
|
57
|
+
puts " #{b.inspect}"
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
puts "\n=== Expression Evaluation ==="
|
|
61
|
+
|
|
62
|
+
# Evaluate expressions
|
|
63
|
+
expressions = [
|
|
64
|
+
'a + b',
|
|
65
|
+
'a * b',
|
|
66
|
+
'a - b',
|
|
67
|
+
'a / 2',
|
|
68
|
+
'(a + b) * 2'
|
|
69
|
+
]
|
|
70
|
+
|
|
71
|
+
expressions.each do |expr|
|
|
72
|
+
result = frame.evaluate_expression(expr)
|
|
73
|
+
if result&.valid?
|
|
74
|
+
puts "#{expr} = #{result.value}"
|
|
75
|
+
else
|
|
76
|
+
puts "#{expr} = (error)"
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
process.kill
|
|
81
|
+
end
|
|
82
|
+
ensure
|
|
83
|
+
LLDB.terminate
|
|
84
|
+
end
|
data/ext/lldb/Makefile
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
CXX = clang++
|
|
2
|
+
CXXFLAGS = -fdeclspec -std=c++17 -I/opt/homebrew/opt/llvm/include -fPIC
|
|
3
|
+
LDFLAGS = -L. -fstack-protector-strong -L/opt/homebrew/Cellar/gmp/6.3.0/lib -L/opt/homebrew/opt/llvm/lib -llldb -Wl,-rpath,/opt/homebrew/opt/llvm/lib -lc++ -L/opt/homebrew/Cellar/gmp/6.3.0/lib -Wl,-undefined,dynamic_lookup -dynamiclib
|
|
4
|
+
|
|
5
|
+
TARGET = liblldb_wrapper.dylib
|
|
6
|
+
SRCS = lldb_wrapper.cpp
|
|
7
|
+
OBJS = lldb_wrapper.o
|
|
8
|
+
|
|
9
|
+
all: $(TARGET)
|
|
10
|
+
|
|
11
|
+
$(TARGET): $(OBJS)
|
|
12
|
+
$(CXX) $(LDFLAGS) -o $@ $(OBJS)
|
|
13
|
+
|
|
14
|
+
%.o: %.cpp
|
|
15
|
+
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
|
16
|
+
|
|
17
|
+
install: $(TARGET)
|
|
18
|
+
mkdir -p $(DESTDIR)/Users/yudai.takada/.rbenv/versions/4.0.0/lib/ruby/site_ruby/4.0.0/lldb
|
|
19
|
+
cp $(TARGET) $(DESTDIR)/Users/yudai.takada/.rbenv/versions/4.0.0/lib/ruby/site_ruby/4.0.0/lldb/
|
|
20
|
+
|
|
21
|
+
clean:
|
|
22
|
+
rm -f $(OBJS) $(TARGET)
|
|
23
|
+
|
|
24
|
+
.PHONY: all install clean
|
data/ext/lldb/extconf.rb
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require 'mkmf'
|
|
5
|
+
|
|
6
|
+
# Enable C++17
|
|
7
|
+
$CXXFLAGS ||= ''
|
|
8
|
+
$CXXFLAGS << ' -std=c++17'
|
|
9
|
+
|
|
10
|
+
# Common LLDB search paths
|
|
11
|
+
lldb_search_paths = [
|
|
12
|
+
# macOS Xcode
|
|
13
|
+
'/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr',
|
|
14
|
+
'/Library/Developer/CommandLineTools/usr',
|
|
15
|
+
# Homebrew LLVM on macOS (Apple Silicon)
|
|
16
|
+
'/opt/homebrew/opt/llvm',
|
|
17
|
+
# Homebrew LLVM on macOS (Intel)
|
|
18
|
+
'/usr/local/opt/llvm',
|
|
19
|
+
# Linux system paths
|
|
20
|
+
'/usr',
|
|
21
|
+
'/usr/local'
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
# Find LLDB version-specific paths on Linux
|
|
25
|
+
Dir.glob('/usr/lib/llvm-*').each do |path|
|
|
26
|
+
lldb_search_paths << path
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
lldb_lib_dir = nil
|
|
30
|
+
lldb_include_dir = nil
|
|
31
|
+
|
|
32
|
+
# Try to find LLDB using lldb-config or llvm-config
|
|
33
|
+
llvm_config = find_executable('llvm-config') ||
|
|
34
|
+
find_executable('llvm-config-18') ||
|
|
35
|
+
find_executable('llvm-config-17') ||
|
|
36
|
+
find_executable('llvm-config-16') ||
|
|
37
|
+
find_executable('llvm-config-15') ||
|
|
38
|
+
find_executable('llvm-config-14')
|
|
39
|
+
|
|
40
|
+
if llvm_config
|
|
41
|
+
lldb_lib_dir = `#{llvm_config} --libdir`.strip
|
|
42
|
+
lldb_include_dir = `#{llvm_config} --includedir`.strip
|
|
43
|
+
else
|
|
44
|
+
# Search manually
|
|
45
|
+
lldb_search_paths.each do |base_path|
|
|
46
|
+
next unless File.directory?(base_path)
|
|
47
|
+
|
|
48
|
+
lib_candidates = [
|
|
49
|
+
File.join(base_path, 'lib'),
|
|
50
|
+
File.join(base_path, 'lib64')
|
|
51
|
+
]
|
|
52
|
+
|
|
53
|
+
lib_candidates.each do |lib_path|
|
|
54
|
+
next unless File.directory?(lib_path)
|
|
55
|
+
|
|
56
|
+
# Check for liblldb
|
|
57
|
+
has_lldb = File.exist?(File.join(lib_path, 'liblldb.so')) ||
|
|
58
|
+
File.exist?(File.join(lib_path, 'liblldb.dylib')) ||
|
|
59
|
+
Dir.glob(File.join(lib_path, 'liblldb.so.*')).any?
|
|
60
|
+
|
|
61
|
+
next unless has_lldb
|
|
62
|
+
|
|
63
|
+
lldb_lib_dir = lib_path
|
|
64
|
+
lldb_include_dir = File.join(base_path, 'include')
|
|
65
|
+
break
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
break if lldb_lib_dir
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
unless lldb_lib_dir
|
|
74
|
+
abort <<~MSG
|
|
75
|
+
|
|
76
|
+
*** ERROR: Could not find LLDB library ***
|
|
77
|
+
|
|
78
|
+
Please install LLDB development files:
|
|
79
|
+
|
|
80
|
+
On Ubuntu/Debian:
|
|
81
|
+
sudo apt-get install lldb-14 liblldb-14-dev
|
|
82
|
+
|
|
83
|
+
On Fedora/RHEL:
|
|
84
|
+
sudo dnf install lldb-devel
|
|
85
|
+
|
|
86
|
+
On macOS:
|
|
87
|
+
xcode-select --install
|
|
88
|
+
# or
|
|
89
|
+
brew install llvm
|
|
90
|
+
|
|
91
|
+
You can also set LLDB_DIR environment variable to point to your LLDB installation:
|
|
92
|
+
LLDB_DIR=/path/to/llvm gem install lldb
|
|
93
|
+
|
|
94
|
+
MSG
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
puts "Found LLDB library directory: #{lldb_lib_dir}"
|
|
98
|
+
puts "Found LLDB include directory: #{lldb_include_dir}" if lldb_include_dir
|
|
99
|
+
|
|
100
|
+
# Add include paths
|
|
101
|
+
$CXXFLAGS << " -I#{lldb_include_dir}" if lldb_include_dir && File.directory?(lldb_include_dir)
|
|
102
|
+
|
|
103
|
+
# Link against LLDB library
|
|
104
|
+
$LDFLAGS << " -L#{lldb_lib_dir} -llldb"
|
|
105
|
+
$LDFLAGS << " -Wl,-rpath,#{lldb_lib_dir}"
|
|
106
|
+
|
|
107
|
+
# Check for C++ standard library
|
|
108
|
+
$LDFLAGS << if RUBY_PLATFORM =~ /darwin/
|
|
109
|
+
' -lc++'
|
|
110
|
+
else
|
|
111
|
+
' -lstdc++'
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# Create the extension as a shared library, not a Ruby native extension
|
|
115
|
+
# because we're using FFI to load it
|
|
116
|
+
$srcs = ['lldb_wrapper.cpp']
|
|
117
|
+
$objs = ['lldb_wrapper.o']
|
|
118
|
+
|
|
119
|
+
# Set the target library name
|
|
120
|
+
$DLDFLAGS ||= ''
|
|
121
|
+
|
|
122
|
+
if RUBY_PLATFORM =~ /darwin/
|
|
123
|
+
target = 'liblldb_wrapper.dylib'
|
|
124
|
+
$DLDFLAGS << ' -dynamiclib'
|
|
125
|
+
else
|
|
126
|
+
target = 'liblldb_wrapper.so'
|
|
127
|
+
$DLDFLAGS << ' -shared'
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# Create a custom Makefile that builds a shared library
|
|
131
|
+
File.open('Makefile', 'w') do |f|
|
|
132
|
+
f.puts <<~MAKEFILE
|
|
133
|
+
CXX = #{RbConfig::CONFIG['CXX'] || 'c++'}
|
|
134
|
+
CXXFLAGS = #{$CXXFLAGS} -fPIC
|
|
135
|
+
LDFLAGS = #{$LDFLAGS} #{$DLDFLAGS}
|
|
136
|
+
|
|
137
|
+
TARGET = #{target}
|
|
138
|
+
SRCS = lldb_wrapper.cpp
|
|
139
|
+
OBJS = lldb_wrapper.o
|
|
140
|
+
|
|
141
|
+
all: $(TARGET)
|
|
142
|
+
|
|
143
|
+
$(TARGET): $(OBJS)
|
|
144
|
+
\t$(CXX) $(LDFLAGS) -o $@ $(OBJS)
|
|
145
|
+
|
|
146
|
+
%.o: %.cpp
|
|
147
|
+
\t$(CXX) $(CXXFLAGS) -c -o $@ $<
|
|
148
|
+
|
|
149
|
+
install: $(TARGET)
|
|
150
|
+
\tmkdir -p $(DESTDIR)#{RbConfig::CONFIG['sitelibdir']}/lldb
|
|
151
|
+
\tcp $(TARGET) $(DESTDIR)#{RbConfig::CONFIG['sitelibdir']}/lldb/
|
|
152
|
+
|
|
153
|
+
clean:
|
|
154
|
+
\trm -f $(OBJS) $(TARGET)
|
|
155
|
+
|
|
156
|
+
.PHONY: all install clean
|
|
157
|
+
MAKEFILE
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
puts 'Makefile created successfully'
|
|
Binary file
|