2 # SPDX-License-Identifier: GPL-2.0-only
4 # Copyright (C) 2019-2022 Red Hat, Inc. Daniel Bristot de Oliveira <bristot@kernel.org>
6 # dot2k: transform dot files into a monitor for the Linux kernel.
8 # For further information, see:
9 # Documentation/trace/rv/da_monitor_synthesis.rst
11 from dot2
.dot2c
import Dot2c
16 monitor_types
= { "global" : 1, "per_cpu" : 2, "per_task" : 3 }
17 monitor_templates_dir
= "dot2k/rv_templates/"
18 monitor_type
= "per_cpu"
20 def __init__(self
, file_path
, MonitorType
):
21 super().__init
__(file_path
)
23 self
.monitor_type
= self
.monitor_types
.get(MonitorType
)
24 if self
.monitor_type
== None:
25 raise Exception("Unknown monitor type: %s" % MonitorType
)
27 self
.monitor_type
= MonitorType
28 self
.__fill
_rv
_templates
_dir
()
29 self
.main_c
= self
.__open
_file
(self
.monitor_templates_dir
+ "main_" + MonitorType
+ ".c")
30 self
.enum_suffix
= "_%s" % self
.name
32 def __fill_rv_templates_dir(self
):
34 if os
.path
.exists(self
.monitor_templates_dir
) == True:
37 if platform
.system() != "Linux":
38 raise Exception("I can only run on Linux.")
40 kernel_path
= "/lib/modules/%s/build/tools/verification/dot2/dot2k_templates/" % (platform
.release())
42 if os
.path
.exists(kernel_path
) == True:
43 self
.monitor_templates_dir
= kernel_path
46 if os
.path
.exists("/usr/share/dot2/dot2k_templates/") == True:
47 self
.monitor_templates_dir
= "/usr/share/dot2/dot2k_templates/"
50 raise Exception("Could not find the template directory, do you have the kernel source installed?")
53 def __open_file(self
, path
):
57 raise Exception("Cannot open the file: %s" % path
)
63 def __buff_to_string(self
, buff
):
67 string
= string
+ line
+ "\n"
72 def fill_tracepoint_handlers_skel(self
):
74 for event
in self
.events
:
75 buff
.append("static void handle_%s(void *data, /* XXX: fill header */)" % event
)
77 if self
.monitor_type
== "per_task":
78 buff
.append("\tstruct task_struct *p = /* XXX: how do I get p? */;");
79 buff
.append("\tda_handle_event_%s(p, %s%s);" % (self
.name
, event
, self
.enum_suffix
));
81 buff
.append("\tda_handle_event_%s(%s%s);" % (self
.name
, event
, self
.enum_suffix
));
84 return self
.__buff
_to
_string
(buff
)
86 def fill_tracepoint_attach_probe(self
):
88 for event
in self
.events
:
89 buff
.append("\trv_attach_trace_probe(\"%s\", /* XXX: tracepoint */, handle_%s);" % (self
.name
, event
))
90 return self
.__buff
_to
_string
(buff
)
92 def fill_tracepoint_detach_helper(self
):
94 for event
in self
.events
:
95 buff
.append("\trv_detach_trace_probe(\"%s\", /* XXX: tracepoint */, handle_%s);" % (self
.name
, event
))
96 return self
.__buff
_to
_string
(buff
)
98 def fill_main_c(self
):
100 min_type
= self
.get_minimun_type()
101 nr_events
= self
.events
.__len
__()
102 tracepoint_handlers
= self
.fill_tracepoint_handlers_skel()
103 tracepoint_attach
= self
.fill_tracepoint_attach_probe()
104 tracepoint_detach
= self
.fill_tracepoint_detach_helper()
106 main_c
= main_c
.replace("MIN_TYPE", min_type
)
107 main_c
= main_c
.replace("MODEL_NAME", self
.name
)
108 main_c
= main_c
.replace("NR_EVENTS", str(nr_events
))
109 main_c
= main_c
.replace("TRACEPOINT_HANDLERS_SKEL", tracepoint_handlers
)
110 main_c
= main_c
.replace("TRACEPOINT_ATTACH", tracepoint_attach
)
111 main_c
= main_c
.replace("TRACEPOINT_DETACH", tracepoint_detach
)
115 def fill_model_h_header(self
):
118 buff
.append(" * Automatically generated C representation of %s automaton" % (self
.name
))
119 buff
.append(" * For further information about this format, see kernel documentation:")
120 buff
.append(" * Documentation/trace/rv/deterministic_automata.rst")
126 def fill_model_h(self
):
128 # Adjust the definition names
130 self
.enum_states_def
= "states_%s" % self
.name
131 self
.enum_events_def
= "events_%s" % self
.name
132 self
.struct_automaton_def
= "automaton_%s" % self
.name
133 self
.var_automaton_def
= "automaton_%s" % self
.name
135 buff
= self
.fill_model_h_header()
136 buff
+= self
.format_model()
138 return self
.__buff
_to
_string
(buff
)
140 def __create_directory(self
):
143 except FileExistsError
:
146 print("Fail creating the output dir: %s" % self
.name
)
148 def __create_file(self
, file_name
, content
):
149 path
= "%s/%s" % (self
.name
, file_name
)
151 file = open(path
, 'w')
152 except FileExistsError
:
155 print("Fail creating file: %s" % path
)
161 def __get_main_name(self
):
162 path
= "%s/%s" % (self
.name
, "main.c")
163 if os
.path
.exists(path
) == False:
167 def print_files(self
):
168 main_c
= self
.fill_main_c()
169 model_h
= self
.fill_model_h()
171 self
.__create
_directory
()
173 path
= "%s.c" % self
.name
174 self
.__create
_file
(path
, main_c
)
176 path
= "%s.h" % self
.name
177 self
.__create
_file
(path
, model_h
)