svd_gdb.py 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518
  1. #!/usr/bin/env python
  2. """
  3. This file is part of PyCortexMDebug
  4. PyCortexMDebug is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. PyCortexMDebug is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with PyCortexMDebug. If not, see <http://www.gnu.org/licenses/>.
  14. """
  15. import gdb
  16. import re
  17. import math
  18. import sys
  19. import struct
  20. import pkg_resources
  21. import fnmatch
  22. from .svd import SVDFile
  23. BITS_TO_UNPACK_FORMAT = {
  24. 8: "B",
  25. 16: "H",
  26. 32: "I",
  27. }
  28. class LoadSVD(gdb.Command):
  29. """A command to load an SVD file and to create the command for inspecting
  30. that object
  31. """
  32. def __init__(self):
  33. self.vendors = {}
  34. try:
  35. vendor_names = pkg_resources.resource_listdir("cmsis_svd", "data")
  36. for vendor in vendor_names:
  37. fnames = pkg_resources.resource_listdir(
  38. "cmsis_svd", "data/{}".format(vendor)
  39. )
  40. self.vendors[vendor] = [
  41. fname for fname in fnames if fname.lower().endswith(".svd")
  42. ]
  43. except:
  44. pass
  45. if len(self.vendors) > 0:
  46. gdb.Command.__init__(self, "svd_load", gdb.COMMAND_USER)
  47. else:
  48. gdb.Command.__init__(
  49. self, "svd_load", gdb.COMMAND_DATA, gdb.COMPLETE_FILENAME
  50. )
  51. def complete(self, text, word):
  52. args = gdb.string_to_argv(text)
  53. num_args = len(args)
  54. if text.endswith(" "):
  55. num_args += 1
  56. if not text:
  57. num_args = 1
  58. # "svd_load <tab>" or "svd_load ST<tab>"
  59. if num_args == 1:
  60. prefix = word.lower()
  61. return [
  62. vendor for vendor in self.vendors if vendor.lower().startswith(prefix)
  63. ]
  64. # "svd_load STMicro<tab>" or "svd_load STMicro STM32F1<tab>"
  65. elif num_args == 2 and args[0] in self.vendors:
  66. prefix = word.lower()
  67. filenames = self.vendors[args[0]]
  68. return [fname for fname in filenames if fname.lower().startswith(prefix)]
  69. return gdb.COMPLETE_NONE
  70. @staticmethod
  71. def invoke(args, from_tty):
  72. args = gdb.string_to_argv(args)
  73. argc = len(args)
  74. if argc == 1:
  75. gdb.write("Loading SVD file {}...\n".format(args[0]))
  76. f = args[0]
  77. elif argc == 2:
  78. gdb.write("Loading SVD file {}/{}...\n".format(args[0], args[1]))
  79. f = pkg_resources.resource_filename(
  80. "cmsis_svd", "data/{}/{}".format(args[0], args[1])
  81. )
  82. else:
  83. raise gdb.GdbError(
  84. "Usage: svd_load <vendor> <device.svd> or svd_load <path/to/filename.svd>\n"
  85. )
  86. try:
  87. SVD(SVDFile(f))
  88. except Exception as e:
  89. raise gdb.GdbError("Could not load SVD file {} : {}...\n".format(f, e))
  90. class SVD(gdb.Command):
  91. """The CMSIS SVD (System View Description) inspector command
  92. This allows easy access to all peripheral registers supported by the system
  93. in the GDB debug environment
  94. """
  95. def __init__(self, svd_file):
  96. gdb.Command.__init__(self, "svd", gdb.COMMAND_DATA)
  97. self.svd_file = svd_file
  98. def _print_registers(self, container_name, form, registers):
  99. if len(registers) == 0:
  100. return
  101. try:
  102. regs_iter = registers.itervalues()
  103. except AttributeError:
  104. regs_iter = registers.values()
  105. gdb.write("Registers in %s:\n" % container_name)
  106. reg_list = []
  107. for r in regs_iter:
  108. if r.readable():
  109. try:
  110. data = self.read(r.address(), r.size)
  111. data = self.format(data, form, r.size)
  112. if form == "a":
  113. data += (
  114. " <"
  115. + re.sub(
  116. r"\s+",
  117. " ",
  118. gdb.execute(
  119. "info symbol {}".format(data), True, True
  120. ).strip(),
  121. )
  122. + ">"
  123. )
  124. except gdb.MemoryError:
  125. data = "(error reading)"
  126. else:
  127. data = "(not readable)"
  128. desc = re.sub(r"\s+", " ", r.description)
  129. reg_list.append((r.name, data, desc))
  130. column1_width = max(len(reg[0]) for reg in reg_list) + 2 # padding
  131. column2_width = max(len(reg[1]) for reg in reg_list)
  132. for reg in reg_list:
  133. gdb.write(
  134. "\t{}:{}{}".format(
  135. reg[0],
  136. "".ljust(column1_width - len(reg[0])),
  137. reg[1].rjust(column2_width),
  138. )
  139. )
  140. if reg[2] != reg[0]:
  141. gdb.write(" {}".format(reg[2]))
  142. gdb.write("\n")
  143. def _print_register_fields(self, container_name, form, register):
  144. gdb.write("Fields in {}:\n".format(container_name))
  145. fields = register.fields
  146. if not register.readable():
  147. data = 0
  148. else:
  149. data = self.read(register.address(), register.size)
  150. field_list = []
  151. try:
  152. fields_iter = fields.itervalues()
  153. except AttributeError:
  154. fields_iter = fields.values()
  155. for f in fields_iter:
  156. desc = re.sub(r"\s+", " ", f.description)
  157. if register.readable():
  158. val = data >> f.offset
  159. val &= (1 << f.width) - 1
  160. if f.enum:
  161. if val in f.enum:
  162. desc = f.enum[val][1] + " - " + desc
  163. val = f.enum[val][0]
  164. else:
  165. val = "Invalid enum value: " + self.format(val, form, f.width)
  166. else:
  167. val = self.format(val, form, f.width)
  168. else:
  169. val = "(not readable)"
  170. field_list.append((f.name, val, desc))
  171. column1_width = max(len(field[0]) for field in field_list) + 2 # padding
  172. column2_width = max(len(field[1]) for field in field_list) # padding
  173. for field in field_list:
  174. gdb.write(
  175. "\t{}:{}{}".format(
  176. field[0],
  177. "".ljust(column1_width - len(field[0])),
  178. field[1].rjust(column2_width),
  179. )
  180. )
  181. if field[2] != field[0]:
  182. gdb.write(" {}".format(field[2]))
  183. gdb.write("\n")
  184. def invoke(self, args, from_tty):
  185. s = str(args).split(" ")
  186. form = ""
  187. if s[0] and s[0][0] == "/":
  188. if len(s[0]) == 1:
  189. gdb.write("Incorrect format\n")
  190. return
  191. else:
  192. form = s[0][1:]
  193. if len(s) == 1:
  194. return
  195. s = s[1:]
  196. if s[0].lower() == "help":
  197. gdb.write("Usage:\n")
  198. gdb.write("=========\n")
  199. gdb.write("svd:\n")
  200. gdb.write("\tList available peripherals\n")
  201. gdb.write("svd [peripheral_name]:\n")
  202. gdb.write("\tDisplay all registers pertaining to that peripheral\n")
  203. gdb.write("svd [peripheral_name] [register_name]:\n")
  204. gdb.write("\tDisplay the fields in that register\n")
  205. gdb.write("svd/[format_character] ...\n")
  206. gdb.write("\tFormat values using that character\n")
  207. gdb.write("\td(default):decimal, x: hex, o: octal, b: binary\n")
  208. gdb.write("\n")
  209. gdb.write(
  210. "Both prefix matching and case-insensitive matching is supported for peripherals, registers, clusters and fields.\n"
  211. )
  212. return
  213. if not len(s[0]):
  214. gdb.write("Available Peripherals:\n")
  215. try:
  216. peripherals = self.svd_file.peripherals.itervalues()
  217. except AttributeError:
  218. peripherals = self.svd_file.peripherals.values()
  219. column_width = max(len(p.name) for p in peripherals) + 2 # padding
  220. try:
  221. peripherals = self.svd_file.peripherals.itervalues()
  222. except AttributeError:
  223. peripherals = self.svd_file.peripherals.values()
  224. for p in peripherals:
  225. desc = re.sub(r"\s+", " ", p.description)
  226. gdb.write(
  227. "\t{}:{}{}\n".format(
  228. p.name, "".ljust(column_width - len(p.name)), desc
  229. )
  230. )
  231. return
  232. def warn_if_ambiguous(smart_dict, key):
  233. if smart_dict.is_ambiguous(key):
  234. gdb.write(
  235. "Warning: {} could prefix match any of: {}\n".format(
  236. key, ", ".join(smart_dict.prefix_match_iter(key))
  237. )
  238. )
  239. registers = None
  240. if len(s) >= 1:
  241. peripheral_name = s[0]
  242. if peripheral_name not in self.svd_file.peripherals:
  243. gdb.write("Peripheral {} does not exist!\n".format(s[0]))
  244. return
  245. warn_if_ambiguous(self.svd_file.peripherals, peripheral_name)
  246. peripheral = self.svd_file.peripherals[peripheral_name]
  247. if len(s) == 1:
  248. self._print_registers(peripheral.name, form, peripheral.registers)
  249. if len(peripheral.clusters) > 0:
  250. try:
  251. clusters_iter = peripheral.clusters.itervalues()
  252. except AttributeError:
  253. clusters_iter = peripheral.clusters.values()
  254. gdb.write("Clusters in %s:\n" % peripheral.name)
  255. reg_list = []
  256. for r in clusters_iter:
  257. desc = re.sub(r"\s+", " ", r.description)
  258. reg_list.append((r.name, "", desc))
  259. column1_width = max(len(reg[0]) for reg in reg_list) + 2 # padding
  260. column2_width = max(len(reg[1]) for reg in reg_list)
  261. for reg in reg_list:
  262. gdb.write(
  263. "\t{}:{}{}".format(
  264. reg[0],
  265. "".ljust(column1_width - len(reg[0])),
  266. reg[1].rjust(column2_width),
  267. )
  268. )
  269. if reg[2] != reg[0]:
  270. gdb.write(" {}".format(reg[2]))
  271. gdb.write("\n")
  272. return
  273. cluster = None
  274. if len(s) == 2:
  275. if s[1] in peripheral.clusters:
  276. warn_if_ambiguous(peripheral.clusters, s[1])
  277. cluster = peripheral.clusters[s[1]]
  278. container = peripheral.name + " > " + cluster.name
  279. self._print_registers(container, form, cluster.registers)
  280. elif s[1] in peripheral.registers:
  281. warn_if_ambiguous(peripheral.registers, s[1])
  282. register = peripheral.registers[s[1]]
  283. container = peripheral.name + " > " + register.name
  284. self._print_register_fields(container, form, register)
  285. else:
  286. found = False
  287. for key in fnmatch.filter(peripheral.registers.keys(), s[1]):
  288. register = peripheral.registers[key]
  289. container = peripheral.name + " > " + register.name
  290. self._print_register_fields(container, form, register)
  291. found = True
  292. if not found:
  293. gdb.write(
  294. "Register/cluster {} in peripheral {} does not exist!\n".format(
  295. s[1], peripheral.name
  296. )
  297. )
  298. return
  299. if len(s) == 3:
  300. if s[1] not in peripheral.clusters:
  301. gdb.write(
  302. "Cluster {} in peripheral {} does not exist!\n".format(
  303. s[1], peripheral.name
  304. )
  305. )
  306. return
  307. warn_if_ambiguous(peripheral.clusters, s[1])
  308. cluster = peripheral.clusters[s[1]]
  309. if s[2] not in cluster.registers:
  310. gdb.write(
  311. "Register {} in cluster {} in peripheral {} does not exist!\n".format(
  312. s[2], cluster.name, peripheral.name
  313. )
  314. )
  315. return
  316. warn_if_ambiguous(cluster.registers, s[2])
  317. register = cluster.registers[s[2]]
  318. container = " > ".join([peripheral.name, cluster.name, register.name])
  319. self._print_register_fields(container, form, register)
  320. return
  321. if len(s) == 4:
  322. if s[1] not in peripheral.registers:
  323. gdb.write(
  324. "Register {} in peripheral {} does not exist!\n".format(
  325. s[1], peripheral.name
  326. )
  327. )
  328. return
  329. warn_if_ambiguous(peripheral.registers, s[1])
  330. reg = peripheral.registers[s[1]]
  331. if s[2] not in reg.fields:
  332. gdb.write(
  333. "Field {} in register {} in peripheral {} does not exist!\n".format(
  334. s[2], reg.name, peripheral.name
  335. )
  336. )
  337. return
  338. warn_if_ambiguous(reg.fields, s[2])
  339. field = reg.fields[s[2]]
  340. if not field.writable() or not reg.writable():
  341. gdb.write(
  342. "Field {} in register {} in peripheral {} is read-only!\n".format(
  343. field.name, reg.name, peripheral.name
  344. )
  345. )
  346. return
  347. try:
  348. val = int(s[3], 0)
  349. except ValueError:
  350. gdb.write(
  351. "{} is not a valid number! You can prefix numbers with 0x for hex, 0b for binary, or any python "
  352. "int literal\n".format(s[3])
  353. )
  354. return
  355. if val >= 1 << field.width or val < 0:
  356. gdb.write(
  357. "{} not a valid number for a field with width {}!\n".format(
  358. val, field.width
  359. )
  360. )
  361. return
  362. if not reg.readable():
  363. data = 0
  364. else:
  365. data = self.read(reg.address(), reg.size)
  366. data &= ~(((1 << field.width) - 1) << field.offset)
  367. data |= val << field.offset
  368. self.write(reg.address(), data, reg.size)
  369. return
  370. gdb.write("Unknown input\n")
  371. def complete(self, text, word):
  372. """Perform tab-completion for the command"""
  373. text = str(text)
  374. s = text.split(" ")
  375. # Deal with the possibility of a '/' parameter
  376. if s[0] and s[0][0] == "/":
  377. if len(s) > 1:
  378. s = s[1:]
  379. else:
  380. return [] # completion after e.g. "svd/x" but before trailing space
  381. if len(s) == 1:
  382. return list(self.svd_file.peripherals.prefix_match_iter(s[0]))
  383. if len(s) == 2:
  384. reg = s[1].upper()
  385. if len(reg) and reg[0] == "&":
  386. reg = reg[1:]
  387. if s[0] not in self.svd_file.peripherals:
  388. return []
  389. per = self.svd_file.peripherals[s[0]]
  390. return list(per.registers.prefix_match_iter(s[1]))
  391. return []
  392. @staticmethod
  393. def read(address, bits=32):
  394. """Read from memory and return an integer"""
  395. value = gdb.selected_inferior().read_memory(address, bits / 8)
  396. unpack_format = "I"
  397. if bits in BITS_TO_UNPACK_FORMAT:
  398. unpack_format = BITS_TO_UNPACK_FORMAT[bits]
  399. # gdb.write("{:x} {}\n".format(address, binascii.hexlify(value)))
  400. return struct.unpack_from("<" + unpack_format, value)[0]
  401. @staticmethod
  402. def write(address, data, bits=32):
  403. """Write data to memory"""
  404. gdb.selected_inferior().write_memory(address, bytes(data), bits / 8)
  405. @staticmethod
  406. def format(value, form, length=32):
  407. """Format a number based on a format character and length"""
  408. # get current gdb radix setting
  409. radix = int(
  410. re.search(r"\d+", gdb.execute("show output-radix", True, True)).group(0)
  411. )
  412. # override it if asked to
  413. if form == "x" or form == "a":
  414. radix = 16
  415. elif form == "o":
  416. radix = 8
  417. elif form == "b" or form == "t":
  418. radix = 2
  419. # format the output
  420. if radix == 16:
  421. # For addresses, probably best in hex too
  422. l = int(math.ceil(length / 4.0))
  423. return "0x" + "{:X}".format(value).zfill(l)
  424. if radix == 8:
  425. l = int(math.ceil(length / 3.0))
  426. return "0" + "{:o}".format(value).zfill(l)
  427. if radix == 2:
  428. return "0b" + "{:b}".format(value).zfill(length)
  429. # Default: Just return in decimal
  430. return str(value)
  431. def peripheral_list(self):
  432. try:
  433. keys = self.svd_file.peripherals.iterkeys()
  434. except AttributeError:
  435. keys = self.svd_file.peripherals.keys()
  436. return list(keys)
  437. def register_list(self, peripheral):
  438. try:
  439. try:
  440. keys = self.svd_file.peripherals[peripheral].registers.iterkeys()
  441. except AttributeError:
  442. keys = self.svd_file.peripherals[peripheral].registers.keys()
  443. return list(keys)
  444. except:
  445. gdb.write("Peripheral {} doesn't exist\n".format(peripheral))
  446. return []
  447. def field_list(self, peripheral, register):
  448. try:
  449. periph = self.svd_file.peripherals[peripheral]
  450. reg = periph.registers[register]
  451. try:
  452. regs = reg.fields.iterkeys()
  453. except AttributeError:
  454. regs = reg.fields.keys()
  455. return list(regs)
  456. except:
  457. gdb.write("Register {} doesn't exist on {}\n".format(register, peripheral))
  458. return []