commit 601f42667bb4b969a0d85090c28c53c445681b20 from: Matthias L. Jugel date: Tue Jan 15 13:15:18 2019 UTC add some colorization and a heap dump commit - b335c8c7de73dfe3caeb88f91f8b3bc895c19497 commit + 601f42667bb4b969a0d85090c28c53c445681b20 blob - 4f35c1a0516289063bdbcaedce3d6a2f12a91bbb blob + d7a7cf1684f1ec2a66b6292cd77dbd72d16160c7 --- memtrace_calliope_trns.py +++ memtrace_calliope_trns.py @@ -22,16 +22,21 @@ from serial.tools.miniterm import Transform def debug(s): sys.stderr.write("D "+repr(s)+"\r\n") + class CalliopeDebugTransform(Transform): mem = {} + max = 0 allocated = 0 reset = None buffer = "" def __init__(self): self.r_malloc = re.compile("(?:microbit_)?malloc:\s+(?:NATIVE\s+)?(?:ALLOCATED:)\s+(\d+)\s+\[(0x[0-9a-f]+)\]") - self.r_free = re.compile("^(?:microbit_)?free:\\s+(0x[0-9a-f]+)") - self.r_heap_size = re.compile("^mb_total_free : (\d+)") + self.r_free = re.compile("^(?:microbit_)?free:\\s+((0x)?[0-9a-f]+)") + self.r_heap_start = re.compile("^heap_start\s+:\s+(0x[0-9a-f]+)") + self.r_heap_end = re.compile("^heap_end\s+:\s+(0x[0-9a-f]+)") + self.r_heap_size = re.compile("^heap_size\s+:\s+(\d+)") + self.r_oom = re.compile("^malloc:\s+OUT OF MEMORY\s+\[(\d+)\]") def rx(self, rx_input): # collect lines @@ -49,6 +54,12 @@ class CalliopeDebugTransform(Transform): continue return out + + def colorize(self, free): + if free > self.max/2: return "4" + elif free > self.max/3: return "5" + return "1" + def trace_line(self, line): # strip newline and carriage return line = line.rstrip('\n').rstrip('\r') @@ -59,9 +70,19 @@ class CalliopeDebugTransform(Transform): self.mem = {} self.allocated = 0 line += "\r\n\r\n\033[91m>> RESET HEAP COUNTERS >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\033[0m\r\n" - line += "\033[4m (NUM) TOTAL [ ADDRESS] CHANGE (COMMENT)\033[0m\r\n" + line += "\033[4m (NUM) FREE [ ADDRESS] CHANGE (COMMENT)\033[0m\r\n" return line + m = self.r_heap_start.search(line) + if m: + self.heap_start = int(m.group(1), 16) + return line + "\r\n" + + m = self.r_heap_end.search(line) + if m: + self.heap_end = int(m.group(1), 16) + return line + "\r\n" + # match malloc, realloc and free m = self.r_malloc.search(line) if m: @@ -69,25 +90,56 @@ class CalliopeDebugTransform(Transform): if m.group(2) == "0": out += "\033[1m!! (%03d) \033[31mmalloc failed\033[0m (%s)\r\n" % (len(self.mem), line) else: - self.mem[m.group(2)] = int(m.group(1)) + addr = int(m.group(2), 16) + self.mem[addr] = int(m.group(1)) self.allocated += int(m.group(1)) - out += "\033[1m== (%03d) \033[34m%8d\033[0m [%8x] \033[31m+%-6d\033[0m (%s)\r\n" % \ - (len(self.mem), self.allocated, int(m.group(2), 16), int(m.group(1)), line) + free = self.max - self.allocated + out += "\033[1m== (%03d) \033[3%sm%8d\033[0m [%8x] \033[31m+%-6d\033[0m (%s)\r\n" % \ + (len(self.mem), self.colorize(free), free, addr, int(m.group(1)), line) return out m = self.r_free.search(line) if m: out = "" + addr = 0 freed = 0 if m.group(1) in self.mem: - freed = self.mem[m.group(1)] + addr = int(m.group(1), 16) + freed = self.mem[addr] self.allocated -= freed - del self.mem[m.group(1)] + del self.mem[addr] else: - out += "\033[33m!! (%03d) WARN: free(0x%s)\033[0m\r\n" % (len(self.mem), m.group(4)) - out += "\033[1m== (%03d) \033[34m%8d\033[0m [%8x] \033[92m-%-6d\033[0m (%s)\r\n" % \ - (len(self.mem), self.allocated, int(m.group(1), 16), freed, line) + out += "\033[33m!! (%03d) WARN: free(0x%s)\033[0m\r\n" % (len(self.mem), m.group(1)) + + free = self.max - self.allocated + out += "\033[1m== (%03d) \033[3%sm%8d\033[0m [%8x] \033[92m-%-6d\033[0m (%s)\r\n" % \ + (len(self.mem), self.colorize(free), free, addr, freed, line) return out + m = self.r_oom.search(line) + if m: + out = "" + wanted = int(m.group(1)) + out += "\033[31m!! (%03d) : malloc(): no free block of size %d\033[0m\r\n" % (len(self.mem), wanted) + + out += "HEAP ALLOCATION:\r\n" + + mem = "" + end = 0 + for addr in range(self.heap_start, self.heap_end): + if addr in self.mem: + end = addr + self.mem[addr] + if addr == end: + end = 0 + if end: + mem += "*" + else: + mem += "." + + for a in range(0, self.max, 64): + out += "%06d %08x %s\r\n" % (a, self.heap_start + a, mem[a:a+64]) + + return out + # print all other lines as is, so we can still use the log functionality return line + "\r\n"