mirror of
https://github.com/zeek/zeek.git
synced 2025-10-14 04:28:20 +00:00
Merge remote-tracking branch 'origin/topic/timw/4553-combine-call-stacks'
Some checks are pending
pre-commit / pre-commit (push) Waiting to run
Some checks are pending
pre-commit / pre-commit (push) Waiting to run
* origin/topic/timw/4553-combine-call-stacks: Replace g_frame_stack with call_stack used by ScriptProfiler Clean up initialization in Func.h
This commit is contained in:
commit
5227e7ebb9
13 changed files with 135 additions and 116 deletions
18
CHANGES
18
CHANGES
|
@ -1,3 +1,21 @@
|
|||
8.1.0-dev.676 | 2025-10-13 09:54:47 -0700
|
||||
|
||||
* Replace g_frame_stack with call_stack used by ScriptProfiler (Tim Wojtulewicz, Corelight)
|
||||
|
||||
* Clean up initialization in Func.h (Tim Wojtulewicz, Corelight)
|
||||
|
||||
* Bump spicy-format (Benjamin Bannier, Corelight)
|
||||
|
||||
This brings in two changes:
|
||||
|
||||
- proper indention for blocks starting with multiple comments
|
||||
- switch the hook from `language: rust` to `language: python` to avoid
|
||||
nonsense due to pre-commit ignore Rust lock files,
|
||||
https://github.com/pre-commit/pre-commit/issues/3162.
|
||||
|
||||
The second one should help avoid future instances of the hook randomly
|
||||
breaking as its dependencies accidentially break semver.
|
||||
|
||||
8.1.0-dev.671 | 2025-10-11 12:38:21 +0200
|
||||
|
||||
* ZValElement: s to o renaming (Arne Welzel, Corelight)
|
||||
|
|
8
NEWS
8
NEWS
|
@ -26,6 +26,14 @@ Breaking Changes
|
|||
to live in the ``auxil`` directory, after having moved there from an external plugin.
|
||||
It is now built as part of main Zeek build whenever building on Linux.
|
||||
|
||||
- The global ``g_frame_stack`` C++ variable was removed. This variable was used to track
|
||||
the current stack of script-function frames, mostly for the built-in script debugger. We
|
||||
realized that we were also tracking this information in the global ``call_stack``
|
||||
variable, used by the script profiler. These two have now been combined together into
|
||||
``call_stack``. Plugins using ``g_frame_stack`` will need to be adapted to use the other
|
||||
variable. We opted to not use a deprecation cycle for this due to the complication with
|
||||
managing the data across both variables.
|
||||
|
||||
New Functionality
|
||||
-----------------
|
||||
|
||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
8.1.0-dev.671
|
||||
8.1.0-dev.676
|
||||
|
|
|
@ -303,17 +303,16 @@ void DbgBreakpoint::PrintHitMsg() {
|
|||
case BP_FUNC:
|
||||
case BP_LINE: {
|
||||
ODesc d;
|
||||
Frame* f = g_frame_stack.back();
|
||||
const ScriptFunc* func = f->GetFunction();
|
||||
const auto& f = call_stack.back().frame;
|
||||
|
||||
if ( func )
|
||||
if ( const Func* func = f->GetFunction() )
|
||||
func->DescribeDebug(&d, f->GetFuncArgs());
|
||||
|
||||
const Location* loc = at_stmt->GetLocationInfo();
|
||||
|
||||
debug_msg("Breakpoint %d, %s at %s:%d\n", GetID(), d.Description(), loc->FileName(), loc->FirstLine());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
case BP_TIME: assert(false);
|
||||
|
||||
|
|
49
src/Debug.cc
49
src/Debug.cc
|
@ -143,15 +143,13 @@ int TraceState::LogTrace(const char* fmt, ...) {
|
|||
const Stmt* stmt;
|
||||
Location loc;
|
||||
|
||||
if ( g_frame_stack.size() > 0 && g_frame_stack.back() ) {
|
||||
stmt = g_frame_stack.back()->GetNextStmt();
|
||||
if ( ! call_stack.empty() ) {
|
||||
const auto& frame = call_stack.back().frame;
|
||||
stmt = frame->GetNextStmt();
|
||||
if ( stmt )
|
||||
loc = *stmt->GetLocationInfo();
|
||||
else {
|
||||
const ScriptFunc* f = g_frame_stack.back()->GetFunction();
|
||||
if ( f )
|
||||
loc = *f->GetLocationInfo();
|
||||
}
|
||||
else if ( const Func* f = frame->GetFunction() )
|
||||
loc = *f->GetLocationInfo();
|
||||
}
|
||||
|
||||
if ( ! loc.FileName() ) {
|
||||
|
@ -163,7 +161,7 @@ int TraceState::LogTrace(const char* fmt, ...) {
|
|||
fprintf(trace_file, "%s:%d", loc.FileName(), loc.LastLine());
|
||||
|
||||
// Each stack frame is indented.
|
||||
for ( int i = 0; i < int(g_frame_stack.size()); ++i )
|
||||
for ( const auto& call : call_stack )
|
||||
fprintf(trace_file, "\t");
|
||||
|
||||
retval = vfprintf(trace_file, fmt, args);
|
||||
|
@ -589,16 +587,18 @@ static int dbg_dispatch_cmd(DebugCmd cmd_code, const vector<string>& args) {
|
|||
|
||||
case dcQuit: debug_msg("Program Terminating\n"); exit(0);
|
||||
|
||||
case dcNext:
|
||||
g_frame_stack.back()->BreakBeforeNextStmt(true);
|
||||
case dcNext: {
|
||||
Frame* frame = call_stack.back().frame;
|
||||
frame->BreakBeforeNextStmt(true);
|
||||
step_or_next_pending = true;
|
||||
last_frame = g_frame_stack.back();
|
||||
last_frame = frame;
|
||||
break;
|
||||
}
|
||||
|
||||
case dcStep:
|
||||
g_debugger_state.BreakBeforeNextStmt(true);
|
||||
step_or_next_pending = true;
|
||||
last_frame = g_frame_stack.back();
|
||||
last_frame = call_stack.back().frame;
|
||||
break;
|
||||
|
||||
case dcContinue:
|
||||
|
@ -607,7 +607,7 @@ static int dbg_dispatch_cmd(DebugCmd cmd_code, const vector<string>& args) {
|
|||
break;
|
||||
|
||||
case dcFinish:
|
||||
g_frame_stack.back()->BreakOnReturn(true);
|
||||
call_stack.back().frame->BreakOnReturn(true);
|
||||
g_debugger_state.BreakBeforeNextStmt(false);
|
||||
break;
|
||||
|
||||
|
@ -663,7 +663,7 @@ static char* get_prompt(bool reset_counter = false) {
|
|||
|
||||
string get_context_description(const Stmt* stmt, const Frame* frame) {
|
||||
ODesc d;
|
||||
const ScriptFunc* func = frame ? frame->GetFunction() : nullptr;
|
||||
const Func* func = frame ? frame->GetFunction() : nullptr;
|
||||
|
||||
if ( func )
|
||||
func->DescribeDebug(&d, frame->GetFuncArgs());
|
||||
|
@ -698,9 +698,8 @@ int dbg_handle_debug_input() {
|
|||
g_debugger_state.BreakFromSignal(false);
|
||||
}
|
||||
|
||||
Frame* curr_frame = g_frame_stack.back();
|
||||
const ScriptFunc* func = curr_frame->GetFunction();
|
||||
if ( func )
|
||||
auto curr_frame = call_stack.back().frame;
|
||||
if ( const Func* func = curr_frame->GetFunction() )
|
||||
current_module = extract_module_name(func->GetName().c_str());
|
||||
else
|
||||
current_module = GLOBAL_MODULE_NAME;
|
||||
|
@ -711,8 +710,8 @@ int dbg_handle_debug_input() {
|
|||
|
||||
const Location loc = *stmt->GetLocationInfo();
|
||||
|
||||
if ( ! step_or_next_pending || g_frame_stack.back() != last_frame ) {
|
||||
string context = get_context_description(stmt, g_frame_stack.back());
|
||||
if ( ! step_or_next_pending || call_stack.back().frame != last_frame ) {
|
||||
string context = get_context_description(stmt, call_stack.back().frame);
|
||||
debug_msg("%s\n", context.c_str());
|
||||
}
|
||||
|
||||
|
@ -848,16 +847,16 @@ ValPtr dbg_eval_expr(const char* expr) {
|
|||
// Push the current frame's associated scope.
|
||||
// Note: g_debugger_state.curr_frame_idx is the user-visible number,
|
||||
// while the array index goes in the opposite direction
|
||||
int frame_idx = (g_frame_stack.size() - 1) - g_debugger_state.curr_frame_idx;
|
||||
int frame_idx = (call_stack.size() - 1) - g_debugger_state.curr_frame_idx;
|
||||
|
||||
if ( ! (frame_idx >= 0 && (unsigned)frame_idx < g_frame_stack.size()) )
|
||||
reporter->InternalError("Assertion failed: frame_idx >= 0 && (unsigned) frame_idx < g_frame_stack.size()");
|
||||
if ( ! (frame_idx >= 0 && static_cast<size_t>(frame_idx) < call_stack.size()) )
|
||||
reporter->InternalError("Assertion failed: frame_idx >= 0 && (unsigned) frame_idx < call_stack.size()");
|
||||
|
||||
Frame* frame = g_frame_stack[frame_idx];
|
||||
if ( ! (frame) )
|
||||
const auto& frame = call_stack[frame_idx].frame;
|
||||
if ( ! frame )
|
||||
reporter->InternalError("Assertion failed: frame");
|
||||
|
||||
const ScriptFunc* func = frame->GetFunction();
|
||||
const Func* func = frame->GetFunction();
|
||||
if ( func )
|
||||
push_existing_scope(func->GetScope());
|
||||
|
||||
|
|
|
@ -173,7 +173,7 @@ int find_all_matching_cmds(const string& prefix, const char* array_of_matches[])
|
|||
|
||||
// Start, end bounds of which frame numbers to print
|
||||
static int dbg_backtrace_internal(int start, int end) {
|
||||
if ( start < 0 || end < 0 || (unsigned)start >= g_frame_stack.size() || (unsigned)end >= g_frame_stack.size() )
|
||||
if ( start < 0 || end < 0 || (unsigned)start >= call_stack.size() || (unsigned)end >= call_stack.size() )
|
||||
reporter->InternalError("Invalid stack frame index in DbgBacktraceInternal\n");
|
||||
|
||||
if ( start < end ) {
|
||||
|
@ -183,11 +183,11 @@ static int dbg_backtrace_internal(int start, int end) {
|
|||
}
|
||||
|
||||
for ( int i = start; i >= end; --i ) {
|
||||
const Frame* f = g_frame_stack[i];
|
||||
const auto& f = call_stack[i].frame;
|
||||
const Stmt* stmt = f ? f->GetNextStmt() : nullptr;
|
||||
|
||||
string context = get_context_description(stmt, f);
|
||||
debug_msg("#%d %s\n", int(g_frame_stack.size() - 1 - i), context.c_str());
|
||||
debug_msg("#%d %s\n", int(call_stack.size() - 1 - i), context.c_str());
|
||||
};
|
||||
|
||||
return 1;
|
||||
|
@ -196,7 +196,7 @@ static int dbg_backtrace_internal(int start, int end) {
|
|||
// Returns 0 for illegal arguments, or 1 on success.
|
||||
int dbg_cmd_backtrace(DebugCmd cmd, const vector<string>& args) {
|
||||
assert(cmd == dcBacktrace);
|
||||
assert(g_frame_stack.size() > 0);
|
||||
assert(! call_stack.empty());
|
||||
|
||||
unsigned int start_iter;
|
||||
int end_iter;
|
||||
|
@ -210,20 +210,20 @@ int dbg_cmd_backtrace(DebugCmd cmd, const vector<string>& args) {
|
|||
}
|
||||
|
||||
if ( how_many > 0 ) { // innermost N frames
|
||||
start_iter = g_frame_stack.size() - 1;
|
||||
start_iter = call_stack.size() - 1;
|
||||
end_iter = start_iter - how_many + 1;
|
||||
if ( end_iter < 0 )
|
||||
end_iter = 0;
|
||||
}
|
||||
else { // outermost N frames
|
||||
start_iter = how_many - 1;
|
||||
if ( start_iter + 1 > g_frame_stack.size() )
|
||||
start_iter = g_frame_stack.size() - 1;
|
||||
if ( start_iter + 1 > call_stack.size() )
|
||||
start_iter = call_stack.size() - 1;
|
||||
end_iter = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
start_iter = g_frame_stack.size() - 1;
|
||||
start_iter = call_stack.size() - 1;
|
||||
end_iter = 0;
|
||||
}
|
||||
|
||||
|
@ -248,7 +248,7 @@ int dbg_cmd_frame(DebugCmd cmd, const vector<string>& args) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
if ( idx < 0 || (unsigned int)idx >= g_frame_stack.size() ) {
|
||||
if ( idx < 0 || (unsigned int)idx >= call_stack.size() ) {
|
||||
debug_msg("No frame %d", idx);
|
||||
return 0;
|
||||
}
|
||||
|
@ -267,7 +267,7 @@ int dbg_cmd_frame(DebugCmd cmd, const vector<string>& args) {
|
|||
}
|
||||
|
||||
else if ( cmd == dcUp ) {
|
||||
if ( (unsigned int)(g_debugger_state.curr_frame_idx + 1) == g_frame_stack.size() ) {
|
||||
if ( (unsigned int)(g_debugger_state.curr_frame_idx + 1) == call_stack.size() ) {
|
||||
debug_msg("Outermost frame already selected\n");
|
||||
return 0;
|
||||
}
|
||||
|
@ -275,11 +275,11 @@ int dbg_cmd_frame(DebugCmd cmd, const vector<string>& args) {
|
|||
++g_debugger_state.curr_frame_idx;
|
||||
}
|
||||
|
||||
int user_frame_number = g_frame_stack.size() - 1 - g_debugger_state.curr_frame_idx;
|
||||
int user_frame_number = call_stack.size() - 1 - g_debugger_state.curr_frame_idx;
|
||||
|
||||
// Set the current location to the new frame being looked at
|
||||
// for 'list', 'break', etc.
|
||||
const Stmt* stmt = g_frame_stack[user_frame_number]->GetNextStmt();
|
||||
const Stmt* stmt = call_stack[user_frame_number].frame->GetNextStmt();
|
||||
if ( ! stmt )
|
||||
reporter->InternalError("Assertion failed: stmt is null");
|
||||
|
||||
|
@ -310,9 +310,9 @@ int dbg_cmd_break(DebugCmd cmd, const vector<string>& args) {
|
|||
int cond_index = -1; // at which argument pos. does bp condition start?
|
||||
|
||||
if ( args.empty() || args[0] == "if" ) { // break on next stmt
|
||||
int user_frame_number = g_frame_stack.size() - 1 - g_debugger_state.curr_frame_idx;
|
||||
int user_frame_number = call_stack.size() - 1 - g_debugger_state.curr_frame_idx;
|
||||
|
||||
Stmt* stmt = g_frame_stack[user_frame_number]->GetNextStmt();
|
||||
Stmt* stmt = call_stack[user_frame_number].frame->GetNextStmt();
|
||||
if ( ! stmt )
|
||||
reporter->InternalError("Assertion failed: stmt is null");
|
||||
|
||||
|
|
22
src/Frame.cc
22
src/Frame.cc
|
@ -11,31 +11,25 @@
|
|||
#include "zeek/Val.h"
|
||||
#include "zeek/broker/Data.h"
|
||||
|
||||
std::vector<zeek::detail::Frame*> g_frame_stack;
|
||||
|
||||
namespace zeek::detail {
|
||||
|
||||
Frame::Frame(int arg_size, const ScriptFunc* func, const zeek::Args* fn_args) {
|
||||
Frame::Frame(int arg_size, const Func* func, const zeek::Args* fn_args) {
|
||||
size = arg_size;
|
||||
frame = std::make_unique<Element[]>(size);
|
||||
if ( size > 0 )
|
||||
frame = std::make_unique<Element[]>(size);
|
||||
function = func;
|
||||
func_args = fn_args;
|
||||
|
||||
next_stmt = nullptr;
|
||||
break_before_next_stmt = false;
|
||||
break_on_return = false;
|
||||
|
||||
call = nullptr;
|
||||
delayed = false;
|
||||
|
||||
// We could Ref()/Unref() the captures frame, but there's really
|
||||
// no need because by definition this current frame exists to
|
||||
// enable execution of the function, and its captures frame won't
|
||||
// go away until the function itself goes away, which can only be
|
||||
// after this frame does.
|
||||
captures = function ? function->GetCapturesFrame() : nullptr;
|
||||
captures_offset_map = function ? function->GetCapturesOffsetMap() : nullptr;
|
||||
current_offset = 0;
|
||||
if ( function && function->GetKind() == Func::SCRIPT_FUNC ) {
|
||||
auto* sf = static_cast<const ScriptFunc*>(function);
|
||||
captures = sf->GetCapturesFrame();
|
||||
captures_offset_map = sf->GetCapturesOffsetMap();
|
||||
}
|
||||
}
|
||||
|
||||
void Frame::SetElement(int n, ValPtr v) {
|
||||
|
|
28
src/Frame.h
28
src/Frame.h
|
@ -20,11 +20,11 @@ using ValPtr = IntrusivePtr<Val>;
|
|||
|
||||
class BrokerListView;
|
||||
class BrokerData;
|
||||
class Func;
|
||||
|
||||
namespace detail {
|
||||
|
||||
class CallExpr;
|
||||
class ScriptFunc;
|
||||
using IDPtr = IntrusivePtr<ID>;
|
||||
|
||||
namespace trigger {
|
||||
|
@ -47,7 +47,7 @@ public:
|
|||
* @param func the function that is creating this frame
|
||||
* @param fn_args the arguments being passed to that function.
|
||||
*/
|
||||
Frame(int size, const ScriptFunc* func, const zeek::Args* fn_args);
|
||||
Frame(int size, const Func* func, const zeek::Args* fn_args);
|
||||
|
||||
/**
|
||||
* Returns the size of the frame.
|
||||
|
@ -117,7 +117,7 @@ public:
|
|||
/**
|
||||
* @return the function that the frame is associated with.
|
||||
*/
|
||||
const ScriptFunc* GetFunction() const { return function; }
|
||||
const Func* GetFunction() const { return function; }
|
||||
|
||||
/**
|
||||
* @return the arguments passed to the function that this frame
|
||||
|
@ -130,7 +130,7 @@ public:
|
|||
*
|
||||
* @param func the function for the frame to be associated with.
|
||||
*/
|
||||
void SetFunction(ScriptFunc* func) { function = func; }
|
||||
void SetFunction(Func* func) { function = func; }
|
||||
|
||||
/**
|
||||
* Sets the next statement to be executed in the context of the frame.
|
||||
|
@ -216,9 +216,9 @@ private:
|
|||
/** The number of vals that can be stored in this frame. */
|
||||
int size;
|
||||
|
||||
bool break_before_next_stmt;
|
||||
bool break_on_return;
|
||||
bool delayed;
|
||||
bool break_before_next_stmt = false;
|
||||
bool break_on_return = false;
|
||||
bool delayed = false;
|
||||
|
||||
/** Associates ID's offsets with values. */
|
||||
std::unique_ptr<Element[]> frame;
|
||||
|
@ -228,25 +228,25 @@ private:
|
|||
* This is how we support inlined functions without having to
|
||||
* alter the offsets associated with their local variables.
|
||||
*/
|
||||
int current_offset;
|
||||
int current_offset = 0;
|
||||
|
||||
/** Frame used for lambda/when captures. */
|
||||
Frame* captures;
|
||||
Frame* captures = nullptr;
|
||||
|
||||
/** Maps IDs to offsets into the "captures" frame. If the ID
|
||||
* isn't present, then it's not a capture.
|
||||
*/
|
||||
const OffsetMap* captures_offset_map;
|
||||
const OffsetMap* captures_offset_map = nullptr;
|
||||
|
||||
/** The function this frame is associated with. */
|
||||
const ScriptFunc* function;
|
||||
const Func* function = nullptr;
|
||||
|
||||
// The following is only needed for the debugger.
|
||||
/** The arguments to the function that this Frame is associated with. */
|
||||
const zeek::Args* func_args;
|
||||
const zeek::Args* func_args = nullptr;
|
||||
|
||||
/** The next statement to be evaluated in the context of this frame. */
|
||||
Stmt* next_stmt;
|
||||
Stmt* next_stmt = nullptr;
|
||||
|
||||
trigger::TriggerPtr trigger;
|
||||
const CallExpr* call = nullptr;
|
||||
|
@ -266,4 +266,4 @@ private:
|
|||
* DebugFrame which provides the information that the debugger uses. See:
|
||||
* https://stackoverflow.com/a/16211097
|
||||
*/
|
||||
extern std::vector<zeek::detail::Frame*> g_frame_stack;
|
||||
// extern std::vector<zeek::detail::Frame*> g_frame_stack;
|
||||
|
|
59
src/Func.cc
59
src/Func.cc
|
@ -93,10 +93,11 @@ std::string render_call_stack() {
|
|||
if ( lvl > 0 )
|
||||
rval += " | ";
|
||||
|
||||
const auto& name = ci.func->GetName();
|
||||
const auto& name = ci.frame->GetFunction()->GetName();
|
||||
std::string arg_desc;
|
||||
|
||||
for ( const auto& arg : ci.args ) {
|
||||
const auto& args = ci.frame->GetFuncArgs();
|
||||
for ( const auto& arg : *args ) {
|
||||
ODesc d;
|
||||
d.SetShort();
|
||||
arg->Describe(&d);
|
||||
|
@ -331,17 +332,16 @@ ValPtr ScriptFunc::Invoke(zeek::Args* args, Frame* parent) const {
|
|||
return Flavor() == FUNC_FLAVOR_HOOK ? val_mgr->True() : nullptr;
|
||||
}
|
||||
|
||||
auto f = make_intrusive<Frame>(frame_size, this, args);
|
||||
Frame f{static_cast<int>(frame_size), this, args};
|
||||
|
||||
// Hand down any trigger.
|
||||
if ( parent ) {
|
||||
f->SetTrigger({NewRef{}, parent->GetTrigger()});
|
||||
f->SetTriggerAssoc(parent->GetTriggerAssoc());
|
||||
f.SetTrigger({NewRef{}, parent->GetTrigger()});
|
||||
f.SetTriggerAssoc(parent->GetTriggerAssoc());
|
||||
}
|
||||
|
||||
g_frame_stack.push_back(f.get()); // used for backtracing
|
||||
const CallExpr* call_expr = parent ? parent->GetCall() : nullptr;
|
||||
call_stack.emplace_back(CallInfo{call_expr, this, *args});
|
||||
call_stack.emplace_back(call_expr, &f);
|
||||
|
||||
// If a script function is ever invoked with more arguments than it has
|
||||
// parameters log an error and return. Most likely a "variadic function"
|
||||
|
@ -374,24 +374,23 @@ ValPtr ScriptFunc::Invoke(zeek::Args* args, Frame* parent) const {
|
|||
for ( auto j = 0u; j < args->size(); ++j ) {
|
||||
const auto& arg = (*args)[j];
|
||||
|
||||
if ( f->GetElement(j) != arg )
|
||||
if ( f.GetElement(j) != arg )
|
||||
// Either not yet set, or somebody reassigned the frame slot.
|
||||
f->SetElement(j, arg);
|
||||
f.SetElement(j, arg);
|
||||
}
|
||||
|
||||
if ( spm )
|
||||
spm->StartInvocation(this, body.stmts);
|
||||
|
||||
f->Reset(args->size());
|
||||
f.Reset(args->size());
|
||||
|
||||
try {
|
||||
result = body.stmts->Exec(f.get(), flow);
|
||||
result = body.stmts->Exec(&f, flow);
|
||||
}
|
||||
|
||||
catch ( InterpreterException& e ) {
|
||||
// Already reported, but now determine whether to unwind further.
|
||||
if ( Flavor() == FUNC_FLAVOR_FUNCTION ) {
|
||||
g_frame_stack.pop_back();
|
||||
call_stack.pop_back();
|
||||
// Result not set b/c exception was thrown
|
||||
throw;
|
||||
|
@ -404,7 +403,7 @@ ValPtr ScriptFunc::Invoke(zeek::Args* args, Frame* parent) const {
|
|||
if ( spm )
|
||||
spm->EndInvocation();
|
||||
|
||||
if ( f->HasDelayed() ) {
|
||||
if ( f.HasDelayed() ) {
|
||||
assert(! result);
|
||||
assert(parent);
|
||||
parent->SetDelayed();
|
||||
|
@ -424,8 +423,6 @@ ValPtr ScriptFunc::Invoke(zeek::Args* args, Frame* parent) const {
|
|||
}
|
||||
}
|
||||
|
||||
call_stack.pop_back();
|
||||
|
||||
if ( Flavor() == FUNC_FLAVOR_HOOK ) {
|
||||
if ( ! result )
|
||||
result = val_mgr->True();
|
||||
|
@ -438,7 +435,7 @@ ValPtr ScriptFunc::Invoke(zeek::Args* args, Frame* parent) const {
|
|||
// the function without an explicit return, or without a value.
|
||||
else if ( GetType()->Yield() && GetType()->Yield()->Tag() != TYPE_VOID && ! GetType()->ExpressionlessReturnOkay() &&
|
||||
(flow != FLOW_RETURN /* we fell off the end */ || ! result /* explicit return with no result */) &&
|
||||
! f->HasDelayed() )
|
||||
! f.HasDelayed() )
|
||||
reporter->Warning("non-void function returning without a value: %s", GetName().c_str());
|
||||
|
||||
if ( result && g_trace_state.DoTrace() ) {
|
||||
|
@ -448,7 +445,7 @@ ValPtr ScriptFunc::Invoke(zeek::Args* args, Frame* parent) const {
|
|||
g_trace_state.LogTrace("Function return: %s\n", d.Description());
|
||||
}
|
||||
|
||||
g_frame_stack.pop_back();
|
||||
call_stack.pop_back();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -733,8 +730,10 @@ ValPtr BuiltinFunc::Invoke(Args* args, Frame* parent) const {
|
|||
g_trace_state.LogTrace("\tBuiltin Function called: %s\n", d.Description());
|
||||
}
|
||||
|
||||
Frame f{0, this, args};
|
||||
|
||||
const CallExpr* call_expr = parent ? parent->GetCall() : nullptr;
|
||||
call_stack.emplace_back(CallInfo{call_expr, this, *args});
|
||||
call_stack.emplace_back(call_expr, &f);
|
||||
auto result = func(parent, args);
|
||||
call_stack.pop_back();
|
||||
|
||||
|
@ -937,15 +936,15 @@ zeek::VectorValPtr get_current_script_backtrace() {
|
|||
auto cs_copy = zeek::detail::call_stack;
|
||||
|
||||
for ( const auto& ci : std::ranges::reverse_view(cs_copy) ) {
|
||||
if ( ! ci.func )
|
||||
// This happens for compiled code.
|
||||
if ( ! ci.frame->GetFunction() )
|
||||
// This happens for compiled code and BIFs.
|
||||
continue;
|
||||
|
||||
const auto& params = ci.func->GetType()->Params();
|
||||
auto args = MakeCallArgumentVector(ci.args, params);
|
||||
const auto& params = ci.frame->GetFunction()->GetType()->Params();
|
||||
auto args = MakeCallArgumentVector(*ci.frame->GetFuncArgs(), params);
|
||||
|
||||
auto elem =
|
||||
make_backtrace_element(ci.func->GetName(), std::move(args), ci.call ? ci.call->GetLocationInfo() : nullptr);
|
||||
auto elem = make_backtrace_element(ci.frame->GetFunction()->GetName(), std::move(args),
|
||||
ci.call ? ci.call->GetLocationInfo() : nullptr);
|
||||
rval->Append(std::move(elem));
|
||||
}
|
||||
|
||||
|
@ -990,7 +989,7 @@ static void emit_builtin_error_common(const char* msg, Obj* arg, bool unwind) {
|
|||
return;
|
||||
}
|
||||
|
||||
auto last_call = call_stack.back();
|
||||
const auto& last_call = call_stack.back();
|
||||
|
||||
if ( call_stack.size() < 2 ) {
|
||||
// Don't need to check for wrapper function like "<module>::__<func>"
|
||||
|
@ -998,10 +997,13 @@ static void emit_builtin_error_common(const char* msg, Obj* arg, bool unwind) {
|
|||
return;
|
||||
}
|
||||
|
||||
if ( ! last_call.frame->GetFunction() )
|
||||
return;
|
||||
|
||||
auto starts_with_double_underscore = [](const std::string& name) -> bool {
|
||||
return name.size() > 2 && name[0] == '_' && name[1] == '_';
|
||||
};
|
||||
const std::string& last_func = last_call.func->GetName();
|
||||
const std::string& last_func = last_call.frame->GetFunction()->GetName();
|
||||
|
||||
auto pos = last_func.find_first_of("::");
|
||||
std::string wrapper_func;
|
||||
|
@ -1027,7 +1029,10 @@ static void emit_builtin_error_common(const char* msg, Obj* arg, bool unwind) {
|
|||
}
|
||||
|
||||
auto parent_call = call_stack[call_stack.size() - 2];
|
||||
const auto& parent_func = parent_call.func->GetName();
|
||||
|
||||
std::string parent_func;
|
||||
if ( const auto* pcf = parent_call.frame->GetFunction() )
|
||||
parent_func = pcf->GetName();
|
||||
|
||||
if ( wrapper_func == parent_func )
|
||||
emit(parent_call.call);
|
||||
|
|
15
src/Func.h
15
src/Func.h
|
@ -339,21 +339,16 @@ public:
|
|||
void Describe(ODesc* d) const override;
|
||||
|
||||
protected:
|
||||
BuiltinFunc() {
|
||||
func = nullptr;
|
||||
is_pure = false;
|
||||
}
|
||||
|
||||
built_in_func func;
|
||||
bool is_pure;
|
||||
BuiltinFunc() = default;
|
||||
built_in_func func = nullptr;
|
||||
bool is_pure = false;
|
||||
};
|
||||
|
||||
extern bool check_built_in_call(BuiltinFunc* f, CallExpr* call);
|
||||
|
||||
struct CallInfo {
|
||||
const CallExpr* call;
|
||||
const Func* func;
|
||||
const zeek::Args& args;
|
||||
const CallExpr* call = nullptr;
|
||||
Frame* frame = nullptr;
|
||||
};
|
||||
|
||||
// Class that collects all the specifics defining a Func.
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
#include "zeek/Desc.h"
|
||||
#include "zeek/Expr.h"
|
||||
#include "zeek/Frame.h"
|
||||
#include "zeek/Func.h"
|
||||
#include "zeek/IntrusivePtr.h"
|
||||
#include "zeek/Reporter.h"
|
||||
|
@ -136,7 +137,7 @@ std::string_view determine_script_location() {
|
|||
|
||||
ssize_t sidx = static_cast<ssize_t>(zeek::detail::call_stack.size()) - 1;
|
||||
while ( sidx >= 0 ) {
|
||||
const auto* func = zeek::detail::call_stack[sidx].func;
|
||||
const auto* func = zeek::detail::call_stack[sidx].frame->GetFunction();
|
||||
const auto* ce = zeek::detail::call_stack[sidx].call;
|
||||
|
||||
// Cached?
|
||||
|
|
|
@ -41,12 +41,12 @@ eval auto& v = $$;
|
|||
|
||||
internal-op Load-Capture
|
||||
class Vi
|
||||
eval $$ = Z_FRAME->GetFunction()->GetCapturesVec()[$1];
|
||||
eval $$ = static_cast<const ScriptFunc*>(Z_FRAME->GetFunction())->GetCapturesVec()[$1];
|
||||
|
||||
internal-op Load-Managed-Capture
|
||||
class Vi
|
||||
eval auto& lhs = $$;
|
||||
auto& rhs = Z_FRAME->GetFunction()->GetCapturesVec()[$1];
|
||||
auto& rhs = static_cast<const ScriptFunc*>(Z_FRAME->GetFunction())->GetCapturesVec()[$1];
|
||||
zeek::Ref(rhs.ManagedVal());
|
||||
ZVal::DeleteManagedType(lhs);
|
||||
lhs = rhs;
|
||||
|
@ -62,12 +62,12 @@ eval GlobalID($1)->SetVal(GlobalVal($1).ToVal(Z_TYPE));
|
|||
internal-op Store-Capture
|
||||
op1-read
|
||||
class Vi
|
||||
eval Z_FRAME->GetFunction()->GetCapturesVec()[$2] = $1;
|
||||
eval static_cast<const ScriptFunc*>(Z_FRAME->GetFunction())->GetCapturesVec()[$2] = $1;
|
||||
|
||||
internal-op Store-Managed-Capture
|
||||
op1-read
|
||||
class Vi
|
||||
eval auto& lhs = Z_FRAME->GetFunction()->GetCapturesVec()[$2];
|
||||
eval auto& lhs = static_cast<const ScriptFunc*>(Z_FRAME->GetFunction())->GetCapturesVec()[$2];
|
||||
auto& rhs = $1;
|
||||
zeek::Ref(rhs.ManagedVal());
|
||||
ZVal::DeleteManagedType(lhs);
|
||||
|
|
|
@ -1054,7 +1054,7 @@ SetupResult setup(int argc, char** argv, Options* zopts) {
|
|||
auto [body, scope] = get_global_stmts();
|
||||
StmtFlowType flow;
|
||||
Frame f(scope->Length(), nullptr, nullptr);
|
||||
g_frame_stack.push_back(&f);
|
||||
call_stack.emplace_back(nullptr, &f);
|
||||
|
||||
try {
|
||||
body->Exec(&f, flow);
|
||||
|
@ -1062,7 +1062,7 @@ SetupResult setup(int argc, char** argv, Options* zopts) {
|
|||
reporter->FatalError("failed to execute script statements at top-level scope");
|
||||
}
|
||||
|
||||
g_frame_stack.pop_back();
|
||||
call_stack.pop_back();
|
||||
}
|
||||
|
||||
clear_script_analysis();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue