@@ -86,6 +86,14 @@ std::optional<RequiredResources> ResourceAnalyser::analyse()
8686 bpftrace::globalvars::GlobalVar::MAX_CPU_ID);
8787 }
8888
89+ if (resources_.max_variable_size > 0 ) {
90+ assert (resources_.variable_buffers > 0 );
91+ resources_.needed_global_vars .insert (
92+ bpftrace::globalvars::GlobalVar::VARIABLE_BUFFER);
93+ resources_.needed_global_vars .insert (
94+ bpftrace::globalvars::GlobalVar::MAX_CPU_ID);
95+ }
96+
8997 return std::optional{ std::move (resources_) };
9098}
9199
@@ -114,8 +122,6 @@ void ResourceAnalyser::visit(Call &call)
114122{
115123 Visitor::visit (call);
116124
117- const auto on_stack_limit = bpftrace_.config_ .get (
118- ConfigKeyInt::on_stack_limit);
119125 if (call.func == " printf" || call.func == " system" || call.func == " cat" ||
120126 call.func == " debugf" ) {
121127 // Implicit first field is the 64bit printf ID.
@@ -152,7 +158,7 @@ void ResourceAnalyser::visit(Call &call)
152158 // will use this information to create a percpu array map of large
153159 // enough size for all fmt string calls to use.
154160 const auto tuple_size = static_cast <uint64_t >(tuple->size );
155- if (tuple_size > on_stack_limit ) {
161+ if (exceeds_stack_limit ( tuple_size) ) {
156162 resources_.max_fmtstring_args_size = std::max (
157163 resources_.max_fmtstring_args_size ,
158164 static_cast <uint64_t >(tuple_size));
@@ -227,7 +233,7 @@ void ResourceAnalyser::visit(Call &call)
227233 resources_.non_map_print_args .push_back (arg.type );
228234
229235 const auto fmtstring_args_size = nonmap_headroom + arg.type .GetSize ();
230- if (fmtstring_args_size > on_stack_limit ) {
236+ if (exceeds_stack_limit ( fmtstring_args_size) ) {
231237 resources_.max_fmtstring_args_size = std::max (
232238 resources_.max_fmtstring_args_size , fmtstring_args_size);
233239 }
@@ -237,7 +243,7 @@ void ResourceAnalyser::visit(Call &call)
237243 resources_.non_map_print_args .push_back (map.type );
238244
239245 const auto fmtstring_args_size = nonmap_headroom + map.type .GetSize ();
240- if (fmtstring_args_size > on_stack_limit ) {
246+ if (exceeds_stack_limit ( fmtstring_args_size) ) {
241247 resources_.max_fmtstring_args_size = std::max (
242248 resources_.max_fmtstring_args_size , fmtstring_args_size);
243249 }
@@ -261,7 +267,7 @@ void ResourceAnalyser::visit(Call &call)
261267 } else if (call.func == " delete" ) {
262268 auto &arg0 = *call.vargs .at (0 );
263269 auto &map = static_cast <Map &>(arg0);
264- if (map.type .GetSize () > on_stack_limit ) {
270+ if (exceeds_stack_limit ( map.type .GetSize ()) ) {
265271 resources_.max_write_map_value_size = std::max (
266272 resources_.max_write_map_value_size , map.type .GetSize ());
267273 }
@@ -279,7 +285,7 @@ void ResourceAnalyser::visit(Call &call)
279285
280286 if (call.func == " str" || call.func == " buf" || call.func == " path" ) {
281287 const auto max_strlen = bpftrace_.config_ .get (ConfigKeyInt::max_strlen);
282- if (max_strlen > on_stack_limit )
288+ if (exceeds_stack_limit ( max_strlen) )
283289 resources_.str_buffers ++;
284290 }
285291
@@ -296,9 +302,7 @@ void ResourceAnalyser::visit(Map &map)
296302
297303 update_map_info (map);
298304
299- const auto on_stack_limit = bpftrace_.config_ .get (
300- ConfigKeyInt::on_stack_limit);
301- if (map.type .GetSize () > on_stack_limit) {
305+ if (exceeds_stack_limit (map.type .GetSize ())) {
302306 resources_.read_map_value_buffers ++;
303307 resources_.max_read_map_value_size = std::max (
304308 resources_.max_read_map_value_size , map.type .GetSize ());
@@ -309,9 +313,7 @@ void ResourceAnalyser::visit(Tuple &tuple)
309313{
310314 Visitor::visit (tuple);
311315
312- const auto on_stack_limit = bpftrace_.config_ .get (
313- ConfigKeyInt::on_stack_limit);
314- if (tuple.type .GetSize () > on_stack_limit) {
316+ if (exceeds_stack_limit (tuple.type .GetSize ())) {
315317 resources_.tuple_buffers ++;
316318 resources_.max_tuple_size = std::max (resources_.max_tuple_size ,
317319 tuple.type .GetSize ());
@@ -323,9 +325,7 @@ void ResourceAnalyser::visit(For &f)
323325 Visitor::visit (f);
324326
325327 // Need tuple per for loop to store key and value
326- const auto on_stack_limit = bpftrace_.config_ .get (
327- ConfigKeyInt::on_stack_limit);
328- if (f.decl ->type .GetSize () > on_stack_limit) {
328+ if (exceeds_stack_limit (f.decl ->type .GetSize ())) {
329329 resources_.tuple_buffers ++;
330330 resources_.max_tuple_size = std::max (resources_.max_tuple_size ,
331331 f.decl ->type .GetSize ());
@@ -360,9 +360,7 @@ void ResourceAnalyser::visit(AssignMapStatement &assignment)
360360 update_map_info (*assignment.map );
361361
362362 if (needAssignMapStatementAllocation (assignment)) {
363- const auto on_stack_limit = bpftrace_.config_ .get (
364- ConfigKeyInt::on_stack_limit);
365- if (assignment.map ->type .GetSize () > on_stack_limit) {
363+ if (exceeds_stack_limit (assignment.map ->type .GetSize ())) {
366364 resources_.max_write_map_value_size = std::max (
367365 resources_.max_write_map_value_size , assignment.map ->type .GetSize ());
368366 }
@@ -379,14 +377,46 @@ void ResourceAnalyser::visit(Ternary &ternary)
379377 // blow it up. So we need a scratch buffer for it.
380378
381379 if (ternary.type .IsStringTy ()) {
382- const auto on_stack_limit = bpftrace_.config_ .get (
383- ConfigKeyInt::on_stack_limit);
384380 const auto max_strlen = bpftrace_.config_ .get (ConfigKeyInt::max_strlen);
385- if (max_strlen > on_stack_limit )
381+ if (exceeds_stack_limit ( max_strlen) )
386382 resources_.str_buffers ++;
387383 }
388384}
389385
386+ void ResourceAnalyser::update_variable_info (Variable &var)
387+ {
388+ /* Note we don't check if a variable has been declared/assigned before.
389+ * We do this to simplify the code and make it more robust to changes
390+ * in other modules at the expense of memory over-allocation. Otherwise,
391+ * we would need to track scopes like SemanticAnalyser and CodegenLLVM
392+ * and duplicate scope tracking in a third module.
393+ */
394+ if (exceeds_stack_limit (var.type .GetSize ())) {
395+ resources_.variable_buffers ++;
396+ resources_.max_variable_size = std::max (resources_.max_variable_size ,
397+ var.type .GetSize ());
398+ }
399+ }
400+
401+ void ResourceAnalyser::visit (AssignVarStatement &assignment)
402+ {
403+ Visitor::visit (assignment);
404+
405+ update_variable_info (*assignment.var );
406+ }
407+
408+ void ResourceAnalyser::visit (VarDeclStatement &decl)
409+ {
410+ Visitor::visit (decl);
411+
412+ update_variable_info (*decl.var );
413+ }
414+
415+ bool ResourceAnalyser::exceeds_stack_limit (size_t size)
416+ {
417+ return size > bpftrace_.config_ .get (ConfigKeyInt::on_stack_limit);
418+ }
419+
390420bool ResourceAnalyser::uses_usym_table (const std::string &fun)
391421{
392422 return fun == " usym" || fun == " func" || fun == " ustack" ;
0 commit comments