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