Skip to content

Commit 568ef71

Browse files
committed
LoadSVD: Load SVD from ZIP file instead of pkg_resources
This changes the logic with `svd_load <VENDOR> <MODEL>` to not search in the pkg_resources of Python module `cmsis_svd.data` but instead search in a ZIP file at `$CMSIS_SVD_ZIPFILE` if that environment variable is defined, otherwise it looks `$XDG_CACHE_HOME/cmdebug/cmsis-svd-data.zip` with `$XDG_CACHE_HOME` falling back to `~/.cache` if not found in the environment. As of 2025-11-09, the `HEAD` of https://github.com/cmsis-svd/cmsis-svd-data is 5.8 GiB in size uncompressed, or 254 MiB when zipped. Personally, I do not perceive any additional latency by having to unzip the chosen SVD file first.
1 parent ce37150 commit 568ef71

File tree

1 file changed

+42
-10
lines changed

1 file changed

+42
-10
lines changed

cmdebug/svd_gdb.py

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,15 @@
1616
"""
1717

1818
import gdb
19-
import re
2019
import math
21-
import sys
20+
import pathlib
21+
import re
2222
import struct
23-
import pkg_resources
23+
import sys
24+
import tempfile
25+
import zipfile
26+
27+
from os import environ
2428

2529
sys.path.append('.')
2630
from cmdebug.svd import SVDFile
@@ -31,6 +35,16 @@
3135
32: "I",
3236
}
3337

38+
if "XDG_CACHE_HOME" in environ and environ["XDG_CACHE_HOME"] != "":
39+
CACHE_DIR = pathlib.Path.joinpath(environ["XDG_CACHE_HOME"], "cmdebug")
40+
else:
41+
CACHE_DIR = pathlib.Path.joinpath(pathlib.Path.home(), ".cache", "cmdebug")
42+
43+
if "CMSIS_SVD_ZIPFILE" in environ and environ["CMSIS_SVD_ZIPFILE"] != "":
44+
CMSIS_SVD_ZIPFILE = pathlib.Path(environ("CMSIS_SVD_ZIPFILE"))
45+
else:
46+
CMSIS_SVD_ZIPFILE = pathlib.Path.joinpath(CACHE_DIR, "cmsis-svd-data.zip")
47+
3448

3549
class LoadSVD(gdb.Command):
3650
""" A command to load an SVD file and to create the command for inspecting
@@ -40,11 +54,16 @@ class LoadSVD(gdb.Command):
4054
def __init__(self):
4155
self.vendors = {}
4256
try:
43-
vendor_names = pkg_resources.resource_listdir("cmsis_svd", "data")
44-
for vendor in vendor_names:
45-
fnames = pkg_resources.resource_listdir("cmsis_svd", "data/{}".format(vendor))
46-
self.vendors[vendor] = [fname for fname in fnames if fname.lower().endswith(".svd")]
47-
except:
57+
with zipfile.ZipFile(CMSIS_SVD_ZIPFILE, mode='r') as svdzip:
58+
for entry in svdzip.namelist():
59+
if entry.lower().endswith(".svd"):
60+
p = pathlib.Path(entry)
61+
vendor = p.parent.name
62+
model = p.name[:-4]
63+
if vendor not in self.vendors:
64+
self.vendors[vendor] = list()
65+
self.vendors[vendor].append(model)
66+
except FileNotFoundError:
4867
pass
4968

5069
if len(self.vendors) > 0:
@@ -75,14 +94,27 @@ def complete(self, text, word):
7594
def invoke(args, from_tty):
7695
args = gdb.string_to_argv(args)
7796
argc = len(args)
97+
f = None
7898
if argc == 1:
7999
gdb.write("Loading SVD file {}...\n".format(args[0]))
80100
f = args[0]
81101
elif argc == 2:
82102
gdb.write("Loading SVD file {}/{}...\n".format(args[0], args[1]))
83-
f = pkg_resources.resource_filename("cmsis_svd", "data/{}/{}".format(args[0], args[1]))
103+
name = args[0].lower() + "/" + args[1].lower() + ".svd"
104+
try:
105+
with zipfile.ZipFile(CMSIS_SVD_ZIPFILE, mode='r') as svdzip:
106+
for entry in svdzip.namelist():
107+
lower = entry.lower()
108+
if lower == name or lower.endswith("/" + name):
109+
f = svdzip.extract(entry, path=tempfile.TemporaryDirectory().name)
110+
break
111+
except FileNotFoundError:
112+
raise gdb.GdbError(f"Could not open \"{CMSIS_SVD_ZIPFILE}\"")
113+
114+
if f is None:
115+
raise gdb.GdbError(f"Could not find SVD for \"{args[0]}/{args[1]}\" in \"{CMSIS_SVD_ZIPFILE}\": No case-insensitive match for \"**/{name}\"")
84116
else:
85-
raise gdb.GdbError("Usage: svd_load <vendor> <device.svd> or svd_load <path/to/filename.svd>\n")
117+
raise gdb.GdbError("Usage: svd_load <vendor> <device> or svd_load <path/to/filename.svd>\n")
86118
try:
87119
SVD(SVDFile(f))
88120
except Exception as e:

0 commit comments

Comments
 (0)