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,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
@@ -0,0 +1,14 @@
1
+ #include <stdio.h>
2
+
3
+ int add(int a, int b) {
4
+ int result = a + b;
5
+ return result;
6
+ }
7
+
8
+ int main(int argc, char** argv) {
9
+ int x = 10;
10
+ int y = 20;
11
+ int sum = add(x, y);
12
+ printf("Sum: %d\n", sum);
13
+ return 0;
14
+ }
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
@@ -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