1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2009, Steven Rostedt <srostedt@redhat.com> 4 */ 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <string.h> 8 #include <errno.h> 9 10 #include "debug.h" 11 #include "trace-event.h" 12 13 #include <linux/ctype.h> 14 #include <linux/kernel.h> 15 #include <event-parse.h> 16 17 static int get_common_field(struct scripting_context *context, 18 int *offset, int *size, const char *type) 19 { 20 struct tep_handle *pevent = context->pevent; 21 struct tep_event *event; 22 struct tep_format_field *field; 23 24 if (!*size) { 25 26 event = tep_get_first_event(pevent); 27 if (!event) 28 return 0; 29 30 field = tep_find_common_field(event, type); 31 if (!field) 32 return 0; 33 *offset = field->offset; 34 *size = field->size; 35 } 36 37 return tep_read_number(pevent, context->event_data + *offset, *size); 38 } 39 40 int common_lock_depth(struct scripting_context *context) 41 { 42 static int offset; 43 static int size; 44 int ret; 45 46 ret = get_common_field(context, &size, &offset, 47 "common_lock_depth"); 48 if (ret < 0) 49 return -1; 50 51 return ret; 52 } 53 54 int common_flags(struct scripting_context *context) 55 { 56 static int offset; 57 static int size; 58 int ret; 59 60 ret = get_common_field(context, &size, &offset, 61 "common_flags"); 62 if (ret < 0) 63 return -1; 64 65 return ret; 66 } 67 68 int common_pc(struct scripting_context *context) 69 { 70 static int offset; 71 static int size; 72 int ret; 73 74 ret = get_common_field(context, &size, &offset, 75 "common_preempt_count"); 76 if (ret < 0) 77 return -1; 78 79 return ret; 80 } 81 82 unsigned long long 83 raw_field_value(struct tep_event *event, const char *name, void *data) 84 { 85 struct tep_format_field *field; 86 unsigned long long val; 87 88 field = tep_find_any_field(event, name); 89 if (!field) 90 return 0ULL; 91 92 tep_read_number_field(field, data, &val); 93 94 return val; 95 } 96 97 unsigned long long read_size(struct tep_event *event, void *ptr, int size) 98 { 99 return tep_read_number(event->tep, ptr, size); 100 } 101 102 void event_format__fprintf(struct tep_event *event, 103 int cpu, void *data, int size, FILE *fp) 104 { 105 struct tep_record record; 106 struct trace_seq s; 107 108 memset(&record, 0, sizeof(record)); 109 record.cpu = cpu; 110 record.size = size; 111 record.data = data; 112 113 trace_seq_init(&s); 114 tep_print_event(event->tep, &s, &record, "%s", TEP_PRINT_INFO); 115 trace_seq_do_fprintf(&s, fp); 116 trace_seq_destroy(&s); 117 } 118 119 /* 120 * prev_state is of size long, which is 32 bits on 32 bit architectures. 121 * As it needs to have the same bits for both 32 bit and 64 bit architectures 122 * we can just assume that the flags we care about will all be within 123 * the 32 bits. 124 */ 125 #define MAX_STATE_BITS 32 126 127 static const char *convert_sym(struct tep_print_flag_sym *sym) 128 { 129 static char save_states[MAX_STATE_BITS + 1]; 130 131 memset(save_states, 0, sizeof(save_states)); 132 133 /* This is the flags for the prev_state_field, now make them into a string */ 134 for (; sym; sym = sym->next) { 135 long bitmask = strtoul(sym->value, NULL, 0); 136 int i; 137 138 for (i = 0; !(bitmask & 1); i++) 139 bitmask >>= 1; 140 141 if (i >= MAX_STATE_BITS) 142 continue; 143 144 save_states[i] = sym->str[0]; 145 } 146 147 return save_states; 148 } 149 150 static struct tep_print_arg_field * 151 find_arg_field(struct tep_format_field *prev_state_field, struct tep_print_arg *arg) 152 { 153 struct tep_print_arg_field *field; 154 155 if (!arg) 156 return NULL; 157 158 if (arg->type == TEP_PRINT_FIELD) 159 return &arg->field; 160 161 if (arg->type == TEP_PRINT_OP) { 162 field = find_arg_field(prev_state_field, arg->op.left); 163 if (field && field->field == prev_state_field) 164 return field; 165 field = find_arg_field(prev_state_field, arg->op.right); 166 if (field && field->field == prev_state_field) 167 return field; 168 } 169 return NULL; 170 } 171 172 static struct tep_print_flag_sym * 173 test_flags(struct tep_format_field *prev_state_field, struct tep_print_arg *arg) 174 { 175 struct tep_print_arg_field *field; 176 177 field = find_arg_field(prev_state_field, arg->flags.field); 178 if (!field) 179 return NULL; 180 181 return arg->flags.flags; 182 } 183 184 static struct tep_print_flag_sym * 185 search_op(struct tep_format_field *prev_state_field, struct tep_print_arg *arg) 186 { 187 struct tep_print_flag_sym *sym = NULL; 188 189 if (!arg) 190 return NULL; 191 192 if (arg->type == TEP_PRINT_OP) { 193 sym = search_op(prev_state_field, arg->op.left); 194 if (sym) 195 return sym; 196 197 sym = search_op(prev_state_field, arg->op.right); 198 if (sym) 199 return sym; 200 } else if (arg->type == TEP_PRINT_FLAGS) { 201 sym = test_flags(prev_state_field, arg); 202 } 203 204 return sym; 205 } 206 207 const char *parse_task_states(struct tep_format_field *state_field) 208 { 209 struct tep_print_flag_sym *sym; 210 struct tep_print_arg *arg; 211 struct tep_event *event; 212 213 event = state_field->event; 214 215 /* 216 * Look at the event format fields, and search for where 217 * the prev_state is parsed via the format flags. 218 */ 219 for (arg = event->print_fmt.args; arg; arg = arg->next) { 220 /* 221 * Currently, the __print_flags() for the prev_state 222 * is embedded in operations, so they too must be 223 * searched. 224 */ 225 sym = search_op(state_field, arg); 226 if (sym) 227 return convert_sym(sym); 228 } 229 return NULL; 230 } 231 232 void parse_ftrace_printk(struct tep_handle *pevent, 233 char *file, unsigned int size __maybe_unused) 234 { 235 unsigned long long addr; 236 char *printk; 237 char *line; 238 char *next = NULL; 239 char *addr_str; 240 char *fmt = NULL; 241 242 line = strtok_r(file, "\n", &next); 243 while (line) { 244 addr_str = strtok_r(line, ":", &fmt); 245 if (!addr_str) { 246 pr_warning("printk format with empty entry"); 247 break; 248 } 249 addr = strtoull(addr_str, NULL, 16); 250 /* fmt still has a space, skip it */ 251 printk = strdup(fmt+1); 252 line = strtok_r(NULL, "\n", &next); 253 tep_register_print_string(pevent, printk, addr); 254 free(printk); 255 } 256 } 257 258 void parse_saved_cmdline(struct tep_handle *pevent, 259 char *file, unsigned int size __maybe_unused) 260 { 261 char comm[17]; /* Max comm length in the kernel is 16. */ 262 char *line; 263 char *next = NULL; 264 int pid; 265 266 line = strtok_r(file, "\n", &next); 267 while (line) { 268 if (sscanf(line, "%d %16s", &pid, comm) == 2) 269 tep_register_comm(pevent, comm, pid); 270 line = strtok_r(NULL, "\n", &next); 271 } 272 } 273 274 int parse_ftrace_file(struct tep_handle *pevent, char *buf, unsigned long size) 275 { 276 return tep_parse_event(pevent, buf, size, "ftrace"); 277 } 278 279 int parse_event_file(struct tep_handle *pevent, 280 char *buf, unsigned long size, char *sys) 281 { 282 return tep_parse_event(pevent, buf, size, sys); 283 } 284 285 struct flag { 286 const char *name; 287 unsigned long long value; 288 }; 289 290 static const struct flag flags[] = { 291 { "HI_SOFTIRQ", 0 }, 292 { "TIMER_SOFTIRQ", 1 }, 293 { "NET_TX_SOFTIRQ", 2 }, 294 { "NET_RX_SOFTIRQ", 3 }, 295 { "BLOCK_SOFTIRQ", 4 }, 296 { "IRQ_POLL_SOFTIRQ", 5 }, 297 { "TASKLET_SOFTIRQ", 6 }, 298 { "SCHED_SOFTIRQ", 7 }, 299 { "HRTIMER_SOFTIRQ", 8 }, 300 { "RCU_SOFTIRQ", 9 }, 301 302 { "HRTIMER_NORESTART", 0 }, 303 { "HRTIMER_RESTART", 1 }, 304 }; 305 306 unsigned long long eval_flag(const char *flag) 307 { 308 int i; 309 310 /* 311 * Some flags in the format files do not get converted. 312 * If the flag is not numeric, see if it is something that 313 * we already know about. 314 */ 315 if (isdigit(flag[0])) 316 return strtoull(flag, NULL, 0); 317 318 for (i = 0; i < (int)(ARRAY_SIZE(flags)); i++) 319 if (strcmp(flags[i].name, flag) == 0) 320 return flags[i].value; 321 322 return 0; 323 } 324