From d60a33fa9d376b9e7e93e9135af0c4a37bd1113d Mon Sep 17 00:00:00 2001 From: Douglas Raillard Date: Thu, 6 Mar 2025 12:25:44 +0000 Subject: [PATCH] lisa._assets.kmodules.lisa.introspect_header: Support tracepoint vtables FEATURE Support tracepoint vtable types that refer to kernel private in their getters, so that the generated C code from BTF only contains forward declarations to those types rather than a full dump of them. This allows getters to use public types, which could otherwise not be dumped under their original names as it would conflict with the definition available in public headers. Dumping them under a modified name is possible but breaks CFI, as CFI check relies on each types having the same name both on the caller and callee sides. --- .../kmodules/lisa/introspect_header.py | 55 ++++++++++++++++++- lisa/_assets/kmodules/lisa/introspection.json | 3 + 2 files changed, 55 insertions(+), 3 deletions(-) diff --git a/lisa/_assets/kmodules/lisa/introspect_header.py b/lisa/_assets/kmodules/lisa/introspect_header.py index c173fb1e9..6654a0b02 100755 --- a/lisa/_assets/kmodules/lisa/introspect_header.py +++ b/lisa/_assets/kmodules/lisa/introspect_header.py @@ -30,7 +30,7 @@ import re import lisa._btf as btf -def process_btf(out, path, introspect, internal_type_prefix, define_typ_names): +def process_btf(out, path, introspect, internal_type_prefix, define_typ_names, define_tp_vtable): internal_type_prefix = internal_type_prefix or '' with open(path, 'rb') as f: data = f.read() @@ -131,8 +131,50 @@ def process_btf(out, path, introspect, internal_type_prefix, define_typ_names): if isinstance(typ, named_classes) and typ.name: typ.name = rename_internal_typ(typ) + if define_tp_vtable: + def process_typ(typ): + if isinstance(typ, btf.BTFPtr) and isinstance(typ.typ, btf.BTFStruct): + typ.typ = btf._LinkedForwardDecl(typ.typ) + + return typ + + def process_param(param): + typ = param.typ + param.typ = process_typ(typ) + return param + + def process_member(member): + typ = member.typ + if isinstance(typ, btf.BTFPtr) and isinstance(typ.typ, btf.BTFFuncProto): + proto = typ.typ + # Process each parameter of the function + for param in proto.params: + process_param(param) + # Also process the return type of the function + proto.typ = process_typ(proto.typ) + return member + + def process_vtable(typ): + for member in typ.members: + process_member(member) + return typ + + def select(typ): + if isinstance(typ, btf.BTFStruct): + return typ.name in define_tp_vtable + else: + return False + + vtable_typs = set(filter(select, typs)) + for vtable_typ in vtable_typs: + process_vtable(vtable_typ) + else: + vtable_typs = set() + + to_dump = reachable_typs | vtable_typs + # Dump declaration for all the types we are interested in - btf.dump_c(reachable_typs, fileobj=out, introspection=False, decls=True) + btf.dump_c(to_dump, fileobj=out, introspection=False, decls=True) def is_exported_symbol(code): @@ -280,7 +322,14 @@ def main(): try: if args.btf: - process_btf(out, args.btf, args.introspect, args.internal_type_prefix, conf.get('btf-types', [])) + process_btf( + out=out, + path=args.btf, + introspect=args.introspect, + internal_type_prefix=args.internal_type_prefix, + define_typ_names=conf.get('btf-types', []), + define_tp_vtable=conf.get('tracepoint-vtables'), + ) if args.kallsyms and args.introspect: dump_records(process_kallsyms_introspection(args.kallsyms)) diff --git a/lisa/_assets/kmodules/lisa/introspection.json b/lisa/_assets/kmodules/lisa/introspection.json index b3fc671f8..e1f32b6e6 100644 --- a/lisa/_assets/kmodules/lisa/introspection.json +++ b/lisa/_assets/kmodules/lisa/introspection.json @@ -6,6 +6,9 @@ "task_group", "autogroup" ], + "tracepoint-vtables": [ + "trace_probe_callbacks" + ], "kernel-features": { "RQ_CAPACITY": "HAS_MEMBER(struct, rq, cpu_capacity)", "RQ_NR_RUNNING": "HAS_MEMBER(struct, rq, nr_running)", -- GitLab