Skip to content

Commit c9651cd

Browse files
Initial LLDB support.
1 parent fbb8747 commit c9651cd

94 files changed

Lines changed: 3341 additions & 252 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/test.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ jobs:
3434
with:
3535
ruby-version: ${{matrix.ruby}}
3636
bundler-cache: true
37-
apt-get: gdb
37+
apt-get: gdb lldb
3838

3939
- name: Run tests
4040
timeout-minutes: 10

bake/toolbox/gdb.rb

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
# frozen_string_literal: true
2+
3+
# Released under the MIT License.
4+
# Copyright, 2025, by Samuel Williams.
5+
6+
require "toolbox/gdb"
7+
require "fileutils"
8+
9+
# Install GDB extensions by adding source line to ~/.gdbinit
10+
# @parameter gdbinit [String] Optional path to .gdbinit (defaults to ~/.gdbinit)
11+
def install(gdbinit: nil)
12+
gdbinit_path = gdbinit || File.join(Dir.home, ".gdbinit")
13+
init_py_path = Toolbox::GDB.init_script_path
14+
source_line = "source #{init_py_path}"
15+
marker_comment = "# Ruby Toolbox GDB Extensions"
16+
17+
puts "Installing Ruby Toolbox GDB extensions..."
18+
puts " Extensions: #{File.dirname(init_py_path)}"
19+
puts " Config: #{gdbinit_path}"
20+
21+
# Read existing .gdbinit or create empty array
22+
lines = File.exist?(gdbinit_path) ? File.readlines(gdbinit_path) : []
23+
24+
# Check if already installed (look for marker comment)
25+
marker_index = lines.index{|line| line.strip == marker_comment}
26+
27+
if marker_index
28+
# Already installed - update the source line in case path changed
29+
source_index = marker_index + 1
30+
if source_index < lines.size && lines[source_index].strip.start_with?("source")
31+
old_source = lines[source_index].strip
32+
if old_source == source_line
33+
puts "\n✓ Already installed in #{gdbinit_path}"
34+
puts " #{source_line}"
35+
return
36+
else
37+
# Path changed - update it
38+
lines[source_index] = "#{source_line}\n"
39+
File.write(gdbinit_path, lines.join)
40+
puts "\n✓ Updated installation in #{gdbinit_path}"
41+
puts " Old: #{old_source}"
42+
puts " New: #{source_line}"
43+
return
44+
end
45+
end
46+
end
47+
48+
# Not installed - add it
49+
File.open(gdbinit_path, "a") do |f|
50+
f.puts unless lines.last&.strip&.empty?
51+
f.puts marker_comment
52+
f.puts source_line
53+
end
54+
55+
puts "\n✓ Installation complete!"
56+
puts "\nAdded to #{gdbinit_path}:"
57+
puts " #{source_line}"
58+
puts "\nExtensions will load automatically when you start GDB."
59+
end
60+
61+
# Uninstall GDB extensions by removing source line from ~/.gdbinit
62+
# @parameter gdbinit [String] Optional path to .gdbinit (defaults to ~/.gdbinit)
63+
def uninstall(gdbinit: nil)
64+
gdbinit_path = gdbinit || File.join(Dir.home, ".gdbinit")
65+
marker_comment = "# Ruby Toolbox GDB Extensions"
66+
67+
puts "Uninstalling Ruby Toolbox GDB extensions..."
68+
69+
unless File.exist?(gdbinit_path)
70+
puts "No ~/.gdbinit file found - nothing to uninstall."
71+
return
72+
end
73+
74+
lines = File.readlines(gdbinit_path)
75+
marker_index = lines.index{|line| line.strip == marker_comment}
76+
77+
unless marker_index
78+
puts "Extensions were not found in #{gdbinit_path}"
79+
return
80+
end
81+
82+
# Remove the marker comment and the source line after it
83+
lines.delete_at(marker_index) # Remove comment
84+
if marker_index < lines.size && lines[marker_index].strip.start_with?("source")
85+
removed_line = lines.delete_at(marker_index).strip # Remove source line
86+
puts " Removed: #{removed_line}"
87+
end
88+
89+
# Clean up empty line before marker if it exists
90+
if marker_index > 0 && lines[marker_index - 1].strip.empty?
91+
lines.delete_at(marker_index - 1)
92+
end
93+
94+
File.write(gdbinit_path, lines.join)
95+
puts "✓ Removed Ruby Toolbox GDB extensions from #{gdbinit_path}"
96+
end
97+
98+
# Show installation information
99+
# @parameter gdbinit [String] Optional path to .gdbinit (defaults to ~/.gdbinit)
100+
def info(gdbinit: nil)
101+
gdbinit_path = gdbinit || File.join(Dir.home, ".gdbinit")
102+
init_py_path = Toolbox::GDB.init_script_path
103+
marker_comment = "# Ruby Toolbox GDB Extensions"
104+
105+
puts "Ruby Toolbox GDB Extensions v#{Toolbox::VERSION}"
106+
puts "\nToolbox directory: #{Toolbox::GDB.data_path}"
107+
puts "Init script: #{init_py_path}"
108+
puts "Note: Same init.py works for both GDB and LLDB"
109+
110+
# Check installation status by looking for marker comment
111+
installed = false
112+
current_source = nil
113+
114+
if File.exist?(gdbinit_path)
115+
lines = File.readlines(gdbinit_path)
116+
marker_index = lines.index{|line| line.strip == marker_comment}
117+
if marker_index
118+
installed = true
119+
source_index = marker_index + 1
120+
if source_index < lines.size
121+
current_source = lines[source_index].strip
122+
end
123+
end
124+
end
125+
126+
puts "\nGDB config: #{gdbinit_path}"
127+
if installed
128+
puts "Status: ✓ Installed"
129+
if current_source
130+
puts " #{current_source}"
131+
end
132+
else
133+
puts "Status: ✗ Not installed"
134+
puts "\nRun: bake toolbox:gdb:install"
135+
end
136+
end
137+

bake/toolbox/lldb.rb

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
# frozen_string_literal: true
2+
3+
# Released under the MIT License.
4+
# Copyright, 2025, by Samuel Williams.
5+
6+
require "toolbox/lldb"
7+
require "fileutils"
8+
9+
# Install LLDB extensions by adding command to ~/.lldbinit
10+
# @parameter lldbinit [String] Optional path to .lldbinit (defaults to ~/.lldbinit)
11+
def install(lldbinit: nil)
12+
lldbinit_path = lldbinit || File.join(Dir.home, ".lldbinit")
13+
init_py_path = Toolbox::LLDB.init_script_path
14+
command_line = "command script import #{init_py_path}"
15+
marker_comment = "# Ruby Toolbox LLDB Extensions"
16+
17+
puts "Installing Ruby Toolbox LLDB extensions..."
18+
puts " Extensions: #{File.dirname(init_py_path)}"
19+
puts " Config: #{lldbinit_path}"
20+
21+
# Read existing .lldbinit or create empty array
22+
lines = File.exist?(lldbinit_path) ? File.readlines(lldbinit_path) : []
23+
24+
# Check if already installed (look for marker comment)
25+
marker_index = lines.index{|line| line.strip == marker_comment}
26+
27+
if marker_index
28+
# Already installed - update the command line in case path changed
29+
command_index = marker_index + 1
30+
if command_index < lines.size && lines[command_index].strip.start_with?("command script import")
31+
old_command = lines[command_index].strip
32+
if old_command == command_line
33+
puts "\n✓ Already installed in #{lldbinit_path}"
34+
puts " #{command_line}"
35+
return
36+
else
37+
# Path changed - update it
38+
lines[command_index] = "#{command_line}\n"
39+
File.write(lldbinit_path, lines.join)
40+
puts "\n✓ Updated installation in #{lldbinit_path}"
41+
puts " Old: #{old_command}"
42+
puts " New: #{command_line}"
43+
return
44+
end
45+
end
46+
end
47+
48+
# Not installed - add it
49+
File.open(lldbinit_path, "a") do |f|
50+
f.puts unless lines.last&.strip&.empty?
51+
f.puts marker_comment
52+
f.puts command_line
53+
end
54+
55+
puts "\n✓ Installation complete!"
56+
puts "\nAdded to #{lldbinit_path}:"
57+
puts " #{command_line}"
58+
puts "\nExtensions will load automatically when you start LLDB."
59+
end
60+
61+
# Uninstall LLDB extensions by removing command from ~/.lldbinit
62+
# @parameter lldbinit [String] Optional path to .lldbinit (defaults to ~/.lldbinit)
63+
def uninstall(lldbinit: nil)
64+
lldbinit_path = lldbinit || File.join(Dir.home, ".lldbinit")
65+
marker_comment = "# Ruby Toolbox LLDB Extensions"
66+
67+
puts "Uninstalling Ruby Toolbox LLDB extensions..."
68+
69+
unless File.exist?(lldbinit_path)
70+
puts "No ~/.lldbinit file found - nothing to uninstall."
71+
return
72+
end
73+
74+
lines = File.readlines(lldbinit_path)
75+
marker_index = lines.index{|line| line.strip == marker_comment}
76+
77+
unless marker_index
78+
puts "Extensions were not found in #{lldbinit_path}"
79+
return
80+
end
81+
82+
# Remove the marker comment and the command line after it
83+
lines.delete_at(marker_index) # Remove comment
84+
if marker_index < lines.size && lines[marker_index].strip.start_with?("command script import")
85+
removed_line = lines.delete_at(marker_index).strip # Remove command line
86+
puts " Removed: #{removed_line}"
87+
end
88+
89+
# Clean up empty line before marker if it exists
90+
if marker_index > 0 && lines[marker_index - 1].strip.empty?
91+
lines.delete_at(marker_index - 1)
92+
end
93+
94+
File.write(lldbinit_path, lines.join)
95+
puts "✓ Removed Ruby Toolbox LLDB extensions from #{lldbinit_path}"
96+
end
97+
98+
# Show installation information
99+
# @parameter lldbinit [String] Optional path to .lldbinit (defaults to ~/.lldbinit)
100+
def info(lldbinit: nil)
101+
lldbinit_path = lldbinit || File.join(Dir.home, ".lldbinit")
102+
init_py_path = Toolbox::LLDB.init_script_path
103+
marker_comment = "# Ruby Toolbox LLDB Extensions"
104+
105+
puts "Ruby Toolbox LLDB Extensions v#{Toolbox::VERSION}"
106+
puts "\nToolbox directory: #{Toolbox::LLDB.data_path}"
107+
puts "Init script: #{init_py_path}"
108+
puts "Note: Same init.py works for both GDB and LLDB"
109+
110+
# Check installation status by looking for marker comment
111+
installed = false
112+
current_command = nil
113+
114+
if File.exist?(lldbinit_path)
115+
lines = File.readlines(lldbinit_path)
116+
marker_index = lines.index{|line| line.strip == marker_comment}
117+
if marker_index
118+
installed = true
119+
command_index = marker_index + 1
120+
if command_index < lines.size
121+
current_command = lines[command_index].strip
122+
end
123+
end
124+
end
125+
126+
puts "\nLLDB config: #{lldbinit_path}"
127+
if installed
128+
puts "Status: ✓ Installed"
129+
if current_command
130+
puts " #{current_command}"
131+
end
132+
else
133+
puts "Status: ✗ Not installed"
134+
puts "\nRun: bake toolbox:lldb:install"
135+
end
136+
end
137+

data/ruby/gdb/constants.py

Lines changed: 0 additions & 59 deletions
This file was deleted.

data/ruby/gdb/init.py

Lines changed: 0 additions & 25 deletions
This file was deleted.

0 commit comments

Comments
 (0)