Added dbgtag.py for easy tag decoding on the command-line
Example: $ ./scripts/dbgtag.py 0x3001 cksum 0x01 dbgtag.py inherits most of crc32c.py's decoding options. The most useful probably being -x/--hex: $ ./scripts/dbgtag.py -x e1 00 01 8a 09 altbgt 0x100 w1 -1162 dbgtag.py also supports reading from a block device if either -b/--block-size or --off are provided. This is mainly for consistency with the other dbg*.py scripts: $ ./scripts/dbgtag.py disk -b4096 0x2.1e4 bookmark w1 1 This should help when debugging and finding a raw tag/alt in some register. Manually decoding is just an unnecessary road bump when this happens.
This commit is contained in:
+37
-33
@@ -153,14 +153,14 @@ def xxd(data, width=16):
|
||||
b if b >= ' ' and b <= '~' else '.'
|
||||
for b in map(chr, data[i:i+width])))
|
||||
|
||||
def tagrepr(tag, w, size, off=None):
|
||||
if (tag & 0xefff) == TAG_NULL:
|
||||
def tagrepr(tag, w=None, size=None, off=None):
|
||||
if (tag & 0x6fff) == TAG_NULL:
|
||||
return '%snull%s%s' % (
|
||||
'shrub' if tag & TAG_SHRUB else '',
|
||||
' w%d' % w if w else '',
|
||||
' %d' % size if size else '')
|
||||
elif (tag & 0xef00) == TAG_CONFIG:
|
||||
return '%s%s%s %d' % (
|
||||
elif (tag & 0x6f00) == TAG_CONFIG:
|
||||
return '%s%s%s%s' % (
|
||||
'shrub' if tag & TAG_SHRUB else '',
|
||||
'magic' if (tag & 0xfff) == TAG_MAGIC
|
||||
else 'version' if (tag & 0xfff) == TAG_VERSION
|
||||
@@ -172,16 +172,16 @@ def tagrepr(tag, w, size, off=None):
|
||||
else 'namelimit' if (tag & 0xfff) == TAG_NAMELIMIT
|
||||
else 'config 0x%02x' % (tag & 0xff),
|
||||
' w%d' % w if w else '',
|
||||
size)
|
||||
elif (tag & 0xef00) == TAG_GDELTA:
|
||||
return '%s%s%s %d' % (
|
||||
' %s' % size if size is not None else '')
|
||||
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' % w if w else '',
|
||||
size)
|
||||
elif (tag & 0xef00) == TAG_NAME:
|
||||
return '%s%s%s %d' % (
|
||||
' %s' % size if size is not None else '')
|
||||
elif (tag & 0x6f00) == TAG_NAME:
|
||||
return '%s%s%s%s' % (
|
||||
'shrub' if tag & TAG_SHRUB else '',
|
||||
'name' if (tag & 0xfff) == TAG_NAME
|
||||
else 'reg' if (tag & 0xfff) == TAG_REG
|
||||
@@ -190,9 +190,9 @@ def tagrepr(tag, w, size, off=None):
|
||||
else 'bookmark' if (tag & 0xfff) == TAG_BOOKMARK
|
||||
else 'name 0x%02x' % (tag & 0xff),
|
||||
' w%d' % w if w else '',
|
||||
size)
|
||||
elif (tag & 0xef00) == TAG_STRUCT:
|
||||
return '%s%s%s %d' % (
|
||||
' %s' % size if size is not None else '')
|
||||
elif (tag & 0x6f00) == TAG_STRUCT:
|
||||
return '%s%s%s%s' % (
|
||||
'shrub' if tag & TAG_SHRUB else '',
|
||||
'data' if (tag & 0xfff) == TAG_DATA
|
||||
else 'block' if (tag & 0xfff) == TAG_BLOCK
|
||||
@@ -206,43 +206,47 @@ def tagrepr(tag, w, size, off=None):
|
||||
else 'mtree' if (tag & 0xfff) == TAG_MTREE
|
||||
else 'struct 0x%02x' % (tag & 0xff),
|
||||
' w%d' % w if w else '',
|
||||
size)
|
||||
elif (tag & 0xef00) == TAG_UATTR:
|
||||
return '%suattr 0x%02x%s %d' % (
|
||||
' %s' % size if size is not None else '')
|
||||
elif (tag & 0x6e00) == TAG_UATTR:
|
||||
return '%suattr 0x%02x%s%s' % (
|
||||
'shrub' if tag & TAG_SHRUB else '',
|
||||
((tag & 0x100) >> 1) | (tag & 0xff),
|
||||
' w%d' % w if w else '',
|
||||
size)
|
||||
elif (tag & 0xef00) == TAG_SATTR:
|
||||
return '%ssattr 0x%02x%s %d' % (
|
||||
' %s' % size if size is not None else '')
|
||||
elif (tag & 0x6e00) == TAG_SATTR:
|
||||
return '%ssattr 0x%02x%s%s' % (
|
||||
'shrub' if tag & TAG_SHRUB else '',
|
||||
((tag & 0x100) >> 1) | (tag & 0xff),
|
||||
' w%d' % w if w else '',
|
||||
size)
|
||||
elif (tag & 0xff00) == TAG_CKSUM:
|
||||
return 'cksum 0x%02x%s %d' % (
|
||||
' %s' % size if size is not None else '')
|
||||
elif (tag & 0x7f00) == TAG_CKSUM:
|
||||
return 'cksum 0x%02x%s%s' % (
|
||||
tag & 0xff,
|
||||
' w%d' % w if w > 0 else '',
|
||||
size)
|
||||
elif (tag & 0xff00) == TAG_ECKSUM:
|
||||
return 'ecksum%s%s %d' % (
|
||||
' w%d' % w if w else '',
|
||||
' %s' % size if size is not None else '')
|
||||
elif (tag & 0x7f00) == TAG_ECKSUM:
|
||||
return 'ecksum%s%s%s' % (
|
||||
' 0x%02x' % (tag & 0xff) if tag & 0xff else '',
|
||||
' w%d' % w if w > 0 else '',
|
||||
size)
|
||||
' w%d' % w if w else '',
|
||||
' %s' % size if size is not None else '')
|
||||
elif tag & TAG_ALT:
|
||||
return 'alt%s%s%s w%d %s' % (
|
||||
return 'alt%s%s%s%s%s' % (
|
||||
'r' if tag & TAG_R else 'b',
|
||||
'a' if tag & 0x0fff == 0 and tag & TAG_GT
|
||||
else 'n' if tag & 0x0fff == 0
|
||||
else 'gt' if tag & TAG_GT
|
||||
else 'le',
|
||||
' 0x%x' % (tag & 0x0fff) if tag & 0x0fff != 0 else '',
|
||||
w,
|
||||
' w%d' % w if w is not None else '',
|
||||
' 0x%x' % (0xffffffff & (off-size))
|
||||
if off is not None
|
||||
else '-%d' % off)
|
||||
if size is not None and off is not None
|
||||
else ' -%d' % size if size is not None
|
||||
else '')
|
||||
else:
|
||||
return '0x%04x w%d %d' % (tag, w, size)
|
||||
return '0x%04x%s%s' % (
|
||||
tag,
|
||||
' w%d' % w if w is not None else '',
|
||||
' %d' % size if size is not None else '')
|
||||
|
||||
|
||||
# this type is used for tree representations
|
||||
|
||||
+37
-33
@@ -184,14 +184,14 @@ def xxd(data, width=16):
|
||||
b if b >= ' ' and b <= '~' else '.'
|
||||
for b in map(chr, data[i:i+width])))
|
||||
|
||||
def tagrepr(tag, w, size, off=None):
|
||||
if (tag & 0xefff) == TAG_NULL:
|
||||
def tagrepr(tag, w=None, size=None, off=None):
|
||||
if (tag & 0x6fff) == TAG_NULL:
|
||||
return '%snull%s%s' % (
|
||||
'shrub' if tag & TAG_SHRUB else '',
|
||||
' w%d' % w if w else '',
|
||||
' %d' % size if size else '')
|
||||
elif (tag & 0xef00) == TAG_CONFIG:
|
||||
return '%s%s%s %d' % (
|
||||
elif (tag & 0x6f00) == TAG_CONFIG:
|
||||
return '%s%s%s%s' % (
|
||||
'shrub' if tag & TAG_SHRUB else '',
|
||||
'magic' if (tag & 0xfff) == TAG_MAGIC
|
||||
else 'version' if (tag & 0xfff) == TAG_VERSION
|
||||
@@ -203,16 +203,16 @@ def tagrepr(tag, w, size, off=None):
|
||||
else 'namelimit' if (tag & 0xfff) == TAG_NAMELIMIT
|
||||
else 'config 0x%02x' % (tag & 0xff),
|
||||
' w%d' % w if w else '',
|
||||
size)
|
||||
elif (tag & 0xef00) == TAG_GDELTA:
|
||||
return '%s%s%s %d' % (
|
||||
' %s' % size if size is not None else '')
|
||||
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' % w if w else '',
|
||||
size)
|
||||
elif (tag & 0xef00) == TAG_NAME:
|
||||
return '%s%s%s %d' % (
|
||||
' %s' % size if size is not None else '')
|
||||
elif (tag & 0x6f00) == TAG_NAME:
|
||||
return '%s%s%s%s' % (
|
||||
'shrub' if tag & TAG_SHRUB else '',
|
||||
'name' if (tag & 0xfff) == TAG_NAME
|
||||
else 'reg' if (tag & 0xfff) == TAG_REG
|
||||
@@ -221,9 +221,9 @@ def tagrepr(tag, w, size, off=None):
|
||||
else 'bookmark' if (tag & 0xfff) == TAG_BOOKMARK
|
||||
else 'name 0x%02x' % (tag & 0xff),
|
||||
' w%d' % w if w else '',
|
||||
size)
|
||||
elif (tag & 0xef00) == TAG_STRUCT:
|
||||
return '%s%s%s %d' % (
|
||||
' %s' % size if size is not None else '')
|
||||
elif (tag & 0x6f00) == TAG_STRUCT:
|
||||
return '%s%s%s%s' % (
|
||||
'shrub' if tag & TAG_SHRUB else '',
|
||||
'data' if (tag & 0xfff) == TAG_DATA
|
||||
else 'block' if (tag & 0xfff) == TAG_BLOCK
|
||||
@@ -237,43 +237,47 @@ def tagrepr(tag, w, size, off=None):
|
||||
else 'mtree' if (tag & 0xfff) == TAG_MTREE
|
||||
else 'struct 0x%02x' % (tag & 0xff),
|
||||
' w%d' % w if w else '',
|
||||
size)
|
||||
elif (tag & 0xef00) == TAG_UATTR:
|
||||
return '%suattr 0x%02x%s %d' % (
|
||||
' %s' % size if size is not None else '')
|
||||
elif (tag & 0x6e00) == TAG_UATTR:
|
||||
return '%suattr 0x%02x%s%s' % (
|
||||
'shrub' if tag & TAG_SHRUB else '',
|
||||
((tag & 0x100) >> 1) | (tag & 0xff),
|
||||
' w%d' % w if w else '',
|
||||
size)
|
||||
elif (tag & 0xef00) == TAG_SATTR:
|
||||
return '%ssattr 0x%02x%s %d' % (
|
||||
' %s' % size if size is not None else '')
|
||||
elif (tag & 0x6e00) == TAG_SATTR:
|
||||
return '%ssattr 0x%02x%s%s' % (
|
||||
'shrub' if tag & TAG_SHRUB else '',
|
||||
((tag & 0x100) >> 1) | (tag & 0xff),
|
||||
' w%d' % w if w else '',
|
||||
size)
|
||||
elif (tag & 0xff00) == TAG_CKSUM:
|
||||
return 'cksum 0x%02x%s %d' % (
|
||||
' %s' % size if size is not None else '')
|
||||
elif (tag & 0x7f00) == TAG_CKSUM:
|
||||
return 'cksum 0x%02x%s%s' % (
|
||||
tag & 0xff,
|
||||
' w%d' % w if w > 0 else '',
|
||||
size)
|
||||
elif (tag & 0xff00) == TAG_ECKSUM:
|
||||
return 'ecksum%s%s %d' % (
|
||||
' w%d' % w if w else '',
|
||||
' %s' % size if size is not None else '')
|
||||
elif (tag & 0x7f00) == TAG_ECKSUM:
|
||||
return 'ecksum%s%s%s' % (
|
||||
' 0x%02x' % (tag & 0xff) if tag & 0xff else '',
|
||||
' w%d' % w if w > 0 else '',
|
||||
size)
|
||||
' w%d' % w if w else '',
|
||||
' %s' % size if size is not None else '')
|
||||
elif tag & TAG_ALT:
|
||||
return 'alt%s%s%s w%d %s' % (
|
||||
return 'alt%s%s%s%s%s' % (
|
||||
'r' if tag & TAG_R else 'b',
|
||||
'a' if tag & 0x0fff == 0 and tag & TAG_GT
|
||||
else 'n' if tag & 0x0fff == 0
|
||||
else 'gt' if tag & TAG_GT
|
||||
else 'le',
|
||||
' 0x%x' % (tag & 0x0fff) if tag & 0x0fff != 0 else '',
|
||||
w,
|
||||
' w%d' % w if w is not None else '',
|
||||
' 0x%x' % (0xffffffff & (off-size))
|
||||
if off is not None
|
||||
else '-%d' % off)
|
||||
if size is not None and off is not None
|
||||
else ' -%d' % size if size is not None
|
||||
else '')
|
||||
else:
|
||||
return '0x%04x w%d %d' % (tag, w, size)
|
||||
return '0x%04x%s%s' % (
|
||||
tag,
|
||||
' w%d' % w if w is not None else '',
|
||||
' %d' % size if size is not None else '')
|
||||
|
||||
|
||||
# this type is used for tree representations
|
||||
|
||||
+37
-33
@@ -168,14 +168,14 @@ def xxd(data, width=16):
|
||||
b if b >= ' ' and b <= '~' else '.'
|
||||
for b in map(chr, data[i:i+width])))
|
||||
|
||||
def tagrepr(tag, w, size, off=None):
|
||||
if (tag & 0xefff) == TAG_NULL:
|
||||
def tagrepr(tag, w=None, size=None, off=None):
|
||||
if (tag & 0x6fff) == TAG_NULL:
|
||||
return '%snull%s%s' % (
|
||||
'shrub' if tag & TAG_SHRUB else '',
|
||||
' w%d' % w if w else '',
|
||||
' %d' % size if size else '')
|
||||
elif (tag & 0xef00) == TAG_CONFIG:
|
||||
return '%s%s%s %d' % (
|
||||
elif (tag & 0x6f00) == TAG_CONFIG:
|
||||
return '%s%s%s%s' % (
|
||||
'shrub' if tag & TAG_SHRUB else '',
|
||||
'magic' if (tag & 0xfff) == TAG_MAGIC
|
||||
else 'version' if (tag & 0xfff) == TAG_VERSION
|
||||
@@ -187,16 +187,16 @@ def tagrepr(tag, w, size, off=None):
|
||||
else 'namelimit' if (tag & 0xfff) == TAG_NAMELIMIT
|
||||
else 'config 0x%02x' % (tag & 0xff),
|
||||
' w%d' % w if w else '',
|
||||
size)
|
||||
elif (tag & 0xef00) == TAG_GDELTA:
|
||||
return '%s%s%s %d' % (
|
||||
' %s' % size if size is not None else '')
|
||||
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' % w if w else '',
|
||||
size)
|
||||
elif (tag & 0xef00) == TAG_NAME:
|
||||
return '%s%s%s %d' % (
|
||||
' %s' % size if size is not None else '')
|
||||
elif (tag & 0x6f00) == TAG_NAME:
|
||||
return '%s%s%s%s' % (
|
||||
'shrub' if tag & TAG_SHRUB else '',
|
||||
'name' if (tag & 0xfff) == TAG_NAME
|
||||
else 'reg' if (tag & 0xfff) == TAG_REG
|
||||
@@ -205,9 +205,9 @@ def tagrepr(tag, w, size, off=None):
|
||||
else 'bookmark' if (tag & 0xfff) == TAG_BOOKMARK
|
||||
else 'name 0x%02x' % (tag & 0xff),
|
||||
' w%d' % w if w else '',
|
||||
size)
|
||||
elif (tag & 0xef00) == TAG_STRUCT:
|
||||
return '%s%s%s %d' % (
|
||||
' %s' % size if size is not None else '')
|
||||
elif (tag & 0x6f00) == TAG_STRUCT:
|
||||
return '%s%s%s%s' % (
|
||||
'shrub' if tag & TAG_SHRUB else '',
|
||||
'data' if (tag & 0xfff) == TAG_DATA
|
||||
else 'block' if (tag & 0xfff) == TAG_BLOCK
|
||||
@@ -221,43 +221,47 @@ def tagrepr(tag, w, size, off=None):
|
||||
else 'mtree' if (tag & 0xfff) == TAG_MTREE
|
||||
else 'struct 0x%02x' % (tag & 0xff),
|
||||
' w%d' % w if w else '',
|
||||
size)
|
||||
elif (tag & 0xef00) == TAG_UATTR:
|
||||
return '%suattr 0x%02x%s %d' % (
|
||||
' %s' % size if size is not None else '')
|
||||
elif (tag & 0x6e00) == TAG_UATTR:
|
||||
return '%suattr 0x%02x%s%s' % (
|
||||
'shrub' if tag & TAG_SHRUB else '',
|
||||
((tag & 0x100) >> 1) | (tag & 0xff),
|
||||
' w%d' % w if w else '',
|
||||
size)
|
||||
elif (tag & 0xef00) == TAG_SATTR:
|
||||
return '%ssattr 0x%02x%s %d' % (
|
||||
' %s' % size if size is not None else '')
|
||||
elif (tag & 0x6e00) == TAG_SATTR:
|
||||
return '%ssattr 0x%02x%s%s' % (
|
||||
'shrub' if tag & TAG_SHRUB else '',
|
||||
((tag & 0x100) >> 1) | (tag & 0xff),
|
||||
' w%d' % w if w else '',
|
||||
size)
|
||||
elif (tag & 0xff00) == TAG_CKSUM:
|
||||
return 'cksum 0x%02x%s %d' % (
|
||||
' %s' % size if size is not None else '')
|
||||
elif (tag & 0x7f00) == TAG_CKSUM:
|
||||
return 'cksum 0x%02x%s%s' % (
|
||||
tag & 0xff,
|
||||
' w%d' % w if w > 0 else '',
|
||||
size)
|
||||
elif (tag & 0xff00) == TAG_ECKSUM:
|
||||
return 'ecksum%s%s %d' % (
|
||||
' w%d' % w if w else '',
|
||||
' %s' % size if size is not None else '')
|
||||
elif (tag & 0x7f00) == TAG_ECKSUM:
|
||||
return 'ecksum%s%s%s' % (
|
||||
' 0x%02x' % (tag & 0xff) if tag & 0xff else '',
|
||||
' w%d' % w if w > 0 else '',
|
||||
size)
|
||||
' w%d' % w if w else '',
|
||||
' %s' % size if size is not None else '')
|
||||
elif tag & TAG_ALT:
|
||||
return 'alt%s%s%s w%d %s' % (
|
||||
return 'alt%s%s%s%s%s' % (
|
||||
'r' if tag & TAG_R else 'b',
|
||||
'a' if tag & 0x0fff == 0 and tag & TAG_GT
|
||||
else 'n' if tag & 0x0fff == 0
|
||||
else 'gt' if tag & TAG_GT
|
||||
else 'le',
|
||||
' 0x%x' % (tag & 0x0fff) if tag & 0x0fff != 0 else '',
|
||||
w,
|
||||
' w%d' % w if w is not None else '',
|
||||
' 0x%x' % (0xffffffff & (off-size))
|
||||
if off is not None
|
||||
else '-%d' % off)
|
||||
if size is not None and off is not None
|
||||
else ' -%d' % size if size is not None
|
||||
else '')
|
||||
else:
|
||||
return '0x%04x w%d %d' % (tag, w, size)
|
||||
return '0x%04x%s%s' % (
|
||||
tag,
|
||||
' w%d' % w if w is not None else '',
|
||||
' %d' % size if size is not None else '')
|
||||
|
||||
|
||||
# this type is used for tree representations
|
||||
|
||||
+37
-33
@@ -155,14 +155,14 @@ def xxd(data, width=16):
|
||||
b if b >= ' ' and b <= '~' else '.'
|
||||
for b in map(chr, data[i:i+width])))
|
||||
|
||||
def tagrepr(tag, w, size, off=None):
|
||||
if (tag & 0xefff) == TAG_NULL:
|
||||
def tagrepr(tag, w=None, size=None, off=None):
|
||||
if (tag & 0x6fff) == TAG_NULL:
|
||||
return '%snull%s%s' % (
|
||||
'shrub' if tag & TAG_SHRUB else '',
|
||||
' w%d' % w if w else '',
|
||||
' %d' % size if size else '')
|
||||
elif (tag & 0xef00) == TAG_CONFIG:
|
||||
return '%s%s%s %d' % (
|
||||
elif (tag & 0x6f00) == TAG_CONFIG:
|
||||
return '%s%s%s%s' % (
|
||||
'shrub' if tag & TAG_SHRUB else '',
|
||||
'magic' if (tag & 0xfff) == TAG_MAGIC
|
||||
else 'version' if (tag & 0xfff) == TAG_VERSION
|
||||
@@ -174,16 +174,16 @@ def tagrepr(tag, w, size, off=None):
|
||||
else 'namelimit' if (tag & 0xfff) == TAG_NAMELIMIT
|
||||
else 'config 0x%02x' % (tag & 0xff),
|
||||
' w%d' % w if w else '',
|
||||
size)
|
||||
elif (tag & 0xef00) == TAG_GDELTA:
|
||||
return '%s%s%s %d' % (
|
||||
' %s' % size if size is not None else '')
|
||||
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' % w if w else '',
|
||||
size)
|
||||
elif (tag & 0xef00) == TAG_NAME:
|
||||
return '%s%s%s %d' % (
|
||||
' %s' % size if size is not None else '')
|
||||
elif (tag & 0x6f00) == TAG_NAME:
|
||||
return '%s%s%s%s' % (
|
||||
'shrub' if tag & TAG_SHRUB else '',
|
||||
'name' if (tag & 0xfff) == TAG_NAME
|
||||
else 'reg' if (tag & 0xfff) == TAG_REG
|
||||
@@ -192,9 +192,9 @@ def tagrepr(tag, w, size, off=None):
|
||||
else 'bookmark' if (tag & 0xfff) == TAG_BOOKMARK
|
||||
else 'name 0x%02x' % (tag & 0xff),
|
||||
' w%d' % w if w else '',
|
||||
size)
|
||||
elif (tag & 0xef00) == TAG_STRUCT:
|
||||
return '%s%s%s %d' % (
|
||||
' %s' % size if size is not None else '')
|
||||
elif (tag & 0x6f00) == TAG_STRUCT:
|
||||
return '%s%s%s%s' % (
|
||||
'shrub' if tag & TAG_SHRUB else '',
|
||||
'data' if (tag & 0xfff) == TAG_DATA
|
||||
else 'block' if (tag & 0xfff) == TAG_BLOCK
|
||||
@@ -208,43 +208,47 @@ def tagrepr(tag, w, size, off=None):
|
||||
else 'mtree' if (tag & 0xfff) == TAG_MTREE
|
||||
else 'struct 0x%02x' % (tag & 0xff),
|
||||
' w%d' % w if w else '',
|
||||
size)
|
||||
elif (tag & 0xef00) == TAG_UATTR:
|
||||
return '%suattr 0x%02x%s %d' % (
|
||||
' %s' % size if size is not None else '')
|
||||
elif (tag & 0x6e00) == TAG_UATTR:
|
||||
return '%suattr 0x%02x%s%s' % (
|
||||
'shrub' if tag & TAG_SHRUB else '',
|
||||
((tag & 0x100) >> 1) | (tag & 0xff),
|
||||
' w%d' % w if w else '',
|
||||
size)
|
||||
elif (tag & 0xef00) == TAG_SATTR:
|
||||
return '%ssattr 0x%02x%s %d' % (
|
||||
' %s' % size if size is not None else '')
|
||||
elif (tag & 0x6e00) == TAG_SATTR:
|
||||
return '%ssattr 0x%02x%s%s' % (
|
||||
'shrub' if tag & TAG_SHRUB else '',
|
||||
((tag & 0x100) >> 1) | (tag & 0xff),
|
||||
' w%d' % w if w else '',
|
||||
size)
|
||||
elif (tag & 0xff00) == TAG_CKSUM:
|
||||
return 'cksum 0x%02x%s %d' % (
|
||||
' %s' % size if size is not None else '')
|
||||
elif (tag & 0x7f00) == TAG_CKSUM:
|
||||
return 'cksum 0x%02x%s%s' % (
|
||||
tag & 0xff,
|
||||
' w%d' % w if w > 0 else '',
|
||||
size)
|
||||
elif (tag & 0xff00) == TAG_ECKSUM:
|
||||
return 'ecksum%s%s %d' % (
|
||||
' w%d' % w if w else '',
|
||||
' %s' % size if size is not None else '')
|
||||
elif (tag & 0x7f00) == TAG_ECKSUM:
|
||||
return 'ecksum%s%s%s' % (
|
||||
' 0x%02x' % (tag & 0xff) if tag & 0xff else '',
|
||||
' w%d' % w if w > 0 else '',
|
||||
size)
|
||||
' w%d' % w if w else '',
|
||||
' %s' % size if size is not None else '')
|
||||
elif tag & TAG_ALT:
|
||||
return 'alt%s%s%s w%d %s' % (
|
||||
return 'alt%s%s%s%s%s' % (
|
||||
'r' if tag & TAG_R else 'b',
|
||||
'a' if tag & 0x0fff == 0 and tag & TAG_GT
|
||||
else 'n' if tag & 0x0fff == 0
|
||||
else 'gt' if tag & TAG_GT
|
||||
else 'le',
|
||||
' 0x%x' % (tag & 0x0fff) if tag & 0x0fff != 0 else '',
|
||||
w,
|
||||
' w%d' % w if w is not None else '',
|
||||
' 0x%x' % (0xffffffff & (off-size))
|
||||
if off is not None
|
||||
else '-%d' % off)
|
||||
if size is not None and off is not None
|
||||
else ' -%d' % size if size is not None
|
||||
else '')
|
||||
else:
|
||||
return '0x%04x w%d %d' % (tag, w, size)
|
||||
return '0x%04x%s%s' % (
|
||||
tag,
|
||||
' w%d' % w if w is not None else '',
|
||||
' %d' % size if size is not None else '')
|
||||
|
||||
|
||||
def dbg_log(data, block_size, rev, eoff, weight, *,
|
||||
|
||||
Executable
+314
@@ -0,0 +1,314 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import io
|
||||
import os
|
||||
import struct
|
||||
import sys
|
||||
|
||||
|
||||
TAG_NULL = 0x0000
|
||||
TAG_CONFIG = 0x0000
|
||||
TAG_MAGIC = 0x0003
|
||||
TAG_VERSION = 0x0004
|
||||
TAG_RCOMPAT = 0x0005
|
||||
TAG_WCOMPAT = 0x0006
|
||||
TAG_OCOMPAT = 0x0007
|
||||
TAG_GEOMETRY = 0x0009
|
||||
TAG_NAMELIMIT = 0x000c
|
||||
TAG_SIZELIMIT = 0x000d
|
||||
TAG_GDELTA = 0x0100
|
||||
TAG_GRMDELTA = 0x0100
|
||||
TAG_NAME = 0x0200
|
||||
TAG_REG = 0x0201
|
||||
TAG_DIR = 0x0202
|
||||
TAG_ORPHAN = 0x0203
|
||||
TAG_BOOKMARK = 0x0204
|
||||
TAG_STRUCT = 0x0300
|
||||
TAG_DATA = 0x0300
|
||||
TAG_BLOCK = 0x0304
|
||||
TAG_BSHRUB = 0x0308
|
||||
TAG_BTREE = 0x030c
|
||||
TAG_DID = 0x0310
|
||||
TAG_BECKSUM = 0x0314
|
||||
TAG_BRANCH = 0x031c
|
||||
TAG_MROOT = 0x0321
|
||||
TAG_MDIR = 0x0325
|
||||
TAG_MTREE = 0x032c
|
||||
TAG_UATTR = 0x0400
|
||||
TAG_SATTR = 0x0600
|
||||
TAG_SHRUB = 0x1000
|
||||
TAG_CKSUM = 0x3000
|
||||
TAG_ECKSUM = 0x3100
|
||||
TAG_ALT = 0x4000
|
||||
TAG_GT = 0x2000
|
||||
TAG_R = 0x1000
|
||||
|
||||
|
||||
# some ways of block geometry representations
|
||||
# 512 -> 512
|
||||
# 512x16 -> (512, 16)
|
||||
# 0x200x10 -> (512, 16)
|
||||
def bdgeom(s):
|
||||
s = s.strip()
|
||||
b = 10
|
||||
if s.startswith('0x') or s.startswith('0X'):
|
||||
s = s[2:]
|
||||
b = 16
|
||||
elif s.startswith('0o') or s.startswith('0O'):
|
||||
s = s[2:]
|
||||
b = 8
|
||||
elif s.startswith('0b') or s.startswith('0B'):
|
||||
s = s[2:]
|
||||
b = 2
|
||||
|
||||
if 'x' in s:
|
||||
s, s_ = s.split('x', 1)
|
||||
return (int(s, b), int(s_, b))
|
||||
else:
|
||||
return int(s, b)
|
||||
|
||||
# parse some rbyd addr encodings
|
||||
# 0xa -> [0xa]
|
||||
# 0xa.c -> [(0xa, 0xc)]
|
||||
# 0x{a,b} -> [0xa, 0xb]
|
||||
# 0x{a,b}.c -> [(0xa, 0xc), (0xb, 0xc)]
|
||||
def rbydaddr(s):
|
||||
s = s.strip()
|
||||
b = 10
|
||||
if s.startswith('0x') or s.startswith('0X'):
|
||||
s = s[2:]
|
||||
b = 16
|
||||
elif s.startswith('0o') or s.startswith('0O'):
|
||||
s = s[2:]
|
||||
b = 8
|
||||
elif s.startswith('0b') or s.startswith('0B'):
|
||||
s = s[2:]
|
||||
b = 2
|
||||
|
||||
trunk = None
|
||||
if '.' in s:
|
||||
s, s_ = s.split('.', 1)
|
||||
trunk = int(s_, b)
|
||||
|
||||
if s.startswith('{') and '}' in s:
|
||||
ss = s[1:s.find('}')].split(',')
|
||||
else:
|
||||
ss = [s]
|
||||
|
||||
addr = []
|
||||
for s in ss:
|
||||
if trunk is not None:
|
||||
addr.append((int(s, b), trunk))
|
||||
else:
|
||||
addr.append(int(s, b))
|
||||
|
||||
return addr
|
||||
|
||||
def fromleb128(data):
|
||||
word = 0
|
||||
for i, b in enumerate(data):
|
||||
word |= ((b & 0x7f) << 7*i)
|
||||
word &= 0xffffffff
|
||||
if not b & 0x80:
|
||||
return word, i+1
|
||||
return word, len(data)
|
||||
|
||||
def tagrepr(tag, w=None, size=None, off=None):
|
||||
if (tag & 0x6fff) == TAG_NULL:
|
||||
return '%snull%s%s' % (
|
||||
'shrub' if tag & TAG_SHRUB else '',
|
||||
' w%d' % w if w else '',
|
||||
' %d' % size if size else '')
|
||||
elif (tag & 0x6f00) == TAG_CONFIG:
|
||||
return '%s%s%s%s' % (
|
||||
'shrub' if tag & TAG_SHRUB else '',
|
||||
'magic' if (tag & 0xfff) == TAG_MAGIC
|
||||
else 'version' if (tag & 0xfff) == TAG_VERSION
|
||||
else 'rcompat' if (tag & 0xfff) == TAG_RCOMPAT
|
||||
else 'wcompat' if (tag & 0xfff) == TAG_WCOMPAT
|
||||
else 'ocompat' if (tag & 0xfff) == TAG_OCOMPAT
|
||||
else 'geometry' if (tag & 0xfff) == TAG_GEOMETRY
|
||||
else 'sizelimit' if (tag & 0xfff) == TAG_SIZELIMIT
|
||||
else 'namelimit' if (tag & 0xfff) == TAG_NAMELIMIT
|
||||
else 'config 0x%02x' % (tag & 0xff),
|
||||
' w%d' % w if w else '',
|
||||
' %s' % size if size is not None else '')
|
||||
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' % w if w else '',
|
||||
' %s' % size if size is not None else '')
|
||||
elif (tag & 0x6f00) == TAG_NAME:
|
||||
return '%s%s%s%s' % (
|
||||
'shrub' if tag & TAG_SHRUB else '',
|
||||
'name' if (tag & 0xfff) == TAG_NAME
|
||||
else 'reg' if (tag & 0xfff) == TAG_REG
|
||||
else 'dir' if (tag & 0xfff) == TAG_DIR
|
||||
else 'orphan' if (tag & 0xfff) == TAG_ORPHAN
|
||||
else 'bookmark' if (tag & 0xfff) == TAG_BOOKMARK
|
||||
else 'name 0x%02x' % (tag & 0xff),
|
||||
' w%d' % w if w else '',
|
||||
' %s' % size if size is not None else '')
|
||||
elif (tag & 0x6f00) == TAG_STRUCT:
|
||||
return '%s%s%s%s' % (
|
||||
'shrub' if tag & TAG_SHRUB else '',
|
||||
'data' if (tag & 0xfff) == TAG_DATA
|
||||
else 'block' if (tag & 0xfff) == TAG_BLOCK
|
||||
else 'bshrub' if (tag & 0xfff) == TAG_BSHRUB
|
||||
else 'btree' if (tag & 0xfff) == TAG_BTREE
|
||||
else 'did' if (tag & 0xfff) == TAG_DID
|
||||
else 'becksum' if (tag & 0xfff) == TAG_BECKSUM
|
||||
else 'branch' if (tag & 0xfff) == TAG_BRANCH
|
||||
else 'mroot' if (tag & 0xfff) == TAG_MROOT
|
||||
else 'mdir' if (tag & 0xfff) == TAG_MDIR
|
||||
else 'mtree' if (tag & 0xfff) == TAG_MTREE
|
||||
else 'struct 0x%02x' % (tag & 0xff),
|
||||
' w%d' % w if w else '',
|
||||
' %s' % size if size is not None else '')
|
||||
elif (tag & 0x6e00) == TAG_UATTR:
|
||||
return '%suattr 0x%02x%s%s' % (
|
||||
'shrub' if tag & TAG_SHRUB else '',
|
||||
((tag & 0x100) >> 1) | (tag & 0xff),
|
||||
' w%d' % w if w else '',
|
||||
' %s' % size if size is not None else '')
|
||||
elif (tag & 0x6e00) == TAG_SATTR:
|
||||
return '%ssattr 0x%02x%s%s' % (
|
||||
'shrub' if tag & TAG_SHRUB else '',
|
||||
((tag & 0x100) >> 1) | (tag & 0xff),
|
||||
' w%d' % w if w else '',
|
||||
' %s' % size if size is not None else '')
|
||||
elif (tag & 0x7f00) == TAG_CKSUM:
|
||||
return 'cksum 0x%02x%s%s' % (
|
||||
tag & 0xff,
|
||||
' w%d' % w if w else '',
|
||||
' %s' % size if size is not None else '')
|
||||
elif (tag & 0x7f00) == TAG_ECKSUM:
|
||||
return 'ecksum%s%s%s' % (
|
||||
' 0x%02x' % (tag & 0xff) if tag & 0xff else '',
|
||||
' w%d' % w if w else '',
|
||||
' %s' % size if size is not None else '')
|
||||
elif tag & TAG_ALT:
|
||||
return 'alt%s%s%s%s%s' % (
|
||||
'r' if tag & TAG_R else 'b',
|
||||
'a' if tag & 0x0fff == 0 and tag & TAG_GT
|
||||
else 'n' if tag & 0x0fff == 0
|
||||
else 'gt' if tag & TAG_GT
|
||||
else 'le',
|
||||
' 0x%x' % (tag & 0x0fff) if tag & 0x0fff != 0 else '',
|
||||
' w%d' % w if w is not None else '',
|
||||
' 0x%x' % (0xffffffff & (off-size))
|
||||
if size is not None and off is not None
|
||||
else ' -%d' % size if size is not None
|
||||
else '')
|
||||
else:
|
||||
return '0x%04x%s%s' % (
|
||||
tag,
|
||||
' w%d' % w if w is not None else '',
|
||||
' %d' % size if size is not None else '')
|
||||
|
||||
|
||||
def dbg_tag(data):
|
||||
if isinstance(data, int):
|
||||
tag = data
|
||||
weight = None
|
||||
size = None
|
||||
else:
|
||||
data = data.ljust(2, b'\0')
|
||||
tag = (data[0] << 8) | data[1]
|
||||
weight, d = fromleb128(data[2:]) if 2 < len(data) else (None, 2)
|
||||
size, d_ = fromleb128(data[2+d:]) if d < len(data) else (None, d)
|
||||
|
||||
print(tagrepr(tag, weight, size))
|
||||
|
||||
def main(tags, *,
|
||||
block_size=None,
|
||||
block_count=None,
|
||||
off=None,
|
||||
**args):
|
||||
# interpret as a sequence of hex bytes
|
||||
if args.get('hex'):
|
||||
dbg_tag(bytes(int(tag, 16) for tag in tags))
|
||||
|
||||
# interpret as strings
|
||||
elif args.get('string'):
|
||||
for tag in tags:
|
||||
dbg_tag(tag.encode('utf8'))
|
||||
|
||||
# default to interpreting as ints
|
||||
elif block_size is None and off is None:
|
||||
for tag in tags:
|
||||
dbg_tag(int(tag, 0))
|
||||
|
||||
# if either block_size or off provided interpret as a block device
|
||||
else:
|
||||
disk, *blocks = tags
|
||||
blocks = [rbydaddr(block) for block in blocks]
|
||||
|
||||
# is bd geometry specified?
|
||||
if isinstance(block_size, tuple):
|
||||
block_size, block_count_ = block_size
|
||||
if block_count is None:
|
||||
block_count = block_count_
|
||||
|
||||
# flatten block, default to block 0
|
||||
if not blocks:
|
||||
blocks = [[0]]
|
||||
blocks = [block for blocks_ in blocks for block in blocks_]
|
||||
|
||||
with open(disk, 'rb') as f:
|
||||
# if block_size is omitted, assume the block device is one big block
|
||||
if block_size is None:
|
||||
f.seek(0, os.SEEK_END)
|
||||
block_size = f.tell()
|
||||
|
||||
# blocks may also encode offsets
|
||||
blocks, offs = (
|
||||
[block[0] if isinstance(block, tuple) else block
|
||||
for block in blocks],
|
||||
[off if off is not None
|
||||
else block[1] if isinstance(block, tuple)
|
||||
else None
|
||||
for block in blocks])
|
||||
|
||||
# read each tag
|
||||
for block, off in zip(blocks, offs):
|
||||
f.seek((block * block_size) + (off or 0))
|
||||
# read maximum tag size
|
||||
data = f.read(2+5+5)
|
||||
dbg_tag(data)
|
||||
|
||||
if __name__ == "__main__":
|
||||
import argparse
|
||||
import sys
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Decode littlefs tags.",
|
||||
allow_abbrev=False)
|
||||
parser.add_argument(
|
||||
'tags',
|
||||
nargs='*',
|
||||
help="Tags to decode.")
|
||||
parser.add_argument(
|
||||
'-x', '--hex',
|
||||
action='store_true',
|
||||
help="Interpret as a sequence of hex bytes.")
|
||||
parser.add_argument(
|
||||
'-s', '--string',
|
||||
action='store_true',
|
||||
help="Interpret as strings.")
|
||||
parser.add_argument(
|
||||
'-b', '--block-size',
|
||||
type=bdgeom,
|
||||
help="Block size/geometry in bytes.")
|
||||
parser.add_argument(
|
||||
'--block-count',
|
||||
type=lambda x: int(x, 0),
|
||||
help="Block count in blocks.")
|
||||
parser.add_argument(
|
||||
'--off',
|
||||
type=lambda x: int(x, 0),
|
||||
help="Use this offset.")
|
||||
sys.exit(main(**{k: v
|
||||
for k, v in vars(parser.parse_intermixed_args()).items()
|
||||
if v is not None}))
|
||||
Reference in New Issue
Block a user