From 173de4388b5518171b8be20118f2b03b10492224 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Sat, 14 Oct 2023 04:47:25 -0500 Subject: [PATCH] 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 ... --- scripts/dbglfs.py | 134 +++++++++++++++++++++++++++++++--------------- 1 file changed, 92 insertions(+), 42 deletions(-) diff --git a/scripts/dbglfs.py b/scripts/dbglfs.py index f930844e..2dc92497 100755 --- a/scripts/dbglfs.py +++ b/scripts/dbglfs.py @@ -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)