Skip to content

Commit de6f45c

Browse files
glemcorostedt
authored andcommitted
verification/dot2k: Auto patch current kernel source
dot2k suggests a list of changes to the kernel tree while adding a monitor: edit tracepoints header, Makefile, Kconfig and moving the monitor folder. Those changes can be easily run automatically. Add a flag to dot2k to alter the kernel source. The kernel source directory can be either assumed from the PWD, or from the running kernel, if installed. This feature works best if the kernel tree is a git repository, so that its easier to make sure there are no unintended changes. The main RV files (e.g. Makefile) have now a comment placeholder that can be useful for manual editing (e.g. to know where to add new monitors) and it is used by the script to append the required lines. We also slightly adapt the file handling functions in dot2k: __open_file is now called __read_file and also closes the file before returning the content; __create_file is now a more general __write_file, we no longer return on FileExistsError (not thrown while opening), a new __create_file simply calls __write_file specifying the monitor folder in the path. Cc: Juri Lelli <[email protected]> Cc: Thomas Gleixner <[email protected]> Cc: John Kacur <[email protected]> Link: https://lore.kernel.org/[email protected] Signed-off-by: Gabriele Monaco <[email protected]> Signed-off-by: Steven Rostedt (Google) <[email protected]>
1 parent 9c6cfe8 commit de6f45c

File tree

5 files changed

+86
-16
lines changed

5 files changed

+86
-16
lines changed

kernel/trace/rv/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ menuconfig RV
2626
Documentation/trace/rv/runtime-verification.rst
2727

2828
source "kernel/trace/rv/monitors/wip/Kconfig"
29-
3029
source "kernel/trace/rv/monitors/wwnr/Kconfig"
30+
# Add new monitors here
3131

3232
config RV_REACTORS
3333
bool "Runtime verification reactors"

kernel/trace/rv/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ ccflags-y += -I $(src) # needed for trace events
55
obj-$(CONFIG_RV) += rv.o
66
obj-$(CONFIG_RV_MON_WIP) += monitors/wip/wip.o
77
obj-$(CONFIG_RV_MON_WWNR) += monitors/wwnr/wwnr.o
8+
# Add new monitors here
89
obj-$(CONFIG_RV_REACTORS) += rv_reactors.o
910
obj-$(CONFIG_RV_REACT_PRINTK) += reactor_printk.o
1011
obj-$(CONFIG_RV_REACT_PANIC) += reactor_panic.o

kernel/trace/rv/rv_trace.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ DECLARE_EVENT_CLASS(error_da_monitor,
5858
);
5959

6060
#include <monitors/wip/wip_trace.h>
61+
// Add new monitors based on CONFIG_DA_MON_EVENTS_IMPLICIT here
6162

6263
#endif /* CONFIG_DA_MON_EVENTS_IMPLICIT */
6364

@@ -117,6 +118,7 @@ DECLARE_EVENT_CLASS(error_da_monitor_id,
117118
);
118119

119120
#include <monitors/wwnr/wwnr_trace.h>
121+
// Add new monitors based on CONFIG_DA_MON_EVENTS_ID here
120122

121123
#endif /* CONFIG_DA_MON_EVENTS_ID */
122124
#endif /* _TRACE_RV_H */

tools/verification/dot2/dot2k

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ if __name__ == '__main__':
2121
parser.add_argument('-t', "--monitor_type", dest="monitor_type", required=True)
2222
parser.add_argument('-n', "--model_name", dest="model_name", required=False)
2323
parser.add_argument("-D", "--description", dest="description", required=False)
24+
parser.add_argument("-a", "--auto_patch", dest="auto_patch",
25+
action="store_true", required=False,
26+
help="Patch the kernel in place")
2427
params = parser.parse_args()
2528

2629
print("Opening and parsing the dot file %s" % params.dot_file)
@@ -38,4 +41,4 @@ if __name__ == '__main__':
3841
print(monitor.fill_tracepoint_tooltip())
3942
print(monitor.fill_makefile_tooltip())
4043
print(monitor.fill_kconfig_tooltip())
41-
print(" - Move %s/ to the kernel's monitor directory (%s/monitors)" % (monitor.name, monitor.rv_dir))
44+
print(monitor.fill_monitor_tooltip())

tools/verification/dot2/dot2k.py

Lines changed: 78 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,19 +27,22 @@ def __init__(self, file_path, MonitorType, extra_params={}):
2727

2828
self.monitor_type = MonitorType
2929
self.__fill_rv_templates_dir()
30-
self.main_c = self.__open_file(self.monitor_templates_dir + "main.c")
31-
self.trace_h = self.__open_file(self.monitor_templates_dir + "trace.h")
32-
self.kconfig = self.__open_file(self.monitor_templates_dir + "Kconfig")
30+
self.main_c = self.__read_file(self.monitor_templates_dir + "main.c")
31+
self.trace_h = self.__read_file(self.monitor_templates_dir + "trace.h")
32+
self.kconfig = self.__read_file(self.monitor_templates_dir + "Kconfig")
3333
self.enum_suffix = "_%s" % self.name
3434
self.description = extra_params.get("description", self.name) or "auto-generated"
35+
self.auto_patch = extra_params.get("auto_patch")
36+
if self.auto_patch:
37+
self.__fill_rv_kernel_dir()
3538

3639
def __fill_rv_templates_dir(self):
3740

3841
if os.path.exists(self.monitor_templates_dir):
3942
return
4043

4144
if platform.system() != "Linux":
42-
raise Exception("I can only run on Linux.")
45+
raise OSError("I can only run on Linux.")
4346

4447
kernel_path = "/lib/modules/%s/build/tools/verification/dot2/dot2k_templates/" % (platform.release())
4548

@@ -51,17 +54,43 @@ def __fill_rv_templates_dir(self):
5154
self.monitor_templates_dir = "/usr/share/dot2/dot2k_templates/"
5255
return
5356

54-
raise Exception("Could not find the template directory, do you have the kernel source installed?")
57+
raise FileNotFoundError("Could not find the template directory, do you have the kernel source installed?")
5558

59+
def __fill_rv_kernel_dir(self):
5660

57-
def __open_file(self, path):
61+
# first try if we are running in the kernel tree root
62+
if os.path.exists(self.rv_dir):
63+
return
64+
65+
# offset if we are running inside the kernel tree from verification/dot2
66+
kernel_path = os.path.join("../..", self.rv_dir)
67+
68+
if os.path.exists(kernel_path):
69+
self.rv_dir = kernel_path
70+
return
71+
72+
if platform.system() != "Linux":
73+
raise OSError("I can only run on Linux.")
74+
75+
kernel_path = os.path.join("/lib/modules/%s/build" % platform.release(), self.rv_dir)
76+
77+
# if the current kernel is from a distro this may not be a full kernel tree
78+
# verify that one of the files we are going to modify is available
79+
if os.path.exists(os.path.join(kernel_path, "rv_trace.h")):
80+
self.rv_dir = kernel_path
81+
return
82+
83+
raise FileNotFoundError("Could not find the rv directory, do you have the kernel source installed?")
84+
85+
def __read_file(self, path):
5886
try:
59-
fd = open(path)
87+
fd = open(path, 'r')
6088
except OSError:
6189
raise Exception("Cannot open the file: %s" % path)
6290

6391
content = fd.read()
6492

93+
fd.close()
6594
return content
6695

6796
def __buff_to_string(self, buff):
@@ -202,14 +231,32 @@ def fill_kconfig(self):
202231
kconfig = kconfig.replace("%%DESCRIPTION%%", self.description)
203232
return kconfig
204233

234+
def __patch_file(self, file, marker, line):
235+
file_to_patch = os.path.join(self.rv_dir, file)
236+
content = self.__read_file(file_to_patch)
237+
content = content.replace(marker, line + "\n" + marker)
238+
self.__write_file(file_to_patch, content)
239+
205240
def fill_tracepoint_tooltip(self):
206241
monitor_class_type = self.fill_monitor_class_type()
242+
if self.auto_patch:
243+
self.__patch_file("rv_trace.h",
244+
"// Add new monitors based on CONFIG_%s here" % monitor_class_type,
245+
"#include <monitors/%s/%s_trace.h>" % (self.name, self.name))
246+
return " - Patching %s/rv_trace.h, double check the result" % self.rv_dir
247+
207248
return """ - Edit %s/rv_trace.h:
208249
Add this line where other tracepoints are included and %s is defined:
209250
#include <monitors/%s/%s_trace.h>
210251
""" % (self.rv_dir, monitor_class_type, self.name, self.name)
211252

212253
def fill_kconfig_tooltip(self):
254+
if self.auto_patch:
255+
self.__patch_file("Kconfig",
256+
"# Add new monitors here",
257+
"source \"kernel/trace/rv/monitors/%s/Kconfig\"" % (self.name))
258+
return " - Patching %s/Kconfig, double check the result" % self.rv_dir
259+
213260
return """ - Edit %s/Kconfig:
214261
Add this line where other monitors are included:
215262
source \"kernel/trace/rv/monitors/%s/Kconfig\"
@@ -218,32 +265,49 @@ def fill_kconfig_tooltip(self):
218265
def fill_makefile_tooltip(self):
219266
name = self.name
220267
name_up = name.upper()
268+
if self.auto_patch:
269+
self.__patch_file("Makefile",
270+
"# Add new monitors here",
271+
"obj-$(CONFIG_RV_MON_%s) += monitors/%s/%s.o" % (name_up, name, name))
272+
return " - Patching %s/Makefile, double check the result" % self.rv_dir
273+
221274
return """ - Edit %s/Makefile:
222275
Add this line where other monitors are included:
223276
obj-$(CONFIG_RV_MON_%s) += monitors/%s/%s.o
224277
""" % (self.rv_dir, name_up, name, name)
225278

279+
def fill_monitor_tooltip(self):
280+
if self.auto_patch:
281+
return " - Monitor created in %s/monitors/%s" % (self.rv_dir, self. name)
282+
return " - Move %s/ to the kernel's monitor directory (%s/monitors)" % (self.name, self.rv_dir)
283+
226284
def __create_directory(self):
285+
path = self.name
286+
if self.auto_patch:
287+
path = os.path.join(self.rv_dir, "monitors", path)
227288
try:
228-
os.mkdir(self.name)
289+
os.mkdir(path)
229290
except FileExistsError:
230291
return
231292
except:
232293
print("Fail creating the output dir: %s" % self.name)
233294

234-
def __create_file(self, file_name, content):
235-
path = "%s/%s" % (self.name, file_name)
295+
def __write_file(self, file_name, content):
236296
try:
237-
file = open(path, 'w')
238-
except FileExistsError:
239-
return
297+
file = open(file_name, 'w')
240298
except:
241-
print("Fail creating file: %s" % path)
299+
print("Fail writing to file: %s" % file_name)
242300

243301
file.write(content)
244302

245303
file.close()
246304

305+
def __create_file(self, file_name, content):
306+
path = "%s/%s" % (self.name, file_name)
307+
if self.auto_patch:
308+
path = os.path.join(self.rv_dir, "monitors", path)
309+
self.__write_file(path, content)
310+
247311
def __get_main_name(self):
248312
path = "%s/%s" % (self.name, "main.c")
249313
if not os.path.exists(path):

0 commit comments

Comments
 (0)