1#!/usr/bin/python3 2# this script is called form stack_report_gen.sh 3from tabulate import tabulate 4from dataclasses import dataclass 5import os, shutil 6import sys 7import gdb 8 9output_file = "build_reports/stack_report.html" 10 11 12def print_summary(d, fkt_name): 13 headers = ["measured function", "Used stack"] 14 with open(output_file, "a") as f: 15 f.write( 16 "<br> The following stack consumption is achieved when uoscore-uedhoc is built with the following flags: " 17 ) 18 f.write(arg_flags) 19 f.write("<br>") 20 f.write(tabulate(d, headers, tablefmt="unsafehtml")) 21 f.write("<br>") 22 23 24def measure_stack_usage_of_function(f): 25 gdb.execute("set pagination off") 26 bp = gdb.Breakpoint(f.fkt_name) 27 28 gdb.execute("run") 29 i = gdb.inferiors()[0] 30 31 measurements = [] 32 33 while True: 34 # Loop through all break points and measure the stack for each function. 35 try: 36 # Here we stop at the beginning of the function that we want to profile. 37 breakpoint_location = gdb.execute("backtrace 2", False, True) 38 sp_start = int(gdb.parse_and_eval("$sp")) 39 print("Starting SP: 0x{:08x}".format(sp_start)) 40 41 stack_bottom = sp_start - f.max_stack_size 42 print("stack_bottom: 0x{:08x}".format(stack_bottom)) 43 44 i = gdb.inferiors()[0] 45 stack_dump_start = i.read_memory(stack_bottom, f.max_stack_size) 46 47 while True: 48 # Step one line until we stepped out of the function. 49 gdb.execute("n") 50 sp = int(gdb.parse_and_eval("$sp")) 51 if sp > sp_start: 52 break 53 54 stack_dump_end = i.read_memory(stack_bottom, f.max_stack_size) 55 56 used_stack_memory = 0 57 for i in range(f.max_stack_size): 58 if ( 59 stack_dump_start.tobytes()[f.max_stack_size - i - 1] 60 != stack_dump_end.tobytes()[f.max_stack_size - i - 1] 61 ): 62 used_stack_memory = i 63 64 print("Stack usage: ", used_stack_memory) 65 print(breakpoint_location) 66 fkt = breakpoint_location.split(" ")[2] 67 print("fkt is: ", fkt) 68 69 caller = breakpoint_location.split("#1")[1].split(" ")[-1:] 70 print("caller is: ", caller) 71 measurements.append([fkt, caller, used_stack_memory]) 72 gdb.execute("c") 73 except gdb.error: 74 # We are here when the program went to its end. 75 break 76 77 gdb.Breakpoint.delete(bp) 78 print_summary(measurements, f.fkt_name) 79 80 81def main(): 82 @dataclass 83 class Function: 84 fkt_name: str 85 max_stack_size: int 86 87 gdb.execute("file " + "build/zephyr/zephyr.elf") 88 89 functions = [ 90 Function("coap2oscore", 1500), 91 Function("oscore2coap", 1500), 92 Function("edhoc_responder_run", 7000), 93 Function("edhoc_initiator_run", 7000), 94 ] 95 for f in functions: 96 measure_stack_usage_of_function(f) 97 98 gdb.execute("q") 99 100 101if __name__ == "__main__": 102 main() 103