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): 25 return self.monitor_type.upper() 26 27 def fill_tracepoint_handlers_skel(self): 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_%s(p, %s%s);" % (handle, self.name, event, self.enum_suffix)); 42 else: 43 buff.append("\tda_%s_%s(%s%s);" % (handle, self.name, event, self.enum_suffix)); 44 buff.append("}") 45 buff.append("") 46 return '\n'.join(buff) 47 48 def fill_tracepoint_attach_probe(self): 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): 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): 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 70 return buff 71 72 def fill_model_h(self): 73 # 74 # Adjust the definition names 75 # 76 self.enum_states_def = "states_%s" % self.name 77 self.enum_events_def = "events_%s" % self.name 78 self.struct_automaton_def = "automaton_%s" % self.name 79 self.var_automaton_def = "automaton_%s" % self.name 80 81 buff = self.fill_model_h_header() 82 buff += self.format_model() 83 84 return '\n'.join(buff) 85 86 def fill_monitor_class_type(self): 87 if self.monitor_type == "per_task": 88 return "DA_MON_EVENTS_ID" 89 return "DA_MON_EVENTS_IMPLICIT" 90 91 def fill_monitor_class(self): 92 if self.monitor_type == "per_task": 93 return "da_monitor_id" 94 return "da_monitor" 95 96 def fill_tracepoint_args_skel(self, tp_type): 97 buff = [] 98 tp_args_event = [ 99 ("char *", "state"), 100 ("char *", "event"), 101 ("char *", "next_state"), 102 ("bool ", "final_state"), 103 ] 104 tp_args_error = [ 105 ("char *", "state"), 106 ("char *", "event"), 107 ] 108 tp_args_id = ("int ", "id") 109 tp_args = tp_args_event if tp_type == "event" else tp_args_error 110 if self.monitor_type == "per_task": 111 tp_args.insert(0, tp_args_id) 112 tp_proto_c = ", ".join([a+b for a,b in tp_args]) 113 tp_args_c = ", ".join([b for a,b in tp_args]) 114 buff.append(" TP_PROTO(%s)," % tp_proto_c) 115 buff.append(" TP_ARGS(%s)" % tp_args_c) 116 return '\n'.join(buff) 117 118 def fill_main_c(self): 119 main_c = super().fill_main_c() 120 121 min_type = self.get_minimun_type() 122 nr_events = len(self.events) 123 monitor_type = self.fill_monitor_type() 124 125 main_c = main_c.replace("%%MIN_TYPE%%", min_type) 126 main_c = main_c.replace("%%NR_EVENTS%%", str(nr_events)) 127 main_c = main_c.replace("%%MONITOR_TYPE%%", monitor_type) 128 129 return main_c 130