Actual debugging works

This commit is contained in:
Christian Weichel 2019-11-15 16:34:01 +01:00 committed by Miro Spönemann
parent 3d6d2ce814
commit ea5f528ef0
6 changed files with 51 additions and 40 deletions

View File

@ -27,9 +27,15 @@ export class ArduinoDebugAdapterContribution implements DebugAdapterContribution
"description": "Path to the program to be launched", "description": "Path to the program to be launched",
"default": "${workspaceFolder}/${command:askProgramPath}" "default": "${workspaceFolder}/${command:askProgramPath}"
}, },
"arguments": { "sketch": {
"type": "string", "type": "string",
"description": "Arguments for the program" "description": "Path to the sketch folder",
"default": "${workspaceFolder}"
},
"fbqn": {
"type": "string",
"description": "Fully qualified board name of the debugging target",
"default": "unknown"
}, },
"runToMain": { "runToMain": {
"description": "If enabled the debugger will run until the start of the main function.", "description": "If enabled the debugger will run until the start of the main function.",
@ -75,7 +81,7 @@ export class ArduinoDebugAdapterContribution implements DebugAdapterContribution
"type": "boolean", "type": "boolean",
"description": "Start the debug adapter in debug mode (with --inspect-brk)", "description": "Start the debug adapter in debug mode (with --inspect-brk)",
"default": "false" "default": "false"
} },
} }
} }
] ]
@ -85,7 +91,7 @@ export class ArduinoDebugAdapterContribution implements DebugAdapterContribution
return [] return []
} }
provideDebugAdapterExecutable?(config: DebugConfiguration): MaybePromise<DebugAdapterExecutable> { provideDebugAdapterExecutable(config: DebugConfiguration): MaybePromise<DebugAdapterExecutable> {
let args: string[] = []; let args: string[] = [];
if (!!config.debugDebugAdapter) { if (!!config.debugDebugAdapter) {
args.push('--inspect-brk') args.push('--inspect-brk')

View File

@ -33,7 +33,6 @@ import { CmsisRequestArguments } from './cmsis-debug-session';
const TIMEOUT = 1000 * 10; // 10 seconds const TIMEOUT = 1000 * 10; // 10 seconds
export abstract class AbstractServer extends EventEmitter { export abstract class AbstractServer extends EventEmitter {
protected process?: ChildProcess; protected process?: ChildProcess;
protected outBuffer: string = ''; protected outBuffer: string = '';
protected errBuffer: string = ''; protected errBuffer: string = '';
@ -50,7 +49,7 @@ export abstract class AbstractServer extends EventEmitter {
this.timer = setTimeout(() => this.onSpawnError(new Error('Timeout waiting for gdb server to start')), TIMEOUT); this.timer = setTimeout(() => this.onSpawnError(new Error('Timeout waiting for gdb server to start')), TIMEOUT);
const command = args.gdbServer || 'gdb-server'; const command = args.gdbServer || 'gdb-server';
const serverArguments = await this.resolveServerArguments(args.gdbServerArguments); const serverArguments = await this.resolveServerArguments(args);
this.process = spawn(command, serverArguments, { this.process = spawn(command, serverArguments, {
cwd: dirname(command), cwd: dirname(command),
}); });
@ -80,8 +79,8 @@ export abstract class AbstractServer extends EventEmitter {
} }
} }
protected async resolveServerArguments(serverArguments?: string[]): Promise<string[]> { protected async resolveServerArguments(req: CmsisRequestArguments): Promise<string[]> {
return serverArguments || []; return req.gdbServerArguments || [];
} }
protected onExit(code: number, signal: string) { protected onExit(code: number, signal: string) {

View File

@ -29,16 +29,18 @@ import { Logger, logger, InitializedEvent, OutputEvent, Scope, TerminatedEvent }
import { GDBDebugSession, RequestArguments, FrameVariableReference, FrameReference, ObjectVariableReference } from 'cdt-gdb-adapter/dist/GDBDebugSession'; import { GDBDebugSession, RequestArguments, FrameVariableReference, FrameReference, ObjectVariableReference } from 'cdt-gdb-adapter/dist/GDBDebugSession';
import { GDBBackend } from 'cdt-gdb-adapter/dist/GDBBackend'; import { GDBBackend } from 'cdt-gdb-adapter/dist/GDBBackend';
import { CmsisBackend } from './cmsis-backend'; import { CmsisBackend } from './cmsis-backend';
import { PyocdServer } from './pyocd-server'; // import { PyocdServer } from './pyocd-server';
import { PortScanner } from './port-scanner'; import { PortScanner } from './port-scanner';
import { SymbolTable } from './symbols'; import { SymbolTable } from './symbols';
import * as varMgr from 'cdt-gdb-adapter/dist/varManager'; import * as varMgr from 'cdt-gdb-adapter/dist/varManager';
import * as mi from './mi'; import * as mi from './mi';
import { OpenocdServer } from './openocd-server';
export interface CmsisRequestArguments extends RequestArguments { export interface CmsisRequestArguments extends RequestArguments {
runToMain?: boolean; runToMain?: boolean;
gdbServer?: string; gdbServer?: string;
gdbServerArguments?: string[]; gdbServerArguments?: string[];
gdbServerPort?: number;
objdump?: string; objdump?: string;
} }
@ -48,7 +50,7 @@ const STATIC_HANDLES_FINISH = 0x01FFFF;
export class CmsisDebugSession extends GDBDebugSession { export class CmsisDebugSession extends GDBDebugSession {
protected gdbServer = new PyocdServer(); protected gdbServer = new OpenocdServer();
protected portScanner = new PortScanner(); protected portScanner = new PortScanner();
protected symbolTable!: SymbolTable; protected symbolTable!: SymbolTable;
protected globalHandle!: number; protected globalHandle!: number;
@ -110,6 +112,11 @@ export class CmsisDebugSession extends GDBDebugSession {
} }
} }
protected async setBreakPointsRequest(response: DebugProtocol.SetBreakpointsResponse, args: DebugProtocol.SetBreakpointsArguments): Promise<void> {
await super.setBreakPointsRequest(response, args);
return;
}
protected scopesRequest(response: DebugProtocol.ScopesResponse, args: DebugProtocol.ScopesArguments): void { protected scopesRequest(response: DebugProtocol.ScopesResponse, args: DebugProtocol.ScopesArguments): void {
try { try {
const frame: FrameVariableReference = { const frame: FrameVariableReference = {
@ -245,10 +252,11 @@ export class CmsisDebugSession extends GDBDebugSession {
if (!args.gdbServerArguments) { if (!args.gdbServerArguments) {
args.gdbServerArguments = []; args.gdbServerArguments = [];
} }
args.gdbServerArguments.push('--port', port.toString()); args.gdbServerPort = port;
// Start gdb client and server // Start gdb client and server
this.progressEvent(0, 'Starting Debugger'); this.progressEvent(0, 'Starting Debugger');
this.sendEvent(new OutputEvent(`Starting debugger: ${JSON.stringify(args)}`));
await this.gdbServer.spawn(args); await this.gdbServer.spawn(args);
await this.spawn(args); await this.spawn(args);

View File

@ -42,8 +42,8 @@ export function sendTargetSelectRemote(gdb: GDBBackend, remote: string) {
} }
export function sendTargetDownload(gdb: GDBBackend) { export function sendTargetDownload(gdb: GDBBackend) {
const command = '-target-download'; // const command = '-target-download';
return gdb.sendCommand(command); // return gdb.sendCommand(command);
} }
export function sendBreakOnFunction(gdb: GDBBackend, fn: string = 'main') { export function sendBreakOnFunction(gdb: GDBBackend, fn: string = 'main') {

View File

@ -1,31 +1,33 @@
import { AbstractServer } from './abstract-server'; import { AbstractServer } from './abstract-server';
import { PortScanner } from './port-scanner'; import { PortScanner } from './port-scanner';
import { CmsisRequestArguments } from './cmsis-debug-session';
import * as fs from 'fs-extra';
import * as path from 'path';
const LAUNCH_REGEX = /GDB server started/; const LAUNCH_REGEX = /GDB server started/;
const ERROR_REGEX = /:ERROR:gdbserver:/; const ERROR_REGEX = /:ERROR:gdbserver:/;
const PERCENT_MULTIPLIER = 100 / 40; // pyOCD outputs 40 markers for progress const PERCENT_MULTIPLIER = 100 / 40; // pyOCD outputs 40 markers for progress
export class OpenocdServer extends AbstractServer { export class OpenocdServer extends AbstractServer {
protected portScanner = new PortScanner(); protected portScanner = new PortScanner();
protected progress = 0; protected progress = 0;
protected async resolveServerArguments(serverArguments?: string[]): Promise<string[]> { protected async resolveServerArguments(req: CmsisRequestArguments): Promise<string[]> {
if (!serverArguments) { let sessionConfigFile = `gdb_port ${req.gdbServerPort!}${"\n"}`;
serverArguments = [];
}
const telnetPort = await this.portScanner.findFreePort(4444); const telnetPort = await this.portScanner.findFreePort(4444);
if (!!telnetPort) {
if (!telnetPort) { sessionConfigFile += `telnet_port ${telnetPort}${"\n"}`
return serverArguments;
} }
sessionConfigFile += `echo "GDB server started"${"\n"}`
const tmpdir = await fs.mkdtemp("arduino-debugger");
const sessionCfgPath = path.join(tmpdir, "gdb.cfg");
await fs.writeFile(sessionCfgPath, sessionConfigFile);
return [ let serverArguments = req.gdbServerArguments || [];
...serverArguments, serverArguments.push("--file", sessionCfgPath);
'--telnet-port',
telnetPort.toString() return serverArguments;
];
} }
protected onStdout(chunk: string | Buffer) { protected onStdout(chunk: string | Buffer) {

View File

@ -25,6 +25,7 @@
import { AbstractServer } from './abstract-server'; import { AbstractServer } from './abstract-server';
import { PortScanner } from './port-scanner'; import { PortScanner } from './port-scanner';
import { CmsisRequestArguments } from './cmsis-debug-session';
const LAUNCH_REGEX = /GDB server started/; const LAUNCH_REGEX = /GDB server started/;
const ERROR_REGEX = /:ERROR:gdbserver:/; const ERROR_REGEX = /:ERROR:gdbserver:/;
@ -35,22 +36,17 @@ export class PyocdServer extends AbstractServer {
protected portScanner = new PortScanner(); protected portScanner = new PortScanner();
protected progress = 0; protected progress = 0;
protected async resolveServerArguments(serverArguments?: string[]): Promise<string[]> { protected async resolveServerArguments(req: CmsisRequestArguments): Promise<string[]> {
if (!serverArguments) { let serverArguments = req.gdbServerArguments || [];
serverArguments = [];
} serverArguments.push('--port', req.gdbServerPort!.toString())
const telnetPort = await this.portScanner.findFreePort(4444); const telnetPort = await this.portScanner.findFreePort(4444);
if (!!telnetPort) {
if (!telnetPort) { serverArguments.push('--telnet-port', telnetPort.toString())
return serverArguments;
} }
return [ return serverArguments;
...serverArguments,
'--telnet-port',
telnetPort.toString()
];
} }
protected onStdout(chunk: string | Buffer) { protected onStdout(chunk: string | Buffer) {