support for event groups

This commit is contained in:
Vern Paxson 2025-09-13 08:02:12 -07:00
parent 3b37eb4b3a
commit 0a7256994a
9 changed files with 85 additions and 14 deletions

View file

@ -1,5 +1,6 @@
// See the file "COPYING" in the main distribution directory for copyright. // See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/EventRegistry.h"
#include "zeek/script_opt/CPP/Compile.h" #include "zeek/script_opt/CPP/Compile.h"
namespace zeek::detail { namespace zeek::detail {
@ -15,8 +16,9 @@ void CPPCompile::DeclareFunc(const FuncInfo& func) {
auto f = func.Func(); auto f = func.Func();
const auto& body = func.Body(); const auto& body = func.Body();
auto priority = func.Priority(); auto priority = func.Priority();
const auto& e_g = func.EventGroups();
CreateFunction(f->GetType(), pf, fname, body, priority, nullptr, f->Flavor()); CreateFunction(f->GetType(), pf, fname, body, priority, nullptr, f->Flavor(), &e_g);
if ( f->GetBodies().size() == 1 ) if ( f->GetBodies().size() == 1 )
compiled_simple_funcs[f->GetName()] = fname; compiled_simple_funcs[f->GetName()] = fname;
@ -42,7 +44,8 @@ void CPPCompile::DeclareLambda(const LambdaExpr* l, const ProfileFunc* pf) {
} }
void CPPCompile::CreateFunction(const FuncTypePtr& ft, const ProfileFunc* pf, const string& fname, const StmtPtr& body, void CPPCompile::CreateFunction(const FuncTypePtr& ft, const ProfileFunc* pf, const string& fname, const StmtPtr& body,
int priority, const LambdaExpr* l, FunctionFlavor flavor) { int priority, const LambdaExpr* l, FunctionFlavor flavor,
const std::forward_list<EventGroupPtr>* e_g) {
const auto& yt = ft->Yield(); const auto& yt = ft->Yield();
in_hook = flavor == FUNC_FLAVOR_HOOK; in_hook = flavor == FUNC_FLAVOR_HOOK;
@ -103,7 +106,29 @@ void CPPCompile::CreateFunction(const FuncTypePtr& ft, const ProfileFunc* pf, co
compiled_funcs.emplace(fname); compiled_funcs.emplace(fname);
} }
body_info[fname] = {.hash = pf->HashVal(), .priority = priority, .loc = body->GetLocationInfo()}; string module_group;
vector<string> attr_groups;
if ( e_g )
for ( auto g : *e_g ) {
const auto& name = g->GetName();
if ( g->GetEventGroupKind() == EventGroupKind::Module ) {
if ( module_group.empty() )
module_group = g->GetName();
else {
ASSERT(module_group == name);
}
}
else
attr_groups.push_back(name);
}
body_info[fname] = {.hash = pf->HashVal(),
.priority = priority,
.loc = body->GetLocationInfo(),
.module = module_group,
.groups = std::move(attr_groups)};
body_names.emplace(body.get(), fname); body_names.emplace(body.get(), fname);
} }

View file

@ -32,7 +32,8 @@ void DeclareLambda(const LambdaExpr* l, const ProfileFunc* pf);
// dynamic casting approach, which only requires one additional class. // dynamic casting approach, which only requires one additional class.
void CreateFunction(const FuncTypePtr& ft, const ProfileFunc* pf, const std::string& fname, const StmtPtr& body, void CreateFunction(const FuncTypePtr& ft, const ProfileFunc* pf, const std::string& fname, const StmtPtr& body,
int priority, const LambdaExpr* l, FunctionFlavor flavor); int priority, const LambdaExpr* l, FunctionFlavor flavor,
const std::forward_list<EventGroupPtr>* e_g = nullptr);
// Used for the case of creating a custom subclass of CPPStmt. // Used for the case of creating a custom subclass of CPPStmt.
void DeclareSubclass(const FuncTypePtr& ft, const ProfileFunc* pf, const std::string& fname, const std::string& args, void DeclareSubclass(const FuncTypePtr& ft, const ProfileFunc* pf, const std::string& fname, const std::string& args,

View file

@ -383,10 +383,18 @@ void CPPCompile::RegisterCompiledBody(const string& f) {
auto h = bi.hash; auto h = bi.hash;
auto p = bi.priority; auto p = bi.priority;
auto loc = bi.loc; auto loc = bi.loc;
auto body_info = Fmt(p) + ", " + Fmt(h) + ", \"" + loc->FileName() + " (C++)\", " + Fmt(loc->FirstLine()); auto body_info = Fmt(p) + ", " + Fmt(h) + ", \"" + loc->FileName() + " (C++)\", " + Fmt(loc->FirstLine());
Emit("\tCPP_RegisterBody(\"%s\", (void*) %s, %s, %s, std::vector<std::string>(%s)),", f, f, Fmt(type_signature), string module_group = "\"" + bi.module + "\"";
body_info, events);
string attr_groups = "{";
for ( const auto& g : bi.groups )
attr_groups += " \"" + g + "\",";
attr_groups += " }";
Emit("\tCPP_RegisterBody(\"%s\", (void*) %s, %s, %s, std::vector<std::string>(%s), %s, %s),", f, f,
Fmt(type_signature), body_info, events, module_group, attr_groups);
} }
void CPPCompile::GenEpilog() { void CPPCompile::GenEpilog() {
@ -570,8 +578,12 @@ void CPPCompile::GenRegisterBodies() {
"auto f = make_intrusive<CPPDynStmt>(b.func_name.c_str(), b.func, b.type_signature, " "auto f = make_intrusive<CPPDynStmt>(b.func_name.c_str(), b.func, b.type_signature, "
"b.filename, b.line_num);"); "b.filename, b.line_num);");
auto reg = standalone ? "register_standalone_body" : "register_body"; if ( standalone )
Emit("%s__CPP(f, b.priority, b.h, b.events, finish_init__CPP);", reg); Emit(
"register_standalone_body__CPP(f, b.priority, b.h, b.events, b.module_group, b.attr_groups, "
"finish_init__CPP);");
else
Emit("register_body__CPP(f, b.priority, b.h, b.events, finish_init__CPP);");
EndBlock(); EndBlock();
EndBlock(); EndBlock();

View file

@ -68,6 +68,14 @@ void Emit(const std::string& fmt, const std::string& arg1, const std::string& ar
NL(); NL();
} }
void Emit(const std::string& fmt, const std::string& arg1, const std::string& arg2, const std::string& arg3,
const std::string& arg4, const std::string& arg5, const std::string& arg6, const std::string& arg7) const {
Indent();
fprintf(write_file, fmt.c_str(), arg1.c_str(), arg2.c_str(), arg3.c_str(), arg4.c_str(), arg5.c_str(), arg6.c_str(),
arg7.c_str());
NL();
}
void NL() const { fputc('\n', write_file); } void NL() const { fputc('\n', write_file); }
// Indents to the current indentation level. // Indents to the current indentation level.

View file

@ -90,6 +90,8 @@ struct CompiledScript {
CPPStmtPtr body; CPPStmtPtr body;
int priority; int priority;
std::vector<std::string> events; std::vector<std::string> events;
std::string module_group;
std::vector<std::string> attr_groups;
void (*finish_init_func)(); void (*finish_init_func)();
}; };

View file

@ -54,7 +54,9 @@ std::unordered_map<const Stmt*, std::string> body_names;
struct BodyInfo { struct BodyInfo {
p_hash_type hash; p_hash_type hash;
int priority; int priority;
const Location* loc; // for better-than-nothing error reporting const Location* loc; // for better-than-nothing error reporting
std::string module; // if non-nil, used for "module" event groups
std::vector<std::string> groups; // attribute-based event groups
}; };
// Maps function names to their body info. // Maps function names to their body info.

View file

@ -46,16 +46,18 @@ void register_type__CPP(TypePtr t, const string& name) {
} }
void register_body__CPP(CPPStmtPtr body, int priority, p_hash_type hash, vector<string> events, void (*finish_init)()) { void register_body__CPP(CPPStmtPtr body, int priority, p_hash_type hash, vector<string> events, void (*finish_init)()) {
compiled_scripts[hash] = {std::move(body), priority, std::move(events), finish_init}; compiled_scripts[hash] = {std::move(body), priority, std::move(events), {}, {}, finish_init};
} }
static unordered_map<p_hash_type, CompiledScript> compiled_standalone_scripts; static unordered_map<p_hash_type, CompiledScript> compiled_standalone_scripts;
void register_standalone_body__CPP(CPPStmtPtr body, int priority, p_hash_type hash, vector<string> events, void register_standalone_body__CPP(CPPStmtPtr body, int priority, p_hash_type hash, vector<string> events,
std::string module_group, std::vector<std::string> attr_groups,
void (*finish_init)()) { void (*finish_init)()) {
// For standalone scripts we don't actually need finish_init, but // For standalone scripts we don't actually need finish_init, but
// we keep it for symmetry with compiled_scripts. // we keep it for symmetry with compiled_scripts.
compiled_standalone_scripts[hash] = {std::move(body), priority, std::move(events), finish_init}; compiled_standalone_scripts[hash] = {std::move(body), priority, std::move(events), std::move(module_group),
std::move(attr_groups), finish_init};
} }
void register_lambda__CPP(CPPStmtPtr body, p_hash_type hash, const char* name, TypePtr t, bool has_captures) { void register_lambda__CPP(CPPStmtPtr body, p_hash_type hash, const char* name, TypePtr t, bool has_captures) {
@ -174,6 +176,7 @@ FuncValPtr lookup_func__CPP(string name, int num_bodies, vector<p_hash_type> has
vector<StmtPtr> bodies; vector<StmtPtr> bodies;
vector<int> priorities; vector<int> priorities;
vector<EventGroupPtr> groups;
for ( auto h : hashes ) { for ( auto h : hashes ) {
auto cs = compiled_scripts.find(h); auto cs = compiled_scripts.find(h);
@ -192,10 +195,22 @@ FuncValPtr lookup_func__CPP(string name, int num_bodies, vector<p_hash_type> has
// the semantics for Register explicitly allow it. // the semantics for Register explicitly allow it.
for ( auto& e : f.events ) for ( auto& e : f.events )
event_registry->Register(e); event_registry->Register(e);
vector<string> group_names = f.attr_groups;
if ( ! f.module_group.empty() )
group_names.push_back(f.module_group);
for ( const auto& g : group_names ) {
auto er = event_registry->RegisterGroup(EventGroupKind::Module, g);
groups.emplace_back(std::move(er));
}
} }
auto sf = make_intrusive<ScriptFunc>(std::move(name), std::move(ft), std::move(bodies), std::move(priorities)); auto sf = make_intrusive<ScriptFunc>(std::move(name), std::move(ft), std::move(bodies), std::move(priorities));
for ( auto& g : groups )
g->AddFunc(sf);
return make_intrusive<FuncVal>(std::move(sf)); return make_intrusive<FuncVal>(std::move(sf));
} }

View file

@ -47,7 +47,8 @@ extern void register_body__CPP(CPPStmtPtr body, int priority, p_hash_type hash,
// Same but for standalone function bodies. // Same but for standalone function bodies.
extern void register_standalone_body__CPP(CPPStmtPtr body, int priority, p_hash_type hash, extern void register_standalone_body__CPP(CPPStmtPtr body, int priority, p_hash_type hash,
std::vector<std::string> events, void (*finish_init)()); std::vector<std::string> events, std::string module_group,
std::vector<std::string> attr_groups, void (*finish_init)());
// Registers a lambda body as associated with the given hash. Includes // Registers a lambda body as associated with the given hash. Includes
// the name of the lambda (so it can be made available as a quasi-global // the name of the lambda (so it can be made available as a quasi-global

View file

@ -544,7 +544,8 @@ protected:
// code that loops over a vector of these to perform the registrations. // code that loops over a vector of these to perform the registrations.
struct CPP_RegisterBody { struct CPP_RegisterBody {
CPP_RegisterBody(std::string _func_name, void* _func, int _type_signature, int _priority, p_hash_type _h, CPP_RegisterBody(std::string _func_name, void* _func, int _type_signature, int _priority, p_hash_type _h,
const char* _filename, int _line_num, std::vector<std::string> _events) const char* _filename, int _line_num, std::vector<std::string> _events, std::string _module_group,
std::vector<std::string> _attr_groups)
: func_name(std::move(_func_name)), : func_name(std::move(_func_name)),
func(_func), func(_func),
type_signature(_type_signature), type_signature(_type_signature),
@ -552,7 +553,9 @@ struct CPP_RegisterBody {
h(_h), h(_h),
filename(_filename), filename(_filename),
line_num(_line_num), line_num(_line_num),
events(std::move(_events)) {} events(std::move(_events)),
module_group(std::move(_module_group)),
attr_groups(std::move(_attr_groups)) {}
std::string func_name; // name of the function std::string func_name; // name of the function
void* func; // pointer to C++ void* func; // pointer to C++
@ -562,6 +565,8 @@ struct CPP_RegisterBody {
const char* filename; const char* filename;
int line_num; int line_num;
std::vector<std::string> events; std::vector<std::string> events;
std::string module_group;
std::vector<std::string> attr_groups;
}; };
} // namespace zeek::detail } // namespace zeek::detail