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