diff --git a/src/script_opt/CPP/DeclFunc.cc b/src/script_opt/CPP/DeclFunc.cc index 21e1ba7ef9..df634f5e46 100644 --- a/src/script_opt/CPP/DeclFunc.cc +++ b/src/script_opt/CPP/DeclFunc.cc @@ -1,5 +1,6 @@ // See the file "COPYING" in the main distribution directory for copyright. +#include "zeek/EventRegistry.h" #include "zeek/script_opt/CPP/Compile.h" namespace zeek::detail { @@ -15,8 +16,9 @@ void CPPCompile::DeclareFunc(const FuncInfo& func) { auto f = func.Func(); const auto& body = func.Body(); 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 ) 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, - int priority, const LambdaExpr* l, FunctionFlavor flavor) { + int priority, const LambdaExpr* l, FunctionFlavor flavor, + const std::forward_list* e_g) { const auto& yt = ft->Yield(); in_hook = flavor == FUNC_FLAVOR_HOOK; @@ -103,7 +106,29 @@ void CPPCompile::CreateFunction(const FuncTypePtr& ft, const ProfileFunc* pf, co compiled_funcs.emplace(fname); } - body_info[fname] = {.hash = pf->HashVal(), .priority = priority, .loc = body->GetLocationInfo()}; + string module_group; + vector 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); } diff --git a/src/script_opt/CPP/DeclFunc.h b/src/script_opt/CPP/DeclFunc.h index 1423b2b8fe..19dbffa043 100644 --- a/src/script_opt/CPP/DeclFunc.h +++ b/src/script_opt/CPP/DeclFunc.h @@ -32,7 +32,8 @@ void DeclareLambda(const LambdaExpr* l, const ProfileFunc* pf); // dynamic casting approach, which only requires one additional class. 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* e_g = nullptr); // 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, diff --git a/src/script_opt/CPP/Driver.cc b/src/script_opt/CPP/Driver.cc index 727daba30f..1437f7c37e 100644 --- a/src/script_opt/CPP/Driver.cc +++ b/src/script_opt/CPP/Driver.cc @@ -383,10 +383,18 @@ void CPPCompile::RegisterCompiledBody(const string& f) { auto h = bi.hash; auto p = bi.priority; auto loc = bi.loc; + auto body_info = Fmt(p) + ", " + Fmt(h) + ", \"" + loc->FileName() + " (C++)\", " + Fmt(loc->FirstLine()); - Emit("\tCPP_RegisterBody(\"%s\", (void*) %s, %s, %s, std::vector(%s)),", f, f, Fmt(type_signature), - body_info, events); + string module_group = "\"" + bi.module + "\""; + + string attr_groups = "{"; + for ( const auto& g : bi.groups ) + attr_groups += " \"" + g + "\","; + attr_groups += " }"; + + Emit("\tCPP_RegisterBody(\"%s\", (void*) %s, %s, %s, std::vector(%s), %s, %s),", f, f, + Fmt(type_signature), body_info, events, module_group, attr_groups); } void CPPCompile::GenEpilog() { @@ -570,8 +578,12 @@ void CPPCompile::GenRegisterBodies() { "auto f = make_intrusive(b.func_name.c_str(), b.func, b.type_signature, " "b.filename, b.line_num);"); - auto reg = standalone ? "register_standalone_body" : "register_body"; - Emit("%s__CPP(f, b.priority, b.h, b.events, finish_init__CPP);", reg); + if ( standalone ) + 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(); diff --git a/src/script_opt/CPP/Emit.h b/src/script_opt/CPP/Emit.h index 6871c84df8..402f4bb1b6 100644 --- a/src/script_opt/CPP/Emit.h +++ b/src/script_opt/CPP/Emit.h @@ -68,6 +68,14 @@ void Emit(const std::string& fmt, const std::string& arg1, const std::string& ar 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); } // Indents to the current indentation level. diff --git a/src/script_opt/CPP/Func.h b/src/script_opt/CPP/Func.h index 4642c2fdaa..402b8ee0b0 100644 --- a/src/script_opt/CPP/Func.h +++ b/src/script_opt/CPP/Func.h @@ -90,6 +90,8 @@ struct CompiledScript { CPPStmtPtr body; int priority; std::vector events; + std::string module_group; + std::vector attr_groups; void (*finish_init_func)(); }; diff --git a/src/script_opt/CPP/GenFunc.h b/src/script_opt/CPP/GenFunc.h index 35345bab38..eab99052f1 100644 --- a/src/script_opt/CPP/GenFunc.h +++ b/src/script_opt/CPP/GenFunc.h @@ -54,7 +54,9 @@ std::unordered_map body_names; struct BodyInfo { p_hash_type hash; 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 groups; // attribute-based event groups }; // Maps function names to their body info. diff --git a/src/script_opt/CPP/RuntimeInitSupport.cc b/src/script_opt/CPP/RuntimeInitSupport.cc index 0306e53120..589c5822c3 100644 --- a/src/script_opt/CPP/RuntimeInitSupport.cc +++ b/src/script_opt/CPP/RuntimeInitSupport.cc @@ -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 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 compiled_standalone_scripts; void register_standalone_body__CPP(CPPStmtPtr body, int priority, p_hash_type hash, vector events, + std::string module_group, std::vector attr_groups, void (*finish_init)()) { // For standalone scripts we don't actually need finish_init, but // 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) { @@ -174,6 +176,7 @@ FuncValPtr lookup_func__CPP(string name, int num_bodies, vector has vector bodies; vector priorities; + vector groups; for ( auto h : hashes ) { auto cs = compiled_scripts.find(h); @@ -192,10 +195,22 @@ FuncValPtr lookup_func__CPP(string name, int num_bodies, vector has // the semantics for Register explicitly allow it. for ( auto& e : f.events ) event_registry->Register(e); + + vector 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(std::move(name), std::move(ft), std::move(bodies), std::move(priorities)); + for ( auto& g : groups ) + g->AddFunc(sf); + return make_intrusive(std::move(sf)); } diff --git a/src/script_opt/CPP/RuntimeInitSupport.h b/src/script_opt/CPP/RuntimeInitSupport.h index fb016eb338..40f40ffe7c 100644 --- a/src/script_opt/CPP/RuntimeInitSupport.h +++ b/src/script_opt/CPP/RuntimeInitSupport.h @@ -47,7 +47,8 @@ extern void register_body__CPP(CPPStmtPtr body, int priority, p_hash_type hash, // Same but for standalone function bodies. extern void register_standalone_body__CPP(CPPStmtPtr body, int priority, p_hash_type hash, - std::vector events, void (*finish_init)()); + std::vector events, std::string module_group, + std::vector attr_groups, void (*finish_init)()); // 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 diff --git a/src/script_opt/CPP/RuntimeInits.h b/src/script_opt/CPP/RuntimeInits.h index c1fa9f87da..024dac961e 100644 --- a/src/script_opt/CPP/RuntimeInits.h +++ b/src/script_opt/CPP/RuntimeInits.h @@ -544,7 +544,8 @@ protected: // code that loops over a vector of these to perform the registrations. struct CPP_RegisterBody { 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 _events) + const char* _filename, int _line_num, std::vector _events, std::string _module_group, + std::vector _attr_groups) : func_name(std::move(_func_name)), func(_func), type_signature(_type_signature), @@ -552,7 +553,9 @@ struct CPP_RegisterBody { h(_h), filename(_filename), 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 void* func; // pointer to C++ @@ -562,6 +565,8 @@ struct CPP_RegisterBody { const char* filename; int line_num; std::vector events; + std::string module_group; + std::vector attr_groups; }; } // namespace zeek::detail