124bce201SDaniel Bristot de Oliveira#!/usr/bin/env python3 224bce201SDaniel Bristot de Oliveira# SPDX-License-Identifier: GPL-2.0-only 324bce201SDaniel Bristot de Oliveira# 424bce201SDaniel Bristot de Oliveira# Copyright (C) 2019-2022 Red Hat, Inc. Daniel Bristot de Oliveira <bristot@kernel.org> 524bce201SDaniel Bristot de Oliveira# 624bce201SDaniel Bristot de Oliveira# dot2k: transform dot files into a monitor for the Linux kernel. 7*d57aff24SDaniel Bristot de Oliveira# 8*d57aff24SDaniel Bristot de Oliveira# For further information, see: 9*d57aff24SDaniel Bristot de Oliveira# Documentation/trace/rv/da_monitor_synthesis.rst 1024bce201SDaniel Bristot de Oliveira 1124bce201SDaniel Bristot de Oliveirafrom dot2.dot2c import Dot2c 1224bce201SDaniel Bristot de Oliveiraimport platform 1324bce201SDaniel Bristot de Oliveiraimport os 1424bce201SDaniel Bristot de Oliveira 1524bce201SDaniel Bristot de Oliveiraclass dot2k(Dot2c): 1624bce201SDaniel Bristot de Oliveira monitor_types = { "global" : 1, "per_cpu" : 2, "per_task" : 3 } 1724bce201SDaniel Bristot de Oliveira monitor_templates_dir = "dot2k/rv_templates/" 1824bce201SDaniel Bristot de Oliveira monitor_type = "per_cpu" 1924bce201SDaniel Bristot de Oliveira 2024bce201SDaniel Bristot de Oliveira def __init__(self, file_path, MonitorType): 2124bce201SDaniel Bristot de Oliveira super().__init__(file_path) 2224bce201SDaniel Bristot de Oliveira 2324bce201SDaniel Bristot de Oliveira self.monitor_type = self.monitor_types.get(MonitorType) 2424bce201SDaniel Bristot de Oliveira if self.monitor_type == None: 2524bce201SDaniel Bristot de Oliveira raise Exception("Unknown monitor type: %s" % MonitorType) 2624bce201SDaniel Bristot de Oliveira 2724bce201SDaniel Bristot de Oliveira self.monitor_type = MonitorType 2824bce201SDaniel Bristot de Oliveira self.__fill_rv_templates_dir() 2924bce201SDaniel Bristot de Oliveira self.main_c = self.__open_file(self.monitor_templates_dir + "main_" + MonitorType + ".c") 3024bce201SDaniel Bristot de Oliveira self.enum_suffix = "_%s" % self.name 3124bce201SDaniel Bristot de Oliveira 3224bce201SDaniel Bristot de Oliveira def __fill_rv_templates_dir(self): 3324bce201SDaniel Bristot de Oliveira 3424bce201SDaniel Bristot de Oliveira if os.path.exists(self.monitor_templates_dir) == True: 3524bce201SDaniel Bristot de Oliveira return 3624bce201SDaniel Bristot de Oliveira 3724bce201SDaniel Bristot de Oliveira if platform.system() != "Linux": 3824bce201SDaniel Bristot de Oliveira raise Exception("I can only run on Linux.") 3924bce201SDaniel Bristot de Oliveira 4024bce201SDaniel Bristot de Oliveira kernel_path = "/lib/modules/%s/build/tools/verification/dot2/dot2k_templates/" % (platform.release()) 4124bce201SDaniel Bristot de Oliveira 4224bce201SDaniel Bristot de Oliveira if os.path.exists(kernel_path) == True: 4324bce201SDaniel Bristot de Oliveira self.monitor_templates_dir = kernel_path 4424bce201SDaniel Bristot de Oliveira return 4524bce201SDaniel Bristot de Oliveira 4624bce201SDaniel Bristot de Oliveira if os.path.exists("/usr/share/dot2/dot2k_templates/") == True: 4724bce201SDaniel Bristot de Oliveira self.monitor_templates_dir = "/usr/share/dot2/dot2k_templates/" 4824bce201SDaniel Bristot de Oliveira return 4924bce201SDaniel Bristot de Oliveira 5024bce201SDaniel Bristot de Oliveira raise Exception("Could not find the template directory, do you have the kernel source installed?") 5124bce201SDaniel Bristot de Oliveira 5224bce201SDaniel Bristot de Oliveira 5324bce201SDaniel Bristot de Oliveira def __open_file(self, path): 5424bce201SDaniel Bristot de Oliveira try: 5524bce201SDaniel Bristot de Oliveira fd = open(path) 5624bce201SDaniel Bristot de Oliveira except OSError: 5724bce201SDaniel Bristot de Oliveira raise Exception("Cannot open the file: %s" % path) 5824bce201SDaniel Bristot de Oliveira 5924bce201SDaniel Bristot de Oliveira content = fd.read() 6024bce201SDaniel Bristot de Oliveira 6124bce201SDaniel Bristot de Oliveira return content 6224bce201SDaniel Bristot de Oliveira 6324bce201SDaniel Bristot de Oliveira def __buff_to_string(self, buff): 6424bce201SDaniel Bristot de Oliveira string = "" 6524bce201SDaniel Bristot de Oliveira 6624bce201SDaniel Bristot de Oliveira for line in buff: 6724bce201SDaniel Bristot de Oliveira string = string + line + "\n" 6824bce201SDaniel Bristot de Oliveira 6924bce201SDaniel Bristot de Oliveira # cut off the last \n 7024bce201SDaniel Bristot de Oliveira return string[:-1] 7124bce201SDaniel Bristot de Oliveira 7224bce201SDaniel Bristot de Oliveira def fill_tracepoint_handlers_skel(self): 7324bce201SDaniel Bristot de Oliveira buff = [] 7424bce201SDaniel Bristot de Oliveira for event in self.events: 7524bce201SDaniel Bristot de Oliveira buff.append("static void handle_%s(void *data, /* XXX: fill header */)" % event) 7624bce201SDaniel Bristot de Oliveira buff.append("{") 7724bce201SDaniel Bristot de Oliveira if self.monitor_type == "per_task": 7824bce201SDaniel Bristot de Oliveira buff.append("\tstruct task_struct *p = /* XXX: how do I get p? */;"); 7924bce201SDaniel Bristot de Oliveira buff.append("\tda_handle_event_%s(p, %s%s);" % (self.name, event, self.enum_suffix)); 8024bce201SDaniel Bristot de Oliveira else: 8124bce201SDaniel Bristot de Oliveira buff.append("\tda_handle_event_%s(%s%s);" % (self.name, event, self.enum_suffix)); 8224bce201SDaniel Bristot de Oliveira buff.append("}") 8324bce201SDaniel Bristot de Oliveira buff.append("") 8424bce201SDaniel Bristot de Oliveira return self.__buff_to_string(buff) 8524bce201SDaniel Bristot de Oliveira 8624bce201SDaniel Bristot de Oliveira def fill_tracepoint_attach_probe(self): 8724bce201SDaniel Bristot de Oliveira buff = [] 8824bce201SDaniel Bristot de Oliveira for event in self.events: 8924bce201SDaniel Bristot de Oliveira buff.append("\trv_attach_trace_probe(\"%s\", /* XXX: tracepoint */, handle_%s);" % (self.name, event)) 9024bce201SDaniel Bristot de Oliveira return self.__buff_to_string(buff) 9124bce201SDaniel Bristot de Oliveira 9224bce201SDaniel Bristot de Oliveira def fill_tracepoint_detach_helper(self): 9324bce201SDaniel Bristot de Oliveira buff = [] 9424bce201SDaniel Bristot de Oliveira for event in self.events: 9524bce201SDaniel Bristot de Oliveira buff.append("\trv_detach_trace_probe(\"%s\", /* XXX: tracepoint */, handle_%s);" % (self.name, event)) 9624bce201SDaniel Bristot de Oliveira return self.__buff_to_string(buff) 9724bce201SDaniel Bristot de Oliveira 9824bce201SDaniel Bristot de Oliveira def fill_main_c(self): 9924bce201SDaniel Bristot de Oliveira main_c = self.main_c 10024bce201SDaniel Bristot de Oliveira min_type = self.get_minimun_type() 10124bce201SDaniel Bristot de Oliveira nr_events = self.events.__len__() 10224bce201SDaniel Bristot de Oliveira tracepoint_handlers = self.fill_tracepoint_handlers_skel() 10324bce201SDaniel Bristot de Oliveira tracepoint_attach = self.fill_tracepoint_attach_probe() 10424bce201SDaniel Bristot de Oliveira tracepoint_detach = self.fill_tracepoint_detach_helper() 10524bce201SDaniel Bristot de Oliveira 10624bce201SDaniel Bristot de Oliveira main_c = main_c.replace("MIN_TYPE", min_type) 10724bce201SDaniel Bristot de Oliveira main_c = main_c.replace("MODEL_NAME", self.name) 10824bce201SDaniel Bristot de Oliveira main_c = main_c.replace("NR_EVENTS", str(nr_events)) 10924bce201SDaniel Bristot de Oliveira main_c = main_c.replace("TRACEPOINT_HANDLERS_SKEL", tracepoint_handlers) 11024bce201SDaniel Bristot de Oliveira main_c = main_c.replace("TRACEPOINT_ATTACH", tracepoint_attach) 11124bce201SDaniel Bristot de Oliveira main_c = main_c.replace("TRACEPOINT_DETACH", tracepoint_detach) 11224bce201SDaniel Bristot de Oliveira 11324bce201SDaniel Bristot de Oliveira return main_c 11424bce201SDaniel Bristot de Oliveira 11524bce201SDaniel Bristot de Oliveira def fill_model_h_header(self): 11624bce201SDaniel Bristot de Oliveira buff = [] 11724bce201SDaniel Bristot de Oliveira buff.append("/*") 11824bce201SDaniel Bristot de Oliveira buff.append(" * Automatically generated C representation of %s automaton" % (self.name)) 11924bce201SDaniel Bristot de Oliveira buff.append(" * For further information about this format, see kernel documentation:") 12024bce201SDaniel Bristot de Oliveira buff.append(" * Documentation/trace/rv/deterministic_automata.rst") 12124bce201SDaniel Bristot de Oliveira buff.append(" */") 12224bce201SDaniel Bristot de Oliveira buff.append("") 12324bce201SDaniel Bristot de Oliveira 12424bce201SDaniel Bristot de Oliveira return buff 12524bce201SDaniel Bristot de Oliveira 12624bce201SDaniel Bristot de Oliveira def fill_model_h(self): 12724bce201SDaniel Bristot de Oliveira # 12824bce201SDaniel Bristot de Oliveira # Adjust the definition names 12924bce201SDaniel Bristot de Oliveira # 13024bce201SDaniel Bristot de Oliveira self.enum_states_def = "states_%s" % self.name 13124bce201SDaniel Bristot de Oliveira self.enum_events_def = "events_%s" % self.name 13224bce201SDaniel Bristot de Oliveira self.struct_automaton_def = "automaton_%s" % self.name 13324bce201SDaniel Bristot de Oliveira self.var_automaton_def = "automaton_%s" % self.name 13424bce201SDaniel Bristot de Oliveira 13524bce201SDaniel Bristot de Oliveira buff = self.fill_model_h_header() 13624bce201SDaniel Bristot de Oliveira buff += self.format_model() 13724bce201SDaniel Bristot de Oliveira 13824bce201SDaniel Bristot de Oliveira return self.__buff_to_string(buff) 13924bce201SDaniel Bristot de Oliveira 14024bce201SDaniel Bristot de Oliveira def __create_directory(self): 14124bce201SDaniel Bristot de Oliveira try: 14224bce201SDaniel Bristot de Oliveira os.mkdir(self.name) 14324bce201SDaniel Bristot de Oliveira except FileExistsError: 14424bce201SDaniel Bristot de Oliveira return 14524bce201SDaniel Bristot de Oliveira except: 14624bce201SDaniel Bristot de Oliveira print("Fail creating the output dir: %s" % self.name) 14724bce201SDaniel Bristot de Oliveira 14824bce201SDaniel Bristot de Oliveira def __create_file(self, file_name, content): 14924bce201SDaniel Bristot de Oliveira path = "%s/%s" % (self.name, file_name) 15024bce201SDaniel Bristot de Oliveira try: 15124bce201SDaniel Bristot de Oliveira file = open(path, 'w') 15224bce201SDaniel Bristot de Oliveira except FileExistsError: 15324bce201SDaniel Bristot de Oliveira return 15424bce201SDaniel Bristot de Oliveira except: 15524bce201SDaniel Bristot de Oliveira print("Fail creating file: %s" % path) 15624bce201SDaniel Bristot de Oliveira 15724bce201SDaniel Bristot de Oliveira file.write(content) 15824bce201SDaniel Bristot de Oliveira 15924bce201SDaniel Bristot de Oliveira file.close() 16024bce201SDaniel Bristot de Oliveira 16124bce201SDaniel Bristot de Oliveira def __get_main_name(self): 16224bce201SDaniel Bristot de Oliveira path = "%s/%s" % (self.name, "main.c") 16324bce201SDaniel Bristot de Oliveira if os.path.exists(path) == False: 16424bce201SDaniel Bristot de Oliveira return "main.c" 16524bce201SDaniel Bristot de Oliveira return "__main.c" 16624bce201SDaniel Bristot de Oliveira 16724bce201SDaniel Bristot de Oliveira def print_files(self): 16824bce201SDaniel Bristot de Oliveira main_c = self.fill_main_c() 16924bce201SDaniel Bristot de Oliveira model_h = self.fill_model_h() 17024bce201SDaniel Bristot de Oliveira 17124bce201SDaniel Bristot de Oliveira self.__create_directory() 17224bce201SDaniel Bristot de Oliveira 17324bce201SDaniel Bristot de Oliveira path = "%s.c" % self.name 17424bce201SDaniel Bristot de Oliveira self.__create_file(path, main_c) 17524bce201SDaniel Bristot de Oliveira 17624bce201SDaniel Bristot de Oliveira path = "%s.h" % self.name 17724bce201SDaniel Bristot de Oliveira self.__create_file(path, model_h) 178