static void process_function(struct pevent *pevent, struct pevent_record *record) { unsigned long long parent_ip; unsigned long long ip; unsigned long long val; const char *parent; const char *func; int pid; int ret; ret = pevent_read_number_field(common_pid_field, record->data, &val); if (ret < 0) die("no pid field for function?"); ret = pevent_read_number_field(function_ip_field, record->data, &ip); if (ret < 0) die("no ip field for function?"); ret = pevent_read_number_field(function_parent_ip_field, record->data, &parent_ip); if (ret < 0) die("no parent ip field for function?"); pid = val; func = pevent_find_function(pevent, ip); parent = pevent_find_function(pevent, parent_ip); if (current_pid >= 0 && pid != current_pid) { save_stack(); restore_stack(pid); } current_pid = pid; if (ips_idx) { if (ips[ips_idx - 1] == parent) push_stack_func(func); else { save_call_chain(pid, ips, ips_idx, 0); while (ips_idx) { pop_stack_func(); if (ips[ips_idx - 1] == parent) { push_stack_func(func); break; } } } } /* The above check can set ips_idx to zero again */ if (!ips_idx) { push_stack_func(parent); push_stack_func(func); } }
static void process_kmalloc(struct pevent *pevent, struct pevent_record *record, struct format_field *callsite_field, struct format_field *bytes_req_field, struct format_field *bytes_alloc_field, struct format_field *ptr_field) { unsigned long long callsite; unsigned long long val; unsigned long long ptr; unsigned int req; int alloc; const char *func; pevent_read_number_field(callsite_field, record->data, &callsite); pevent_read_number_field(bytes_req_field, record->data, &val); req = val; pevent_read_number_field(bytes_alloc_field, record->data, &val); alloc = val; pevent_read_number_field(ptr_field, record->data, &ptr); func = pevent_find_function(pevent, callsite); add_kmalloc(func, ptr, req, alloc); }
static int function_handler(struct trace_seq *s, struct pevent_record *record, struct event_format *event, void *context) { struct pevent *pevent = event->pevent; unsigned long long function; unsigned long long pfunction; const char *func; const char *parent; int index; if (pevent_get_field_val(s, event, "ip", record, &function, 1)) return trace_seq_putc(s, '!'); func = pevent_find_function(pevent, function); if (pevent_get_field_val(s, event, "parent_ip", record, &pfunction, 1)) return trace_seq_putc(s, '!'); parent = pevent_find_function(pevent, pfunction); index = add_and_get_index(parent, func, record->cpu); trace_seq_printf(s, "%*s", index*3, ""); if (func) trace_seq_printf(s, "%s", func); else trace_seq_printf(s, "0x%llx", function); trace_seq_printf(s, " <-- "); if (parent) trace_seq_printf(s, "%s", parent); else trace_seq_printf(s, "0x%llx", pfunction); return 0; }
static void process_function_graph_entry(struct pevent *pevent, struct pevent_record *record) { unsigned long long depth; unsigned long long ip; unsigned long long val; const char *func; int pid; int ret; ret = pevent_read_number_field(common_pid_field, record->data, &val); if (ret < 0) die("no pid field for function graph entry?"); ret = pevent_read_number_field(function_graph_entry_func_field, record->data, &ip); if (ret < 0) die("no ip field for function graph entry?"); ret = pevent_read_number_field(function_graph_entry_depth_field, record->data, &depth); if (ret < 0) die("no parent ip field for function entry?"); pid = val; func = pevent_find_function(pevent, ip); if (current_pid >= 0 && pid != current_pid) { save_stack(); restore_stack(pid); } current_pid = pid; if (depth != ips_idx) { save_call_chain(pid, ips, ips_idx, 0); while (ips_idx > depth) pop_stack_func(); } func_depth = depth; push_stack_func(func); }
static const char *get_field_str(struct filter_arg *arg, struct pevent_record *record) { struct event_format *event; struct pevent *pevent; unsigned long long addr; const char *val = NULL; char hex[64]; /* If the field is not a string convert it */ if (arg->str.field->flags & FIELD_IS_STRING) { val = record->data + arg->str.field->offset; /* * We need to copy the data since we can't be sure the field * is null terminated. */ if (*(val + arg->str.field->size - 1)) { /* copy it */ memcpy(arg->str.buffer, val, arg->str.field->size); /* the buffer is already NULL terminated */ val = arg->str.buffer; } } else { event = arg->str.field->event; pevent = event->pevent; addr = get_value(event, arg->str.field, record); if (arg->str.field->flags & (FIELD_IS_POINTER | FIELD_IS_LONG)) /* convert to a kernel symbol */ val = pevent_find_function(pevent, addr); if (val == NULL) { /* just use the hex of the string name */ snprintf(hex, 64, "0x%llx", addr); val = hex; } } return val; }
static void process_kernel_stack(struct pevent *pevent, struct pevent_record *record) { struct format_field *field = kernel_stack_caller_field; unsigned long long val; void *data = record->data; int do_restore = 0; int pid; int ret; ret = pevent_read_number_field(common_pid_field, record->data, &val); if (ret < 0) die("no pid field for function?"); pid = val; if (pending_pid >= 0 && pid != pending_pid) { reset_pending_stack(); return; } if (!field) die("no caller field for kernel stack?"); if (pending_pid >= 0) { if (current_pid >= 0) { save_stack(); do_restore = 1; } } else { /* function stack trace? */ if (current_pid >= 0) { copy_stack_to_pending(current_pid); free(ips); reset_stack(); } } current_pid = pid; /* Need to start at the end of the callers and work up */ for (data += field->offset; data < record->data + record->size; data += long_size) { unsigned long long addr; addr = pevent_read_number(pevent, data, long_size); if ((long_size == 8 && addr == (unsigned long long)-1) || ((int)addr == -1)) break; } for (data -= long_size; data >= record->data + field->offset; data -= long_size) { unsigned long long addr; const char *func; addr = pevent_read_number(pevent, data, long_size); func = pevent_find_function(pevent, addr); if (func) push_stack_func(func); } if (pending_pid >= 0) { push_stack_func(pending_ips[pending_ips_idx - 1]); reset_pending_stack(); } save_call_chain(current_pid, ips, ips_idx, 1); if (do_restore) restore_stack(current_pid); }