Line 27... |
Line 27... |
#
|
#
|
# Author(s):
|
# Author(s):
|
# - Olivier Girard, olgirard@gmail.com
|
# - Olivier Girard, olgirard@gmail.com
|
#
|
#
|
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
# $Rev: 158 $
|
# $Rev: 172 $
|
# $LastChangedBy: olivier.girard $
|
# $LastChangedBy: olivier.girard $
|
# $LastChangedDate: 2012-10-15 23:49:09 +0200 (Mon, 15 Oct 2012) $
|
# $LastChangedDate: 2012-12-28 00:06:56 +0100 (Fri, 28 Dec 2012) $
|
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
|
|
global mem_breakpoint
|
global mem_breakpoint
|
|
global mem_mapping
|
|
global breakSelect
|
|
|
###############################################################################
|
###############################################################################
|
# #
|
# #
|
# RSP COMMAND PARSER #
|
# RSP COMMAND PARSER #
|
# #
|
# #
|
###############################################################################
|
###############################################################################
|
|
|
proc rspParse {sock rsp_cmd} {
|
proc rspParse {CpuNr sock rsp_cmd} {
|
|
|
set rsp_answer ""
|
set rsp_answer ""
|
set cmd_tail [string range $rsp_cmd 1 [string length $rsp_cmd]]
|
set cmd_tail [string range $rsp_cmd 1 [string length $rsp_cmd]]
|
|
|
switch -exact -- [string index $rsp_cmd 0] {
|
switch -exact -- [string index $rsp_cmd 0] {
|
"!" {set rsp_answer "OK"}
|
"!" {set rsp_answer "OK"}
|
"?" {set rsp_answer [rsp_stop_reply $sock "?"]}
|
"?" {set rsp_answer [rsp_stop_reply $CpuNr $sock "?"]}
|
"A" {}
|
"A" {}
|
"b" {}
|
"b" {}
|
"c" {set rsp_answer [rsp_c $sock $cmd_tail]}
|
"c" {set rsp_answer [rsp_c $CpuNr $sock $cmd_tail]}
|
"C" {set rsp_answer [rsp_c $sock $cmd_tail]}
|
"C" {set rsp_answer [rsp_c $CpuNr $sock $cmd_tail]}
|
"D" {}
|
"D" {}
|
"F" {}
|
"F" {}
|
"g" {set rsp_answer [rsp_g]}
|
"g" {set rsp_answer [rsp_g $CpuNr]}
|
"G" {set rsp_answer [rsp_G $cmd_tail]}
|
"G" {set rsp_answer [rsp_G $CpuNr $cmd_tail]}
|
"H" {set rsp_answer ""}
|
"H" {set rsp_answer ""}
|
"i" {}
|
"i" {}
|
"I" {}
|
"I" {}
|
"k" {set rsp_answer [rsp_k $cmd_tail]}
|
"k" {set rsp_answer [rsp_k $CpuNr $cmd_tail]}
|
"m" {set rsp_answer [rsp_m $cmd_tail]}
|
"m" {set rsp_answer [rsp_m $CpuNr $cmd_tail]}
|
"M" {set rsp_answer [rsp_M $cmd_tail]}
|
"M" {set rsp_answer [rsp_M $CpuNr $cmd_tail]}
|
"p" {}
|
"p" {}
|
"P" {}
|
"P" {}
|
"q" {set rsp_answer [rsp_q $sock $cmd_tail]}
|
"q" {set rsp_answer [rsp_q $CpuNr $sock $cmd_tail]}
|
"Q" {}
|
"Q" {}
|
"R" {}
|
"R" {}
|
"s" {set rsp_answer [rsp_s $sock $cmd_tail]}
|
"s" {set rsp_answer [rsp_s $CpuNr $sock $cmd_tail]}
|
"S" {set rsp_answer [rsp_s $sock $cmd_tail]}
|
"S" {set rsp_answer [rsp_s $CpuNr $sock $cmd_tail]}
|
"t" {}
|
"t" {}
|
"T" {}
|
"T" {}
|
"v" {}
|
"v" {}
|
"X" {}
|
"X" {}
|
"z" {set rsp_answer [rsp_z $sock $cmd_tail]}
|
"z" {set rsp_answer [rsp_z $CpuNr $sock $cmd_tail]}
|
"Z" {set rsp_answer [rsp_Z $sock $cmd_tail]}
|
"Z" {set rsp_answer [rsp_Z $CpuNr $sock $cmd_tail]}
|
default {}
|
default {}
|
}
|
}
|
|
|
|
|
return $rsp_answer
|
return $rsp_answer
|
Line 92... |
Line 94... |
###############################################################################
|
###############################################################################
|
|
|
#-----------------------------------------------------------------------------#
|
#-----------------------------------------------------------------------------#
|
# Read CPU registers #
|
# Read CPU registers #
|
#-----------------------------------------------------------------------------#
|
#-----------------------------------------------------------------------------#
|
proc rsp_g {} {
|
proc rsp_g {CpuNr} {
|
|
|
global CpuNr
|
|
|
|
# Read register value
|
# Read register value
|
set reg_val [ReadRegAll $CpuNr]
|
set reg_val [ReadRegAll $CpuNr]
|
|
|
# Format answer
|
# Format answer
|
Line 113... |
Line 113... |
}
|
}
|
|
|
#-----------------------------------------------------------------------------#
|
#-----------------------------------------------------------------------------#
|
# Write CPU registers #
|
# Write CPU registers #
|
#-----------------------------------------------------------------------------#
|
#-----------------------------------------------------------------------------#
|
proc rsp_G {cmd} {
|
proc rsp_G {CpuNr cmd} {
|
|
|
global CpuNr
|
|
|
|
# Format register value
|
# Format register value
|
set num_reg [expr [string length $cmd]/4]
|
set num_reg [expr [string length $cmd]/4]
|
|
|
set reg_val ""
|
set reg_val ""
|
Line 137... |
Line 135... |
}
|
}
|
|
|
#-----------------------------------------------------------------------------#
|
#-----------------------------------------------------------------------------#
|
# Kill request. #
|
# Kill request. #
|
#-----------------------------------------------------------------------------#
|
#-----------------------------------------------------------------------------#
|
proc rsp_k {cmd} {
|
proc rsp_k {CpuNr cmd} {
|
|
|
global CpuNr
|
|
|
|
# Reset & Stop CPU
|
# Reset & Stop CPU
|
ExecutePOR_Halt $CpuNr
|
ExecutePOR_Halt $CpuNr
|
|
|
return "-1"
|
return "-1"
|
}
|
}
|
|
|
#-----------------------------------------------------------------------------#
|
#-----------------------------------------------------------------------------#
|
# Write length bytes of memory. #
|
# Write length bytes of memory. #
|
#-----------------------------------------------------------------------------#
|
#-----------------------------------------------------------------------------#
|
proc rsp_M {cmd} {
|
proc rsp_M {CpuNr cmd} {
|
|
|
global mem_breakpoint
|
global mem_breakpoint
|
global CpuNr
|
global mem_mapping
|
|
global breakSelect
|
|
|
# Parse command
|
# Parse command
|
regexp {(.*),(.*):(.*)} $cmd match addr length data
|
regexp {(.*),(.*):(.*)} $cmd match addr length data
|
set addr [format %04x "0x$addr"]
|
set addr [format %04x "0x$addr"]
|
set length [format %d "0x$length"]
|
set length [format %d "0x$length"]
|
Line 175... |
Line 172... |
} else {
|
} else {
|
WriteMemQuick8 $CpuNr "0x$addr" $mem_val
|
WriteMemQuick8 $CpuNr "0x$addr" $mem_val
|
}
|
}
|
|
|
# Eventually re-set the software breakpoints in case they have been overwritten
|
# Eventually re-set the software breakpoints in case they have been overwritten
|
|
if {$breakSelect==0} {
|
set addr_start [format %d "0x$addr"]
|
set addr_start [format %d "0x$addr"]
|
foreach {brk_addr brk_val} [array get mem_breakpoint] {
|
foreach {brk_addr brk_val} [array get mem_breakpoint] {
|
set brk_addr_dec [format %d "0x$brk_addr"]
|
regsub {,} $brk_addr { } brk_addr_lst
|
|
if {[lindex $brk_addr_lst 0]==$mem_mapping($CpuNr)} {
|
|
set brk_addr_dec [format %d "0x[lindex $brk_addr_lst 1]"]
|
set brk_addr_offset [expr $brk_addr_dec-$addr_start]
|
set brk_addr_offset [expr $brk_addr_dec-$addr_start]
|
if {(0<=$brk_addr_offset) && ($brk_addr_offset<=$length)} {
|
if {(0<=$brk_addr_offset) && ($brk_addr_offset<=$length)} {
|
set mem_breakpoint($brk_addr) [lindex $mem_val $brk_addr_offset]
|
set mem_breakpoint($brk_addr) [lindex $mem_val $brk_addr_offset]
|
WriteMem $CpuNr 0 "0x$brk_addr" 0x4343
|
WriteMem $CpuNr 0 "0x[lindex $brk_addr 1]" 0x4343
|
|
}
|
|
}
|
}
|
}
|
}
|
}
|
|
|
return "OK"
|
return "OK"
|
}
|
}
|
|
|
|
|
#-----------------------------------------------------------------------------#
|
#-----------------------------------------------------------------------------#
|
# Read length bytes from memory. #
|
# Read length bytes from memory. #
|
#-----------------------------------------------------------------------------#
|
#-----------------------------------------------------------------------------#
|
proc rsp_m {cmd} {
|
proc rsp_m {CpuNr cmd} {
|
|
|
global mem_breakpoint
|
global mem_breakpoint
|
global CpuNr
|
global mem_mapping
|
|
global breakSelect
|
|
|
# Parse command
|
# Parse command
|
regexp {(.*),(.*)} $cmd match addr length
|
regexp {(.*),(.*)} $cmd match addr length
|
set addr [format %04x "0x$addr"]
|
set addr [format %04x "0x$addr"]
|
set length [format %d "0x$length"]
|
set length [format %d "0x$length"]
|
Line 207... |
Line 210... |
# Read memory
|
# Read memory
|
set data [ReadMemQuick8 $CpuNr "0x$addr" $length]
|
set data [ReadMemQuick8 $CpuNr "0x$addr" $length]
|
|
|
|
|
# Eventually replace read data by the original software breakpoint value
|
# Eventually replace read data by the original software breakpoint value
|
|
if {$breakSelect==0} {
|
set addr_start [format %d "0x$addr"]
|
set addr_start [format %d "0x$addr"]
|
foreach {brk_addr brk_val} [array get mem_breakpoint] {
|
foreach {brk_addr brk_val} [array get mem_breakpoint] {
|
set brk_addr_dec [format %d "0x$brk_addr"]
|
regsub {,} $brk_addr { } brk_addr_lst
|
|
if {[lindex $brk_addr_lst 0]==$mem_mapping($CpuNr)} {
|
|
set brk_addr_dec [format %d "0x[lindex $brk_addr_lst 1]"]
|
set brk_addr_offset [expr $brk_addr_dec-$addr_start]
|
set brk_addr_offset [expr $brk_addr_dec-$addr_start]
|
if {(0<=$brk_addr_offset) && ($brk_addr_offset<=$length)} {
|
if {(0<=$brk_addr_offset) && ($brk_addr_offset<=$length)} {
|
set data [lreplace $data $brk_addr_offset $brk_addr_offset "0x$mem_breakpoint($brk_addr)"]
|
set data [lreplace $data $brk_addr_offset $brk_addr_offset "0x$mem_breakpoint($brk_addr)"]
|
}
|
}
|
}
|
}
|
|
}
|
|
}
|
|
|
# Format data
|
# Format data
|
regsub -all {0x} $data {} data
|
regsub -all {0x} $data {} data
|
regsub -all { } $data {} data
|
regsub -all { } $data {} data
|
|
|
Line 227... |
Line 235... |
|
|
|
|
#-----------------------------------------------------------------------------#
|
#-----------------------------------------------------------------------------#
|
# Insert breakpoint. #
|
# Insert breakpoint. #
|
#-----------------------------------------------------------------------------#
|
#-----------------------------------------------------------------------------#
|
proc rsp_Z {sock cmd} {
|
proc rsp_Z {CpuNr sock cmd} {
|
|
|
global mem_breakpoint
|
global mem_breakpoint
|
global CpuNr
|
global mem_mapping
|
|
global breakSelect
|
|
|
# Parse command
|
# Parse command
|
regexp {(.),(.*),(.*)} $cmd match type addr length
|
regexp {(.),(.*),(.*)} $cmd match type addr length
|
set addr [format %04x "0x$addr"]
|
set addr [format %04x "0x$addr"]
|
|
|
switch -exact -- $type {
|
switch -exact -- $type {
|
"0" {# Memory breakpoint
|
"0" {# Soft Memory breakpoint
|
set mem_breakpoint($addr) [ReadMem $CpuNr 0 "0x$addr"]
|
if {$breakSelect==0} {
|
|
if {![info exists mem_breakpoint($mem_mapping($CpuNr),$addr)]} {
|
|
set mem_breakpoint($mem_mapping($CpuNr),$addr) [ReadMem $CpuNr 0 "0x$addr"]
|
WriteMem $CpuNr 0 "0x$addr" 0x4343
|
WriteMem $CpuNr 0 "0x$addr" 0x4343
|
|
}
|
return "OK"
|
return "OK"
|
|
|
|
# Hard Memory breakpoint
|
|
} else {
|
|
if {[SetHWBreak $CpuNr 1 [format "0x%04x" 0x$addr] 1 0]} {
|
|
#putsLog "CORE $CpuNr: --- INFO --- SET HARDWARE MEMORY BREAKPOINT. "
|
|
return "OK"
|
|
}
|
|
putsLog "CORE $CpuNr: --- ERROR --- NO MORE HARDWARE MEMORY BREAKPOINT AVAILABLE. "
|
|
return ""
|
|
}
|
}
|
}
|
|
|
"1" {# Hardware breakpoint
|
"1" {# Hardware breakpoint
|
if {[SetHWBreak $CpuNr 1 [format "0x%04x" 0x$addr] 1 0]} {
|
if {[SetHWBreak $CpuNr 1 [format "0x%04x" 0x$addr] 1 0]} {
|
return "OK"
|
return "OK"
|
}
|
}
|
|
putsLog "CORE $CpuNr: --- ERROR --- NO MORE HARDWARE BREAKPOINT AVAILABLE. "
|
return ""
|
return ""
|
}
|
}
|
|
|
"2" {# Write watchpoint
|
"2" {# Write watchpoint
|
if {[SetHWBreak $CpuNr 0 [format "0x%04x" 0x$addr] 0 1]} {
|
if {[SetHWBreak $CpuNr 0 [format "0x%04x" 0x$addr] 0 1]} {
|
return "OK"
|
return "OK"
|
}
|
}
|
|
putsLog "CORE $CpuNr: --- ERROR --- NO MORE WRITE WATCHPOINT AVAILABLE. "
|
return ""
|
return ""
|
}
|
}
|
|
|
"3" {# Read watchpoint
|
"3" {# Read watchpoint
|
if {[SetHWBreak $CpuNr 0 [format "0x%04x" 0x$addr] 1 0]} {
|
if {[SetHWBreak $CpuNr 0 [format "0x%04x" 0x$addr] 1 0]} {
|
return "OK"
|
return "OK"
|
}
|
}
|
|
putsLog "CORE $CpuNr: --- ERROR --- NO MORE READ WATCHPOINT AVAILABLE. "
|
return ""
|
return ""
|
}
|
}
|
|
|
"4" {# Access watchpoint
|
"4" {# Access watchpoint
|
if {[SetHWBreak $CpuNr 0 [format "0x%04x" 0x$addr] 1 1]} {
|
if {[SetHWBreak $CpuNr 0 [format "0x%04x" 0x$addr] 1 1]} {
|
return "OK"
|
return "OK"
|
}
|
}
|
|
putsLog "CORE $CpuNr: --- ERROR --- NO MORE ACCESS WATCHPOINT AVAILABLE. "
|
return ""
|
return ""
|
}
|
}
|
|
|
default {return ""}
|
default {return ""}
|
}
|
}
|
}
|
}
|
|
|
#-----------------------------------------------------------------------------#
|
#-----------------------------------------------------------------------------#
|
# Remove breakpoint. #
|
# Remove breakpoint. #
|
#-----------------------------------------------------------------------------#
|
#-----------------------------------------------------------------------------#
|
proc rsp_z {sock cmd} {
|
proc rsp_z {CpuNr sock cmd} {
|
|
|
global mem_breakpoint
|
global mem_breakpoint
|
global CpuNr
|
global mem_mapping
|
|
global breakSelect
|
|
|
# Parse command
|
# Parse command
|
regexp {(.),(.*),(.*)} $cmd match type addr length
|
regexp {(.),(.*),(.*)} $cmd match type addr length
|
set addr [format %04x "0x$addr"]
|
set addr [format %04x "0x$addr"]
|
|
|
switch -exact -- $type {
|
switch -exact -- $type {
|
"0" {# Memory breakpoint
|
"0" {# Soft Memory breakpoint
|
WriteMem $CpuNr 0 "0x$addr" $mem_breakpoint($addr)
|
if {$breakSelect==0} {
|
unset mem_breakpoint($addr)
|
if {[info exists mem_breakpoint($mem_mapping($CpuNr),$addr)]} {
|
|
WriteMem $CpuNr 0 "0x$addr" $mem_breakpoint($mem_mapping($CpuNr),$addr)
|
|
unset mem_breakpoint($mem_mapping($CpuNr),$addr)
|
|
}
|
|
return "OK"
|
|
|
|
# Hard Memory breakpoint
|
|
} else {
|
|
if {[ClearHWBreak $CpuNr 1 [format "0x%04x" 0x$addr]]} {
|
|
#putsLog "CORE $CpuNr: --- INFO --- RELEASE HARDWARE MEMORY BREAKPOINT. "
|
return "OK"
|
return "OK"
|
}
|
}
|
|
putsLog "CORE $CpuNr: --- ERROR --- COULD NOT REMOVE HARDWARE MEMORY BREAKPOINT. "
|
|
return ""
|
|
}
|
|
}
|
|
|
"1" {# Hardware breakpoint
|
"1" {# Hardware breakpoint
|
if {[ClearHWBreak $CpuNr 1 [format "0x%04x" 0x$addr]]} {
|
if {[ClearHWBreak $CpuNr 1 [format "0x%04x" 0x$addr]]} {
|
return "OK"
|
return "OK"
|
}
|
}
|
Line 329... |
Line 369... |
}
|
}
|
|
|
#-----------------------------------------------------------------------------#
|
#-----------------------------------------------------------------------------#
|
# Continue. #
|
# Continue. #
|
#-----------------------------------------------------------------------------#
|
#-----------------------------------------------------------------------------#
|
proc rsp_c {sock cmd} {
|
proc rsp_c {CpuNr sock cmd} {
|
|
|
global CpuNr
|
|
|
|
# Set address if required
|
# Set address if required
|
if {$cmd!=""} {
|
if {$cmd!=""} {
|
set cmd [format %04x "0x$cmd"]
|
set cmd [format %04x "0x$cmd"]
|
SetPC $CpuNr "0x$cmd"
|
SetPC $CpuNr "0x$cmd"
|
Line 346... |
Line 384... |
|
|
# Continue
|
# Continue
|
ReleaseCPU $CpuNr
|
ReleaseCPU $CpuNr
|
|
|
|
|
return [rsp_stop_reply $sock "c"]
|
return [rsp_stop_reply $CpuNr $sock "c"]
|
}
|
}
|
|
|
#-----------------------------------------------------------------------------#
|
#-----------------------------------------------------------------------------#
|
# Step. #
|
# Step. #
|
#-----------------------------------------------------------------------------#
|
#-----------------------------------------------------------------------------#
|
proc rsp_s {sock cmd} {
|
proc rsp_s {CpuNr sock cmd} {
|
|
|
global CpuNr
|
|
|
|
# Set address if required
|
# Set address if required
|
if {$cmd!=""} {
|
if {$cmd!=""} {
|
set cmd [format %04x "0x$cmd"]
|
set cmd [format %04x "0x$cmd"]
|
SetPC $CpuNr "0x$cmd"
|
SetPC $CpuNr "0x$cmd"
|
Line 371... |
Line 407... |
set pc [ReadReg $CpuNr 0]
|
set pc [ReadReg $CpuNr 0]
|
|
|
# Incremental step
|
# Incremental step
|
StepCPU $CpuNr
|
StepCPU $CpuNr
|
|
|
return [rsp_stop_reply $sock "s" $pc]
|
return [rsp_stop_reply $CpuNr $sock "s" $pc]
|
}
|
}
|
|
|
|
|
#-----------------------------------------------------------------------------#
|
#-----------------------------------------------------------------------------#
|
# The `C', `c', `S', `s', `vCont', `vAttach', `vRun', `vStopped', and `?' #
|
# The `C', `c', `S', `s', `vCont', `vAttach', `vRun', `vStopped', and `?' #
|
# packets can receive any of the below as a reply. Except for `?' and #
|
# packets can receive any of the below as a reply. Except for `?' and #
|
# `vStopped', that reply is only returned when the target halts. #
|
# `vStopped', that reply is only returned when the target halts. #
|
#-----------------------------------------------------------------------------#
|
#-----------------------------------------------------------------------------#
|
proc rsp_stop_reply {sock cmd {opt_val "0"}} {
|
proc rsp_stop_reply {CpuNr sock cmd {opt_val "0"}} {
|
|
|
global CpuNr
|
|
|
|
# Wait until halted
|
# Wait until halted
|
while {![IsHalted $CpuNr]} {
|
while {![IsHalted $CpuNr]} {
|
|
|
# Wait a few milliseconds to prevent the gui from freezing
|
# Wait a few milliseconds to prevent the gui from freezing
|
Line 424... |
Line 458... |
|
|
|
|
#-----------------------------------------------------------------------------#
|
#-----------------------------------------------------------------------------#
|
# #
|
# #
|
#-----------------------------------------------------------------------------#
|
#-----------------------------------------------------------------------------#
|
proc rsp_q {sock cmd} {
|
proc rsp_q {CpuNr sock cmd} {
|
|
|
switch -regexp -- $cmd {
|
switch -regexp -- $cmd {
|
|
|
"C" {set rsp_answer ""}
|
"C" {set rsp_answer ""}
|
"Offsets" {set rsp_answer "Text=0;Data=0;Bss=0"}
|
"Offsets" {set rsp_answer "Text=0;Data=0;Bss=0"}
|
"Rcmd,.+" {set rsp_answer [rsp_qRcmd $sock $cmd]}
|
"Rcmd,.+" {set rsp_answer [rsp_qRcmd $CpuNr $sock $cmd]}
|
default {set rsp_answer ""}
|
default {set rsp_answer ""}
|
}
|
}
|
return $rsp_answer
|
return $rsp_answer
|
}
|
}
|
|
|
Line 445... |
Line 479... |
# final result packet, the target may also respond with a number of #
|
# final result packet, the target may also respond with a number of #
|
# intermediate `Ooutput' console output packets. Implementors should note #
|
# intermediate `Ooutput' console output packets. Implementors should note #
|
# that providing access to a stubs's interpreter may have security #
|
# that providing access to a stubs's interpreter may have security #
|
# implications. #
|
# implications. #
|
#-----------------------------------------------------------------------------#
|
#-----------------------------------------------------------------------------#
|
proc rsp_qRcmd {sock cmd} {
|
proc rsp_qRcmd {CpuNr sock cmd} {
|
|
|
global CpuNr
|
|
|
|
regsub {^Rcmd,} $cmd {} cmd
|
regsub {^Rcmd,} $cmd {} cmd
|
set cmd [binary format H* $cmd]; # Convert hex to ascii
|
set cmd [binary format H* $cmd]; # Convert hex to ascii
|
|
|
switch -exact -- $cmd {
|
switch -exact -- $cmd {
|