Skip to content

Instantly share code, notes, and snippets.

@devanlai
Created October 17, 2016 08:21
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save devanlai/f9636f68c57fde2c5da912231f03c47e to your computer and use it in GitHub Desktop.
Save devanlai/f9636f68c57fde2c5da912231f03c47e to your computer and use it in GitHub Desktop.
gdb script to emulate the trace command for logging memory reads/writes on Cortex-M targets
import re
from collections import OrderedDict
register_names = "pc sp lr r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 xPSR".split(" ")
addr_pattern = re.compile(r";\s+\((0x[0-9a-fA-F]{1,8})\)")
def get_registers(names=register_names):
uint32_t = gdb.lookup_type("unsigned long")
d = OrderedDict()
for name in names:
value = gdb.parse_and_eval("$"+name).cast(uint32_t)
d[name] = int(value)
return d
def step_and_record_while(log, predicate):
prev_registers = {}
while True:
registers = get_registers()
changeset = [(reg,val) for (reg,val) in registers.items() if val != prev_registers.get(reg)]
prev_registers = registers
inst = gdb.execute("x /i $pc", to_string=True)
if inst.startswith("=> "):
inst = inst[3:]
log.write(inst.strip())
if ";" in inst:
m = addr_pattern.search(inst)
if m is not None:
word = gdb.parse_and_eval("*(unsigned long*)({})".format(m.group(1)))
log.write(" @#MEM=" + ("0x{:08X}".format(int(word))))
if changeset:
log.write(" @#")
log.write(",".join("{:s}=0x{:08X}".format(reg,val) for (reg,val) in changeset) + "\n")
if not predicate(registers):
break
gdb.execute("si", to_string=True)
def step_through_bootloader(log):
def not_in_user_code(registers):
return (registers["pc"] <= 0x08004000)
step_and_record_while(log, not_in_user_code)
def step_until_before_loop(log):
def before_loop(registers):
if registers["pc"] == 0x8001292:
return False
return True
step_and_record_while(log, before_loop)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment