Linux Perf
scripts.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0
2 #include <elf.h>
3 #include <inttypes.h>
4 #include <sys/ttydefaults.h>
5 #include <string.h>
6 #include "../../util/sort.h"
7 #include "../../util/util.h"
8 #include "../../util/hist.h"
9 #include "../../util/debug.h"
10 #include "../../util/symbol.h"
11 #include "../browser.h"
12 #include "../helpline.h"
13 #include "../libslang.h"
14 
15 /* 2048 lines should be enough for a script output */
16 #define MAX_LINES 2048
17 
18 /* 160 bytes for one output line */
19 #define AVERAGE_LINE_LEN 160
20 
21 struct script_line {
22  struct list_head node;
24 };
25 
27  struct ui_browser b;
28  struct list_head entries;
29  const char *script_name;
30  int nr_lines;
31 };
32 
33 #define SCRIPT_NAMELEN 128
34 #define SCRIPT_MAX_NO 64
35 /*
36  * Usually the full path for a script is:
37  * /home/username/libexec/perf-core/scripts/python/xxx.py
38  * /home/username/libexec/perf-core/scripts/perl/xxx.pl
39  * So 256 should be long enough to contain the full path.
40  */
41 #define SCRIPT_FULLPATH_LEN 256
42 
43 /*
44  * When success, will copy the full path of the selected script
45  * into the buffer pointed by script_name, and return 0.
46  * Return -1 on failure.
47  */
48 static int list_scripts(char *script_name)
49 {
50  char *buf, *names[SCRIPT_MAX_NO], *paths[SCRIPT_MAX_NO];
51  int i, num, choice, ret = -1;
52 
53  /* Preset the script name to SCRIPT_NAMELEN */
55  if (!buf)
56  return ret;
57 
58  for (i = 0; i < SCRIPT_MAX_NO; i++) {
59  names[i] = buf + i * (SCRIPT_NAMELEN + SCRIPT_FULLPATH_LEN);
60  paths[i] = names[i] + SCRIPT_NAMELEN;
61  }
62 
63  num = find_scripts(names, paths);
64  if (num > 0) {
65  choice = ui__popup_menu(num, names);
66  if (choice < num && choice >= 0) {
67  strcpy(script_name, paths[choice]);
68  ret = 0;
69  }
70  }
71 
72  free(buf);
73  return ret;
74 }
75 
76 static void script_browser__write(struct ui_browser *browser,
77  void *entry, int row)
78 {
79  struct script_line *sline = list_entry(entry, struct script_line, node);
80  bool current_entry = ui_browser__is_current_entry(browser, row);
81 
82  ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED :
84 
85  ui_browser__write_nstring(browser, sline->line, browser->width);
86 }
87 
88 static int script_browser__run(struct perf_script_browser *browser)
89 {
90  int key;
91 
92  if (ui_browser__show(&browser->b, browser->script_name,
93  "Press ESC to exit") < 0)
94  return -1;
95 
96  while (1) {
97  key = ui_browser__run(&browser->b, 0);
98 
99  /* We can add some special key handling here if needed */
100  break;
101  }
102 
103  ui_browser__hide(&browser->b);
104  return key;
105 }
106 
107 
108 int script_browse(const char *script_opt)
109 {
111  char *line = NULL;
112  size_t len = 0;
113  ssize_t retlen;
114  int ret = -1, nr_entries = 0;
115  FILE *fp;
116  void *buf;
117  struct script_line *sline;
118 
119  struct perf_script_browser script = {
120  .b = {
123  .write = script_browser__write,
124  },
125  .script_name = script_name,
126  };
127 
128  INIT_LIST_HEAD(&script.entries);
129 
130  /* Save each line of the output in one struct script_line object. */
131  buf = zalloc((sizeof(*sline)) * MAX_LINES);
132  if (!buf)
133  return -1;
134  sline = buf;
135 
136  memset(script_name, 0, SCRIPT_FULLPATH_LEN);
137  if (list_scripts(script_name))
138  goto exit;
139 
140  sprintf(cmd, "perf script -s %s ", script_name);
141 
142  if (script_opt)
143  strcat(cmd, script_opt);
144 
145  if (input_name) {
146  strcat(cmd, " -i ");
147  strcat(cmd, input_name);
148  }
149 
150  strcat(cmd, " 2>&1");
151 
152  fp = popen(cmd, "r");
153  if (!fp)
154  goto exit;
155 
156  while ((retlen = getline(&line, &len, fp)) != -1) {
157  strncpy(sline->line, line, AVERAGE_LINE_LEN);
158 
159  /* If one output line is very large, just cut it short */
160  if (retlen >= AVERAGE_LINE_LEN) {
161  sline->line[AVERAGE_LINE_LEN - 1] = '\0';
162  sline->line[AVERAGE_LINE_LEN - 2] = '\n';
163  }
164  list_add_tail(&sline->node, &script.entries);
165 
166  if (script.b.width < retlen)
167  script.b.width = retlen;
168 
169  if (nr_entries++ >= MAX_LINES - 1)
170  break;
171  sline++;
172  }
173 
174  if (script.b.width > AVERAGE_LINE_LEN)
175  script.b.width = AVERAGE_LINE_LEN;
176 
177  free(line);
178  pclose(fp);
179 
180  script.nr_lines = nr_entries;
181  script.b.nr_entries = nr_entries;
182  script.b.entries = &script.entries;
183 
184  ret = script_browser__run(&script);
185 exit:
186  free(buf);
187  return ret;
188 }
Definition: mem2node.c:7
#define AVERAGE_LINE_LEN
Definition: scripts.c:19
#define HE_COLORSET_NORMAL
Definition: browser.h:10
static char const * script_name
int ui_browser__show(struct ui_browser *browser, const char *title, const char *helpline,...)
Definition: browser.c:277
const char * script_name
Definition: scripts.c:29
x86 movsq based memset() in arch/x86/lib/memset_64.S") MEMSET_FN(memset_erms
void * malloc(YYSIZE_T)
const char * key
Definition: bpf-loader.c:196
bool ui_browser__is_current_entry(struct ui_browser *browser, unsigned row)
Definition: browser.c:190
#define SCRIPT_MAX_NO
Definition: scripts.c:34
unsigned int ui_browser__list_head_refresh(struct ui_browser *browser)
Definition: browser.c:497
void ui_browser__list_head_seek(struct ui_browser *browser, off_t offset, int whence)
Definition: browser.c:104
static int entry(u64 ip, struct unwind_info *ui)
Definition: unwind-libdw.c:71
struct list_head entries
Definition: scripts.c:28
const char * input_name
Definition: perf.c:40
struct list_head node
Definition: scripts.c:22
unsigned int(* refresh)(struct ui_browser *browser)
Definition: browser.h:26
void ui_browser__write_nstring(struct ui_browser *browser __maybe_unused, const char *msg, unsigned int width)
Definition: browser.c:58
static int list_scripts(char *script_name)
Definition: scripts.c:48
#define SCRIPT_NAMELEN
Definition: scripts.c:33
u32 nr_entries
Definition: browser.h:30
static int script_browser__run(struct perf_script_browser *browser)
Definition: scripts.c:88
char line[AVERAGE_LINE_LEN]
Definition: scripts.c:23
#define HE_COLORSET_SELECTED
Definition: browser.h:11
int ui_browser__run(struct ui_browser *browser, int delay_secs)
Definition: browser.c:385
void free(void *)
void ui_browser__hide(struct ui_browser *browser)
Definition: browser.c:303
#define SCRIPT_FULLPATH_LEN
Definition: scripts.c:41
int ui_browser__set_color(struct ui_browser *browser, int color)
Definition: browser.c:33
void * entries
Definition: browser.h:18
int find_scripts(char **scripts_array, char **scripts_path_array)
struct ui_browser b
Definition: scripts.c:27
int script_browse(const char *script_opt)
Definition: scripts.c:108
int ui__popup_menu(int argc, char *const argv[])
Definition: util.c:60
#define MAX_LINES
Definition: scripts.c:16
static void script_browser__write(struct ui_browser *browser, void *entry, int row)
Definition: scripts.c:76
void static void * zalloc(size_t size)
Definition: util.h:20
u16 width
Definition: browser.h:19