From ba9cb2f6d363a3e86fd00bd49290f9d4749f8a31 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Fri, 4 Jun 2021 19:40:00 +0100 Subject: [PATCH 01/23] WIP: First sort-of untested attempt at readmemory request --- autoload/vimspector.vim | 7 ++++++ python3/vimspector/code.py | 17 ++++++++++++++ python3/vimspector/debug_session.py | 29 ++++++++++++++++++++++- python3/vimspector/settings.py | 3 ++- python3/vimspector/variables.py | 36 +++++++++++++++++++++++++++-- 5 files changed, 88 insertions(+), 4 deletions(-) diff --git a/autoload/vimspector.vim b/autoload/vimspector.vim index 78c7c1b..0eb394f 100644 --- a/autoload/vimspector.vim +++ b/autoload/vimspector.vim @@ -223,6 +223,13 @@ function! vimspector#SetVariableValue( ... ) abort endif endfunction +function! vimspector#ReadMemory() abort + if !s:Enabled() + return + endif + py3 _vimspector_session.ReadMemory() +endfunction + function! vimspector#DeleteWatch() abort if !s:Enabled() return diff --git a/python3/vimspector/code.py b/python3/vimspector/code.py index 98aeca5..37fe23b 100644 --- a/python3/vimspector/code.py +++ b/python3/vimspector/code.py @@ -16,6 +16,7 @@ import vim import logging import json +import os from collections import defaultdict from vimspector import utils, terminal, signs @@ -40,6 +41,7 @@ class CodeView( object ): 'breakpoints': [] } self._current_frame = None + self._scratch_buffers = [] with utils.LetCurrentWindow( self._window ): if utils.UseWinBar(): @@ -173,6 +175,10 @@ class CodeView( object ): self.ClearBreakpoints() self.Clear() + for b in self._scratch_buffers: + utils.CleanUpHiddenBuffer( b ) + self._scratch_buffers = [] + def AddBreakpoints( self, source, breakpoints ): for breakpoint in breakpoints: source = breakpoint.get( 'source' ) or source @@ -287,3 +293,14 @@ class CodeView( object ): # FIXME: Change this tor return the PID rather than having debug_session # work that out return self._terminal.buffer_number + + + def ShowMemory( self, memoryReference, msg ): + buf_name = os.path.join( '_vimspector_mem', memoryReference ) + buf = utils.BufferForFile( buf_name ) + self._scratch_buffers.append( buf ) + utils.SetUpHiddenBuffer( buf, buf_name ) + with utils.ModifiableScratchBuffer( buf ): + utils.SetBufferContents( + buf, + msg.get( 'body', {} ).get( 'data', 'Cannot read memory' ) ) diff --git a/python3/vimspector/debug_session.py b/python3/vimspector/debug_session.py index 36ad62b..3fc983a 100644 --- a/python3/vimspector/debug_session.py +++ b/python3/vimspector/debug_session.py @@ -535,6 +535,32 @@ class DebugSession( object ): def SetVariableValue( self, new_value = None, buf = None, line_num = None ): self._variablesView.SetVariableValue( new_value, buf, line_num ) + @IfConnected() + def ReadMemory( self, buf = None, line_num = None ): + if not self._server_capabilities.get( 'supportsReadMemoryRequest' ): + utils.UserMessage( "Server does not support memory request", + error = True ) + return + + memoryReference = self._variablesView.GetMemoryReference( buf, line_num ) + + if memoryReference is None: + utils.UserMessage( "Cannot find memory reference for that", + error = True ) + return + + def handler( msg ): + self._codeView.ShowMemory( msg ) + + self._connection.DoRequest( handler, { + 'command': 'readMemory', + 'arguments': { + 'memoryReference': memoryReference, + 'count': 10 # TODO: What + } + } ) + + @IfConnected() def AddWatch( self, expression ): self._variablesView.AddWatch( self._stackTraceView.GetCurrentFrame(), @@ -1163,7 +1189,8 @@ class DebugSession( object ): 'pathFormat': 'path', 'supportsVariableType': True, 'supportsVariablePaging': False, - 'supportsRunInTerminalRequest': True + 'supportsRunInTerminalRequest': True, + 'supportsMemoryReferences': True }, } ) diff --git a/python3/vimspector/settings.py b/python3/vimspector/settings.py index 89378af..60e8341 100644 --- a/python3/vimspector/settings.py +++ b/python3/vimspector/settings.py @@ -54,7 +54,8 @@ DEFAULTS = { 'variables': { 'expand_collapse': [ '', '<2-LeftMouse>' ], 'delete': [ '' ], - 'set_value': [ '', '' ] + 'set_value': [ '', '' ], + 'read_memory': [ 'm' ], }, 'stack_trace': { 'expand_or_jump': [ '', '<2-LeftMouse>' ], diff --git a/python3/vimspector/variables.py b/python3/vimspector/variables.py index 8dcb493..8524d67 100644 --- a/python3/vimspector/variables.py +++ b/python3/vimspector/variables.py @@ -56,6 +56,11 @@ class Expandable: def VariablesReference( self ): assert False + @abc.abstractmethod + def MemoryReference( self ): + assert None + + class Scope( Expandable ): """Holds an expandable scope (a DAP scope dict), with expand/collapse state""" @@ -66,6 +71,9 @@ class Scope( Expandable ): def VariablesReference( self ): return self.scope.get( 'variablesReference', 0 ) + def MemoryReference( self ): + return None + def Update( self, scope ): self.scope = scope @@ -81,6 +89,9 @@ class WatchResult( Expandable ): def VariablesReference( self ): return self.result.get( 'variablesReference', 0 ) + def MemoryReference( self ): + return self.result.get( 'memoryReference' ) + def Update( self, result ): self.changed = False if self.result[ 'result' ] != result[ 'result' ]: @@ -105,6 +116,9 @@ class Variable( Expandable ): def VariablesReference( self ): return self.variable.get( 'variablesReference', 0 ) + def MemoryReference( self ): + return self.variable.get( 'memoryReference' ) + def Update( self, variable ): self.changed = False if self.variable[ 'value' ] != variable[ 'value' ]: @@ -163,6 +177,10 @@ def AddExpandMappings( mappings = None ): for mapping in utils.GetVimList( mappings, 'set_value' ): vim.command( f'nnoremap { mapping } ' ':call vimspector#SetVariableValue()' ) + for mapping in utils.GetVimList( mappings, 'read_memory' ): + vim.command( f'nnoremap { mapping } ' + ':call vimspector#ReadMemory()' ) + class VariablesView( object ): @@ -187,6 +205,8 @@ class VariablesView( object ): if utils.UseWinBar(): vim.command( 'nnoremenu 1.1 WinBar.Set ' ':call vimspector#SetVariableValue()' ) + vim.command( 'nnoremenu 1.2 WinBar.Memory ' + ':call vimspector#ReadMemory()' ) AddExpandMappings( mappings ) # Set up the "Watches" buffer in the watches_win (and create a WinBar in @@ -211,8 +231,10 @@ class VariablesView( object ): ':call vimspector#ExpandVariable()' ) vim.command( 'nnoremenu 1.3 WinBar.Delete ' ':call vimspector#DeleteWatch()' ) - vim.command( 'nnoremenu 1.1 WinBar.Set ' + vim.command( 'nnoremenu 1.4 WinBar.Set ' ':call vimspector#SetVariableValue()' ) + vim.command( 'nnoremenu 1.5 WinBar.Memory ' + ':call vimspector#ReadMemory()' ) # Set the (global!) balloon expr if supported has_balloon = int( vim.eval( "has( 'balloon_eval' )" ) ) @@ -580,6 +602,14 @@ class VariablesView( object ): }, failure_handler = failure_handler ) + def GetMemoryReference( self, buf = None, line_num = None ): + # Get a memoryReference for use in a ReadMemory request + variable, _ = self._GetVariable( buf, line_num ) + if variable is None: + return None + + return variable.MemoryReference() + def _DrawVariables( self, view, variables, indent, is_short = False ): assert indent > 0 @@ -595,10 +625,12 @@ class VariablesView( object ): value = variable.variable.get( 'value', '' ) ) else: + marker = 'm' if variable.MemoryReference() is not None else ' ' + marker += '*' if variable.changed else ' ' text = '{indent}{marker}{icon} {name} ({type_}): {value}'.format( # We borrow 1 space of indent to draw the change marker indent = ' ' * ( indent - 1 ), - marker = '*' if variable.changed else ' ', + marker = marker, icon = '+' if ( variable.IsExpandable() and not variable.IsExpanded() ) else '-', name = variable.variable.get( 'name', '' ), From 61a62c5ab5115f721c1ece8308320d8f642931fb Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Fri, 4 Jun 2021 19:40:13 +0100 Subject: [PATCH 02/23] Update CodeLLDB to support readMemeory --- python3/vimspector/gadgets.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/python3/vimspector/gadgets.py b/python3/vimspector/gadgets.py index 23a298c..140c9f4 100644 --- a/python3/vimspector/gadgets.py +++ b/python3/vimspector/gadgets.py @@ -394,12 +394,12 @@ GADGETS = { '${version}/${file_name}', }, 'all': { - 'version': 'v1.6.1', + 'version': 'v1.6.4', }, 'macos': { 'file_name': 'codelldb-x86_64-darwin.vsix', 'checksum': - 'b1c998e7421beea9f3ba21aa5706210bb2249eba93c99b809247ee831075262f', + 'aa920b7b7d2ad4e9d70086355841b0b4844fb5f62cdea1296904100a1b660776', 'make_executable': [ 'adapter/codelldb', 'lldb/bin/debugserver', @@ -410,7 +410,7 @@ GADGETS = { 'linux': { 'file_name': 'codelldb-x86_64-linux.vsix', 'checksum': - 'f2a36cb6971fd95a467cf1a7620e160914e8f11bf82929932ee0aa5afbf6ae6a', + '', 'make_executable': [ 'adapter/codelldb', 'lldb/bin/lldb', @@ -421,7 +421,7 @@ GADGETS = { 'windows': { 'file_name': 'codelldb-x86_64-windows.vsix', 'checksum': - 'ca6a6525bf7719dc95265dc630b3cc817a8c0393b756fd242b710805ffdfb940', + '', 'make_executable': [] }, 'adapters': { From f09cd89384f667128d60061687b5413e83284194 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Fri, 4 Jun 2021 22:16:28 +0100 Subject: [PATCH 03/23] Make a sort of memory view work by dumping using hexdump.py --- python3/vimspector/code.py | 13 +- python3/vimspector/debug_session.py | 4 +- python3/vimspector/utils.py | 7 + python3/vimspector/vendor/hexdump.py | 466 +++++++++++++++++++++++++++ 4 files changed, 485 insertions(+), 5 deletions(-) create mode 100755 python3/vimspector/vendor/hexdump.py diff --git a/python3/vimspector/code.py b/python3/vimspector/code.py index 37fe23b..635a12f 100644 --- a/python3/vimspector/code.py +++ b/python3/vimspector/code.py @@ -296,11 +296,18 @@ class CodeView( object ): def ShowMemory( self, memoryReference, msg ): + if not self._window.valid: + return False + buf_name = os.path.join( '_vimspector_mem', memoryReference ) buf = utils.BufferForFile( buf_name ) self._scratch_buffers.append( buf ) utils.SetUpHiddenBuffer( buf, buf_name ) with utils.ModifiableScratchBuffer( buf ): - utils.SetBufferContents( - buf, - msg.get( 'body', {} ).get( 'data', 'Cannot read memory' ) ) + # TODO: The data is encoded in base64, so we need to convert that to the + # equivalent output of say xxd + data = msg.get( 'body', {} ).get( 'data', '' ) + utils.SetBufferContents( buf, utils.Base64ToHexDump( data ) ) + + utils.JumpToWindow( self._window ) + utils.OpenFileInCurrentWindow( buf_name ) diff --git a/python3/vimspector/debug_session.py b/python3/vimspector/debug_session.py index 3fc983a..bd93967 100644 --- a/python3/vimspector/debug_session.py +++ b/python3/vimspector/debug_session.py @@ -550,13 +550,13 @@ class DebugSession( object ): return def handler( msg ): - self._codeView.ShowMemory( msg ) + self._codeView.ShowMemory( memoryReference, msg ) self._connection.DoRequest( handler, { 'command': 'readMemory', 'arguments': { 'memoryReference': memoryReference, - 'count': 10 # TODO: What + 'count': 1024 # TODO: What } } ) diff --git a/python3/vimspector/utils.py b/python3/vimspector/utils.py index 5f836fc..150ab95 100644 --- a/python3/vimspector/utils.py +++ b/python3/vimspector/utils.py @@ -25,7 +25,9 @@ import shlex import collections import re import typing +import base64 +from vimspector.vendor.hexdump import hexdump LOG_FILE = os.path.expanduser( os.path.join( '~', '.vimspector.log' ) ) @@ -864,3 +866,8 @@ def UseWinBar(): # Buggy neovim doesn't render correctly when the WinBar is defined: # https://github.com/neovim/neovim/issues/12689 return not int( Call( 'has', 'nvim' ) ) + + +def Base64ToHexDump( data ): + data = base64.b64decode( data ) + return list( hexdump( data, 'generator' ) ) diff --git a/python3/vimspector/vendor/hexdump.py b/python3/vimspector/vendor/hexdump.py new file mode 100755 index 0000000..33b9b6b --- /dev/null +++ b/python3/vimspector/vendor/hexdump.py @@ -0,0 +1,466 @@ +#!/usr/bin/env python +# -*- coding: latin-1 -*- + +# <-- removing this magic comment breaks Python 3.4 on Windows +""" +1. Dump binary data to the following text format: + +00000000: 00 00 00 5B 68 65 78 64 75 6D 70 5D 00 00 00 00 ...[hexdump].... +00000010: 00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF .."3DUfw........ + +It is similar to the one used by: +Scapy +00 00 00 5B 68 65 78 64 75 6D 70 5D 00 00 00 00 ...[hexdump].... +00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF .."3DUfw........ + +Far Manager +000000000: 00 00 00 5B 68 65 78 64 ¦ 75 6D 70 5D 00 00 00 00 [hexdump] +000000010: 00 11 22 33 44 55 66 77 ¦ 88 99 AA BB CC DD EE FF ?"3DUfwˆ™ª»ÌÝîÿ + + +2. Restore binary data from the formats above as well + as from less exotic strings of raw hex + +""" + +__version__ = '3.3' +__author__ = 'anatoly techtonik ' +__license__ = 'Public Domain' + +__history__ = \ +""" +3.3 (2015-01-22) + * accept input from sys.stdin if "-" is specified + for both dump and restore (issue #1) + * new normalize_py() helper to set sys.stdout to + binary mode on Windows + +3.2 (2015-07-02) + * hexdump is now packaged as .zip on all platforms + (on Linux created archive was tar.gz) + * .zip is executable! try `python hexdump-3.2.zip` + * dump() now accepts configurable separator, patch + by Ian Land (PR #3) + +3.1 (2014-10-20) + * implemented workaround against mysterious coding + issue with Python 3 (see revision 51302cf) + * fix Python 3 installs for systems where UTF-8 is + not default (Windows), thanks to George Schizas + (the problem was caused by reading of README.txt) + +3.0 (2014-09-07) + * remove unused int2byte() helper + * add dehex(text) helper to convert hex string + to binary data + * add 'size' argument to dump() helper to specify + length of chunks + +2.0 (2014-02-02) + * add --restore option to command line mode to get + binary data back from hex dump + * support saving test output with `--test logfile` + * restore() from hex strings without spaces + * restore() now raises TypeError if input data is + not string + * hexdump() and dumpgen() now don't return unicode + strings in Python 2.x when generator is requested + +1.0 (2013-12-30) + * length of address is reduced from 10 to 8 + * hexdump() got new 'result' keyword argument, it + can be either 'print', 'generator' or 'return' + * actual dumping logic is now in new dumpgen() + generator function + * new dump(binary) function that takes binary data + and returns string like "66 6F 72 6D 61 74" + * new genchunks(mixed, size) function that chunks + both sequences and file like objects + +0.5 (2013-06-10) + * hexdump is now also a command line utility (no + restore yet) + +0.4 (2013-06-09) + * fix installation with Python 3 for non English + versions of Windows, thanks to George Schizas + +0.3 (2013-04-29) + * fully Python 3 compatible + +0.2 (2013-04-28) + * restore() to recover binary data from a hex dump in + native, Far Manager and Scapy text formats (others + might work as well) + * restore() is Python 3 compatible + +0.1 (2013-04-28) + * working hexdump() function for Python 2 +""" + +import binascii # binascii is required for Python 3 +import sys + +# --- constants +PY3K = sys.version_info >= (3, 0) + +# --- workaround against Python consistency issues +def normalize_py(): + ''' Problem 001 - sys.stdout in Python is by default opened in + text mode, and writes to this stdout produce corrupted binary + data on Windows + + python -c "import sys; sys.stdout.write('_\n_')" > file + python -c "print(repr(open('file', 'rb').read()))" + ''' + if sys.platform == "win32": + # set sys.stdout to binary mode on Windows + import os, msvcrt + msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY) + +# --- - chunking helpers +def chunks(seq, size): + '''Generator that cuts sequence (bytes, memoryview, etc.) + into chunks of given size. If `seq` length is not multiply + of `size`, the lengh of the last chunk returned will be + less than requested. + + >>> list( chunks([1,2,3,4,5,6,7], 3) ) + [[1, 2, 3], [4, 5, 6], [7]] + ''' + d, m = divmod(len(seq), size) + for i in range(d): + yield seq[i*size:(i+1)*size] + if m: + yield seq[d*size:] + +def chunkread(f, size): + '''Generator that reads from file like object. May return less + data than requested on the last read.''' + c = f.read(size) + while len(c): + yield c + c = f.read(size) + +def genchunks(mixed, size): + '''Generator to chunk binary sequences or file like objects. + The size of the last chunk returned may be less than + requested.''' + if hasattr(mixed, 'read'): + return chunkread(mixed, size) + else: + return chunks(mixed, size) +# --- - /chunking helpers + + +def dehex(hextext): + """ + Convert from hex string to binary data stripping + whitespaces from `hextext` if necessary. + """ + if PY3K: + return bytes.fromhex(hextext) + else: + hextext = "".join(hextext.split()) + return hextext.decode('hex') + +def dump(binary, size=2, sep=' '): + ''' + Convert binary data (bytes in Python 3 and str in + Python 2) to hex string like '00 DE AD BE EF'. + `size` argument specifies length of text chunks + and `sep` sets chunk separator. + ''' + hexstr = binascii.hexlify(binary) + if PY3K: + hexstr = hexstr.decode('ascii') + return sep.join(chunks(hexstr.upper(), size)) + +def dumpgen(data): + ''' + Generator that produces strings: + + '00000000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................' + ''' + generator = genchunks(data, 16) + for addr, d in enumerate(generator): + # 00000000: + line = '%08X: ' % (addr*16) + # 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + dumpstr = dump(d) + line += dumpstr[:8*3] + if len(d) > 8: # insert separator if needed + line += ' ' + dumpstr[8*3:] + # ................ + # calculate indentation, which may be different for the last line + pad = 2 + if len(d) < 16: + pad += 3*(16 - len(d)) + if len(d) <= 8: + pad += 1 + line += ' '*pad + + for byte in d: + # printable ASCII range 0x20 to 0x7E + if not PY3K: + byte = ord(byte) + if 0x20 <= byte <= 0x7E: + line += chr(byte) + else: + line += '.' + yield line + +def hexdump(data, result='print'): + ''' + Transform binary data to the hex dump text format: + + 00000000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ + + [x] data argument as a binary string + [x] data argument as a file like object + + Returns result depending on the `result` argument: + 'print' - prints line by line + 'return' - returns single string + 'generator' - returns generator that produces lines + ''' + if PY3K and type(data) == str: + raise TypeError('Abstract unicode data (expected bytes sequence)') + + gen = dumpgen(data) + if result == 'generator': + return gen + elif result == 'return': + return '\n'.join(gen) + elif result == 'print': + for line in gen: + print(line) + else: + raise ValueError('Unknown value of `result` argument') + +def restore(dump): + ''' + Restore binary data from a hex dump. + [x] dump argument as a string + [ ] dump argument as a line iterator + + Supported formats: + [x] hexdump.hexdump + [x] Scapy + [x] Far Manager + ''' + minhexwidth = 2*16 # minimal width of the hex part - 00000... style + bytehexwidth = 3*16-1 # min width for a bytewise dump - 00 00 ... style + + result = bytes() if PY3K else '' + if type(dump) != str: + raise TypeError('Invalid data for restore') + + text = dump.strip() # ignore surrounding empty lines + for line in text.split('\n'): + # strip address part + addrend = line.find(':') + if 0 < addrend < minhexwidth: # : is not in ascii part + line = line[addrend+1:] + line = line.lstrip() + # check dump type + if line[2] == ' ': # 00 00 00 ... type of dump + # check separator + sepstart = (2+1)*7+2 # ('00'+' ')*7+'00' + sep = line[sepstart:sepstart+3] + if sep[:2] == ' ' and sep[2:] != ' ': # ...00 00 00 00... + hexdata = line[:bytehexwidth+1] + elif sep[2:] == ' ': # ...00 00 | 00 00... - Far Manager + hexdata = line[:sepstart] + line[sepstart+3:bytehexwidth+2] + else: # ...00 00 00 00... - Scapy, no separator + hexdata = line[:bytehexwidth] + line = hexdata + result += dehex(line) + return result + + +def runtest(logfile=None): + '''Run hexdump tests. Requires hexfile.bin to be in the same + directory as hexdump.py itself''' + + class TeeOutput(object): + def __init__(self, stream1, stream2): + self.outputs = [stream1, stream2] + + # -- methods from sys.stdout / sys.stderr + def write(self, data): + for stream in self.outputs: + if PY3K: + if 'b' in stream.mode: + data = data.encode('utf-8') + stream.write(data) + stream.flush() + + def tell(self): + raise IOError + + def flush(self): + for stream in self.outputs: + stream.flush() + # --/ sys.stdout + + if logfile: + openlog = open(logfile, 'wb') + # copy stdout and stderr streams to log file + savedstd = sys.stderr, sys.stdout + sys.stderr = TeeOutput(sys.stderr, openlog) + sys.stdout = TeeOutput(sys.stdout, openlog) + + + def echo(msg, linefeed=True): + sys.stdout.write(msg) + if linefeed: + sys.stdout.write('\n') + + expected = '''\ +00000000: 00 00 00 5B 68 65 78 64 75 6D 70 5D 00 00 00 00 ...[hexdump].... +00000010: 00 11 22 33 44 55 66 77 88 99 0A BB CC DD EE FF .."3DUfw........\ +''' + + # get path to hexfile.bin + # this doesn't work from .zip + # import os.path as osp + # hexfile = osp.dirname(osp.abspath(__file__)) + '/hexfile.bin' + # this doesn't work either + # hexfile = osp.dirname(sys.modules[__name__].__file__) + '/hexfile.bin' + # this works + import pkgutil + bin = pkgutil.get_data('hexdump', 'data/hexfile.bin') + + # varios length of input data + hexdump(b'zzzz'*12) + hexdump(b'o'*17) + hexdump(b'p'*24) + hexdump(b'q'*26) + # allowable character set filter + hexdump(b'line\nfeed\r\ntest') + hexdump(b'\x00\x00\x00\x5B\x68\x65\x78\x64\x75\x6D\x70\x5D\x00\x00\x00\x00' + b'\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\x0A\xBB\xCC\xDD\xEE\xFF') + print('---') + # dumping file-like binary object to screen (default behavior) + hexdump(bin) + print('return output') + hexout = hexdump(bin, result='return') + assert hexout == expected, 'returned hex didn\'t match' + print('return generator') + hexgen = hexdump(bin, result='generator') + assert next(hexgen) == expected.split('\n')[0], 'hex generator 1 didn\'t match' + assert next(hexgen) == expected.split('\n')[1], 'hex generator 2 didn\'t match' + + # binary restore test + bindata = restore( +''' +00000000: 00 00 00 5B 68 65 78 64 75 6D 70 5D 00 00 00 00 ...[hexdump].... +00000010: 00 11 22 33 44 55 66 77 88 99 0A BB CC DD EE FF .."3DUfw........ +''') + echo('restore check ', linefeed=False) + assert bin == bindata, 'restore check failed' + echo('passed') + + far = \ +''' +000000000: 00 00 00 5B 68 65 78 64 ¦ 75 6D 70 5D 00 00 00 00 [hexdump] +000000010: 00 11 22 33 44 55 66 77 ¦ 88 99 0A BB CC DD EE FF ?"3DUfwˆ™ª»ÌÝîÿ +''' + echo('restore far format ', linefeed=False) + assert bin == restore(far), 'far format check failed' + echo('passed') + + scapy = '''\ +00 00 00 5B 68 65 78 64 75 6D 70 5D 00 00 00 00 ...[hexdump].... +00 11 22 33 44 55 66 77 88 99 0A BB CC DD EE FF .."3DUfw........ +''' + echo('restore scapy format ', linefeed=False) + assert bin == restore(scapy), 'scapy format check failed' + echo('passed') + + if not PY3K: + assert restore('5B68657864756D705D') == '[hexdump]', 'no space check failed' + assert dump('\\\xa1\xab\x1e', sep='').lower() == '5ca1ab1e' + else: + assert restore('5B68657864756D705D') == b'[hexdump]', 'no space check failed' + assert dump(b'\\\xa1\xab\x1e', sep='').lower() == '5ca1ab1e' + + print('---[test file hexdumping]---') + + import os + import tempfile + hexfile = tempfile.NamedTemporaryFile(delete=False) + try: + hexfile.write(bin) + hexfile.close() + hexdump(open(hexfile.name, 'rb')) + finally: + os.remove(hexfile.name) + if logfile: + sys.stderr, sys.stdout = savedstd + openlog.close() + + +def main(): + from optparse import OptionParser + parser = OptionParser(usage=''' + %prog [binfile|-] + %prog -r hexfile + %prog --test [logfile]''', version=__version__) + parser.add_option('-r', '--restore', action='store_true', + help='restore binary from hex dump') + parser.add_option('--test', action='store_true', help='run hexdump sanity checks') + + options, args = parser.parse_args() + + if options.test: + if args: + runtest(logfile=args[0]) + else: + runtest() + elif not args or len(args) > 1: + parser.print_help() + sys.exit(-1) + else: + ## dump file + if not options.restore: + # [x] memory effective dump + if args[0] == '-': + if not PY3K: + hexdump(sys.stdin) + else: + hexdump(sys.stdin.buffer) + else: + hexdump(open(args[0], 'rb')) + + ## restore file + else: + # prepare input stream + if args[0] == '-': + instream = sys.stdin + else: + if PY3K: + instream = open(args[0]) + else: + instream = open(args[0], 'rb') + + # output stream + # [ ] memory efficient restore + if PY3K: + sys.stdout.buffer.write(restore(instream.read())) + else: + # Windows - binary mode for sys.stdout to prevent data corruption + normalize_py() + sys.stdout.write(restore(instream.read())) + +if __name__ == '__main__': + main() + +# [x] file restore from command line utility +# [ ] write dump with LF on Windows for consistency +# [ ] encoding param for hexdump()ing Python 3 str if anybody requests that + +# [ ] document chunking API +# [ ] document hexdump API +# [ ] blog about sys.stdout text mode problem on Windows From 9745d559191c9bc1c71347d62b6f39fd712858fb Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Fri, 4 Jun 2021 22:36:15 +0100 Subject: [PATCH 04/23] Add a little header --- python3/vimspector/code.py | 9 ++++++++- python3/vimspector/debug_session.py | 7 +++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/python3/vimspector/code.py b/python3/vimspector/code.py index 635a12f..7e33407 100644 --- a/python3/vimspector/code.py +++ b/python3/vimspector/code.py @@ -295,7 +295,7 @@ class CodeView( object ): return self._terminal.buffer_number - def ShowMemory( self, memoryReference, msg ): + def ShowMemory( self, memoryReference, length, msg ): if not self._window.valid: return False @@ -308,6 +308,13 @@ class CodeView( object ): # equivalent output of say xxd data = msg.get( 'body', {} ).get( 'data', '' ) utils.SetBufferContents( buf, utils.Base64ToHexDump( data ) ) + buf[ 0:0 ] = [ + f'Memory Dump for Reference {memoryReference} Length: {length} bytes', + '-' * 80, + 'Offset Bytes Text', + ] + + utils.SetSyntax( '', 'xxd', buf ) utils.JumpToWindow( self._window ) utils.OpenFileInCurrentWindow( buf_name ) diff --git a/python3/vimspector/debug_session.py b/python3/vimspector/debug_session.py index bd93967..c0ddafa 100644 --- a/python3/vimspector/debug_session.py +++ b/python3/vimspector/debug_session.py @@ -543,20 +543,23 @@ class DebugSession( object ): return memoryReference = self._variablesView.GetMemoryReference( buf, line_num ) + length = 1024 # TODO: WHat? if memoryReference is None: utils.UserMessage( "Cannot find memory reference for that", error = True ) return + + def handler( msg ): - self._codeView.ShowMemory( memoryReference, msg ) + self._codeView.ShowMemory( memoryReference, length, msg ) self._connection.DoRequest( handler, { 'command': 'readMemory', 'arguments': { 'memoryReference': memoryReference, - 'count': 1024 # TODO: What + 'count': length, } } ) From ae6572dde66d4a61a1df209bc0cb4b8a2c544277 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Sat, 5 Jun 2021 12:10:45 +0100 Subject: [PATCH 05/23] Make sure the buffer is not marked modified --- python3/vimspector/code.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/python3/vimspector/code.py b/python3/vimspector/code.py index 7e33407..9d1e37b 100644 --- a/python3/vimspector/code.py +++ b/python3/vimspector/code.py @@ -307,14 +307,14 @@ class CodeView( object ): # TODO: The data is encoded in base64, so we need to convert that to the # equivalent output of say xxd data = msg.get( 'body', {} ).get( 'data', '' ) - utils.SetBufferContents( buf, utils.Base64ToHexDump( data ) ) - buf[ 0:0 ] = [ + utils.SetBufferContents( buf, [ f'Memory Dump for Reference {memoryReference} Length: {length} bytes', '-' * 80, 'Offset Bytes Text', - ] + '-' * 80, + ] ) + utils.AppendToBuffer( buf, utils.Base64ToHexDump( data ) ) utils.SetSyntax( '', 'xxd', buf ) - utils.JumpToWindow( self._window ) utils.OpenFileInCurrentWindow( buf_name ) From 58a1c05465d51d7369363e0c4d309fab5934333e Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Tue, 8 Jun 2021 22:25:24 +0100 Subject: [PATCH 06/23] Ask user for how many bytes to read --- python3/vimspector/debug_session.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/python3/vimspector/debug_session.py b/python3/vimspector/debug_session.py index c0ddafa..31dc165 100644 --- a/python3/vimspector/debug_session.py +++ b/python3/vimspector/debug_session.py @@ -543,13 +543,16 @@ class DebugSession( object ): return memoryReference = self._variablesView.GetMemoryReference( buf, line_num ) - length = 1024 # TODO: WHat? - if memoryReference is None: utils.UserMessage( "Cannot find memory reference for that", error = True ) return + length = utils.AskForInput( 'How much data to display? ', + default_value = '1024' ) + + if length is None: + return def handler( msg ): @@ -559,7 +562,7 @@ class DebugSession( object ): 'command': 'readMemory', 'arguments': { 'memoryReference': memoryReference, - 'count': length, + 'count': int( length ), } } ) From 4d4f85233dcd6998a612f43b1640e14dfc00cf7c Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Tue, 8 Jun 2021 22:45:59 +0100 Subject: [PATCH 07/23] Add offset support, sort of --- python3/vimspector/code.py | 8 ++++++-- python3/vimspector/debug_session.py | 11 +++++++++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/python3/vimspector/code.py b/python3/vimspector/code.py index 9d1e37b..5f54e1c 100644 --- a/python3/vimspector/code.py +++ b/python3/vimspector/code.py @@ -295,7 +295,7 @@ class CodeView( object ): return self._terminal.buffer_number - def ShowMemory( self, memoryReference, length, msg ): + def ShowMemory( self, memoryReference, length, offset, msg ): if not self._window.valid: return False @@ -308,7 +308,8 @@ class CodeView( object ): # equivalent output of say xxd data = msg.get( 'body', {} ).get( 'data', '' ) utils.SetBufferContents( buf, [ - f'Memory Dump for Reference {memoryReference} Length: {length} bytes', + f'Memory Dump for Reference {memoryReference} Length: {length} bytes' + f' Offset: {offset}', '-' * 80, 'Offset Bytes Text', '-' * 80, @@ -318,3 +319,6 @@ class CodeView( object ): utils.SetSyntax( '', 'xxd', buf ) utils.JumpToWindow( self._window ) utils.OpenFileInCurrentWindow( buf_name ) + + # TODO: Need to set up some mappings here that allow the user to browse + # around by setting the offset diff --git a/python3/vimspector/debug_session.py b/python3/vimspector/debug_session.py index 31dc165..c8c6ce8 100644 --- a/python3/vimspector/debug_session.py +++ b/python3/vimspector/debug_session.py @@ -536,7 +536,7 @@ class DebugSession( object ): self._variablesView.SetVariableValue( new_value, buf, line_num ) @IfConnected() - def ReadMemory( self, buf = None, line_num = None ): + def ReadMemory( self, offset = None, buf = None, line_num = None ): if not self._server_capabilities.get( 'supportsReadMemoryRequest' ): utils.UserMessage( "Server does not support memory request", error = True ) @@ -554,15 +554,22 @@ class DebugSession( object ): if length is None: return + offset = utils.AskForInput( 'Location offset? ', + default_value = '0' ) + + if offset is None: + return + def handler( msg ): - self._codeView.ShowMemory( memoryReference, length, msg ) + self._codeView.ShowMemory( memoryReference, length, offset, msg ) self._connection.DoRequest( handler, { 'command': 'readMemory', 'arguments': { 'memoryReference': memoryReference, 'count': int( length ), + 'offset': int( offset ) } } ) From 0500e41429bde17105e931d9920b3c6dbe5eabdb Mon Sep 17 00:00:00 2001 From: Paulo Date: Wed, 9 Jun 2021 19:24:37 +0200 Subject: [PATCH 08/23] FIx typo in configuration.md A small typo that wastes time for people that copy and modify the config file --- docs/configuration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/configuration.md b/docs/configuration.md index a2864b1..3d524bf 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -722,7 +722,7 @@ Vimspector then orchestrates the various tools to set you up. "variables": { // Just an example of how to specify a variable manually rather than // vimspector asking for input from the user - "ServiceName": "${fileBasenameNoExtention}" + "ServiceName": "${fileBasenameNoExtension}" }, "adapter": "python-remote", From 5075f3a11aba4e31cb7994746862a4342c8546ae Mon Sep 17 00:00:00 2001 From: Simon Drake Date: Thu, 24 Jun 2021 14:40:40 +0100 Subject: [PATCH 09/23] Add a runnable Go example --- README.md | 2 +- .../name-starts-with-vowel/.vimspector.json | 29 ++++++++++++++++ .../test/go/name-starts-with-vowel/README.md | 33 +++++++++++++++++++ .../cmd/namestartswithvowel/main.go | 20 +++++++++++ support/test/go/name-starts-with-vowel/go.mod | 3 ++ .../internal/vowels/vowels.go | 9 +++++ .../internal/vowels/vowels_test.go | 30 +++++++++++++++++ 7 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 support/test/go/name-starts-with-vowel/.vimspector.json create mode 100644 support/test/go/name-starts-with-vowel/README.md create mode 100644 support/test/go/name-starts-with-vowel/cmd/namestartswithvowel/main.go create mode 100644 support/test/go/name-starts-with-vowel/go.mod create mode 100644 support/test/go/name-starts-with-vowel/internal/vowels/vowels.go create mode 100644 support/test/go/name-starts-with-vowel/internal/vowels/vowels_test.go diff --git a/README.md b/README.md index f8db3aa..66f2720 100644 --- a/README.md +++ b/README.md @@ -290,7 +290,7 @@ If you just want to try out vimspector without changing your vim config, there are example projects for a number of languages in `support/test`, including: * Python (`support/test/python/simple_python`) -* Go (`support/test/go/hello_world`) +* Go (`support/test/go/hello_world` and `support/test/go/name-starts-with-vowel`) * Nodejs (`support/test/node/simple`) * Chrome (`support/test/chrome/`) * etc. diff --git a/support/test/go/name-starts-with-vowel/.vimspector.json b/support/test/go/name-starts-with-vowel/.vimspector.json new file mode 100644 index 0000000..ffcfc93 --- /dev/null +++ b/support/test/go/name-starts-with-vowel/.vimspector.json @@ -0,0 +1,29 @@ +{ + "configurations": { + "run-cmd": { + "adapter": "vscode-go", + "configuration": { + "request": "launch", + "program": "${workspaceRoot}/cmd/namestartswithvowel/main.go", + "mode": "debug", + "dlvToolPath": "$HOME/go/bin/dlv", + "dlvLoadConfig": { + "maxArrayValues": 1000, + "maxStringLen": 1000 + } + } + }, + "test-current-file": { + "adapter": "vscode-go", + "configuration": { + "request": "launch", + "mode": "test", + "program": "${fileDirname}", + "cwd": "${fileDirname}", + "dlvToolPath": "$GOPATH/bin/dlv", + "env": {}, + "args": [] + } + } + } +} diff --git a/support/test/go/name-starts-with-vowel/README.md b/support/test/go/name-starts-with-vowel/README.md new file mode 100644 index 0000000..fec967e --- /dev/null +++ b/support/test/go/name-starts-with-vowel/README.md @@ -0,0 +1,33 @@ +# Purpose + +This example comes with two example vimspector configs for the Go programming language. + +1) `run-cmd` will launch the main programme under `cmd/namestartswithvowel`. +1) `test-current-file` will run the tests in the current file in debug mode. + +## Example use-cases + +### run-cmd + +* Open `cmd/namestartswithvowel/main.go` +* Add a breakpoint somewhere within the programme +* Start the debugger (`:call vimspector#Continue()` or your relevant keymapping) +* Select the first launch configuration (`1: run-cmd`) + +### test-current-file + +* Open `internal/vowels/vowels_test.go` +* Add a breakpoint somewhere within the test +* Start the debugger (`:call vimspector#Continue()` or your relevant keymapping) +* Select the second launch configuration (`2: test-current-file`) + +## Additional Configuration + +There are two additional configuration options specified under `run-cmd`; these parameters configure the maximum string/array size to be shown while debugging. + +``` +"dlvLoadConfig": { + "maxArrayValues": 1000, + "maxStringLen": 1000 +} +``` diff --git a/support/test/go/name-starts-with-vowel/cmd/namestartswithvowel/main.go b/support/test/go/name-starts-with-vowel/cmd/namestartswithvowel/main.go new file mode 100644 index 0000000..c160aea --- /dev/null +++ b/support/test/go/name-starts-with-vowel/cmd/namestartswithvowel/main.go @@ -0,0 +1,20 @@ +package main + +import ( + "fmt" + + "example.com/internal/vowels" +) + +func main() { + names := []string{"Simon", "Bob", "Jennifer", "Amy", "Duke", "Elizabeth"} + + for _, n := range names { + if vowels.NameStartsWithVowel(n) { + fmt.Printf("%s starts with a vowel!\n", n) + continue + } + + fmt.Printf("%s does not start with a vowel!\n", n) + } +} diff --git a/support/test/go/name-starts-with-vowel/go.mod b/support/test/go/name-starts-with-vowel/go.mod new file mode 100644 index 0000000..3070734 --- /dev/null +++ b/support/test/go/name-starts-with-vowel/go.mod @@ -0,0 +1,3 @@ +module example.com + +go 1.16 diff --git a/support/test/go/name-starts-with-vowel/internal/vowels/vowels.go b/support/test/go/name-starts-with-vowel/internal/vowels/vowels.go new file mode 100644 index 0000000..4e76480 --- /dev/null +++ b/support/test/go/name-starts-with-vowel/internal/vowels/vowels.go @@ -0,0 +1,9 @@ +package vowels + +import "strings" + +func NameStartsWithVowel(name string) bool { + s := strings.Split(strings.ToLower(name), "") + + return s[0] == "a" || s[0] == "e" || s[0] == "i" || s[0] == "o" || s[0] == "u" +} diff --git a/support/test/go/name-starts-with-vowel/internal/vowels/vowels_test.go b/support/test/go/name-starts-with-vowel/internal/vowels/vowels_test.go new file mode 100644 index 0000000..e0d5773 --- /dev/null +++ b/support/test/go/name-starts-with-vowel/internal/vowels/vowels_test.go @@ -0,0 +1,30 @@ +package vowels + +import ( + "fmt" + "testing" +) + +func TestNameStartsWithVowel(t *testing.T) { + testCases := []struct { + input string + expectedOutput bool + }{ + { + input: "Simon", + expectedOutput: false, + }, + { + input: "Andy", + expectedOutput: true, + }, + } + for _, tt := range testCases { + t.Run(fmt.Sprintf("%s should product %t", tt.input, tt.expectedOutput), func(t *testing.T) { + out := NameStartsWithVowel(tt.input) + if out != tt.expectedOutput { + t.Errorf("%s produced %t, when %t was expected", tt.input, out, tt.expectedOutput) + } + }) + } +} From 21ebb22fd44c586f6b22ef393012863b6502a010 Mon Sep 17 00:00:00 2001 From: przepompownia Date: Sun, 4 Jul 2021 23:00:32 +0200 Subject: [PATCH 10/23] Upgrade vscode-php-debug to 1.16.1 --- python3/vimspector/gadgets.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/python3/vimspector/gadgets.py b/python3/vimspector/gadgets.py index 23a298c..240fc68 100644 --- a/python3/vimspector/gadgets.py +++ b/python3/vimspector/gadgets.py @@ -323,10 +323,10 @@ GADGETS = { '${version}/${file_name}', }, 'all': { - 'version': 'v1.16.0', - 'file_name': 'php-debug-1.16.0.vsix', + 'version': 'v1.16.1', + 'file_name': 'php-debug-1.16.1.vsix', 'checksum': - '62d210f7b87b21315c37ea10a1a5dbae376ff9f963b8f8cf33361e01413731be', + '2eb6ff1100b6b3d2d160f243858f3524e269078b8154e108d015882e2c0d52c4', }, 'adapters': { 'vscode-php-debug': { From 3af97f192841247a2891c021d935a2e4f15db7c6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 Jul 2021 05:43:17 +0000 Subject: [PATCH 11/23] Bump addressable from 2.7.0 to 2.8.0 in /docs Bumps [addressable](https://github.com/sporkmonger/addressable) from 2.7.0 to 2.8.0. - [Release notes](https://github.com/sporkmonger/addressable/releases) - [Changelog](https://github.com/sporkmonger/addressable/blob/main/CHANGELOG.md) - [Commits](https://github.com/sporkmonger/addressable/compare/addressable-2.7.0...addressable-2.8.0) --- updated-dependencies: - dependency-name: addressable dependency-type: indirect ... Signed-off-by: dependabot[bot] --- docs/Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Gemfile.lock b/docs/Gemfile.lock index 0fa7776..acf20f2 100644 --- a/docs/Gemfile.lock +++ b/docs/Gemfile.lock @@ -7,7 +7,7 @@ GEM minitest (~> 5.1) tzinfo (~> 1.1) zeitwerk (~> 2.2, >= 2.2.2) - addressable (2.7.0) + addressable (2.8.0) public_suffix (>= 2.0.2, < 5.0) coffee-script (2.4.1) coffee-script-source From 59c9cd10ab9073b91a11ccd9b21c34d8331fa9cb Mon Sep 17 00:00:00 2001 From: przepompownia Date: Mon, 2 Aug 2021 16:11:04 +0200 Subject: [PATCH 12/23] Upgrade vscode-php-debug to 1.17.0 --- python3/vimspector/gadgets.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/python3/vimspector/gadgets.py b/python3/vimspector/gadgets.py index 240fc68..170956a 100644 --- a/python3/vimspector/gadgets.py +++ b/python3/vimspector/gadgets.py @@ -323,10 +323,10 @@ GADGETS = { '${version}/${file_name}', }, 'all': { - 'version': 'v1.16.1', - 'file_name': 'php-debug-1.16.1.vsix', + 'version': 'v1.17.0', + 'file_name': 'php-debug-1.17.0.vsix', 'checksum': - '2eb6ff1100b6b3d2d160f243858f3524e269078b8154e108d015882e2c0d52c4', + 'd0fff272503414b6696cc737bc2e18e060fdd5e5dc4bcaf38ae7373afd8d8bc9', }, 'adapters': { 'vscode-php-debug': { From f1e2c12e5bfbb0b9abd1dec75ad8d2810ecc4fc9 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Mon, 2 Aug 2021 16:01:47 +0100 Subject: [PATCH 13/23] Update codelldb Add a way to checksum downloads and a little guide to updating gadgets --- python3/vimspector/gadgets.py | 8 ++++---- run_tests | 4 ++-- support/gadget_upgrade/README.md | 8 ++++++++ support/gadget_upgrade/checksum.py | 13 +++++++++++++ 4 files changed, 27 insertions(+), 6 deletions(-) create mode 100644 support/gadget_upgrade/README.md create mode 100755 support/gadget_upgrade/checksum.py diff --git a/python3/vimspector/gadgets.py b/python3/vimspector/gadgets.py index 170956a..72f13c8 100644 --- a/python3/vimspector/gadgets.py +++ b/python3/vimspector/gadgets.py @@ -394,12 +394,12 @@ GADGETS = { '${version}/${file_name}', }, 'all': { - 'version': 'v1.6.1', + 'version': 'v1.6.5', }, 'macos': { 'file_name': 'codelldb-x86_64-darwin.vsix', 'checksum': - 'b1c998e7421beea9f3ba21aa5706210bb2249eba93c99b809247ee831075262f', + 'e7d9f4f8ec3c3774af6d1dbf11f0568db1417c4d51038927228cd07028725594', 'make_executable': [ 'adapter/codelldb', 'lldb/bin/debugserver', @@ -410,7 +410,7 @@ GADGETS = { 'linux': { 'file_name': 'codelldb-x86_64-linux.vsix', 'checksum': - 'f2a36cb6971fd95a467cf1a7620e160914e8f11bf82929932ee0aa5afbf6ae6a', + 'eda2cd9b3089dcc0524c273e91ffb5875fe08c930bf643739a2cd1846e1f98d6', 'make_executable': [ 'adapter/codelldb', 'lldb/bin/lldb', @@ -421,7 +421,7 @@ GADGETS = { 'windows': { 'file_name': 'codelldb-x86_64-windows.vsix', 'checksum': - 'ca6a6525bf7719dc95265dc630b3cc817a8c0393b756fd242b710805ffdfb940', + '8ddebe8381a3d22dc3d95139c3797fda06b5cc34aadf300e13b1c516b9da95fe', 'make_executable': [] }, 'adapters': { diff --git a/run_tests b/run_tests index 441acb0..201ec1b 100755 --- a/run_tests +++ b/run_tests @@ -21,7 +21,7 @@ out_fd=1 while [ -n "$1" ]; do case "$1" in - "--basedir") + "--basedir"|"--base-dir"|"--test-base") shift SetBaseDir $1 shift @@ -36,7 +36,7 @@ while [ -n "$1" ]; do INSTALL=$1 shift ;; - "--update") + "--update"|"--upgrade") UPDATE=1 shift ;; diff --git a/support/gadget_upgrade/README.md b/support/gadget_upgrade/README.md new file mode 100644 index 0000000..9ae3d7f --- /dev/null +++ b/support/gadget_upgrade/README.md @@ -0,0 +1,8 @@ +# Manually updating shipped gadgets + +Download the gadget files manuall from their official source into this dir. +Run `./checksum.py ` to get the checksums. + +Update ../../python3/vimspector/gadgets.py with the new version and the +checksums. + diff --git a/support/gadget_upgrade/checksum.py b/support/gadget_upgrade/checksum.py new file mode 100755 index 0000000..d0c1404 --- /dev/null +++ b/support/gadget_upgrade/checksum.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python3 + +import hashlib +import sys + + +def GetChecksumSHA254( file_path ): + with open( file_path, 'rb' ) as existing_file: + return hashlib.sha256( existing_file.read() ).hexdigest() + + +for arg in sys.argv[ 1: ]: + print( f"{ arg } = { GetChecksumSHA254( arg ) }" ) From 57ce0992803fcf22c0557550fff45e3fe869f707 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Tue, 3 Aug 2021 17:29:55 +0100 Subject: [PATCH 14/23] SHow the output in the console, as this is where codelldb puts it --- python3/vimspector/output.py | 1 + 1 file changed, 1 insertion(+) diff --git a/python3/vimspector/output.py b/python3/vimspector/output.py index 8c94b44..3f0da1e 100644 --- a/python3/vimspector/output.py +++ b/python3/vimspector/output.py @@ -32,6 +32,7 @@ class TabBuffer( object ): BUFFER_MAP = { 'console': 'Console', 'stdout': 'Console', + 'output': 'Console', 'stderr': 'stderr', 'telemetry': None, } From 7c7e3f9c3f63de7ef91e5d579662a4e16be95315 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Fri, 20 Aug 2021 11:17:05 +0100 Subject: [PATCH 15/23] Add config for bash to tests --- support/test/bash/.vimspector.json | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 support/test/bash/.vimspector.json diff --git a/support/test/bash/.vimspector.json b/support/test/bash/.vimspector.json new file mode 100644 index 0000000..a1be1b9 --- /dev/null +++ b/support/test/bash/.vimspector.json @@ -0,0 +1,15 @@ +{ + "$schema": "https://puremourning.github.io/vimspector/schema/vimspector.schema.json", + "configurations": { + "Run Current Script": { + "adapter": "vscode-bash", + "autoselect": false, + "configuration": { + "request": "launch", + "program": "${file}", + "cwd": "${fileDirname}", + "args": [ "*${args}" ] + } + } + } +} From a720d0e1d56743bb1f335b2a4bcb963491e9b421 Mon Sep 17 00:00:00 2001 From: roachsinai Date: Sat, 21 Aug 2021 00:57:27 +0800 Subject: [PATCH 16/23] Fix error: E806: using Float as a String. --- support/custom_ui_vimrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/support/custom_ui_vimrc b/support/custom_ui_vimrc index a8812cb..e76c6ee 100644 --- a/support/custom_ui_vimrc +++ b/support/custom_ui_vimrc @@ -54,7 +54,7 @@ function s:SetUpTerminal() let padding = 4 let cols = max( [ min( [ &columns - left_bar - code - padding, 80 ] ), 10 ] ) call win_gotoid( terminal_win ) - execute cols . 'wincmd |' + execute string(cols) . 'wincmd |' endfunction function! s:CustomiseWinBar() From 51d78fce5f95fb10ba84b8ab66e97d44d75df010 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Tue, 7 Sep 2021 17:00:04 +0100 Subject: [PATCH 17/23] Note on using legacy vscode-dap --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 66f2720..3420d56 100644 --- a/README.md +++ b/README.md @@ -1368,6 +1368,8 @@ Requires: * [Delve][delve-install] installed, e.g. `go get -u github.com/go-delve/delve/cmd/dlv` * Delve to be in your PATH, or specify the `dlvToolPath` launch option +NOTE: Vimspector uses the ["legacy" vscode-go debug adapter](https://github.com/golang/vscode-go/blob/master/docs/debugging-legacy.md) rather than the "built-in" DAP support in Delve. You can track https://github.com/puremourning/vimspector/issues/186 for that. + ```json { "configurations": { @@ -1385,7 +1387,7 @@ Requires: ``` See the vscode-go docs for -[troubleshooting information](https://github.com/golang/vscode-go/blob/master/docs/debugging.md#troubleshooting) +[troubleshooting information](https://github.com/golang/vscode-go/blob/master/docs/debugging-legacy.md#troubleshooting) ## PHP From 46cfdc678dbdbb162f8cb8ab4384897e1a3d3bd0 Mon Sep 17 00:00:00 2001 From: Sebastian Goth Date: Wed, 8 Sep 2021 12:19:51 +0200 Subject: [PATCH 18/23] Update vscode-cpptools from 0.27.0 to 1.6.0 --- python3/vimspector/gadgets.py | 10 +++++----- python3/vimspector/installer.py | 3 ++- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/python3/vimspector/gadgets.py b/python3/vimspector/gadgets.py index 72f13c8..dda962d 100644 --- a/python3/vimspector/gadgets.py +++ b/python3/vimspector/gadgets.py @@ -30,12 +30,12 @@ GADGETS = { root, gadget ), 'all': { - 'version': '0.27.0', + 'version': '1.6.0', "adapters": { "vscode-cpptools": { "name": "cppdbg", "command": [ - "${gadgetDir}/vscode-cpptools/debugAdapters/OpenDebugAD7" + "${gadgetDir}/vscode-cpptools/debugAdapters/bin/OpenDebugAD7" ], "attach": { "pidProperty": "processId", @@ -53,17 +53,17 @@ GADGETS = { 'linux': { 'file_name': 'cpptools-linux.vsix', 'checksum': - '3695202e1e75a03de18049323b66d868165123f26151f8c974a480eaf0205435', + 'c25299bcfb46b22d41aa3f125df7184e6282a35ff9fb69c47def744cb4778f55', }, 'macos': { 'file_name': 'cpptools-osx.vsix', 'checksum': - 'cb061e3acd7559a539e5586f8d3f535101c4ec4e8a48195856d1d39380b5cf3c', + 'ae21cde361335b350402904991cf9f746fec685449ca9bd5d50227c3dec3719b', }, 'windows': { 'file_name': 'cpptools-win32.vsix', 'checksum': - 'aa294368ed16d48c59e49c8000e146eae5a19ad07b654efed5db8ec93b24229e', + 'ef7ac5831874a3c7dbf0feb826bfda2be579aff9b6d990622fff1d0d4ede00d1', "adapters": { "vscode-cpptools": { "name": "cppdbg", diff --git a/python3/vimspector/installer.py b/python3/vimspector/installer.py index f0f85a4..a81db8f 100644 --- a/python3/vimspector/installer.py +++ b/python3/vimspector/installer.py @@ -358,7 +358,8 @@ def InstallCppTools( name, root, gadget ): # It's hilarious, but the execute bits aren't set in the vsix. So they # actually have javascript code which does this. It's just a horrible horrible # hack that really is not funny. - MakeExecutable( os.path.join( extension, 'debugAdapters', 'OpenDebugAD7' ) ) + MakeExecutable( + os.path.join( extension, 'debugAdapters', 'bin', 'OpenDebugAD7' ) ) with open( os.path.join( extension, 'package.json' ) ) as f: package = json.load( f ) runtime_dependencies = package[ 'runtimeDependencies' ] From 561a5b9aa2c0c0a9f801b12af3cd7ef861fad962 Mon Sep 17 00:00:00 2001 From: Sebastian Goth Date: Wed, 8 Sep 2021 21:36:37 +0200 Subject: [PATCH 19/23] Update variables tests to expect register scope vscode-cpptools 1.6.0 now reports an additional scope 'Registers' after 'Locals'. --- tests/variables.test.vim | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/variables.test.vim b/tests/variables.test.vim index 59ca2c0..c00fb7f 100644 --- a/tests/variables.test.vim +++ b/tests/variables.test.vim @@ -194,6 +194,7 @@ function! Test_ExpandVariables() \ [ \ '- Scope: Locals', \ ' *+ t (Test): {...}', + \ '+ Scope: Registers', \ ], \ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ 1, @@ -219,6 +220,7 @@ function! Test_ExpandVariables() \ ' \*- c (char): 0 ''\\0\{1,3}''', \ ' \*- fffff (float): 0', \ ' \*+ another_test (AnotherTest):\( {...}\)\?', + \ '+ Scope: Registers', \ ], \ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ 1, @@ -237,6 +239,7 @@ function! Test_ExpandVariables() \ ' - c (char): 0 ''\\0\{1,3}''', \ ' - fffff (float): 0', \ ' + another_test (AnotherTest):\( {...}\)\?', + \ '+ Scope: Registers', \ ], \ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ 1, @@ -253,6 +256,7 @@ function! Test_ExpandVariables() \ [ \ '- Scope: Locals', \ ' + t (Test): {...}', + \ '+ Scope: Registers', \ ], \ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ 1, @@ -267,6 +271,7 @@ function! Test_ExpandVariables() \ [ \ '- Scope: Locals', \ ' + t (Test): {...}', + \ '+ Scope: Registers', \ ], \ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ 1, @@ -286,6 +291,7 @@ function! Test_ExpandVariables() \ ' \*- c (char): 99 ''c''', \ ' \*- fffff (float): 0', \ ' \*+ another_test (AnotherTest):\( {...}\)\?', + \ '+ Scope: Registers', \ ], \ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ 1, @@ -302,6 +308,7 @@ function! Test_ExpandVariables() \ assert_equal( \ [ \ '+ Scope: Locals', + \ '+ Scope: Registers', \ ], \ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ 1, @@ -316,6 +323,7 @@ function! Test_ExpandVariables() \ assert_equal( \ [ \ '+ Scope: Locals', + \ '+ Scope: Registers', \ ], \ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ 1, @@ -331,6 +339,7 @@ function! Test_ExpandVariables() \ assert_equal( \ [ \ '+ Scope: Locals', + \ '+ Scope: Registers', \ ], \ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ 1, @@ -846,6 +855,7 @@ function! Test_SetVariableValue_Local() \ [ \ '- Scope: Locals', \ ' *+ t (Test): {...}', + \ '+ Scope: Registers', \ ], \ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ 1, @@ -871,6 +881,7 @@ function! Test_SetVariableValue_Local() \ ' \*- c (char): 0 ''\\0\{1,3}''', \ ' \*- fffff (float): 0', \ ' \*+ another_test (AnotherTest):\( {...}\)\?', + \ '+ Scope: Registers', \ ], \ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ 1, @@ -897,6 +908,7 @@ EOF \ ' \*- c (char): 0 ''\\0\{1,3}''', \ ' \*- fffff (float): 0', \ ' \*+ another_test (AnotherTest):\( {...}\)\?', + \ '+ Scope: Registers', \ ], \ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ 1, @@ -916,6 +928,7 @@ EOF \ ' \*- c (char): 0 ''\\0\{1,3}''', \ ' \*- fffff (float): 0', \ ' \*+ another_test (AnotherTest):\( {...}\)\?', + \ '+ Scope: Registers', \ ], \ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ 1, @@ -935,6 +948,7 @@ EOF \ ' \*- c (char): 0 ''\\0\{1,3}''', \ ' \*- fffff (float): 0', \ ' \*+ another_test (AnotherTest):\( {...}\)\?', + \ '+ Scope: Registers', \ ], \ getbufline( winbufnr( g:vimspector_session_windows.variables ), \ 1, From 17ca1522f8a0cca53c8ab75a680f27ea58b50de3 Mon Sep 17 00:00:00 2001 From: Sebastian Goth Date: Wed, 8 Sep 2021 23:16:47 +0200 Subject: [PATCH 20/23] Use correct spelling of MIMode in tests --- tests/testdata/cpp/simple/.vimspector.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/testdata/cpp/simple/.vimspector.json b/tests/testdata/cpp/simple/.vimspector.json index 0dca061..48ce801 100644 --- a/tests/testdata/cpp/simple/.vimspector.json +++ b/tests/testdata/cpp/simple/.vimspector.json @@ -12,7 +12,7 @@ "externalConsole": false, "stopAtEntry": true, "stopOnEntry": true, - "MImode": "${VIMSPECTOR_MIMODE}" + "MIMode": "${VIMSPECTOR_MIMODE}" }, "breakpoints": { "exception": { @@ -33,7 +33,7 @@ "externalConsole": false, "stopAtEntry": false, "stopOnEntry": false, - "MImode": "${VIMSPECTOR_MIMODE}" + "MIMode": "${VIMSPECTOR_MIMODE}" }, "breakpoints": { "exception": { @@ -55,7 +55,7 @@ "externalConsole": false, "stopAtEntry": false, "stopOnEntry": false, - "MImode": "${VIMSPECTOR_MIMODE}" + "MIMode": "${VIMSPECTOR_MIMODE}" }, "breakpoints": { "exception": { @@ -82,7 +82,7 @@ "configuration": { "request": "launch", "program": "${workspaceRoot}/${fileBasenameNoExtension}", - "MImode": "${VIMSPECTOR_MIMODE}", + "MIMode": "${VIMSPECTOR_MIMODE}", "externalConsole": false, "args": [ "CALCULATED_LIST", "${CALCULATED_LIST}", From db5ed8e80228fbb5366e6fc7629e430f886d2b34 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Wed, 8 Sep 2021 22:20:33 +0100 Subject: [PATCH 21/23] Update to ubuntu 18.04 as 16.04 is deprecated --- .github/workflows/build.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 14f5979..f186f5d 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -13,7 +13,7 @@ defaults: jobs: PythonLint: - runs-on: ubuntu-16.04 + runs-on: ubuntu-18.04 container: 'puremourning/vimspector:test' steps: - uses: actions/checkout@v2 @@ -22,7 +22,7 @@ jobs: - name: 'Run flake8' run: '$HOME/.local/bin/flake8 python3/ *.py' VimscriptLint: - runs-on: 'ubuntu-16.04' + runs-on: 'ubuntu-18.04' container: 'puremourning/vimspector:test' steps: - uses: actions/checkout@v2 @@ -32,7 +32,7 @@ jobs: run: $HOME/.local/bin/vint autoload/ compiler/ plugin/ tests/ syntax/ Linux: - runs-on: 'ubuntu-16.04' + runs-on: 'ubuntu-18.04' container: image: 'puremourning/vimspector:test' options: --cap-add=SYS_PTRACE --security-opt seccomp=unconfined @@ -156,7 +156,7 @@ jobs: # SSH_PASS: ${{ secrets.SSH_PASS }} # [V]imspector PublishRelease: - runs-on: 'ubuntu-16.04' + runs-on: 'ubuntu-18.04' needs: - Linux - MacOS From dc862fe565a74a9810f37edaa8d0e1bb7bbdd79d Mon Sep 17 00:00:00 2001 From: Sebastian Goth Date: Thu, 9 Sep 2021 16:42:49 +0200 Subject: [PATCH 22/23] Readme: pretty printing with vscode-cpptools / gdb --- README.md | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 3420d56..d198292 100644 --- a/README.md +++ b/README.md @@ -61,9 +61,10 @@ For detailed explanation of the `.vimspector.json` format, see the * [Closing debugger](#closing-debugger) * [Terminate debuggee](#terminate-debuggee) * [Debug profile configuration](#debug-profile-configuration) - * [C, C , Rust, etc.](#c-c-rust-etc) - * [C Remote debugging](#c-remote-debugging) - * [C Remote launch and attach](#c-remote-launch-and-attach) + * [C, C++, Rust, etc.](#c-c-rust-etc) + * [Data visualization / pretty printing](#data-visualization--pretty-printing) + * [C++ Remote debugging](#c-remote-debugging) + * [C++ Remote launch and attach](#c-remote-launch-and-attach) * [Rust](#rust) * [Python](#python) * [Python Remote Debugging](#python-remote-debugging) @@ -1176,6 +1177,38 @@ licensing. } ``` +### Data visualization / pretty printing + +Depending on the backend you need to enable pretty printing of complex types manually. + +* LLDB: Pretty printing is enabled by default + +* GDB: To enable gdb pretty printers, consider the snippet below. + It is not enough to have `set print pretty on` in your .gdbinit! + +``` +{ + "configurations": { + "Launch": { + "adapter": "vscode-cpptools", + "configuration": { + "request": "launch", + "program": "", + ... + "MIMode": "gdb" + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ], + } + } + } +} +``` + ### C++ Remote debugging The cpptools documentation describes how to attach cpptools to gdbserver using From 7c12519b9d87f261abfff62f4f197c693a0ffb4f Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Fri, 10 Sep 2021 10:30:44 -0600 Subject: [PATCH 23/23] Modify for mac m1 --- python3/vimspector/gadgets.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/python3/vimspector/gadgets.py b/python3/vimspector/gadgets.py index dda962d..02eb0e7 100644 --- a/python3/vimspector/gadgets.py +++ b/python3/vimspector/gadgets.py @@ -56,9 +56,9 @@ GADGETS = { 'c25299bcfb46b22d41aa3f125df7184e6282a35ff9fb69c47def744cb4778f55', }, 'macos': { - 'file_name': 'cpptools-osx.vsix', + 'file_name': 'cpptools-osx-arm64.vsix', 'checksum': - 'ae21cde361335b350402904991cf9f746fec685449ca9bd5d50227c3dec3719b', + 'ceb3e8cdaa2b5bb45af50913ddd8402089969748af8d70f5d46480408287ba6f', }, 'windows': { 'file_name': 'cpptools-win32.vsix', @@ -394,12 +394,12 @@ GADGETS = { '${version}/${file_name}', }, 'all': { - 'version': 'v1.6.5', + 'version': 'v1.6.6', }, 'macos': { - 'file_name': 'codelldb-x86_64-darwin.vsix', + 'file_name': 'codelldb-aarch64-darwin.vsix', 'checksum': - 'e7d9f4f8ec3c3774af6d1dbf11f0568db1417c4d51038927228cd07028725594', + '5adc3b9139eabdafd825bd5efc55df4424a203fb2b6087b425cd434956e7ec58', 'make_executable': [ 'adapter/codelldb', 'lldb/bin/debugserver',