blob: b1f16c4636d9117ad3fc638a6ddf75257a7ab217 [file] [log] [blame]
#!/usr/bin/env python3
# SPDX-License-Identifier: BSD-2-Clause
#
# Copyright (c) 2023, Linaro Limited
#
# Converts a ftrace binary file to text. The input file has the following
# format:
#
# <ASCII text> <zero or more nul bytes> FTRACE\x00\x01 <binary data>...
#
# <binary data> is an array of 64-bit integers.
# - When the topmost byte is 0, the entry indicates a function return and the
# remaining bytes are a duration in nanoseconds.
# - A non-zero value is a stack depth, indicating a function entry, and the
# remaining bytes are the function's address.
import sys
line = ""
curr_depth = 0
def usage():
print(f"Usage: {sys.argv[0]} ftrace.out")
print("Converts a ftrace file to text. Output is written to stdout.")
sys.exit(0)
def format_time(ns):
if ns < 1000000:
us = ns / 1000
return f"{us:7.3f} us"
elif ns < 1000000000:
ms = ns / 1000000
return f"{ms:7.3f} ms"
else:
s = ns / 1000000000
return f"{s:7.3f} s "
def display(depth, val):
global line, curr_depth
if depth != 0:
curr_depth = depth
if line != "":
line = line.replace("TIME", " " * 10) + " {"
print(line)
line = ""
line = f" TIME | {depth:3} | " + " " * depth + f"0x{val:016x}()"
else:
if line != "":
line = line.replace("TIME", format_time(val))
print(line)
line = ""
else:
if curr_depth != 0:
curr_depth = curr_depth - 1
print(" " + format_time(val) + f" | {curr_depth:3} | " +
" " * curr_depth + "}")
def main():
if len(sys.argv) < 2:
usage()
with open(sys.argv[1], 'rb') as f:
s = f.read()
magic = s.find(b'FTRACE\x00\x01')
if magic == -1:
print("Magic not found", file=sys.stderr)
sys.exit(1)
print(s[:magic].rstrip(b'\x00').decode())
s = s[magic + 8:]
for i in range(0, len(s), 8):
elem = int.from_bytes(s[i:i + 8], byteorder="little", signed=False)
depth = elem >> 56
val = elem & 0xFFFFFFFFFFFFFF
display(depth, val)
if __name__ == "__main__":
main()