* 'perf-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: perf session: Make events_stats u64 to avoid overflow on 32-bit arches hw-breakpoints: Fix hardware breakpoints -> perf events dependency perf events: Dont report side-band events on each cpu for per-task-per-cpu events perf events, x86/stacktrace: Fix performance/softlockup by providing a special frame pointer-only stack walker perf events, x86/stacktrace: Make stack walking optional perf events: Remove unused perf_counter.h header file perf probe: Check new event name kprobe-tracer: Check new event/group name perf probe: Check whether debugfs path is correct perf probe: Fix libdwarf include path for Debian
Unified · Split
| @@ -135,9 +135,7 @@ config HAVE_DEFAULT_NO_SPIN_MUTEXES · 134 unmodified lines | ||
| 135 | 135 | |
| 136 | 136 | config HAVE_HW_BREAKPOINT |
| 137 | 137 | bool |
| 138 | − depends on HAVE_PERF_EVENTS | |
| 139 | − select ANON_INODES | |
| 140 | − select PERF_EVENTS | |
| 138 | + depends on PERF_EVENTS | |
| 141 | 139 | |
| 142 | 140 | config HAVE_USER_RETURN_NOTIFIER |
| 143 | 141 | bool |
| @@ -50,6 +50,8 @@ config X86 · 49 unmodified lines | ||
| 50 | 50 | select HAVE_KERNEL_BZIP2 |
| 51 | 51 | select HAVE_KERNEL_LZMA |
| 52 | 52 | select HAVE_HW_BREAKPOINT |
| 53 | + select PERF_EVENTS | |
| 54 | + select ANON_INODES | |
| 53 | 55 | select HAVE_ARCH_KMEMCHECK |
| 54 | 56 | select HAVE_USER_RETURN_NOTIFIER |
| 55 | 57 | |
| @@ -5,6 +5,29 @@ extern int kstack_depth_to_print; · 4 unmodified lines | ||
| 5 | 5 | |
| 6 | 6 | int x86_is_stack_id(int id, char *name); |
| 7 | 7 | |
| 8 | +struct thread_info; | |
| 9 | +struct stacktrace_ops; | |
| 10 | + | |
| 11 | +typedef unsigned long (*walk_stack_t)(struct thread_info *tinfo, | |
| 12 | + unsigned long *stack, | |
| 13 | + unsigned long bp, | |
| 14 | + const struct stacktrace_ops *ops, | |
| 15 | + void *data, | |
| 16 | + unsigned long *end, | |
| 17 | + int *graph); | |
| 18 | + | |
| 19 | +extern unsigned long | |
| 20 | +print_context_stack(struct thread_info *tinfo, | |
| 21 | + unsigned long *stack, unsigned long bp, | |
| 22 | + const struct stacktrace_ops *ops, void *data, | |
| 23 | + unsigned long *end, int *graph); | |
| 24 | + | |
| 25 | +extern unsigned long | |
| 26 | +print_context_stack_bp(struct thread_info *tinfo, | |
| 27 | + unsigned long *stack, unsigned long bp, | |
| 28 | + const struct stacktrace_ops *ops, void *data, | |
| 29 | + unsigned long *end, int *graph); | |
| 30 | + | |
| 8 | 31 | /* Generic stack tracer with callbacks */ |
| 9 | 32 | |
| 10 | 33 | struct stacktrace_ops { |
| @@ -14,6 +37,7 @@ struct stacktrace_ops { · 3 unmodified lines | ||
| 14 | 37 | void (*address)(void *data, unsigned long address, int reliable); |
| 15 | 38 | /* On negative return stop dumping */ |
| 16 | 39 | int (*stack)(void *data, char *name); |
| 40 | + walk_stack_t walk_stack; | |
| 17 | 41 | }; |
| 18 | 42 | |
| 19 | 43 | void dump_trace(struct task_struct *tsk, struct pt_regs *regs, |
| @@ -2336,6 +2336,7 @@ static const struct stacktrace_ops backtrace_ops = { · 2335 unmodified lines | ||
| 2336 | 2336 | .warning_symbol = backtrace_warning_symbol, |
| 2337 | 2337 | .stack = backtrace_stack, |
| 2338 | 2338 | .address = backtrace_address, |
| 2339 | + .walk_stack = print_context_stack_bp, | |
| 2339 | 2340 | }; |
| 2340 | 2341 | |
| 2341 | 2342 | #include "../dumpstack.h" |
| @@ -109,6 +109,30 @@ print_context_stack(struct thread_info *tinfo, · 108 unmodified lines | ||
| 109 | 109 | } |
| 110 | 110 | return bp; |
| 111 | 111 | } |
| 112 | +EXPORT_SYMBOL_GPL(print_context_stack); | |
| 113 | + | |
| 114 | +unsigned long | |
| 115 | +print_context_stack_bp(struct thread_info *tinfo, | |
| 116 | + unsigned long *stack, unsigned long bp, | |
| 117 | + const struct stacktrace_ops *ops, void *data, | |
| 118 | + unsigned long *end, int *graph) | |
| 119 | +{ | |
| 120 | + struct stack_frame *frame = (struct stack_frame *)bp; | |
| 121 | + unsigned long *ret_addr = &frame->return_address; | |
| 122 | + | |
| 123 | + while (valid_stack_ptr(tinfo, ret_addr, sizeof(*ret_addr), end)) { | |
| 124 | + unsigned long addr = *ret_addr; | |
| 125 | + | |
| 126 | + if (__kernel_text_address(addr)) { | |
| 127 | + ops->address(data, addr, 1); | |
| 128 | + frame = frame->next_frame; | |
| 129 | + ret_addr = &frame->return_address; | |
| 130 | + print_ftrace_graph_addr(addr, data, ops, tinfo, graph); | |
| 131 | + } | |
| 132 | + } | |
| 133 | + return (unsigned long)frame; | |
| 134 | +} | |
| 135 | +EXPORT_SYMBOL_GPL(print_context_stack_bp); | |
| 112 | 136 | |
| 113 | 137 | |
| 114 | 138 | static void |
| @@ -141,10 +165,11 @@ static void print_trace_address(void *data, unsigned long addr, int reliable) · 26 unmodified lines | ||
| 141 | 165 | } |
| 142 | 166 | |
| 143 | 167 | static const struct stacktrace_ops print_trace_ops = { |
| 144 | − .warning = print_trace_warning, | |
| 145 | − .warning_symbol = print_trace_warning_symbol, | |
| 146 | − .stack = print_trace_stack, | |
| 147 | − .address = print_trace_address, | |
| 168 | + .warning = print_trace_warning, | |
| 169 | + .warning_symbol = print_trace_warning_symbol, | |
| 170 | + .stack = print_trace_stack, | |
| 171 | + .address = print_trace_address, | |
| 172 | + .walk_stack = print_context_stack, | |
| 148 | 173 | }; |
| 149 | 174 | |
| 150 | 175 | void |
| @@ -14,12 +14,6 @@ · 13 unmodified lines | ||
| 14 | 14 | #define get_bp(bp) asm("movq %%rbp, %0" : "=r" (bp) :) |
| 15 | 15 | #endif |
| 16 | 16 | |
| 17 | −extern unsigned long | |
| 18 | −print_context_stack(struct thread_info *tinfo, | |
| 19 | − unsigned long *stack, unsigned long bp, | |
| 20 | − const struct stacktrace_ops *ops, void *data, | |
| 21 | − unsigned long *end, int *graph); | |
| 22 | − | |
| 23 | 17 | extern void |
| 24 | 18 | show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs, |
| 25 | 19 | unsigned long *stack, unsigned long bp, char *log_lvl); |
| @@ -58,7 +58,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs, · 57 unmodified lines | ||
| 58 | 58 | |
| 59 | 59 | context = (struct thread_info *) |
| 60 | 60 | ((unsigned long)stack & (~(THREAD_SIZE - 1))); |
| 61 | − bp = print_context_stack(context, stack, bp, ops, data, NULL, &graph); | |
| 61 | + bp = ops->walk_stack(context, stack, bp, ops, data, NULL, &graph); | |
| 62 | 62 | |
| 63 | 63 | stack = (unsigned long *)context->previous_esp; |
| 64 | 64 | if (!stack) |
| @@ -188,8 +188,8 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs, · 187 unmodified lines | ||
| 188 | 188 | if (ops->stack(data, id) < 0) |
| 189 | 189 | break; |
| 190 | 190 | |
| 191 | − bp = print_context_stack(tinfo, stack, bp, ops, | |
| 192 | − data, estack_end, &graph); | |
| 191 | + bp = ops->walk_stack(tinfo, stack, bp, ops, | |
| 192 | + data, estack_end, &graph); | |
| 193 | 193 | ops->stack(data, "<EOE>"); |
| 194 | 194 | /* |
| 195 | 195 | * We link to the next stack via the |
| @@ -53,17 +53,19 @@ save_stack_address_nosched(void *data, unsigned long addr, int reliable) · 52 unmodified lines | ||
| 53 | 53 | } |
| 54 | 54 | |
| 55 | 55 | static const struct stacktrace_ops save_stack_ops = { |
| 56 | − .warning = save_stack_warning, | |
| 57 | − .warning_symbol = save_stack_warning_symbol, | |
| 58 | − .stack = save_stack_stack, | |
| 59 | − .address = save_stack_address, | |
| 56 | + .warning = save_stack_warning, | |
| 57 | + .warning_symbol = save_stack_warning_symbol, | |
| 58 | + .stack = save_stack_stack, | |
| 59 | + .address = save_stack_address, | |
| 60 | + .walk_stack = print_context_stack, | |
| 60 | 61 | }; |
| 61 | 62 | |
| 62 | 63 | static const struct stacktrace_ops save_stack_ops_nosched = { |
| 63 | − .warning = save_stack_warning, | |
| 64 | − .warning_symbol = save_stack_warning_symbol, | |
| 65 | − .stack = save_stack_stack, | |
| 66 | − .address = save_stack_address_nosched, | |
| 64 | + .warning = save_stack_warning, | |
| 65 | + .warning_symbol = save_stack_warning_symbol, | |
| 66 | + .stack = save_stack_stack, | |
| 67 | + .address = save_stack_address_nosched, | |
| 68 | + .walk_stack = print_context_stack, | |
| 67 | 69 | }; |
| 68 | 70 | |
| 69 | 71 | /* |
| @@ -41,10 +41,11 @@ static void backtrace_address(void *data, unsigned long addr, int reliable) · 40 unmodified lines | ||
| 41 | 41 | } |
| 42 | 42 | |
| 43 | 43 | static struct stacktrace_ops backtrace_ops = { |
| 44 | − .warning = backtrace_warning, | |
| 45 | − .warning_symbol = backtrace_warning_symbol, | |
| 46 | − .stack = backtrace_stack, | |
| 47 | − .address = backtrace_address, | |
| 44 | + .warning = backtrace_warning, | |
| 45 | + .warning_symbol = backtrace_warning_symbol, | |
| 46 | + .stack = backtrace_stack, | |
| 47 | + .address = backtrace_address, | |
| 48 | + .walk_stack = print_context_stack, | |
| 48 | 49 | }; |
| 49 | 50 | |
| 50 | 51 | struct frame_head { |
| @@ -1,444 +0,0 @@ | ||
| 1 | −/* | |
| 2 | − * NOTE: this file will be removed in a future kernel release, it is | |
| 3 | − * provided as a courtesy copy of user-space code that relies on the | |
| 4 | − * old (pre-rename) symbols and constants. | |
| 5 | − * | |
| 6 | − * Performance events: | |
| 7 | − * | |
| 8 | − * Copyright (C) 2008-2009, Thomas Gleixner <tglx@linutronix.de> | |
| 9 | − * Copyright (C) 2008-2009, Red Hat, Inc., Ingo Molnar | |
| 10 | − * Copyright (C) 2008-2009, Red Hat, Inc., Peter Zijlstra | |
| 11 | − * | |
| 12 | − * Data type definitions, declarations, prototypes. | |
| 13 | − * | |
| 14 | − * Started by: Thomas Gleixner and Ingo Molnar | |
| 15 | − * | |
| 16 | − * For licencing details see kernel-base/COPYING | |
| 17 | − */ | |
| 18 | −#ifndef _LINUX_PERF_COUNTER_H | |
| 19 | −#define _LINUX_PERF_COUNTER_H | |
| 20 | − | |
| 21 | −#include <linux/types.h> | |
| 22 | −#include <linux/ioctl.h> | |
| 23 | −#include <asm/byteorder.h> | |
| 24 | − | |
| 25 | −/* | |
| 26 | − * User-space ABI bits: | |
| 27 | − */ | |
| 28 | − | |
| 29 | −/* | |
| 30 | − * attr.type | |
| 31 | − */ | |
| 32 | −enum perf_type_id { | |
| 33 | − PERF_TYPE_HARDWARE = 0, | |
| 34 | − PERF_TYPE_SOFTWARE = 1, | |
| 35 | − PERF_TYPE_TRACEPOINT = 2, | |
| 36 | − PERF_TYPE_HW_CACHE = 3, | |
| 37 | − PERF_TYPE_RAW = 4, | |
| 38 | − | |
| 39 | − PERF_TYPE_MAX, /* non-ABI */ | |
| 40 | −}; | |
| 41 | − | |
| 42 | −/* | |
| 43 | − * Generalized performance counter event types, used by the | |
| 44 | − * attr.event_id parameter of the sys_perf_counter_open() | |
| 45 | − * syscall: | |
| 46 | − */ | |
| 47 | −enum perf_hw_id { | |
| 48 | − /* | |
| 49 | − * Common hardware events, generalized by the kernel: | |
| 50 | − */ | |
| 51 | − PERF_COUNT_HW_CPU_CYCLES = 0, | |
| 52 | − PERF_COUNT_HW_INSTRUCTIONS = 1, | |
| 53 | − PERF_COUNT_HW_CACHE_REFERENCES = 2, | |
| 54 | − PERF_COUNT_HW_CACHE_MISSES = 3, | |
| 55 | − PERF_COUNT_HW_BRANCH_INSTRUCTIONS = 4, | |
| 56 | − PERF_COUNT_HW_BRANCH_MISSES = 5, | |
| 57 | − PERF_COUNT_HW_BUS_CYCLES = 6, | |
| 58 | − | |
| 59 | − PERF_COUNT_HW_MAX, /* non-ABI */ | |
| 60 | −}; | |
| 61 | − | |
| 62 | −/* | |
| 63 | − * Generalized hardware cache counters: | |
| 64 | − * | |
| 65 | − * { L1-D, L1-I, LLC, ITLB, DTLB, BPU } x | |
| 66 | − * { read, write, prefetch } x | |
| 67 | − * { accesses, misses } | |
| 68 | − */ | |
| 69 | −enum perf_hw_cache_id { | |
| 70 | − PERF_COUNT_HW_CACHE_L1D = 0, | |
| 71 | − PERF_COUNT_HW_CACHE_L1I = 1, | |
| 72 | − PERF_COUNT_HW_CACHE_LL = 2, | |
| 73 | − PERF_COUNT_HW_CACHE_DTLB = 3, | |
| 74 | − PERF_COUNT_HW_CACHE_ITLB = 4, | |
| 75 | − PERF_COUNT_HW_CACHE_BPU = 5, | |
| 76 | − | |
| 77 | − PERF_COUNT_HW_CACHE_MAX, /* non-ABI */ | |
| 78 | −}; | |
| 79 | − | |
| 80 | −enum perf_hw_cache_op_id { | |
| 81 | − PERF_COUNT_HW_CACHE_OP_READ = 0, | |
| 82 | − PERF_COUNT_HW_CACHE_OP_WRITE = 1, | |
| 83 | − PERF_COUNT_HW_CACHE_OP_PREFETCH = 2, | |
| 84 | − | |
| 85 | − PERF_COUNT_HW_CACHE_OP_MAX, /* non-ABI */ | |
| 86 | −}; | |
| 87 | − | |
| 88 | −enum perf_hw_cache_op_result_id { | |
| 89 | − PERF_COUNT_HW_CACHE_RESULT_ACCESS = 0, | |
| 90 | − PERF_COUNT_HW_CACHE_RESULT_MISS = 1, | |
| 91 | − | |
| 92 | − PERF_COUNT_HW_CACHE_RESULT_MAX, /* non-ABI */ | |
| 93 | −}; | |
| 94 | − | |
| 95 | −/* | |
| 96 | − * Special "software" counters provided by the kernel, even if the hardware | |
| 97 | − * does not support performance counters. These counters measure various | |
| 98 | − * physical and sw events of the kernel (and allow the profiling of them as | |
| 99 | − * well): | |
| 100 | − */ | |
| 101 | −enum perf_sw_ids { | |
| 102 | − PERF_COUNT_SW_CPU_CLOCK = 0, | |
| 103 | − PERF_COUNT_SW_TASK_CLOCK = 1, | |
| 104 | − PERF_COUNT_SW_PAGE_FAULTS = 2, | |
| 105 | − PERF_COUNT_SW_CONTEXT_SWITCHES = 3, | |
| 106 | − PERF_COUNT_SW_CPU_MIGRATIONS = 4, | |
| 107 | − PERF_COUNT_SW_PAGE_FAULTS_MIN = 5, | |
| 108 | − PERF_COUNT_SW_PAGE_FAULTS_MAJ = 6, | |
| 109 | − PERF_COUNT_SW_ALIGNMENT_FAULTS = 7, | |
| 110 | − PERF_COUNT_SW_EMULATION_FAULTS = 8, | |
| 111 | − | |
| 112 | − PERF_COUNT_SW_MAX, /* non-ABI */ | |
| 113 | −}; | |
| 114 | − | |
| 115 | −/* | |
| 116 | − * Bits that can be set in attr.sample_type to request information | |
| 117 | − * in the overflow packets. | |
| 118 | − */ | |
| 119 | −enum perf_counter_sample_format { | |
| 120 | − PERF_SAMPLE_IP = 1U << 0, | |
| 121 | − PERF_SAMPLE_TID = 1U << 1, | |
| 122 | − PERF_SAMPLE_TIME = 1U << 2, | |
| 123 | − PERF_SAMPLE_ADDR = 1U << 3, | |
| 124 | − PERF_SAMPLE_READ = 1U << 4, | |
| 125 | − PERF_SAMPLE_CALLCHAIN = 1U << 5, | |
| 126 | − PERF_SAMPLE_ID = 1U << 6, | |
| 127 | − PERF_SAMPLE_CPU = 1U << 7, | |
| 128 | − PERF_SAMPLE_PERIOD = 1U << 8, | |
| 129 | − PERF_SAMPLE_STREAM_ID = 1U << 9, | |
| 130 | − PERF_SAMPLE_RAW = 1U << 10, | |
| 131 | − | |
| 132 | − PERF_SAMPLE_MAX = 1U << 11, /* non-ABI */ | |
| 133 | −}; | |
| 134 | − | |
| 135 | −/* | |
| 136 | − * The format of the data returned by read() on a perf counter fd, | |
| 137 | − * as specified by attr.read_format: | |
| 138 | − * | |
| 139 | − * struct read_format { | |
| 140 | − * { u64 value; | |
| 141 | − * { u64 time_enabled; } && PERF_FORMAT_ENABLED | |
| 142 | − * { u64 time_running; } && PERF_FORMAT_RUNNING | |
| 143 | − * { u64 id; } && PERF_FORMAT_ID | |
| 144 | − * } && !PERF_FORMAT_GROUP | |
| 145 | − * | |
| 146 | − * { u64 nr; | |
| 147 | − * { u64 time_enabled; } && PERF_FORMAT_ENABLED | |
| 148 | − * { u64 time_running; } && PERF_FORMAT_RUNNING | |
| 149 | − * { u64 value; | |
| 150 | − * { u64 id; } && PERF_FORMAT_ID | |
| 151 | − * } cntr[nr]; | |
| 152 | − * } && PERF_FORMAT_GROUP | |
| 153 | − * }; | |
| 154 | − */ | |
| 155 | −enum perf_counter_read_format { | |
| 156 | − PERF_FORMAT_TOTAL_TIME_ENABLED = 1U << 0, | |
| 157 | − PERF_FORMAT_TOTAL_TIME_RUNNING = 1U << 1, | |
| 158 | − PERF_FORMAT_ID = 1U << 2, | |
| 159 | − PERF_FORMAT_GROUP = 1U << 3, | |
| 160 | − | |
| 161 | − PERF_FORMAT_MAX = 1U << 4, /* non-ABI */ | |
| 162 | −}; | |
| 163 | − | |
| 164 | −#define PERF_ATTR_SIZE_VER0 64 /* sizeof first published struct */ | |
| 165 | − | |
| 166 | −/* | |
| 167 | − * Hardware event to monitor via a performance monitoring counter: | |
| 168 | − */ | |
| 169 | −struct perf_counter_attr { | |
| 170 | − | |
| 171 | − /* | |
| 172 | − * Major type: hardware/software/tracepoint/etc. | |
| 173 | − */ | |
| 174 | − __u32 type; | |
| 175 | − | |
| 176 | − /* | |
| 177 | − * Size of the attr structure, for fwd/bwd compat. | |
| 178 | − */ | |
| 179 | − __u32 size; | |
| 180 | − | |
| 181 | − /* | |
| 182 | − * Type specific configuration information. | |
| 183 | − */ | |
| 184 | − __u64 config; | |
| 185 | − | |
| 186 | − union { | |
| 187 | − __u64 sample_period; | |
| 188 | − __u64 sample_freq; | |
| 189 | − }; | |
| 190 | − | |
| 191 | − __u64 sample_type; | |
| 192 | − __u64 read_format; | |
| 193 | − | |
| 194 | − __u64 disabled : 1, /* off by default */ | |
| 195 | − inherit : 1, /* children inherit it */ | |
| 196 | − pinned : 1, /* must always be on PMU */ | |
| 197 | − exclusive : 1, /* only group on PMU */ | |
| 198 | − exclude_user : 1, /* don't count user */ | |
| 199 | − exclude_kernel : 1, /* ditto kernel */ | |
| 200 | − exclude_hv : 1, /* ditto hypervisor */ | |
| 201 | − exclude_idle : 1, /* don't count when idle */ | |
| 202 | − mmap : 1, /* include mmap data */ | |
| 203 | − comm : 1, /* include comm data */ | |
| 204 | − freq : 1, /* use freq, not period */ | |
| 205 | − inherit_stat : 1, /* per task counts */ | |
| 206 | − enable_on_exec : 1, /* next exec enables */ | |
| 207 | − task : 1, /* trace fork/exit */ | |
| 208 | − watermark : 1, /* wakeup_watermark */ | |
| 209 | − | |
| 210 | − __reserved_1 : 49; | |
| 211 | − | |
| 212 | − union { | |
| 213 | − __u32 wakeup_events; /* wakeup every n events */ | |
| 214 | − __u32 wakeup_watermark; /* bytes before wakeup */ | |
| 215 | − }; | |
| 216 | − __u32 __reserved_2; | |
| 217 | − | |
| 218 | − __u64 __reserved_3; | |
| 219 | −}; | |
| 220 | − | |
| 221 | −/* | |
| 222 | − * Ioctls that can be done on a perf counter fd: | |
| 223 | − */ | |
| 224 | −#define PERF_COUNTER_IOC_ENABLE _IO ('$', 0) | |
| 225 | −#define PERF_COUNTER_IOC_DISABLE _IO ('$', 1) | |
| 226 | −#define PERF_COUNTER_IOC_REFRESH _IO ('$', 2) | |
| 227 | −#define PERF_COUNTER_IOC_RESET _IO ('$', 3) | |
| 228 | −#define PERF_COUNTER_IOC_PERIOD _IOW('$', 4, u64) | |
| 229 | −#define PERF_COUNTER_IOC_SET_OUTPUT _IO ('$', 5) | |
| 230 | −#define PERF_COUNTER_IOC_SET_FILTER _IOW('$', 6, char *) | |
| 231 | − | |
| 232 | −enum perf_counter_ioc_flags { | |
| 233 | − PERF_IOC_FLAG_GROUP = 1U << 0, | |
| 234 | −}; | |
| 235 | − | |
| 236 | −/* | |
| 237 | − * Structure of the page that can be mapped via mmap | |
| 238 | − */ | |
| 239 | −struct perf_counter_mmap_page { | |
| 240 | − __u32 version; /* version number of this structure */ | |
| 241 | − __u32 compat_version; /* lowest version this is compat with */ | |
| 242 | − | |
| 243 | − /* | |
| 244 | − * Bits needed to read the hw counters in user-space. | |
| 245 | − * | |
| 246 | − * u32 seq; | |
| 247 | − * s64 count; | |
| 248 | − * | |
| 249 | − * do { | |
| 250 | − * seq = pc->lock; | |
| 251 | − * | |
| 252 | − * barrier() | |
| 253 | − * if (pc->index) { | |
| 254 | − * count = pmc_read(pc->index - 1); | |
| 255 | − * count += pc->offset; | |
| 256 | − * } else | |
| 257 | − * goto regular_read; | |
| 258 | − * | |
| 259 | − * barrier(); | |
| 260 | − * } while (pc->lock != seq); | |
| 261 | − * | |
| 262 | − * NOTE: for obvious reason this only works on self-monitoring | |
| 263 | − * processes. | |
| 264 | − */ | |
| 265 | − __u32 lock; /* seqlock for synchronization */ | |
| 266 | − __u32 index; /* hardware counter identifier */ | |
| 267 | − __s64 offset; /* add to hardware counter value */ | |
| 268 | − __u64 time_enabled; /* time counter active */ | |
| 269 | − __u64 time_running; /* time counter on cpu */ | |
| 270 | − | |
| 271 | − /* | |
| 272 | − * Hole for extension of the self monitor capabilities | |
| 273 | − */ | |
| 274 | − | |
| 275 | − __u64 __reserved[123]; /* align to 1k */ | |
| 276 | − | |
| 277 | − /* | |
| 278 | − * Control data for the mmap() data buffer. | |
| 279 | − * | |
| 280 | − * User-space reading the @data_head value should issue an rmb(), on | |
| 281 | − * SMP capable platforms, after reading this value -- see | |
| 282 | − * perf_counter_wakeup(). | |
| 283 | − * | |
| 284 | − * When the mapping is PROT_WRITE the @data_tail value should be | |
| 285 | − * written by userspace to reflect the last read data. In this case | |
| 286 | − * the kernel will not over-write unread data. | |
| 287 | − */ | |
| 288 | − __u64 data_head; /* head in the data section */ | |
| 289 | − __u64 data_tail; /* user-space written tail */ | |
| 290 | −}; | |
| 291 | − | |
| 292 | −#define PERF_EVENT_MISC_CPUMODE_MASK (3 << 0) | |
| 293 | −#define PERF_EVENT_MISC_CPUMODE_UNKNOWN (0 << 0) | |
| 294 | −#define PERF_EVENT_MISC_KERNEL (1 << 0) | |
| 295 | −#define PERF_EVENT_MISC_USER (2 << 0) | |
| 296 | −#define PERF_EVENT_MISC_HYPERVISOR (3 << 0) | |
| 297 | − | |
| 298 | −struct perf_event_header { | |
| 299 | − __u32 type; | |
| 300 | − __u16 misc; | |
| 301 | − __u16 size; | |
| 302 | −}; | |
| 303 | − | |
| 304 | −enum perf_event_type { | |
| 305 | − | |
| 306 | − /* | |
| 307 | − * The MMAP events record the PROT_EXEC mappings so that we can | |
| 308 | − * correlate userspace IPs to code. They have the following structure: | |
| 309 | − * | |
| 310 | − * struct { | |
| 311 | − * struct perf_event_header header; | |
| 312 | − * | |
| 313 | − * u32 pid, tid; | |
| 314 | − * u64 addr; | |
| 315 | − * u64 len; | |
| 316 | − * u64 pgoff; | |
| 317 | − * char filename[]; | |
| 318 | − * }; | |
| 319 | − */ | |
| 320 | − PERF_EVENT_MMAP = 1, | |
| 321 | − | |
| 322 | − /* | |
| 323 | − * struct { | |
| 324 | − * struct perf_event_header header; | |
| 325 | − * u64 id; | |
| 326 | − * u64 lost; | |
| 327 | − * }; | |
| 328 | − */ | |
| 329 | − PERF_EVENT_LOST = 2, | |
| 330 | − | |
| 331 | − /* | |
| 332 | − * struct { | |
| 333 | − * struct perf_event_header header; | |
| 334 | − * | |
| 335 | − * u32 pid, tid; | |
| 336 | − * char comm[]; | |
| 337 | − * }; | |
| 338 | − */ | |
| 339 | − PERF_EVENT_COMM = 3, | |
| 340 | − | |
| 341 | − /* | |
| 342 | − * struct { | |
| 343 | − * struct perf_event_header header; | |
| 344 | − * u32 pid, ppid; | |
| 345 | − * u32 tid, ptid; | |
| 346 | − * u64 time; | |
| 347 | − * }; | |
| 348 | − */ | |
| 349 | − PERF_EVENT_EXIT = 4, | |
| 350 | − | |
| 351 | − /* | |
| 352 | − * struct { | |
| 353 | − * struct perf_event_header header; | |
| 354 | − * u64 time; | |
| 355 | − * u64 id; | |
| 356 | − * u64 stream_id; | |
| 357 | − * }; | |
| 358 | − */ | |
| 359 | − PERF_EVENT_THROTTLE = 5, | |
| 360 | − PERF_EVENT_UNTHROTTLE = 6, | |
| 361 | − | |
| 362 | − /* | |
| 363 | − * struct { | |
| 364 | − * struct perf_event_header header; | |
| 365 | − * u32 pid, ppid; | |
| 366 | − * u32 tid, ptid; | |
| 367 | − * u64 time; | |
| 368 | − * }; | |
| 369 | − */ | |
| 370 | − PERF_EVENT_FORK = 7, | |
| 371 | − | |
| 372 | − /* | |
| 373 | − * struct { | |
| 374 | − * struct perf_event_header header; | |
| 375 | − * u32 pid, tid; | |
| 376 | − * | |
| 377 | − * struct read_format values; | |
| 378 | − * }; | |
| 379 | − */ | |
| 380 | − PERF_EVENT_READ = 8, | |
| 381 | − | |
| 382 | − /* | |
| 383 | − * struct { | |
| 384 | − * struct perf_event_header header; | |
| 385 | − * | |
| 386 | − * { u64 ip; } && PERF_SAMPLE_IP | |
| 387 | − * { u32 pid, tid; } && PERF_SAMPLE_TID | |
| 388 | − * { u64 time; } && PERF_SAMPLE_TIME | |
| 389 | − * { u64 addr; } && PERF_SAMPLE_ADDR | |
| 390 | − * { u64 id; } && PERF_SAMPLE_ID | |
| 391 | − * { u64 stream_id;} && PERF_SAMPLE_STREAM_ID | |
| 392 | − * { u32 cpu, res; } && PERF_SAMPLE_CPU | |
| 393 | − * { u64 period; } && PERF_SAMPLE_PERIOD | |
| 394 | − * | |
| 395 | − * { struct read_format values; } && PERF_SAMPLE_READ | |
| 396 | − * | |
| 397 | − * { u64 nr, | |
| 398 | − * u64 ips[nr]; } && PERF_SAMPLE_CALLCHAIN | |
| 399 | − * | |
| 400 | − * # | |
| 401 | − * # The RAW record below is opaque data wrt the ABI | |
| 402 | − * # | |
| 403 | − * # That is, the ABI doesn't make any promises wrt to | |
| 404 | − * # the stability of its content, it may vary depending | |
| 405 | − * # on event, hardware, kernel version and phase of | |
| 406 | − * # the moon. | |
| 407 | − * # | |
| 408 | − * # In other words, PERF_SAMPLE_RAW contents are not an ABI. | |
| 409 | − * # | |
| 410 | − * | |
| 411 | − * { u32 size; | |
| 412 | − * char data[size];}&& PERF_SAMPLE_RAW | |
| 413 | − * }; | |
| 414 | − */ | |
| 415 | − PERF_EVENT_SAMPLE = 9, | |
| 416 | − | |
| 417 | − PERF_EVENT_MAX, /* non-ABI */ | |
| 418 | −}; | |
| 419 | − | |
| 420 | −enum perf_callchain_context { | |
| 421 | − PERF_CONTEXT_HV = (__u64)-32, | |
| 422 | − PERF_CONTEXT_KERNEL = (__u64)-128, | |
| 423 | − PERF_CONTEXT_USER = (__u64)-512, | |
| 424 | − | |
| 425 | − PERF_CONTEXT_GUEST = (__u64)-2048, | |
| 426 | − PERF_CONTEXT_GUEST_KERNEL = (__u64)-2176, | |
| 427 | − PERF_CONTEXT_GUEST_USER = (__u64)-2560, | |
| 428 | − | |
| 429 | − PERF_CONTEXT_MAX = (__u64)-4095, | |
| 430 | −}; | |
| 431 | − | |
| 432 | −#define PERF_FLAG_FD_NO_GROUP (1U << 0) | |
| 433 | −#define PERF_FLAG_FD_OUTPUT (1U << 1) | |
| 434 | − | |
| 435 | −/* | |
| 436 | − * In case some app still references the old symbols: | |
| 437 | − */ | |
| 438 | − | |
| 439 | −#define __NR_perf_counter_open __NR_perf_event_open | |
| 440 | − | |
| 441 | −#define PR_TASK_PERF_COUNTERS_DISABLE PR_TASK_PERF_EVENTS_DISABLE | |
| 442 | −#define PR_TASK_PERF_COUNTERS_ENABLE PR_TASK_PERF_EVENTS_ENABLE | |
| 443 | − | |
| 444 | −#endif /* _LINUX_PERF_COUNTER_H */ | |
| @@ -1381,6 +1381,9 @@ static void perf_ctx_adjust_freq(struct perf_event_context *ctx) · 1380 unmodified lines | ||
| 1381 | 1381 | if (event->state != PERF_EVENT_STATE_ACTIVE) |
| 1382 | 1382 | continue; |
| 1383 | 1383 | |
| 1384 | + if (event->cpu != -1 && event->cpu != smp_processor_id()) | |
| 1385 | + continue; | |
| 1386 | + | |
| 1384 | 1387 | hwc = &event->hw; |
| 1385 | 1388 | |
| 1386 | 1389 | interrupts = hwc->interrupts; |
| @@ -3265,6 +3268,9 @@ static void perf_event_task_output(struct perf_event *event, · 1878 unmodified lines | ||
| 3265 | 3268 | |
| 3266 | 3269 | static int perf_event_task_match(struct perf_event *event) |
| 3267 | 3270 | { |
| 3271 | + if (event->cpu != -1 && event->cpu != smp_processor_id()) | |
| 3272 | + return 0; | |
| 3273 | + | |
| 3268 | 3274 | if (event->attr.comm || event->attr.mmap || event->attr.task) |
| 3269 | 3275 | return 1; |
| 3270 | 3276 | |
| @@ -3290,12 +3296,11 @@ static void perf_event_task_event(struct perf_task_event *task_event) · 19 unmodified lines | ||
| 3290 | 3296 | rcu_read_lock(); |
| 3291 | 3297 | cpuctx = &get_cpu_var(perf_cpu_context); |
| 3292 | 3298 | perf_event_task_ctx(&cpuctx->ctx, task_event); |
| 3293 | − put_cpu_var(perf_cpu_context); | |
| 3294 | − | |
| 3295 | 3299 | if (!ctx) |
| 3296 | 3300 | ctx = rcu_dereference(task_event->task->perf_event_ctxp); |
| 3297 | 3301 | if (ctx) |
| 3298 | 3302 | perf_event_task_ctx(ctx, task_event); |
| 3303 | + put_cpu_var(perf_cpu_context); | |
| 3299 | 3304 | rcu_read_unlock(); |
| 3300 | 3305 | } |
| 3301 | 3306 | |
| @@ -3372,6 +3377,9 @@ static void perf_event_comm_output(struct perf_event *event, · 70 unmodified lines | ||
| 3372 | 3377 | |
| 3373 | 3378 | static int perf_event_comm_match(struct perf_event *event) |
| 3374 | 3379 | { |
| 3380 | + if (event->cpu != -1 && event->cpu != smp_processor_id()) | |
| 3381 | + return 0; | |
| 3382 | + | |
| 3375 | 3383 | if (event->attr.comm) |
| 3376 | 3384 | return 1; |
| 3377 | 3385 | |
| @@ -3408,15 +3416,10 @@ static void perf_event_comm_event(struct perf_comm_event *comm_event) · 30 unmodified lines | ||
| 3408 | 3416 | rcu_read_lock(); |
| 3409 | 3417 | cpuctx = &get_cpu_var(perf_cpu_context); |
| 3410 | 3418 | perf_event_comm_ctx(&cpuctx->ctx, comm_event); |
| 3411 | − put_cpu_var(perf_cpu_context); | |
| 3412 | − | |
| 3413 | − /* | |
| 3414 | − * doesn't really matter which of the child contexts the | |
| 3415 | − * events ends up in. | |
| 3416 | − */ | |
| 3417 | 3419 | ctx = rcu_dereference(current->perf_event_ctxp); |
| 3418 | 3420 | if (ctx) |
| 3419 | 3421 | perf_event_comm_ctx(ctx, comm_event); |
| 3422 | + put_cpu_var(perf_cpu_context); | |
| 3420 | 3423 | rcu_read_unlock(); |
| 3421 | 3424 | } |
| 3422 | 3425 | |
| @@ -3491,6 +3494,9 @@ static void perf_event_mmap_output(struct perf_event *event, · 68 unmodified lines | ||
| 3491 | 3494 | static int perf_event_mmap_match(struct perf_event *event, |
| 3492 | 3495 | struct perf_mmap_event *mmap_event) |
| 3493 | 3496 | { |
| 3497 | + if (event->cpu != -1 && event->cpu != smp_processor_id()) | |
| 3498 | + return 0; | |
| 3499 | + | |
| 3494 | 3500 | if (event->attr.mmap) |
| 3495 | 3501 | return 1; |
| 3496 | 3502 | |
| @@ -3564,15 +3570,10 @@ got_name: · 67 unmodified lines | ||
| 3564 | 3570 | rcu_read_lock(); |
| 3565 | 3571 | cpuctx = &get_cpu_var(perf_cpu_context); |
| 3566 | 3572 | perf_event_mmap_ctx(&cpuctx->ctx, mmap_event); |
| 3567 | − put_cpu_var(perf_cpu_context); | |
| 3568 | − | |
| 3569 | − /* | |
| 3570 | − * doesn't really matter which of the child contexts the | |
| 3571 | − * events ends up in. | |
| 3572 | − */ | |
| 3573 | 3573 | ctx = rcu_dereference(current->perf_event_ctxp); |
| 3574 | 3574 | if (ctx) |
| 3575 | 3575 | perf_event_mmap_ctx(ctx, mmap_event); |
| 3576 | + put_cpu_var(perf_cpu_context); | |
| 3576 | 3577 | rcu_read_unlock(); |
| 3577 | 3578 | |
| 3578 | 3579 | kfree(buf); |
| @@ -3863,6 +3864,9 @@ static int perf_swevent_match(struct perf_event *event, · 284 unmodified lines | ||
| 3863 | 3864 | struct perf_sample_data *data, |
| 3864 | 3865 | struct pt_regs *regs) |
| 3865 | 3866 | { |
| 3867 | + if (event->cpu != -1 && event->cpu != smp_processor_id()) | |
| 3868 | + return 0; | |
| 3869 | + | |
| 3866 | 3870 | if (!perf_swevent_is_counting(event)) |
| 3867 | 3871 | return 0; |
| 3868 | 3872 | |
| @@ -282,6 +282,18 @@ static int kprobe_dispatcher(struct kprobe *kp, struct pt_regs *regs); · 281 unmodified lines | ||
| 282 | 282 | static int kretprobe_dispatcher(struct kretprobe_instance *ri, |
| 283 | 283 | struct pt_regs *regs); |
| 284 | 284 | |
| 285 | +/* Check the name is good for event/group */ | |
| 286 | +static int check_event_name(const char *name) | |
| 287 | +{ | |
| 288 | + if (!isalpha(*name) && *name != '_') | |
| 289 | + return 0; | |
| 290 | + while (*++name != '\0') { | |
| 291 | + if (!isalpha(*name) && !isdigit(*name) && *name != '_') | |
| 292 | + return 0; | |
| 293 | + } | |
| 294 | + return 1; | |
| 295 | +} | |
| 296 | + | |
| 285 | 297 | /* |
| 286 | 298 | * Allocate new trace_probe and initialize it (including kprobes). |
| 287 | 299 | */ |
| @@ -293,10 +305,11 @@ static struct trace_probe *alloc_trace_probe(const char *group, · 5 unmodified lines | ||
| 293 | 305 | int nargs, int is_return) |
| 294 | 306 | { |
| 295 | 307 | struct trace_probe *tp; |
| 308 | + int ret = -ENOMEM; | |
| 296 | 309 | |
| 297 | 310 | tp = kzalloc(SIZEOF_TRACE_PROBE(nargs), GFP_KERNEL); |
| 298 | 311 | if (!tp) |
| 299 | − return ERR_PTR(-ENOMEM); | |
| 312 | + return ERR_PTR(ret); | |
| 300 | 313 | |
| 301 | 314 | if (symbol) { |
| 302 | 315 | tp->symbol = kstrdup(symbol, GFP_KERNEL); |
| @@ -312,14 +325,20 @@ static struct trace_probe *alloc_trace_probe(const char *group, · 9 unmodified lines | ||
| 312 | 325 | else |
| 313 | 326 | tp->rp.kp.pre_handler = kprobe_dispatcher; |
| 314 | 327 | |
| 315 | − if (!event) | |
| 328 | + if (!event || !check_event_name(event)) { | |
| 329 | + ret = -EINVAL; | |
| 316 | 330 | goto error; |
| 331 | + } | |
| 332 | + | |
| 317 | 333 | tp->call.name = kstrdup(event, GFP_KERNEL); |
| 318 | 334 | if (!tp->call.name) |
| 319 | 335 | goto error; |
| 320 | 336 | |
| 321 | − if (!group) | |
| 337 | + if (!group || !check_event_name(group)) { | |
| 338 | + ret = -EINVAL; | |
| 322 | 339 | goto error; |
| 340 | + } | |
| 341 | + | |
| 323 | 342 | tp->call.system = kstrdup(group, GFP_KERNEL); |
| 324 | 343 | if (!tp->call.system) |
| 325 | 344 | goto error; |
| @@ -330,7 +349,7 @@ error: · 4 unmodified lines | ||
| 330 | 349 | kfree(tp->call.name); |
| 331 | 350 | kfree(tp->symbol); |
| 332 | 351 | kfree(tp); |
| 333 | − return ERR_PTR(-ENOMEM); | |
| 352 | + return ERR_PTR(ret); | |
| 334 | 353 | } |
| 335 | 354 | |
| 336 | 355 | static void free_probe_arg(struct probe_arg *arg) |
| @@ -695,10 +714,10 @@ static int create_trace_probe(int argc, char **argv) · 358 unmodified lines | ||
| 695 | 714 | if (!event) { |
| 696 | 715 | /* Make a new event name */ |
| 697 | 716 | if (symbol) |
| 698 | − snprintf(buf, MAX_EVENT_NAME_LEN, "%c@%s%+ld", | |
| 717 | + snprintf(buf, MAX_EVENT_NAME_LEN, "%c_%s_%ld", | |
| 699 | 718 | is_return ? 'r' : 'p', symbol, offset); |
| 700 | 719 | else |
| 701 | − snprintf(buf, MAX_EVENT_NAME_LEN, "%c@0x%p", | |
| 720 | + snprintf(buf, MAX_EVENT_NAME_LEN, "%c_0x%p", | |
| 702 | 721 | is_return ? 'r' : 'p', addr); |
| 703 | 722 | event = buf; |
| 704 | 723 | } |
| @@ -93,6 +93,7 @@ static const struct stacktrace_ops backtrace_ops = { · 92 unmodified lines | ||
| 93 | 93 | .warning_symbol = backtrace_warning_symbol, |
| 94 | 94 | .stack = backtrace_stack, |
| 95 | 95 | .address = backtrace_address, |
| 96 | + .walk_stack = print_context_stack, | |
| 96 | 97 | }; |
| 97 | 98 | |
| 98 | 99 | static int |
| @@ -487,10 +487,11 @@ else · 486 unmodified lines | ||
| 487 | 487 | msg := $(error No libelf.h/libelf found, please install libelf-dev/elfutils-libelf-devel and glibc-dev[el]); |
| 488 | 488 | endif |
| 489 | 489 | |
| 490 | −ifneq ($(shell sh -c "(echo '\#include <libdwarf/dwarf.h>'; echo '\#include <libdwarf/libdwarf.h>'; echo 'int main(void) { Dwarf_Debug dbg; Dwarf_Error err; Dwarf_Ranges *rng; dwarf_init(0, DW_DLC_READ, 0, 0, &dbg, &err); dwarf_get_ranges(dbg, 0, &rng, 0, 0, &err); return (long)dbg; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -ldwarf -lelf -o /dev/null $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y) | |
| 490 | +ifneq ($(shell sh -c "(echo '\#ifndef _MIPS_SZLONG'; echo '\#define _MIPS_SZLONG 0'; echo '\#endif'; echo '\#include <dwarf.h>'; echo '\#include <libdwarf.h>'; echo 'int main(void) { Dwarf_Debug dbg; Dwarf_Error err; Dwarf_Ranges *rng; dwarf_init(0, DW_DLC_READ, 0, 0, &dbg, &err); dwarf_get_ranges(dbg, 0, &rng, 0, 0, &err); return (long)dbg; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/libdwarf -ldwarf -lelf -o /dev/null $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y) | |
| 491 | 491 | msg := $(warning No libdwarf.h found or old libdwarf.h found, disables dwarf support. Please install libdwarf-dev/libdwarf-devel >= 20081231); |
| 492 | 492 | BASIC_CFLAGS += -DNO_LIBDWARF |
| 493 | 493 | else |
| 494 | + BASIC_CFLAGS += -I/usr/include/libdwarf | |
| 494 | 495 | EXTLIBS += -lelf -ldwarf |
| 495 | 496 | LIB_OBJS += util/probe-finder.o |
| 496 | 497 | endif |
| @@ -38,6 +38,7 @@ · 37 unmodified lines | ||
| 38 | 38 | #include "util/strlist.h" |
| 39 | 39 | #include "util/event.h" |
| 40 | 40 | #include "util/debug.h" |
| 41 | +#include "util/debugfs.h" | |
| 41 | 42 | #include "util/symbol.h" |
| 42 | 43 | #include "util/thread.h" |
| 43 | 44 | #include "util/session.h" |
| @@ -205,6 +206,9 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used) · 161 unmodified lines | ||
| 205 | 206 | if ((!session.nr_probe && !session.dellist && !session.list_events)) |
| 206 | 207 | usage_with_options(probe_usage, options); |
| 207 | 208 | |
| 209 | + if (debugfs_valid_mountpoint(debugfs_path) < 0) | |
| 210 | + die("Failed to find debugfs path."); | |
| 211 | + | |
| 208 | 212 | if (session.list_events) { |
| 209 | 213 | if (session.nr_probe != 0 || session.dellist) { |
| 210 | 214 | pr_warning(" Error: Don't use --list with" |
| @@ -224,7 +224,7 @@ static int __cmd_report(void) · 223 unmodified lines | ||
| 224 | 224 | |
| 225 | 225 | perf_session__collapse_resort(session); |
| 226 | 226 | perf_session__output_resort(session, session->events_stats.total); |
| 227 | − fprintf(stdout, "# Samples: %ld\n#\n", session->events_stats.total); | |
| 227 | + fprintf(stdout, "# Samples: %Ld\n#\n", session->events_stats.total); | |
| 228 | 228 | perf_session__fprintf_hists(session, NULL, false, stdout); |
| 229 | 229 | if (sort_order == default_sort_order && |
| 230 | 230 | parent_pattern == default_parent_pattern) |
| @@ -95,8 +95,8 @@ typedef union event_union { · 94 unmodified lines | ||
| 95 | 95 | } event_t; |
| 96 | 96 | |
| 97 | 97 | struct events_stats { |
| 98 | − unsigned long total; | |
| 99 | − unsigned long lost; | |
| 98 | + u64 total; | |
| 99 | + u64 lost; | |
| 100 | 100 | }; |
| 101 | 101 | |
| 102 | 102 | void event__print_totals(void); |
| @@ -62,6 +62,18 @@ static int e_snprintf(char *str, size_t size, const char *format, ...) · 61 unmodified lines | ||
| 62 | 62 | return ret; |
| 63 | 63 | } |
| 64 | 64 | |
| 65 | +/* Check the name is good for event/group */ | |
| 66 | +static bool check_event_name(const char *name) | |
| 67 | +{ | |
| 68 | + if (!isalpha(*name) && *name != '_') | |
| 69 | + return false; | |
| 70 | + while (*++name != '\0') { | |
| 71 | + if (!isalpha(*name) && !isdigit(*name) && *name != '_') | |
| 72 | + return false; | |
| 73 | + } | |
| 74 | + return true; | |
| 75 | +} | |
| 76 | + | |
| 65 | 77 | /* Parse probepoint definition. */ |
| 66 | 78 | static void parse_perf_probe_probepoint(char *arg, struct probe_point *pp) |
| 67 | 79 | { |
| @@ -82,6 +94,9 @@ static void parse_perf_probe_probepoint(char *arg, struct probe_point *pp) · 14 unmodified lines | ||
| 82 | 94 | ptr = strchr(arg, ':'); |
| 83 | 95 | if (ptr) /* Group name is not supported yet. */ |
| 84 | 96 | semantic_error("Group name is not supported yet."); |
| 97 | + if (!check_event_name(arg)) | |
| 98 | + semantic_error("%s is bad for event name -it must " | |
| 99 | + "follow C symbol-naming rule.", arg); | |
| 85 | 100 | pp->event = strdup(arg); |
| 86 | 101 | arg = tmp; |
| 87 | 102 | } |
| @@ -1,9 +1,9 @@ | ||
| 1 | 1 | #ifndef _PROBE_FINDER_H |
| 2 | 2 | #define _PROBE_FINDER_H |
| 3 | 3 | |
| 4 | −#define MAX_PATH_LEN 256 | |
| 5 | −#define MAX_PROBE_BUFFER 1024 | |
| 6 | −#define MAX_PROBES 128 | |
| 4 | +#define MAX_PATH_LEN 256 | |
| 5 | +#define MAX_PROBE_BUFFER 1024 | |
| 6 | +#define MAX_PROBES 128 | |
| 7 | 7 | |
| 8 | 8 | static inline int is_c_varname(const char *name) |
| 9 | 9 | { |
| @@ -12,48 +12,53 @@ static inline int is_c_varname(const char *name) · 2 unmodified lines | ||
| 12 | 12 | } |
| 13 | 13 | |
| 14 | 14 | struct probe_point { |
| 15 | − char *event; /* Event name */ | |
| 16 | − char *group; /* Event group */ | |
| 15 | + char *event; /* Event name */ | |
| 16 | + char *group; /* Event group */ | |
| 17 | 17 | |
| 18 | 18 | /* Inputs */ |
| 19 | − char *file; /* File name */ | |
| 20 | − int line; /* Line number */ | |
| 19 | + char *file; /* File name */ | |
| 20 | + int line; /* Line number */ | |
| 21 | 21 | |
| 22 | − char *function; /* Function name */ | |
| 23 | − int offset; /* Offset bytes */ | |
| 22 | + char *function; /* Function name */ | |
| 23 | + int offset; /* Offset bytes */ | |
| 24 | 24 | |
| 25 | − int nr_args; /* Number of arguments */ | |
| 26 | − char **args; /* Arguments */ | |
| 25 | + int nr_args; /* Number of arguments */ | |
| 26 | + char **args; /* Arguments */ | |
| 27 | 27 | |
| 28 | − int retprobe; /* Return probe */ | |
| 28 | + int retprobe; /* Return probe */ | |
| 29 | 29 | |
| 30 | 30 | /* Output */ |
| 31 | − int found; /* Number of found probe points */ | |
| 32 | − char *probes[MAX_PROBES]; /* Output buffers (will be allocated)*/ | |
| 31 | + int found; /* Number of found probe points */ | |
| 32 | + char *probes[MAX_PROBES]; /* Output buffers (will be allocated)*/ | |
| 33 | 33 | }; |
| 34 | 34 | |
| 35 | 35 | #ifndef NO_LIBDWARF |
| 36 | 36 | extern int find_probepoint(int fd, struct probe_point *pp); |
| 37 | 37 | |
| 38 | −#include <libdwarf/dwarf.h> | |
| 39 | −#include <libdwarf/libdwarf.h> | |
| 38 | +/* Workaround for undefined _MIPS_SZLONG bug in libdwarf.h: */ | |
| 39 | +#ifndef _MIPS_SZLONG | |
| 40 | +# define _MIPS_SZLONG 0 | |
| 41 | +#endif | |
| 42 | + | |
| 43 | +#include <dwarf.h> | |
| 44 | +#include <libdwarf.h> | |
| 40 | 45 | |
| 41 | 46 | struct probe_finder { |
| 42 | − struct probe_point *pp; /* Target probe point */ | |
| 47 | + struct probe_point *pp; /* Target probe point */ | |
| 43 | 48 | |
| 44 | 49 | /* For function searching */ |
| 45 | − Dwarf_Addr addr; /* Address */ | |
| 46 | − Dwarf_Unsigned fno; /* File number */ | |
| 47 | − Dwarf_Unsigned lno; /* Line number */ | |
| 48 | − Dwarf_Off inl_offs; /* Inline offset */ | |
| 49 | − Dwarf_Die cu_die; /* Current CU */ | |
| 50 | + Dwarf_Addr addr; /* Address */ | |
| 51 | + Dwarf_Unsigned fno; /* File number */ | |
| 52 | + Dwarf_Unsigned lno; /* Line number */ | |
| 53 | + Dwarf_Off inl_offs; /* Inline offset */ | |
| 54 | + Dwarf_Die cu_die; /* Current CU */ | |
| 50 | 55 | |
| 51 | 56 | /* For variable searching */ |
| 52 | − Dwarf_Addr cu_base; /* Current CU base address */ | |
| 53 | − Dwarf_Locdesc fbloc; /* Location of Current Frame Base */ | |
| 54 | − const char *var; /* Current variable name */ | |
| 55 | − char *buf; /* Current output buffer */ | |
| 56 | − int len; /* Length of output buffer */ | |
| 57 | + Dwarf_Addr cu_base; /* Current CU base address */ | |
| 58 | + Dwarf_Locdesc fbloc; /* Location of Current Frame Base */ | |
| 59 | + const char *var; /* Current variable name */ | |
| 60 | + char *buf; /* Current output buffer */ | |
| 61 | + int len; /* Length of output buffer */ | |
| 57 | 62 | }; |
| 58 | 63 | #endif /* NO_LIBDWARF */ |
| 59 | 64 | |