-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
4bea65f
commit e003cfb
Showing
49 changed files
with
990 additions
and
764 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 |
---|---|---|
@@ -1,5 +1,6 @@ | ||
out | ||
dist | ||
extension/dist | ||
node_modules | ||
.vscode-test/ | ||
npm-debug.log | ||
|
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
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,75 @@ | ||
# Features | ||
|
||
This document describes features that the AVM debugger supports. | ||
|
||
Screenshots and the exact features are based on the VS Code client. | ||
|
||
## View transaction groups being debugged | ||
|
||
Every execution starts with a top level transaction group. | ||
|
||
![A transaction group being debugged](images/transaction%20group.png) | ||
|
||
## Step into programs executions | ||
|
||
Both LogicSig and application programs associated with transactions can be stepped into. Source maps | ||
are used to show the original source code. | ||
|
||
![A program being debugged](images/app%20call.png) | ||
|
||
## Step into inner transactions | ||
|
||
If an application spawns an inner transaction, the debugger can step into it as well. | ||
|
||
![An inner transaction group being debugged](images/inner%20transaction%20group.png) | ||
|
||
Additionally, the entire call stack can be seen, showing the depth of the inner transaction or inner | ||
application being executed. Each frame of the call stack can be inspected to view the higher level | ||
state. | ||
|
||
![Call stack](images/call%20stack.png) | ||
|
||
## Step-by-step debugging | ||
|
||
The debugger supports step into, over, out, and back. Yes, you can step back! | ||
|
||
## Breakpoint support | ||
|
||
Breakpoints can be set in program source files. The debugger will pause when code corresponding to a | ||
breakpoint is about to be executed. Since multiple opcodes can be in a single line of source code, | ||
breakpoints can be set on specific columns. | ||
|
||
![Breakpoints in program code](images/breakpoints.png) | ||
|
||
## Error reporting | ||
|
||
Execution errors will be reported by the debugger. Since any error stops the execution of a | ||
transaction group, the debugger will not allow you to advance after an error. You can however step | ||
backwards to inspect what happened prior to the error. | ||
|
||
![An error in the debugger](images/error.png) | ||
|
||
## Inspect program state | ||
|
||
The debugger allows you to inspect the state of the program being debugged. This includes the PC | ||
(program counter), stack, and scratch space. | ||
|
||
![Inspecting program state](images/program%20state%20variables.png) | ||
|
||
Byte arrays can be displayed in a variety of formats, including base64, hex, and UTF-8. | ||
|
||
![Inspecting byte arrays in program state](images/program%20state%20variables%20bytes%20expanded.png) | ||
|
||
Additionally, specific values can be added to the watch list. | ||
|
||
Since values relative to the top of the stack are often important, negative indexing is supported to | ||
look up values relative to the top of the stack. | ||
|
||
![Watched values](images/watch%20values.png) | ||
|
||
## Inspect application state | ||
|
||
The debugger also allows you to inspect and watch any available application state from the | ||
execution. Such state includes application boxes, global, and local state. | ||
|
||
![Inspecting application state variables](images/app%20state%20variables%20expanded.png) |
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 @@ | ||
# AVM Debugger | ||
|
||
## Summary | ||
|
||
This repo contains an AVM debugger which adheres to the [Debug Adapter Protocol](https://microsoft.github.io/debug-adapter-protocol/). | ||
This protocol is used by a variety of clients, and this repo additionally | ||
implements a basic client for VS Code. | ||
|
||
Unlike traditional debuggers, which typically execute code as it is being | ||
debugged, this debugger operates on an execution trace. The trace is created by | ||
the [algod simulate API](https://developer.algorand.org/docs/rest-apis/algod/#post-v2transactionssimulate). | ||
This debugger is not responsible for compiling programs, assembling transaction groups, or executing | ||
transactions/programs. It is only responsible for replaying the execution trace, which must already | ||
exist. | ||
|
||
This code is based on the [`vscode-mock-debug`](https://github.com/microsoft/vscode-mock-debug) repo. | ||
|
||
## Features | ||
|
||
See [FEATURES.md](FEATURES.md) for a list of features this debugger supports. | ||
|
||
## Build and Run | ||
|
||
1. Clone the repo. | ||
2. `npm i` to install dependencies. | ||
3. Open the project folder in VS Code. | ||
4. From the Run and Debug menu, run the `Extension` configuration to open the AVM Debug extension in another VS Code window. | ||
5. In the new window, go to its Run and Debug menu to select and launch one of the existing configurations. | ||
6. You are now in a debugging session of a transaction group. You can step through the transaction group, inspect variables, set breakpoints and more. See [FEATURES.md](FEATURES.md) for more details. |
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,118 @@ | ||
{ | ||
"name": "avm-debug-vscode-extension", | ||
"displayName": "AVM Debug", | ||
"version": "1.0.0", | ||
"publisher": "algorand-vscode", | ||
"description": "Debug extension for developing AVM transactions and smart contracts.", | ||
"author": { | ||
"name": "Algorand, llc" | ||
}, | ||
"license": "MIT", | ||
"keywords": [ | ||
"multi-root ready" | ||
], | ||
"engines": { | ||
"vscode": "^1.80.0" | ||
}, | ||
"categories": [ | ||
"Debuggers" | ||
], | ||
"private": true, | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/algorand/avm-debugger.git" | ||
}, | ||
"bugs": { | ||
"url": "https://github.com/algorand/avm-debugger/issues" | ||
}, | ||
"main": "dist/extension.js", | ||
"browser": "dist/web-extension.js", | ||
"activationEvents": [ | ||
"workspaceContains:**/*.teal", | ||
"onDebug", | ||
"onDebugResolve:avm", | ||
"onDebugDynamicConfigurations:avm" | ||
], | ||
"workspaceTrust": { | ||
"request": "never" | ||
}, | ||
"contributes": { | ||
"languages": [ | ||
{ | ||
"id": "teal", | ||
"extensions": [ | ||
".teal" | ||
], | ||
"configuration": "teal-language-configuration.json" | ||
} | ||
], | ||
"grammars": [ | ||
{ | ||
"language": "teal", | ||
"scopeName": "source.teal", | ||
"path": "syntaxes/teal.tmLanguage.json" | ||
} | ||
], | ||
"breakpoints": [ | ||
{ | ||
"language": "teal" | ||
} | ||
], | ||
"debuggers": [ | ||
{ | ||
"type": "avm", | ||
"languages": [ | ||
"teal" | ||
], | ||
"label": "AVM Debug", | ||
"program": "../out/src/cli.js", | ||
"runtime": "node", | ||
"configurationAttributes": { | ||
"launch": { | ||
"properties": { | ||
"simulateTraceFile": { | ||
"type": "string", | ||
"description": "Transaction group simulation response with execution trace.", | ||
"default": "${workspaceFolder}/path/to/simulateTraceFile.json" | ||
}, | ||
"programSourcesDescriptionFile": { | ||
"type": "string", | ||
"description": "Description file for sources of programs appearing in transaction group.", | ||
"default": "${workspaceFolder}/path/to/programSourcesDescriptionFile.json" | ||
}, | ||
"stopOnEntry": { | ||
"type": "boolean", | ||
"description": "Automatically stop after launch.", | ||
"default": true | ||
} | ||
} | ||
} | ||
}, | ||
"initialConfigurations": [ | ||
{ | ||
"type": "avm", | ||
"request": "launch", | ||
"name": "Debug AVM Transactions", | ||
"simulateTraceFile": "${workspaceFolder}/path/to/simulateTraceFile.json", | ||
"programSourcesDescriptionFile": "${workspaceFolder}/path/to/programSourcesDescriptionFile.json", | ||
"stopOnEntry": true | ||
} | ||
], | ||
"configurationSnippets": [ | ||
{ | ||
"label": "AVM Debug", | ||
"description": "A new configuration for replaying and debugging a Algorand transactions.", | ||
"body": { | ||
"type": "avm", | ||
"request": "launch", | ||
"name": "Debug AVM Transactions", | ||
"simulateTraceFile": "^\"\\${workspaceFolder}/path/to/simulateTraceFile.json\"", | ||
"programSourcesDescriptionFile": "^\"\\${workspaceFolder}/path/to/programSourcesDescriptionFile.json\"", | ||
"stopOnEntry": true | ||
} | ||
} | ||
] | ||
} | ||
] | ||
} | ||
} |
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 @@ | ||
'use strict'; | ||
|
||
import * as vscode from 'vscode'; | ||
import { AvmDebugConfigProvider } from './configuration'; | ||
|
||
export function activateAvmDebug( | ||
context: vscode.ExtensionContext, | ||
factory: vscode.DebugAdapterDescriptorFactory, | ||
) { | ||
// register a configuration provider for 'avm' debug type | ||
const provider = new AvmDebugConfigProvider(); | ||
context.subscriptions.push( | ||
vscode.debug.registerDebugConfigurationProvider('avm', provider), | ||
); | ||
|
||
context.subscriptions.push( | ||
vscode.debug.registerDebugAdapterDescriptorFactory('avm', factory), | ||
); | ||
|
||
if (isDisposable(factory)) { | ||
// https://vscode-docs.readthedocs.io/en/stable/extensions/patterns-and-principles/#events | ||
// see events, by the end of subscription, call `dispose()` to release resource. | ||
context.subscriptions.push(factory); | ||
} | ||
} | ||
|
||
function isDisposable(value: object): value is { dispose(): unknown } { | ||
return 'dispose' in value; | ||
} |
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,25 @@ | ||
'use strict'; | ||
|
||
import * as vscode from 'vscode'; | ||
import { activateAvmDebug } from './activateAvmDebug'; | ||
import { ServerDebugAdapterFactory } from './serverDescriptorFactory'; | ||
import { InlineDebugAdapterFactory } from './internalDescriptorFactory'; | ||
|
||
const runMode: 'server' | 'inline' = 'inline'; | ||
|
||
export function activate(context: vscode.ExtensionContext) { | ||
switch (runMode) { | ||
case 'server': | ||
// run the debug adapter as a server inside the extension and communicate via a socket | ||
activateAvmDebug(context, new ServerDebugAdapterFactory()); | ||
break; | ||
|
||
case 'inline': | ||
// run the debug adapter inside the extension and directly talk to it | ||
activateAvmDebug(context, new InlineDebugAdapterFactory()); | ||
break; | ||
} | ||
} | ||
|
||
// eslint-disable-next-line @typescript-eslint/no-empty-function | ||
export function deactivate() {} |
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,38 @@ | ||
'use strict'; | ||
|
||
import * as vscode from 'vscode'; | ||
import { FileAccessor } from '../../src'; | ||
|
||
export const workspaceFileAccessor: FileAccessor = { | ||
isWindows: typeof process !== 'undefined' && process.platform === 'win32', | ||
readFile(path: string): Promise<Uint8Array> { | ||
const uri = pathToUri(path); | ||
return thenableToPromise(vscode.workspace.fs.readFile(uri)); | ||
}, | ||
writeFile(path: string, contents: Uint8Array): Promise<void> { | ||
const uri = pathToUri(path); | ||
return thenableToPromise(vscode.workspace.fs.writeFile(uri, contents)); | ||
}, | ||
basename(path: string): string { | ||
const uri = pathToUri(path); | ||
const lastSlash = uri.path.lastIndexOf('/'); | ||
if (lastSlash === -1) { | ||
return path; | ||
} | ||
return uri.path.substring(lastSlash + 1); | ||
}, | ||
}; | ||
|
||
function pathToUri(path: string) { | ||
try { | ||
return vscode.Uri.file(path); | ||
} catch (e) { | ||
return vscode.Uri.parse(path, true); | ||
} | ||
} | ||
|
||
function thenableToPromise<T>(t: Thenable<T>): Promise<T> { | ||
return new Promise((resolve, reject) => { | ||
t.then(resolve, reject); | ||
}); | ||
} |
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,18 @@ | ||
'use strict'; | ||
|
||
import * as vscode from 'vscode'; | ||
import { ProviderResult } from 'vscode'; | ||
import { AvmDebugSession } from '../../src'; | ||
import { workspaceFileAccessor } from './fileAccessor'; | ||
|
||
export class InlineDebugAdapterFactory | ||
implements vscode.DebugAdapterDescriptorFactory | ||
{ | ||
createDebugAdapterDescriptor( | ||
_session: vscode.DebugSession, | ||
): ProviderResult<vscode.DebugAdapterDescriptor> { | ||
return new vscode.DebugAdapterInlineImplementation( | ||
new AvmDebugSession(workspaceFileAccessor), | ||
); | ||
} | ||
} |
Oops, something went wrong.