1#!/usr/bin/env python3 2# SPDX-License-Identifier: BSD-2-Clause 3# 4# Copyright (c) 2023, Linaro Limited 5# 6# Converts a ftrace binary file to text. The input file has the following 7# format: 8# 9# <ASCII text> <zero or more nul bytes> FTRACE\x00\x01 <binary data>... 10# 11# <binary data> is an array of 64-bit integers. 12# - When the topmost byte is 0, the entry indicates a function return and the 13# remaining bytes are a duration in nanoseconds. 14# - A non-zero value is a stack depth, indicating a function entry, and the 15# remaining bytes are the function's address. 16 17import sys 18 19 20line = "" 21curr_depth = 0 22 23 24def usage(): 25 print(f"Usage: {sys.argv[0]} ftrace.out") 26 print("Converts a ftrace file to text. Output is written to stdout.") 27 sys.exit(0) 28 29 30def format_time(ns): 31 if ns < 1000000: 32 us = ns / 1000 33 return f"{us:7.3f} us" 34 elif ns < 1000000000: 35 ms = ns / 1000000 36 return f"{ms:7.3f} ms" 37 else: 38 s = ns / 1000000000 39 return f"{s:7.3f} s " 40 41 42def display(depth, val): 43 global line, curr_depth 44 if depth != 0: 45 curr_depth = depth 46 if line != "": 47 line = line.replace("TIME", " " * 10) + " {" 48 print(line) 49 line = "" 50 line = f" TIME | {depth:3} | " + " " * depth + f"0x{val:016x}()" 51 else: 52 if line != "": 53 line = line.replace("TIME", format_time(val)) 54 print(line) 55 line = "" 56 else: 57 if curr_depth != 0: 58 curr_depth = curr_depth - 1 59 print(" " + format_time(val) + f" | {curr_depth:3} | " + 60 " " * curr_depth + "}") 61 62 63def main(): 64 if len(sys.argv) < 2: 65 usage() 66 with open(sys.argv[1], 'rb') as f: 67 s = f.read() 68 magic = s.find(b'FTRACE\x00\x01') 69 if magic == -1: 70 print("Magic not found", file=sys.stderr) 71 sys.exit(1) 72 print(s[:magic].rstrip(b'\x00').decode()) 73 s = s[magic + 8:] 74 for i in range(0, len(s), 8): 75 elem = int.from_bytes(s[i:i + 8], byteorder="little", signed=False) 76 depth = elem >> 56 77 val = elem & 0xFFFFFFFFFFFFFF 78 display(depth, val) 79 80 81if __name__ == "__main__": 82 main() 83