Added file tags to rendering of inner tree tags in dbglfs.py

Now -i/--inner will also show the file tags that reference the
underlying data structure.

The difference is subtle but useful:

  littlefs v2.0 0x{0,1}.eee, rev 315, weight 0.256, bd 4096x262144
  {0000,0001}:  -1.1 hello  reg 8192, btree 0x5121.d50 8143
    0000.0efc:       +          0-8142 btree w8143 11             ...
    5121.0d50:       | .-+      0-4095 block w4096 6              ...
                     | | '->    0-4095 block w4096 0x5117.0 4096  ...
                     '-+-+   4096-8142 block w4047 6              ...
                         '-> 4096-8142 block w4047 0x5139.0 4047  ...
This commit is contained in:
Christopher Haster
2023-10-14 04:47:25 -05:00
parent fbb6a27b05
commit 173de4388b

View File

@@ -1223,10 +1223,54 @@ def frepr(mdir, rid, tag):
else:
return 'type 0x%02x' % (tag & 0xff)
def dbg_fstruct(f, block_size, btree, inlined=False, *,
def dbg_fstruct(f, block_size, mdir, rid, tag, j, d, data, inlined=False, *,
m_width=0,
color=False,
args={}):
# first decode possible rbyds/btrees, for sprouts/direct blocks we pretend
# the entry itself is a single-element btree
# sprout?
if tag == TAG_INLINED:
btree = Rbyd(
mdir.block,
mdir.data,
mdir.rev,
mdir.eoff,
j,
0)
w = len(data)
# shrub?
elif tag == TAG_TRUNK:
d = 0
trunk, d_ = fromleb128(data[d:]); d += d_
weight, d_ = fromleb128(data[d:]); d += d_
btree = Rbyd.fetch(f, block_size, mdir.block, trunk)
w = weight
# direct block?
elif tag == TAG_BLOCK:
btree = Rbyd(
mdir.block,
mdir.data,
mdir.rev,
mdir.eoff,
j,
0)
d = 0
block, d_ = fromleb128(data[d:]); d += d_
off, d_ = fromleb128(data[d:]); d += d_
size, d_ = fromleb128(data[d:]); d += d_
w = size
# indirect btree?
elif tag == TAG_BTREE:
d = 0
block, d_ = fromleb128(data[d:]); d += d_
trunk, d_ = fromleb128(data[d:]); d += d_
weight, d_ = fromleb128(data[d:]); d += d_
cksum = fromle32(data[d:]); d += 4
btree = Rbyd.fetch(f, block_size, block, trunk)
w = weight
# precompute rbyd-trees if requested
t_width = 0
if args.get('tree'):
@@ -1251,11 +1295,32 @@ def dbg_fstruct(f, block_size, btree, inlined=False, *,
tree_.add(TBranch(
a=(a_bid, a_bd, a_rid, a_tag, a_tag == TAG_BLOCK),
b=(b_bid, b_bd, b_rid, b_tag, b_tag == TAG_BLOCK),
d=branch.d,
d=branch.d + (1 if args.get('inner') else 0),
c=branch.c,
))
tree = tree_
# connect our source tag if we are showing inner nodes
if tag != TAG_INLINED and tag != TAG_BLOCK and args.get('inner'):
if tree:
branch = min(tree, key=lambda branch: branch.d)
a_bid, a_bd, a_rid, a_tag, a_block = branch.a
tree.add(TBranch(
a=(0, -1, 0, tag, False),
b=(a_bid, a_bd, a_rid, a_tag, a_block),
d=0,
c='b'
))
else:
done, rid_, tag_, w_, j_, d_, data_, _ = btree.lookup(-1, 0)
if not done:
tree.add(TBranch(
a=(0, -1, 0, tag, False),
b=(rid_-(w_-1), 0, rid_-(w_-1), tag_, False),
d=0,
c='b'
))
# we need to do some patching if our tree contains blocks and we're
# showing inner nodes
if args.get('inner') and any(branch.b[-1] for branch in tree):
@@ -1365,7 +1430,7 @@ def dbg_fstruct(f, block_size, btree, inlined=False, *,
'%*s ' % (2*w_width+1, '' if i != 0
else '%d-%d' % (bid-(w-1), bid) if w > 1
else bid if w > 0
else '') if not inlined else '',
else ''),
21+w_width, tagrepr(tag, w if i == 0 else 0, len(data), None),
next(xxd(data, 8), '')
if not args.get('raw') and not args.get('no_truncate')
@@ -1378,7 +1443,7 @@ def dbg_fstruct(f, block_size, btree, inlined=False, *,
'',
m_width, '',
t_width, '',
'%*s ' % (2*w_width+1, '') if not inlined else '',
'%*s ' % (2*w_width+1, ''),
tag, w if i == 0 else 0, len(data)))
# show on-disk encoding of tags/data
@@ -1388,7 +1453,7 @@ def dbg_fstruct(f, block_size, btree, inlined=False, *,
'%04x' % (j + o*16),
m_width, '',
t_width, '',
'%*s ' % (2*w_width+1, '') if not inlined else '',
'%*s ' % (2*w_width+1, ''),
line))
if args.get('raw') or args.get('no_truncate'):
for o, line in enumerate(xxd(data)):
@@ -1396,7 +1461,7 @@ def dbg_fstruct(f, block_size, btree, inlined=False, *,
'%04x' % (j+d + o*16),
m_width, '',
t_width, '',
'%*s ' % (2*w_width+1, '') if not inlined else '',
'%*s ' % (2*w_width+1, ''),
line))
def dbg_block(bid, w, rbyd, rid, bptr, block, off, size, data, bd):
@@ -1413,7 +1478,7 @@ def dbg_fstruct(f, block_size, btree, inlined=False, *,
if args.get('tree') or args.get('btree') else '',
'%*s ' % (2*w_width+1, '%d-%d' % (bid-(w-1), bid) if w > 1
else bid if w > 0
else '') if not inlined else '',
else ''),
21+w_width, 'block%s 0x%x.%x %d' % (
' w%d' % w if w else '',
block, off, size),
@@ -1429,7 +1494,7 @@ def dbg_fstruct(f, block_size, btree, inlined=False, *,
'',
m_width, '',
t_width, '',
'%*s ' % (2*w_width+1, '') if not inlined else '',
'%*s ' % (2*w_width+1, ''),
tag, w, len(data_)))
# show on-disk encoding of tags/bptr/data
@@ -1440,7 +1505,7 @@ def dbg_fstruct(f, block_size, btree, inlined=False, *,
'%04x' % (j + o*16),
m_width, '',
t_width, '',
'%*s ' % (2*w_width+1, '') if not inlined else '',
'%*s ' % (2*w_width+1, ''),
line))
if args.get('raw'):
_, j, d, data_ = bptr
@@ -1449,7 +1514,7 @@ def dbg_fstruct(f, block_size, btree, inlined=False, *,
'%04x' % (j+d + o*16),
m_width, '',
t_width, '',
'%*s ' % (2*w_width+1, '') if not inlined else '',
'%*s ' % (2*w_width+1, ''),
line))
if args.get('raw') or args.get('no_truncate'):
for o, line in enumerate(xxd(data)):
@@ -1458,14 +1523,25 @@ def dbg_fstruct(f, block_size, btree, inlined=False, *,
else '%04x' % (off + o*16),
m_width, '',
t_width, '',
'%*s ' % (2*w_width+1, '') if not inlined else '',
'%*s ' % (2*w_width+1, ''),
line))
# if we show non-truncated file contents we need to
# reset the rbyd address
prbyd = None
# show our source tag? note the big hack here of pretending our
# entry is a single-element btree
if tag == TAG_INLINED or tag == TAG_BLOCK or args.get('inner'):
dbg_branch(w-1, w, Rbyd(
mdir.block,
mdir.data,
mdir.rev,
mdir.eoff,
j,
0), w-1, [(tag, j, d, data)], -1)
# traverse and print entries
bid = -2 if inlined else -1
bid = -1
prbyd = None
ppath = []
corrupted = False
@@ -1992,17 +2068,8 @@ def main(disk, mroots=None, *,
done, rid_, tag_, w_, j, d, data, _ = mdir.lookup(
rid, TAG_INLINED)
if not done and rid_ == rid and tag_ == TAG_INLINED:
# turns out we can reuse dbg_fstruct here by
# pretending our sprout is a single element shrub
dbg_fstruct(f, block_size,
Rbyd(
mdir.block,
mdir.data,
mdir.rev,
mdir.eoff,
j,
0),
inlined=True,
mdir, rid_, tag_, j, d, data,
m_width=2*w_width+1,
color=color,
args=args)
@@ -2011,11 +2078,8 @@ def main(disk, mroots=None, *,
done, rid_, tag_, w_, j, d, data, _ = mdir.lookup(
rid, TAG_TRUNK)
if not done and rid_ == rid and tag_ == TAG_TRUNK:
d = 0
trunk, d_ = fromleb128(data[d:]); d += d_
weight, d_ = fromleb128(data[d:]); d += d_
dbg_fstruct(f, block_size,
Rbyd.fetch(f, block_size, mdir.block, trunk),
mdir, rid_, tag_, j, d, data,
m_width=2*w_width+1,
color=color,
args=args)
@@ -2024,17 +2088,8 @@ def main(disk, mroots=None, *,
done, rid_, tag_, w_, j, d, data, _ = mdir.lookup(
rid, TAG_BLOCK)
if not done and rid_ == rid and tag_ == TAG_BLOCK:
# we can reuse dbg_fstruct here like with the
# shrub trick above
dbg_fstruct(f, block_size,
Rbyd(
mdir.block,
mdir.data,
mdir.rev,
mdir.eoff,
j,
0),
inlined=True,
mdir, rid_, tag_, j, d, data,
m_width=2*w_width+1,
color=color,
args=args)
@@ -2043,13 +2098,8 @@ def main(disk, mroots=None, *,
done, rid_, tag_, w_, j, d, data, _ = mdir.lookup(
rid, TAG_BTREE)
if not done and rid_ == rid and tag_ == TAG_BTREE:
d = 0
block, d_ = fromleb128(data[d:]); d += d_
trunk, d_ = fromleb128(data[d:]); d += d_
weight, d_ = fromleb128(data[d:]); d += d_
cksum = fromle32(data[d:]); d += 4
dbg_fstruct(f, block_size,
Rbyd.fetch(f, block_size, block, trunk),
mdir, rid_, tag_, j, d, data,
m_width=2*w_width+1,
color=color,
args=args)