Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/littlefs-project/littlefs.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Haster <chaster@utexas.edu>2020-03-30 05:19:33 +0300
committerChristopher Haster <chaster@utexas.edu>2020-03-30 05:19:33 +0300
commit5137e4b0bab12a2d88c1e960acc1acf0f278563f (patch)
treebcfe94d3c7a5d0444d86d10b62ccd9de87ab0f3c /scripts
parentff84902970326efc4449f5cb1a8ccd3b466e18a9 (diff)
Last minute tweaks to debug scripts
- Standardized littlefs debug statements to use hex prefixes and brackets for printing pairs. - Removed the entry behavior for readtree and made -t the default. This is because 1. the CTZ skip-list parsing was broken, which is not surprising, and 2. the entry parsing was more complicated than useful. This functionality may be better implemented as a proper filesystem read script, complete with directory tree dumping. - Changed test.py's --gdb argument to take [init, main, assert], this matches the names of the stages in C's startup. - Added printing of tail to all mdir dumps in readtree/readmdir. - Added a print for if any mdirs are corrupted in readtree. - Added debug script side-effects to .gitignore.
Diffstat (limited to 'scripts')
-rwxr-xr-xscripts/readmdir.py18
-rwxr-xr-xscripts/readtree.py162
-rwxr-xr-xscripts/test.py4
3 files changed, 58 insertions, 126 deletions
diff --git a/scripts/readmdir.py b/scripts/readmdir.py
index 75f8b9a..b6c3dcc 100755
--- a/scripts/readmdir.py
+++ b/scripts/readmdir.py
@@ -233,8 +233,8 @@ class MetadataPair:
def __lt__(self, other):
# corrupt blocks don't count
- if not self and other:
- return True
+ if not self or not other:
+ return bool(other)
# use sequence arithmetic to avoid overflow
return not ((other.rev - self.rev) & 0x80000000)
@@ -318,14 +318,24 @@ def main(args):
# find most recent pair
mdir = MetadataPair(blocks)
- print("mdir {%s} rev %d%s%s" % (
+
+ try:
+ mdir.tail = mdir[Tag('tail', 0, 0)]
+ if mdir.tail.size != 8 or mdir.tail.data == 8*b'\xff':
+ mdir.tail = None
+ except KeyError:
+ mdir.tail = None
+
+ print("mdir {%s} rev %d%s%s%s" % (
', '.join('%#x' % b
for b in [args.block1, args.block2]
if b is not None),
mdir.rev,
' (was %s)' % ', '.join('%d' % m.rev for m in mdir.pair[1:])
if len(mdir.pair) > 1 else '',
- ' (corrupted)' if not mdir else ''))
+ ' (corrupted!)' if not mdir else '',
+ ' -> {%#x, %#x}' % struct.unpack('<II', mdir.tail.data)
+ if mdir.tail else ''))
if args.all:
mdir.dump_all(truncate=not args.no_truncate)
elif args.log:
diff --git a/scripts/readtree.py b/scripts/readtree.py
index 3965a36..36135ab 100755
--- a/scripts/readtree.py
+++ b/scripts/readtree.py
@@ -7,97 +7,14 @@ import io
import itertools as it
from readmdir import Tag, MetadataPair
-def popc(x):
- return bin(x).count('1')
-
-def ctz(x):
- return len(bin(x)) - len(bin(x).rstrip('0'))
-
-def dumpentries(args, mdir, f):
- for k, id_ in enumerate(mdir.ids):
- name = mdir[Tag('name', id_, 0)]
- struct_ = mdir[Tag('struct', id_, 0)]
-
- desc = "id %d %s %s" % (
- id_, name.typerepr(),
- json.dumps(name.data.decode('utf8')))
- if struct_.is_('dirstruct'):
- desc += " dir {%#x, %#x}" % struct.unpack(
- '<II', struct_.data[:8].ljust(8, b'\xff'))
- if struct_.is_('ctzstruct'):
- desc += " ctz {%#x} size %d" % struct.unpack(
- '<II', struct_.data[:8].ljust(8, b'\xff'))
- if struct_.is_('inlinestruct'):
- desc += " inline size %d" % struct_.size
-
- data = None
- if struct_.is_('inlinestruct'):
- data = struct_.data
- elif struct_.is_('ctzstruct'):
- block, size = struct.unpack(
- '<II', struct_.data[:8].ljust(8, b'\xff'))
- data = []
- i = 0 if size == 0 else (size-1) // (args.block_size - 8)
- if i != 0:
- i = ((size-1) - 4*popc(i-1)+2) // (args.block_size - 8)
- with open(args.disk, 'rb') as f2:
- while i >= 0:
- f2.seek(block * args.block_size)
- dat = f2.read(args.block_size)
- data.append(dat[4*(ctz(i)+1) if i != 0 else 0:])
- block, = struct.unpack('<I', dat[:4].ljust(4, b'\xff'))
- i -= 1
- data = bytes(it.islice(
- it.chain.from_iterable(reversed(data)), size))
-
- f.write("%-45s%s\n" % (desc,
- "%-23s %-8s" % (
- ' '.join('%02x' % c for c in data[:8]),
- ''.join(c if c >= ' ' and c <= '~' else '.'
- for c in map(chr, data[:8])))
- if not args.no_truncate and len(desc) < 45
- and data is not None else ""))
-
- if name.is_('superblock') and struct_.is_('inlinestruct'):
- f.write(
- " block_size %d\n"
- " block_count %d\n"
- " name_max %d\n"
- " file_max %d\n"
- " attr_max %d\n" % struct.unpack(
- '<IIIII', struct_.data[4:4+20].ljust(20, b'\xff')))
-
- for tag in mdir.tags:
- if tag.id==id_ and tag.is_('userattr'):
- desc = "%s size %d" % (tag.typerepr(), tag.size)
- f.write(" %-43s%s\n" % (desc,
- "%-23s %-8s" % (
- ' '.join('%02x' % c for c in tag.data[:8]),
- ''.join(c if c >= ' ' and c <= '~' else '.'
- for c in map(chr, tag.data[:8])))
- if not args.no_truncate and len(desc) < 43 else ""))
-
- if args.no_truncate:
- for i in range(0, len(tag.data), 16):
- f.write(" %08x: %-47s %-16s\n" % (
- i, ' '.join('%02x' % c for c in tag.data[i:i+16]),
- ''.join(c if c >= ' ' and c <= '~' else '.'
- for c in map(chr, tag.data[i:i+16]))))
-
- if args.no_truncate and data is not None:
- for i in range(0, len(data), 16):
- f.write(" %08x: %-47s %-16s\n" % (
- i, ' '.join('%02x' % c for c in data[i:i+16]),
- ''.join(c if c >= ' ' and c <= '~' else '.'
- for c in map(chr, data[i:i+16]))))
-
def main(args):
+ superblock = None
+ gstate = b'\0\0\0\0\0\0\0\0\0\0\0\0'
+ dirs = []
+ mdirs = []
+ corrupted = []
+ cycle = False
with open(args.disk, 'rb') as f:
- dirs = []
- superblock = None
- gstate = b''
- mdirs = []
- cycle = False
tail = (args.block1, args.block2)
hard = False
while True:
@@ -144,6 +61,10 @@ def main(args):
except KeyError:
pass
+ # corrupted?
+ if not mdir:
+ corrupted.append(mdir)
+
# add to directories
mdirs.append(mdir)
if mdir.tail is None or not mdir.tail.is_('hardtail'):
@@ -178,7 +99,7 @@ def main(args):
dir[0].path = path.replace('//', '/')
- # dump tree
+ # print littlefs + version info
version = ('?', '?')
if superblock:
version = tuple(reversed(
@@ -187,53 +108,56 @@ def main(args):
"data (truncated, if it fits)"
if not any([args.no_truncate, args.tags, args.log, args.all]) else ""))
- if gstate:
- print("gstate 0x%s" % ''.join('%02x' % c for c in gstate))
- tag = Tag(struct.unpack('<I', gstate[0:4].ljust(4, b'\xff'))[0])
- blocks = struct.unpack('<II', gstate[4:4+8].ljust(8, b'\xff'))
- if tag.size or not tag.isvalid:
- print(" orphans >=%d" % max(tag.size, 1))
- if tag.type:
- print(" move dir {%#x, %#x} id %d" % (
- blocks[0], blocks[1], tag.id))
-
+ # print gstate
+ print("gstate 0x%s" % ''.join('%02x' % c for c in gstate))
+ tag = Tag(struct.unpack('<I', gstate[0:4].ljust(4, b'\xff'))[0])
+ blocks = struct.unpack('<II', gstate[4:4+8].ljust(8, b'\xff'))
+ if tag.size or not tag.isvalid:
+ print(" orphans >=%d" % max(tag.size, 1))
+ if tag.type:
+ print(" move dir {%#x, %#x} id %d" % (
+ blocks[0], blocks[1], tag.id))
+
+ # print mdir info
for i, dir in enumerate(dirs):
print("dir %s" % (json.dumps(dir[0].path)
if hasattr(dir[0], 'path') else '(orphan)'))
for j, mdir in enumerate(dir):
- print("mdir {%#x, %#x} rev %d%s" % (
- mdir.blocks[0], mdir.blocks[1], mdir.rev,
- ' (corrupted)' if not mdir else ''))
+ print("mdir {%#x, %#x} rev %d (was %d)%s%s" % (
+ mdir.blocks[0], mdir.blocks[1], mdir.rev, mdir.pair[1].rev,
+ ' (corrupted!)' if not mdir else '',
+ ' -> {%#x, %#x}' % struct.unpack('<II', mdir.tail.data)
+ if mdir.tail else ''))
f = io.StringIO()
- if args.tags:
- mdir.dump_tags(f, truncate=not args.no_truncate)
- elif args.log:
+ if args.log:
mdir.dump_log(f, truncate=not args.no_truncate)
elif args.all:
mdir.dump_all(f, truncate=not args.no_truncate)
else:
- dumpentries(args, mdir, f)
+ mdir.dump_tags(f, truncate=not args.no_truncate)
lines = list(filter(None, f.getvalue().split('\n')))
for k, line in enumerate(lines):
print("%s %s" % (
- ' ' if i == len(dirs)-1 and j == len(dir)-1 else
+ ' ' if j == len(dir)-1 else
'v' if k == len(lines)-1 else
- '.' if j == len(dir)-1 else
'|',
line))
- if cycle:
- print("*** cycle detected! -> {%#x, %#x} ***" % (cycle[0], cycle[1]))
+ errcode = 0
+ for mdir in corrupted:
+ errcode = errcode or 1
+ print("*** corrupted mdir {%#x, %#x}! ***" % (
+ mdir.blocks[0], mdir.blocks[1]))
if cycle:
- return 2
- elif not all(mdir for dir in dirs for mdir in dir):
- return 1
- else:
- return 0;
+ errcode = errcode or 2
+ print("*** cycle detected {%#x, %#x}! ***" % (
+ cycle[0], cycle[1]))
+
+ return errcode
if __name__ == "__main__":
import argparse
@@ -246,12 +170,10 @@ if __name__ == "__main__":
help="Size of a block in bytes.")
parser.add_argument('block1', nargs='?', default=0,
type=lambda x: int(x, 0),
- help="Optional first block address for finding the root.")
+ help="Optional first block address for finding the superblock.")
parser.add_argument('block2', nargs='?', default=1,
type=lambda x: int(x, 0),
- help="Optional second block address for finding the root.")
- parser.add_argument('-t', '--tags', action='store_true',
- help="Show metadata tags instead of reconstructing entries.")
+ help="Optional second block address for finding the superblock.")
parser.add_argument('-l', '--log', action='store_true',
help="Show tags in log.")
parser.add_argument('-a', '--all', action='store_true',
diff --git a/scripts/test.py b/scripts/test.py
index 6187028..e5869c2 100755
--- a/scripts/test.py
+++ b/scripts/test.py
@@ -231,7 +231,7 @@ class TestCase:
ncmd.extend(['-ex', 'r'])
if failure.assert_:
ncmd.extend(['-ex', 'up 2'])
- elif gdb == 'start':
+ elif gdb == 'main':
ncmd.extend([
'-ex', 'b %s:%d' % (self.suite.path, self.code_lineno),
'-ex', 'r'])
@@ -760,7 +760,7 @@ if __name__ == "__main__":
help="Store disk image in a file.")
parser.add_argument('-b', '--build', action='store_true',
help="Only build the tests, do not execute.")
- parser.add_argument('-g', '--gdb', choices=['init', 'start', 'assert'],
+ parser.add_argument('-g', '--gdb', choices=['init', 'main', 'assert'],
nargs='?', const='assert',
help="Drop into gdb on test failure.")
parser.add_argument('--no-internal', action='store_true',