1#!/usr/bin/env python3 2# SPDX-License-Identifier: GPL-2.0-only 3# 4# Copyright (C) 2019-2022 Red Hat, Inc. Daniel Bristot de Oliveira <bristot@kernel.org> 5# 6# dot2k: transform dot files into a monitor for the Linux kernel. 7# 8# For further information, see: 9# Documentation/trace/rv/da_monitor_synthesis.rst 10 11from .dot2c import Dot2c 12from .generator import Monitor 13 14 15class dot2k(Monitor, Dot2c): 16 template_dir = "dot2k" 17 18 def __init__(self, file_path, MonitorType, extra_params={}): 19 self.monitor_type = MonitorType 20 Monitor.__init__(self, extra_params) 21 Dot2c.__init__(self, file_path, extra_params.get("model_name")) 22 self.enum_suffix = "_%s" % self.name 23 24 def fill_monitor_type(self) -> str: 25 return self.monitor_type.upper() 26 27 def fill_tracepoint_handlers_skel(self) -> str: 28 buff = [] 29 for event in self.events: 30 buff.append("static void handle_%s(void *data, /* XXX: fill header */)" % event) 31 buff.append("{") 32 handle = "handle_event" 33 if self.is_start_event(event): 34 buff.append("\t/* XXX: validate that this event always leads to the initial state */") 35 handle = "handle_start_event" 36 elif self.is_start_run_event(event): 37 buff.append("\t/* XXX: validate that this event is only valid in the initial state */") 38 handle = "handle_start_run_event" 39 if self.monitor_type == "per_task": 40 buff.append("\tstruct task_struct *p = /* XXX: how do I get p? */;"); 41 buff.append("\tda_%s(p, %s%s);" % (handle, event, self.enum_suffix)); 42 else: 43 buff.append("\tda_%s(%s%s);" % (handle, event, self.enum_suffix)); 44 buff.append("}") 45 buff.append("") 46 return '\n'.join(buff) 47 48 def fill_tracepoint_attach_probe(self) -> str: 49 buff = [] 50 for event in self.events: 51 buff.append("\trv_attach_trace_probe(\"%s\", /* XXX: tracepoint */, handle_%s);" % (self.name, event)) 52 return '\n'.join(buff) 53 54 def fill_tracepoint_detach_helper(self) -> str: 55 buff = [] 56 for event in self.events: 57 buff.append("\trv_detach_trace_probe(\"%s\", /* XXX: tracepoint */, handle_%s);" % (self.name, event)) 58 return '\n'.join(buff) 59 60 def fill_model_h_header(self) -> list[str]: 61 buff = [] 62 buff.append("/* SPDX-License-Identifier: GPL-2.0 */") 63 buff.append("/*") 64 buff.append(" * Automatically generated C representation of %s automaton" % (self.name)) 65 buff.append(" * For further information about this format, see kernel documentation:") 66 buff.append(" * Documentation/trace/rv/deterministic_automata.rst") 67 buff.append(" */") 68 buff.append("") 69 buff.append("#define MONITOR_NAME %s" % (self.name)) 70 buff.append("") 71 72 return buff 73 74 def fill_model_h(self) -> str: 75 # 76 # Adjust the definition names 77 # 78 self.enum_states_def = "states_%s" % self.name 79 self.enum_events_def = "events_%s" % self.name 80 self.struct_automaton_def = "automaton_%s" % self.name 81 self.var_automaton_def = "automaton_%s" % self.name 82 83 buff = self.fill_model_h_header() 84 buff += self.format_model() 85 86 return '\n'.join(buff) 87 88 def fill_monitor_class_type(self) -> str: 89 if self.monitor_type == "per_task": 90 return "DA_MON_EVENTS_ID" 91 return "DA_MON_EVENTS_IMPLICIT" 92 93 def fill_monitor_class(self) -> str: 94 if self.monitor_type == "per_task": 95 return "da_monitor_id" 96 return "da_monitor" 97 98 def fill_tracepoint_args_skel(self, tp_type: str) -> str: 99 buff = [] 100 tp_args_event = [ 101 ("char *", "state"), 102 ("char *", "event"), 103 ("char *", "next_state"), 104 ("bool ", "final_state"), 105 ] 106 tp_args_error = [ 107 ("char *", "state"), 108 ("char *", "event"), 109 ] 110 tp_args_id = ("int ", "id") 111 tp_args = tp_args_event if tp_type == "event" else tp_args_error 112 if self.monitor_type == "per_task": 113 tp_args.insert(0, tp_args_id) 114 tp_proto_c = ", ".join([a+b for a,b in tp_args]) 115 tp_args_c = ", ".join([b for a,b in tp_args]) 116 buff.append(" TP_PROTO(%s)," % tp_proto_c) 117 buff.append(" TP_ARGS(%s)" % tp_args_c) 118 return '\n'.join(buff) 119 120 def fill_main_c(self) -> str: 121 main_c = super().fill_main_c() 122 123 min_type = self.get_minimun_type() 124 nr_events = len(self.events) 125 monitor_type = self.fill_monitor_type() 126 127 main_c = main_c.replace("%%MIN_TYPE%%", min_type) 128 main_c = main_c.replace("%%NR_EVENTS%%", str(nr_events)) 129 main_c = main_c.replace("%%MONITOR_TYPE%%", monitor_type) 130 131 return main_c 132