mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 06:38:20 +00:00
fixes for standalone C++ scripts making types & variables/functions available
This commit is contained in:
parent
fb9c73fa86
commit
725aa558a7
13 changed files with 125 additions and 19 deletions
|
@ -22,7 +22,8 @@ function load_CPP%(h: count%): bool
|
||||||
%{
|
%{
|
||||||
auto cb = detail::standalone_callbacks.find(h);
|
auto cb = detail::standalone_callbacks.find(h);
|
||||||
|
|
||||||
if ( cb == detail::standalone_callbacks.end() )
|
if ( cb == detail::standalone_callbacks.end() ||
|
||||||
|
! detail::CPP_init_hook )
|
||||||
{
|
{
|
||||||
reporter->Error("load of non-existing C++ code (%" PRIu64 ")", h);
|
reporter->Error("load of non-existing C++ code (%" PRIu64 ")", h);
|
||||||
return zeek::val_mgr->False();
|
return zeek::val_mgr->False();
|
||||||
|
@ -38,5 +39,8 @@ function load_CPP%(h: count%): bool
|
||||||
// compiled scripts.
|
// compiled scripts.
|
||||||
detail::standalone_activations.push_back(cb->second);
|
detail::standalone_activations.push_back(cb->second);
|
||||||
|
|
||||||
|
// Proceed with activation.
|
||||||
|
(*detail::CPP_init_hook)();
|
||||||
|
|
||||||
return zeek::val_mgr->True();
|
return zeek::val_mgr->True();
|
||||||
%}
|
%}
|
||||||
|
|
|
@ -303,6 +303,9 @@ void CPPCompile::GenEpilog()
|
||||||
CheckInitConsistency(to_do);
|
CheckInitConsistency(to_do);
|
||||||
auto nc = GenDependentInits(to_do);
|
auto nc = GenDependentInits(to_do);
|
||||||
|
|
||||||
|
if ( standalone )
|
||||||
|
GenStandaloneActivation();
|
||||||
|
|
||||||
NL();
|
NL();
|
||||||
Emit("void init__CPP()");
|
Emit("void init__CPP()");
|
||||||
|
|
||||||
|
@ -319,6 +322,9 @@ void CPPCompile::GenEpilog()
|
||||||
NL();
|
NL();
|
||||||
InitializeFieldMappings();
|
InitializeFieldMappings();
|
||||||
|
|
||||||
|
if ( standalone )
|
||||||
|
Emit("standalone_init__CPP();");
|
||||||
|
|
||||||
EndBlock(true);
|
EndBlock(true);
|
||||||
|
|
||||||
GenInitHook();
|
GenInitHook();
|
||||||
|
|
|
@ -246,15 +246,18 @@ string CPPCompile::GenCallExpr(const CallExpr* c, GenType gt)
|
||||||
auto f_id = f->AsNameExpr()->Id();
|
auto f_id = f->AsNameExpr()->Id();
|
||||||
const auto& params = f_id->GetType()->AsFuncType()->Params();
|
const auto& params = f_id->GetType()->AsFuncType()->Params();
|
||||||
auto id_name = f_id->Name();
|
auto id_name = f_id->Name();
|
||||||
auto fname = Canonicalize(id_name) + "_zf";
|
|
||||||
|
|
||||||
bool is_compiled = compiled_funcs.count(fname) > 0;
|
bool is_compiled = compiled_simple_funcs.count(id_name) > 0;
|
||||||
bool was_compiled = hashed_funcs.count(id_name) > 0;
|
bool was_compiled = hashed_funcs.count(id_name) > 0;
|
||||||
|
|
||||||
if ( is_compiled || was_compiled )
|
if ( is_compiled || was_compiled )
|
||||||
{
|
{
|
||||||
|
string fname;
|
||||||
|
|
||||||
if ( was_compiled )
|
if ( was_compiled )
|
||||||
fname = hashed_funcs[id_name];
|
fname = hashed_funcs[id_name];
|
||||||
|
else
|
||||||
|
fname = compiled_simple_funcs[id_name];
|
||||||
|
|
||||||
if ( args_l->Exprs().length() > 0 )
|
if ( args_l->Exprs().length() > 0 )
|
||||||
gen = fname + "(" + GenArgs(params, args_l) +
|
gen = fname + "(" + GenArgs(params, args_l) +
|
||||||
|
|
|
@ -12,6 +12,7 @@ namespace zeek::detail {
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
unordered_map<p_hash_type, CompiledScript> compiled_scripts;
|
unordered_map<p_hash_type, CompiledScript> compiled_scripts;
|
||||||
|
unordered_map<string, unordered_set<p_hash_type>> added_bodies;
|
||||||
unordered_map<p_hash_type, void (*)()> standalone_callbacks;
|
unordered_map<p_hash_type, void (*)()> standalone_callbacks;
|
||||||
vector<void (*)()> standalone_activations;
|
vector<void (*)()> standalone_activations;
|
||||||
|
|
||||||
|
|
|
@ -108,6 +108,14 @@ struct CompiledScript {
|
||||||
// Maps hashes to compiled information.
|
// Maps hashes to compiled information.
|
||||||
extern std::unordered_map<p_hash_type, CompiledScript> compiled_scripts;
|
extern std::unordered_map<p_hash_type, CompiledScript> compiled_scripts;
|
||||||
|
|
||||||
|
// When using standalone-code, tracks which function bodies have had
|
||||||
|
// compiled versions added to them. Needed so that we don't replace
|
||||||
|
// the body twice, leading to two copies. Indexed first by the name
|
||||||
|
// of the function, and then via the hash of the body that has been
|
||||||
|
// added to it.
|
||||||
|
extern std::unordered_map<std::string, std::unordered_set<p_hash_type>>
|
||||||
|
added_bodies;
|
||||||
|
|
||||||
// Maps hashes to standalone script initialization callbacks.
|
// Maps hashes to standalone script initialization callbacks.
|
||||||
extern std::unordered_map<p_hash_type, void (*)()> standalone_callbacks;
|
extern std::unordered_map<p_hash_type, void (*)()> standalone_callbacks;
|
||||||
|
|
||||||
|
|
|
@ -460,9 +460,6 @@ void CPPCompile::GenInitHook()
|
||||||
{
|
{
|
||||||
NL();
|
NL();
|
||||||
|
|
||||||
if ( standalone )
|
|
||||||
GenStandaloneActivation();
|
|
||||||
|
|
||||||
Emit("int hook_in_init()");
|
Emit("int hook_in_init()");
|
||||||
|
|
||||||
StartBlock();
|
StartBlock();
|
||||||
|
@ -482,6 +479,15 @@ void CPPCompile::GenInitHook()
|
||||||
|
|
||||||
void CPPCompile::GenStandaloneActivation()
|
void CPPCompile::GenStandaloneActivation()
|
||||||
{
|
{
|
||||||
|
NL();
|
||||||
|
|
||||||
|
Emit("void standalone_activation__CPP()");
|
||||||
|
StartBlock();
|
||||||
|
for ( auto& a : activations )
|
||||||
|
Emit(a);
|
||||||
|
EndBlock();
|
||||||
|
|
||||||
|
NL();
|
||||||
Emit("void standalone_init__CPP()");
|
Emit("void standalone_init__CPP()");
|
||||||
StartBlock();
|
StartBlock();
|
||||||
|
|
||||||
|
@ -497,11 +503,6 @@ void CPPCompile::GenStandaloneActivation()
|
||||||
for ( const auto& func : funcs )
|
for ( const auto& func : funcs )
|
||||||
{
|
{
|
||||||
auto f = func.Func();
|
auto f = func.Func();
|
||||||
|
|
||||||
if ( f->Flavor() == FUNC_FLAVOR_FUNCTION )
|
|
||||||
// No need to explicitly add bodies.
|
|
||||||
continue;
|
|
||||||
|
|
||||||
auto fname = BodyName(func);
|
auto fname = BodyName(func);
|
||||||
auto bname = Canonicalize(fname.c_str()) + "_zf";
|
auto bname = Canonicalize(fname.c_str()) + "_zf";
|
||||||
|
|
||||||
|
@ -534,8 +535,11 @@ void CPPCompile::GenStandaloneActivation()
|
||||||
fn, GenTypeName(ft), hashes);
|
fn, GenTypeName(ft), hashes);
|
||||||
}
|
}
|
||||||
|
|
||||||
EndBlock();
|
|
||||||
NL();
|
NL();
|
||||||
|
Emit("CPP_activation_funcs.push_back(standalone_activation__CPP);");
|
||||||
|
Emit("CPP_activation_hook = activate__CPPs;");
|
||||||
|
|
||||||
|
EndBlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPPCompile::GenLoad()
|
void CPPCompile::GenLoad()
|
||||||
|
|
|
@ -9,12 +9,30 @@ namespace zeek::detail {
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
vector<CPP_init_func> CPP_init_funcs;
|
vector<CPP_init_func> CPP_init_funcs;
|
||||||
|
vector<CPP_init_func> CPP_activation_funcs;
|
||||||
|
|
||||||
// Calls all of the initialization hooks, in the order they were added.
|
// Calls all of the initialization hooks, in the order they were added.
|
||||||
void init_CPPs()
|
void init_CPPs()
|
||||||
{
|
{
|
||||||
for ( auto f : CPP_init_funcs )
|
static bool need_init = true;
|
||||||
f();
|
|
||||||
|
if ( need_init )
|
||||||
|
for ( auto f : CPP_init_funcs )
|
||||||
|
f();
|
||||||
|
|
||||||
|
need_init = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calls all of the registered activation hooks for standalone code.
|
||||||
|
void activate__CPPs()
|
||||||
|
{
|
||||||
|
static bool need_init = true;
|
||||||
|
|
||||||
|
if ( need_init )
|
||||||
|
for ( auto f : CPP_activation_funcs )
|
||||||
|
f();
|
||||||
|
|
||||||
|
need_init = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is a trick used to register the presence of compiled code.
|
// This is a trick used to register the presence of compiled code.
|
||||||
|
@ -30,6 +48,19 @@ static int flag_init_CPP()
|
||||||
static int dummy = flag_init_CPP();
|
static int dummy = flag_init_CPP();
|
||||||
|
|
||||||
|
|
||||||
|
void register_type__CPP(TypePtr t, const std::string& name)
|
||||||
|
{
|
||||||
|
if ( t->GetName().size() > 0 )
|
||||||
|
// Already registered.
|
||||||
|
return;
|
||||||
|
|
||||||
|
t->SetName(name);
|
||||||
|
|
||||||
|
auto id = install_ID(name.c_str(), GLOBAL_MODULE_NAME, true, false);
|
||||||
|
id->SetType(t);
|
||||||
|
id->MakeType();
|
||||||
|
}
|
||||||
|
|
||||||
void register_body__CPP(CPPStmtPtr body, int priority, p_hash_type hash,
|
void register_body__CPP(CPPStmtPtr body, int priority, p_hash_type hash,
|
||||||
vector<string> events)
|
vector<string> events)
|
||||||
{
|
{
|
||||||
|
@ -78,7 +109,19 @@ void activate_bodies__CPP(const char* fn, TypePtr t, vector<p_hash_type> hashes)
|
||||||
fg->SetType(ft);
|
fg->SetType(ft);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto f = fg->GetVal()->AsFunc();
|
auto v = fg->GetVal();
|
||||||
|
if ( ! v )
|
||||||
|
{ // Create it.
|
||||||
|
std::vector<StmtPtr> no_bodies;
|
||||||
|
std::vector<int> no_priorities;
|
||||||
|
auto sf = make_intrusive<ScriptFunc>(fn, ft, no_bodies,
|
||||||
|
no_priorities);
|
||||||
|
|
||||||
|
v = make_intrusive<FuncVal>(move(sf));
|
||||||
|
fg->SetVal(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto f = v->AsFunc();
|
||||||
const auto& bodies = f->GetBodies();
|
const auto& bodies = f->GetBodies();
|
||||||
|
|
||||||
// Track hashes of compiled bodies already associated with f.
|
// Track hashes of compiled bodies already associated with f.
|
||||||
|
@ -115,6 +158,7 @@ void activate_bodies__CPP(const char* fn, TypePtr t, vector<p_hash_type> hashes)
|
||||||
auto cs = compiled_scripts[h];
|
auto cs = compiled_scripts[h];
|
||||||
|
|
||||||
f->AddBody(cs.body, no_inits, num_params, cs.priority);
|
f->AddBody(cs.body, no_inits, num_params, cs.priority);
|
||||||
|
added_bodies[fn].insert(h);
|
||||||
|
|
||||||
events.insert(cs.events.begin(), cs.events.end());
|
events.insert(cs.events.begin(), cs.events.end());
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,15 @@ typedef void (*CPP_init_func)();
|
||||||
// Tracks the initialization hooks for different compilation runs.
|
// Tracks the initialization hooks for different compilation runs.
|
||||||
extern std::vector<CPP_init_func> CPP_init_funcs;
|
extern std::vector<CPP_init_func> CPP_init_funcs;
|
||||||
|
|
||||||
|
// Tracks the activation hooks for different "standalone" compilations.
|
||||||
|
extern std::vector<CPP_init_func> CPP_activation_funcs;
|
||||||
|
|
||||||
|
// Activates all previously registered standalone code.
|
||||||
|
extern void activate__CPPs();
|
||||||
|
|
||||||
|
// Registers the given global type, if not already present.
|
||||||
|
extern void register_type__CPP(TypePtr t, const std::string& name);
|
||||||
|
|
||||||
// Registers the given compiled function body as associated with the
|
// Registers the given compiled function body as associated with the
|
||||||
// given priority and hash. "events" is a list of event handlers
|
// given priority and hash. "events" is a list of event handlers
|
||||||
// relevant for the function body, which should be registered if the
|
// relevant for the function body, which should be registered if the
|
||||||
|
|
|
@ -134,7 +134,8 @@ void CPPCompile::ExpandTypeVar(const TypePtr& t)
|
||||||
|
|
||||||
auto& script_type_name = t->GetName();
|
auto& script_type_name = t->GetName();
|
||||||
if ( script_type_name.size() > 0 )
|
if ( script_type_name.size() > 0 )
|
||||||
AddInit(t, tn + "->SetName(\"" + script_type_name + "\");");
|
AddInit(t, "register_type__CPP(" + tn + ", \"" +
|
||||||
|
script_type_name + "\");");
|
||||||
|
|
||||||
AddInit(t);
|
AddInit(t);
|
||||||
}
|
}
|
||||||
|
|
|
@ -168,7 +168,12 @@ void CPPCompile::AddBiF(const ID* b, bool is_var)
|
||||||
if ( AddGlobal(n, "bif", true) )
|
if ( AddGlobal(n, "bif", true) )
|
||||||
Emit("Func* %s;", globals[n]);
|
Emit("Func* %s;", globals[n]);
|
||||||
|
|
||||||
AddInit(b, globals[n], string("lookup_bif__CPP(\"") + bn + "\")");
|
auto lookup = string("lookup_bif__CPP(\"") + bn + "\")";
|
||||||
|
|
||||||
|
if ( standalone )
|
||||||
|
AddActivation(globals[n] + " = " + lookup + ";");
|
||||||
|
else
|
||||||
|
AddInit(b, globals[n], lookup);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CPPCompile::AddGlobal(const string& g, const char* suffix, bool track)
|
bool CPPCompile::AddGlobal(const string& g, const char* suffix, bool track)
|
||||||
|
|
|
@ -24,6 +24,7 @@ AnalyOpt analysis_options;
|
||||||
std::unordered_set<const Func*> non_recursive_funcs;
|
std::unordered_set<const Func*> non_recursive_funcs;
|
||||||
|
|
||||||
void (*CPP_init_hook)() = nullptr;
|
void (*CPP_init_hook)() = nullptr;
|
||||||
|
void (*CPP_activation_hook)() = nullptr;
|
||||||
|
|
||||||
// Tracks all of the loaded functions (including event handlers and hooks).
|
// Tracks all of the loaded functions (including event handlers and hooks).
|
||||||
static std::vector<FuncInfo> funcs;
|
static std::vector<FuncInfo> funcs;
|
||||||
|
@ -354,8 +355,21 @@ void analyze_scripts()
|
||||||
{
|
{
|
||||||
auto b = s->second.body;
|
auto b = s->second.body;
|
||||||
b->SetHash(hash);
|
b->SetHash(hash);
|
||||||
f.Func()->ReplaceBody(f.Body(), b);
|
|
||||||
f.SetBody(b);
|
// We may have already updated the body if
|
||||||
|
// we're using code compiled for standalone.
|
||||||
|
if ( f.Body()->Tag() != STMT_CPP )
|
||||||
|
{
|
||||||
|
auto func = f.Func();
|
||||||
|
if ( added_bodies[func->Name()].count(hash) > 0 )
|
||||||
|
// We've already added the
|
||||||
|
// replacement. Delete orig.
|
||||||
|
func->ReplaceBody(f.Body(), nullptr);
|
||||||
|
else
|
||||||
|
func->ReplaceBody(f.Body(), b);
|
||||||
|
|
||||||
|
f.SetBody(b);
|
||||||
|
}
|
||||||
|
|
||||||
for ( auto& e : s->second.events )
|
for ( auto& e : s->second.events )
|
||||||
{
|
{
|
||||||
|
|
|
@ -147,5 +147,9 @@ extern void analyze_scripts();
|
||||||
// to a non-empty value.
|
// to a non-empty value.
|
||||||
extern void (*CPP_init_hook)();
|
extern void (*CPP_init_hook)();
|
||||||
|
|
||||||
|
// Used for "standalone" C++-compiled scripts to complete their activation;
|
||||||
|
// called after parsing and BiF initialization, but before zeek_init.
|
||||||
|
extern void (*CPP_activation_hook)();
|
||||||
|
|
||||||
|
|
||||||
} // namespace zeek::detail
|
} // namespace zeek::detail
|
||||||
|
|
|
@ -849,6 +849,9 @@ SetupResult setup(int argc, char** argv, Options* zopts)
|
||||||
// we don't have any other source for it.
|
// we don't have any other source for it.
|
||||||
run_state::detail::update_network_time(util::current_time());
|
run_state::detail::update_network_time(util::current_time());
|
||||||
|
|
||||||
|
if ( CPP_activation_hook )
|
||||||
|
(*CPP_activation_hook)();
|
||||||
|
|
||||||
if ( zeek_init )
|
if ( zeek_init )
|
||||||
event_mgr.Enqueue(zeek_init, Args{});
|
event_mgr.Enqueue(zeek_init, Args{});
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue