aboutsummaryrefslogtreecommitdiff
path: root/src/helper
diff options
context:
space:
mode:
authorAntonio Borneo <borneo.antonio@gmail.com>2018-10-22 09:06:50 +0200
committerTomas Vanek <vanekt@fbl.cz>2018-12-15 07:18:13 +0000
commit334552bc831baf4a88f8b42c93e87ed052c923d2 (patch)
tree26fc0067be2cd546564a83c89256e9068800141d /src/helper
parent02279e2f5e99885106bbd3acbb5926b3f2146296 (diff)
downloadriscv-openocd-334552bc831baf4a88f8b42c93e87ed052c923d2.zip
riscv-openocd-334552bc831baf4a88f8b42c93e87ed052c923d2.tar.gz
riscv-openocd-334552bc831baf4a88f8b42c93e87ed052c923d2.tar.bz2
helper/startup.tcl: fix execution stack frame of wrapped commands
The OpenOCD commands that have been wrapped with 'ocd_bouncer' are executed within two levels of nested proc's: # see register_command_handler() in src/helper/command.c proc my_command {args} {eval ocd_bouncer my_command $args} # see ocd_bouncer in src/helper/startup.tcl proc ocd_bouncer {name args} { ... [eval ocd_my_command $args] ... } This causes the stack frame of 'ocd_my_command' to be the same one of proc 'ocd_bouncer', thus two levels below the stack frame of the caller of 'my_command'. This is an issue with commands that receive a variable by name and have to resolve them to access the value. E.g. the command <target> mem2array arrayname bitwidth address count is wrapped; it receives the name of the array but fails to resolve it in the current stack frame. Instead, the commands mem2array arrayname bitwidth address count ocd_<target> mem2array arrayname bitwidth address count are not wrapped and can directly access the array because they share the same stack frame of the caller. Same situation with the symmetric commands 'array2mem'. How to test: within a telnet connection, run the following set of commands, eventually replacing the address 0x08000000 with a valid readable address of your <target>, unset -nocomplain v1 v2 v3 info vars v? mem2array v1 32 0x08000000 1 <target> mem2array v2 32 0x08000000 1 ocd_<target> mem2array v3 32 0x08000000 1 info vars v? and notice that only v1 and v3 are now allocated. The array v2 has been allocated in the temporarily stack frame of proc ocd_bouncer, together with its local variables, and then lost when proc ended. Fixed by executing the wrapped commands with the command 'uplevel' instead of 'eval'. The amount of levels to skip is checked to avoid errors in the unusual case 'ocd_bouncer' is called directly without the first level of wrapper. Change-Id: Iff90fb8921faf9b5ab04f61062a530578cc20d78 Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com> Reviewed-on: http://openocd.zylin.com/4731 Tested-by: jenkins Reviewed-by: Christopher Head <chead@zaber.com> Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
Diffstat (limited to 'src/helper')
-rw-r--r--src/helper/startup.tcl9
1 files changed, 6 insertions, 3 deletions
diff --git a/src/helper/startup.tcl b/src/helper/startup.tcl
index 4ca2cab..2578de9 100644
--- a/src/helper/startup.tcl
+++ b/src/helper/startup.tcl
@@ -12,15 +12,18 @@ proc exit {} {
# All commands are registered with an 'ocd_' prefix, while the "real"
# command is a wrapper that calls this function. Its primary purpose is
-# to discard 'handler' command output,
+# to discard 'handler' command output.
+# Due to the two nested proc calls, this wrapper has to explicitly run
+# the wrapped command in the stack frame two levels above.
proc ocd_bouncer {name args} {
set cmd [format "ocd_%s" $name]
set type [eval ocd_command type $cmd $args]
set errcode error
+ set skiplevel [expr [eval info level] > 1 ? 2 : 1]
if {$type == "native"} {
- return [eval $cmd $args]
+ return [uplevel $skiplevel $cmd $args]
} else {if {$type == "simple"} {
- set errcode [catch {eval $cmd $args}]
+ set errcode [catch {uplevel $skiplevel $cmd $args}]
if {$errcode == 0} {
return ""
} else {