scripts: Reworked dbglfs.py, adopted Lfs, Config, Gstate, etc
I'm starting to regret these reworks. They've been a big time sink. But at least these should be much easier to extend with the future planned auxiliary trees? New classes: - Bptr - A representation of littlefs's data-only block pointers. Extra fun is the lazily checked Bptr.__bool__ method, which should prevent slowing down scripts that don't actually verify checksums. - Config - The set of littlefs config entries. - Gstate - The set of littlefs gstate. I may have had too much fun with Config and Gstate. Not only do these provide lookup functions for config/gstate, but known config/gstate get lazily parsed classes that can provide easy access to the relevant metadata. These even abuse Python's __subclasses__, so all you need to do to add a new known config/gstate is extend the relevant Config.Config/ Gstate.Gstate class. The __subclasses__ API is a weird but powerful one. - Lfs - The big one, a high-level abstraction of littlefs itself. Contains subclasses for known files: Lfs.Reg, Lfs.Dir, Lfs.Stickynote, etc, which can be accessed by path, did+name, mid, etc. It even supports iterating over orphaned files, though it's expensive (but incredibly valuable for debugging!). Note that all file types can currently have attached bshrubs/btrees. In the existing implementation only reg files should actually end up with bshrubs/btrees, but the whole point of these scripts is to debug things that _shouldn't_ happen. I intentionally gave up on providing depth bounds in Lfs. Too complicated for something so high-level. On noteworthy change is not recursing into directories by default. This hopefully avoids overloading new users and matches the behavior of most other Linux/Unix tools. This adopts -r/--recurse/--file-depth for controlling how far to recurse down directories, and -z/--depth/--tree-depth for controlling how far to recurse down tree structures (mostly files). I like this API. It's consistent with -z/--depth in the other dbg scripts, and -r/--recurse is probably intuitive for most Linux/Unix users. To make this work we did need to change -r/--raw -> -x/--raw. But --raw is already a bit of a weird name for what really means "include a hex dump". Note that -z/--depth/--tree-depth does _not_ imply --files. Right now only files can contain tree structures, but this will change when we get around to adding the auxiliary trees. This also adds the ability to specify a file path to use as the root directory, though we need the leading slash to disambiguate file paths and mroot addresses. --- Also tagrepr has been tweaked to include the global/delta names, toggleable with the optional global_ kwarg. Rattr now has its own lazy parsers for did + name. A more organized codebase would probably have a separate Name type, but it just wasn't worth the hassle. And the abstraction classes have all been tweaked to require the explicit Rbyd.repr() function for a CLI-friendly representation. Relying on __str__ hurt readability and debugging, especially since Python prefers __str__ over __repr__ when printing things.
This commit is contained in:
+42
-13
@@ -62,12 +62,17 @@ def fromleb128(data):
|
||||
return word, i+1
|
||||
return word, len(data)
|
||||
|
||||
def tagrepr(tag, weight=None, size=None, off=None):
|
||||
# human readable tag repr
|
||||
def tagrepr(tag, weight=None, size=None, *,
|
||||
global_=False,
|
||||
toff=None):
|
||||
# null tags
|
||||
if (tag & 0x6fff) == TAG_NULL:
|
||||
return '%snull%s%s' % (
|
||||
'shrub' if tag & TAG_SHRUB else '',
|
||||
' w%d' % weight if weight else '',
|
||||
' %d' % size if size else '')
|
||||
# config tags
|
||||
elif (tag & 0x6f00) == TAG_CONFIG:
|
||||
return '%s%s%s%s' % (
|
||||
'shrub' if tag & TAG_SHRUB else '',
|
||||
@@ -82,13 +87,23 @@ def tagrepr(tag, weight=None, size=None, off=None):
|
||||
else 'config 0x%02x' % (tag & 0xff),
|
||||
' w%d' % weight if weight else '',
|
||||
' %s' % size if size is not None else '')
|
||||
# global-state delta tags
|
||||
elif (tag & 0x6f00) == TAG_GDELTA:
|
||||
return '%s%s%s%s' % (
|
||||
'shrub' if tag & TAG_SHRUB else '',
|
||||
'grmdelta' if (tag & 0xfff) == TAG_GRMDELTA
|
||||
else 'gdelta 0x%02x' % (tag & 0xff),
|
||||
' w%d' % weight if weight else '',
|
||||
' %s' % size if size is not None else '')
|
||||
if global_:
|
||||
return '%s%s%s%s' % (
|
||||
'shrub' if tag & TAG_SHRUB else '',
|
||||
'grm' if (tag & 0xfff) == TAG_GRMDELTA
|
||||
else 'gstate 0x%02x' % (tag & 0xff),
|
||||
' w%d' % weight if weight else '',
|
||||
' %s' % size if size is not None else '')
|
||||
else:
|
||||
return '%s%s%s%s' % (
|
||||
'shrub' if tag & TAG_SHRUB else '',
|
||||
'grmdelta' if (tag & 0xfff) == TAG_GRMDELTA
|
||||
else 'gdelta 0x%02x' % (tag & 0xff),
|
||||
' w%d' % weight if weight else '',
|
||||
' %s' % size if size is not None else '')
|
||||
# name tags, includes file types
|
||||
elif (tag & 0x6f00) == TAG_NAME:
|
||||
return '%s%s%s%s' % (
|
||||
'shrub' if tag & TAG_SHRUB else '',
|
||||
@@ -100,6 +115,7 @@ def tagrepr(tag, weight=None, size=None, off=None):
|
||||
else 'name 0x%02x' % (tag & 0xff),
|
||||
' w%d' % weight if weight else '',
|
||||
' %s' % size if size is not None else '')
|
||||
# structure tags
|
||||
elif (tag & 0x6f00) == TAG_STRUCT:
|
||||
return '%s%s%s%s' % (
|
||||
'shrub' if tag & TAG_SHRUB else '',
|
||||
@@ -115,6 +131,7 @@ def tagrepr(tag, weight=None, size=None, off=None):
|
||||
else 'struct 0x%02x' % (tag & 0xff),
|
||||
' w%d' % weight if weight else '',
|
||||
' %s' % size if size is not None else '')
|
||||
# custom attributes
|
||||
elif (tag & 0x6e00) == TAG_ATTR:
|
||||
return '%s%sattr 0x%02x%s%s' % (
|
||||
'shrub' if tag & TAG_SHRUB else '',
|
||||
@@ -122,37 +139,49 @@ def tagrepr(tag, weight=None, size=None, off=None):
|
||||
((tag & 0x100) >> 1) ^ (tag & 0xff),
|
||||
' w%d' % weight if weight else '',
|
||||
' %s' % size if size is not None else '')
|
||||
# alt pointers
|
||||
elif tag & TAG_ALT:
|
||||
return 'alt%s%s 0x%03x%s%s' % (
|
||||
'r' if tag & TAG_R else 'b',
|
||||
'gt' if tag & TAG_GT else 'le',
|
||||
tag & 0x0fff,
|
||||
' w%d' % weight if weight is not None else '',
|
||||
' 0x%x' % (0xffffffff & (off-size))
|
||||
if size and off is not None
|
||||
' 0x%x' % (0xffffffff & (toff-size))
|
||||
if size and toff is not None
|
||||
else ' -%d' % size if size
|
||||
else '')
|
||||
# checksum tags
|
||||
elif (tag & 0x7f00) == TAG_CKSUM:
|
||||
return 'cksum%s%s%s%s' % (
|
||||
'p' if not tag & 0xfe and tag & TAG_P else '',
|
||||
' 0x%02x' % (tag & 0xff) if tag & 0xfe else '',
|
||||
' w%d' % weight if weight else '',
|
||||
' %s' % size if size is not None else '')
|
||||
# note tags
|
||||
elif (tag & 0x7f00) == TAG_NOTE:
|
||||
return 'note%s%s%s' % (
|
||||
' 0x%02x' % (tag & 0xff) if tag & 0xff else '',
|
||||
' w%d' % weight if weight else '',
|
||||
' %s' % size if size is not None else '')
|
||||
# erased-state checksum tags
|
||||
elif (tag & 0x7f00) == TAG_ECKSUM:
|
||||
return 'ecksum%s%s%s' % (
|
||||
' 0x%02x' % (tag & 0xff) if tag & 0xff else '',
|
||||
' w%d' % weight if weight else '',
|
||||
' %s' % size if size is not None else '')
|
||||
# global-checksum delta tags
|
||||
elif (tag & 0x7f00) == TAG_GCKSUMDELTA:
|
||||
return 'gcksumdelta%s%s%s' % (
|
||||
' 0x%02x' % (tag & 0xff) if tag & 0xff else '',
|
||||
' w%d' % weight if weight else '',
|
||||
' %s' % size if size is not None else '')
|
||||
if global_:
|
||||
return 'gcksum%s%s%s' % (
|
||||
' 0x%02x' % (tag & 0xff) if tag & 0xff else '',
|
||||
' w%d' % weight if weight else '',
|
||||
' %s' % size if size is not None else '')
|
||||
else:
|
||||
return 'gcksumdelta%s%s%s' % (
|
||||
' 0x%02x' % (tag & 0xff) if tag & 0xff else '',
|
||||
' w%d' % weight if weight else '',
|
||||
' %s' % size if size is not None else '')
|
||||
# unknown tags
|
||||
else:
|
||||
return '0x%04x%s%s' % (
|
||||
tag,
|
||||
|
||||
Reference in New Issue
Block a user