Skip to content

Commit 748fcf6

Browse files
cmaglieumbynos
andauthored
feat: added more debug options (#2356)
* Improved specification of debug configuration * Added integration test * Added the possibility to provide cortex-debug custom configs * Added svd-file debug option * Added textual print of custom cortex-debug config * Updated docs * Apply suggestions from code review Co-authored-by: Umberto Baldi <34278123+umbynos@users.noreply.github.com> * Added integration test for programmer selection --------- Co-authored-by: Umberto Baldi <34278123+umbynos@users.noreply.github.com>
1 parent f561da0 commit 748fcf6

File tree

10 files changed

+685
-122
lines changed

10 files changed

+685
-122
lines changed

commands/debug/debug.go

+7-2
Original file line numberDiff line numberDiff line change
@@ -158,13 +158,18 @@ func getCommandLine(req *rpc.GetDebugConfigRequest, pme *packagemanager.Explorer
158158
// Extract path to GDB Server
159159
switch debugInfo.GetServer() {
160160
case "openocd":
161+
var openocdConf rpc.DebugOpenOCDServerConfiguration
162+
if err := debugInfo.ServerConfiguration.UnmarshalTo(&openocdConf); err != nil {
163+
return nil, err
164+
}
165+
161166
serverCmd := fmt.Sprintf(`target extended-remote | "%s"`, debugInfo.ServerPath)
162167

163-
if cfg := debugInfo.ServerConfiguration["scripts_dir"]; cfg != "" {
168+
if cfg := openocdConf.GetScriptsDir(); cfg != "" {
164169
serverCmd += fmt.Sprintf(` -s "%s"`, cfg)
165170
}
166171

167-
if script := debugInfo.ServerConfiguration["script"]; script != "" {
172+
for _, script := range openocdConf.GetScripts() {
168173
serverCmd += fmt.Sprintf(` --file "%s"`, script)
169174
}
170175

commands/debug/debug_info.go

+79-2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ package debug
1717

1818
import (
1919
"context"
20+
"encoding/json"
21+
"regexp"
2022
"strings"
2123

2224
"github.com/arduino/arduino-cli/arduino"
@@ -28,6 +30,7 @@ import (
2830
"github.com/arduino/go-paths-helper"
2931
"github.com/arduino/go-properties-orderedmap"
3032
"github.com/sirupsen/logrus"
33+
"google.golang.org/protobuf/types/known/anypb"
3134
)
3235

3336
// GetDebugConfig returns metadata to start debugging with the specified board
@@ -150,14 +153,88 @@ func getDebugProperties(req *rpc.GetDebugConfigRequest, pme *packagemanager.Expl
150153

151154
server := debugProperties.Get("server")
152155
toolchain := debugProperties.Get("toolchain")
156+
157+
var serverConfiguration anypb.Any
158+
switch server {
159+
case "openocd":
160+
openocdProperties := debugProperties.SubTree("server." + server)
161+
scripts := openocdProperties.ExtractSubIndexLists("scripts")
162+
if s := openocdProperties.Get("script"); s != "" {
163+
// backward compatibility
164+
scripts = append(scripts, s)
165+
}
166+
openocdConf := &rpc.DebugOpenOCDServerConfiguration{
167+
Path: openocdProperties.Get("path"),
168+
ScriptsDir: openocdProperties.Get("scripts_dir"),
169+
Scripts: scripts,
170+
}
171+
if err := serverConfiguration.MarshalFrom(openocdConf); err != nil {
172+
return nil, err
173+
}
174+
}
175+
176+
var toolchainConfiguration anypb.Any
177+
switch toolchain {
178+
case "gcc":
179+
gccConf := &rpc.DebugGCCToolchainConfiguration{}
180+
if err := toolchainConfiguration.MarshalFrom(gccConf); err != nil {
181+
return nil, err
182+
}
183+
}
184+
185+
cortexDebugCustomJson := ""
186+
if cortexDebugProps := debugProperties.SubTree("cortex-debug.custom"); cortexDebugProps.Size() > 0 {
187+
cortexDebugCustomJson = convertToJsonMap(cortexDebugProps)
188+
}
153189
return &rpc.GetDebugConfigResponse{
154190
Executable: debugProperties.Get("executable"),
155191
Server: server,
156192
ServerPath: debugProperties.Get("server." + server + ".path"),
157-
ServerConfiguration: debugProperties.SubTree("server." + server).AsMap(),
193+
ServerConfiguration: &serverConfiguration,
194+
SvdFile: debugProperties.Get("svd_file"),
158195
Toolchain: toolchain,
159196
ToolchainPath: debugProperties.Get("toolchain.path"),
160197
ToolchainPrefix: debugProperties.Get("toolchain.prefix"),
161-
ToolchainConfiguration: debugProperties.SubTree("toolchain." + toolchain).AsMap(),
198+
ToolchainConfiguration: &toolchainConfiguration,
199+
CortexDebugCustomJson: cortexDebugCustomJson,
162200
}, nil
163201
}
202+
203+
// Extract a JSON from a given properies.Map and converts key-indexed arrays
204+
// like:
205+
//
206+
// my.indexed.array.0=first
207+
// my.indexed.array.1=second
208+
// my.indexed.array.2=third
209+
//
210+
// into the corresponding JSON arrays.
211+
func convertToJsonMap(in *properties.Map) string {
212+
// XXX: Maybe this method could be a good candidate for propertis.Map?
213+
214+
// Find the values that should be kept as is, and the indexed arrays
215+
// that should be later converted into arrays.
216+
arraysKeys := map[string]bool{}
217+
stringKeys := []string{}
218+
trailingNumberMatcher := regexp.MustCompile(`^(.*)\.[0-9]+$`)
219+
for _, k := range in.Keys() {
220+
match := trailingNumberMatcher.FindAllStringSubmatch(k, -1)
221+
if len(match) > 0 && len(match[0]) > 1 {
222+
arraysKeys[match[0][1]] = true
223+
} else {
224+
stringKeys = append(stringKeys, k)
225+
}
226+
}
227+
228+
// Compose a map that can be later marshaled into JSON keeping
229+
// the arrays where they are expected to be.
230+
res := map[string]any{}
231+
for _, k := range stringKeys {
232+
res[k] = in.Get(k)
233+
}
234+
for k := range arraysKeys {
235+
res[k] = in.ExtractSubIndexLists(k)
236+
}
237+
238+
data, _ := json.MarshalIndent(res, "", " ")
239+
return string(data)
240+
}

docs/UPGRADING.md

+37
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,43 @@ Here you can find a list of migration guides to handle breaking changes between
44

55
## 0.35.0
66

7+
### CLI `debug --info` changed JSON output.
8+
9+
The string field `server_configuration.script` is now an array and has been renamed `scripts`, here an example:
10+
11+
```json
12+
{
13+
"executable": "/tmp/arduino/sketches/002050EAA7EFB9A4FC451CDFBC0FA2D3/Blink.ino.elf",
14+
"toolchain": "gcc",
15+
"toolchain_path": "/home/user/.arduino15/packages/arduino/tools/arm-none-eabi-gcc/7-2017q4/bin/",
16+
"toolchain_prefix": "arm-none-eabi-",
17+
"server": "openocd",
18+
"server_path": "/home/user/.arduino15/packages/arduino/tools/openocd/0.10.0-arduino7/bin/openocd",
19+
"server_configuration": {
20+
"path": "/home/user/.arduino15/packages/arduino/tools/openocd/0.10.0-arduino7/bin/openocd",
21+
"scripts_dir": "/home/user/.arduino15/packages/arduino/tools/openocd/0.10.0-arduino7/share/openocd/scripts/",
22+
"scripts": [
23+
"/home/user/Workspace/arduino-cli/internal/integrationtest/debug/testdata/hardware/my/samd/variants/arduino:mkr1000/openocd_scripts/arduino_zero.cfg"
24+
]
25+
}
26+
}
27+
```
28+
29+
### gRPC `cc.arduino.cli.commands.v1.GetDebugConfigResponse` message has been changed.
30+
31+
The fields `toolchain_configuration` and `server_configuration` are no more generic `map<string, string>` but they have
32+
changed type to `goog.protobuf.Any`, the concrete type is assigned at runtime based on the value of `toolchain` and
33+
`server` fields respectively.
34+
35+
For the moment:
36+
37+
- only `gcc` is supported for `toolchain`, and the concrete type for `toolchain_configuration` is
38+
`DebugGCCToolchainConfiguration`.
39+
- only `openocd` is supported for `server`, and the concrete type for `server_configuration` is
40+
`DebugOpenOCDServerConfiguration`
41+
42+
More concrete type may be added in the future as more servers/toolchains support is implemented.
43+
744
### gRPC service `cc.arduino.cli.debug.v1` moved to `cc.arduino.cli.commands.v1`.
845

946
The gRPC service `cc.arduino.cli.debug.v1` has been removed and all gRPC messages and rpc calls have been moved to

docs/platform-specification.md

+61-1
Original file line numberDiff line numberDiff line change
@@ -1335,13 +1335,73 @@ the [core platform](#platform-terminology) is not used at all in defining the re
13351335
actions. When using Arduino development software other than the Arduino IDE, the handling of properties from the core
13361336
platform's platform.txt is done as usual.
13371337

1338-
### Sketch debugging configuration
1338+
## Sketch debugging configuration
13391339

13401340
Starting from Arduino CLI 0.9.0 / Arduino IDE 2.x, sketch debugging support is available for platforms.
13411341

13421342
The debug action is triggered when the user clicks the Debug button in the Arduino IDE or runs the
13431343
[`arduino-cli debug`](commands/arduino-cli_debug.md) command.
13441344

1345+
Since opening a debug session requires the orchestration of numerous tools, the CLI/IDE will take care of that duty:
1346+
differently from the upload actions, there is no need for the platform to provide debug recipes, the only requirement is
1347+
to provide some debug configuration directives.
1348+
1349+
### Debugger configuration directives
1350+
1351+
All the debug directives are grouped under the `debug.*` directives. Here is the complete list of the supported
1352+
directives:
1353+
1354+
- `debug.toolchain`: is a unique identifier of the required toolchain, currently we support `gcc` (and compatible) only
1355+
- `debug.toolchain.path`: is the absolute path to the toolchain directory
1356+
- `debug.toolchain.prefix`: is the prefix of the toolchain (for example `arm-none-eabi-`)
1357+
- `debug.server`: is a unique identifier of the required debug server, currently we support only `openocd`
1358+
- `debug.svd_file`: is the absolute path to the SVD descriptor.
1359+
1360+
OpenOCD server specific configurations:
1361+
1362+
- `debug.server.openocd.path`: is the absolute path to the OpenOCD directory
1363+
- `debug.server.openocd.scripts_dir`: is the absolute path to the OpenOCD scripts directory
1364+
- `debug.server.openocd.scripts.N`: is a list of OpenOCD scripts to run (where N is a number starting from 0)
1365+
1366+
### Custom config for Cortext-debug plugin for Arduino IDE
1367+
1368+
The Arduino IDE uses cortex-debug plugin to start a debugging session. The IDE creates a `launch.json` file that is
1369+
needed to start the debugging via the cortex-debug plugin. To give the platform developers more flexibility, it is
1370+
allowed to pass any extra arbitrary setup to `launch.json` generated by the IDE. To allow this the directives under the
1371+
group `debug.cortex-debug.custom.*` are converted into JSON and added to the generated `launch.json` as-is. Moreover, if
1372+
a directive has a key with a numeric suffix, it is converted into a JSON array.
1373+
1374+
For example the following directives:
1375+
1376+
```
1377+
debug.cortex-debug.custom.postAttachCommands.0=set remote hardware-watchpoint-limit 2
1378+
debug.cortex-debug.custom.postAttachCommands.1=monitor reset halt
1379+
debug.cortex-debug.custom.postAttachCommands.2=monitor gdb_sync
1380+
debug.cortex-debug.custom.postAttachCommands.3=thb setup
1381+
debug.cortex-debug.custom.postAttachCommands.4=c
1382+
debug.cortex-debug.custom.overrideRestartCommands.0=monitor reset halt
1383+
debug.cortex-debug.custom.overrideRestartCommands.1=monitor gdb_sync
1384+
debug.cortex-debug.custom.overrideRestartCommands.2=thb setup
1385+
debug.cortex-debug.custom.overrideRestartCommands.3=c
1386+
```
1387+
1388+
will result in the following JSON to be merged in the Arduino IDE generated `launch.json`:
1389+
1390+
```json
1391+
{
1392+
"overrideRestartCommands": ["monitor reset halt", "monitor gdb_sync", "thb setup", "c"],
1393+
"postAttachCommands": [
1394+
"set remote hardware-watchpoint-limit 2",
1395+
"monitor reset halt",
1396+
"monitor gdb_sync",
1397+
"thb setup",
1398+
"c"
1399+
]
1400+
}
1401+
```
1402+
1403+
### Optimization level for debugging
1404+
13451405
The compiler optimization level that is appropriate for normal usage will often not provide a good experience while
13461406
debugging. For this reason, it may be helpful to use different compiler flags when compiling a sketch for use with the
13471407
debugger. The flags for use when compiling for debugging can be defined via the **compiler.optimization_flags.debug**

0 commit comments

Comments
 (0)