1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
|
# Copyright 2019 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# This file is intended to be used as a .gdbinit for an EC debugging session.
# It defines some useful functions for analyzing the EC state.
#
# Setup Automatic Import:
# ln -s util/gdbinit .gdbinit
#
# Environment Variables:
# BOARD=[nocturne_fp|bloonchipper|...]
# GDBSERVER=[segger|openocd]
# GDBPORT=[gdb-server-port-number]
#
# Warning, this is a working collection that is not guaranteed to function
# properly on all platforms. The ec-tasks functions is a good example of a
# function that works well on most simple platforms, but may have issues on
# platforms with data cache enabled.
#
# Note, this file must maintain space indention to allow easy copy/paste
# while in active debugging. Using tabs interferes with the embedded python
# during copy/paste.
#####################################################################
# Environment Setup and Initialization #
#####################################################################
set verbose on
# Start of python code
# Setup environment and pull in object files for the particular BOARD.
# This requires setting the environment variables mentioned above.
python
import distutils.util
import os
BOARD = os.getenv('BOARD', '')
GDBSERVER = os.getenv('GDBSERVER', 'openocd')
USING_CLION = distutils.util.strtobool(os.getenv('USING_CLION', 'FALSE'))
# BIN_NAME can be changed to be the name of a unit test, such as "sha256"
BIN_NAME = os.getenv('BIN_NAME', 'ec')
BIN_DIR = ''
if BIN_NAME != 'ec':
BIN_DIR = BIN_NAME
if GDBSERVER == "openocd":
DEFAULT_GDB_PORT = '3333'
else:
DEFAULT_GDB_PORT = '2331'
GDBPORT = os.getenv('GDBPORT', DEFAULT_GDB_PORT)
EC_DIR = os.getenv('EC_DIR', os.path.join(os.getenv('HOME'),
'chromiumos/src/platform/ec'))
if not os.path.isdir(EC_DIR):
print('Error - EC_DIR "' + EC_DIR + '" doesn\'t exist. Aborting.')
gdb.execute('quit')
# Monitor commands must be run after connecting to the remote target
# See https://stackoverflow.com/a/39828850
# https://youtrack.jetbrains.com/issue/CPP-7322
# https://sourceware.org/gdb/onlinedocs/gdb/Hooks.html
post_remote_hook='''
define target hookpost-remote
echo \ Flashing EC binary
load {EC_DIR}/build/{BOARD}/{BIN_DIR}/{BIN_NAME}.obj
echo \ Resetting target
monitor reset
echo \ Setting breakpoint on main
b main
end\n
'''.format(BOARD=BOARD, EC_DIR=EC_DIR, BIN_DIR=BIN_DIR, BIN_NAME=BIN_NAME)
gdb.execute('set $BOARD = "%s"'%BOARD)
gdb.execute('set $GDBSERVER = "%s"'%GDBSERVER)
gdb.execute('set $GDBPORT = "%s"'%GDBPORT)
build = os.path.join(EC_DIR, 'build', BOARD)
if BOARD != "":
if not os.path.isdir(build):
print('Error - Build path "' + build + '" doesn\'t exist. Aborting.')
gdb.execute('quit')
# When using gdb from CLion, this kills gdb.
if not USING_CLION:
gdb.execute('file ' + os.path.join(build, 'ec.obj'))
gdb.execute('add-symbol-file ' + os.path.join(build, BIN_DIR, 'RO', BIN_NAME + '.RO.elf'))
gdb.execute('add-symbol-file ' + os.path.join(build, BIN_DIR, 'RW', BIN_NAME + '.RW.elf'))
if GDBSERVER == "openocd":
gdb.execute('set $GDBSERVER_OPENOCD = 1')
gdb.execute('set $GDBSERVER_SEGGER = 0')
elif GDBSERVER == "segger":
gdb.execute('set $GDBSERVER_OPENOCD = 0')
gdb.execute('set $GDBSERVER_SEGGER = 1')
gdb.execute(post_remote_hook)
else:
print('Error - GDBSERVER="' + GDBSERVER + '" is invalid.')
gdb.execute('quit')
# End of python code
end
# OpenOCD specific config
if $GDBSERVER_OPENOCD
# Don't auto choose hw/sw breakpoints from memory-map
set breakpoint auto-hw off
end
# Segger specific config
if $GDBSERVER_SEGGER
# If enabled, disable flash breakpoints.
#monitor flash breakpoints = 0
end
# If enabled, force breakpoints to be inserted at all times.
# They will not be reinserted on reconnects.
#set breakpoint always-inserted on
#####################################################################
# Helper Functions #
#####################################################################
# Usage: reg32 <address> [offset]
# Read a 32 bit register
define reg32
set $a = $arg0
if $argc > 1
set $a += $arg1
end
set $v = *((uint32_t *)$a)
print $v
print /x $v
print /t $v
end
# Usage: ec-connect
# Issue the overly long target connect command using the
# specified gdb server port.
define ec-connect
python
# May want to only use "target remote".
gdb.execute(f'target extended-remote :{GDBPORT}')
end
end
alias connect = ec-connect
# Usage: ec-reset
# Issue the reset sequence for the debugger to halt on boot.
define ec-reset
if $GDBSERVER_OPENOCD
monitor halt
monitor reset halt
else
monitor halt
monitor reset
end
end
alias reset = ec-reset
# Usage: ec-tasks
# Prints out information about current EC task set and tries to determine
# if the task's stack has been overrun.
# This function may not work properly if MCU data cache is enabled.
define ec-tasks
set $taskid_cur = current_task - tasks
set $id = 0
set $taskcount = sizeof(tasks)/sizeof(tasks[0])
printf "Task Ready Name Events Time (s) StkUsed\n"
while $id < $taskcount
set $is_ready = (tasks_ready & (1<<$id)) ? 'R' : ' '
set $unused = (uint32_t)0xdeadd00d
set $stacksize = tasks_init[$id].stack_size
set $stackused = $stacksize
set $s = tasks[$id].stack
while $s < (uint32_t *)tasks[$id].sp && *$s == $unused
set $stackused -= sizeof(uint32_t)
set $s++
end
printf "%4d %-5c %-16s %08x %11.6ld %3d/%3d", $id, $is_ready, task_names[$id], tasks[$id].events, tasks[$id].runtime, $stackused, tasks_init[$id].stack_size
if $stackused == $stacksize
printf "\t [overrun]"
end
if $id == $taskid_cur
printf "\t*"
end
printf "\n"
set $id++
end
if $taskid_cur == scratchpad
printf "Current task is set to scratchpad\n"
end
end
# Usage: ec-stayro
# Adds magic breakpoint that changes the outcome of the RW signature
# validation step that forces the MCU to stay in the RO section.
# This function needs improvements to not be dependent on line numbers.
define ec-stayro
break common/rwsig.c:282
commands
set evt = 1
printf "Continuing as RO\n"
continue
end
end
# Usage: ec-brexception
# Set breakpoints on EC exception handlers.
define ec-brexception
break exception_panic
break bus_fault_handler
break panic_assert_fail
end
|