Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix #7 (gdb only): Merge branch 'breakpoint'
- Loading branch information
Showing
11 changed files
with
373 additions
and
212 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
let s:root_dir = expand('<sfile>:p:h:h:h') | ||
let s:impl = {} | ||
|
||
function s:DoFindSource(file) | ||
exe 'py3 import sys' | ||
exe 'py3 sys.argv = ["' . a:file . '"]' | ||
exe 'py3file ' . s:root_dir . '/lib/gdb_find_source.py' | ||
return return_value | ||
endfunction | ||
|
||
function s:impl.FindSource(file) | ||
if filereadable(a:file) | ||
return fnamemodify(a:file, ':p') | ||
endif | ||
|
||
let ret = s:DoFindSource(a:file) | ||
if !len(ret) | ||
return "" | ||
elseif len(ret) == 1 | ||
return ret[0] | ||
else | ||
" TODO: inputlist() | ||
return "" | ||
endif | ||
endfunction | ||
|
||
function! nvimgdb#gdb#GetImpl() | ||
return s:impl | ||
endfunction |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
let s:impl = {} | ||
|
||
function s:impl.FindSource(file) | ||
return "" | ||
endfunction | ||
|
||
function! nvimgdb#lldb#GetImpl() | ||
return s:impl | ||
endfunction |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import re | ||
import socket | ||
|
||
class InfoSources(gdb.Command): | ||
def __init__(self): | ||
super(InfoSources, self).__init__("nvim-gdb-info-sources", gdb.COMMAND_NONE) | ||
|
||
def invoke(self, arg, from_tty): | ||
output = gdb.execute('info sources', from_tty=False, to_string=True) | ||
sources = "\n".join(sorted([f[0][::-1] for f in re.finditer(r'/[^, \n]+', output)])) | ||
sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM) | ||
sock.sendto(sources.encode('utf-8'), arg) | ||
|
||
InfoSources() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import vim | ||
import socket | ||
import sys | ||
import os | ||
|
||
server_address = '/tmp/nvim-gdb-python-socket' | ||
|
||
# Make sure the socket does not already exist | ||
try: | ||
os.unlink(server_address) | ||
except OSError: | ||
if os.path.exists(server_address): | ||
raise | ||
|
||
# Create a UDS socket | ||
sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM) | ||
sock.bind(server_address) | ||
sock.settimeout(0.5) | ||
|
||
vim.command('call nvimgdb#Send("nvim-gdb-info-sources %s")' % server_address) | ||
|
||
data, addr = sock.recvfrom(65536) | ||
lines = data.decode('utf-8').splitlines() | ||
target = os.path.normpath(sys.argv[0]) | ||
target_min_len = len(os.path.basename(target)) | ||
target = target[::-1] | ||
|
||
def LongestCommonPrefix(a, b): | ||
n = min(len(a), len(b)) | ||
for i in range(n): | ||
if a[i] != b[i]: | ||
return i | ||
return n | ||
|
||
m = target_min_len | ||
result = [] | ||
for l in lines: | ||
x = LongestCommonPrefix(target, l) | ||
if x > m: | ||
m = x | ||
result = [l[::-1]] | ||
elif x == m: | ||
result.append(l[::-1]) | ||
|
||
vim.command('let return_value = ' + str(result)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
#!/usr/bin/python | ||
|
||
import lldb | ||
import os | ||
|
||
|
||
def dump_module_sources(module, result): | ||
if module: | ||
files = set() | ||
print >> result, "Module: %s" % (module.file) | ||
for compile_unit in module.compile_units: | ||
for line_entry in compile_unit: | ||
files.add(os.path.normpath(str(line_entry.GetFileSpec()))) | ||
for f in files: | ||
print >> result, " %s" % str(f) | ||
|
||
|
||
def info_sources(debugger, command, result, dict): | ||
description = '''This command will dump all compile units in any modules that are listed as arguments, or for all modules if no arguments are supplied.''' | ||
target = debugger.GetSelectedTarget() | ||
for module in target.modules: | ||
dump_module_sources(module, result) | ||
|
||
|
||
def __lldb_init_module(debugger, dict): | ||
# Add any commands contained in this module to LLDB | ||
debugger.HandleCommand( | ||
'command script add -f lldb_sources.info_sources info_sources') | ||
print 'The "info_sources" command has been installed, type "help info_sources" or "info_sources --help" for detailed help.' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import os | ||
import time | ||
import re | ||
from neovim import attach | ||
|
||
# Neovim proxy | ||
class Engine: | ||
|
||
delay = 0.5 | ||
|
||
def __init__(self): | ||
os.system('g++ -g src/test.cpp') | ||
addr = os.environ.get('NVIM_LISTEN_ADDRESS') | ||
if addr: | ||
self.nvim = attach('socket', path=addr) | ||
else: | ||
self.nvim = attach('child', argv=["/usr/bin/env", "nvim", "--embed", "-n", "-u", "init.vim"]) | ||
|
||
def Command(self, cmd): | ||
self.nvim.command(cmd) | ||
time.sleep(Engine.delay) | ||
|
||
def GetSigns(self): | ||
out = self.nvim.eval('execute("sign place")') | ||
curline = [int(l) for l in re.findall(r'line=(\d+)\s+id=\d+\s+name=GdbCurrentLine', out)] | ||
assert(len(curline) <= 1) | ||
breaks = [int(l) for l in re.findall(r'line=(\d+)\s+id=\d+\s+name=GdbBreakpoint', out)] | ||
return (curline[0] if curline else -1), breaks | ||
|
||
def KeyStrokeL(self, keys): | ||
self.nvim.input(keys) | ||
time.sleep(Engine.delay) | ||
|
||
def KeyStroke(self, keys): | ||
self.nvim.feedkeys(keys, 't') | ||
time.sleep(Engine.delay) | ||
|
||
def Eval(self, expr): | ||
return self.nvim.eval(expr) | ||
|
||
def CountBuffers(self): | ||
return sum(self.Eval('buflisted(%d)' % (i+1)) for i in range(0, self.Eval('bufnr("$")'))) | ||
|
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
#!/usr/bin/env python | ||
|
||
import unittest | ||
import engine | ||
|
||
|
||
eng = engine.Engine() | ||
subtests = {"gdb": [' dd', '\n'], "lldb": [' dl', '\n']} | ||
|
||
|
||
class TestGdb(unittest.TestCase): | ||
|
||
def test_10_quit(self): | ||
''' => Verify that the session exits correctly on window close ''' | ||
cases = [["<esc>", ":GdbDebugStop<cr>"], ["<esc>","ZZ"], ["<esc>","<c-w>w","ZZ"]] | ||
numBufs = eng.CountBuffers() | ||
for c in cases: | ||
with self.subTest(case=c): | ||
for k in subtests['gdb']: | ||
eng.KeyStrokeL(k) | ||
for k in c: | ||
eng.KeyStrokeL(k) | ||
self.assertEqual(1, eng.Eval('tabpagenr("$")')) | ||
# Check that no new buffers have left | ||
self.assertEqual(numBufs, eng.CountBuffers()) | ||
|
||
def test_20_generic(self): | ||
''' => Test a generic use case ''' | ||
for backend, launch in subtests.items(): | ||
with self.subTest(backend=backend): | ||
for k in launch: | ||
eng.KeyStroke(k) | ||
eng.KeyStroke('tbreak main\n') | ||
eng.KeyStroke('run\n') | ||
eng.KeyStrokeL('<esc>') | ||
|
||
cur, breaks = eng.GetSigns() | ||
self.assertEqual(16, cur) | ||
self.assertFalse(breaks) | ||
|
||
eng.KeyStrokeL('<f10>') | ||
cur, breaks = eng.GetSigns() | ||
self.assertEqual(18, cur) | ||
self.assertFalse(breaks) | ||
|
||
eng.KeyStrokeL('<f11>') | ||
cur, breaks = eng.GetSigns() | ||
self.assertEqual(9, cur) | ||
self.assertFalse(breaks) | ||
|
||
eng.KeyStrokeL('<f12>') | ||
cur, breaks = eng.GetSigns() | ||
self.assertEqual(16, cur) | ||
self.assertFalse(breaks) | ||
|
||
eng.KeyStrokeL('<f5>') | ||
cur, breaks = eng.GetSigns() | ||
self.assertEqual(-1, cur) | ||
self.assertFalse(breaks) | ||
|
||
eng.Command('GdbDebugStop') | ||
|
||
def test_30_breakpoint(self): | ||
''' => Test toggling breakpoints ''' | ||
for backend, launch in subtests.items(): | ||
with self.subTest(backend=backend): | ||
for k in launch: | ||
eng.KeyStroke(k) | ||
eng.KeyStrokeL('<esc><c-w>k') | ||
eng.KeyStroke(":e src/test.cpp\n") | ||
eng.KeyStrokeL(':4<cr>') | ||
eng.KeyStrokeL('<f8>') | ||
cur, breaks = eng.GetSigns() | ||
self.assertEqual(-1, cur) | ||
self.assertListEqual([4], breaks) | ||
|
||
eng.Command("GdbRun") | ||
cur, breaks = eng.GetSigns() | ||
self.assertEqual(4, cur) | ||
self.assertListEqual([4], breaks) | ||
|
||
eng.KeyStrokeL('<f8>') | ||
cur, breaks = eng.GetSigns() | ||
self.assertEqual(4, cur) | ||
self.assertFalse(breaks) | ||
|
||
eng.Command('GdbDebugStop') | ||
|
||
def test_35_breakpoint_cleanup(self): | ||
''' => Verify that breakpoints are cleaned up after session end''' | ||
launch = subtests['gdb'] | ||
for k in launch: | ||
eng.KeyStroke(k) | ||
eng.KeyStrokeL('<esc><c-w>k') | ||
eng.KeyStroke(":e src/test.cpp\n") | ||
eng.KeyStrokeL(':4<cr>') | ||
eng.KeyStrokeL('<f8>') | ||
cur, breaks = eng.GetSigns() | ||
self.assertEqual(-1, cur) | ||
self.assertListEqual([4], breaks) | ||
|
||
eng.Command("GdbDebugStop") | ||
cur, breaks = eng.GetSigns() | ||
self.assertEqual(-1, cur) | ||
self.assertFalse(breaks) | ||
|
||
def test_40_multiview(self): | ||
''' => Test multiple views ''' | ||
# Launch GDB first | ||
for k in subtests['gdb']: | ||
eng.KeyStroke(k) | ||
eng.KeyStroke('tbreak main\n') | ||
eng.KeyStroke('run\n') | ||
eng.KeyStrokeL('<esc>') | ||
eng.KeyStrokeL('<c-w>w') | ||
eng.KeyStrokeL(':10<cr>') | ||
eng.KeyStrokeL('<f8>') | ||
eng.KeyStrokeL('<f10>') | ||
eng.KeyStrokeL('<f11>') | ||
|
||
cur, breaks = eng.GetSigns() | ||
self.assertEqual(9, cur) | ||
self.assertEqual([10], breaks) | ||
|
||
# Then launch LLDB | ||
for k in subtests['lldb']: | ||
eng.KeyStroke(k) | ||
eng.KeyStroke('tbreak main\n') | ||
eng.KeyStroke('run\n') | ||
eng.KeyStrokeL('<esc>') | ||
eng.KeyStrokeL('<c-w>w') | ||
eng.KeyStrokeL(':4<cr>') | ||
eng.KeyStrokeL('<f8>') | ||
eng.KeyStrokeL(':11<cr>') | ||
eng.KeyStrokeL('<f8>') | ||
eng.KeyStrokeL('<f10>') | ||
|
||
cur, breaks = eng.GetSigns() | ||
self.assertEqual(18, cur) | ||
self.assertEqual([4, 11], breaks) | ||
|
||
# Switch to GDB | ||
eng.KeyStrokeL('2gt') | ||
cur, breaks = eng.GetSigns() | ||
self.assertEqual(9, cur) | ||
self.assertEqual([10], breaks) | ||
|
||
# Quit GDB | ||
eng.KeyStrokeL('ZZ') | ||
|
||
# Switch back to LLDB | ||
cur, breaks = eng.GetSigns() | ||
self.assertEqual(18, cur) | ||
self.assertEqual([4, 11], breaks) | ||
|
||
# Quit LLDB | ||
eng.KeyStrokeL('ZZ') | ||
|
||
|
||
if __name__ == "__main__": | ||
unittest.main() |
Oops, something went wrong.