218 lines
6.6 KiB
Plaintext
218 lines
6.6 KiB
Plaintext
# 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('target extended-remote :%d'%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 |