svd_gdb.py 17 KB

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