Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

perf probe: Dynamically allocate params memory

Avoid 14,432 bytes in .bss by dynamically allocating params.

Signed-off-by: Ian Rogers <irogers@google.com>
Link: https://lore.kernel.org/r/20230526183401.2326121-12-irogers@google.com
Cc: K Prateek Nayak <kprateek.nayak@amd.com>
Cc: Ravi Bangoria <ravi.bangoria@amd.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Ross Zwisler <zwisler@chromium.org>
Cc: Steven Rostedt (Google) <rostedt@goodmis.org>
Cc: Sean Christopherson <seanjc@google.com>
Cc: Yang Jihong <yangjihong1@huawei.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Leo Yan <leo.yan@linaro.org>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Tiezhu Yang <yangtiezhu@loongson.cn>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: linux-kernel@vger.kernel.org
Cc: linux-perf-users@vger.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Ian Rogers and committed by
Arnaldo Carvalho de Melo
430952e6 ddc27bb8

+71 -62
+71 -62
tools/perf/builtin-probe.c
··· 47 47 char *target; 48 48 struct strfilter *filter; 49 49 struct nsinfo *nsi; 50 - } params; 50 + } *params; 51 51 52 52 /* Parse an event definition. Note that any error must die. */ 53 53 static int parse_probe_event(const char *str) 54 54 { 55 - struct perf_probe_event *pev = &params.events[params.nevents]; 55 + struct perf_probe_event *pev = &params->events[params->nevents]; 56 56 int ret; 57 57 58 - pr_debug("probe-definition(%d): %s\n", params.nevents, str); 59 - if (++params.nevents == MAX_PROBES) { 58 + pr_debug("probe-definition(%d): %s\n", params->nevents, str); 59 + if (++params->nevents == MAX_PROBES) { 60 60 pr_err("Too many probes (> %d) were specified.", MAX_PROBES); 61 61 return -1; 62 62 } 63 63 64 - pev->uprobes = params.uprobes; 65 - if (params.target) { 66 - pev->target = strdup(params.target); 64 + pev->uprobes = params->uprobes; 65 + if (params->target) { 66 + pev->target = strdup(params->target); 67 67 if (!pev->target) 68 68 return -ENOMEM; 69 - params.target_used = true; 69 + params->target_used = true; 70 70 } 71 71 72 - pev->nsi = nsinfo__get(params.nsi); 72 + pev->nsi = nsinfo__get(params->nsi); 73 73 74 74 /* Parse a perf-probe command into event */ 75 75 ret = parse_perf_probe_command(str, pev); ··· 84 84 int ret = 0; 85 85 86 86 pr_debug2("Add filter: %s\n", str); 87 - if (!params.filter) { 88 - params.filter = strfilter__new(str, &err); 89 - if (!params.filter) 87 + if (!params->filter) { 88 + params->filter = strfilter__new(str, &err); 89 + if (!params->filter) 90 90 ret = err ? -EINVAL : -ENOMEM; 91 91 } else 92 - ret = strfilter__or(params.filter, str, &err); 92 + ret = strfilter__or(params->filter, str, &err); 93 93 94 94 if (ret == -EINVAL) { 95 95 pr_err("Filter parse error at %td.\n", err - str + 1); ··· 112 112 * TODO: Support relative path, and $PATH, $LD_LIBRARY_PATH, 113 113 * short module name. 114 114 */ 115 - if (!params.target && ptr && *ptr == '/') { 116 - params.target = strdup(ptr); 117 - if (!params.target) 115 + if (!params->target && ptr && *ptr == '/') { 116 + params->target = strdup(ptr); 117 + if (!params->target) 118 118 return -ENOMEM; 119 - params.target_used = false; 119 + params->target_used = false; 120 120 121 121 found = 1; 122 122 buf = ptr + (strlen(ptr) - 3); 123 123 124 124 if (strcmp(buf, ".ko")) 125 - params.uprobes = true; 125 + params->uprobes = true; 126 126 127 127 } 128 128 ··· 172 172 173 173 if (str) { 174 174 if (!strcmp(opt->long_name, "exec")) 175 - params.uprobes = true; 175 + params->uprobes = true; 176 176 else if (!strcmp(opt->long_name, "module")) 177 - params.uprobes = false; 177 + params->uprobes = false; 178 178 else 179 179 return ret; 180 180 181 181 /* Expand given path to absolute path, except for modulename */ 182 - if (params.uprobes || strchr(str, '/')) { 183 - tmp = nsinfo__realpath(str, params.nsi); 182 + if (params->uprobes || strchr(str, '/')) { 183 + tmp = nsinfo__realpath(str, params->nsi); 184 184 if (!tmp) { 185 185 pr_warning("Failed to get the absolute path of %s: %m\n", str); 186 186 return ret; ··· 190 190 if (!tmp) 191 191 return -ENOMEM; 192 192 } 193 - free(params.target); 194 - params.target = tmp; 195 - params.target_used = false; 193 + free(params->target); 194 + params->target = tmp; 195 + params->target_used = false; 196 196 ret = 0; 197 197 } 198 198 ··· 217 217 } 218 218 nsip = nsinfo__new(ns_pid); 219 219 if (nsip && nsinfo__need_setns(nsip)) 220 - params.nsi = nsinfo__get(nsip); 220 + params->nsi = nsinfo__get(nsip); 221 221 nsinfo__put(nsip); 222 222 223 223 ret = 0; ··· 238 238 if (!str) 239 239 return 0; 240 240 241 - if (params.command == 'L') { 241 + if (params->command == 'L') { 242 242 pr_warning("Warning: more than one --line options are" 243 243 " detected. Only the first one is valid.\n"); 244 244 return 0; 245 245 } 246 246 247 - params.command = opt->short_name; 248 - ret = parse_line_range_desc(str, &params.line_range); 247 + params->command = opt->short_name; 248 + ret = parse_line_range_desc(str, &params->line_range); 249 249 250 250 return ret; 251 251 } ··· 253 253 static int opt_show_vars(const struct option *opt, 254 254 const char *str, int unset __maybe_unused) 255 255 { 256 - struct perf_probe_event *pev = &params.events[params.nevents]; 256 + struct perf_probe_event *pev = &params->events[params->nevents]; 257 257 int ret; 258 258 259 259 if (!str) ··· 264 264 pr_err(" Error: '--vars' doesn't accept arguments.\n"); 265 265 return -EINVAL; 266 266 } 267 - params.command = opt->short_name; 267 + params->command = opt->short_name; 268 268 269 269 return ret; 270 270 } ··· 276 276 const char *str, int unset __maybe_unused) 277 277 { 278 278 if (str) { 279 - params.command = opt->short_name; 279 + params->command = opt->short_name; 280 280 return parse_probe_event(str); 281 281 } 282 282 ··· 287 287 const char *str, int unset) 288 288 { 289 289 if (!unset) 290 - params.command = opt->short_name; 290 + params->command = opt->short_name; 291 291 292 292 if (str) 293 293 return params_add_filter(str); ··· 306 306 307 307 static int init_params(void) 308 308 { 309 - return line_range__init(&params.line_range); 309 + int ret; 310 + 311 + params = calloc(1, sizeof(*params)); 312 + if (!params) 313 + return -ENOMEM; 314 + 315 + ret = line_range__init(&params->line_range); 316 + if (ret) 317 + zfree(&params); 318 + return ret; 310 319 } 311 320 312 321 static void cleanup_params(void) 313 322 { 314 323 int i; 315 324 316 - for (i = 0; i < params.nevents; i++) 317 - clear_perf_probe_event(params.events + i); 318 - line_range__clear(&params.line_range); 319 - free(params.target); 320 - strfilter__delete(params.filter); 321 - nsinfo__put(params.nsi); 322 - memset(&params, 0, sizeof(params)); 325 + for (i = 0; i < params->nevents; i++) 326 + clear_perf_probe_event(params->events + i); 327 + line_range__clear(&params->line_range); 328 + free(params->target); 329 + strfilter__delete(params->filter); 330 + nsinfo__put(params->nsi); 331 + zfree(&params); 323 332 } 324 333 325 334 static void pr_err_with_code(const char *msg, int err) ··· 355 346 if (ret < 0) 356 347 goto out_cleanup; 357 348 358 - if (params.command == 'D') { /* it shows definition */ 349 + if (params->command == 'D') { /* it shows definition */ 359 350 if (probe_conf.bootconfig) 360 351 ret = show_bootconfig_events(pevs, npevs); 361 352 else ··· 644 635 usage_with_options_msg(probe_usage, options, 645 636 "'-' is not supported.\n"); 646 637 } 647 - if (params.command && params.command != 'a') { 638 + if (params->command && params->command != 'a') { 648 639 usage_with_options_msg(probe_usage, options, 649 640 "another command except --add is set.\n"); 650 641 } ··· 653 644 pr_err_with_code(" Error: Command Parse Error.", ret); 654 645 return ret; 655 646 } 656 - params.command = 'a'; 647 + params->command = 'a'; 657 648 } 658 649 659 650 ret = symbol__validate_sym_arguments(); ··· 673 664 * nor change running kernel. So if user gives offline vmlinux, 674 665 * ignore its buildid. 675 666 */ 676 - if (!strchr("lda", params.command) && symbol_conf.vmlinux_name) 667 + if (!strchr("lda", params->command) && symbol_conf.vmlinux_name) 677 668 symbol_conf.ignore_vmlinux_buildid = true; 678 669 679 - switch (params.command) { 670 + switch (params->command) { 680 671 case 'l': 681 - if (params.uprobes) { 672 + if (params->uprobes) { 682 673 pr_err(" Error: Don't use --list with --exec.\n"); 683 674 parse_options_usage(probe_usage, options, "l", true); 684 675 parse_options_usage(NULL, options, "x", true); 685 676 return -EINVAL; 686 677 } 687 - ret = show_perf_probe_events(params.filter); 678 + ret = show_perf_probe_events(params->filter); 688 679 if (ret < 0) 689 680 pr_err_with_code(" Error: Failed to show event list.", ret); 690 681 return ret; 691 682 case 'F': 692 - ret = show_available_funcs(params.target, params.nsi, 693 - params.filter, params.uprobes); 683 + ret = show_available_funcs(params->target, params->nsi, 684 + params->filter, params->uprobes); 694 685 if (ret < 0) 695 686 pr_err_with_code(" Error: Failed to show functions.", ret); 696 687 return ret; 697 688 #ifdef HAVE_DWARF_SUPPORT 698 689 case 'L': 699 - ret = show_line_range(&params.line_range, params.target, 700 - params.nsi, params.uprobes); 690 + ret = show_line_range(&params->line_range, params->target, 691 + params->nsi, params->uprobes); 701 692 if (ret < 0) 702 693 pr_err_with_code(" Error: Failed to show lines.", ret); 703 694 return ret; 704 695 case 'V': 705 - if (!params.filter) 706 - params.filter = strfilter__new(DEFAULT_VAR_FILTER, 696 + if (!params->filter) 697 + params->filter = strfilter__new(DEFAULT_VAR_FILTER, 707 698 NULL); 708 699 709 - ret = show_available_vars(params.events, params.nevents, 710 - params.filter); 700 + ret = show_available_vars(params->events, params->nevents, 701 + params->filter); 711 702 if (ret < 0) 712 703 pr_err_with_code(" Error: Failed to show vars.", ret); 713 704 return ret; 714 705 #endif 715 706 case 'd': 716 - ret = perf_del_probe_events(params.filter); 707 + ret = perf_del_probe_events(params->filter); 717 708 if (ret < 0) { 718 709 pr_err_with_code(" Error: Failed to delete events.", ret); 719 710 return ret; 720 711 } 721 712 break; 722 713 case 'D': 723 - if (probe_conf.bootconfig && params.uprobes) { 714 + if (probe_conf.bootconfig && params->uprobes) { 724 715 pr_err(" Error: --bootconfig doesn't support uprobes.\n"); 725 716 return -EINVAL; 726 717 } ··· 728 719 case 'a': 729 720 730 721 /* Ensure the last given target is used */ 731 - if (params.target && !params.target_used) { 722 + if (params->target && !params->target_used) { 732 723 pr_err(" Error: -x/-m must follow the probe definitions.\n"); 733 724 parse_options_usage(probe_usage, options, "m", true); 734 725 parse_options_usage(NULL, options, "x", true); 735 726 return -EINVAL; 736 727 } 737 728 738 - ret = perf_add_probe_events(params.events, params.nevents); 729 + ret = perf_add_probe_events(params->events, params->nevents); 739 730 if (ret < 0) { 740 731 741 732 /* 742 733 * When perf_add_probe_events() fails it calls 743 734 * cleanup_perf_probe_events(pevs, npevs), i.e. 744 - * cleanup_perf_probe_events(params.events, params.nevents), which 735 + * cleanup_perf_probe_events(params->events, params->nevents), which 745 736 * will call clear_perf_probe_event(), so set nevents to zero 746 737 * to avoid cleanup_params() to call clear_perf_probe_event() again 747 738 * on the same pevs. 748 739 */ 749 - params.nevents = 0; 740 + params->nevents = 0; 750 741 pr_err_with_code(" Error: Failed to add events.", ret); 751 742 return ret; 752 743 }