aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/kernel-parameters.txt7
-rw-r--r--Documentation/trace/ftrace-design.txt13
-rw-r--r--arch/s390/kernel/ftrace.c67
-rw-r--r--arch/x86/include/asm/perf_event.h13
-rw-r--r--arch/x86/kernel/cpu/perf_event.c185
-rw-r--r--arch/x86/kernel/entry_32.S7
-rw-r--r--arch/x86/kernel/entry_64.S6
-rw-r--r--arch/x86/kernel/ftrace.c84
-rw-r--r--arch/x86/mm/testmmiotrace.c29
-rw-r--r--include/linux/ftrace_event.h11
-rw-r--r--include/linux/perf_counter.h1
-rw-r--r--include/linux/perf_event.h6
-rw-r--r--include/linux/smp_lock.h21
-rw-r--r--include/trace/events/bkl.h61
-rw-r--r--include/trace/events/irq.h8
-rw-r--r--include/trace/events/power.h2
-rw-r--r--include/trace/events/sched.h44
-rw-r--r--include/trace/events/timer.h79
-rw-r--r--include/trace/ftrace.h15
-rw-r--r--include/trace/syscall.h2
-rw-r--r--kernel/perf_event.c82
-rw-r--r--kernel/trace/ftrace.c370
-rw-r--r--kernel/trace/ring_buffer.c15
-rw-r--r--kernel/trace/trace.c4
-rw-r--r--kernel/trace/trace.h48
-rw-r--r--kernel/trace/trace_events.c47
-rw-r--r--kernel/trace/trace_events_filter.c423
-rw-r--r--kernel/trace/trace_export.c25
-rw-r--r--kernel/trace/trace_syscalls.c106
-rw-r--r--lib/kernel_lock.c20
-rwxr-xr-xscripts/recordmcount.pl1
-rw-r--r--tools/perf/Documentation/perf-timechart.txt5
-rw-r--r--tools/perf/Makefile58
-rw-r--r--tools/perf/builtin-annotate.c645
-rw-r--r--tools/perf/builtin-record.c93
-rw-r--r--tools/perf/builtin-report.c961
-rw-r--r--tools/perf/builtin-sched.c310
-rw-r--r--tools/perf/builtin-stat.c31
-rw-r--r--tools/perf/builtin-timechart.c146
-rw-r--r--tools/perf/builtin-top.c173
-rw-r--r--tools/perf/builtin-trace.c174
-rw-r--r--tools/perf/perf.c16
-rwxr-xr-xtools/perf/util/PERF-VERSION-GEN2
-rw-r--r--tools/perf/util/cache.h11
-rw-r--r--tools/perf/util/callchain.c2
-rw-r--r--tools/perf/util/callchain.h2
-rw-r--r--tools/perf/util/color.h6
-rw-r--r--tools/perf/util/data_map.c222
-rw-r--r--tools/perf/util/data_map.h31
-rw-r--r--tools/perf/util/debug.c4
-rw-r--r--tools/perf/util/debug.h7
-rw-r--r--tools/perf/util/event.h30
-rw-r--r--tools/perf/util/exec_cmd.h6
-rw-r--r--tools/perf/util/header.c74
-rw-r--r--tools/perf/util/header.h29
-rw-r--r--tools/perf/util/help.h6
-rw-r--r--tools/perf/util/hist.c210
-rw-r--r--tools/perf/util/hist.h50
-rw-r--r--tools/perf/util/include/asm/asm-offsets.h1
-rw-r--r--tools/perf/util/include/asm/bitops.h18
-rw-r--r--tools/perf/util/include/asm/byteorder.h2
-rw-r--r--tools/perf/util/include/asm/swab.h1
-rw-r--r--tools/perf/util/include/asm/uaccess.h14
-rw-r--r--tools/perf/util/include/linux/bitmap.h2
-rw-r--r--tools/perf/util/include/linux/bitops.h27
-rw-r--r--tools/perf/util/include/linux/compiler.h10
-rw-r--r--tools/perf/util/include/linux/ctype.h1
-rw-r--r--tools/perf/util/include/linux/kernel.h76
-rw-r--r--tools/perf/util/include/linux/string.h1
-rw-r--r--tools/perf/util/include/linux/types.h9
-rw-r--r--tools/perf/util/levenshtein.h6
-rw-r--r--tools/perf/util/map.c26
-rw-r--r--tools/perf/util/module.c545
-rw-r--r--tools/perf/util/module.h53
-rw-r--r--tools/perf/util/parse-events.c26
-rw-r--r--tools/perf/util/parse-events.h8
-rw-r--r--tools/perf/util/parse-options.h6
-rw-r--r--tools/perf/util/quote.h6
-rw-r--r--tools/perf/util/run-command.h6
-rw-r--r--tools/perf/util/sigchain.h6
-rw-r--r--tools/perf/util/sort.c290
-rw-r--r--tools/perf/util/sort.h99
-rw-r--r--tools/perf/util/strbuf.h6
-rw-r--r--tools/perf/util/string.c11
-rw-r--r--tools/perf/util/string.h7
-rw-r--r--tools/perf/util/strlist.h6
-rw-r--r--tools/perf/util/svghelper.c2
-rw-r--r--tools/perf/util/svghelper.h6
-rw-r--r--tools/perf/util/symbol.c785
-rw-r--r--tools/perf/util/symbol.h34
-rw-r--r--tools/perf/util/thread.c167
-rw-r--r--tools/perf/util/thread.h31
-rw-r--r--tools/perf/util/trace-event-info.c6
-rw-r--r--tools/perf/util/trace-event-parse.c537
-rw-r--r--tools/perf/util/trace-event-read.c7
-rw-r--r--tools/perf/util/trace-event.h41
-rw-r--r--tools/perf/util/types.h6
-rw-r--r--tools/perf/util/values.h6
98 files changed, 4475 insertions, 3528 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 9107b387e91..c8d1b2be28e 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -779,6 +779,13 @@ and is between 256 and 4096 characters. It is defined in the file
779 by the set_ftrace_notrace file in the debugfs 779 by the set_ftrace_notrace file in the debugfs
780 tracing directory. 780 tracing directory.
781 781
782 ftrace_graph_filter=[function-list]
783 [FTRACE] Limit the top level callers functions traced
784 by the function graph tracer at boot up.
785 function-list is a comma separated list of functions
786 that can be changed at run time by the
787 set_graph_function file in the debugfs tracing directory.
788
782 gamecon.map[2|3]= 789 gamecon.map[2|3]=
783 [HW,JOY] Multisystem joystick and NES/SNES/PSX pad 790 [HW,JOY] Multisystem joystick and NES/SNES/PSX pad
784 support via parallel port (up to 5 devices per port) 791 support via parallel port (up to 5 devices per port)
diff --git a/Documentation/trace/ftrace-design.txt b/Documentation/trace/ftrace-design.txt
index 7003e10f10f..641a1ef2a7f 100644
--- a/Documentation/trace/ftrace-design.txt
+++ b/Documentation/trace/ftrace-design.txt
@@ -213,10 +213,19 @@ If you can't trace NMI functions, then skip this option.
213<details to be filled> 213<details to be filled>
214 214
215 215
216HAVE_FTRACE_SYSCALLS 216HAVE_SYSCALL_TRACEPOINTS
217--------------------- 217---------------------
218 218
219<details to be filled> 219You need very few things to get the syscalls tracing in an arch.
220
221- Have a NR_syscalls variable in <asm/unistd.h> that provides the number
222 of syscalls supported by the arch.
223- Implement arch_syscall_addr() that resolves a syscall address from a
224 syscall number.
225- Support the TIF_SYSCALL_TRACEPOINT thread flags
226- Put the trace_sys_enter() and trace_sys_exit() tracepoints calls from ptrace
227 in the ptrace syscalls tracing path.
228- Tag this arch as HAVE_SYSCALL_TRACEPOINTS.
220 229
221 230
222HAVE_FTRACE_MCOUNT_RECORD 231HAVE_FTRACE_MCOUNT_RECORD
diff --git a/arch/s390/kernel/ftrace.c b/arch/s390/kernel/ftrace.c
index f5fe34dd821..5a82bc68193 100644
--- a/arch/s390/kernel/ftrace.c
+++ b/arch/s390/kernel/ftrace.c
@@ -203,73 +203,10 @@ out:
203 203
204#ifdef CONFIG_FTRACE_SYSCALLS 204#ifdef CONFIG_FTRACE_SYSCALLS
205 205
206extern unsigned long __start_syscalls_metadata[];
207extern unsigned long __stop_syscalls_metadata[];
208extern unsigned int sys_call_table[]; 206extern unsigned int sys_call_table[];
209 207
210static struct syscall_metadata **syscalls_metadata; 208unsigned long __init arch_syscall_addr(int nr)
211
212struct syscall_metadata *syscall_nr_to_meta(int nr)
213{
214 if (!syscalls_metadata || nr >= NR_syscalls || nr < 0)
215 return NULL;
216
217 return syscalls_metadata[nr];
218}
219
220int syscall_name_to_nr(char *name)
221{
222 int i;
223
224 if (!syscalls_metadata)
225 return -1;
226 for (i = 0; i < NR_syscalls; i++)
227 if (syscalls_metadata[i])
228 if (!strcmp(syscalls_metadata[i]->name, name))
229 return i;
230 return -1;
231}
232
233void set_syscall_enter_id(int num, int id)
234{
235 syscalls_metadata[num]->enter_id = id;
236}
237
238void set_syscall_exit_id(int num, int id)
239{ 209{
240 syscalls_metadata[num]->exit_id = id; 210 return (unsigned long)sys_call_table[nr];
241}
242
243static struct syscall_metadata *find_syscall_meta(unsigned long syscall)
244{
245 struct syscall_metadata *start;
246 struct syscall_metadata *stop;
247 char str[KSYM_SYMBOL_LEN];
248
249 start = (struct syscall_metadata *)__start_syscalls_metadata;
250 stop = (struct syscall_metadata *)__stop_syscalls_metadata;
251 kallsyms_lookup(syscall, NULL, NULL, NULL, str);
252
253 for ( ; start < stop; start++) {
254 if (start->name && !strcmp(start->name + 3, str + 3))
255 return start;
256 }
257 return NULL;
258}
259
260static int __init arch_init_ftrace_syscalls(void)
261{
262 struct syscall_metadata *meta;
263 int i;
264 syscalls_metadata = kzalloc(sizeof(*syscalls_metadata) * NR_syscalls,
265 GFP_KERNEL);
266 if (!syscalls_metadata)
267 return -ENOMEM;
268 for (i = 0; i < NR_syscalls; i++) {
269 meta = find_syscall_meta((unsigned long)sys_call_table[i]);
270 syscalls_metadata[i] = meta;
271 }
272 return 0;
273} 211}
274arch_initcall(arch_init_ftrace_syscalls);
275#endif 212#endif
diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h
index ad7ce3fd506..8d9f8548a87 100644
--- a/arch/x86/include/asm/perf_event.h
+++ b/arch/x86/include/asm/perf_event.h
@@ -28,9 +28,20 @@
28 */ 28 */
29#define ARCH_PERFMON_EVENT_MASK 0xffff 29#define ARCH_PERFMON_EVENT_MASK 0xffff
30 30
31/*
32 * filter mask to validate fixed counter events.
33 * the following filters disqualify for fixed counters:
34 * - inv
35 * - edge
36 * - cnt-mask
37 * The other filters are supported by fixed counters.
38 * The any-thread option is supported starting with v3.
39 */
40#define ARCH_PERFMON_EVENT_FILTER_MASK 0xff840000
41
31#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL 0x3c 42#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL 0x3c
32#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK (0x00 << 8) 43#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK (0x00 << 8)
33#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX 0 44#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX 0
34#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT \ 45#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT \
35 (1 << (ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX)) 46 (1 << (ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX))
36 47
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index b5801c31184..2e20bca3cca 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -77,6 +77,18 @@ struct cpu_hw_events {
77 struct debug_store *ds; 77 struct debug_store *ds;
78}; 78};
79 79
80struct event_constraint {
81 unsigned long idxmsk[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
82 int code;
83};
84
85#define EVENT_CONSTRAINT(c, m) { .code = (c), .idxmsk[0] = (m) }
86#define EVENT_CONSTRAINT_END { .code = 0, .idxmsk[0] = 0 }
87
88#define for_each_event_constraint(e, c) \
89 for ((e) = (c); (e)->idxmsk[0]; (e)++)
90
91
80/* 92/*
81 * struct x86_pmu - generic x86 pmu 93 * struct x86_pmu - generic x86 pmu
82 */ 94 */
@@ -102,6 +114,8 @@ struct x86_pmu {
102 u64 intel_ctrl; 114 u64 intel_ctrl;
103 void (*enable_bts)(u64 config); 115 void (*enable_bts)(u64 config);
104 void (*disable_bts)(void); 116 void (*disable_bts)(void);
117 int (*get_event_idx)(struct cpu_hw_events *cpuc,
118 struct hw_perf_event *hwc);
105}; 119};
106 120
107static struct x86_pmu x86_pmu __read_mostly; 121static struct x86_pmu x86_pmu __read_mostly;
@@ -110,6 +124,8 @@ static DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events) = {
110 .enabled = 1, 124 .enabled = 1,
111}; 125};
112 126
127static const struct event_constraint *event_constraints;
128
113/* 129/*
114 * Not sure about some of these 130 * Not sure about some of these
115 */ 131 */
@@ -155,6 +171,16 @@ static u64 p6_pmu_raw_event(u64 hw_event)
155 return hw_event & P6_EVNTSEL_MASK; 171 return hw_event & P6_EVNTSEL_MASK;
156} 172}
157 173
174static const struct event_constraint intel_p6_event_constraints[] =
175{
176 EVENT_CONSTRAINT(0xc1, 0x1), /* FLOPS */
177 EVENT_CONSTRAINT(0x10, 0x1), /* FP_COMP_OPS_EXE */
178 EVENT_CONSTRAINT(0x11, 0x1), /* FP_ASSIST */
179 EVENT_CONSTRAINT(0x12, 0x2), /* MUL */
180 EVENT_CONSTRAINT(0x13, 0x2), /* DIV */
181 EVENT_CONSTRAINT(0x14, 0x1), /* CYCLES_DIV_BUSY */
182 EVENT_CONSTRAINT_END
183};
158 184
159/* 185/*
160 * Intel PerfMon v3. Used on Core2 and later. 186 * Intel PerfMon v3. Used on Core2 and later.
@@ -170,6 +196,35 @@ static const u64 intel_perfmon_event_map[] =
170 [PERF_COUNT_HW_BUS_CYCLES] = 0x013c, 196 [PERF_COUNT_HW_BUS_CYCLES] = 0x013c,
171}; 197};
172 198
199static const struct event_constraint intel_core_event_constraints[] =
200{
201 EVENT_CONSTRAINT(0x10, 0x1), /* FP_COMP_OPS_EXE */
202 EVENT_CONSTRAINT(0x11, 0x2), /* FP_ASSIST */
203 EVENT_CONSTRAINT(0x12, 0x2), /* MUL */
204 EVENT_CONSTRAINT(0x13, 0x2), /* DIV */
205 EVENT_CONSTRAINT(0x14, 0x1), /* CYCLES_DIV_BUSY */
206 EVENT_CONSTRAINT(0x18, 0x1), /* IDLE_DURING_DIV */
207 EVENT_CONSTRAINT(0x19, 0x2), /* DELAYED_BYPASS */
208 EVENT_CONSTRAINT(0xa1, 0x1), /* RS_UOPS_DISPATCH_CYCLES */
209 EVENT_CONSTRAINT(0xcb, 0x1), /* MEM_LOAD_RETIRED */
210 EVENT_CONSTRAINT_END
211};
212
213static const struct event_constraint intel_nehalem_event_constraints[] =
214{
215 EVENT_CONSTRAINT(0x40, 0x3), /* L1D_CACHE_LD */
216 EVENT_CONSTRAINT(0x41, 0x3), /* L1D_CACHE_ST */
217 EVENT_CONSTRAINT(0x42, 0x3), /* L1D_CACHE_LOCK */
218 EVENT_CONSTRAINT(0x43, 0x3), /* L1D_ALL_REF */
219 EVENT_CONSTRAINT(0x4e, 0x3), /* L1D_PREFETCH */
220 EVENT_CONSTRAINT(0x4c, 0x3), /* LOAD_HIT_PRE */
221 EVENT_CONSTRAINT(0x51, 0x3), /* L1D */
222 EVENT_CONSTRAINT(0x52, 0x3), /* L1D_CACHE_PREFETCH_LOCK_FB_HIT */
223 EVENT_CONSTRAINT(0x53, 0x3), /* L1D_CACHE_LOCK_FB_HIT */
224 EVENT_CONSTRAINT(0xc5, 0x3), /* CACHE_LOCK_CYCLES */
225 EVENT_CONSTRAINT_END
226};
227
173static u64 intel_pmu_event_map(int hw_event) 228static u64 intel_pmu_event_map(int hw_event)
174{ 229{
175 return intel_perfmon_event_map[hw_event]; 230 return intel_perfmon_event_map[hw_event];
@@ -469,7 +524,7 @@ static u64 intel_pmu_raw_event(u64 hw_event)
469#define CORE_EVNTSEL_UNIT_MASK 0x0000FF00ULL 524#define CORE_EVNTSEL_UNIT_MASK 0x0000FF00ULL
470#define CORE_EVNTSEL_EDGE_MASK 0x00040000ULL 525#define CORE_EVNTSEL_EDGE_MASK 0x00040000ULL
471#define CORE_EVNTSEL_INV_MASK 0x00800000ULL 526#define CORE_EVNTSEL_INV_MASK 0x00800000ULL
472#define CORE_EVNTSEL_REG_MASK 0xFF000000ULL 527#define CORE_EVNTSEL_REG_MASK 0xFF000000ULL
473 528
474#define CORE_EVNTSEL_MASK \ 529#define CORE_EVNTSEL_MASK \
475 (CORE_EVNTSEL_EVENT_MASK | \ 530 (CORE_EVNTSEL_EVENT_MASK | \
@@ -932,6 +987,8 @@ static int __hw_perf_event_init(struct perf_event *event)
932 */ 987 */
933 hwc->config = ARCH_PERFMON_EVENTSEL_INT; 988 hwc->config = ARCH_PERFMON_EVENTSEL_INT;
934 989
990 hwc->idx = -1;
991
935 /* 992 /*
936 * Count user and OS events unless requested not to. 993 * Count user and OS events unless requested not to.
937 */ 994 */
@@ -1334,8 +1391,7 @@ static void amd_pmu_enable_event(struct hw_perf_event *hwc, int idx)
1334 x86_pmu_enable_event(hwc, idx); 1391 x86_pmu_enable_event(hwc, idx);
1335} 1392}
1336 1393
1337static int 1394static int fixed_mode_idx(struct hw_perf_event *hwc)
1338fixed_mode_idx(struct perf_event *event, struct hw_perf_event *hwc)
1339{ 1395{
1340 unsigned int hw_event; 1396 unsigned int hw_event;
1341 1397
@@ -1349,6 +1405,12 @@ fixed_mode_idx(struct perf_event *event, struct hw_perf_event *hwc)
1349 if (!x86_pmu.num_events_fixed) 1405 if (!x86_pmu.num_events_fixed)
1350 return -1; 1406 return -1;
1351 1407
1408 /*
1409 * fixed counters do not take all possible filters
1410 */
1411 if (hwc->config & ARCH_PERFMON_EVENT_FILTER_MASK)
1412 return -1;
1413
1352 if (unlikely(hw_event == x86_pmu.event_map(PERF_COUNT_HW_INSTRUCTIONS))) 1414 if (unlikely(hw_event == x86_pmu.event_map(PERF_COUNT_HW_INSTRUCTIONS)))
1353 return X86_PMC_IDX_FIXED_INSTRUCTIONS; 1415 return X86_PMC_IDX_FIXED_INSTRUCTIONS;
1354 if (unlikely(hw_event == x86_pmu.event_map(PERF_COUNT_HW_CPU_CYCLES))) 1416 if (unlikely(hw_event == x86_pmu.event_map(PERF_COUNT_HW_CPU_CYCLES)))
@@ -1360,22 +1422,57 @@ fixed_mode_idx(struct perf_event *event, struct hw_perf_event *hwc)
1360} 1422}
1361 1423
1362/* 1424/*
1363 * Find a PMC slot for the freshly enabled / scheduled in event: 1425 * generic counter allocator: get next free counter
1364 */ 1426 */
1365static int x86_pmu_enable(struct perf_event *event) 1427static int
1428gen_get_event_idx(struct cpu_hw_events *cpuc, struct hw_perf_event *hwc)
1429{
1430 int idx;
1431
1432 idx = find_first_zero_bit(cpuc->used_mask, x86_pmu.num_events);
1433 return idx == x86_pmu.num_events ? -1 : idx;
1434}
1435
1436/*
1437 * intel-specific counter allocator: check event constraints
1438 */
1439static int
1440intel_get_event_idx(struct cpu_hw_events *cpuc, struct hw_perf_event *hwc)
1441{
1442 const struct event_constraint *event_constraint;
1443 int i, code;
1444
1445 if (!event_constraints)
1446 goto skip;
1447
1448 code = hwc->config & CORE_EVNTSEL_EVENT_MASK;
1449
1450 for_each_event_constraint(event_constraint, event_constraints) {
1451 if (code == event_constraint->code) {
1452 for_each_bit(i, event_constraint->idxmsk, X86_PMC_IDX_MAX) {
1453 if (!test_and_set_bit(i, cpuc->used_mask))
1454 return i;
1455 }
1456 return -1;
1457 }
1458 }
1459skip:
1460 return gen_get_event_idx(cpuc, hwc);
1461}
1462
1463static int
1464x86_schedule_event(struct cpu_hw_events *cpuc, struct hw_perf_event *hwc)
1366{ 1465{
1367 struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
1368 struct hw_perf_event *hwc = &event->hw;
1369 int idx; 1466 int idx;
1370 1467
1371 idx = fixed_mode_idx(event, hwc); 1468 idx = fixed_mode_idx(hwc);
1372 if (idx == X86_PMC_IDX_FIXED_BTS) { 1469 if (idx == X86_PMC_IDX_FIXED_BTS) {
1373 /* BTS is already occupied. */ 1470 /* BTS is already occupied. */
1374 if (test_and_set_bit(idx, cpuc->used_mask)) 1471 if (test_and_set_bit(idx, cpuc->used_mask))
1375 return -EAGAIN; 1472 return -EAGAIN;
1376 1473
1377 hwc->config_base = 0; 1474 hwc->config_base = 0;
1378 hwc->event_base = 0; 1475 hwc->event_base = 0;
1379 hwc->idx = idx; 1476 hwc->idx = idx;
1380 } else if (idx >= 0) { 1477 } else if (idx >= 0) {
1381 /* 1478 /*
@@ -1396,20 +1493,35 @@ static int x86_pmu_enable(struct perf_event *event)
1396 } else { 1493 } else {
1397 idx = hwc->idx; 1494 idx = hwc->idx;
1398 /* Try to get the previous generic event again */ 1495 /* Try to get the previous generic event again */
1399 if (test_and_set_bit(idx, cpuc->used_mask)) { 1496 if (idx == -1 || test_and_set_bit(idx, cpuc->used_mask)) {
1400try_generic: 1497try_generic:
1401 idx = find_first_zero_bit(cpuc->used_mask, 1498 idx = x86_pmu.get_event_idx(cpuc, hwc);
1402 x86_pmu.num_events); 1499 if (idx == -1)
1403 if (idx == x86_pmu.num_events)
1404 return -EAGAIN; 1500 return -EAGAIN;
1405 1501
1406 set_bit(idx, cpuc->used_mask); 1502 set_bit(idx, cpuc->used_mask);
1407 hwc->idx = idx; 1503 hwc->idx = idx;
1408 } 1504 }
1409 hwc->config_base = x86_pmu.eventsel; 1505 hwc->config_base = x86_pmu.eventsel;
1410 hwc->event_base = x86_pmu.perfctr; 1506 hwc->event_base = x86_pmu.perfctr;
1411 } 1507 }
1412 1508
1509 return idx;
1510}
1511
1512/*
1513 * Find a PMC slot for the freshly enabled / scheduled in event:
1514 */
1515static int x86_pmu_enable(struct perf_event *event)
1516{
1517 struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
1518 struct hw_perf_event *hwc = &event->hw;
1519 int idx;
1520
1521 idx = x86_schedule_event(cpuc, hwc);
1522 if (idx < 0)
1523 return idx;
1524
1413 perf_events_lapic_init(); 1525 perf_events_lapic_init();
1414 1526
1415 x86_pmu.disable(hwc, idx); 1527 x86_pmu.disable(hwc, idx);
@@ -1877,6 +1989,7 @@ static struct x86_pmu p6_pmu = {
1877 */ 1989 */
1878 .event_bits = 32, 1990 .event_bits = 32,
1879 .event_mask = (1ULL << 32) - 1, 1991 .event_mask = (1ULL << 32) - 1,
1992 .get_event_idx = intel_get_event_idx,
1880}; 1993};
1881 1994
1882static struct x86_pmu intel_pmu = { 1995static struct x86_pmu intel_pmu = {
@@ -1900,6 +2013,7 @@ static struct x86_pmu intel_pmu = {
1900 .max_period = (1ULL << 31) - 1, 2013 .max_period = (1ULL << 31) - 1,
1901 .enable_bts = intel_pmu_enable_bts, 2014 .enable_bts = intel_pmu_enable_bts,
1902 .disable_bts = intel_pmu_disable_bts, 2015 .disable_bts = intel_pmu_disable_bts,
2016 .get_event_idx = intel_get_event_idx,
1903}; 2017};
1904 2018
1905static struct x86_pmu amd_pmu = { 2019static struct x86_pmu amd_pmu = {
@@ -1920,6 +2034,7 @@ static struct x86_pmu amd_pmu = {
1920 .apic = 1, 2034 .apic = 1,
1921 /* use highest bit to detect overflow */ 2035 /* use highest bit to detect overflow */
1922 .max_period = (1ULL << 47) - 1, 2036 .max_period = (1ULL << 47) - 1,
2037 .get_event_idx = gen_get_event_idx,
1923}; 2038};
1924 2039
1925static int p6_pmu_init(void) 2040static int p6_pmu_init(void)
@@ -1932,10 +2047,12 @@ static int p6_pmu_init(void)
1932 case 7: 2047 case 7:
1933 case 8: 2048 case 8:
1934 case 11: /* Pentium III */ 2049 case 11: /* Pentium III */
2050 event_constraints = intel_p6_event_constraints;
1935 break; 2051 break;
1936 case 9: 2052 case 9:
1937 case 13: 2053 case 13:
1938 /* Pentium M */ 2054 /* Pentium M */
2055 event_constraints = intel_p6_event_constraints;
1939 break; 2056 break;
1940 default: 2057 default:
1941 pr_cont("unsupported p6 CPU model %d ", 2058 pr_cont("unsupported p6 CPU model %d ",
@@ -2007,12 +2124,14 @@ static int intel_pmu_init(void)
2007 sizeof(hw_cache_event_ids)); 2124 sizeof(hw_cache_event_ids));
2008 2125
2009 pr_cont("Core2 events, "); 2126 pr_cont("Core2 events, ");
2127 event_constraints = intel_core_event_constraints;
2010 break; 2128 break;
2011 default: 2129 default:
2012 case 26: 2130 case 26:
2013 memcpy(hw_cache_event_ids, nehalem_hw_cache_event_ids, 2131 memcpy(hw_cache_event_ids, nehalem_hw_cache_event_ids,
2014 sizeof(hw_cache_event_ids)); 2132 sizeof(hw_cache_event_ids));
2015 2133
2134 event_constraints = intel_nehalem_event_constraints;
2016 pr_cont("Nehalem/Corei7 events, "); 2135 pr_cont("Nehalem/Corei7 events, ");
2017 break; 2136 break;
2018 case 28: 2137 case 28:
@@ -2105,11 +2224,47 @@ static const struct pmu pmu = {
2105 .unthrottle = x86_pmu_unthrottle, 2224 .unthrottle = x86_pmu_unthrottle,
2106}; 2225};
2107 2226
2227static int
2228validate_event(struct cpu_hw_events *cpuc, struct perf_event *event)
2229{
2230 struct hw_perf_event fake_event = event->hw;
2231
2232 if (event->pmu != &pmu)
2233 return 0;
2234
2235 return x86_schedule_event(cpuc, &fake_event);
2236}
2237
2238static int validate_group(struct perf_event *event)
2239{
2240 struct perf_event *sibling, *leader = event->group_leader;
2241 struct cpu_hw_events fake_pmu;
2242
2243 memset(&fake_pmu, 0, sizeof(fake_pmu));
2244
2245 if (!validate_event(&fake_pmu, leader))
2246 return -ENOSPC;
2247
2248 list_for_each_entry(sibling, &leader->sibling_list, group_entry) {
2249 if (!validate_event(&fake_pmu, sibling))
2250 return -ENOSPC;
2251 }
2252
2253 if (!validate_event(&fake_pmu, event))
2254 return -ENOSPC;
2255
2256 return 0;
2257}
2258
2108const struct pmu *hw_perf_event_init(struct perf_event *event) 2259const struct pmu *hw_perf_event_init(struct perf_event *event)
2109{ 2260{
2110 int err; 2261 int err;
2111 2262
2112 err = __hw_perf_event_init(event); 2263 err = __hw_perf_event_init(event);
2264 if (!err) {
2265 if (event->group_leader != event)
2266 err = validate_group(event);
2267 }
2113 if (err) { 2268 if (err) {
2114 if (event->destroy) 2269 if (event->destroy)
2115 event->destroy(event); 2270 event->destroy(event);
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S
index beb30da203d..50b9c220e12 100644
--- a/arch/x86/kernel/entry_32.S
+++ b/arch/x86/kernel/entry_32.S
@@ -1209,17 +1209,14 @@ END(ftrace_graph_caller)
1209 1209
1210.globl return_to_handler 1210.globl return_to_handler
1211return_to_handler: 1211return_to_handler:
1212 pushl $0
1213 pushl %eax 1212 pushl %eax
1214 pushl %ecx
1215 pushl %edx 1213 pushl %edx
1216 movl %ebp, %eax 1214 movl %ebp, %eax
1217 call ftrace_return_to_handler 1215 call ftrace_return_to_handler
1218 movl %eax, 0xc(%esp) 1216 movl %eax, %ecx
1219 popl %edx 1217 popl %edx
1220 popl %ecx
1221 popl %eax 1218 popl %eax
1222 ret 1219 jmp *%ecx
1223#endif 1220#endif
1224 1221
1225.section .rodata,"a" 1222.section .rodata,"a"
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index 42a0b2cbf2e..722df1b1152 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -155,11 +155,11 @@ GLOBAL(return_to_handler)
155 155
156 call ftrace_return_to_handler 156 call ftrace_return_to_handler
157 157
158 movq %rax, 16(%rsp) 158 movq %rax, %rdi
159 movq 8(%rsp), %rdx 159 movq 8(%rsp), %rdx
160 movq (%rsp), %rax 160 movq (%rsp), %rax
161 addq $16, %rsp 161 addq $24, %rsp
162 retq 162 jmp *%rdi
163#endif 163#endif
164 164
165 165
diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c
index 9dbb527e165..5a1b9758fd6 100644
--- a/arch/x86/kernel/ftrace.c
+++ b/arch/x86/kernel/ftrace.c
@@ -9,6 +9,8 @@
9 * the dangers of modifying code on the run. 9 * the dangers of modifying code on the run.
10 */ 10 */
11 11
12#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
13
12#include <linux/spinlock.h> 14#include <linux/spinlock.h>
13#include <linux/hardirq.h> 15#include <linux/hardirq.h>
14#include <linux/uaccess.h> 16#include <linux/uaccess.h>
@@ -336,15 +338,15 @@ int __init ftrace_dyn_arch_init(void *data)
336 338
337 switch (faulted) { 339 switch (faulted) {
338 case 0: 340 case 0:
339 pr_info("ftrace: converting mcount calls to 0f 1f 44 00 00\n"); 341 pr_info("converting mcount calls to 0f 1f 44 00 00\n");
340 memcpy(ftrace_nop, ftrace_test_p6nop, MCOUNT_INSN_SIZE); 342 memcpy(ftrace_nop, ftrace_test_p6nop, MCOUNT_INSN_SIZE);
341 break; 343 break;
342 case 1: 344 case 1:
343 pr_info("ftrace: converting mcount calls to 66 66 66 66 90\n"); 345 pr_info("converting mcount calls to 66 66 66 66 90\n");
344 memcpy(ftrace_nop, ftrace_test_nop5, MCOUNT_INSN_SIZE); 346 memcpy(ftrace_nop, ftrace_test_nop5, MCOUNT_INSN_SIZE);
345 break; 347 break;
346 case 2: 348 case 2:
347 pr_info("ftrace: converting mcount calls to jmp . + 5\n"); 349 pr_info("converting mcount calls to jmp . + 5\n");
348 memcpy(ftrace_nop, ftrace_test_jmp, MCOUNT_INSN_SIZE); 350 memcpy(ftrace_nop, ftrace_test_jmp, MCOUNT_INSN_SIZE);
349 break; 351 break;
350 } 352 }
@@ -468,82 +470,10 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
468 470
469#ifdef CONFIG_FTRACE_SYSCALLS 471#ifdef CONFIG_FTRACE_SYSCALLS
470 472
471extern unsigned long __start_syscalls_metadata[];
472extern unsigned long __stop_syscalls_metadata[];
473extern unsigned long *sys_call_table; 473extern unsigned long *sys_call_table;
474 474
475static struct syscall_metadata **syscalls_metadata; 475unsigned long __init arch_syscall_addr(int nr)
476
477static struct syscall_metadata *find_syscall_meta(unsigned long *syscall)
478{
479 struct syscall_metadata *start;
480 struct syscall_metadata *stop;
481 char str[KSYM_SYMBOL_LEN];
482
483
484 start = (struct syscall_metadata *)__start_syscalls_metadata;
485 stop = (struct syscall_metadata *)__stop_syscalls_metadata;
486 kallsyms_lookup((unsigned long) syscall, NULL, NULL, NULL, str);
487
488 for ( ; start < stop; start++) {
489 if (start->name && !strcmp(start->name, str))
490 return start;
491 }
492 return NULL;
493}
494
495struct syscall_metadata *syscall_nr_to_meta(int nr)
496{
497 if (!syscalls_metadata || nr >= NR_syscalls || nr < 0)
498 return NULL;
499
500 return syscalls_metadata[nr];
501}
502
503int syscall_name_to_nr(char *name)
504{ 476{
505 int i; 477 return (unsigned long)(&sys_call_table)[nr];
506
507 if (!syscalls_metadata)
508 return -1;
509
510 for (i = 0; i < NR_syscalls; i++) {
511 if (syscalls_metadata[i]) {
512 if (!strcmp(syscalls_metadata[i]->name, name))
513 return i;
514 }
515 }
516 return -1;
517}
518
519void set_syscall_enter_id(int num, int id)
520{
521 syscalls_metadata[num]->enter_id = id;
522}
523
524void set_syscall_exit_id(int num, int id)
525{
526 syscalls_metadata[num]->exit_id = id;
527}
528
529static int __init arch_init_ftrace_syscalls(void)
530{
531 int i;
532 struct syscall_metadata *meta;
533 unsigned long **psys_syscall_table = &sys_call_table;
534
535 syscalls_metadata = kzalloc(sizeof(*syscalls_metadata) *
536 NR_syscalls, GFP_KERNEL);
537 if (!syscalls_metadata) {
538 WARN_ON(1);
539 return -ENOMEM;
540 }
541
542 for (i = 0; i < NR_syscalls; i++) {
543 meta = find_syscall_meta(psys_syscall_table[i]);
544 syscalls_metadata[i] = meta;
545 }
546 return 0;
547} 478}
548arch_initcall(arch_init_ftrace_syscalls);
549#endif 479#endif
diff --git a/arch/x86/mm/testmmiotrace.c b/arch/x86/mm/testmmiotrace.c
index 427fd1b56df..8565d944f7c 100644
--- a/arch/x86/mm/testmmiotrace.c
+++ b/arch/x86/mm/testmmiotrace.c
@@ -1,12 +1,13 @@
1/* 1/*
2 * Written by Pekka Paalanen, 2008-2009 <pq@iki.fi> 2 * Written by Pekka Paalanen, 2008-2009 <pq@iki.fi>
3 */ 3 */
4
5#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
6
4#include <linux/module.h> 7#include <linux/module.h>
5#include <linux/io.h> 8#include <linux/io.h>
6#include <linux/mmiotrace.h> 9#include <linux/mmiotrace.h>
7 10
8#define MODULE_NAME "testmmiotrace"
9
10static unsigned long mmio_address; 11static unsigned long mmio_address;
11module_param(mmio_address, ulong, 0); 12module_param(mmio_address, ulong, 0);
12MODULE_PARM_DESC(mmio_address, " Start address of the mapping of 16 kB " 13MODULE_PARM_DESC(mmio_address, " Start address of the mapping of 16 kB "
@@ -30,7 +31,7 @@ static unsigned v32(unsigned i)
30static void do_write_test(void __iomem *p) 31static void do_write_test(void __iomem *p)
31{ 32{
32 unsigned int i; 33 unsigned int i;
33 pr_info(MODULE_NAME ": write test.\n"); 34 pr_info("write test.\n");
34 mmiotrace_printk("Write test.\n"); 35 mmiotrace_printk("Write test.\n");
35 36
36 for (i = 0; i < 256; i++) 37 for (i = 0; i < 256; i++)
@@ -47,7 +48,7 @@ static void do_read_test(void __iomem *p)
47{ 48{
48 unsigned int i; 49 unsigned int i;
49 unsigned errs[3] = { 0 }; 50 unsigned errs[3] = { 0 };
50 pr_info(MODULE_NAME ": read test.\n"); 51 pr_info("read test.\n");
51 mmiotrace_printk("Read test.\n"); 52 mmiotrace_printk("Read test.\n");
52 53
53 for (i = 0; i < 256; i++) 54 for (i = 0; i < 256; i++)
@@ -68,7 +69,7 @@ static void do_read_test(void __iomem *p)
68 69
69static void do_read_far_test(void __iomem *p) 70static void do_read_far_test(void __iomem *p)
70{ 71{
71 pr_info(MODULE_NAME ": read far test.\n"); 72 pr_info("read far test.\n");
72 mmiotrace_printk("Read far test.\n"); 73 mmiotrace_printk("Read far test.\n");
73 74
74 ioread32(p + read_far); 75 ioread32(p + read_far);
@@ -78,7 +79,7 @@ static void do_test(unsigned long size)
78{ 79{
79 void __iomem *p = ioremap_nocache(mmio_address, size); 80 void __iomem *p = ioremap_nocache(mmio_address, size);
80 if (!p) { 81 if (!p) {
81 pr_err(MODULE_NAME ": could not ioremap, aborting.\n"); 82 pr_err("could not ioremap, aborting.\n");
82 return; 83 return;
83 } 84 }
84 mmiotrace_printk("ioremap returned %p.\n", p); 85 mmiotrace_printk("ioremap returned %p.\n", p);
@@ -94,24 +95,22 @@ static int __init init(void)
94 unsigned long size = (read_far) ? (8 << 20) : (16 << 10); 95 unsigned long size = (read_far) ? (8 << 20) : (16 << 10);
95 96
96 if (mmio_address == 0) { 97 if (mmio_address == 0) {
97 pr_err(MODULE_NAME ": you have to use the module argument " 98 pr_err("you have to use the module argument mmio_address.\n");
98 "mmio_address.\n"); 99 pr_err("DO NOT LOAD THIS MODULE UNLESS YOU REALLY KNOW WHAT YOU ARE DOING!\n");
99 pr_err(MODULE_NAME ": DO NOT LOAD THIS MODULE UNLESS"
100 " YOU REALLY KNOW WHAT YOU ARE DOING!\n");
101 return -ENXIO; 100 return -ENXIO;
102 } 101 }
103 102
104 pr_warning(MODULE_NAME ": WARNING: mapping %lu kB @ 0x%08lx in PCI " 103 pr_warning("WARNING: mapping %lu kB @ 0x%08lx in PCI address space, "
105 "address space, and writing 16 kB of rubbish in there.\n", 104 "and writing 16 kB of rubbish in there.\n",
106 size >> 10, mmio_address); 105 size >> 10, mmio_address);
107 do_test(size); 106 do_test(size);
108 pr_info(MODULE_NAME ": All done.\n"); 107 pr_info("All done.\n");
109 return 0; 108 return 0;
110} 109}
111 110
112static void __exit cleanup(void) 111static void __exit cleanup(void)
113{ 112{
114 pr_debug(MODULE_NAME ": unloaded.\n"); 113 pr_debug("unloaded.\n");
115} 114}
116 115
117module_init(init); 116module_init(init);
diff --git a/include/linux/ftrace_event.h b/include/linux/ftrace_event.h
index 3451c55acb5..f7b47c33670 100644
--- a/include/linux/ftrace_event.h
+++ b/include/linux/ftrace_event.h
@@ -144,7 +144,7 @@ extern char *trace_profile_buf_nmi;
144#define MAX_FILTER_STR_VAL 256 /* Should handle KSYM_SYMBOL_LEN */ 144#define MAX_FILTER_STR_VAL 256 /* Should handle KSYM_SYMBOL_LEN */
145 145
146extern void destroy_preds(struct ftrace_event_call *call); 146extern void destroy_preds(struct ftrace_event_call *call);
147extern int filter_match_preds(struct ftrace_event_call *call, void *rec); 147extern int filter_match_preds(struct event_filter *filter, void *rec);
148extern int filter_current_check_discard(struct ring_buffer *buffer, 148extern int filter_current_check_discard(struct ring_buffer *buffer,
149 struct ftrace_event_call *call, 149 struct ftrace_event_call *call,
150 void *rec, 150 void *rec,
@@ -187,4 +187,13 @@ do { \
187 __trace_printk(ip, fmt, ##args); \ 187 __trace_printk(ip, fmt, ##args); \
188} while (0) 188} while (0)
189 189
190#ifdef CONFIG_EVENT_PROFILE
191struct perf_event;
192extern int ftrace_profile_enable(int event_id);
193extern void ftrace_profile_disable(int event_id);
194extern int ftrace_profile_set_filter(struct perf_event *event, int event_id,
195 char *filter_str);
196extern void ftrace_profile_free_filter(struct perf_event *event);
197#endif
198
190#endif /* _LINUX_FTRACE_EVENT_H */ 199#endif /* _LINUX_FTRACE_EVENT_H */
diff --git a/include/linux/perf_counter.h b/include/linux/perf_counter.h
index 7b7fbf433cf..91a2b4309e7 100644
--- a/include/linux/perf_counter.h
+++ b/include/linux/perf_counter.h
@@ -225,6 +225,7 @@ struct perf_counter_attr {
225#define PERF_COUNTER_IOC_RESET _IO ('$', 3) 225#define PERF_COUNTER_IOC_RESET _IO ('$', 3)
226#define PERF_COUNTER_IOC_PERIOD _IOW('$', 4, u64) 226#define PERF_COUNTER_IOC_PERIOD _IOW('$', 4, u64)
227#define PERF_COUNTER_IOC_SET_OUTPUT _IO ('$', 5) 227#define PERF_COUNTER_IOC_SET_OUTPUT _IO ('$', 5)
228#define PERF_COUNTER_IOC_SET_FILTER _IOW('$', 6, char *)
228 229
229enum perf_counter_ioc_flags { 230enum perf_counter_ioc_flags {
230 PERF_IOC_FLAG_GROUP = 1U << 0, 231 PERF_IOC_FLAG_GROUP = 1U << 0,
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 2e6d95f9741..df9d964c15f 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -221,6 +221,7 @@ struct perf_event_attr {
221#define PERF_EVENT_IOC_RESET _IO ('$', 3) 221#define PERF_EVENT_IOC_RESET _IO ('$', 3)
222#define PERF_EVENT_IOC_PERIOD _IOW('$', 4, u64) 222#define PERF_EVENT_IOC_PERIOD _IOW('$', 4, u64)
223#define PERF_EVENT_IOC_SET_OUTPUT _IO ('$', 5) 223#define PERF_EVENT_IOC_SET_OUTPUT _IO ('$', 5)
224#define PERF_EVENT_IOC_SET_FILTER _IOW('$', 6, char *)
224 225
225enum perf_event_ioc_flags { 226enum perf_event_ioc_flags {
226 PERF_IOC_FLAG_GROUP = 1U << 0, 227 PERF_IOC_FLAG_GROUP = 1U << 0,
@@ -633,7 +634,12 @@ struct perf_event {
633 634
634 struct pid_namespace *ns; 635 struct pid_namespace *ns;
635 u64 id; 636 u64 id;
637
638#ifdef CONFIG_EVENT_PROFILE
639 struct event_filter *filter;
636#endif 640#endif
641
642#endif /* CONFIG_PERF_EVENTS */
637}; 643};
638 644
639/** 645/**
diff --git a/include/linux/smp_lock.h b/include/linux/smp_lock.h
index 813be59bf34..2ea1dd1ba21 100644
--- a/include/linux/smp_lock.h
+++ b/include/linux/smp_lock.h
@@ -24,8 +24,21 @@ static inline int reacquire_kernel_lock(struct task_struct *task)
24 return 0; 24 return 0;
25} 25}
26 26
27extern void __lockfunc lock_kernel(void) __acquires(kernel_lock); 27extern void __lockfunc
28extern void __lockfunc unlock_kernel(void) __releases(kernel_lock); 28_lock_kernel(const char *func, const char *file, int line)
29__acquires(kernel_lock);
30
31extern void __lockfunc
32_unlock_kernel(const char *func, const char *file, int line)
33__releases(kernel_lock);
34
35#define lock_kernel() do { \
36 _lock_kernel(__func__, __FILE__, __LINE__); \
37} while (0)
38
39#define unlock_kernel() do { \
40 _unlock_kernel(__func__, __FILE__, __LINE__); \
41} while (0)
29 42
30/* 43/*
31 * Various legacy drivers don't really need the BKL in a specific 44 * Various legacy drivers don't really need the BKL in a specific
@@ -41,8 +54,8 @@ static inline void cycle_kernel_lock(void)
41 54
42#else 55#else
43 56
44#define lock_kernel() do { } while(0) 57#define lock_kernel()
45#define unlock_kernel() do { } while(0) 58#define unlock_kernel()
46#define release_kernel_lock(task) do { } while(0) 59#define release_kernel_lock(task) do { } while(0)
47#define cycle_kernel_lock() do { } while(0) 60#define cycle_kernel_lock() do { } while(0)
48#define reacquire_kernel_lock(task) 0 61#define reacquire_kernel_lock(task) 0
diff --git a/include/trace/events/bkl.h b/include/trace/events/bkl.h
new file mode 100644
index 00000000000..1af72dc2427
--- /dev/null
+++ b/include/trace/events/bkl.h
@@ -0,0 +1,61 @@
1#undef TRACE_SYSTEM
2#define TRACE_SYSTEM bkl
3
4#if !defined(_TRACE_BKL_H) || defined(TRACE_HEADER_MULTI_READ)
5#define _TRACE_BKL_H
6
7#include <linux/tracepoint.h>
8
9TRACE_EVENT(lock_kernel,
10
11 TP_PROTO(const char *func, const char *file, int line),
12
13 TP_ARGS(func, file, line),
14
15 TP_STRUCT__entry(
16 __field( int, depth )
17 __field_ext( const char *, func, FILTER_PTR_STRING )
18 __field_ext( const char *, file, FILTER_PTR_STRING )
19 __field( int, line )
20 ),
21
22 TP_fast_assign(
23 /* We want to record the lock_depth after lock is acquired */
24 __entry->depth = current->lock_depth + 1;
25 __entry->func = func;
26 __entry->file = file;
27 __entry->line = line;
28 ),
29
30 TP_printk("depth=%d file:line=%s:%d func=%s()", __entry->depth,
31 __entry->file, __entry->line, __entry->func)
32);
33
34TRACE_EVENT(unlock_kernel,
35
36 TP_PROTO(const char *func, const char *file, int line),
37
38 TP_ARGS(func, file, line),
39
40 TP_STRUCT__entry(
41 __field(int, depth )
42 __field(const char *, func )
43 __field(const char *, file )
44 __field(int, line )
45 ),
46
47 TP_fast_assign(
48 __entry->depth = current->lock_depth;
49 __entry->func = func;
50 __entry->file = file;
51 __entry->line = line;
52 ),
53
54 TP_printk("depth=%d file:line=%s:%d func=%s()", __entry->depth,
55 __entry->file, __entry->line, __entry->func)
56);
57
58#endif /* _TRACE_BKL_H */
59
60/* This part must be outside protection */
61#include <trace/define_trace.h>
diff --git a/include/trace/events/irq.h b/include/trace/events/irq.h
index b89f9db4a40..dcfcd440762 100644
--- a/include/trace/events/irq.h
+++ b/include/trace/events/irq.h
@@ -48,7 +48,7 @@ TRACE_EVENT(irq_handler_entry,
48 __assign_str(name, action->name); 48 __assign_str(name, action->name);
49 ), 49 ),
50 50
51 TP_printk("irq=%d handler=%s", __entry->irq, __get_str(name)) 51 TP_printk("irq=%d name=%s", __entry->irq, __get_str(name))
52); 52);
53 53
54/** 54/**
@@ -78,7 +78,7 @@ TRACE_EVENT(irq_handler_exit,
78 __entry->ret = ret; 78 __entry->ret = ret;
79 ), 79 ),
80 80
81 TP_printk("irq=%d return=%s", 81 TP_printk("irq=%d ret=%s",
82 __entry->irq, __entry->ret ? "handled" : "unhandled") 82 __entry->irq, __entry->ret ? "handled" : "unhandled")
83); 83);
84 84
@@ -107,7 +107,7 @@ TRACE_EVENT(softirq_entry,
107 __entry->vec = (int)(h - vec); 107 __entry->vec = (int)(h - vec);
108 ), 108 ),
109 109
110 TP_printk("softirq=%d action=%s", __entry->vec, 110 TP_printk("vec=%d [action=%s]", __entry->vec,
111 show_softirq_name(__entry->vec)) 111 show_softirq_name(__entry->vec))
112); 112);
113 113
@@ -136,7 +136,7 @@ TRACE_EVENT(softirq_exit,
136 __entry->vec = (int)(h - vec); 136 __entry->vec = (int)(h - vec);
137 ), 137 ),
138 138
139 TP_printk("softirq=%d action=%s", __entry->vec, 139 TP_printk("vec=%d [action=%s]", __entry->vec,
140 show_softirq_name(__entry->vec)) 140 show_softirq_name(__entry->vec))
141); 141);
142 142
diff --git a/include/trace/events/power.h b/include/trace/events/power.h
index ea6d579261a..9bb96e5a284 100644
--- a/include/trace/events/power.h
+++ b/include/trace/events/power.h
@@ -16,8 +16,6 @@ enum {
16}; 16};
17#endif 17#endif
18 18
19
20
21TRACE_EVENT(power_start, 19TRACE_EVENT(power_start,
22 20
23 TP_PROTO(unsigned int type, unsigned int state), 21 TP_PROTO(unsigned int type, unsigned int state),
diff --git a/include/trace/events/sched.h b/include/trace/events/sched.h
index 4069c43f418..b50b9856c59 100644
--- a/include/trace/events/sched.h
+++ b/include/trace/events/sched.h
@@ -26,7 +26,7 @@ TRACE_EVENT(sched_kthread_stop,
26 __entry->pid = t->pid; 26 __entry->pid = t->pid;
27 ), 27 ),
28 28
29 TP_printk("task %s:%d", __entry->comm, __entry->pid) 29 TP_printk("comm=%s pid=%d", __entry->comm, __entry->pid)
30); 30);
31 31
32/* 32/*
@@ -46,7 +46,7 @@ TRACE_EVENT(sched_kthread_stop_ret,
46 __entry->ret = ret; 46 __entry->ret = ret;
47 ), 47 ),
48 48
49 TP_printk("ret %d", __entry->ret) 49 TP_printk("ret=%d", __entry->ret)
50); 50);
51 51
52/* 52/*
@@ -73,7 +73,7 @@ TRACE_EVENT(sched_wait_task,
73 __entry->prio = p->prio; 73 __entry->prio = p->prio;
74 ), 74 ),
75 75
76 TP_printk("task %s:%d [%d]", 76 TP_printk("comm=%s pid=%d prio=%d",
77 __entry->comm, __entry->pid, __entry->prio) 77 __entry->comm, __entry->pid, __entry->prio)
78); 78);
79 79
@@ -94,7 +94,7 @@ TRACE_EVENT(sched_wakeup,
94 __field( pid_t, pid ) 94 __field( pid_t, pid )
95 __field( int, prio ) 95 __field( int, prio )
96 __field( int, success ) 96 __field( int, success )
97 __field( int, cpu ) 97 __field( int, target_cpu )
98 ), 98 ),
99 99
100 TP_fast_assign( 100 TP_fast_assign(
@@ -102,12 +102,12 @@ TRACE_EVENT(sched_wakeup,
102 __entry->pid = p->pid; 102 __entry->pid = p->pid;
103 __entry->prio = p->prio; 103 __entry->prio = p->prio;
104 __entry->success = success; 104 __entry->success = success;
105 __entry->cpu = task_cpu(p); 105 __entry->target_cpu = task_cpu(p);
106 ), 106 ),
107 107
108 TP_printk("task %s:%d [%d] success=%d [%03d]", 108 TP_printk("comm=%s pid=%d prio=%d success=%d target_cpu=%03d",
109 __entry->comm, __entry->pid, __entry->prio, 109 __entry->comm, __entry->pid, __entry->prio,
110 __entry->success, __entry->cpu) 110 __entry->success, __entry->target_cpu)
111); 111);
112 112
113/* 113/*
@@ -127,7 +127,7 @@ TRACE_EVENT(sched_wakeup_new,
127 __field( pid_t, pid ) 127 __field( pid_t, pid )
128 __field( int, prio ) 128 __field( int, prio )
129 __field( int, success ) 129 __field( int, success )
130 __field( int, cpu ) 130 __field( int, target_cpu )
131 ), 131 ),
132 132
133 TP_fast_assign( 133 TP_fast_assign(
@@ -135,12 +135,12 @@ TRACE_EVENT(sched_wakeup_new,
135 __entry->pid = p->pid; 135 __entry->pid = p->pid;
136 __entry->prio = p->prio; 136 __entry->prio = p->prio;
137 __entry->success = success; 137 __entry->success = success;
138 __entry->cpu = task_cpu(p); 138 __entry->target_cpu = task_cpu(p);
139 ), 139 ),
140 140
141 TP_printk("task %s:%d [%d] success=%d [%03d]", 141 TP_printk("comm=%s pid=%d prio=%d success=%d target_cpu=%03d",
142 __entry->comm, __entry->pid, __entry->prio, 142 __entry->comm, __entry->pid, __entry->prio,
143 __entry->success, __entry->cpu) 143 __entry->success, __entry->target_cpu)
144); 144);
145 145
146/* 146/*
@@ -176,7 +176,7 @@ TRACE_EVENT(sched_switch,
176 __entry->next_prio = next->prio; 176 __entry->next_prio = next->prio;
177 ), 177 ),
178 178
179 TP_printk("task %s:%d [%d] (%s) ==> %s:%d [%d]", 179 TP_printk("prev_comm=%s prev_pid=%d prev_prio=%d prev_state=%s ==> next_comm=%s next_pid=%d next_prio=%d",
180 __entry->prev_comm, __entry->prev_pid, __entry->prev_prio, 180 __entry->prev_comm, __entry->prev_pid, __entry->prev_prio,
181 __entry->prev_state ? 181 __entry->prev_state ?
182 __print_flags(__entry->prev_state, "|", 182 __print_flags(__entry->prev_state, "|",
@@ -211,7 +211,7 @@ TRACE_EVENT(sched_migrate_task,
211 __entry->dest_cpu = dest_cpu; 211 __entry->dest_cpu = dest_cpu;
212 ), 212 ),
213 213
214 TP_printk("task %s:%d [%d] from: %d to: %d", 214 TP_printk("comm=%s pid=%d prio=%d orig_cpu=%d dest_cpu=%d",
215 __entry->comm, __entry->pid, __entry->prio, 215 __entry->comm, __entry->pid, __entry->prio,
216 __entry->orig_cpu, __entry->dest_cpu) 216 __entry->orig_cpu, __entry->dest_cpu)
217); 217);
@@ -237,7 +237,7 @@ TRACE_EVENT(sched_process_free,
237 __entry->prio = p->prio; 237 __entry->prio = p->prio;
238 ), 238 ),
239 239
240 TP_printk("task %s:%d [%d]", 240 TP_printk("comm=%s pid=%d prio=%d",
241 __entry->comm, __entry->pid, __entry->prio) 241 __entry->comm, __entry->pid, __entry->prio)
242); 242);
243 243
@@ -262,7 +262,7 @@ TRACE_EVENT(sched_process_exit,
262 __entry->prio = p->prio; 262 __entry->prio = p->prio;
263 ), 263 ),
264 264
265 TP_printk("task %s:%d [%d]", 265 TP_printk("comm=%s pid=%d prio=%d",
266 __entry->comm, __entry->pid, __entry->prio) 266 __entry->comm, __entry->pid, __entry->prio)
267); 267);
268 268
@@ -287,7 +287,7 @@ TRACE_EVENT(sched_process_wait,
287 __entry->prio = current->prio; 287 __entry->prio = current->prio;
288 ), 288 ),
289 289
290 TP_printk("task %s:%d [%d]", 290 TP_printk("comm=%s pid=%d prio=%d",
291 __entry->comm, __entry->pid, __entry->prio) 291 __entry->comm, __entry->pid, __entry->prio)
292); 292);
293 293
@@ -314,7 +314,7 @@ TRACE_EVENT(sched_process_fork,
314 __entry->child_pid = child->pid; 314 __entry->child_pid = child->pid;
315 ), 315 ),
316 316
317 TP_printk("parent %s:%d child %s:%d", 317 TP_printk("comm=%s pid=%d child_comm=%s child_pid=%d",
318 __entry->parent_comm, __entry->parent_pid, 318 __entry->parent_comm, __entry->parent_pid,
319 __entry->child_comm, __entry->child_pid) 319 __entry->child_comm, __entry->child_pid)
320); 320);
@@ -340,7 +340,7 @@ TRACE_EVENT(sched_signal_send,
340 __entry->sig = sig; 340 __entry->sig = sig;
341 ), 341 ),
342 342
343 TP_printk("sig: %d task %s:%d", 343 TP_printk("sig=%d comm=%s pid=%d",
344 __entry->sig, __entry->comm, __entry->pid) 344 __entry->sig, __entry->comm, __entry->pid)
345); 345);
346 346
@@ -374,7 +374,7 @@ TRACE_EVENT(sched_stat_wait,
374 __perf_count(delay); 374 __perf_count(delay);
375 ), 375 ),
376 376
377 TP_printk("task: %s:%d wait: %Lu [ns]", 377 TP_printk("comm=%s pid=%d delay=%Lu [ns]",
378 __entry->comm, __entry->pid, 378 __entry->comm, __entry->pid,
379 (unsigned long long)__entry->delay) 379 (unsigned long long)__entry->delay)
380); 380);
@@ -406,7 +406,7 @@ TRACE_EVENT(sched_stat_runtime,
406 __perf_count(runtime); 406 __perf_count(runtime);
407 ), 407 ),
408 408
409 TP_printk("task: %s:%d runtime: %Lu [ns], vruntime: %Lu [ns]", 409 TP_printk("comm=%s pid=%d runtime=%Lu [ns] vruntime=%Lu [ns]",
410 __entry->comm, __entry->pid, 410 __entry->comm, __entry->pid,
411 (unsigned long long)__entry->runtime, 411 (unsigned long long)__entry->runtime,
412 (unsigned long long)__entry->vruntime) 412 (unsigned long long)__entry->vruntime)
@@ -437,7 +437,7 @@ TRACE_EVENT(sched_stat_sleep,
437 __perf_count(delay); 437 __perf_count(delay);
438 ), 438 ),
439 439
440 TP_printk("task: %s:%d sleep: %Lu [ns]", 440 TP_printk("comm=%s pid=%d delay=%Lu [ns]",
441 __entry->comm, __entry->pid, 441 __entry->comm, __entry->pid,
442 (unsigned long long)__entry->delay) 442 (unsigned long long)__entry->delay)
443); 443);
@@ -467,7 +467,7 @@ TRACE_EVENT(sched_stat_iowait,
467 __perf_count(delay); 467 __perf_count(delay);
468 ), 468 ),
469 469
470 TP_printk("task: %s:%d iowait: %Lu [ns]", 470 TP_printk("comm=%s pid=%d delay=%Lu [ns]",
471 __entry->comm, __entry->pid, 471 __entry->comm, __entry->pid,
472 (unsigned long long)__entry->delay) 472 (unsigned long long)__entry->delay)
473); 473);
diff --git a/include/trace/events/timer.h b/include/trace/events/timer.h
index 1844c48d640..e5ce87a0498 100644
--- a/include/trace/events/timer.h
+++ b/include/trace/events/timer.h
@@ -26,7 +26,7 @@ TRACE_EVENT(timer_init,
26 __entry->timer = timer; 26 __entry->timer = timer;
27 ), 27 ),
28 28
29 TP_printk("timer %p", __entry->timer) 29 TP_printk("timer=%p", __entry->timer)
30); 30);
31 31
32/** 32/**
@@ -54,7 +54,7 @@ TRACE_EVENT(timer_start,
54 __entry->now = jiffies; 54 __entry->now = jiffies;
55 ), 55 ),
56 56
57 TP_printk("timer %p: func %pf, expires %lu, timeout %ld", 57 TP_printk("timer=%p function=%pf expires=%lu [timeout=%ld]",
58 __entry->timer, __entry->function, __entry->expires, 58 __entry->timer, __entry->function, __entry->expires,
59 (long)__entry->expires - __entry->now) 59 (long)__entry->expires - __entry->now)
60); 60);
@@ -81,7 +81,7 @@ TRACE_EVENT(timer_expire_entry,
81 __entry->now = jiffies; 81 __entry->now = jiffies;
82 ), 82 ),
83 83
84 TP_printk("timer %p: now %lu", __entry->timer, __entry->now) 84 TP_printk("timer=%p now=%lu", __entry->timer, __entry->now)
85); 85);
86 86
87/** 87/**
@@ -108,7 +108,7 @@ TRACE_EVENT(timer_expire_exit,
108 __entry->timer = timer; 108 __entry->timer = timer;
109 ), 109 ),
110 110
111 TP_printk("timer %p", __entry->timer) 111 TP_printk("timer=%p", __entry->timer)
112); 112);
113 113
114/** 114/**
@@ -129,7 +129,7 @@ TRACE_EVENT(timer_cancel,
129 __entry->timer = timer; 129 __entry->timer = timer;
130 ), 130 ),
131 131
132 TP_printk("timer %p", __entry->timer) 132 TP_printk("timer=%p", __entry->timer)
133); 133);
134 134
135/** 135/**
@@ -140,24 +140,24 @@ TRACE_EVENT(timer_cancel,
140 */ 140 */
141TRACE_EVENT(hrtimer_init, 141TRACE_EVENT(hrtimer_init,
142 142
143 TP_PROTO(struct hrtimer *timer, clockid_t clockid, 143 TP_PROTO(struct hrtimer *hrtimer, clockid_t clockid,
144 enum hrtimer_mode mode), 144 enum hrtimer_mode mode),
145 145
146 TP_ARGS(timer, clockid, mode), 146 TP_ARGS(hrtimer, clockid, mode),
147 147
148 TP_STRUCT__entry( 148 TP_STRUCT__entry(
149 __field( void *, timer ) 149 __field( void *, hrtimer )
150 __field( clockid_t, clockid ) 150 __field( clockid_t, clockid )
151 __field( enum hrtimer_mode, mode ) 151 __field( enum hrtimer_mode, mode )
152 ), 152 ),
153 153
154 TP_fast_assign( 154 TP_fast_assign(
155 __entry->timer = timer; 155 __entry->hrtimer = hrtimer;
156 __entry->clockid = clockid; 156 __entry->clockid = clockid;
157 __entry->mode = mode; 157 __entry->mode = mode;
158 ), 158 ),
159 159
160 TP_printk("hrtimer %p, clockid %s, mode %s", __entry->timer, 160 TP_printk("hrtimer=%p clockid=%s mode=%s", __entry->hrtimer,
161 __entry->clockid == CLOCK_REALTIME ? 161 __entry->clockid == CLOCK_REALTIME ?
162 "CLOCK_REALTIME" : "CLOCK_MONOTONIC", 162 "CLOCK_REALTIME" : "CLOCK_MONOTONIC",
163 __entry->mode == HRTIMER_MODE_ABS ? 163 __entry->mode == HRTIMER_MODE_ABS ?
@@ -170,26 +170,26 @@ TRACE_EVENT(hrtimer_init,
170 */ 170 */
171TRACE_EVENT(hrtimer_start, 171TRACE_EVENT(hrtimer_start,
172 172
173 TP_PROTO(struct hrtimer *timer), 173 TP_PROTO(struct hrtimer *hrtimer),
174 174
175 TP_ARGS(timer), 175 TP_ARGS(hrtimer),
176 176
177 TP_STRUCT__entry( 177 TP_STRUCT__entry(
178 __field( void *, timer ) 178 __field( void *, hrtimer )
179 __field( void *, function ) 179 __field( void *, function )
180 __field( s64, expires ) 180 __field( s64, expires )
181 __field( s64, softexpires ) 181 __field( s64, softexpires )
182 ), 182 ),
183 183
184 TP_fast_assign( 184 TP_fast_assign(
185 __entry->timer = timer; 185 __entry->hrtimer = hrtimer;
186 __entry->function = timer->function; 186 __entry->function = hrtimer->function;
187 __entry->expires = hrtimer_get_expires(timer).tv64; 187 __entry->expires = hrtimer_get_expires(hrtimer).tv64;
188 __entry->softexpires = hrtimer_get_softexpires(timer).tv64; 188 __entry->softexpires = hrtimer_get_softexpires(hrtimer).tv64;
189 ), 189 ),
190 190
191 TP_printk("hrtimer %p, func %pf, expires %llu, softexpires %llu", 191 TP_printk("hrtimer=%p function=%pf expires=%llu softexpires=%llu",
192 __entry->timer, __entry->function, 192 __entry->hrtimer, __entry->function,
193 (unsigned long long)ktime_to_ns((ktime_t) { 193 (unsigned long long)ktime_to_ns((ktime_t) {
194 .tv64 = __entry->expires }), 194 .tv64 = __entry->expires }),
195 (unsigned long long)ktime_to_ns((ktime_t) { 195 (unsigned long long)ktime_to_ns((ktime_t) {
@@ -206,23 +206,22 @@ TRACE_EVENT(hrtimer_start,
206 */ 206 */
207TRACE_EVENT(hrtimer_expire_entry, 207TRACE_EVENT(hrtimer_expire_entry,
208 208
209 TP_PROTO(struct hrtimer *timer, ktime_t *now), 209 TP_PROTO(struct hrtimer *hrtimer, ktime_t *now),
210 210
211 TP_ARGS(timer, now), 211 TP_ARGS(hrtimer, now),
212 212
213 TP_STRUCT__entry( 213 TP_STRUCT__entry(
214 __field( void *, timer ) 214 __field( void *, hrtimer )
215 __field( s64, now ) 215 __field( s64, now )
216 ), 216 ),
217 217
218 TP_fast_assign( 218 TP_fast_assign(
219 __entry->timer = timer; 219 __entry->hrtimer = hrtimer;
220 __entry->now = now->tv64; 220 __entry->now = now->tv64;
221 ), 221 ),
222 222
223 TP_printk("hrtimer %p, now %llu", __entry->timer, 223 TP_printk("hrtimer=%p now=%llu", __entry->hrtimer,
224 (unsigned long long)ktime_to_ns((ktime_t) { 224 (unsigned long long)ktime_to_ns((ktime_t) { .tv64 = __entry->now }))
225 .tv64 = __entry->now }))
226 ); 225 );
227 226
228/** 227/**
@@ -234,40 +233,40 @@ TRACE_EVENT(hrtimer_expire_entry,
234 */ 233 */
235TRACE_EVENT(hrtimer_expire_exit, 234TRACE_EVENT(hrtimer_expire_exit,
236 235
237 TP_PROTO(struct hrtimer *timer), 236 TP_PROTO(struct hrtimer *hrtimer),
238 237
239 TP_ARGS(timer), 238 TP_ARGS(hrtimer),
240 239
241 TP_STRUCT__entry( 240 TP_STRUCT__entry(
242 __field( void *, timer ) 241 __field( void *, hrtimer )
243 ), 242 ),
244 243
245 TP_fast_assign( 244 TP_fast_assign(
246 __entry->timer = timer; 245 __entry->hrtimer = hrtimer;
247 ), 246 ),
248 247
249 TP_printk("hrtimer %p", __entry->timer) 248 TP_printk("hrtimer=%p", __entry->hrtimer)
250); 249);
251 250
252/** 251/**
253 * hrtimer_cancel - called when the hrtimer is canceled 252 * hrtimer_cancel - called when the hrtimer is canceled
254 * @timer: pointer to struct hrtimer 253 * @hrtimer: pointer to struct hrtimer
255 */ 254 */
256TRACE_EVENT(hrtimer_cancel, 255TRACE_EVENT(hrtimer_cancel,
257 256
258 TP_PROTO(struct hrtimer *timer), 257 TP_PROTO(struct hrtimer *hrtimer),
259 258
260 TP_ARGS(timer), 259 TP_ARGS(hrtimer),
261 260
262 TP_STRUCT__entry( 261 TP_STRUCT__entry(
263 __field( void *, timer ) 262 __field( void *, hrtimer )
264 ), 263 ),
265 264
266 TP_fast_assign( 265 TP_fast_assign(
267 __entry->timer = timer; 266 __entry->hrtimer = hrtimer;
268 ), 267 ),
269 268
270 TP_printk("hrtimer %p", __entry->timer) 269 TP_printk("hrtimer=%p", __entry->hrtimer)
271); 270);
272 271
273/** 272/**
@@ -302,7 +301,7 @@ TRACE_EVENT(itimer_state,
302 __entry->interval_usec = value->it_interval.tv_usec; 301 __entry->interval_usec = value->it_interval.tv_usec;
303 ), 302 ),
304 303
305 TP_printk("which %d, expires %lu, it_value %lu.%lu, it_interval %lu.%lu", 304 TP_printk("which=%d expires=%lu it_value=%lu.%lu it_interval=%lu.%lu",
306 __entry->which, __entry->expires, 305 __entry->which, __entry->expires,
307 __entry->value_sec, __entry->value_usec, 306 __entry->value_sec, __entry->value_usec,
308 __entry->interval_sec, __entry->interval_usec) 307 __entry->interval_sec, __entry->interval_usec)
@@ -332,7 +331,7 @@ TRACE_EVENT(itimer_expire,
332 __entry->pid = pid_nr(pid); 331 __entry->pid = pid_nr(pid);
333 ), 332 ),
334 333
335 TP_printk("which %d, pid %d, now %lu", __entry->which, 334 TP_printk("which=%d pid=%d now=%lu", __entry->which,
336 (int) __entry->pid, __entry->now) 335 (int) __entry->pid, __entry->now)
337); 336);
338 337
diff --git a/include/trace/ftrace.h b/include/trace/ftrace.h
index 54d02c06ae7..a7f94609412 100644
--- a/include/trace/ftrace.h
+++ b/include/trace/ftrace.h
@@ -120,9 +120,10 @@
120#undef __field 120#undef __field
121#define __field(type, item) \ 121#define __field(type, item) \
122 ret = trace_seq_printf(s, "\tfield:" #type " " #item ";\t" \ 122 ret = trace_seq_printf(s, "\tfield:" #type " " #item ";\t" \
123 "offset:%u;\tsize:%u;\n", \ 123 "offset:%u;\tsize:%u;\tsigned:%u;\n", \
124 (unsigned int)offsetof(typeof(field), item), \ 124 (unsigned int)offsetof(typeof(field), item), \
125 (unsigned int)sizeof(field.item)); \ 125 (unsigned int)sizeof(field.item), \
126 (unsigned int)is_signed_type(type)); \
126 if (!ret) \ 127 if (!ret) \
127 return 0; 128 return 0;
128 129
@@ -132,19 +133,21 @@
132#undef __array 133#undef __array
133#define __array(type, item, len) \ 134#define __array(type, item, len) \
134 ret = trace_seq_printf(s, "\tfield:" #type " " #item "[" #len "];\t" \ 135 ret = trace_seq_printf(s, "\tfield:" #type " " #item "[" #len "];\t" \
135 "offset:%u;\tsize:%u;\n", \ 136 "offset:%u;\tsize:%u;\tsigned:%u;\n", \
136 (unsigned int)offsetof(typeof(field), item), \ 137 (unsigned int)offsetof(typeof(field), item), \
137 (unsigned int)sizeof(field.item)); \ 138 (unsigned int)sizeof(field.item), \
139 (unsigned int)is_signed_type(type)); \
138 if (!ret) \ 140 if (!ret) \
139 return 0; 141 return 0;
140 142
141#undef __dynamic_array 143#undef __dynamic_array
142#define __dynamic_array(type, item, len) \ 144#define __dynamic_array(type, item, len) \
143 ret = trace_seq_printf(s, "\tfield:__data_loc " #type "[] " #item ";\t"\ 145 ret = trace_seq_printf(s, "\tfield:__data_loc " #type "[] " #item ";\t"\
144 "offset:%u;\tsize:%u;\n", \ 146 "offset:%u;\tsize:%u;\tsigned:%u;\n", \
145 (unsigned int)offsetof(typeof(field), \ 147 (unsigned int)offsetof(typeof(field), \
146 __data_loc_##item), \ 148 __data_loc_##item), \
147 (unsigned int)sizeof(field.__data_loc_##item)); \ 149 (unsigned int)sizeof(field.__data_loc_##item), \
150 (unsigned int)is_signed_type(type)); \
148 if (!ret) \ 151 if (!ret) \
149 return 0; 152 return 0;
150 153
diff --git a/include/trace/syscall.h b/include/trace/syscall.h
index e290b86f616..51ee17d3632 100644
--- a/include/trace/syscall.h
+++ b/include/trace/syscall.h
@@ -33,7 +33,7 @@ struct syscall_metadata {
33}; 33};
34 34
35#ifdef CONFIG_FTRACE_SYSCALLS 35#ifdef CONFIG_FTRACE_SYSCALLS
36extern struct syscall_metadata *syscall_nr_to_meta(int nr); 36extern unsigned long arch_syscall_addr(int nr);
37extern int syscall_name_to_nr(char *name); 37extern int syscall_name_to_nr(char *name);
38void set_syscall_enter_id(int num, int id); 38void set_syscall_enter_id(int num, int id);
39void set_syscall_exit_id(int num, int id); 39void set_syscall_exit_id(int num, int id);
diff --git a/kernel/perf_event.c b/kernel/perf_event.c
index 9d0b5c66588..9ecaa45ab6b 100644
--- a/kernel/perf_event.c
+++ b/kernel/perf_event.c
@@ -28,6 +28,7 @@
28#include <linux/anon_inodes.h> 28#include <linux/anon_inodes.h>
29#include <linux/kernel_stat.h> 29#include <linux/kernel_stat.h>
30#include <linux/perf_event.h> 30#include <linux/perf_event.h>
31#include <linux/ftrace_event.h>
31 32
32#include <asm/irq_regs.h> 33#include <asm/irq_regs.h>
33 34
@@ -1355,7 +1356,7 @@ static void perf_ctx_adjust_freq(struct perf_event_context *ctx)
1355 u64 interrupts, freq; 1356 u64 interrupts, freq;
1356 1357
1357 spin_lock(&ctx->lock); 1358 spin_lock(&ctx->lock);
1358 list_for_each_entry(event, &ctx->group_list, group_entry) { 1359 list_for_each_entry_rcu(event, &ctx->event_list, event_entry) {
1359 if (event->state != PERF_EVENT_STATE_ACTIVE) 1360 if (event->state != PERF_EVENT_STATE_ACTIVE)
1360 continue; 1361 continue;
1361 1362
@@ -1658,6 +1659,8 @@ static struct perf_event_context *find_get_context(pid_t pid, int cpu)
1658 return ERR_PTR(err); 1659 return ERR_PTR(err);
1659} 1660}
1660 1661
1662static void perf_event_free_filter(struct perf_event *event);
1663
1661static void free_event_rcu(struct rcu_head *head) 1664static void free_event_rcu(struct rcu_head *head)
1662{ 1665{
1663 struct perf_event *event; 1666 struct perf_event *event;
@@ -1665,6 +1668,7 @@ static void free_event_rcu(struct rcu_head *head)
1665 event = container_of(head, struct perf_event, rcu_head); 1668 event = container_of(head, struct perf_event, rcu_head);
1666 if (event->ns) 1669 if (event->ns)
1667 put_pid_ns(event->ns); 1670 put_pid_ns(event->ns);
1671 perf_event_free_filter(event);
1668 kfree(event); 1672 kfree(event);
1669} 1673}
1670 1674
@@ -1974,7 +1978,8 @@ unlock:
1974 return ret; 1978 return ret;
1975} 1979}
1976 1980
1977int perf_event_set_output(struct perf_event *event, int output_fd); 1981static int perf_event_set_output(struct perf_event *event, int output_fd);
1982static int perf_event_set_filter(struct perf_event *event, void __user *arg);
1978 1983
1979static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 1984static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
1980{ 1985{
@@ -2002,6 +2007,9 @@ static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
2002 case PERF_EVENT_IOC_SET_OUTPUT: 2007 case PERF_EVENT_IOC_SET_OUTPUT:
2003 return perf_event_set_output(event, arg); 2008 return perf_event_set_output(event, arg);
2004 2009
2010 case PERF_EVENT_IOC_SET_FILTER:
2011 return perf_event_set_filter(event, (void __user *)arg);
2012
2005 default: 2013 default:
2006 return -ENOTTY; 2014 return -ENOTTY;
2007 } 2015 }
@@ -3806,9 +3814,14 @@ static int perf_swevent_is_counting(struct perf_event *event)
3806 return 1; 3814 return 1;
3807} 3815}
3808 3816
3817static int perf_tp_event_match(struct perf_event *event,
3818 struct perf_sample_data *data);
3819
3809static int perf_swevent_match(struct perf_event *event, 3820static int perf_swevent_match(struct perf_event *event,
3810 enum perf_type_id type, 3821 enum perf_type_id type,
3811 u32 event_id, struct pt_regs *regs) 3822 u32 event_id,
3823 struct perf_sample_data *data,
3824 struct pt_regs *regs)
3812{ 3825{
3813 if (!perf_swevent_is_counting(event)) 3826 if (!perf_swevent_is_counting(event))
3814 return 0; 3827 return 0;
@@ -3826,6 +3839,10 @@ static int perf_swevent_match(struct perf_event *event,
3826 return 0; 3839 return 0;
3827 } 3840 }
3828 3841
3842 if (event->attr.type == PERF_TYPE_TRACEPOINT &&
3843 !perf_tp_event_match(event, data))
3844 return 0;
3845
3829 return 1; 3846 return 1;
3830} 3847}
3831 3848
@@ -3842,7 +3859,7 @@ static void perf_swevent_ctx_event(struct perf_event_context *ctx,
3842 3859
3843 rcu_read_lock(); 3860 rcu_read_lock();
3844 list_for_each_entry_rcu(event, &ctx->event_list, event_entry) { 3861 list_for_each_entry_rcu(event, &ctx->event_list, event_entry) {
3845 if (perf_swevent_match(event, type, event_id, regs)) 3862 if (perf_swevent_match(event, type, event_id, data, regs))
3846 perf_swevent_add(event, nr, nmi, data, regs); 3863 perf_swevent_add(event, nr, nmi, data, regs);
3847 } 3864 }
3848 rcu_read_unlock(); 3865 rcu_read_unlock();
@@ -4086,6 +4103,7 @@ static const struct pmu perf_ops_task_clock = {
4086}; 4103};
4087 4104
4088#ifdef CONFIG_EVENT_PROFILE 4105#ifdef CONFIG_EVENT_PROFILE
4106
4089void perf_tp_event(int event_id, u64 addr, u64 count, void *record, 4107void perf_tp_event(int event_id, u64 addr, u64 count, void *record,
4090 int entry_size) 4108 int entry_size)
4091{ 4109{
@@ -4109,8 +4127,15 @@ void perf_tp_event(int event_id, u64 addr, u64 count, void *record,
4109} 4127}
4110EXPORT_SYMBOL_GPL(perf_tp_event); 4128EXPORT_SYMBOL_GPL(perf_tp_event);
4111 4129
4112extern int ftrace_profile_enable(int); 4130static int perf_tp_event_match(struct perf_event *event,
4113extern void ftrace_profile_disable(int); 4131 struct perf_sample_data *data)
4132{
4133 void *record = data->raw->data;
4134
4135 if (likely(!event->filter) || filter_match_preds(event->filter, record))
4136 return 1;
4137 return 0;
4138}
4114 4139
4115static void tp_perf_event_destroy(struct perf_event *event) 4140static void tp_perf_event_destroy(struct perf_event *event)
4116{ 4141{
@@ -4135,12 +4160,53 @@ static const struct pmu *tp_perf_event_init(struct perf_event *event)
4135 4160
4136 return &perf_ops_generic; 4161 return &perf_ops_generic;
4137} 4162}
4163
4164static int perf_event_set_filter(struct perf_event *event, void __user *arg)
4165{
4166 char *filter_str;
4167 int ret;
4168
4169 if (event->attr.type != PERF_TYPE_TRACEPOINT)
4170 return -EINVAL;
4171
4172 filter_str = strndup_user(arg, PAGE_SIZE);
4173 if (IS_ERR(filter_str))
4174 return PTR_ERR(filter_str);
4175
4176 ret = ftrace_profile_set_filter(event, event->attr.config, filter_str);
4177
4178 kfree(filter_str);
4179 return ret;
4180}
4181
4182static void perf_event_free_filter(struct perf_event *event)
4183{
4184 ftrace_profile_free_filter(event);
4185}
4186
4138#else 4187#else
4188
4189static int perf_tp_event_match(struct perf_event *event,
4190 struct perf_sample_data *data)
4191{
4192 return 1;
4193}
4194
4139static const struct pmu *tp_perf_event_init(struct perf_event *event) 4195static const struct pmu *tp_perf_event_init(struct perf_event *event)
4140{ 4196{
4141 return NULL; 4197 return NULL;
4142} 4198}
4143#endif 4199
4200static int perf_event_set_filter(struct perf_event *event, void __user *arg)
4201{
4202 return -ENOENT;
4203}
4204
4205static void perf_event_free_filter(struct perf_event *event)
4206{
4207}
4208
4209#endif /* CONFIG_EVENT_PROFILE */
4144 4210
4145atomic_t perf_swevent_enabled[PERF_COUNT_SW_MAX]; 4211atomic_t perf_swevent_enabled[PERF_COUNT_SW_MAX];
4146 4212
@@ -4394,7 +4460,7 @@ err_size:
4394 goto out; 4460 goto out;
4395} 4461}
4396 4462
4397int perf_event_set_output(struct perf_event *event, int output_fd) 4463static int perf_event_set_output(struct perf_event *event, int output_fd)
4398{ 4464{
4399 struct perf_event *output_event = NULL; 4465 struct perf_event *output_event = NULL;
4400 struct file *output_file = NULL; 4466 struct file *output_file = NULL;
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 37ba67e3326..b10c0d90a6f 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -60,6 +60,13 @@ static int last_ftrace_enabled;
60/* Quick disabling of function tracer. */ 60/* Quick disabling of function tracer. */
61int function_trace_stop; 61int function_trace_stop;
62 62
63/* List for set_ftrace_pid's pids. */
64LIST_HEAD(ftrace_pids);
65struct ftrace_pid {
66 struct list_head list;
67 struct pid *pid;
68};
69
63/* 70/*
64 * ftrace_disabled is set when an anomaly is discovered. 71 * ftrace_disabled is set when an anomaly is discovered.
65 * ftrace_disabled is much stronger than ftrace_enabled. 72 * ftrace_disabled is much stronger than ftrace_enabled.
@@ -78,6 +85,10 @@ ftrace_func_t ftrace_trace_function __read_mostly = ftrace_stub;
78ftrace_func_t __ftrace_trace_function __read_mostly = ftrace_stub; 85ftrace_func_t __ftrace_trace_function __read_mostly = ftrace_stub;
79ftrace_func_t ftrace_pid_function __read_mostly = ftrace_stub; 86ftrace_func_t ftrace_pid_function __read_mostly = ftrace_stub;
80 87
88#ifdef CONFIG_FUNCTION_GRAPH_TRACER
89static int ftrace_set_func(unsigned long *array, int *idx, char *buffer);
90#endif
91
81static void ftrace_list_func(unsigned long ip, unsigned long parent_ip) 92static void ftrace_list_func(unsigned long ip, unsigned long parent_ip)
82{ 93{
83 struct ftrace_ops *op = ftrace_list; 94 struct ftrace_ops *op = ftrace_list;
@@ -155,7 +166,7 @@ static int __register_ftrace_function(struct ftrace_ops *ops)
155 else 166 else
156 func = ftrace_list_func; 167 func = ftrace_list_func;
157 168
158 if (ftrace_pid_trace) { 169 if (!list_empty(&ftrace_pids)) {
159 set_ftrace_pid_function(func); 170 set_ftrace_pid_function(func);
160 func = ftrace_pid_func; 171 func = ftrace_pid_func;
161 } 172 }
@@ -203,7 +214,7 @@ static int __unregister_ftrace_function(struct ftrace_ops *ops)
203 if (ftrace_list->next == &ftrace_list_end) { 214 if (ftrace_list->next == &ftrace_list_end) {
204 ftrace_func_t func = ftrace_list->func; 215 ftrace_func_t func = ftrace_list->func;
205 216
206 if (ftrace_pid_trace) { 217 if (!list_empty(&ftrace_pids)) {
207 set_ftrace_pid_function(func); 218 set_ftrace_pid_function(func);
208 func = ftrace_pid_func; 219 func = ftrace_pid_func;
209 } 220 }
@@ -231,7 +242,7 @@ static void ftrace_update_pid_func(void)
231 func = __ftrace_trace_function; 242 func = __ftrace_trace_function;
232#endif 243#endif
233 244
234 if (ftrace_pid_trace) { 245 if (!list_empty(&ftrace_pids)) {
235 set_ftrace_pid_function(func); 246 set_ftrace_pid_function(func);
236 func = ftrace_pid_func; 247 func = ftrace_pid_func;
237 } else { 248 } else {
@@ -821,8 +832,6 @@ static __init void ftrace_profile_debugfs(struct dentry *d_tracer)
821} 832}
822#endif /* CONFIG_FUNCTION_PROFILER */ 833#endif /* CONFIG_FUNCTION_PROFILER */
823 834
824/* set when tracing only a pid */
825struct pid *ftrace_pid_trace;
826static struct pid * const ftrace_swapper_pid = &init_struct_pid; 835static struct pid * const ftrace_swapper_pid = &init_struct_pid;
827 836
828#ifdef CONFIG_DYNAMIC_FTRACE 837#ifdef CONFIG_DYNAMIC_FTRACE
@@ -1261,12 +1270,34 @@ static int ftrace_update_code(struct module *mod)
1261 ftrace_new_addrs = p->newlist; 1270 ftrace_new_addrs = p->newlist;
1262 p->flags = 0L; 1271 p->flags = 0L;
1263 1272
1264 /* convert record (i.e, patch mcount-call with NOP) */ 1273 /*
1265 if (ftrace_code_disable(mod, p)) { 1274 * Do the initial record convertion from mcount jump
1266 p->flags |= FTRACE_FL_CONVERTED; 1275 * to the NOP instructions.
1267 ftrace_update_cnt++; 1276 */
1268 } else 1277 if (!ftrace_code_disable(mod, p)) {
1269 ftrace_free_rec(p); 1278 ftrace_free_rec(p);
1279 continue;
1280 }
1281
1282 p->flags |= FTRACE_FL_CONVERTED;
1283 ftrace_update_cnt++;
1284
1285 /*
1286 * If the tracing is enabled, go ahead and enable the record.
1287 *
1288 * The reason not to enable the record immediatelly is the
1289 * inherent check of ftrace_make_nop/ftrace_make_call for
1290 * correct previous instructions. Making first the NOP
1291 * conversion puts the module to the correct state, thus
1292 * passing the ftrace_make_call check.
1293 */
1294 if (ftrace_start_up) {
1295 int failed = __ftrace_replace_code(p, 1);
1296 if (failed) {
1297 ftrace_bug(failed, p->ip);
1298 ftrace_free_rec(p);
1299 }
1300 }
1270 } 1301 }
1271 1302
1272 stop = ftrace_now(raw_smp_processor_id()); 1303 stop = ftrace_now(raw_smp_processor_id());
@@ -1656,60 +1687,6 @@ ftrace_regex_lseek(struct file *file, loff_t offset, int origin)
1656 return ret; 1687 return ret;
1657} 1688}
1658 1689
1659enum {
1660 MATCH_FULL,
1661 MATCH_FRONT_ONLY,
1662 MATCH_MIDDLE_ONLY,
1663 MATCH_END_ONLY,
1664};
1665
1666/*
1667 * (static function - no need for kernel doc)
1668 *
1669 * Pass in a buffer containing a glob and this function will
1670 * set search to point to the search part of the buffer and
1671 * return the type of search it is (see enum above).
1672 * This does modify buff.
1673 *
1674 * Returns enum type.
1675 * search returns the pointer to use for comparison.
1676 * not returns 1 if buff started with a '!'
1677 * 0 otherwise.
1678 */
1679static int
1680ftrace_setup_glob(char *buff, int len, char **search, int *not)
1681{
1682 int type = MATCH_FULL;
1683 int i;
1684
1685 if (buff[0] == '!') {
1686 *not = 1;
1687 buff++;
1688 len--;
1689 } else
1690 *not = 0;
1691
1692 *search = buff;
1693
1694 for (i = 0; i < len; i++) {
1695 if (buff[i] == '*') {
1696 if (!i) {
1697 *search = buff + 1;
1698 type = MATCH_END_ONLY;
1699 } else {
1700 if (type == MATCH_END_ONLY)
1701 type = MATCH_MIDDLE_ONLY;
1702 else
1703 type = MATCH_FRONT_ONLY;
1704 buff[i] = 0;
1705 break;
1706 }
1707 }
1708 }
1709
1710 return type;
1711}
1712
1713static int ftrace_match(char *str, char *regex, int len, int type) 1690static int ftrace_match(char *str, char *regex, int len, int type)
1714{ 1691{
1715 int matched = 0; 1692 int matched = 0;
@@ -1758,7 +1735,7 @@ static void ftrace_match_records(char *buff, int len, int enable)
1758 int not; 1735 int not;
1759 1736
1760 flag = enable ? FTRACE_FL_FILTER : FTRACE_FL_NOTRACE; 1737 flag = enable ? FTRACE_FL_FILTER : FTRACE_FL_NOTRACE;
1761 type = ftrace_setup_glob(buff, len, &search, &not); 1738 type = filter_parse_regex(buff, len, &search, &not);
1762 1739
1763 search_len = strlen(search); 1740 search_len = strlen(search);
1764 1741
@@ -1826,7 +1803,7 @@ static void ftrace_match_module_records(char *buff, char *mod, int enable)
1826 } 1803 }
1827 1804
1828 if (strlen(buff)) { 1805 if (strlen(buff)) {
1829 type = ftrace_setup_glob(buff, strlen(buff), &search, &not); 1806 type = filter_parse_regex(buff, strlen(buff), &search, &not);
1830 search_len = strlen(search); 1807 search_len = strlen(search);
1831 } 1808 }
1832 1809
@@ -1991,7 +1968,7 @@ register_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
1991 int count = 0; 1968 int count = 0;
1992 char *search; 1969 char *search;
1993 1970
1994 type = ftrace_setup_glob(glob, strlen(glob), &search, &not); 1971 type = filter_parse_regex(glob, strlen(glob), &search, &not);
1995 len = strlen(search); 1972 len = strlen(search);
1996 1973
1997 /* we do not support '!' for function probes */ 1974 /* we do not support '!' for function probes */
@@ -2068,7 +2045,7 @@ __unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
2068 else if (glob) { 2045 else if (glob) {
2069 int not; 2046 int not;
2070 2047
2071 type = ftrace_setup_glob(glob, strlen(glob), &search, &not); 2048 type = filter_parse_regex(glob, strlen(glob), &search, &not);
2072 len = strlen(search); 2049 len = strlen(search);
2073 2050
2074 /* we do not support '!' for function probes */ 2051 /* we do not support '!' for function probes */
@@ -2297,6 +2274,7 @@ void ftrace_set_notrace(unsigned char *buf, int len, int reset)
2297#define FTRACE_FILTER_SIZE COMMAND_LINE_SIZE 2274#define FTRACE_FILTER_SIZE COMMAND_LINE_SIZE
2298static char ftrace_notrace_buf[FTRACE_FILTER_SIZE] __initdata; 2275static char ftrace_notrace_buf[FTRACE_FILTER_SIZE] __initdata;
2299static char ftrace_filter_buf[FTRACE_FILTER_SIZE] __initdata; 2276static char ftrace_filter_buf[FTRACE_FILTER_SIZE] __initdata;
2277static char ftrace_graph_buf[FTRACE_FILTER_SIZE] __initdata;
2300 2278
2301static int __init set_ftrace_notrace(char *str) 2279static int __init set_ftrace_notrace(char *str)
2302{ 2280{
@@ -2312,6 +2290,31 @@ static int __init set_ftrace_filter(char *str)
2312} 2290}
2313__setup("ftrace_filter=", set_ftrace_filter); 2291__setup("ftrace_filter=", set_ftrace_filter);
2314 2292
2293#ifdef CONFIG_FUNCTION_GRAPH_TRACER
2294static int __init set_graph_function(char *str)
2295{
2296 strlcpy(ftrace_graph_buf, str, FTRACE_FILTER_SIZE);
2297 return 1;
2298}
2299__setup("ftrace_graph_filter=", set_graph_function);
2300
2301static void __init set_ftrace_early_graph(char *buf)
2302{
2303 int ret;
2304 char *func;
2305
2306 while (buf) {
2307 func = strsep(&buf, ",");
2308 /* we allow only one expression at a time */
2309 ret = ftrace_set_func(ftrace_graph_funcs, &ftrace_graph_count,
2310 func);
2311 if (ret)
2312 printk(KERN_DEBUG "ftrace: function %s not "
2313 "traceable\n", func);
2314 }
2315}
2316#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
2317
2315static void __init set_ftrace_early_filter(char *buf, int enable) 2318static void __init set_ftrace_early_filter(char *buf, int enable)
2316{ 2319{
2317 char *func; 2320 char *func;
@@ -2328,6 +2331,10 @@ static void __init set_ftrace_early_filters(void)
2328 set_ftrace_early_filter(ftrace_filter_buf, 1); 2331 set_ftrace_early_filter(ftrace_filter_buf, 1);
2329 if (ftrace_notrace_buf[0]) 2332 if (ftrace_notrace_buf[0])
2330 set_ftrace_early_filter(ftrace_notrace_buf, 0); 2333 set_ftrace_early_filter(ftrace_notrace_buf, 0);
2334#ifdef CONFIG_FUNCTION_GRAPH_TRACER
2335 if (ftrace_graph_buf[0])
2336 set_ftrace_early_graph(ftrace_graph_buf);
2337#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
2331} 2338}
2332 2339
2333static int 2340static int
@@ -2513,7 +2520,7 @@ ftrace_set_func(unsigned long *array, int *idx, char *buffer)
2513 return -ENODEV; 2520 return -ENODEV;
2514 2521
2515 /* decode regex */ 2522 /* decode regex */
2516 type = ftrace_setup_glob(buffer, strlen(buffer), &search, &not); 2523 type = filter_parse_regex(buffer, strlen(buffer), &search, &not);
2517 if (not) 2524 if (not)
2518 return -EINVAL; 2525 return -EINVAL;
2519 2526
@@ -2624,7 +2631,7 @@ static __init int ftrace_init_dyn_debugfs(struct dentry *d_tracer)
2624 return 0; 2631 return 0;
2625} 2632}
2626 2633
2627static int ftrace_convert_nops(struct module *mod, 2634static int ftrace_process_locs(struct module *mod,
2628 unsigned long *start, 2635 unsigned long *start,
2629 unsigned long *end) 2636 unsigned long *end)
2630{ 2637{
@@ -2684,7 +2691,7 @@ static void ftrace_init_module(struct module *mod,
2684{ 2691{
2685 if (ftrace_disabled || start == end) 2692 if (ftrace_disabled || start == end)
2686 return; 2693 return;
2687 ftrace_convert_nops(mod, start, end); 2694 ftrace_process_locs(mod, start, end);
2688} 2695}
2689 2696
2690static int ftrace_module_notify(struct notifier_block *self, 2697static int ftrace_module_notify(struct notifier_block *self,
@@ -2745,7 +2752,7 @@ void __init ftrace_init(void)
2745 2752
2746 last_ftrace_enabled = ftrace_enabled = 1; 2753 last_ftrace_enabled = ftrace_enabled = 1;
2747 2754
2748 ret = ftrace_convert_nops(NULL, 2755 ret = ftrace_process_locs(NULL,
2749 __start_mcount_loc, 2756 __start_mcount_loc,
2750 __stop_mcount_loc); 2757 __stop_mcount_loc);
2751 2758
@@ -2778,23 +2785,6 @@ static inline void ftrace_startup_enable(int command) { }
2778# define ftrace_shutdown_sysctl() do { } while (0) 2785# define ftrace_shutdown_sysctl() do { } while (0)
2779#endif /* CONFIG_DYNAMIC_FTRACE */ 2786#endif /* CONFIG_DYNAMIC_FTRACE */
2780 2787
2781static ssize_t
2782ftrace_pid_read(struct file *file, char __user *ubuf,
2783 size_t cnt, loff_t *ppos)
2784{
2785 char buf[64];
2786 int r;
2787
2788 if (ftrace_pid_trace == ftrace_swapper_pid)
2789 r = sprintf(buf, "swapper tasks\n");
2790 else if (ftrace_pid_trace)
2791 r = sprintf(buf, "%u\n", pid_vnr(ftrace_pid_trace));
2792 else
2793 r = sprintf(buf, "no pid\n");
2794
2795 return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
2796}
2797
2798static void clear_ftrace_swapper(void) 2788static void clear_ftrace_swapper(void)
2799{ 2789{
2800 struct task_struct *p; 2790 struct task_struct *p;
@@ -2845,14 +2835,12 @@ static void set_ftrace_pid(struct pid *pid)
2845 rcu_read_unlock(); 2835 rcu_read_unlock();
2846} 2836}
2847 2837
2848static void clear_ftrace_pid_task(struct pid **pid) 2838static void clear_ftrace_pid_task(struct pid *pid)
2849{ 2839{
2850 if (*pid == ftrace_swapper_pid) 2840 if (pid == ftrace_swapper_pid)
2851 clear_ftrace_swapper(); 2841 clear_ftrace_swapper();
2852 else 2842 else
2853 clear_ftrace_pid(*pid); 2843 clear_ftrace_pid(pid);
2854
2855 *pid = NULL;
2856} 2844}
2857 2845
2858static void set_ftrace_pid_task(struct pid *pid) 2846static void set_ftrace_pid_task(struct pid *pid)
@@ -2863,11 +2851,140 @@ static void set_ftrace_pid_task(struct pid *pid)
2863 set_ftrace_pid(pid); 2851 set_ftrace_pid(pid);
2864} 2852}
2865 2853
2854static int ftrace_pid_add(int p)
2855{
2856 struct pid *pid;
2857 struct ftrace_pid *fpid;
2858 int ret = -EINVAL;
2859
2860 mutex_lock(&ftrace_lock);
2861
2862 if (!p)
2863 pid = ftrace_swapper_pid;
2864 else
2865 pid = find_get_pid(p);
2866
2867 if (!pid)
2868 goto out;
2869
2870 ret = 0;
2871
2872 list_for_each_entry(fpid, &ftrace_pids, list)
2873 if (fpid->pid == pid)
2874 goto out_put;
2875
2876 ret = -ENOMEM;
2877
2878 fpid = kmalloc(sizeof(*fpid), GFP_KERNEL);
2879 if (!fpid)
2880 goto out_put;
2881
2882 list_add(&fpid->list, &ftrace_pids);
2883 fpid->pid = pid;
2884
2885 set_ftrace_pid_task(pid);
2886
2887 ftrace_update_pid_func();
2888 ftrace_startup_enable(0);
2889
2890 mutex_unlock(&ftrace_lock);
2891 return 0;
2892
2893out_put:
2894 if (pid != ftrace_swapper_pid)
2895 put_pid(pid);
2896
2897out:
2898 mutex_unlock(&ftrace_lock);
2899 return ret;
2900}
2901
2902static void ftrace_pid_reset(void)
2903{
2904 struct ftrace_pid *fpid, *safe;
2905
2906 mutex_lock(&ftrace_lock);
2907 list_for_each_entry_safe(fpid, safe, &ftrace_pids, list) {
2908 struct pid *pid = fpid->pid;
2909
2910 clear_ftrace_pid_task(pid);
2911
2912 list_del(&fpid->list);
2913 kfree(fpid);
2914 }
2915
2916 ftrace_update_pid_func();
2917 ftrace_startup_enable(0);
2918
2919 mutex_unlock(&ftrace_lock);
2920}
2921
2922static void *fpid_start(struct seq_file *m, loff_t *pos)
2923{
2924 mutex_lock(&ftrace_lock);
2925
2926 if (list_empty(&ftrace_pids) && (!*pos))
2927 return (void *) 1;
2928
2929 return seq_list_start(&ftrace_pids, *pos);
2930}
2931
2932static void *fpid_next(struct seq_file *m, void *v, loff_t *pos)
2933{
2934 if (v == (void *)1)
2935 return NULL;
2936
2937 return seq_list_next(v, &ftrace_pids, pos);
2938}
2939
2940static void fpid_stop(struct seq_file *m, void *p)
2941{
2942 mutex_unlock(&ftrace_lock);
2943}
2944
2945static int fpid_show(struct seq_file *m, void *v)
2946{
2947 const struct ftrace_pid *fpid = list_entry(v, struct ftrace_pid, list);
2948
2949 if (v == (void *)1) {
2950 seq_printf(m, "no pid\n");
2951 return 0;
2952 }
2953
2954 if (fpid->pid == ftrace_swapper_pid)
2955 seq_printf(m, "swapper tasks\n");
2956 else
2957 seq_printf(m, "%u\n", pid_vnr(fpid->pid));
2958
2959 return 0;
2960}
2961
2962static const struct seq_operations ftrace_pid_sops = {
2963 .start = fpid_start,
2964 .next = fpid_next,
2965 .stop = fpid_stop,
2966 .show = fpid_show,
2967};
2968
2969static int
2970ftrace_pid_open(struct inode *inode, struct file *file)
2971{
2972 int ret = 0;
2973
2974 if ((file->f_mode & FMODE_WRITE) &&
2975 (file->f_flags & O_TRUNC))
2976 ftrace_pid_reset();
2977
2978 if (file->f_mode & FMODE_READ)
2979 ret = seq_open(file, &ftrace_pid_sops);
2980
2981 return ret;
2982}
2983
2866static ssize_t 2984static ssize_t
2867ftrace_pid_write(struct file *filp, const char __user *ubuf, 2985ftrace_pid_write(struct file *filp, const char __user *ubuf,
2868 size_t cnt, loff_t *ppos) 2986 size_t cnt, loff_t *ppos)
2869{ 2987{
2870 struct pid *pid;
2871 char buf[64]; 2988 char buf[64];
2872 long val; 2989 long val;
2873 int ret; 2990 int ret;
@@ -2880,57 +2997,38 @@ ftrace_pid_write(struct file *filp, const char __user *ubuf,
2880 2997
2881 buf[cnt] = 0; 2998 buf[cnt] = 0;
2882 2999
3000 /*
3001 * Allow "echo > set_ftrace_pid" or "echo -n '' > set_ftrace_pid"
3002 * to clean the filter quietly.
3003 */
3004 strstrip(buf);
3005 if (strlen(buf) == 0)
3006 return 1;
3007
2883 ret = strict_strtol(buf, 10, &val); 3008 ret = strict_strtol(buf, 10, &val);
2884 if (ret < 0) 3009 if (ret < 0)
2885 return ret; 3010 return ret;
2886 3011
2887 mutex_lock(&ftrace_lock); 3012 ret = ftrace_pid_add(val);
2888 if (val < 0) {
2889 /* disable pid tracing */
2890 if (!ftrace_pid_trace)
2891 goto out;
2892
2893 clear_ftrace_pid_task(&ftrace_pid_trace);
2894
2895 } else {
2896 /* swapper task is special */
2897 if (!val) {
2898 pid = ftrace_swapper_pid;
2899 if (pid == ftrace_pid_trace)
2900 goto out;
2901 } else {
2902 pid = find_get_pid(val);
2903 3013
2904 if (pid == ftrace_pid_trace) { 3014 return ret ? ret : cnt;
2905 put_pid(pid); 3015}
2906 goto out;
2907 }
2908 }
2909
2910 if (ftrace_pid_trace)
2911 clear_ftrace_pid_task(&ftrace_pid_trace);
2912
2913 if (!pid)
2914 goto out;
2915
2916 ftrace_pid_trace = pid;
2917
2918 set_ftrace_pid_task(ftrace_pid_trace);
2919 }
2920
2921 /* update the function call */
2922 ftrace_update_pid_func();
2923 ftrace_startup_enable(0);
2924 3016
2925 out: 3017static int
2926 mutex_unlock(&ftrace_lock); 3018ftrace_pid_release(struct inode *inode, struct file *file)
3019{
3020 if (file->f_mode & FMODE_READ)
3021 seq_release(inode, file);
2927 3022
2928 return cnt; 3023 return 0;
2929} 3024}
2930 3025
2931static const struct file_operations ftrace_pid_fops = { 3026static const struct file_operations ftrace_pid_fops = {
2932 .read = ftrace_pid_read, 3027 .open = ftrace_pid_open,
2933 .write = ftrace_pid_write, 3028 .write = ftrace_pid_write,
3029 .read = seq_read,
3030 .llseek = seq_lseek,
3031 .release = ftrace_pid_release,
2934}; 3032};
2935 3033
2936static __init int ftrace_init_debugfs(void) 3034static __init int ftrace_init_debugfs(void)
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index d4ff0197054..e43c928356e 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -397,18 +397,21 @@ int ring_buffer_print_page_header(struct trace_seq *s)
397 int ret; 397 int ret;
398 398
399 ret = trace_seq_printf(s, "\tfield: u64 timestamp;\t" 399 ret = trace_seq_printf(s, "\tfield: u64 timestamp;\t"
400 "offset:0;\tsize:%u;\n", 400 "offset:0;\tsize:%u;\tsigned:%u;\n",
401 (unsigned int)sizeof(field.time_stamp)); 401 (unsigned int)sizeof(field.time_stamp),
402 (unsigned int)is_signed_type(u64));
402 403
403 ret = trace_seq_printf(s, "\tfield: local_t commit;\t" 404 ret = trace_seq_printf(s, "\tfield: local_t commit;\t"
404 "offset:%u;\tsize:%u;\n", 405 "offset:%u;\tsize:%u;\tsigned:%u;\n",
405 (unsigned int)offsetof(typeof(field), commit), 406 (unsigned int)offsetof(typeof(field), commit),
406 (unsigned int)sizeof(field.commit)); 407 (unsigned int)sizeof(field.commit),
408 (unsigned int)is_signed_type(long));
407 409
408 ret = trace_seq_printf(s, "\tfield: char data;\t" 410 ret = trace_seq_printf(s, "\tfield: char data;\t"
409 "offset:%u;\tsize:%u;\n", 411 "offset:%u;\tsize:%u;\tsigned:%u;\n",
410 (unsigned int)offsetof(typeof(field), data), 412 (unsigned int)offsetof(typeof(field), data),
411 (unsigned int)BUF_PAGE_SIZE); 413 (unsigned int)BUF_PAGE_SIZE,
414 (unsigned int)is_signed_type(char));
412 415
413 return ret; 416 return ret;
414} 417}
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index c820b0310a1..026e715a0c7 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -129,7 +129,7 @@ static int tracing_set_tracer(const char *buf);
129static char bootup_tracer_buf[MAX_TRACER_SIZE] __initdata; 129static char bootup_tracer_buf[MAX_TRACER_SIZE] __initdata;
130static char *default_bootup_tracer; 130static char *default_bootup_tracer;
131 131
132static int __init set_ftrace(char *str) 132static int __init set_cmdline_ftrace(char *str)
133{ 133{
134 strncpy(bootup_tracer_buf, str, MAX_TRACER_SIZE); 134 strncpy(bootup_tracer_buf, str, MAX_TRACER_SIZE);
135 default_bootup_tracer = bootup_tracer_buf; 135 default_bootup_tracer = bootup_tracer_buf;
@@ -137,7 +137,7 @@ static int __init set_ftrace(char *str)
137 ring_buffer_expanded = 1; 137 ring_buffer_expanded = 1;
138 return 1; 138 return 1;
139} 139}
140__setup("ftrace=", set_ftrace); 140__setup("ftrace=", set_cmdline_ftrace);
141 141
142static int __init set_ftrace_dump_on_oops(char *str) 142static int __init set_ftrace_dump_on_oops(char *str)
143{ 143{
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 104c1a72418..b4e4212e66d 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -506,10 +506,6 @@ static inline int ftrace_graph_addr(unsigned long addr)
506 return 0; 506 return 0;
507} 507}
508#else 508#else
509static inline int ftrace_trace_addr(unsigned long addr)
510{
511 return 1;
512}
513static inline int ftrace_graph_addr(unsigned long addr) 509static inline int ftrace_graph_addr(unsigned long addr)
514{ 510{
515 return 1; 511 return 1;
@@ -523,12 +519,12 @@ print_graph_function(struct trace_iterator *iter)
523} 519}
524#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ 520#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
525 521
526extern struct pid *ftrace_pid_trace; 522extern struct list_head ftrace_pids;
527 523
528#ifdef CONFIG_FUNCTION_TRACER 524#ifdef CONFIG_FUNCTION_TRACER
529static inline int ftrace_trace_task(struct task_struct *task) 525static inline int ftrace_trace_task(struct task_struct *task)
530{ 526{
531 if (!ftrace_pid_trace) 527 if (list_empty(&ftrace_pids))
532 return 1; 528 return 1;
533 529
534 return test_tsk_trace_trace(task); 530 return test_tsk_trace_trace(task);
@@ -710,7 +706,6 @@ struct event_filter {
710 int n_preds; 706 int n_preds;
711 struct filter_pred **preds; 707 struct filter_pred **preds;
712 char *filter_string; 708 char *filter_string;
713 bool no_reset;
714}; 709};
715 710
716struct event_subsystem { 711struct event_subsystem {
@@ -722,22 +717,40 @@ struct event_subsystem {
722}; 717};
723 718
724struct filter_pred; 719struct filter_pred;
720struct regex;
725 721
726typedef int (*filter_pred_fn_t) (struct filter_pred *pred, void *event, 722typedef int (*filter_pred_fn_t) (struct filter_pred *pred, void *event,
727 int val1, int val2); 723 int val1, int val2);
728 724
725typedef int (*regex_match_func)(char *str, struct regex *r, int len);
726
727enum regex_type {
728 MATCH_FULL = 0,
729 MATCH_FRONT_ONLY,
730 MATCH_MIDDLE_ONLY,
731 MATCH_END_ONLY,
732};
733
734struct regex {
735 char pattern[MAX_FILTER_STR_VAL];
736 int len;
737 int field_len;
738 regex_match_func match;
739};
740
729struct filter_pred { 741struct filter_pred {
730 filter_pred_fn_t fn; 742 filter_pred_fn_t fn;
731 u64 val; 743 u64 val;
732 char str_val[MAX_FILTER_STR_VAL]; 744 struct regex regex;
733 int str_len; 745 char *field_name;
734 char *field_name; 746 int offset;
735 int offset; 747 int not;
736 int not; 748 int op;
737 int op; 749 int pop_n;
738 int pop_n;
739}; 750};
740 751
752extern enum regex_type
753filter_parse_regex(char *buff, int len, char **search, int *not);
741extern void print_event_filter(struct ftrace_event_call *call, 754extern void print_event_filter(struct ftrace_event_call *call,
742 struct trace_seq *s); 755 struct trace_seq *s);
743extern int apply_event_filter(struct ftrace_event_call *call, 756extern int apply_event_filter(struct ftrace_event_call *call,
@@ -753,7 +766,8 @@ filter_check_discard(struct ftrace_event_call *call, void *rec,
753 struct ring_buffer *buffer, 766 struct ring_buffer *buffer,
754 struct ring_buffer_event *event) 767 struct ring_buffer_event *event)
755{ 768{
756 if (unlikely(call->filter_active) && !filter_match_preds(call, rec)) { 769 if (unlikely(call->filter_active) &&
770 !filter_match_preds(call->filter, rec)) {
757 ring_buffer_discard_commit(buffer, event); 771 ring_buffer_discard_commit(buffer, event);
758 return 1; 772 return 1;
759 } 773 }
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index f2f5064701e..1d18315dc83 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -503,7 +503,7 @@ extern char *__bad_type_size(void);
503#define FIELD(type, name) \ 503#define FIELD(type, name) \
504 sizeof(type) != sizeof(field.name) ? __bad_type_size() : \ 504 sizeof(type) != sizeof(field.name) ? __bad_type_size() : \
505 #type, "common_" #name, offsetof(typeof(field), name), \ 505 #type, "common_" #name, offsetof(typeof(field), name), \
506 sizeof(field.name) 506 sizeof(field.name), is_signed_type(type)
507 507
508static int trace_write_header(struct trace_seq *s) 508static int trace_write_header(struct trace_seq *s)
509{ 509{
@@ -511,17 +511,17 @@ static int trace_write_header(struct trace_seq *s)
511 511
512 /* struct trace_entry */ 512 /* struct trace_entry */
513 return trace_seq_printf(s, 513 return trace_seq_printf(s,
514 "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\n" 514 "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\tsigned:%u;\n"
515 "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\n" 515 "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\tsigned:%u;\n"
516 "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\n" 516 "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\tsigned:%u;\n"
517 "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\n" 517 "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\tsigned:%u;\n"
518 "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\n" 518 "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\tsigned:%u;\n"
519 "\n", 519 "\n",
520 FIELD(unsigned short, type), 520 FIELD(unsigned short, type),
521 FIELD(unsigned char, flags), 521 FIELD(unsigned char, flags),
522 FIELD(unsigned char, preempt_count), 522 FIELD(unsigned char, preempt_count),
523 FIELD(int, pid), 523 FIELD(int, pid),
524 FIELD(int, lock_depth)); 524 FIELD(int, lock_depth));
525} 525}
526 526
527static ssize_t 527static ssize_t
@@ -874,9 +874,9 @@ event_subsystem_dir(const char *name, struct dentry *d_events)
874 "'%s/filter' entry\n", name); 874 "'%s/filter' entry\n", name);
875 } 875 }
876 876
877 entry = trace_create_file("enable", 0644, system->entry, 877 trace_create_file("enable", 0644, system->entry,
878 (void *)system->name, 878 (void *)system->name,
879 &ftrace_system_enable_fops); 879 &ftrace_system_enable_fops);
880 880
881 return system->entry; 881 return system->entry;
882} 882}
@@ -888,7 +888,6 @@ event_create_dir(struct ftrace_event_call *call, struct dentry *d_events,
888 const struct file_operations *filter, 888 const struct file_operations *filter,
889 const struct file_operations *format) 889 const struct file_operations *format)
890{ 890{
891 struct dentry *entry;
892 int ret; 891 int ret;
893 892
894 /* 893 /*
@@ -906,12 +905,12 @@ event_create_dir(struct ftrace_event_call *call, struct dentry *d_events,
906 } 905 }
907 906
908 if (call->regfunc) 907 if (call->regfunc)
909 entry = trace_create_file("enable", 0644, call->dir, call, 908 trace_create_file("enable", 0644, call->dir, call,
910 enable); 909 enable);
911 910
912 if (call->id && call->profile_enable) 911 if (call->id && call->profile_enable)
913 entry = trace_create_file("id", 0444, call->dir, call, 912 trace_create_file("id", 0444, call->dir, call,
914 id); 913 id);
915 914
916 if (call->define_fields) { 915 if (call->define_fields) {
917 ret = call->define_fields(call); 916 ret = call->define_fields(call);
@@ -920,16 +919,16 @@ event_create_dir(struct ftrace_event_call *call, struct dentry *d_events,
920 " events/%s\n", call->name); 919 " events/%s\n", call->name);
921 return ret; 920 return ret;
922 } 921 }
923 entry = trace_create_file("filter", 0644, call->dir, call, 922 trace_create_file("filter", 0644, call->dir, call,
924 filter); 923 filter);
925 } 924 }
926 925
927 /* A trace may not want to export its format */ 926 /* A trace may not want to export its format */
928 if (!call->show_format) 927 if (!call->show_format)
929 return 0; 928 return 0;
930 929
931 entry = trace_create_file("format", 0444, call->dir, call, 930 trace_create_file("format", 0444, call->dir, call,
932 format); 931 format);
933 932
934 return 0; 933 return 0;
935} 934}
diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c
index 98a6cc5c64e..21d34757b95 100644
--- a/kernel/trace/trace_events_filter.c
+++ b/kernel/trace/trace_events_filter.c
@@ -18,11 +18,10 @@
18 * Copyright (C) 2009 Tom Zanussi <tzanussi@gmail.com> 18 * Copyright (C) 2009 Tom Zanussi <tzanussi@gmail.com>
19 */ 19 */
20 20
21#include <linux/debugfs.h>
22#include <linux/uaccess.h>
23#include <linux/module.h> 21#include <linux/module.h>
24#include <linux/ctype.h> 22#include <linux/ctype.h>
25#include <linux/mutex.h> 23#include <linux/mutex.h>
24#include <linux/perf_event.h>
26 25
27#include "trace.h" 26#include "trace.h"
28#include "trace_output.h" 27#include "trace_output.h"
@@ -31,6 +30,7 @@ enum filter_op_ids
31{ 30{
32 OP_OR, 31 OP_OR,
33 OP_AND, 32 OP_AND,
33 OP_GLOB,
34 OP_NE, 34 OP_NE,
35 OP_EQ, 35 OP_EQ,
36 OP_LT, 36 OP_LT,
@@ -48,16 +48,17 @@ struct filter_op {
48}; 48};
49 49
50static struct filter_op filter_ops[] = { 50static struct filter_op filter_ops[] = {
51 { OP_OR, "||", 1 }, 51 { OP_OR, "||", 1 },
52 { OP_AND, "&&", 2 }, 52 { OP_AND, "&&", 2 },
53 { OP_NE, "!=", 4 }, 53 { OP_GLOB, "~", 4 },
54 { OP_EQ, "==", 4 }, 54 { OP_NE, "!=", 4 },
55 { OP_LT, "<", 5 }, 55 { OP_EQ, "==", 4 },
56 { OP_LE, "<=", 5 }, 56 { OP_LT, "<", 5 },
57 { OP_GT, ">", 5 }, 57 { OP_LE, "<=", 5 },
58 { OP_GE, ">=", 5 }, 58 { OP_GT, ">", 5 },
59 { OP_NONE, "OP_NONE", 0 }, 59 { OP_GE, ">=", 5 },
60 { OP_OPEN_PAREN, "(", 0 }, 60 { OP_NONE, "OP_NONE", 0 },
61 { OP_OPEN_PAREN, "(", 0 },
61}; 62};
62 63
63enum { 64enum {
@@ -197,9 +198,9 @@ static int filter_pred_string(struct filter_pred *pred, void *event,
197 char *addr = (char *)(event + pred->offset); 198 char *addr = (char *)(event + pred->offset);
198 int cmp, match; 199 int cmp, match;
199 200
200 cmp = strncmp(addr, pred->str_val, pred->str_len); 201 cmp = pred->regex.match(addr, &pred->regex, pred->regex.field_len);
201 202
202 match = (!cmp) ^ pred->not; 203 match = cmp ^ pred->not;
203 204
204 return match; 205 return match;
205} 206}
@@ -211,9 +212,9 @@ static int filter_pred_pchar(struct filter_pred *pred, void *event,
211 char **addr = (char **)(event + pred->offset); 212 char **addr = (char **)(event + pred->offset);
212 int cmp, match; 213 int cmp, match;
213 214
214 cmp = strncmp(*addr, pred->str_val, pred->str_len); 215 cmp = pred->regex.match(*addr, &pred->regex, pred->regex.field_len);
215 216
216 match = (!cmp) ^ pred->not; 217 match = cmp ^ pred->not;
217 218
218 return match; 219 return match;
219} 220}
@@ -237,9 +238,9 @@ static int filter_pred_strloc(struct filter_pred *pred, void *event,
237 char *addr = (char *)(event + str_loc); 238 char *addr = (char *)(event + str_loc);
238 int cmp, match; 239 int cmp, match;
239 240
240 cmp = strncmp(addr, pred->str_val, str_len); 241 cmp = pred->regex.match(addr, &pred->regex, str_len);
241 242
242 match = (!cmp) ^ pred->not; 243 match = cmp ^ pred->not;
243 244
244 return match; 245 return match;
245} 246}
@@ -250,10 +251,121 @@ static int filter_pred_none(struct filter_pred *pred, void *event,
250 return 0; 251 return 0;
251} 252}
252 253
254/* Basic regex callbacks */
255static int regex_match_full(char *str, struct regex *r, int len)
256{
257 if (strncmp(str, r->pattern, len) == 0)
258 return 1;
259 return 0;
260}
261
262static int regex_match_front(char *str, struct regex *r, int len)
263{
264 if (strncmp(str, r->pattern, len) == 0)
265 return 1;
266 return 0;
267}
268
269static int regex_match_middle(char *str, struct regex *r, int len)
270{
271 if (strstr(str, r->pattern))
272 return 1;
273 return 0;
274}
275
276static int regex_match_end(char *str, struct regex *r, int len)
277{
278 char *ptr = strstr(str, r->pattern);
279
280 if (ptr && (ptr[r->len] == 0))
281 return 1;
282 return 0;
283}
284
285/**
286 * filter_parse_regex - parse a basic regex
287 * @buff: the raw regex
288 * @len: length of the regex
289 * @search: will point to the beginning of the string to compare
290 * @not: tell whether the match will have to be inverted
291 *
292 * This passes in a buffer containing a regex and this function will
293 * set search to point to the search part of the buffer and
294 * return the type of search it is (see enum above).
295 * This does modify buff.
296 *
297 * Returns enum type.
298 * search returns the pointer to use for comparison.
299 * not returns 1 if buff started with a '!'
300 * 0 otherwise.
301 */
302enum regex_type filter_parse_regex(char *buff, int len, char **search, int *not)
303{
304 int type = MATCH_FULL;
305 int i;
306
307 if (buff[0] == '!') {
308 *not = 1;
309 buff++;
310 len--;
311 } else
312 *not = 0;
313
314 *search = buff;
315
316 for (i = 0; i < len; i++) {
317 if (buff[i] == '*') {
318 if (!i) {
319 *search = buff + 1;
320 type = MATCH_END_ONLY;
321 } else {
322 if (type == MATCH_END_ONLY)
323 type = MATCH_MIDDLE_ONLY;
324 else
325 type = MATCH_FRONT_ONLY;
326 buff[i] = 0;
327 break;
328 }
329 }
330 }
331
332 return type;
333}
334
335static void filter_build_regex(struct filter_pred *pred)
336{
337 struct regex *r = &pred->regex;
338 char *search;
339 enum regex_type type = MATCH_FULL;
340 int not = 0;
341
342 if (pred->op == OP_GLOB) {
343 type = filter_parse_regex(r->pattern, r->len, &search, &not);
344 r->len = strlen(search);
345 memmove(r->pattern, search, r->len+1);
346 }
347
348 switch (type) {
349 case MATCH_FULL:
350 r->match = regex_match_full;
351 break;
352 case MATCH_FRONT_ONLY:
353 r->match = regex_match_front;
354 break;
355 case MATCH_MIDDLE_ONLY:
356 r->match = regex_match_middle;
357 break;
358 case MATCH_END_ONLY:
359 r->match = regex_match_end;
360 break;
361 }
362
363 pred->not ^= not;
364}
365
253/* return 1 if event matches, 0 otherwise (discard) */ 366/* return 1 if event matches, 0 otherwise (discard) */
254int filter_match_preds(struct ftrace_event_call *call, void *rec) 367int filter_match_preds(struct event_filter *filter, void *rec)
255{ 368{
256 struct event_filter *filter = call->filter;
257 int match, top = 0, val1 = 0, val2 = 0; 369 int match, top = 0, val1 = 0, val2 = 0;
258 int stack[MAX_FILTER_PRED]; 370 int stack[MAX_FILTER_PRED];
259 struct filter_pred *pred; 371 struct filter_pred *pred;
@@ -396,7 +508,7 @@ static void filter_clear_pred(struct filter_pred *pred)
396{ 508{
397 kfree(pred->field_name); 509 kfree(pred->field_name);
398 pred->field_name = NULL; 510 pred->field_name = NULL;
399 pred->str_len = 0; 511 pred->regex.len = 0;
400} 512}
401 513
402static int filter_set_pred(struct filter_pred *dest, 514static int filter_set_pred(struct filter_pred *dest,
@@ -426,9 +538,8 @@ static void filter_disable_preds(struct ftrace_event_call *call)
426 filter->preds[i]->fn = filter_pred_none; 538 filter->preds[i]->fn = filter_pred_none;
427} 539}
428 540
429void destroy_preds(struct ftrace_event_call *call) 541static void __free_preds(struct event_filter *filter)
430{ 542{
431 struct event_filter *filter = call->filter;
432 int i; 543 int i;
433 544
434 if (!filter) 545 if (!filter)
@@ -441,21 +552,24 @@ void destroy_preds(struct ftrace_event_call *call)
441 kfree(filter->preds); 552 kfree(filter->preds);
442 kfree(filter->filter_string); 553 kfree(filter->filter_string);
443 kfree(filter); 554 kfree(filter);
555}
556
557void destroy_preds(struct ftrace_event_call *call)
558{
559 __free_preds(call->filter);
444 call->filter = NULL; 560 call->filter = NULL;
561 call->filter_active = 0;
445} 562}
446 563
447static int init_preds(struct ftrace_event_call *call) 564static struct event_filter *__alloc_preds(void)
448{ 565{
449 struct event_filter *filter; 566 struct event_filter *filter;
450 struct filter_pred *pred; 567 struct filter_pred *pred;
451 int i; 568 int i;
452 569
453 if (call->filter) 570 filter = kzalloc(sizeof(*filter), GFP_KERNEL);
454 return 0; 571 if (!filter)
455 572 return ERR_PTR(-ENOMEM);
456 filter = call->filter = kzalloc(sizeof(*filter), GFP_KERNEL);
457 if (!call->filter)
458 return -ENOMEM;
459 573
460 filter->n_preds = 0; 574 filter->n_preds = 0;
461 575
@@ -471,12 +585,24 @@ static int init_preds(struct ftrace_event_call *call)
471 filter->preds[i] = pred; 585 filter->preds[i] = pred;
472 } 586 }
473 587
474 return 0; 588 return filter;
475 589
476oom: 590oom:
477 destroy_preds(call); 591 __free_preds(filter);
592 return ERR_PTR(-ENOMEM);
593}
594
595static int init_preds(struct ftrace_event_call *call)
596{
597 if (call->filter)
598 return 0;
478 599
479 return -ENOMEM; 600 call->filter_active = 0;
601 call->filter = __alloc_preds();
602 if (IS_ERR(call->filter))
603 return PTR_ERR(call->filter);
604
605 return 0;
480} 606}
481 607
482static int init_subsystem_preds(struct event_subsystem *system) 608static int init_subsystem_preds(struct event_subsystem *system)
@@ -499,14 +625,7 @@ static int init_subsystem_preds(struct event_subsystem *system)
499 return 0; 625 return 0;
500} 626}
501 627
502enum { 628static void filter_free_subsystem_preds(struct event_subsystem *system)
503 FILTER_DISABLE_ALL,
504 FILTER_INIT_NO_RESET,
505 FILTER_SKIP_NO_RESET,
506};
507
508static void filter_free_subsystem_preds(struct event_subsystem *system,
509 int flag)
510{ 629{
511 struct ftrace_event_call *call; 630 struct ftrace_event_call *call;
512 631
@@ -517,14 +636,6 @@ static void filter_free_subsystem_preds(struct event_subsystem *system,
517 if (strcmp(call->system, system->name) != 0) 636 if (strcmp(call->system, system->name) != 0)
518 continue; 637 continue;
519 638
520 if (flag == FILTER_INIT_NO_RESET) {
521 call->filter->no_reset = false;
522 continue;
523 }
524
525 if (flag == FILTER_SKIP_NO_RESET && call->filter->no_reset)
526 continue;
527
528 filter_disable_preds(call); 639 filter_disable_preds(call);
529 remove_filter_string(call->filter); 640 remove_filter_string(call->filter);
530 } 641 }
@@ -532,10 +643,10 @@ static void filter_free_subsystem_preds(struct event_subsystem *system,
532 643
533static int filter_add_pred_fn(struct filter_parse_state *ps, 644static int filter_add_pred_fn(struct filter_parse_state *ps,
534 struct ftrace_event_call *call, 645 struct ftrace_event_call *call,
646 struct event_filter *filter,
535 struct filter_pred *pred, 647 struct filter_pred *pred,
536 filter_pred_fn_t fn) 648 filter_pred_fn_t fn)
537{ 649{
538 struct event_filter *filter = call->filter;
539 int idx, err; 650 int idx, err;
540 651
541 if (filter->n_preds == MAX_FILTER_PRED) { 652 if (filter->n_preds == MAX_FILTER_PRED) {
@@ -550,7 +661,6 @@ static int filter_add_pred_fn(struct filter_parse_state *ps,
550 return err; 661 return err;
551 662
552 filter->n_preds++; 663 filter->n_preds++;
553 call->filter_active = 1;
554 664
555 return 0; 665 return 0;
556} 666}
@@ -575,7 +685,10 @@ static bool is_string_field(struct ftrace_event_field *field)
575 685
576static int is_legal_op(struct ftrace_event_field *field, int op) 686static int is_legal_op(struct ftrace_event_field *field, int op)
577{ 687{
578 if (is_string_field(field) && (op != OP_EQ && op != OP_NE)) 688 if (is_string_field(field) &&
689 (op != OP_EQ && op != OP_NE && op != OP_GLOB))
690 return 0;
691 if (!is_string_field(field) && op == OP_GLOB)
579 return 0; 692 return 0;
580 693
581 return 1; 694 return 1;
@@ -626,6 +739,7 @@ static filter_pred_fn_t select_comparison_fn(int op, int field_size,
626 739
627static int filter_add_pred(struct filter_parse_state *ps, 740static int filter_add_pred(struct filter_parse_state *ps,
628 struct ftrace_event_call *call, 741 struct ftrace_event_call *call,
742 struct event_filter *filter,
629 struct filter_pred *pred, 743 struct filter_pred *pred,
630 bool dry_run) 744 bool dry_run)
631{ 745{
@@ -660,21 +774,22 @@ static int filter_add_pred(struct filter_parse_state *ps,
660 } 774 }
661 775
662 if (is_string_field(field)) { 776 if (is_string_field(field)) {
663 pred->str_len = field->size; 777 filter_build_regex(pred);
664 778
665 if (field->filter_type == FILTER_STATIC_STRING) 779 if (field->filter_type == FILTER_STATIC_STRING) {
666 fn = filter_pred_string; 780 fn = filter_pred_string;
667 else if (field->filter_type == FILTER_DYN_STRING) 781 pred->regex.field_len = field->size;
782 } else if (field->filter_type == FILTER_DYN_STRING)
668 fn = filter_pred_strloc; 783 fn = filter_pred_strloc;
669 else { 784 else {
670 fn = filter_pred_pchar; 785 fn = filter_pred_pchar;
671 pred->str_len = strlen(pred->str_val); 786 pred->regex.field_len = strlen(pred->regex.pattern);
672 } 787 }
673 } else { 788 } else {
674 if (field->is_signed) 789 if (field->is_signed)
675 ret = strict_strtoll(pred->str_val, 0, &val); 790 ret = strict_strtoll(pred->regex.pattern, 0, &val);
676 else 791 else
677 ret = strict_strtoull(pred->str_val, 0, &val); 792 ret = strict_strtoull(pred->regex.pattern, 0, &val);
678 if (ret) { 793 if (ret) {
679 parse_error(ps, FILT_ERR_ILLEGAL_INTVAL, 0); 794 parse_error(ps, FILT_ERR_ILLEGAL_INTVAL, 0);
680 return -EINVAL; 795 return -EINVAL;
@@ -694,45 +809,7 @@ static int filter_add_pred(struct filter_parse_state *ps,
694 809
695add_pred_fn: 810add_pred_fn:
696 if (!dry_run) 811 if (!dry_run)
697 return filter_add_pred_fn(ps, call, pred, fn); 812 return filter_add_pred_fn(ps, call, filter, pred, fn);
698 return 0;
699}
700
701static int filter_add_subsystem_pred(struct filter_parse_state *ps,
702 struct event_subsystem *system,
703 struct filter_pred *pred,
704 char *filter_string,
705 bool dry_run)
706{
707 struct ftrace_event_call *call;
708 int err = 0;
709 bool fail = true;
710
711 list_for_each_entry(call, &ftrace_events, list) {
712
713 if (!call->define_fields)
714 continue;
715
716 if (strcmp(call->system, system->name))
717 continue;
718
719 if (call->filter->no_reset)
720 continue;
721
722 err = filter_add_pred(ps, call, pred, dry_run);
723 if (err)
724 call->filter->no_reset = true;
725 else
726 fail = false;
727
728 if (!dry_run)
729 replace_filter_string(call->filter, filter_string);
730 }
731
732 if (fail) {
733 parse_error(ps, FILT_ERR_BAD_SUBSYS_FILTER, 0);
734 return err;
735 }
736 return 0; 813 return 0;
737} 814}
738 815
@@ -1045,8 +1122,8 @@ static struct filter_pred *create_pred(int op, char *operand1, char *operand2)
1045 return NULL; 1122 return NULL;
1046 } 1123 }
1047 1124
1048 strcpy(pred->str_val, operand2); 1125 strcpy(pred->regex.pattern, operand2);
1049 pred->str_len = strlen(operand2); 1126 pred->regex.len = strlen(pred->regex.pattern);
1050 1127
1051 pred->op = op; 1128 pred->op = op;
1052 1129
@@ -1090,8 +1167,8 @@ static int check_preds(struct filter_parse_state *ps)
1090 return 0; 1167 return 0;
1091} 1168}
1092 1169
1093static int replace_preds(struct event_subsystem *system, 1170static int replace_preds(struct ftrace_event_call *call,
1094 struct ftrace_event_call *call, 1171 struct event_filter *filter,
1095 struct filter_parse_state *ps, 1172 struct filter_parse_state *ps,
1096 char *filter_string, 1173 char *filter_string,
1097 bool dry_run) 1174 bool dry_run)
@@ -1138,11 +1215,7 @@ static int replace_preds(struct event_subsystem *system,
1138add_pred: 1215add_pred:
1139 if (!pred) 1216 if (!pred)
1140 return -ENOMEM; 1217 return -ENOMEM;
1141 if (call) 1218 err = filter_add_pred(ps, call, filter, pred, dry_run);
1142 err = filter_add_pred(ps, call, pred, false);
1143 else
1144 err = filter_add_subsystem_pred(ps, system, pred,
1145 filter_string, dry_run);
1146 filter_free_pred(pred); 1219 filter_free_pred(pred);
1147 if (err) 1220 if (err)
1148 return err; 1221 return err;
@@ -1153,10 +1226,50 @@ add_pred:
1153 return 0; 1226 return 0;
1154} 1227}
1155 1228
1156int apply_event_filter(struct ftrace_event_call *call, char *filter_string) 1229static int replace_system_preds(struct event_subsystem *system,
1230 struct filter_parse_state *ps,
1231 char *filter_string)
1157{ 1232{
1233 struct event_filter *filter = system->filter;
1234 struct ftrace_event_call *call;
1235 bool fail = true;
1158 int err; 1236 int err;
1159 1237
1238 list_for_each_entry(call, &ftrace_events, list) {
1239
1240 if (!call->define_fields)
1241 continue;
1242
1243 if (strcmp(call->system, system->name) != 0)
1244 continue;
1245
1246 /* try to see if the filter can be applied */
1247 err = replace_preds(call, filter, ps, filter_string, true);
1248 if (err)
1249 continue;
1250
1251 /* really apply the filter */
1252 filter_disable_preds(call);
1253 err = replace_preds(call, filter, ps, filter_string, false);
1254 if (err)
1255 filter_disable_preds(call);
1256 else {
1257 call->filter_active = 1;
1258 replace_filter_string(filter, filter_string);
1259 }
1260 fail = false;
1261 }
1262
1263 if (fail) {
1264 parse_error(ps, FILT_ERR_BAD_SUBSYS_FILTER, 0);
1265 return -EINVAL;
1266 }
1267 return 0;
1268}
1269
1270int apply_event_filter(struct ftrace_event_call *call, char *filter_string)
1271{
1272 int err;
1160 struct filter_parse_state *ps; 1273 struct filter_parse_state *ps;
1161 1274
1162 mutex_lock(&event_mutex); 1275 mutex_lock(&event_mutex);
@@ -1168,8 +1281,7 @@ int apply_event_filter(struct ftrace_event_call *call, char *filter_string)
1168 if (!strcmp(strstrip(filter_string), "0")) { 1281 if (!strcmp(strstrip(filter_string), "0")) {
1169 filter_disable_preds(call); 1282 filter_disable_preds(call);
1170 remove_filter_string(call->filter); 1283 remove_filter_string(call->filter);
1171 mutex_unlock(&event_mutex); 1284 goto out_unlock;
1172 return 0;
1173 } 1285 }
1174 1286
1175 err = -ENOMEM; 1287 err = -ENOMEM;
@@ -1187,10 +1299,11 @@ int apply_event_filter(struct ftrace_event_call *call, char *filter_string)
1187 goto out; 1299 goto out;
1188 } 1300 }
1189 1301
1190 err = replace_preds(NULL, call, ps, filter_string, false); 1302 err = replace_preds(call, call->filter, ps, filter_string, false);
1191 if (err) 1303 if (err)
1192 append_filter_err(ps, call->filter); 1304 append_filter_err(ps, call->filter);
1193 1305 else
1306 call->filter_active = 1;
1194out: 1307out:
1195 filter_opstack_clear(ps); 1308 filter_opstack_clear(ps);
1196 postfix_clear(ps); 1309 postfix_clear(ps);
@@ -1205,7 +1318,6 @@ int apply_subsystem_event_filter(struct event_subsystem *system,
1205 char *filter_string) 1318 char *filter_string)
1206{ 1319{
1207 int err; 1320 int err;
1208
1209 struct filter_parse_state *ps; 1321 struct filter_parse_state *ps;
1210 1322
1211 mutex_lock(&event_mutex); 1323 mutex_lock(&event_mutex);
@@ -1215,10 +1327,9 @@ int apply_subsystem_event_filter(struct event_subsystem *system,
1215 goto out_unlock; 1327 goto out_unlock;
1216 1328
1217 if (!strcmp(strstrip(filter_string), "0")) { 1329 if (!strcmp(strstrip(filter_string), "0")) {
1218 filter_free_subsystem_preds(system, FILTER_DISABLE_ALL); 1330 filter_free_subsystem_preds(system);
1219 remove_filter_string(system->filter); 1331 remove_filter_string(system->filter);
1220 mutex_unlock(&event_mutex); 1332 goto out_unlock;
1221 return 0;
1222 } 1333 }
1223 1334
1224 err = -ENOMEM; 1335 err = -ENOMEM;
@@ -1235,31 +1346,87 @@ int apply_subsystem_event_filter(struct event_subsystem *system,
1235 goto out; 1346 goto out;
1236 } 1347 }
1237 1348
1238 filter_free_subsystem_preds(system, FILTER_INIT_NO_RESET); 1349 err = replace_system_preds(system, ps, filter_string);
1239 1350 if (err)
1240 /* try to see the filter can be applied to which events */
1241 err = replace_preds(system, NULL, ps, filter_string, true);
1242 if (err) {
1243 append_filter_err(ps, system->filter); 1351 append_filter_err(ps, system->filter);
1244 goto out; 1352
1353out:
1354 filter_opstack_clear(ps);
1355 postfix_clear(ps);
1356 kfree(ps);
1357out_unlock:
1358 mutex_unlock(&event_mutex);
1359
1360 return err;
1361}
1362
1363#ifdef CONFIG_EVENT_PROFILE
1364
1365void ftrace_profile_free_filter(struct perf_event *event)
1366{
1367 struct event_filter *filter = event->filter;
1368
1369 event->filter = NULL;
1370 __free_preds(filter);
1371}
1372
1373int ftrace_profile_set_filter(struct perf_event *event, int event_id,
1374 char *filter_str)
1375{
1376 int err;
1377 struct event_filter *filter;
1378 struct filter_parse_state *ps;
1379 struct ftrace_event_call *call = NULL;
1380
1381 mutex_lock(&event_mutex);
1382
1383 list_for_each_entry(call, &ftrace_events, list) {
1384 if (call->id == event_id)
1385 break;
1245 } 1386 }
1246 1387
1247 filter_free_subsystem_preds(system, FILTER_SKIP_NO_RESET); 1388 err = -EINVAL;
1389 if (!call)
1390 goto out_unlock;
1248 1391
1249 /* really apply the filter to the events */ 1392 err = -EEXIST;
1250 err = replace_preds(system, NULL, ps, filter_string, false); 1393 if (event->filter)
1251 if (err) { 1394 goto out_unlock;
1252 append_filter_err(ps, system->filter); 1395
1253 filter_free_subsystem_preds(system, 2); 1396 filter = __alloc_preds();
1397 if (IS_ERR(filter)) {
1398 err = PTR_ERR(filter);
1399 goto out_unlock;
1254 } 1400 }
1255 1401
1256out: 1402 err = -ENOMEM;
1403 ps = kzalloc(sizeof(*ps), GFP_KERNEL);
1404 if (!ps)
1405 goto free_preds;
1406
1407 parse_init(ps, filter_ops, filter_str);
1408 err = filter_parse(ps);
1409 if (err)
1410 goto free_ps;
1411
1412 err = replace_preds(call, filter, ps, filter_str, false);
1413 if (!err)
1414 event->filter = filter;
1415
1416free_ps:
1257 filter_opstack_clear(ps); 1417 filter_opstack_clear(ps);
1258 postfix_clear(ps); 1418 postfix_clear(ps);
1259 kfree(ps); 1419 kfree(ps);
1420
1421free_preds:
1422 if (err)
1423 __free_preds(filter);
1424
1260out_unlock: 1425out_unlock:
1261 mutex_unlock(&event_mutex); 1426 mutex_unlock(&event_mutex);
1262 1427
1263 return err; 1428 return err;
1264} 1429}
1265 1430
1431#endif /* CONFIG_EVENT_PROFILE */
1432
diff --git a/kernel/trace/trace_export.c b/kernel/trace/trace_export.c
index ed7d4808352..934d81fb4ca 100644
--- a/kernel/trace/trace_export.c
+++ b/kernel/trace/trace_export.c
@@ -66,44 +66,47 @@ static void __used ____ftrace_check_##name(void) \
66#undef __field 66#undef __field
67#define __field(type, item) \ 67#define __field(type, item) \
68 ret = trace_seq_printf(s, "\tfield:" #type " " #item ";\t" \ 68 ret = trace_seq_printf(s, "\tfield:" #type " " #item ";\t" \
69 "offset:%zu;\tsize:%zu;\n", \ 69 "offset:%zu;\tsize:%zu;\tsigned:%u;\n", \
70 offsetof(typeof(field), item), \ 70 offsetof(typeof(field), item), \
71 sizeof(field.item)); \ 71 sizeof(field.item), is_signed_type(type)); \
72 if (!ret) \ 72 if (!ret) \
73 return 0; 73 return 0;
74 74
75#undef __field_desc 75#undef __field_desc
76#define __field_desc(type, container, item) \ 76#define __field_desc(type, container, item) \
77 ret = trace_seq_printf(s, "\tfield:" #type " " #item ";\t" \ 77 ret = trace_seq_printf(s, "\tfield:" #type " " #item ";\t" \
78 "offset:%zu;\tsize:%zu;\n", \ 78 "offset:%zu;\tsize:%zu;\tsigned:%u;\n", \
79 offsetof(typeof(field), container.item), \ 79 offsetof(typeof(field), container.item), \
80 sizeof(field.container.item)); \ 80 sizeof(field.container.item), \
81 is_signed_type(type)); \
81 if (!ret) \ 82 if (!ret) \
82 return 0; 83 return 0;
83 84
84#undef __array 85#undef __array
85#define __array(type, item, len) \ 86#define __array(type, item, len) \
86 ret = trace_seq_printf(s, "\tfield:" #type " " #item "[" #len "];\t" \ 87 ret = trace_seq_printf(s, "\tfield:" #type " " #item "[" #len "];\t" \
87 "offset:%zu;\tsize:%zu;\n", \ 88 "offset:%zu;\tsize:%zu;\tsigned:%u;\n", \
88 offsetof(typeof(field), item), \ 89 offsetof(typeof(field), item), \
89 sizeof(field.item)); \ 90 sizeof(field.item), is_signed_type(type)); \
90 if (!ret) \ 91 if (!ret) \
91 return 0; 92 return 0;
92 93
93#undef __array_desc 94#undef __array_desc
94#define __array_desc(type, container, item, len) \ 95#define __array_desc(type, container, item, len) \
95 ret = trace_seq_printf(s, "\tfield:" #type " " #item "[" #len "];\t" \ 96 ret = trace_seq_printf(s, "\tfield:" #type " " #item "[" #len "];\t" \
96 "offset:%zu;\tsize:%zu;\n", \ 97 "offset:%zu;\tsize:%zu;\tsigned:%u;\n", \
97 offsetof(typeof(field), container.item), \ 98 offsetof(typeof(field), container.item), \
98 sizeof(field.container.item)); \ 99 sizeof(field.container.item), \
100 is_signed_type(type)); \
99 if (!ret) \ 101 if (!ret) \
100 return 0; 102 return 0;
101 103
102#undef __dynamic_array 104#undef __dynamic_array
103#define __dynamic_array(type, item) \ 105#define __dynamic_array(type, item) \
104 ret = trace_seq_printf(s, "\tfield:" #type " " #item ";\t" \ 106 ret = trace_seq_printf(s, "\tfield:" #type " " #item ";\t" \
105 "offset:%zu;\tsize:0;\n", \ 107 "offset:%zu;\tsize:0;\tsigned:%u;\n", \
106 offsetof(typeof(field), item)); \ 108 offsetof(typeof(field), item), \
109 is_signed_type(type)); \
107 if (!ret) \ 110 if (!ret) \
108 return 0; 111 return 0;
109 112
diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c
index 9ade66389d5..58b8e537076 100644
--- a/kernel/trace/trace_syscalls.c
+++ b/kernel/trace/trace_syscalls.c
@@ -14,6 +14,69 @@ static int sys_refcount_exit;
14static DECLARE_BITMAP(enabled_enter_syscalls, NR_syscalls); 14static DECLARE_BITMAP(enabled_enter_syscalls, NR_syscalls);
15static DECLARE_BITMAP(enabled_exit_syscalls, NR_syscalls); 15static DECLARE_BITMAP(enabled_exit_syscalls, NR_syscalls);
16 16
17extern unsigned long __start_syscalls_metadata[];
18extern unsigned long __stop_syscalls_metadata[];
19
20static struct syscall_metadata **syscalls_metadata;
21
22static struct syscall_metadata *find_syscall_meta(unsigned long syscall)
23{
24 struct syscall_metadata *start;
25 struct syscall_metadata *stop;
26 char str[KSYM_SYMBOL_LEN];
27
28
29 start = (struct syscall_metadata *)__start_syscalls_metadata;
30 stop = (struct syscall_metadata *)__stop_syscalls_metadata;
31 kallsyms_lookup(syscall, NULL, NULL, NULL, str);
32
33 for ( ; start < stop; start++) {
34 /*
35 * Only compare after the "sys" prefix. Archs that use
36 * syscall wrappers may have syscalls symbols aliases prefixed
37 * with "SyS" instead of "sys", leading to an unwanted
38 * mismatch.
39 */
40 if (start->name && !strcmp(start->name + 3, str + 3))
41 return start;
42 }
43 return NULL;
44}
45
46static struct syscall_metadata *syscall_nr_to_meta(int nr)
47{
48 if (!syscalls_metadata || nr >= NR_syscalls || nr < 0)
49 return NULL;
50
51 return syscalls_metadata[nr];
52}
53
54int syscall_name_to_nr(char *name)
55{
56 int i;
57
58 if (!syscalls_metadata)
59 return -1;
60
61 for (i = 0; i < NR_syscalls; i++) {
62 if (syscalls_metadata[i]) {
63 if (!strcmp(syscalls_metadata[i]->name, name))
64 return i;
65 }
66 }
67 return -1;
68}
69
70void set_syscall_enter_id(int num, int id)
71{
72 syscalls_metadata[num]->enter_id = id;
73}
74
75void set_syscall_exit_id(int num, int id)
76{
77 syscalls_metadata[num]->exit_id = id;
78}
79
17enum print_line_t 80enum print_line_t
18print_syscall_enter(struct trace_iterator *iter, int flags) 81print_syscall_enter(struct trace_iterator *iter, int flags)
19{ 82{
@@ -103,7 +166,8 @@ extern char *__bad_type_size(void);
103#define SYSCALL_FIELD(type, name) \ 166#define SYSCALL_FIELD(type, name) \
104 sizeof(type) != sizeof(trace.name) ? \ 167 sizeof(type) != sizeof(trace.name) ? \
105 __bad_type_size() : \ 168 __bad_type_size() : \
106 #type, #name, offsetof(typeof(trace), name), sizeof(trace.name) 169 #type, #name, offsetof(typeof(trace), name), \
170 sizeof(trace.name), is_signed_type(type)
107 171
108int syscall_enter_format(struct ftrace_event_call *call, struct trace_seq *s) 172int syscall_enter_format(struct ftrace_event_call *call, struct trace_seq *s)
109{ 173{
@@ -120,7 +184,8 @@ int syscall_enter_format(struct ftrace_event_call *call, struct trace_seq *s)
120 if (!entry) 184 if (!entry)
121 return 0; 185 return 0;
122 186
123 ret = trace_seq_printf(s, "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\n", 187 ret = trace_seq_printf(s, "\tfield:%s %s;\toffset:%zu;\tsize:%zu;"
188 "\tsigned:%u;\n",
124 SYSCALL_FIELD(int, nr)); 189 SYSCALL_FIELD(int, nr));
125 if (!ret) 190 if (!ret)
126 return 0; 191 return 0;
@@ -130,8 +195,10 @@ int syscall_enter_format(struct ftrace_event_call *call, struct trace_seq *s)
130 entry->args[i]); 195 entry->args[i]);
131 if (!ret) 196 if (!ret)
132 return 0; 197 return 0;
133 ret = trace_seq_printf(s, "\toffset:%d;\tsize:%zu;\n", offset, 198 ret = trace_seq_printf(s, "\toffset:%d;\tsize:%zu;"
134 sizeof(unsigned long)); 199 "\tsigned:%u;\n", offset,
200 sizeof(unsigned long),
201 is_signed_type(unsigned long));
135 if (!ret) 202 if (!ret)
136 return 0; 203 return 0;
137 offset += sizeof(unsigned long); 204 offset += sizeof(unsigned long);
@@ -163,8 +230,10 @@ int syscall_exit_format(struct ftrace_event_call *call, struct trace_seq *s)
163 struct syscall_trace_exit trace; 230 struct syscall_trace_exit trace;
164 231
165 ret = trace_seq_printf(s, 232 ret = trace_seq_printf(s,
166 "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\n" 233 "\tfield:%s %s;\toffset:%zu;\tsize:%zu;"
167 "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\n", 234 "\tsigned:%u;\n"
235 "\tfield:%s %s;\toffset:%zu;\tsize:%zu;"
236 "\tsigned:%u;\n",
168 SYSCALL_FIELD(int, nr), 237 SYSCALL_FIELD(int, nr),
169 SYSCALL_FIELD(long, ret)); 238 SYSCALL_FIELD(long, ret));
170 if (!ret) 239 if (!ret)
@@ -212,7 +281,7 @@ int syscall_exit_define_fields(struct ftrace_event_call *call)
212 if (ret) 281 if (ret)
213 return ret; 282 return ret;
214 283
215 ret = trace_define_field(call, SYSCALL_FIELD(long, ret), 0, 284 ret = trace_define_field(call, SYSCALL_FIELD(long, ret),
216 FILTER_OTHER); 285 FILTER_OTHER);
217 286
218 return ret; 287 return ret;
@@ -375,6 +444,29 @@ struct trace_event event_syscall_exit = {
375 .trace = print_syscall_exit, 444 .trace = print_syscall_exit,
376}; 445};
377 446
447int __init init_ftrace_syscalls(void)
448{
449 struct syscall_metadata *meta;
450 unsigned long addr;
451 int i;
452
453 syscalls_metadata = kzalloc(sizeof(*syscalls_metadata) *
454 NR_syscalls, GFP_KERNEL);
455 if (!syscalls_metadata) {
456 WARN_ON(1);
457 return -ENOMEM;
458 }
459
460 for (i = 0; i < NR_syscalls; i++) {
461 addr = arch_syscall_addr(i);
462 meta = find_syscall_meta(addr);
463 syscalls_metadata[i] = meta;
464 }
465
466 return 0;
467}
468core_initcall(init_ftrace_syscalls);
469
378#ifdef CONFIG_EVENT_PROFILE 470#ifdef CONFIG_EVENT_PROFILE
379 471
380static DECLARE_BITMAP(enabled_prof_enter_syscalls, NR_syscalls); 472static DECLARE_BITMAP(enabled_prof_enter_syscalls, NR_syscalls);
diff --git a/lib/kernel_lock.c b/lib/kernel_lock.c
index 39f1029e352..4ebfa5a164d 100644
--- a/lib/kernel_lock.c
+++ b/lib/kernel_lock.c
@@ -5,10 +5,13 @@
5 * relegated to obsolescence, but used by various less 5 * relegated to obsolescence, but used by various less
6 * important (or lazy) subsystems. 6 * important (or lazy) subsystems.
7 */ 7 */
8#include <linux/smp_lock.h>
9#include <linux/module.h> 8#include <linux/module.h>
10#include <linux/kallsyms.h> 9#include <linux/kallsyms.h>
11#include <linux/semaphore.h> 10#include <linux/semaphore.h>
11#include <linux/smp_lock.h>
12
13#define CREATE_TRACE_POINTS
14#include <trace/events/bkl.h>
12 15
13/* 16/*
14 * The 'big kernel lock' 17 * The 'big kernel lock'
@@ -113,21 +116,26 @@ static inline void __unlock_kernel(void)
113 * This cannot happen asynchronously, so we only need to 116 * This cannot happen asynchronously, so we only need to
114 * worry about other CPU's. 117 * worry about other CPU's.
115 */ 118 */
116void __lockfunc lock_kernel(void) 119void __lockfunc _lock_kernel(const char *func, const char *file, int line)
117{ 120{
118 int depth = current->lock_depth+1; 121 int depth = current->lock_depth + 1;
122
123 trace_lock_kernel(func, file, line);
124
119 if (likely(!depth)) 125 if (likely(!depth))
120 __lock_kernel(); 126 __lock_kernel();
121 current->lock_depth = depth; 127 current->lock_depth = depth;
122} 128}
123 129
124void __lockfunc unlock_kernel(void) 130void __lockfunc _unlock_kernel(const char *func, const char *file, int line)
125{ 131{
126 BUG_ON(current->lock_depth < 0); 132 BUG_ON(current->lock_depth < 0);
127 if (likely(--current->lock_depth < 0)) 133 if (likely(--current->lock_depth < 0))
128 __unlock_kernel(); 134 __unlock_kernel();
135
136 trace_unlock_kernel(func, file, line);
129} 137}
130 138
131EXPORT_SYMBOL(lock_kernel); 139EXPORT_SYMBOL(_lock_kernel);
132EXPORT_SYMBOL(unlock_kernel); 140EXPORT_SYMBOL(_unlock_kernel);
133 141
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
index 090d300d739..bfb8b2cdd92 100755
--- a/scripts/recordmcount.pl
+++ b/scripts/recordmcount.pl
@@ -119,6 +119,7 @@ my %text_sections = (
119 ".sched.text" => 1, 119 ".sched.text" => 1,
120 ".spinlock.text" => 1, 120 ".spinlock.text" => 1,
121 ".irqentry.text" => 1, 121 ".irqentry.text" => 1,
122 ".text.unlikely" => 1,
122); 123);
123 124
124$objdump = "objdump" if ((length $objdump) == 0); 125$objdump = "objdump" if ((length $objdump) == 0);
diff --git a/tools/perf/Documentation/perf-timechart.txt b/tools/perf/Documentation/perf-timechart.txt
index a7910099d6f..4b1788355ec 100644
--- a/tools/perf/Documentation/perf-timechart.txt
+++ b/tools/perf/Documentation/perf-timechart.txt
@@ -31,9 +31,12 @@ OPTIONS
31-w:: 31-w::
32--width=:: 32--width=::
33 Select the width of the SVG file (default: 1000) 33 Select the width of the SVG file (default: 1000)
34-p:: 34-P::
35--power-only:: 35--power-only::
36 Only output the CPU power section of the diagram 36 Only output the CPU power section of the diagram
37-p::
38--process::
39 Select the processes to display, by name or PID
37 40
38 41
39SEE ALSO 42SEE ALSO
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 1811a7015f9..147e3cf035d 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -201,7 +201,14 @@ EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wold-style-definition
201EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wstrict-prototypes 201EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wstrict-prototypes
202EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wdeclaration-after-statement 202EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wdeclaration-after-statement
203 203
204CFLAGS = $(MBITS) -ggdb3 -Wall -Wextra -std=gnu99 -Werror -O6 -fstack-protector-all -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) 204ifeq ("$(origin DEBUG)", "command line")
205 PERF_DEBUG = $(DEBUG)
206endif
207ifndef PERF_DEBUG
208 CFLAGS_OPTIMIZE = -O6
209endif
210
211CFLAGS = $(MBITS) -ggdb3 -Wall -Wextra -std=gnu99 -Werror $(CFLAGS_OPTIMIZE) -fstack-protector-all -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS)
205LDFLAGS = -lpthread -lrt -lelf -lm 212LDFLAGS = -lpthread -lrt -lelf -lm
206ALL_CFLAGS = $(CFLAGS) 213ALL_CFLAGS = $(CFLAGS)
207ALL_LDFLAGS = $(LDFLAGS) 214ALL_LDFLAGS = $(LDFLAGS)
@@ -329,8 +336,26 @@ LIB_H += ../../include/linux/perf_event.h
329LIB_H += ../../include/linux/rbtree.h 336LIB_H += ../../include/linux/rbtree.h
330LIB_H += ../../include/linux/list.h 337LIB_H += ../../include/linux/list.h
331LIB_H += ../../include/linux/stringify.h 338LIB_H += ../../include/linux/stringify.h
339LIB_H += util/include/linux/bitmap.h
340LIB_H += util/include/linux/bitops.h
341LIB_H += util/include/linux/compiler.h
342LIB_H += util/include/linux/ctype.h
343LIB_H += util/include/linux/kernel.h
332LIB_H += util/include/linux/list.h 344LIB_H += util/include/linux/list.h
345LIB_H += util/include/linux/module.h
346LIB_H += util/include/linux/poison.h
347LIB_H += util/include/linux/prefetch.h
348LIB_H += util/include/linux/rbtree.h
349LIB_H += util/include/linux/string.h
350LIB_H += util/include/linux/types.h
351LIB_H += util/include/asm/asm-offsets.h
352LIB_H += util/include/asm/bitops.h
353LIB_H += util/include/asm/byteorder.h
354LIB_H += util/include/asm/swab.h
355LIB_H += util/include/asm/system.h
356LIB_H += util/include/asm/uaccess.h
333LIB_H += perf.h 357LIB_H += perf.h
358LIB_H += util/event.h
334LIB_H += util/types.h 359LIB_H += util/types.h
335LIB_H += util/levenshtein.h 360LIB_H += util/levenshtein.h
336LIB_H += util/parse-options.h 361LIB_H += util/parse-options.h
@@ -344,9 +369,12 @@ LIB_H += util/strlist.h
344LIB_H += util/run-command.h 369LIB_H += util/run-command.h
345LIB_H += util/sigchain.h 370LIB_H += util/sigchain.h
346LIB_H += util/symbol.h 371LIB_H += util/symbol.h
347LIB_H += util/module.h
348LIB_H += util/color.h 372LIB_H += util/color.h
349LIB_H += util/values.h 373LIB_H += util/values.h
374LIB_H += util/sort.h
375LIB_H += util/hist.h
376LIB_H += util/thread.h
377LIB_H += util/data_map.h
350 378
351LIB_OBJS += util/abspath.o 379LIB_OBJS += util/abspath.o
352LIB_OBJS += util/alias.o 380LIB_OBJS += util/alias.o
@@ -360,6 +388,9 @@ LIB_OBJS += util/parse-options.o
360LIB_OBJS += util/parse-events.o 388LIB_OBJS += util/parse-events.o
361LIB_OBJS += util/path.o 389LIB_OBJS += util/path.o
362LIB_OBJS += util/rbtree.o 390LIB_OBJS += util/rbtree.o
391LIB_OBJS += util/bitmap.o
392LIB_OBJS += util/hweight.o
393LIB_OBJS += util/find_next_bit.o
363LIB_OBJS += util/run-command.o 394LIB_OBJS += util/run-command.o
364LIB_OBJS += util/quote.o 395LIB_OBJS += util/quote.o
365LIB_OBJS += util/strbuf.o 396LIB_OBJS += util/strbuf.o
@@ -369,7 +400,6 @@ LIB_OBJS += util/usage.o
369LIB_OBJS += util/wrapper.o 400LIB_OBJS += util/wrapper.o
370LIB_OBJS += util/sigchain.o 401LIB_OBJS += util/sigchain.o
371LIB_OBJS += util/symbol.o 402LIB_OBJS += util/symbol.o
372LIB_OBJS += util/module.o
373LIB_OBJS += util/color.o 403LIB_OBJS += util/color.o
374LIB_OBJS += util/pager.o 404LIB_OBJS += util/pager.o
375LIB_OBJS += util/header.o 405LIB_OBJS += util/header.o
@@ -382,6 +412,9 @@ LIB_OBJS += util/trace-event-parse.o
382LIB_OBJS += util/trace-event-read.o 412LIB_OBJS += util/trace-event-read.o
383LIB_OBJS += util/trace-event-info.o 413LIB_OBJS += util/trace-event-info.o
384LIB_OBJS += util/svghelper.o 414LIB_OBJS += util/svghelper.o
415LIB_OBJS += util/sort.o
416LIB_OBJS += util/hist.o
417LIB_OBJS += util/data_map.o
385 418
386BUILTIN_OBJS += builtin-annotate.o 419BUILTIN_OBJS += builtin-annotate.o
387BUILTIN_OBJS += builtin-help.o 420BUILTIN_OBJS += builtin-help.o
@@ -424,8 +457,12 @@ ifeq ($(uname_S),Darwin)
424 PTHREAD_LIBS = 457 PTHREAD_LIBS =
425endif 458endif
426 459
460ifneq ($(shell sh -c "(echo '\#include <gnu/libc-version.h>'; echo 'int main(void) { const char * version = gnu_get_libc_version(); return (long)version; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -o /dev/null $(ALL_LDFLAGS) > /dev/null 2>&1 && echo y"), y)
461 msg := $(error No gnu/libc-version.h found, please install glibc-dev[el]);
462endif
463
427ifneq ($(shell sh -c "(echo '\#include <libelf.h>'; echo 'int main(void) { Elf * elf = elf_begin(0, ELF_C_READ_MMAP, 0); return (long)elf; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -o /dev/null $(ALL_LDFLAGS) > /dev/null 2>&1 && echo y"), y) 464ifneq ($(shell sh -c "(echo '\#include <libelf.h>'; echo 'int main(void) { Elf * elf = elf_begin(0, ELF_C_READ_MMAP, 0); return (long)elf; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -o /dev/null $(ALL_LDFLAGS) > /dev/null 2>&1 && echo y"), y)
428 msg := $(error No libelf.h/libelf found, please install libelf-dev/elfutils-libelf-devel and glibc-dev[el]); 465 msg := $(error No libelf.h/libelf found, please install libelf-dev/elfutils-libelf-devel);
429endif 466endif
430 467
431ifneq ($(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) > /dev/null 2>&1 && echo y"), y) 468ifneq ($(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) > /dev/null 2>&1 && echo y"), y)
@@ -795,6 +832,19 @@ util/config.o: util/config.c PERF-CFLAGS
795util/rbtree.o: ../../lib/rbtree.c PERF-CFLAGS 832util/rbtree.o: ../../lib/rbtree.c PERF-CFLAGS
796 $(QUIET_CC)$(CC) -o util/rbtree.o -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< 833 $(QUIET_CC)$(CC) -o util/rbtree.o -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
797 834
835# some perf warning policies can't fit to lib/bitmap.c, eg: it warns about variable shadowing
836# from <string.h> that comes from kernel headers wrapping.
837KBITMAP_FLAGS=`echo $(ALL_CFLAGS) | sed s/-Wshadow// | sed s/-Wswitch-default// | sed s/-Wextra//`
838
839util/bitmap.o: ../../lib/bitmap.c PERF-CFLAGS
840 $(QUIET_CC)$(CC) -o util/bitmap.o -c $(KBITMAP_FLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
841
842util/hweight.o: ../../lib/hweight.c PERF-CFLAGS
843 $(QUIET_CC)$(CC) -o util/hweight.o -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
844
845util/find_next_bit.o: ../../lib/find_next_bit.c PERF-CFLAGS
846 $(QUIET_CC)$(CC) -o util/find_next_bit.o -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
847
798perf-%$X: %.o $(PERFLIBS) 848perf-%$X: %.o $(PERFLIBS)
799 $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS) 849 $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS)
800 850
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 1ec74161581..6d63c2eea2c 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -22,15 +22,13 @@
22#include "util/parse-options.h" 22#include "util/parse-options.h"
23#include "util/parse-events.h" 23#include "util/parse-events.h"
24#include "util/thread.h" 24#include "util/thread.h"
25#include "util/sort.h"
26#include "util/hist.h"
25 27
26static char const *input_name = "perf.data"; 28static char const *input_name = "perf.data";
27 29
28static char default_sort_order[] = "comm,symbol";
29static char *sort_order = default_sort_order;
30
31static int force; 30static int force;
32static int input; 31static int input;
33static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV;
34 32
35static int full_paths; 33static int full_paths;
36 34
@@ -39,9 +37,10 @@ static int print_line;
39static unsigned long page_size; 37static unsigned long page_size;
40static unsigned long mmap_window = 32; 38static unsigned long mmap_window = 32;
41 39
42static struct rb_root threads; 40struct sym_hist {
43static struct thread *last_match; 41 u64 sum;
44 42 u64 ip[0];
43};
45 44
46struct sym_ext { 45struct sym_ext {
47 struct rb_node node; 46 struct rb_node node;
@@ -49,247 +48,33 @@ struct sym_ext {
49 char *path; 48 char *path;
50}; 49};
51 50
52/* 51struct sym_priv {
53 * histogram, sorted on item, collects counts 52 struct sym_hist *hist;
54 */ 53 struct sym_ext *ext;
55
56static struct rb_root hist;
57
58struct hist_entry {
59 struct rb_node rb_node;
60
61 struct thread *thread;
62 struct map *map;
63 struct dso *dso;
64 struct symbol *sym;
65 u64 ip;
66 char level;
67
68 uint32_t count;
69};
70
71/*
72 * configurable sorting bits
73 */
74
75struct sort_entry {
76 struct list_head list;
77
78 const char *header;
79
80 int64_t (*cmp)(struct hist_entry *, struct hist_entry *);
81 int64_t (*collapse)(struct hist_entry *, struct hist_entry *);
82 size_t (*print)(FILE *fp, struct hist_entry *);
83};
84
85/* --sort pid */
86
87static int64_t
88sort__thread_cmp(struct hist_entry *left, struct hist_entry *right)
89{
90 return right->thread->pid - left->thread->pid;
91}
92
93static size_t
94sort__thread_print(FILE *fp, struct hist_entry *self)
95{
96 return fprintf(fp, "%16s:%5d", self->thread->comm ?: "", self->thread->pid);
97}
98
99static struct sort_entry sort_thread = {
100 .header = " Command: Pid",
101 .cmp = sort__thread_cmp,
102 .print = sort__thread_print,
103};
104
105/* --sort comm */
106
107static int64_t
108sort__comm_cmp(struct hist_entry *left, struct hist_entry *right)
109{
110 return right->thread->pid - left->thread->pid;
111}
112
113static int64_t
114sort__comm_collapse(struct hist_entry *left, struct hist_entry *right)
115{
116 char *comm_l = left->thread->comm;
117 char *comm_r = right->thread->comm;
118
119 if (!comm_l || !comm_r) {
120 if (!comm_l && !comm_r)
121 return 0;
122 else if (!comm_l)
123 return -1;
124 else
125 return 1;
126 }
127
128 return strcmp(comm_l, comm_r);
129}
130
131static size_t
132sort__comm_print(FILE *fp, struct hist_entry *self)
133{
134 return fprintf(fp, "%16s", self->thread->comm);
135}
136
137static struct sort_entry sort_comm = {
138 .header = " Command",
139 .cmp = sort__comm_cmp,
140 .collapse = sort__comm_collapse,
141 .print = sort__comm_print,
142};
143
144/* --sort dso */
145
146static int64_t
147sort__dso_cmp(struct hist_entry *left, struct hist_entry *right)
148{
149 struct dso *dso_l = left->dso;
150 struct dso *dso_r = right->dso;
151
152 if (!dso_l || !dso_r) {
153 if (!dso_l && !dso_r)
154 return 0;
155 else if (!dso_l)
156 return -1;
157 else
158 return 1;
159 }
160
161 return strcmp(dso_l->name, dso_r->name);
162}
163
164static size_t
165sort__dso_print(FILE *fp, struct hist_entry *self)
166{
167 if (self->dso)
168 return fprintf(fp, "%-25s", self->dso->name);
169
170 return fprintf(fp, "%016llx ", (u64)self->ip);
171}
172
173static struct sort_entry sort_dso = {
174 .header = "Shared Object ",
175 .cmp = sort__dso_cmp,
176 .print = sort__dso_print,
177};
178
179/* --sort symbol */
180
181static int64_t
182sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
183{
184 u64 ip_l, ip_r;
185
186 if (left->sym == right->sym)
187 return 0;
188
189 ip_l = left->sym ? left->sym->start : left->ip;
190 ip_r = right->sym ? right->sym->start : right->ip;
191
192 return (int64_t)(ip_r - ip_l);
193}
194
195static size_t
196sort__sym_print(FILE *fp, struct hist_entry *self)
197{
198 size_t ret = 0;
199
200 if (verbose)
201 ret += fprintf(fp, "%#018llx ", (u64)self->ip);
202
203 if (self->sym) {
204 ret += fprintf(fp, "[%c] %s",
205 self->dso == kernel_dso ? 'k' : '.', self->sym->name);
206 } else {
207 ret += fprintf(fp, "%#016llx", (u64)self->ip);
208 }
209
210 return ret;
211}
212
213static struct sort_entry sort_sym = {
214 .header = "Symbol",
215 .cmp = sort__sym_cmp,
216 .print = sort__sym_print,
217};
218
219static int sort__need_collapse = 0;
220
221struct sort_dimension {
222 const char *name;
223 struct sort_entry *entry;
224 int taken;
225};
226
227static struct sort_dimension sort_dimensions[] = {
228 { .name = "pid", .entry = &sort_thread, },
229 { .name = "comm", .entry = &sort_comm, },
230 { .name = "dso", .entry = &sort_dso, },
231 { .name = "symbol", .entry = &sort_sym, },
232}; 54};
233 55
234static LIST_HEAD(hist_entry__sort_list); 56static const char *sym_hist_filter;
235 57
236static int sort_dimension__add(char *tok) 58static int symbol_filter(struct map *map, struct symbol *sym)
237{ 59{
238 unsigned int i; 60 if (sym_hist_filter == NULL ||
239 61 strcmp(sym->name, sym_hist_filter) == 0) {
240 for (i = 0; i < ARRAY_SIZE(sort_dimensions); i++) { 62 struct sym_priv *priv = dso__sym_priv(map->dso, sym);
241 struct sort_dimension *sd = &sort_dimensions[i]; 63 const int size = (sizeof(*priv->hist) +
242 64 (sym->end - sym->start) * sizeof(u64));
243 if (sd->taken)
244 continue;
245
246 if (strncasecmp(tok, sd->name, strlen(tok)))
247 continue;
248
249 if (sd->entry->collapse)
250 sort__need_collapse = 1;
251
252 list_add_tail(&sd->entry->list, &hist_entry__sort_list);
253 sd->taken = 1;
254 65
66 priv->hist = malloc(size);
67 if (priv->hist)
68 memset(priv->hist, 0, size);
255 return 0; 69 return 0;
256 } 70 }
257 71 /*
258 return -ESRCH; 72 * FIXME: We should really filter it out, as we don't want to go thru symbols
259} 73 * we're not interested, and if a DSO ends up with no symbols, delete it too,
260 74 * but right now the kernel loading routines in symbol.c bail out if no symbols
261static int64_t 75 * are found, fix it later.
262hist_entry__cmp(struct hist_entry *left, struct hist_entry *right) 76 */
263{ 77 return 0;
264 struct sort_entry *se;
265 int64_t cmp = 0;
266
267 list_for_each_entry(se, &hist_entry__sort_list, list) {
268 cmp = se->cmp(left, right);
269 if (cmp)
270 break;
271 }
272
273 return cmp;
274}
275
276static int64_t
277hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
278{
279 struct sort_entry *se;
280 int64_t cmp = 0;
281
282 list_for_each_entry(se, &hist_entry__sort_list, list) {
283 int64_t (*f)(struct hist_entry *, struct hist_entry *);
284
285 f = se->collapse ?: se->cmp;
286
287 cmp = f(left, right);
288 if (cmp)
289 break;
290 }
291
292 return cmp;
293} 78}
294 79
295/* 80/*
@@ -299,196 +84,60 @@ static void hist_hit(struct hist_entry *he, u64 ip)
299{ 84{
300 unsigned int sym_size, offset; 85 unsigned int sym_size, offset;
301 struct symbol *sym = he->sym; 86 struct symbol *sym = he->sym;
87 struct sym_priv *priv;
88 struct sym_hist *h;
302 89
303 he->count++; 90 he->count++;
304 91
305 if (!sym || !sym->hist) 92 if (!sym || !he->map)
93 return;
94
95 priv = dso__sym_priv(he->map->dso, sym);
96 if (!priv->hist)
306 return; 97 return;
307 98
308 sym_size = sym->end - sym->start; 99 sym_size = sym->end - sym->start;
309 offset = ip - sym->start; 100 offset = ip - sym->start;
310 101
102 if (verbose)
103 fprintf(stderr, "%s: ip=%Lx\n", __func__,
104 he->map->unmap_ip(he->map, ip));
105
311 if (offset >= sym_size) 106 if (offset >= sym_size)
312 return; 107 return;
313 108
314 sym->hist_sum++; 109 h = priv->hist;
315 sym->hist[offset]++; 110 h->sum++;
111 h->ip[offset]++;
316 112
317 if (verbose >= 3) 113 if (verbose >= 3)
318 printf("%p %s: count++ [ip: %p, %08Lx] => %Ld\n", 114 printf("%p %s: count++ [ip: %p, %08Lx] => %Ld\n",
319 (void *)(unsigned long)he->sym->start, 115 (void *)(unsigned long)he->sym->start,
320 he->sym->name, 116 he->sym->name,
321 (void *)(unsigned long)ip, ip - he->sym->start, 117 (void *)(unsigned long)ip, ip - he->sym->start,
322 sym->hist[offset]); 118 h->ip[offset]);
323} 119}
324 120
325static int 121static int hist_entry__add(struct thread *thread, struct map *map,
326hist_entry__add(struct thread *thread, struct map *map, struct dso *dso, 122 struct symbol *sym, u64 ip, u64 count, char level)
327 struct symbol *sym, u64 ip, char level)
328{ 123{
329 struct rb_node **p = &hist.rb_node; 124 bool hit;
330 struct rb_node *parent = NULL; 125 struct hist_entry *he = __hist_entry__add(thread, map, sym, NULL, ip,
331 struct hist_entry *he; 126 count, level, &hit);
332 struct hist_entry entry = { 127 if (he == NULL)
333 .thread = thread,
334 .map = map,
335 .dso = dso,
336 .sym = sym,
337 .ip = ip,
338 .level = level,
339 .count = 1,
340 };
341 int cmp;
342
343 while (*p != NULL) {
344 parent = *p;
345 he = rb_entry(parent, struct hist_entry, rb_node);
346
347 cmp = hist_entry__cmp(&entry, he);
348
349 if (!cmp) {
350 hist_hit(he, ip);
351
352 return 0;
353 }
354
355 if (cmp < 0)
356 p = &(*p)->rb_left;
357 else
358 p = &(*p)->rb_right;
359 }
360
361 he = malloc(sizeof(*he));
362 if (!he)
363 return -ENOMEM; 128 return -ENOMEM;
364 *he = entry; 129 hist_hit(he, ip);
365 rb_link_node(&he->rb_node, parent, p);
366 rb_insert_color(&he->rb_node, &hist);
367
368 return 0; 130 return 0;
369} 131}
370 132
371static void hist_entry__free(struct hist_entry *he)
372{
373 free(he);
374}
375
376/*
377 * collapse the histogram
378 */
379
380static struct rb_root collapse_hists;
381
382static void collapse__insert_entry(struct hist_entry *he)
383{
384 struct rb_node **p = &collapse_hists.rb_node;
385 struct rb_node *parent = NULL;
386 struct hist_entry *iter;
387 int64_t cmp;
388
389 while (*p != NULL) {
390 parent = *p;
391 iter = rb_entry(parent, struct hist_entry, rb_node);
392
393 cmp = hist_entry__collapse(iter, he);
394
395 if (!cmp) {
396 iter->count += he->count;
397 hist_entry__free(he);
398 return;
399 }
400
401 if (cmp < 0)
402 p = &(*p)->rb_left;
403 else
404 p = &(*p)->rb_right;
405 }
406
407 rb_link_node(&he->rb_node, parent, p);
408 rb_insert_color(&he->rb_node, &collapse_hists);
409}
410
411static void collapse__resort(void)
412{
413 struct rb_node *next;
414 struct hist_entry *n;
415
416 if (!sort__need_collapse)
417 return;
418
419 next = rb_first(&hist);
420 while (next) {
421 n = rb_entry(next, struct hist_entry, rb_node);
422 next = rb_next(&n->rb_node);
423
424 rb_erase(&n->rb_node, &hist);
425 collapse__insert_entry(n);
426 }
427}
428
429/*
430 * reverse the map, sort on count.
431 */
432
433static struct rb_root output_hists;
434
435static void output__insert_entry(struct hist_entry *he)
436{
437 struct rb_node **p = &output_hists.rb_node;
438 struct rb_node *parent = NULL;
439 struct hist_entry *iter;
440
441 while (*p != NULL) {
442 parent = *p;
443 iter = rb_entry(parent, struct hist_entry, rb_node);
444
445 if (he->count > iter->count)
446 p = &(*p)->rb_left;
447 else
448 p = &(*p)->rb_right;
449 }
450
451 rb_link_node(&he->rb_node, parent, p);
452 rb_insert_color(&he->rb_node, &output_hists);
453}
454
455static void output__resort(void)
456{
457 struct rb_node *next;
458 struct hist_entry *n;
459 struct rb_root *tree = &hist;
460
461 if (sort__need_collapse)
462 tree = &collapse_hists;
463
464 next = rb_first(tree);
465
466 while (next) {
467 n = rb_entry(next, struct hist_entry, rb_node);
468 next = rb_next(&n->rb_node);
469
470 rb_erase(&n->rb_node, tree);
471 output__insert_entry(n);
472 }
473}
474
475static unsigned long total = 0,
476 total_mmap = 0,
477 total_comm = 0,
478 total_fork = 0,
479 total_unknown = 0;
480
481static int 133static int
482process_sample_event(event_t *event, unsigned long offset, unsigned long head) 134process_sample_event(event_t *event, unsigned long offset, unsigned long head)
483{ 135{
484 char level; 136 char level;
485 int show = 0;
486 struct dso *dso = NULL;
487 struct thread *thread;
488 u64 ip = event->ip.ip; 137 u64 ip = event->ip.ip;
489 struct map *map = NULL; 138 struct map *map = NULL;
490 139 struct symbol *sym = NULL;
491 thread = threads__findnew(event->ip.pid, &threads, &last_match); 140 struct thread *thread = threads__findnew(event->ip.pid);
492 141
493 dump_printf("%p [%p]: PERF_EVENT (IP, %d): %d: %p\n", 142 dump_printf("%p [%p]: PERF_EVENT (IP, %d): %d: %p\n",
494 (void *)(offset + head), 143 (void *)(offset + head),
@@ -497,60 +146,53 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
497 event->ip.pid, 146 event->ip.pid,
498 (void *)(long)ip); 147 (void *)(long)ip);
499 148
500 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
501
502 if (thread == NULL) { 149 if (thread == NULL) {
503 fprintf(stderr, "problem processing %d event, skipping it.\n", 150 fprintf(stderr, "problem processing %d event, skipping it.\n",
504 event->header.type); 151 event->header.type);
505 return -1; 152 return -1;
506 } 153 }
507 154
155 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
156
508 if (event->header.misc & PERF_RECORD_MISC_KERNEL) { 157 if (event->header.misc & PERF_RECORD_MISC_KERNEL) {
509 show = SHOW_KERNEL;
510 level = 'k'; 158 level = 'k';
511 159 sym = kernel_maps__find_symbol(ip, &map);
512 dso = kernel_dso; 160 dump_printf(" ...... dso: %s\n",
513 161 map ? map->dso->long_name : "<not found>");
514 dump_printf(" ...... dso: %s\n", dso->name);
515
516 } else if (event->header.misc & PERF_RECORD_MISC_USER) { 162 } else if (event->header.misc & PERF_RECORD_MISC_USER) {
517
518 show = SHOW_USER;
519 level = '.'; 163 level = '.';
520
521 map = thread__find_map(thread, ip); 164 map = thread__find_map(thread, ip);
522 if (map != NULL) { 165 if (map != NULL) {
166got_map:
523 ip = map->map_ip(map, ip); 167 ip = map->map_ip(map, ip);
524 dso = map->dso; 168 sym = map->dso->find_symbol(map->dso, ip);
525 } else { 169 } else {
526 /* 170 /*
527 * If this is outside of all known maps, 171 * If this is outside of all known maps,
528 * and is a negative address, try to look it 172 * and is a negative address, try to look it
529 * up in the kernel dso, as it might be a 173 * up in the kernel dso, as it might be a
530 * vsyscall (which executes in user-mode): 174 * vsyscall or vdso (which executes in user-mode).
175 *
176 * XXX This is nasty, we should have a symbol list in
177 * the "[vdso]" dso, but for now lets use the old
178 * trick of looking in the whole kernel symbol list.
531 */ 179 */
532 if ((long long)ip < 0) 180 if ((long long)ip < 0) {
533 dso = kernel_dso; 181 map = kernel_map;
182 goto got_map;
183 }
534 } 184 }
535 dump_printf(" ...... dso: %s\n", dso ? dso->name : "<not found>"); 185 dump_printf(" ...... dso: %s\n",
536 186 map ? map->dso->long_name : "<not found>");
537 } else { 187 } else {
538 show = SHOW_HV;
539 level = 'H'; 188 level = 'H';
540 dump_printf(" ...... dso: [hypervisor]\n"); 189 dump_printf(" ...... dso: [hypervisor]\n");
541 } 190 }
542 191
543 if (show & show_mask) { 192 if (hist_entry__add(thread, map, sym, ip, 1, level)) {
544 struct symbol *sym = NULL; 193 fprintf(stderr, "problem incrementing symbol count, "
545 194 "skipping event\n");
546 if (dso) 195 return -1;
547 sym = dso->find_symbol(dso, ip);
548
549 if (hist_entry__add(thread, map, dso, sym, ip, level)) {
550 fprintf(stderr,
551 "problem incrementing symbol count, skipping event\n");
552 return -1;
553 }
554 } 196 }
555 total++; 197 total++;
556 198
@@ -560,10 +202,9 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
560static int 202static int
561process_mmap_event(event_t *event, unsigned long offset, unsigned long head) 203process_mmap_event(event_t *event, unsigned long offset, unsigned long head)
562{ 204{
563 struct thread *thread; 205 struct map *map = map__new(&event->mmap, NULL, 0,
564 struct map *map = map__new(&event->mmap, NULL, 0); 206 sizeof(struct sym_priv), symbol_filter);
565 207 struct thread *thread = threads__findnew(event->mmap.pid);
566 thread = threads__findnew(event->mmap.pid, &threads, &last_match);
567 208
568 dump_printf("%p [%p]: PERF_RECORD_MMAP %d: [%p(%p) @ %p]: %s\n", 209 dump_printf("%p [%p]: PERF_RECORD_MMAP %d: [%p(%p) @ %p]: %s\n",
569 (void *)(offset + head), 210 (void *)(offset + head),
@@ -588,9 +229,8 @@ process_mmap_event(event_t *event, unsigned long offset, unsigned long head)
588static int 229static int
589process_comm_event(event_t *event, unsigned long offset, unsigned long head) 230process_comm_event(event_t *event, unsigned long offset, unsigned long head)
590{ 231{
591 struct thread *thread; 232 struct thread *thread = threads__findnew(event->comm.pid);
592 233
593 thread = threads__findnew(event->comm.pid, &threads, &last_match);
594 dump_printf("%p [%p]: PERF_RECORD_COMM: %s:%d\n", 234 dump_printf("%p [%p]: PERF_RECORD_COMM: %s:%d\n",
595 (void *)(offset + head), 235 (void *)(offset + head),
596 (void *)(long)(event->header.size), 236 (void *)(long)(event->header.size),
@@ -609,11 +249,9 @@ process_comm_event(event_t *event, unsigned long offset, unsigned long head)
609static int 249static int
610process_fork_event(event_t *event, unsigned long offset, unsigned long head) 250process_fork_event(event_t *event, unsigned long offset, unsigned long head)
611{ 251{
612 struct thread *thread; 252 struct thread *thread = threads__findnew(event->fork.pid);
613 struct thread *parent; 253 struct thread *parent = threads__findnew(event->fork.ppid);
614 254
615 thread = threads__findnew(event->fork.pid, &threads, &last_match);
616 parent = threads__findnew(event->fork.ppid, &threads, &last_match);
617 dump_printf("%p [%p]: PERF_RECORD_FORK: %d:%d\n", 255 dump_printf("%p [%p]: PERF_RECORD_FORK: %d:%d\n",
618 (void *)(offset + head), 256 (void *)(offset + head),
619 (void *)(long)(event->header.size), 257 (void *)(long)(event->header.size),
@@ -665,14 +303,15 @@ process_event(event_t *event, unsigned long offset, unsigned long head)
665 return 0; 303 return 0;
666} 304}
667 305
668static int 306static int parse_line(FILE *file, struct hist_entry *he, u64 len)
669parse_line(FILE *file, struct symbol *sym, u64 start, u64 len)
670{ 307{
308 struct symbol *sym = he->sym;
671 char *line = NULL, *tmp, *tmp2; 309 char *line = NULL, *tmp, *tmp2;
672 static const char *prev_line; 310 static const char *prev_line;
673 static const char *prev_color; 311 static const char *prev_color;
674 unsigned int offset; 312 unsigned int offset;
675 size_t line_len; 313 size_t line_len;
314 u64 start;
676 s64 line_ip; 315 s64 line_ip;
677 int ret; 316 int ret;
678 char *c; 317 char *c;
@@ -709,22 +348,26 @@ parse_line(FILE *file, struct symbol *sym, u64 start, u64 len)
709 line_ip = -1; 348 line_ip = -1;
710 } 349 }
711 350
351 start = he->map->unmap_ip(he->map, sym->start);
352
712 if (line_ip != -1) { 353 if (line_ip != -1) {
713 const char *path = NULL; 354 const char *path = NULL;
714 unsigned int hits = 0; 355 unsigned int hits = 0;
715 double percent = 0.0; 356 double percent = 0.0;
716 const char *color; 357 const char *color;
717 struct sym_ext *sym_ext = sym->priv; 358 struct sym_priv *priv = dso__sym_priv(he->map->dso, sym);
359 struct sym_ext *sym_ext = priv->ext;
360 struct sym_hist *h = priv->hist;
718 361
719 offset = line_ip - start; 362 offset = line_ip - start;
720 if (offset < len) 363 if (offset < len)
721 hits = sym->hist[offset]; 364 hits = h->ip[offset];
722 365
723 if (offset < len && sym_ext) { 366 if (offset < len && sym_ext) {
724 path = sym_ext[offset].path; 367 path = sym_ext[offset].path;
725 percent = sym_ext[offset].percent; 368 percent = sym_ext[offset].percent;
726 } else if (sym->hist_sum) 369 } else if (h->sum)
727 percent = 100.0 * hits / sym->hist_sum; 370 percent = 100.0 * hits / h->sum;
728 371
729 color = get_percent_color(percent); 372 color = get_percent_color(percent);
730 373
@@ -777,9 +420,10 @@ static void insert_source_line(struct sym_ext *sym_ext)
777 rb_insert_color(&sym_ext->node, &root_sym_ext); 420 rb_insert_color(&sym_ext->node, &root_sym_ext);
778} 421}
779 422
780static void free_source_line(struct symbol *sym, int len) 423static void free_source_line(struct hist_entry *he, int len)
781{ 424{
782 struct sym_ext *sym_ext = sym->priv; 425 struct sym_priv *priv = dso__sym_priv(he->map->dso, he->sym);
426 struct sym_ext *sym_ext = priv->ext;
783 int i; 427 int i;
784 428
785 if (!sym_ext) 429 if (!sym_ext)
@@ -789,26 +433,30 @@ static void free_source_line(struct symbol *sym, int len)
789 free(sym_ext[i].path); 433 free(sym_ext[i].path);
790 free(sym_ext); 434 free(sym_ext);
791 435
792 sym->priv = NULL; 436 priv->ext = NULL;
793 root_sym_ext = RB_ROOT; 437 root_sym_ext = RB_ROOT;
794} 438}
795 439
796/* Get the filename:line for the colored entries */ 440/* Get the filename:line for the colored entries */
797static void 441static void
798get_source_line(struct symbol *sym, u64 start, int len, const char *filename) 442get_source_line(struct hist_entry *he, int len, const char *filename)
799{ 443{
444 struct symbol *sym = he->sym;
445 u64 start;
800 int i; 446 int i;
801 char cmd[PATH_MAX * 2]; 447 char cmd[PATH_MAX * 2];
802 struct sym_ext *sym_ext; 448 struct sym_ext *sym_ext;
449 struct sym_priv *priv = dso__sym_priv(he->map->dso, sym);
450 struct sym_hist *h = priv->hist;
803 451
804 if (!sym->hist_sum) 452 if (!h->sum)
805 return; 453 return;
806 454
807 sym->priv = calloc(len, sizeof(struct sym_ext)); 455 sym_ext = priv->ext = calloc(len, sizeof(struct sym_ext));
808 if (!sym->priv) 456 if (!priv->ext)
809 return; 457 return;
810 458
811 sym_ext = sym->priv; 459 start = he->map->unmap_ip(he->map, sym->start);
812 460
813 for (i = 0; i < len; i++) { 461 for (i = 0; i < len; i++) {
814 char *path = NULL; 462 char *path = NULL;
@@ -816,7 +464,7 @@ get_source_line(struct symbol *sym, u64 start, int len, const char *filename)
816 u64 offset; 464 u64 offset;
817 FILE *fp; 465 FILE *fp;
818 466
819 sym_ext[i].percent = 100.0 * sym->hist[i] / sym->hist_sum; 467 sym_ext[i].percent = 100.0 * h->ip[i] / h->sum;
820 if (sym_ext[i].percent <= 0.5) 468 if (sym_ext[i].percent <= 0.5)
821 continue; 469 continue;
822 470
@@ -870,33 +518,34 @@ static void print_summary(const char *filename)
870 } 518 }
871} 519}
872 520
873static void annotate_sym(struct dso *dso, struct symbol *sym) 521static void annotate_sym(struct hist_entry *he)
874{ 522{
875 const char *filename = dso->name, *d_filename; 523 struct map *map = he->map;
876 u64 start, end, len; 524 struct dso *dso = map->dso;
525 struct symbol *sym = he->sym;
526 const char *filename = dso->long_name, *d_filename;
527 u64 len;
877 char command[PATH_MAX*2]; 528 char command[PATH_MAX*2];
878 FILE *file; 529 FILE *file;
879 530
880 if (!filename) 531 if (!filename)
881 return; 532 return;
882 if (sym->module) 533
883 filename = sym->module->path; 534 if (verbose)
884 else if (dso == kernel_dso) 535 fprintf(stderr, "%s: filename=%s, sym=%s, start=%Lx, end=%Lx\n",
885 filename = vmlinux_name; 536 __func__, filename, sym->name,
886 537 map->unmap_ip(map, sym->start),
887 start = sym->obj_start; 538 map->unmap_ip(map, sym->end));
888 if (!start) 539
889 start = sym->start;
890 if (full_paths) 540 if (full_paths)
891 d_filename = filename; 541 d_filename = filename;
892 else 542 else
893 d_filename = basename(filename); 543 d_filename = basename(filename);
894 544
895 end = start + sym->end - sym->start + 1;
896 len = sym->end - sym->start; 545 len = sym->end - sym->start;
897 546
898 if (print_line) { 547 if (print_line) {
899 get_source_line(sym, start, len, filename); 548 get_source_line(he, len, filename);
900 print_summary(filename); 549 print_summary(filename);
901 } 550 }
902 551
@@ -905,10 +554,12 @@ static void annotate_sym(struct dso *dso, struct symbol *sym)
905 printf("------------------------------------------------\n"); 554 printf("------------------------------------------------\n");
906 555
907 if (verbose >= 2) 556 if (verbose >= 2)
908 printf("annotating [%p] %30s : [%p] %30s\n", dso, dso->name, sym, sym->name); 557 printf("annotating [%p] %30s : [%p] %30s\n",
558 dso, dso->long_name, sym, sym->name);
909 559
910 sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s|grep -v %s", 560 sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s|grep -v %s",
911 (u64)start, (u64)end, filename, filename); 561 map->unmap_ip(map, sym->start), map->unmap_ip(map, sym->end),
562 filename, filename);
912 563
913 if (verbose >= 3) 564 if (verbose >= 3)
914 printf("doing: %s\n", command); 565 printf("doing: %s\n", command);
@@ -918,35 +569,38 @@ static void annotate_sym(struct dso *dso, struct symbol *sym)
918 return; 569 return;
919 570
920 while (!feof(file)) { 571 while (!feof(file)) {
921 if (parse_line(file, sym, start, len) < 0) 572 if (parse_line(file, he, len) < 0)
922 break; 573 break;
923 } 574 }
924 575
925 pclose(file); 576 pclose(file);
926 if (print_line) 577 if (print_line)
927 free_source_line(sym, len); 578 free_source_line(he, len);
928} 579}
929 580
930static void find_annotations(void) 581static void find_annotations(void)
931{ 582{
932 struct rb_node *nd; 583 struct rb_node *nd;
933 struct dso *dso;
934 int count = 0;
935 584
936 list_for_each_entry(dso, &dsos, node) { 585 for (nd = rb_first(&output_hists); nd; nd = rb_next(nd)) {
586 struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node);
587 struct sym_priv *priv;
937 588
938 for (nd = rb_first(&dso->syms); nd; nd = rb_next(nd)) { 589 if (he->sym == NULL)
939 struct symbol *sym = rb_entry(nd, struct symbol, rb_node); 590 continue;
940 591
941 if (sym->hist) { 592 priv = dso__sym_priv(he->map->dso, he->sym);
942 annotate_sym(dso, sym); 593 if (priv->hist == NULL)
943 count++; 594 continue;
944 }
945 }
946 }
947 595
948 if (!count) 596 annotate_sym(he);
949 printf(" Error: symbol '%s' not present amongst the samples.\n", sym_hist_filter); 597 /*
598 * Since we have a hist_entry per IP for the same symbol, free
599 * he->sym->hist to signal we already processed this symbol.
600 */
601 free(priv->hist);
602 priv->hist = NULL;
603 }
950} 604}
951 605
952static int __cmd_annotate(void) 606static int __cmd_annotate(void)
@@ -959,7 +613,7 @@ static int __cmd_annotate(void)
959 uint32_t size; 613 uint32_t size;
960 char *buf; 614 char *buf;
961 615
962 register_idle_thread(&threads, &last_match); 616 register_idle_thread();
963 617
964 input = open(input_name, O_RDONLY); 618 input = open(input_name, O_RDONLY);
965 if (input < 0) { 619 if (input < 0) {
@@ -983,7 +637,7 @@ static int __cmd_annotate(void)
983 exit(0); 637 exit(0);
984 } 638 }
985 639
986 if (load_kernel() < 0) { 640 if (load_kernel(sizeof(struct sym_priv), symbol_filter) < 0) {
987 perror("failed to load kernel symbols"); 641 perror("failed to load kernel symbols");
988 return EXIT_FAILURE; 642 return EXIT_FAILURE;
989 } 643 }
@@ -1059,14 +713,14 @@ more:
1059 if (dump_trace) 713 if (dump_trace)
1060 return 0; 714 return 0;
1061 715
1062 if (verbose >= 3) 716 if (verbose > 3)
1063 threads__fprintf(stdout, &threads); 717 threads__fprintf(stdout);
1064 718
1065 if (verbose >= 2) 719 if (verbose > 2)
1066 dsos__fprintf(stdout); 720 dsos__fprintf(stdout);
1067 721
1068 collapse__resort(); 722 collapse__resort();
1069 output__resort(); 723 output__resort(total);
1070 724
1071 find_annotations(); 725 find_annotations();
1072 726
@@ -1134,10 +788,13 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __used)
1134 sym_hist_filter = argv[0]; 788 sym_hist_filter = argv[0];
1135 } 789 }
1136 790
1137 if (!sym_hist_filter)
1138 usage_with_options(annotate_usage, options);
1139
1140 setup_pager(); 791 setup_pager();
1141 792
793 if (field_sep && *field_sep == '.') {
794 fputs("'.' is the only non valid --field-separator argument\n",
795 stderr);
796 exit(129);
797 }
798
1142 return __cmd_annotate(); 799 return __cmd_annotate();
1143} 800}
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 3eeef339c78..ac5ddfff445 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -17,55 +17,51 @@
17#include "util/header.h" 17#include "util/header.h"
18#include "util/event.h" 18#include "util/event.h"
19#include "util/debug.h" 19#include "util/debug.h"
20#include "util/trace-event.h"
21 20
22#include <unistd.h> 21#include <unistd.h>
23#include <sched.h> 22#include <sched.h>
24 23
25#define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a)-1)
26#define __ALIGN_MASK(x, mask) (((x)+(mask))&~(mask))
27
28static int fd[MAX_NR_CPUS][MAX_COUNTERS]; 24static int fd[MAX_NR_CPUS][MAX_COUNTERS];
29 25
30static long default_interval = 100000; 26static long default_interval = 0;
31 27
32static int nr_cpus = 0; 28static int nr_cpus = 0;
33static unsigned int page_size; 29static unsigned int page_size;
34static unsigned int mmap_pages = 128; 30static unsigned int mmap_pages = 128;
35static int freq = 0; 31static int freq = 1000;
36static int output; 32static int output;
37static const char *output_name = "perf.data"; 33static const char *output_name = "perf.data";
38static int group = 0; 34static int group = 0;
39static unsigned int realtime_prio = 0; 35static unsigned int realtime_prio = 0;
40static int raw_samples = 0; 36static int raw_samples = 0;
41static int system_wide = 0; 37static int system_wide = 0;
42static int profile_cpu = -1; 38static int profile_cpu = -1;
43static pid_t target_pid = -1; 39static pid_t target_pid = -1;
44static pid_t child_pid = -1; 40static pid_t child_pid = -1;
45static int inherit = 1; 41static int inherit = 1;
46static int force = 0; 42static int force = 0;
47static int append_file = 0; 43static int append_file = 0;
48static int call_graph = 0; 44static int call_graph = 0;
49static int inherit_stat = 0; 45static int inherit_stat = 0;
50static int no_samples = 0; 46static int no_samples = 0;
51static int sample_address = 0; 47static int sample_address = 0;
52static int multiplex = 0; 48static int multiplex = 0;
53static int multiplex_fd = -1; 49static int multiplex_fd = -1;
54 50
55static long samples; 51static long samples = 0;
56static struct timeval last_read; 52static struct timeval last_read;
57static struct timeval this_read; 53static struct timeval this_read;
58 54
59static u64 bytes_written; 55static u64 bytes_written = 0;
60 56
61static struct pollfd event_array[MAX_NR_CPUS * MAX_COUNTERS]; 57static struct pollfd event_array[MAX_NR_CPUS * MAX_COUNTERS];
62 58
63static int nr_poll; 59static int nr_poll = 0;
64static int nr_cpu; 60static int nr_cpu = 0;
65 61
66static int file_new = 1; 62static int file_new = 1;
67 63
68struct perf_header *header; 64struct perf_header *header = NULL;
69 65
70struct mmap_data { 66struct mmap_data {
71 int counter; 67 int counter;
@@ -375,9 +371,11 @@ static struct perf_header_attr *get_header_attr(struct perf_event_attr *a, int n
375 371
376static void create_counter(int counter, int cpu, pid_t pid) 372static void create_counter(int counter, int cpu, pid_t pid)
377{ 373{
374 char *filter = filters[counter];
378 struct perf_event_attr *attr = attrs + counter; 375 struct perf_event_attr *attr = attrs + counter;
379 struct perf_header_attr *h_attr; 376 struct perf_header_attr *h_attr;
380 int track = !counter; /* only the first counter needs these */ 377 int track = !counter; /* only the first counter needs these */
378 int ret;
381 struct { 379 struct {
382 u64 count; 380 u64 count;
383 u64 time_enabled; 381 u64 time_enabled;
@@ -480,7 +478,6 @@ try_again:
480 multiplex_fd = fd[nr_cpu][counter]; 478 multiplex_fd = fd[nr_cpu][counter];
481 479
482 if (multiplex && fd[nr_cpu][counter] != multiplex_fd) { 480 if (multiplex && fd[nr_cpu][counter] != multiplex_fd) {
483 int ret;
484 481
485 ret = ioctl(fd[nr_cpu][counter], PERF_EVENT_IOC_SET_OUTPUT, multiplex_fd); 482 ret = ioctl(fd[nr_cpu][counter], PERF_EVENT_IOC_SET_OUTPUT, multiplex_fd);
486 assert(ret != -1); 483 assert(ret != -1);
@@ -500,6 +497,16 @@ try_again:
500 } 497 }
501 } 498 }
502 499
500 if (filter != NULL) {
501 ret = ioctl(fd[nr_cpu][counter],
502 PERF_EVENT_IOC_SET_FILTER, filter);
503 if (ret) {
504 error("failed to set filter with %d (%s)\n", errno,
505 strerror(errno));
506 exit(-1);
507 }
508 }
509
503 ioctl(fd[nr_cpu][counter], PERF_EVENT_IOC_ENABLE); 510 ioctl(fd[nr_cpu][counter], PERF_EVENT_IOC_ENABLE);
504} 511}
505 512
@@ -566,17 +573,17 @@ static int __cmd_record(int argc, const char **argv)
566 else 573 else
567 header = perf_header__new(); 574 header = perf_header__new();
568 575
569
570 if (raw_samples) { 576 if (raw_samples) {
571 read_tracing_data(attrs, nr_counters); 577 perf_header__feat_trace_info(header);
572 } else { 578 } else {
573 for (i = 0; i < nr_counters; i++) { 579 for (i = 0; i < nr_counters; i++) {
574 if (attrs[i].sample_type & PERF_SAMPLE_RAW) { 580 if (attrs[i].sample_type & PERF_SAMPLE_RAW) {
575 read_tracing_data(attrs, nr_counters); 581 perf_header__feat_trace_info(header);
576 break; 582 break;
577 } 583 }
578 } 584 }
579 } 585 }
586
580 atexit(atexit_header); 587 atexit(atexit_header);
581 588
582 if (!system_wide) { 589 if (!system_wide) {
@@ -623,7 +630,7 @@ static int __cmd_record(int argc, const char **argv)
623 630
624 param.sched_priority = realtime_prio; 631 param.sched_priority = realtime_prio;
625 if (sched_setscheduler(0, SCHED_FIFO, &param)) { 632 if (sched_setscheduler(0, SCHED_FIFO, &param)) {
626 printf("Could not set realtime priority.\n"); 633 pr_err("Could not set realtime priority.\n");
627 exit(-1); 634 exit(-1);
628 } 635 }
629 } 636 }
@@ -677,6 +684,8 @@ static const struct option options[] = {
677 OPT_CALLBACK('e', "event", NULL, "event", 684 OPT_CALLBACK('e', "event", NULL, "event",
678 "event selector. use 'perf list' to list available events", 685 "event selector. use 'perf list' to list available events",
679 parse_events), 686 parse_events),
687 OPT_CALLBACK(0, "filter", NULL, "filter",
688 "event filter", parse_filter),
680 OPT_INTEGER('p', "pid", &target_pid, 689 OPT_INTEGER('p', "pid", &target_pid,
681 "record events on existing pid"), 690 "record events on existing pid"),
682 OPT_INTEGER('r', "realtime", &realtime_prio, 691 OPT_INTEGER('r', "realtime", &realtime_prio,
@@ -731,6 +740,18 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
731 attrs[0].config = PERF_COUNT_HW_CPU_CYCLES; 740 attrs[0].config = PERF_COUNT_HW_CPU_CYCLES;
732 } 741 }
733 742
743 /*
744 * User specified count overrides default frequency.
745 */
746 if (default_interval)
747 freq = 0;
748 else if (freq) {
749 default_interval = freq;
750 } else {
751 fprintf(stderr, "frequency and count are zero, aborting\n");
752 exit(EXIT_FAILURE);
753 }
754
734 for (counter = 0; counter < nr_counters; counter++) { 755 for (counter = 0; counter < nr_counters; counter++) {
735 if (attrs[counter].sample_period) 756 if (attrs[counter].sample_period)
736 continue; 757 continue;
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 19669c20088..b3d814b5455 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -26,20 +26,18 @@
26#include "util/parse-options.h" 26#include "util/parse-options.h"
27#include "util/parse-events.h" 27#include "util/parse-events.h"
28 28
29#include "util/data_map.h"
29#include "util/thread.h" 30#include "util/thread.h"
31#include "util/sort.h"
32#include "util/hist.h"
30 33
31static char const *input_name = "perf.data"; 34static char const *input_name = "perf.data";
32 35
33static char default_sort_order[] = "comm,dso,symbol";
34static char *sort_order = default_sort_order;
35static char *dso_list_str, *comm_list_str, *sym_list_str, 36static char *dso_list_str, *comm_list_str, *sym_list_str,
36 *col_width_list_str; 37 *col_width_list_str;
37static struct strlist *dso_list, *comm_list, *sym_list; 38static struct strlist *dso_list, *comm_list, *sym_list;
38static char *field_sep;
39 39
40static int force; 40static int force;
41static int input;
42static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV;
43 41
44static int full_paths; 42static int full_paths;
45static int show_nr_samples; 43static int show_nr_samples;
@@ -50,374 +48,39 @@ static struct perf_read_values show_threads_values;
50static char default_pretty_printing_style[] = "normal"; 48static char default_pretty_printing_style[] = "normal";
51static char *pretty_printing_style = default_pretty_printing_style; 49static char *pretty_printing_style = default_pretty_printing_style;
52 50
53static unsigned long page_size;
54static unsigned long mmap_window = 32;
55
56static char default_parent_pattern[] = "^sys_|^do_page_fault";
57static char *parent_pattern = default_parent_pattern;
58static regex_t parent_regex;
59
60static int exclude_other = 1; 51static int exclude_other = 1;
61 52
62static char callchain_default_opt[] = "fractal,0.5"; 53static char callchain_default_opt[] = "fractal,0.5";
63 54
64static int callchain; 55static char *cwd;
65
66static char __cwd[PATH_MAX];
67static char *cwd = __cwd;
68static int cwdlen; 56static int cwdlen;
69 57
70static struct rb_root threads;
71static struct thread *last_match;
72
73static struct perf_header *header; 58static struct perf_header *header;
74 59
75static
76struct callchain_param callchain_param = {
77 .mode = CHAIN_GRAPH_REL,
78 .min_percent = 0.5
79};
80
81static u64 sample_type; 60static u64 sample_type;
82 61
83static int repsep_fprintf(FILE *fp, const char *fmt, ...)
84{
85 int n;
86 va_list ap;
87
88 va_start(ap, fmt);
89 if (!field_sep)
90 n = vfprintf(fp, fmt, ap);
91 else {
92 char *bf = NULL;
93 n = vasprintf(&bf, fmt, ap);
94 if (n > 0) {
95 char *sep = bf;
96
97 while (1) {
98 sep = strchr(sep, *field_sep);
99 if (sep == NULL)
100 break;
101 *sep = '.';
102 }
103 }
104 fputs(bf, fp);
105 free(bf);
106 }
107 va_end(ap);
108 return n;
109}
110
111static unsigned int dsos__col_width,
112 comms__col_width,
113 threads__col_width;
114
115/*
116 * histogram, sorted on item, collects counts
117 */
118
119static struct rb_root hist;
120
121struct hist_entry {
122 struct rb_node rb_node;
123
124 struct thread *thread;
125 struct map *map;
126 struct dso *dso;
127 struct symbol *sym;
128 struct symbol *parent;
129 u64 ip;
130 char level;
131 struct callchain_node callchain;
132 struct rb_root sorted_chain;
133
134 u64 count;
135};
136
137/*
138 * configurable sorting bits
139 */
140
141struct sort_entry {
142 struct list_head list;
143
144 const char *header;
145
146 int64_t (*cmp)(struct hist_entry *, struct hist_entry *);
147 int64_t (*collapse)(struct hist_entry *, struct hist_entry *);
148 size_t (*print)(FILE *fp, struct hist_entry *, unsigned int width);
149 unsigned int *width;
150 bool elide;
151};
152
153static int64_t cmp_null(void *l, void *r)
154{
155 if (!l && !r)
156 return 0;
157 else if (!l)
158 return -1;
159 else
160 return 1;
161}
162
163/* --sort pid */
164
165static int64_t
166sort__thread_cmp(struct hist_entry *left, struct hist_entry *right)
167{
168 return right->thread->pid - left->thread->pid;
169}
170
171static size_t
172sort__thread_print(FILE *fp, struct hist_entry *self, unsigned int width)
173{
174 return repsep_fprintf(fp, "%*s:%5d", width - 6,
175 self->thread->comm ?: "", self->thread->pid);
176}
177
178static struct sort_entry sort_thread = {
179 .header = "Command: Pid",
180 .cmp = sort__thread_cmp,
181 .print = sort__thread_print,
182 .width = &threads__col_width,
183};
184
185/* --sort comm */
186
187static int64_t
188sort__comm_cmp(struct hist_entry *left, struct hist_entry *right)
189{
190 return right->thread->pid - left->thread->pid;
191}
192
193static int64_t
194sort__comm_collapse(struct hist_entry *left, struct hist_entry *right)
195{
196 char *comm_l = left->thread->comm;
197 char *comm_r = right->thread->comm;
198
199 if (!comm_l || !comm_r)
200 return cmp_null(comm_l, comm_r);
201
202 return strcmp(comm_l, comm_r);
203}
204
205static size_t
206sort__comm_print(FILE *fp, struct hist_entry *self, unsigned int width)
207{
208 return repsep_fprintf(fp, "%*s", width, self->thread->comm);
209}
210
211static struct sort_entry sort_comm = {
212 .header = "Command",
213 .cmp = sort__comm_cmp,
214 .collapse = sort__comm_collapse,
215 .print = sort__comm_print,
216 .width = &comms__col_width,
217};
218
219/* --sort dso */
220
221static int64_t
222sort__dso_cmp(struct hist_entry *left, struct hist_entry *right)
223{
224 struct dso *dso_l = left->dso;
225 struct dso *dso_r = right->dso;
226
227 if (!dso_l || !dso_r)
228 return cmp_null(dso_l, dso_r);
229
230 return strcmp(dso_l->name, dso_r->name);
231}
232
233static size_t
234sort__dso_print(FILE *fp, struct hist_entry *self, unsigned int width)
235{
236 if (self->dso)
237 return repsep_fprintf(fp, "%-*s", width, self->dso->name);
238
239 return repsep_fprintf(fp, "%*llx", width, (u64)self->ip);
240}
241
242static struct sort_entry sort_dso = {
243 .header = "Shared Object",
244 .cmp = sort__dso_cmp,
245 .print = sort__dso_print,
246 .width = &dsos__col_width,
247};
248
249/* --sort symbol */
250
251static int64_t
252sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
253{
254 u64 ip_l, ip_r;
255
256 if (left->sym == right->sym)
257 return 0;
258
259 ip_l = left->sym ? left->sym->start : left->ip;
260 ip_r = right->sym ? right->sym->start : right->ip;
261
262 return (int64_t)(ip_r - ip_l);
263}
264 62
265static size_t 63static size_t
266sort__sym_print(FILE *fp, struct hist_entry *self, unsigned int width __used) 64callchain__fprintf_left_margin(FILE *fp, int left_margin)
267{ 65{
268 size_t ret = 0; 66 int i;
67 int ret;
269 68
270 if (verbose) 69 ret = fprintf(fp, " ");
271 ret += repsep_fprintf(fp, "%#018llx %c ", (u64)self->ip,
272 dso__symtab_origin(self->dso));
273 70
274 ret += repsep_fprintf(fp, "[%c] ", self->level); 71 for (i = 0; i < left_margin; i++)
275 if (self->sym) { 72 ret += fprintf(fp, " ");
276 ret += repsep_fprintf(fp, "%s", self->sym->name);
277
278 if (self->sym->module)
279 ret += repsep_fprintf(fp, "\t[%s]",
280 self->sym->module->name);
281 } else {
282 ret += repsep_fprintf(fp, "%#016llx", (u64)self->ip);
283 }
284 73
285 return ret; 74 return ret;
286} 75}
287 76
288static struct sort_entry sort_sym = { 77static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask,
289 .header = "Symbol", 78 int left_margin)
290 .cmp = sort__sym_cmp,
291 .print = sort__sym_print,
292};
293
294/* --sort parent */
295
296static int64_t
297sort__parent_cmp(struct hist_entry *left, struct hist_entry *right)
298{
299 struct symbol *sym_l = left->parent;
300 struct symbol *sym_r = right->parent;
301
302 if (!sym_l || !sym_r)
303 return cmp_null(sym_l, sym_r);
304
305 return strcmp(sym_l->name, sym_r->name);
306}
307
308static size_t
309sort__parent_print(FILE *fp, struct hist_entry *self, unsigned int width)
310{
311 return repsep_fprintf(fp, "%-*s", width,
312 self->parent ? self->parent->name : "[other]");
313}
314
315static unsigned int parent_symbol__col_width;
316
317static struct sort_entry sort_parent = {
318 .header = "Parent symbol",
319 .cmp = sort__parent_cmp,
320 .print = sort__parent_print,
321 .width = &parent_symbol__col_width,
322};
323
324static int sort__need_collapse = 0;
325static int sort__has_parent = 0;
326
327struct sort_dimension {
328 const char *name;
329 struct sort_entry *entry;
330 int taken;
331};
332
333static struct sort_dimension sort_dimensions[] = {
334 { .name = "pid", .entry = &sort_thread, },
335 { .name = "comm", .entry = &sort_comm, },
336 { .name = "dso", .entry = &sort_dso, },
337 { .name = "symbol", .entry = &sort_sym, },
338 { .name = "parent", .entry = &sort_parent, },
339};
340
341static LIST_HEAD(hist_entry__sort_list);
342
343static int sort_dimension__add(const char *tok)
344{
345 unsigned int i;
346
347 for (i = 0; i < ARRAY_SIZE(sort_dimensions); i++) {
348 struct sort_dimension *sd = &sort_dimensions[i];
349
350 if (sd->taken)
351 continue;
352
353 if (strncasecmp(tok, sd->name, strlen(tok)))
354 continue;
355
356 if (sd->entry->collapse)
357 sort__need_collapse = 1;
358
359 if (sd->entry == &sort_parent) {
360 int ret = regcomp(&parent_regex, parent_pattern, REG_EXTENDED);
361 if (ret) {
362 char err[BUFSIZ];
363
364 regerror(ret, &parent_regex, err, sizeof(err));
365 fprintf(stderr, "Invalid regex: %s\n%s",
366 parent_pattern, err);
367 exit(-1);
368 }
369 sort__has_parent = 1;
370 }
371
372 list_add_tail(&sd->entry->list, &hist_entry__sort_list);
373 sd->taken = 1;
374
375 return 0;
376 }
377
378 return -ESRCH;
379}
380
381static int64_t
382hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)
383{
384 struct sort_entry *se;
385 int64_t cmp = 0;
386
387 list_for_each_entry(se, &hist_entry__sort_list, list) {
388 cmp = se->cmp(left, right);
389 if (cmp)
390 break;
391 }
392
393 return cmp;
394}
395
396static int64_t
397hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
398{
399 struct sort_entry *se;
400 int64_t cmp = 0;
401
402 list_for_each_entry(se, &hist_entry__sort_list, list) {
403 int64_t (*f)(struct hist_entry *, struct hist_entry *);
404
405 f = se->collapse ?: se->cmp;
406
407 cmp = f(left, right);
408 if (cmp)
409 break;
410 }
411
412 return cmp;
413}
414
415static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask)
416{ 79{
417 int i; 80 int i;
418 size_t ret = 0; 81 size_t ret = 0;
419 82
420 ret += fprintf(fp, "%s", " "); 83 ret += callchain__fprintf_left_margin(fp, left_margin);
421 84
422 for (i = 0; i < depth; i++) 85 for (i = 0; i < depth; i++)
423 if (depth_mask & (1 << i)) 86 if (depth_mask & (1 << i))
@@ -432,12 +95,12 @@ static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask)
432static size_t 95static size_t
433ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain, int depth, 96ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain, int depth,
434 int depth_mask, int count, u64 total_samples, 97 int depth_mask, int count, u64 total_samples,
435 int hits) 98 int hits, int left_margin)
436{ 99{
437 int i; 100 int i;
438 size_t ret = 0; 101 size_t ret = 0;
439 102
440 ret += fprintf(fp, "%s", " "); 103 ret += callchain__fprintf_left_margin(fp, left_margin);
441 for (i = 0; i < depth; i++) { 104 for (i = 0; i < depth; i++) {
442 if (depth_mask & (1 << i)) 105 if (depth_mask & (1 << i))
443 ret += fprintf(fp, "|"); 106 ret += fprintf(fp, "|");
@@ -475,8 +138,9 @@ static void init_rem_hits(void)
475} 138}
476 139
477static size_t 140static size_t
478callchain__fprintf_graph(FILE *fp, struct callchain_node *self, 141__callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
479 u64 total_samples, int depth, int depth_mask) 142 u64 total_samples, int depth, int depth_mask,
143 int left_margin)
480{ 144{
481 struct rb_node *node, *next; 145 struct rb_node *node, *next;
482 struct callchain_node *child; 146 struct callchain_node *child;
@@ -517,7 +181,8 @@ callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
517 * But we keep the older depth mask for the line seperator 181 * But we keep the older depth mask for the line seperator
518 * to keep the level link until we reach the last child 182 * to keep the level link until we reach the last child
519 */ 183 */
520 ret += ipchain__fprintf_graph_line(fp, depth, depth_mask); 184 ret += ipchain__fprintf_graph_line(fp, depth, depth_mask,
185 left_margin);
521 i = 0; 186 i = 0;
522 list_for_each_entry(chain, &child->val, list) { 187 list_for_each_entry(chain, &child->val, list) {
523 if (chain->ip >= PERF_CONTEXT_MAX) 188 if (chain->ip >= PERF_CONTEXT_MAX)
@@ -525,11 +190,13 @@ callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
525 ret += ipchain__fprintf_graph(fp, chain, depth, 190 ret += ipchain__fprintf_graph(fp, chain, depth,
526 new_depth_mask, i++, 191 new_depth_mask, i++,
527 new_total, 192 new_total,
528 cumul); 193 cumul,
194 left_margin);
529 } 195 }
530 ret += callchain__fprintf_graph(fp, child, new_total, 196 ret += __callchain__fprintf_graph(fp, child, new_total,
531 depth + 1, 197 depth + 1,
532 new_depth_mask | (1 << depth)); 198 new_depth_mask | (1 << depth),
199 left_margin);
533 node = next; 200 node = next;
534 } 201 }
535 202
@@ -543,12 +210,51 @@ callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
543 210
544 ret += ipchain__fprintf_graph(fp, &rem_hits, depth, 211 ret += ipchain__fprintf_graph(fp, &rem_hits, depth,
545 new_depth_mask, 0, new_total, 212 new_depth_mask, 0, new_total,
546 remaining); 213 remaining, left_margin);
547 } 214 }
548 215
549 return ret; 216 return ret;
550} 217}
551 218
219
220static size_t
221callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
222 u64 total_samples, int left_margin)
223{
224 struct callchain_list *chain;
225 bool printed = false;
226 int i = 0;
227 int ret = 0;
228
229 list_for_each_entry(chain, &self->val, list) {
230 if (chain->ip >= PERF_CONTEXT_MAX)
231 continue;
232
233 if (!i++ && sort__first_dimension == SORT_SYM)
234 continue;
235
236 if (!printed) {
237 ret += callchain__fprintf_left_margin(fp, left_margin);
238 ret += fprintf(fp, "|\n");
239 ret += callchain__fprintf_left_margin(fp, left_margin);
240 ret += fprintf(fp, "---");
241
242 left_margin += 3;
243 printed = true;
244 } else
245 ret += callchain__fprintf_left_margin(fp, left_margin);
246
247 if (chain->sym)
248 ret += fprintf(fp, " %s\n", chain->sym->name);
249 else
250 ret += fprintf(fp, " %p\n", (void *)(long)chain->ip);
251 }
252
253 ret += __callchain__fprintf_graph(fp, self, total_samples, 1, 1, left_margin);
254
255 return ret;
256}
257
552static size_t 258static size_t
553callchain__fprintf_flat(FILE *fp, struct callchain_node *self, 259callchain__fprintf_flat(FILE *fp, struct callchain_node *self,
554 u64 total_samples) 260 u64 total_samples)
@@ -577,7 +283,7 @@ callchain__fprintf_flat(FILE *fp, struct callchain_node *self,
577 283
578static size_t 284static size_t
579hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self, 285hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self,
580 u64 total_samples) 286 u64 total_samples, int left_margin)
581{ 287{
582 struct rb_node *rb_node; 288 struct rb_node *rb_node;
583 struct callchain_node *chain; 289 struct callchain_node *chain;
@@ -597,8 +303,8 @@ hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self,
597 break; 303 break;
598 case CHAIN_GRAPH_ABS: /* Falldown */ 304 case CHAIN_GRAPH_ABS: /* Falldown */
599 case CHAIN_GRAPH_REL: 305 case CHAIN_GRAPH_REL:
600 ret += callchain__fprintf_graph(fp, chain, 306 ret += callchain__fprintf_graph(fp, chain, total_samples,
601 total_samples, 1, 1); 307 left_margin);
602 case CHAIN_NONE: 308 case CHAIN_NONE:
603 default: 309 default:
604 break; 310 break;
@@ -610,7 +316,6 @@ hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self,
610 return ret; 316 return ret;
611} 317}
612 318
613
614static size_t 319static size_t
615hist_entry__fprintf(FILE *fp, struct hist_entry *self, u64 total_samples) 320hist_entry__fprintf(FILE *fp, struct hist_entry *self, u64 total_samples)
616{ 321{
@@ -644,8 +349,19 @@ hist_entry__fprintf(FILE *fp, struct hist_entry *self, u64 total_samples)
644 349
645 ret += fprintf(fp, "\n"); 350 ret += fprintf(fp, "\n");
646 351
647 if (callchain) 352 if (callchain) {
648 hist_entry_callchain__fprintf(fp, self, total_samples); 353 int left_margin = 0;
354
355 if (sort__first_dimension == SORT_COMM) {
356 se = list_first_entry(&hist_entry__sort_list, typeof(*se),
357 list);
358 left_margin = se->width ? *se->width : 0;
359 left_margin -= thread__comm_len(self->thread);
360 }
361
362 hist_entry_callchain__fprintf(fp, self, total_samples,
363 left_margin);
364 }
649 365
650 return ret; 366 return ret;
651} 367}
@@ -695,22 +411,17 @@ static int thread__set_comm_adjust(struct thread *self, const char *comm)
695 411
696 412
697static struct symbol * 413static struct symbol *
698resolve_symbol(struct thread *thread, struct map **mapp, 414resolve_symbol(struct thread *thread, struct map **mapp, u64 *ipp)
699 struct dso **dsop, u64 *ipp)
700{ 415{
701 struct dso *dso = dsop ? *dsop : NULL;
702 struct map *map = mapp ? *mapp : NULL; 416 struct map *map = mapp ? *mapp : NULL;
703 u64 ip = *ipp; 417 u64 ip = *ipp;
704 418
705 if (!thread)
706 return NULL;
707
708 if (dso)
709 goto got_dso;
710
711 if (map) 419 if (map)
712 goto got_map; 420 goto got_map;
713 421
422 if (!thread)
423 return NULL;
424
714 map = thread__find_map(thread, ip); 425 map = thread__find_map(thread, ip);
715 if (map != NULL) { 426 if (map != NULL) {
716 /* 427 /*
@@ -725,29 +436,26 @@ resolve_symbol(struct thread *thread, struct map **mapp,
725 *mapp = map; 436 *mapp = map;
726got_map: 437got_map:
727 ip = map->map_ip(map, ip); 438 ip = map->map_ip(map, ip);
728
729 dso = map->dso;
730 } else { 439 } else {
731 /* 440 /*
732 * If this is outside of all known maps, 441 * If this is outside of all known maps,
733 * and is a negative address, try to look it 442 * and is a negative address, try to look it
734 * up in the kernel dso, as it might be a 443 * up in the kernel dso, as it might be a
735 * vsyscall (which executes in user-mode): 444 * vsyscall or vdso (which executes in user-mode).
445 *
446 * XXX This is nasty, we should have a symbol list in
447 * the "[vdso]" dso, but for now lets use the old
448 * trick of looking in the whole kernel symbol list.
736 */ 449 */
737 if ((long long)ip < 0) 450 if ((long long)ip < 0)
738 dso = kernel_dso; 451 return kernel_maps__find_symbol(ip, mapp);
739 } 452 }
740 dump_printf(" ...... dso: %s\n", dso ? dso->name : "<not found>"); 453 dump_printf(" ...... dso: %s\n",
454 map ? map->dso->long_name : "<not found>");
741 dump_printf(" ...... map: %Lx -> %Lx\n", *ipp, ip); 455 dump_printf(" ...... map: %Lx -> %Lx\n", *ipp, ip);
742 *ipp = ip; 456 *ipp = ip;
743 457
744 if (dsop) 458 return map ? map->dso->find_symbol(map->dso, ip) : NULL;
745 *dsop = dso;
746
747 if (!dso)
748 return NULL;
749got_dso:
750 return dso->find_symbol(dso, ip);
751} 459}
752 460
753static int call__match(struct symbol *sym) 461static int call__match(struct symbol *sym)
@@ -758,9 +466,9 @@ static int call__match(struct symbol *sym)
758 return 0; 466 return 0;
759} 467}
760 468
761static struct symbol ** 469static struct symbol **resolve_callchain(struct thread *thread, struct map *map,
762resolve_callchain(struct thread *thread, struct map *map __used, 470 struct ip_callchain *chain,
763 struct ip_callchain *chain, struct hist_entry *entry) 471 struct symbol **parent)
764{ 472{
765 u64 context = PERF_CONTEXT_MAX; 473 u64 context = PERF_CONTEXT_MAX;
766 struct symbol **syms = NULL; 474 struct symbol **syms = NULL;
@@ -776,8 +484,7 @@ resolve_callchain(struct thread *thread, struct map *map __used,
776 484
777 for (i = 0; i < chain->nr; i++) { 485 for (i = 0; i < chain->nr; i++) {
778 u64 ip = chain->ips[i]; 486 u64 ip = chain->ips[i];
779 struct dso *dso = NULL; 487 struct symbol *sym = NULL;
780 struct symbol *sym;
781 488
782 if (ip >= PERF_CONTEXT_MAX) { 489 if (ip >= PERF_CONTEXT_MAX) {
783 context = ip; 490 context = ip;
@@ -786,21 +493,18 @@ resolve_callchain(struct thread *thread, struct map *map __used,
786 493
787 switch (context) { 494 switch (context) {
788 case PERF_CONTEXT_HV: 495 case PERF_CONTEXT_HV:
789 dso = hypervisor_dso;
790 break; 496 break;
791 case PERF_CONTEXT_KERNEL: 497 case PERF_CONTEXT_KERNEL:
792 dso = kernel_dso; 498 sym = kernel_maps__find_symbol(ip, &map);
793 break; 499 break;
794 default: 500 default:
501 sym = resolve_symbol(thread, &map, &ip);
795 break; 502 break;
796 } 503 }
797 504
798 sym = resolve_symbol(thread, NULL, &dso, &ip);
799
800 if (sym) { 505 if (sym) {
801 if (sort__has_parent && call__match(sym) && 506 if (sort__has_parent && !*parent && call__match(sym))
802 !entry->parent) 507 *parent = sym;
803 entry->parent = sym;
804 if (!callchain) 508 if (!callchain)
805 break; 509 break;
806 syms[i] = sym; 510 syms[i] = sym;
@@ -815,177 +519,35 @@ resolve_callchain(struct thread *thread, struct map *map __used,
815 */ 519 */
816 520
817static int 521static int
818hist_entry__add(struct thread *thread, struct map *map, struct dso *dso, 522hist_entry__add(struct thread *thread, struct map *map,
819 struct symbol *sym, u64 ip, struct ip_callchain *chain, 523 struct symbol *sym, u64 ip, struct ip_callchain *chain,
820 char level, u64 count) 524 char level, u64 count)
821{ 525{
822 struct rb_node **p = &hist.rb_node; 526 struct symbol **syms = NULL, *parent = NULL;
823 struct rb_node *parent = NULL; 527 bool hit;
824 struct hist_entry *he; 528 struct hist_entry *he;
825 struct symbol **syms = NULL;
826 struct hist_entry entry = {
827 .thread = thread,
828 .map = map,
829 .dso = dso,
830 .sym = sym,
831 .ip = ip,
832 .level = level,
833 .count = count,
834 .parent = NULL,
835 .sorted_chain = RB_ROOT
836 };
837 int cmp;
838 529
839 if ((sort__has_parent || callchain) && chain) 530 if ((sort__has_parent || callchain) && chain)
840 syms = resolve_callchain(thread, map, chain, &entry); 531 syms = resolve_callchain(thread, map, chain, &parent);
841
842 while (*p != NULL) {
843 parent = *p;
844 he = rb_entry(parent, struct hist_entry, rb_node);
845
846 cmp = hist_entry__cmp(&entry, he);
847 532
848 if (!cmp) { 533 he = __hist_entry__add(thread, map, sym, parent,
849 he->count += count; 534 ip, count, level, &hit);
850 if (callchain) { 535 if (he == NULL)
851 append_chain(&he->callchain, chain, syms); 536 return -ENOMEM;
852 free(syms);
853 }
854 return 0;
855 }
856 537
857 if (cmp < 0) 538 if (hit)
858 p = &(*p)->rb_left; 539 he->count += count;
859 else
860 p = &(*p)->rb_right;
861 }
862 540
863 he = malloc(sizeof(*he));
864 if (!he)
865 return -ENOMEM;
866 *he = entry;
867 if (callchain) { 541 if (callchain) {
868 callchain_init(&he->callchain); 542 if (!hit)
543 callchain_init(&he->callchain);
869 append_chain(&he->callchain, chain, syms); 544 append_chain(&he->callchain, chain, syms);
870 free(syms); 545 free(syms);
871 } 546 }
872 rb_link_node(&he->rb_node, parent, p);
873 rb_insert_color(&he->rb_node, &hist);
874 547
875 return 0; 548 return 0;
876} 549}
877 550
878static void hist_entry__free(struct hist_entry *he)
879{
880 free(he);
881}
882
883/*
884 * collapse the histogram
885 */
886
887static struct rb_root collapse_hists;
888
889static void collapse__insert_entry(struct hist_entry *he)
890{
891 struct rb_node **p = &collapse_hists.rb_node;
892 struct rb_node *parent = NULL;
893 struct hist_entry *iter;
894 int64_t cmp;
895
896 while (*p != NULL) {
897 parent = *p;
898 iter = rb_entry(parent, struct hist_entry, rb_node);
899
900 cmp = hist_entry__collapse(iter, he);
901
902 if (!cmp) {
903 iter->count += he->count;
904 hist_entry__free(he);
905 return;
906 }
907
908 if (cmp < 0)
909 p = &(*p)->rb_left;
910 else
911 p = &(*p)->rb_right;
912 }
913
914 rb_link_node(&he->rb_node, parent, p);
915 rb_insert_color(&he->rb_node, &collapse_hists);
916}
917
918static void collapse__resort(void)
919{
920 struct rb_node *next;
921 struct hist_entry *n;
922
923 if (!sort__need_collapse)
924 return;
925
926 next = rb_first(&hist);
927 while (next) {
928 n = rb_entry(next, struct hist_entry, rb_node);
929 next = rb_next(&n->rb_node);
930
931 rb_erase(&n->rb_node, &hist);
932 collapse__insert_entry(n);
933 }
934}
935
936/*
937 * reverse the map, sort on count.
938 */
939
940static struct rb_root output_hists;
941
942static void output__insert_entry(struct hist_entry *he, u64 min_callchain_hits)
943{
944 struct rb_node **p = &output_hists.rb_node;
945 struct rb_node *parent = NULL;
946 struct hist_entry *iter;
947
948 if (callchain)
949 callchain_param.sort(&he->sorted_chain, &he->callchain,
950 min_callchain_hits, &callchain_param);
951
952 while (*p != NULL) {
953 parent = *p;
954 iter = rb_entry(parent, struct hist_entry, rb_node);
955
956 if (he->count > iter->count)
957 p = &(*p)->rb_left;
958 else
959 p = &(*p)->rb_right;
960 }
961
962 rb_link_node(&he->rb_node, parent, p);
963 rb_insert_color(&he->rb_node, &output_hists);
964}
965
966static void output__resort(u64 total_samples)
967{
968 struct rb_node *next;
969 struct hist_entry *n;
970 struct rb_root *tree = &hist;
971 u64 min_callchain_hits;
972
973 min_callchain_hits = total_samples * (callchain_param.min_percent / 100);
974
975 if (sort__need_collapse)
976 tree = &collapse_hists;
977
978 next = rb_first(tree);
979
980 while (next) {
981 n = rb_entry(next, struct hist_entry, rb_node);
982 next = rb_next(&n->rb_node);
983
984 rb_erase(&n->rb_node, tree);
985 output__insert_entry(n, min_callchain_hits);
986 }
987}
988
989static size_t output__fprintf(FILE *fp, u64 total_samples) 551static size_t output__fprintf(FILE *fp, u64 total_samples)
990{ 552{
991 struct hist_entry *pos; 553 struct hist_entry *pos;
@@ -1080,13 +642,6 @@ print_entries:
1080 return ret; 642 return ret;
1081} 643}
1082 644
1083static unsigned long total = 0,
1084 total_mmap = 0,
1085 total_comm = 0,
1086 total_fork = 0,
1087 total_unknown = 0,
1088 total_lost = 0;
1089
1090static int validate_chain(struct ip_callchain *chain, event_t *event) 645static int validate_chain(struct ip_callchain *chain, event_t *event)
1091{ 646{
1092 unsigned int chain_size; 647 unsigned int chain_size;
@@ -1104,17 +659,14 @@ static int
1104process_sample_event(event_t *event, unsigned long offset, unsigned long head) 659process_sample_event(event_t *event, unsigned long offset, unsigned long head)
1105{ 660{
1106 char level; 661 char level;
1107 int show = 0; 662 struct symbol *sym = NULL;
1108 struct dso *dso = NULL;
1109 struct thread *thread;
1110 u64 ip = event->ip.ip; 663 u64 ip = event->ip.ip;
1111 u64 period = 1; 664 u64 period = 1;
1112 struct map *map = NULL; 665 struct map *map = NULL;
1113 void *more_data = event->ip.__more_data; 666 void *more_data = event->ip.__more_data;
1114 struct ip_callchain *chain = NULL; 667 struct ip_callchain *chain = NULL;
1115 int cpumode; 668 int cpumode;
1116 669 struct thread *thread = threads__findnew(event->ip.pid);
1117 thread = threads__findnew(event->ip.pid, &threads, &last_match);
1118 670
1119 if (sample_type & PERF_SAMPLE_PERIOD) { 671 if (sample_type & PERF_SAMPLE_PERIOD) {
1120 period = *(u64 *)more_data; 672 period = *(u64 *)more_data;
@@ -1137,7 +689,8 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
1137 dump_printf("... chain: nr:%Lu\n", chain->nr); 689 dump_printf("... chain: nr:%Lu\n", chain->nr);
1138 690
1139 if (validate_chain(chain, event) < 0) { 691 if (validate_chain(chain, event) < 0) {
1140 eprintf("call-chain problem with event, skipping it.\n"); 692 pr_debug("call-chain problem with event, "
693 "skipping it.\n");
1141 return 0; 694 return 0;
1142 } 695 }
1143 696
@@ -1147,56 +700,49 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
1147 } 700 }
1148 } 701 }
1149 702
1150 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
1151
1152 if (thread == NULL) { 703 if (thread == NULL) {
1153 eprintf("problem processing %d event, skipping it.\n", 704 pr_debug("problem processing %d event, skipping it.\n",
1154 event->header.type); 705 event->header.type);
1155 return -1; 706 return -1;
1156 } 707 }
1157 708
709 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
710
1158 if (comm_list && !strlist__has_entry(comm_list, thread->comm)) 711 if (comm_list && !strlist__has_entry(comm_list, thread->comm))
1159 return 0; 712 return 0;
1160 713
1161 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 714 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
1162 715
1163 if (cpumode == PERF_RECORD_MISC_KERNEL) { 716 if (cpumode == PERF_RECORD_MISC_KERNEL) {
1164 show = SHOW_KERNEL;
1165 level = 'k'; 717 level = 'k';
1166 718 sym = kernel_maps__find_symbol(ip, &map);
1167 dso = kernel_dso; 719 dump_printf(" ...... dso: %s\n",
1168 720 map ? map->dso->long_name : "<not found>");
1169 dump_printf(" ...... dso: %s\n", dso->name);
1170
1171 } else if (cpumode == PERF_RECORD_MISC_USER) { 721 } else if (cpumode == PERF_RECORD_MISC_USER) {
1172
1173 show = SHOW_USER;
1174 level = '.'; 722 level = '.';
723 sym = resolve_symbol(thread, &map, &ip);
1175 724
1176 } else { 725 } else {
1177 show = SHOW_HV;
1178 level = 'H'; 726 level = 'H';
1179
1180 dso = hypervisor_dso;
1181
1182 dump_printf(" ...... dso: [hypervisor]\n"); 727 dump_printf(" ...... dso: [hypervisor]\n");
1183 } 728 }
1184 729
1185 if (show & show_mask) { 730 if (dso_list &&
1186 struct symbol *sym = resolve_symbol(thread, &map, &dso, &ip); 731 (!map || !map->dso ||
1187 732 !(strlist__has_entry(dso_list, map->dso->short_name) ||
1188 if (dso_list && (!dso || !dso->name || 733 (map->dso->short_name != map->dso->long_name &&
1189 !strlist__has_entry(dso_list, dso->name))) 734 strlist__has_entry(dso_list, map->dso->long_name)))))
1190 return 0; 735 return 0;
1191 736
1192 if (sym_list && (!sym || !strlist__has_entry(sym_list, sym->name))) 737 if (sym_list && sym && !strlist__has_entry(sym_list, sym->name))
1193 return 0; 738 return 0;
1194 739
1195 if (hist_entry__add(thread, map, dso, sym, ip, chain, level, period)) { 740 if (hist_entry__add(thread, map, sym, ip,
1196 eprintf("problem incrementing symbol count, skipping event\n"); 741 chain, level, period)) {
1197 return -1; 742 pr_debug("problem incrementing symbol count, skipping event\n");
1198 } 743 return -1;
1199 } 744 }
745
1200 total += period; 746 total += period;
1201 747
1202 return 0; 748 return 0;
@@ -1205,10 +751,8 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
1205static int 751static int
1206process_mmap_event(event_t *event, unsigned long offset, unsigned long head) 752process_mmap_event(event_t *event, unsigned long offset, unsigned long head)
1207{ 753{
1208 struct thread *thread; 754 struct map *map = map__new(&event->mmap, cwd, cwdlen, 0, NULL);
1209 struct map *map = map__new(&event->mmap, cwd, cwdlen); 755 struct thread *thread = threads__findnew(event->mmap.pid);
1210
1211 thread = threads__findnew(event->mmap.pid, &threads, &last_match);
1212 756
1213 dump_printf("%p [%p]: PERF_RECORD_MMAP %d/%d: [%p(%p) @ %p]: %s\n", 757 dump_printf("%p [%p]: PERF_RECORD_MMAP %d/%d: [%p(%p) @ %p]: %s\n",
1214 (void *)(offset + head), 758 (void *)(offset + head),
@@ -1234,9 +778,7 @@ process_mmap_event(event_t *event, unsigned long offset, unsigned long head)
1234static int 778static int
1235process_comm_event(event_t *event, unsigned long offset, unsigned long head) 779process_comm_event(event_t *event, unsigned long offset, unsigned long head)
1236{ 780{
1237 struct thread *thread; 781 struct thread *thread = threads__findnew(event->comm.pid);
1238
1239 thread = threads__findnew(event->comm.pid, &threads, &last_match);
1240 782
1241 dump_printf("%p [%p]: PERF_RECORD_COMM: %s:%d\n", 783 dump_printf("%p [%p]: PERF_RECORD_COMM: %s:%d\n",
1242 (void *)(offset + head), 784 (void *)(offset + head),
@@ -1256,11 +798,8 @@ process_comm_event(event_t *event, unsigned long offset, unsigned long head)
1256static int 798static int
1257process_task_event(event_t *event, unsigned long offset, unsigned long head) 799process_task_event(event_t *event, unsigned long offset, unsigned long head)
1258{ 800{
1259 struct thread *thread; 801 struct thread *thread = threads__findnew(event->fork.pid);
1260 struct thread *parent; 802 struct thread *parent = threads__findnew(event->fork.ppid);
1261
1262 thread = threads__findnew(event->fork.pid, &threads, &last_match);
1263 parent = threads__findnew(event->fork.ppid, &threads, &last_match);
1264 803
1265 dump_printf("%p [%p]: PERF_RECORD_%s: (%d:%d):(%d:%d)\n", 804 dump_printf("%p [%p]: PERF_RECORD_%s: (%d:%d):(%d:%d)\n",
1266 (void *)(offset + head), 805 (void *)(offset + head),
@@ -1331,216 +870,79 @@ process_read_event(event_t *event, unsigned long offset, unsigned long head)
1331 return 0; 870 return 0;
1332} 871}
1333 872
1334static int 873static int sample_type_check(u64 type)
1335process_event(event_t *event, unsigned long offset, unsigned long head)
1336{
1337 trace_event(event);
1338
1339 switch (event->header.type) {
1340 case PERF_RECORD_SAMPLE:
1341 return process_sample_event(event, offset, head);
1342
1343 case PERF_RECORD_MMAP:
1344 return process_mmap_event(event, offset, head);
1345
1346 case PERF_RECORD_COMM:
1347 return process_comm_event(event, offset, head);
1348
1349 case PERF_RECORD_FORK:
1350 case PERF_RECORD_EXIT:
1351 return process_task_event(event, offset, head);
1352
1353 case PERF_RECORD_LOST:
1354 return process_lost_event(event, offset, head);
1355
1356 case PERF_RECORD_READ:
1357 return process_read_event(event, offset, head);
1358
1359 /*
1360 * We dont process them right now but they are fine:
1361 */
1362
1363 case PERF_RECORD_THROTTLE:
1364 case PERF_RECORD_UNTHROTTLE:
1365 return 0;
1366
1367 default:
1368 return -1;
1369 }
1370
1371 return 0;
1372}
1373
1374static int __cmd_report(void)
1375{ 874{
1376 int ret, rc = EXIT_FAILURE; 875 sample_type = type;
1377 unsigned long offset = 0;
1378 unsigned long head, shift;
1379 struct stat input_stat;
1380 struct thread *idle;
1381 event_t *event;
1382 uint32_t size;
1383 char *buf;
1384
1385 idle = register_idle_thread(&threads, &last_match);
1386 thread__comm_adjust(idle);
1387
1388 if (show_threads)
1389 perf_read_values_init(&show_threads_values);
1390
1391 input = open(input_name, O_RDONLY);
1392 if (input < 0) {
1393 fprintf(stderr, " failed to open file: %s", input_name);
1394 if (!strcmp(input_name, "perf.data"))
1395 fprintf(stderr, " (try 'perf record' first)");
1396 fprintf(stderr, "\n");
1397 exit(-1);
1398 }
1399
1400 ret = fstat(input, &input_stat);
1401 if (ret < 0) {
1402 perror("failed to stat file");
1403 exit(-1);
1404 }
1405
1406 if (!force && input_stat.st_uid && (input_stat.st_uid != geteuid())) {
1407 fprintf(stderr, "file: %s not owned by current user or root\n", input_name);
1408 exit(-1);
1409 }
1410
1411 if (!input_stat.st_size) {
1412 fprintf(stderr, "zero-sized file, nothing to do!\n");
1413 exit(0);
1414 }
1415
1416 header = perf_header__read(input);
1417 head = header->data_offset;
1418
1419 sample_type = perf_header__sample_type(header);
1420 876
1421 if (!(sample_type & PERF_SAMPLE_CALLCHAIN)) { 877 if (!(sample_type & PERF_SAMPLE_CALLCHAIN)) {
1422 if (sort__has_parent) { 878 if (sort__has_parent) {
1423 fprintf(stderr, "selected --sort parent, but no" 879 fprintf(stderr, "selected --sort parent, but no"
1424 " callchain data. Did you call" 880 " callchain data. Did you call"
1425 " perf record without -g?\n"); 881 " perf record without -g?\n");
1426 exit(-1); 882 return -1;
1427 } 883 }
1428 if (callchain) { 884 if (callchain) {
1429 fprintf(stderr, "selected -g but no callchain data." 885 fprintf(stderr, "selected -g but no callchain data."
1430 " Did you call perf record without" 886 " Did you call perf record without"
1431 " -g?\n"); 887 " -g?\n");
1432 exit(-1); 888 return -1;
1433 } 889 }
1434 } else if (callchain_param.mode != CHAIN_NONE && !callchain) { 890 } else if (callchain_param.mode != CHAIN_NONE && !callchain) {
1435 callchain = 1; 891 callchain = 1;
1436 if (register_callchain_param(&callchain_param) < 0) { 892 if (register_callchain_param(&callchain_param) < 0) {
1437 fprintf(stderr, "Can't register callchain" 893 fprintf(stderr, "Can't register callchain"
1438 " params\n"); 894 " params\n");
1439 exit(-1); 895 return -1;
1440 } 896 }
1441 } 897 }
1442 898
1443 if (load_kernel() < 0) { 899 return 0;
1444 perror("failed to load kernel symbols"); 900}
1445 return EXIT_FAILURE;
1446 }
1447
1448 if (!full_paths) {
1449 if (getcwd(__cwd, sizeof(__cwd)) == NULL) {
1450 perror("failed to get the current directory");
1451 return EXIT_FAILURE;
1452 }
1453 cwdlen = strlen(cwd);
1454 } else {
1455 cwd = NULL;
1456 cwdlen = 0;
1457 }
1458
1459 shift = page_size * (head / page_size);
1460 offset += shift;
1461 head -= shift;
1462
1463remap:
1464 buf = (char *)mmap(NULL, page_size * mmap_window, PROT_READ,
1465 MAP_SHARED, input, offset);
1466 if (buf == MAP_FAILED) {
1467 perror("failed to mmap file");
1468 exit(-1);
1469 }
1470
1471more:
1472 event = (event_t *)(buf + head);
1473
1474 size = event->header.size;
1475 if (!size)
1476 size = 8;
1477
1478 if (head + event->header.size >= page_size * mmap_window) {
1479 int munmap_ret;
1480
1481 shift = page_size * (head / page_size);
1482
1483 munmap_ret = munmap(buf, page_size * mmap_window);
1484 assert(munmap_ret == 0);
1485
1486 offset += shift;
1487 head -= shift;
1488 goto remap;
1489 }
1490
1491 size = event->header.size;
1492
1493 dump_printf("\n%p [%p]: event: %d\n",
1494 (void *)(offset + head),
1495 (void *)(long)event->header.size,
1496 event->header.type);
1497
1498 if (!size || process_event(event, offset, head) < 0) {
1499
1500 dump_printf("%p [%p]: skipping unknown header type: %d\n",
1501 (void *)(offset + head),
1502 (void *)(long)(event->header.size),
1503 event->header.type);
1504
1505 total_unknown++;
1506 901
1507 /* 902static struct perf_file_handler file_handler = {
1508 * assume we lost track of the stream, check alignment, and 903 .process_sample_event = process_sample_event,
1509 * increment a single u64 in the hope to catch on again 'soon'. 904 .process_mmap_event = process_mmap_event,
1510 */ 905 .process_comm_event = process_comm_event,
906 .process_exit_event = process_task_event,
907 .process_fork_event = process_task_event,
908 .process_lost_event = process_lost_event,
909 .process_read_event = process_read_event,
910 .sample_type_check = sample_type_check,
911};
1511 912
1512 if (unlikely(head & 7))
1513 head &= ~7ULL;
1514 913
1515 size = 8; 914static int __cmd_report(void)
1516 } 915{
916 struct thread *idle;
917 int ret;
1517 918
1518 head += size; 919 idle = register_idle_thread();
920 thread__comm_adjust(idle);
1519 921
1520 if (offset + head >= header->data_offset + header->data_size) 922 if (show_threads)
1521 goto done; 923 perf_read_values_init(&show_threads_values);
1522 924
1523 if (offset + head < (unsigned long)input_stat.st_size) 925 register_perf_file_handler(&file_handler);
1524 goto more;
1525 926
1526done: 927 ret = mmap_dispatch_perf_file(&header, input_name, force, full_paths,
1527 rc = EXIT_SUCCESS; 928 &cwdlen, &cwd);
1528 close(input); 929 if (ret)
930 return ret;
1529 931
1530 dump_printf(" IP events: %10ld\n", total); 932 dump_printf(" IP events: %10ld\n", total);
1531 dump_printf(" mmap events: %10ld\n", total_mmap); 933 dump_printf(" mmap events: %10ld\n", total_mmap);
1532 dump_printf(" comm events: %10ld\n", total_comm); 934 dump_printf(" comm events: %10ld\n", total_comm);
1533 dump_printf(" fork events: %10ld\n", total_fork); 935 dump_printf(" fork events: %10ld\n", total_fork);
1534 dump_printf(" lost events: %10ld\n", total_lost); 936 dump_printf(" lost events: %10ld\n", total_lost);
1535 dump_printf(" unknown events: %10ld\n", total_unknown); 937 dump_printf(" unknown events: %10ld\n", file_handler.total_unknown);
1536 938
1537 if (dump_trace) 939 if (dump_trace)
1538 return 0; 940 return 0;
1539 941
1540 if (verbose >= 3) 942 if (verbose > 3)
1541 threads__fprintf(stdout, &threads); 943 threads__fprintf(stdout);
1542 944
1543 if (verbose >= 2) 945 if (verbose > 2)
1544 dsos__fprintf(stdout); 946 dsos__fprintf(stdout);
1545 947
1546 collapse__resort(); 948 collapse__resort();
@@ -1550,7 +952,7 @@ done:
1550 if (show_threads) 952 if (show_threads)
1551 perf_read_values_destroy(&show_threads_values); 953 perf_read_values_destroy(&show_threads_values);
1552 954
1553 return rc; 955 return ret;
1554} 956}
1555 957
1556static int 958static int
@@ -1606,7 +1008,8 @@ setup:
1606 return 0; 1008 return 0;
1607} 1009}
1608 1010
1609static const char * const report_usage[] = { 1011//static const char * const report_usage[] = {
1012const char * const report_usage[] = {
1610 "perf report [<options>] <command>", 1013 "perf report [<options>] <command>",
1611 NULL 1014 NULL
1612}; 1015};
@@ -1692,8 +1095,6 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
1692{ 1095{
1693 symbol__init(); 1096 symbol__init();
1694 1097
1695 page_size = getpagesize();
1696
1697 argc = parse_options(argc, argv, options, report_usage, 0); 1098 argc = parse_options(argc, argv, options, report_usage, 0);
1698 1099
1699 setup_sorting(); 1100 setup_sorting();
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index ce2d5be4f30..9a48d9626be 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -11,6 +11,7 @@
11#include "util/trace-event.h" 11#include "util/trace-event.h"
12 12
13#include "util/debug.h" 13#include "util/debug.h"
14#include "util/data_map.h"
14 15
15#include <sys/types.h> 16#include <sys/types.h>
16#include <sys/prctl.h> 17#include <sys/prctl.h>
@@ -20,26 +21,23 @@
20#include <math.h> 21#include <math.h>
21 22
22static char const *input_name = "perf.data"; 23static char const *input_name = "perf.data";
23static int input;
24static unsigned long page_size;
25static unsigned long mmap_window = 32;
26 24
27static unsigned long total_comm = 0; 25static unsigned long total_comm = 0;
28 26
29static struct rb_root threads;
30static struct thread *last_match;
31
32static struct perf_header *header; 27static struct perf_header *header;
33static u64 sample_type; 28static u64 sample_type;
34 29
35static char default_sort_order[] = "avg, max, switch, runtime"; 30static char default_sort_order[] = "avg, max, switch, runtime";
36static char *sort_order = default_sort_order; 31static char *sort_order = default_sort_order;
37 32
33static int profile_cpu = -1;
34
35static char *cwd;
36static int cwdlen;
37
38#define PR_SET_NAME 15 /* Set process name */ 38#define PR_SET_NAME 15 /* Set process name */
39#define MAX_CPUS 4096 39#define MAX_CPUS 4096
40 40
41#define BUG_ON(x) assert(!(x))
42
43static u64 run_measurement_overhead; 41static u64 run_measurement_overhead;
44static u64 sleep_measurement_overhead; 42static u64 sleep_measurement_overhead;
45 43
@@ -74,6 +72,7 @@ enum sched_event_type {
74 SCHED_EVENT_RUN, 72 SCHED_EVENT_RUN,
75 SCHED_EVENT_SLEEP, 73 SCHED_EVENT_SLEEP,
76 SCHED_EVENT_WAKEUP, 74 SCHED_EVENT_WAKEUP,
75 SCHED_EVENT_MIGRATION,
77}; 76};
78 77
79struct sched_atom { 78struct sched_atom {
@@ -398,6 +397,8 @@ process_sched_event(struct task_desc *this_task __used, struct sched_atom *atom)
398 ret = sem_post(atom->wait_sem); 397 ret = sem_post(atom->wait_sem);
399 BUG_ON(ret); 398 BUG_ON(ret);
400 break; 399 break;
400 case SCHED_EVENT_MIGRATION:
401 break;
401 default: 402 default:
402 BUG_ON(1); 403 BUG_ON(1);
403 } 404 }
@@ -635,9 +636,7 @@ static void test_calibrations(void)
635static int 636static int
636process_comm_event(event_t *event, unsigned long offset, unsigned long head) 637process_comm_event(event_t *event, unsigned long offset, unsigned long head)
637{ 638{
638 struct thread *thread; 639 struct thread *thread = threads__findnew(event->comm.tid);
639
640 thread = threads__findnew(event->comm.pid, &threads, &last_match);
641 640
642 dump_printf("%p [%p]: perf_event_comm: %s:%d\n", 641 dump_printf("%p [%p]: perf_event_comm: %s:%d\n",
643 (void *)(offset + head), 642 (void *)(offset + head),
@@ -745,6 +744,22 @@ struct trace_fork_event {
745 u32 child_pid; 744 u32 child_pid;
746}; 745};
747 746
747struct trace_migrate_task_event {
748 u32 size;
749
750 u16 common_type;
751 u8 common_flags;
752 u8 common_preempt_count;
753 u32 common_pid;
754 u32 common_tgid;
755
756 char comm[16];
757 u32 pid;
758
759 u32 prio;
760 u32 cpu;
761};
762
748struct trace_sched_handler { 763struct trace_sched_handler {
749 void (*switch_event)(struct trace_switch_event *, 764 void (*switch_event)(struct trace_switch_event *,
750 struct event *, 765 struct event *,
@@ -769,6 +784,12 @@ struct trace_sched_handler {
769 int cpu, 784 int cpu,
770 u64 timestamp, 785 u64 timestamp,
771 struct thread *thread); 786 struct thread *thread);
787
788 void (*migrate_task_event)(struct trace_migrate_task_event *,
789 struct event *,
790 int cpu,
791 u64 timestamp,
792 struct thread *thread);
772}; 793};
773 794
774 795
@@ -1058,8 +1079,8 @@ latency_switch_event(struct trace_switch_event *switch_event,
1058 die("hm, delta: %Ld < 0 ?\n", delta); 1079 die("hm, delta: %Ld < 0 ?\n", delta);
1059 1080
1060 1081
1061 sched_out = threads__findnew(switch_event->prev_pid, &threads, &last_match); 1082 sched_out = threads__findnew(switch_event->prev_pid);
1062 sched_in = threads__findnew(switch_event->next_pid, &threads, &last_match); 1083 sched_in = threads__findnew(switch_event->next_pid);
1063 1084
1064 out_events = thread_atoms_search(&atom_root, sched_out, &cmp_pid); 1085 out_events = thread_atoms_search(&atom_root, sched_out, &cmp_pid);
1065 if (!out_events) { 1086 if (!out_events) {
@@ -1092,13 +1113,10 @@ latency_runtime_event(struct trace_runtime_event *runtime_event,
1092 u64 timestamp, 1113 u64 timestamp,
1093 struct thread *this_thread __used) 1114 struct thread *this_thread __used)
1094{ 1115{
1095 struct work_atoms *atoms; 1116 struct thread *thread = threads__findnew(runtime_event->pid);
1096 struct thread *thread; 1117 struct work_atoms *atoms = thread_atoms_search(&atom_root, thread, &cmp_pid);
1097 1118
1098 BUG_ON(cpu >= MAX_CPUS || cpu < 0); 1119 BUG_ON(cpu >= MAX_CPUS || cpu < 0);
1099
1100 thread = threads__findnew(runtime_event->pid, &threads, &last_match);
1101 atoms = thread_atoms_search(&atom_root, thread, &cmp_pid);
1102 if (!atoms) { 1120 if (!atoms) {
1103 thread_atoms_insert(thread); 1121 thread_atoms_insert(thread);
1104 atoms = thread_atoms_search(&atom_root, thread, &cmp_pid); 1122 atoms = thread_atoms_search(&atom_root, thread, &cmp_pid);
@@ -1125,7 +1143,7 @@ latency_wakeup_event(struct trace_wakeup_event *wakeup_event,
1125 if (!wakeup_event->success) 1143 if (!wakeup_event->success)
1126 return; 1144 return;
1127 1145
1128 wakee = threads__findnew(wakeup_event->pid, &threads, &last_match); 1146 wakee = threads__findnew(wakeup_event->pid);
1129 atoms = thread_atoms_search(&atom_root, wakee, &cmp_pid); 1147 atoms = thread_atoms_search(&atom_root, wakee, &cmp_pid);
1130 if (!atoms) { 1148 if (!atoms) {
1131 thread_atoms_insert(wakee); 1149 thread_atoms_insert(wakee);
@@ -1139,7 +1157,12 @@ latency_wakeup_event(struct trace_wakeup_event *wakeup_event,
1139 1157
1140 atom = list_entry(atoms->work_list.prev, struct work_atom, list); 1158 atom = list_entry(atoms->work_list.prev, struct work_atom, list);
1141 1159
1142 if (atom->state != THREAD_SLEEPING) 1160 /*
1161 * You WILL be missing events if you've recorded only
1162 * one CPU, or are only looking at only one, so don't
1163 * make useless noise.
1164 */
1165 if (profile_cpu == -1 && atom->state != THREAD_SLEEPING)
1143 nr_state_machine_bugs++; 1166 nr_state_machine_bugs++;
1144 1167
1145 nr_timestamps++; 1168 nr_timestamps++;
@@ -1152,11 +1175,51 @@ latency_wakeup_event(struct trace_wakeup_event *wakeup_event,
1152 atom->wake_up_time = timestamp; 1175 atom->wake_up_time = timestamp;
1153} 1176}
1154 1177
1178static void
1179latency_migrate_task_event(struct trace_migrate_task_event *migrate_task_event,
1180 struct event *__event __used,
1181 int cpu __used,
1182 u64 timestamp,
1183 struct thread *thread __used)
1184{
1185 struct work_atoms *atoms;
1186 struct work_atom *atom;
1187 struct thread *migrant;
1188
1189 /*
1190 * Only need to worry about migration when profiling one CPU.
1191 */
1192 if (profile_cpu == -1)
1193 return;
1194
1195 migrant = threads__findnew(migrate_task_event->pid);
1196 atoms = thread_atoms_search(&atom_root, migrant, &cmp_pid);
1197 if (!atoms) {
1198 thread_atoms_insert(migrant);
1199 register_pid(migrant->pid, migrant->comm);
1200 atoms = thread_atoms_search(&atom_root, migrant, &cmp_pid);
1201 if (!atoms)
1202 die("migration-event: Internal tree error");
1203 add_sched_out_event(atoms, 'R', timestamp);
1204 }
1205
1206 BUG_ON(list_empty(&atoms->work_list));
1207
1208 atom = list_entry(atoms->work_list.prev, struct work_atom, list);
1209 atom->sched_in_time = atom->sched_out_time = atom->wake_up_time = timestamp;
1210
1211 nr_timestamps++;
1212
1213 if (atom->sched_out_time > timestamp)
1214 nr_unordered_timestamps++;
1215}
1216
1155static struct trace_sched_handler lat_ops = { 1217static struct trace_sched_handler lat_ops = {
1156 .wakeup_event = latency_wakeup_event, 1218 .wakeup_event = latency_wakeup_event,
1157 .switch_event = latency_switch_event, 1219 .switch_event = latency_switch_event,
1158 .runtime_event = latency_runtime_event, 1220 .runtime_event = latency_runtime_event,
1159 .fork_event = latency_fork_event, 1221 .fork_event = latency_fork_event,
1222 .migrate_task_event = latency_migrate_task_event,
1160}; 1223};
1161 1224
1162static void output_lat_thread(struct work_atoms *work_list) 1225static void output_lat_thread(struct work_atoms *work_list)
@@ -1385,8 +1448,8 @@ map_switch_event(struct trace_switch_event *switch_event,
1385 die("hm, delta: %Ld < 0 ?\n", delta); 1448 die("hm, delta: %Ld < 0 ?\n", delta);
1386 1449
1387 1450
1388 sched_out = threads__findnew(switch_event->prev_pid, &threads, &last_match); 1451 sched_out = threads__findnew(switch_event->prev_pid);
1389 sched_in = threads__findnew(switch_event->next_pid, &threads, &last_match); 1452 sched_in = threads__findnew(switch_event->next_pid);
1390 1453
1391 curr_thread[this_cpu] = sched_in; 1454 curr_thread[this_cpu] = sched_in;
1392 1455
@@ -1517,6 +1580,26 @@ process_sched_exit_event(struct event *event,
1517} 1580}
1518 1581
1519static void 1582static void
1583process_sched_migrate_task_event(struct raw_event_sample *raw,
1584 struct event *event,
1585 int cpu __used,
1586 u64 timestamp __used,
1587 struct thread *thread __used)
1588{
1589 struct trace_migrate_task_event migrate_task_event;
1590
1591 FILL_COMMON_FIELDS(migrate_task_event, event, raw->data);
1592
1593 FILL_ARRAY(migrate_task_event, comm, event, raw->data);
1594 FILL_FIELD(migrate_task_event, pid, event, raw->data);
1595 FILL_FIELD(migrate_task_event, prio, event, raw->data);
1596 FILL_FIELD(migrate_task_event, cpu, event, raw->data);
1597
1598 if (trace_handler->migrate_task_event)
1599 trace_handler->migrate_task_event(&migrate_task_event, event, cpu, timestamp, thread);
1600}
1601
1602static void
1520process_raw_event(event_t *raw_event __used, void *more_data, 1603process_raw_event(event_t *raw_event __used, void *more_data,
1521 int cpu, u64 timestamp, struct thread *thread) 1604 int cpu, u64 timestamp, struct thread *thread)
1522{ 1605{
@@ -1539,23 +1622,24 @@ process_raw_event(event_t *raw_event __used, void *more_data,
1539 process_sched_fork_event(raw, event, cpu, timestamp, thread); 1622 process_sched_fork_event(raw, event, cpu, timestamp, thread);
1540 if (!strcmp(event->name, "sched_process_exit")) 1623 if (!strcmp(event->name, "sched_process_exit"))
1541 process_sched_exit_event(event, cpu, timestamp, thread); 1624 process_sched_exit_event(event, cpu, timestamp, thread);
1625 if (!strcmp(event->name, "sched_migrate_task"))
1626 process_sched_migrate_task_event(raw, event, cpu, timestamp, thread);
1542} 1627}
1543 1628
1544static int 1629static int
1545process_sample_event(event_t *event, unsigned long offset, unsigned long head) 1630process_sample_event(event_t *event, unsigned long offset, unsigned long head)
1546{ 1631{
1547 char level;
1548 int show = 0;
1549 struct dso *dso = NULL;
1550 struct thread *thread; 1632 struct thread *thread;
1551 u64 ip = event->ip.ip; 1633 u64 ip = event->ip.ip;
1552 u64 timestamp = -1; 1634 u64 timestamp = -1;
1553 u32 cpu = -1; 1635 u32 cpu = -1;
1554 u64 period = 1; 1636 u64 period = 1;
1555 void *more_data = event->ip.__more_data; 1637 void *more_data = event->ip.__more_data;
1556 int cpumode;
1557 1638
1558 thread = threads__findnew(event->ip.pid, &threads, &last_match); 1639 if (!(sample_type & PERF_SAMPLE_RAW))
1640 return 0;
1641
1642 thread = threads__findnew(event->ip.pid);
1559 1643
1560 if (sample_type & PERF_SAMPLE_TIME) { 1644 if (sample_type & PERF_SAMPLE_TIME) {
1561 timestamp = *(u64 *)more_data; 1645 timestamp = *(u64 *)more_data;
@@ -1581,169 +1665,60 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
1581 (void *)(long)ip, 1665 (void *)(long)ip,
1582 (long long)period); 1666 (long long)period);
1583 1667
1584 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
1585
1586 if (thread == NULL) { 1668 if (thread == NULL) {
1587 eprintf("problem processing %d event, skipping it.\n", 1669 pr_debug("problem processing %d event, skipping it.\n",
1588 event->header.type); 1670 event->header.type);
1589 return -1; 1671 return -1;
1590 } 1672 }
1591 1673
1592 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 1674 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
1593
1594 if (cpumode == PERF_RECORD_MISC_KERNEL) {
1595 show = SHOW_KERNEL;
1596 level = 'k';
1597
1598 dso = kernel_dso;
1599
1600 dump_printf(" ...... dso: %s\n", dso->name);
1601
1602 } else if (cpumode == PERF_RECORD_MISC_USER) {
1603
1604 show = SHOW_USER;
1605 level = '.';
1606
1607 } else {
1608 show = SHOW_HV;
1609 level = 'H';
1610
1611 dso = hypervisor_dso;
1612 1675
1613 dump_printf(" ...... dso: [hypervisor]\n"); 1676 if (profile_cpu != -1 && profile_cpu != (int) cpu)
1614 } 1677 return 0;
1615 1678
1616 if (sample_type & PERF_SAMPLE_RAW) 1679 process_raw_event(event, more_data, cpu, timestamp, thread);
1617 process_raw_event(event, more_data, cpu, timestamp, thread);
1618 1680
1619 return 0; 1681 return 0;
1620} 1682}
1621 1683
1622static int 1684static int
1623process_event(event_t *event, unsigned long offset, unsigned long head) 1685process_lost_event(event_t *event __used,
1686 unsigned long offset __used,
1687 unsigned long head __used)
1624{ 1688{
1625 trace_event(event); 1689 nr_lost_chunks++;
1690 nr_lost_events += event->lost.lost;
1626 1691
1627 nr_events++; 1692 return 0;
1628 switch (event->header.type) { 1693}
1629 case PERF_RECORD_MMAP:
1630 return 0;
1631 case PERF_RECORD_LOST:
1632 nr_lost_chunks++;
1633 nr_lost_events += event->lost.lost;
1634 return 0;
1635
1636 case PERF_RECORD_COMM:
1637 return process_comm_event(event, offset, head);
1638
1639 case PERF_RECORD_EXIT ... PERF_RECORD_READ:
1640 return 0;
1641 1694
1642 case PERF_RECORD_SAMPLE: 1695static int sample_type_check(u64 type)
1643 return process_sample_event(event, offset, head); 1696{
1697 sample_type = type;
1644 1698
1645 case PERF_RECORD_MAX: 1699 if (!(sample_type & PERF_SAMPLE_RAW)) {
1646 default: 1700 fprintf(stderr,
1701 "No trace sample to read. Did you call perf record "
1702 "without -R?");
1647 return -1; 1703 return -1;
1648 } 1704 }
1649 1705
1650 return 0; 1706 return 0;
1651} 1707}
1652 1708
1709static struct perf_file_handler file_handler = {
1710 .process_sample_event = process_sample_event,
1711 .process_comm_event = process_comm_event,
1712 .process_lost_event = process_lost_event,
1713 .sample_type_check = sample_type_check,
1714};
1715
1653static int read_events(void) 1716static int read_events(void)
1654{ 1717{
1655 int ret, rc = EXIT_FAILURE; 1718 register_idle_thread();
1656 unsigned long offset = 0; 1719 register_perf_file_handler(&file_handler);
1657 unsigned long head = 0;
1658 struct stat perf_stat;
1659 event_t *event;
1660 uint32_t size;
1661 char *buf;
1662
1663 trace_report();
1664 register_idle_thread(&threads, &last_match);
1665
1666 input = open(input_name, O_RDONLY);
1667 if (input < 0) {
1668 perror("failed to open file");
1669 exit(-1);
1670 }
1671
1672 ret = fstat(input, &perf_stat);
1673 if (ret < 0) {
1674 perror("failed to stat file");
1675 exit(-1);
1676 }
1677
1678 if (!perf_stat.st_size) {
1679 fprintf(stderr, "zero-sized file, nothing to do!\n");
1680 exit(0);
1681 }
1682 header = perf_header__read(input);
1683 head = header->data_offset;
1684 sample_type = perf_header__sample_type(header);
1685
1686 if (!(sample_type & PERF_SAMPLE_RAW))
1687 die("No trace sample to read. Did you call perf record "
1688 "without -R?");
1689
1690 if (load_kernel() < 0) {
1691 perror("failed to load kernel symbols");
1692 return EXIT_FAILURE;
1693 }
1694
1695remap:
1696 buf = (char *)mmap(NULL, page_size * mmap_window, PROT_READ,
1697 MAP_SHARED, input, offset);
1698 if (buf == MAP_FAILED) {
1699 perror("failed to mmap file");
1700 exit(-1);
1701 }
1702
1703more:
1704 event = (event_t *)(buf + head);
1705
1706 size = event->header.size;
1707 if (!size)
1708 size = 8;
1709
1710 if (head + event->header.size >= page_size * mmap_window) {
1711 unsigned long shift = page_size * (head / page_size);
1712 int res;
1713
1714 res = munmap(buf, page_size * mmap_window);
1715 assert(res == 0);
1716
1717 offset += shift;
1718 head -= shift;
1719 goto remap;
1720 }
1721
1722 size = event->header.size;
1723
1724
1725 if (!size || process_event(event, offset, head) < 0) {
1726
1727 /*
1728 * assume we lost track of the stream, check alignment, and
1729 * increment a single u64 in the hope to catch on again 'soon'.
1730 */
1731
1732 if (unlikely(head & 7))
1733 head &= ~7ULL;
1734
1735 size = 8;
1736 }
1737
1738 head += size;
1739
1740 if (offset + head < (unsigned long)perf_stat.st_size)
1741 goto more;
1742
1743 rc = EXIT_SUCCESS;
1744 close(input);
1745 1720
1746 return rc; 1721 return mmap_dispatch_perf_file(&header, input_name, 0, 0, &cwdlen, &cwd);
1747} 1722}
1748 1723
1749static void print_bad_events(void) 1724static void print_bad_events(void)
@@ -1883,6 +1858,8 @@ static const struct option latency_options[] = {
1883 "sort by key(s): runtime, switch, avg, max"), 1858 "sort by key(s): runtime, switch, avg, max"),
1884 OPT_BOOLEAN('v', "verbose", &verbose, 1859 OPT_BOOLEAN('v', "verbose", &verbose,
1885 "be more verbose (show symbol address, etc)"), 1860 "be more verbose (show symbol address, etc)"),
1861 OPT_INTEGER('C', "CPU", &profile_cpu,
1862 "CPU to profile on"),
1886 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 1863 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
1887 "dump raw trace in ASCII"), 1864 "dump raw trace in ASCII"),
1888 OPT_END() 1865 OPT_END()
@@ -1961,7 +1938,6 @@ static int __cmd_record(int argc, const char **argv)
1961int cmd_sched(int argc, const char **argv, const char *prefix __used) 1938int cmd_sched(int argc, const char **argv, const char *prefix __used)
1962{ 1939{
1963 symbol__init(); 1940 symbol__init();
1964 page_size = getpagesize();
1965 1941
1966 argc = parse_options(argc, argv, sched_options, sched_usage, 1942 argc = parse_options(argc, argv, sched_options, sched_usage,
1967 PARSE_OPT_STOP_AT_NON_OPTION); 1943 PARSE_OPT_STOP_AT_NON_OPTION);
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 3db31e7bf17..c6df3770b87 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -50,15 +50,17 @@
50 50
51static struct perf_event_attr default_attrs[] = { 51static struct perf_event_attr default_attrs[] = {
52 52
53 { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_TASK_CLOCK }, 53 { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_TASK_CLOCK },
54 { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CONTEXT_SWITCHES}, 54 { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CONTEXT_SWITCHES },
55 { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CPU_MIGRATIONS }, 55 { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CPU_MIGRATIONS },
56 { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_PAGE_FAULTS }, 56 { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_PAGE_FAULTS },
57 57
58 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CPU_CYCLES }, 58 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CPU_CYCLES },
59 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_INSTRUCTIONS }, 59 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_INSTRUCTIONS },
60 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CACHE_REFERENCES}, 60 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS },
61 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CACHE_MISSES }, 61 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_MISSES },
62 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CACHE_REFERENCES },
63 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CACHE_MISSES },
62 64
63}; 65};
64 66
@@ -125,6 +127,7 @@ struct stats event_res_stats[MAX_COUNTERS][3];
125struct stats runtime_nsecs_stats; 127struct stats runtime_nsecs_stats;
126struct stats walltime_nsecs_stats; 128struct stats walltime_nsecs_stats;
127struct stats runtime_cycles_stats; 129struct stats runtime_cycles_stats;
130struct stats runtime_branches_stats;
128 131
129#define MATCH_EVENT(t, c, counter) \ 132#define MATCH_EVENT(t, c, counter) \
130 (attrs[counter].type == PERF_TYPE_##t && \ 133 (attrs[counter].type == PERF_TYPE_##t && \
@@ -235,6 +238,8 @@ static void read_counter(int counter)
235 update_stats(&runtime_nsecs_stats, count[0]); 238 update_stats(&runtime_nsecs_stats, count[0]);
236 if (MATCH_EVENT(HARDWARE, HW_CPU_CYCLES, counter)) 239 if (MATCH_EVENT(HARDWARE, HW_CPU_CYCLES, counter))
237 update_stats(&runtime_cycles_stats, count[0]); 240 update_stats(&runtime_cycles_stats, count[0]);
241 if (MATCH_EVENT(HARDWARE, HW_BRANCH_INSTRUCTIONS, counter))
242 update_stats(&runtime_branches_stats, count[0]);
238} 243}
239 244
240static int run_perf_stat(int argc __used, const char **argv) 245static int run_perf_stat(int argc __used, const char **argv)
@@ -352,6 +357,14 @@ static void abs_printout(int counter, double avg)
352 ratio = avg / total; 357 ratio = avg / total;
353 358
354 fprintf(stderr, " # %10.3f IPC ", ratio); 359 fprintf(stderr, " # %10.3f IPC ", ratio);
360 } else if (MATCH_EVENT(HARDWARE, HW_BRANCH_MISSES, counter)) {
361 total = avg_stats(&runtime_branches_stats);
362
363 if (total)
364 ratio = avg * 100 / total;
365
366 fprintf(stderr, " # %10.3f %% ", ratio);
367
355 } else { 368 } else {
356 total = avg_stats(&runtime_nsecs_stats); 369 total = avg_stats(&runtime_nsecs_stats);
357 370
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index 702d8fe58fb..0a2f22261c3 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -153,6 +153,17 @@ static struct wake_event *wake_events;
153 153
154struct sample_wrapper *all_samples; 154struct sample_wrapper *all_samples;
155 155
156
157struct process_filter;
158struct process_filter {
159 char *name;
160 int pid;
161 struct process_filter *next;
162};
163
164static struct process_filter *process_filter;
165
166
156static struct per_pid *find_create_pid(int pid) 167static struct per_pid *find_create_pid(int pid)
157{ 168{
158 struct per_pid *cursor = all_data; 169 struct per_pid *cursor = all_data;
@@ -763,21 +774,42 @@ static void draw_wakeups(void)
763 c = p->all; 774 c = p->all;
764 while (c) { 775 while (c) {
765 if (c->Y && c->start_time <= we->time && c->end_time >= we->time) { 776 if (c->Y && c->start_time <= we->time && c->end_time >= we->time) {
766 if (p->pid == we->waker) { 777 if (p->pid == we->waker && !from) {
767 from = c->Y; 778 from = c->Y;
768 task_from = c->comm; 779 task_from = strdup(c->comm);
769 } 780 }
770 if (p->pid == we->wakee) { 781 if (p->pid == we->wakee && !to) {
771 to = c->Y; 782 to = c->Y;
772 task_to = c->comm; 783 task_to = strdup(c->comm);
773 } 784 }
774 } 785 }
775 c = c->next; 786 c = c->next;
776 } 787 }
788 c = p->all;
789 while (c) {
790 if (p->pid == we->waker && !from) {
791 from = c->Y;
792 task_from = strdup(c->comm);
793 }
794 if (p->pid == we->wakee && !to) {
795 to = c->Y;
796 task_to = strdup(c->comm);
797 }
798 c = c->next;
799 }
777 } 800 }
778 p = p->next; 801 p = p->next;
779 } 802 }
780 803
804 if (!task_from) {
805 task_from = malloc(40);
806 sprintf(task_from, "[%i]", we->waker);
807 }
808 if (!task_to) {
809 task_to = malloc(40);
810 sprintf(task_to, "[%i]", we->wakee);
811 }
812
781 if (we->waker == -1) 813 if (we->waker == -1)
782 svg_interrupt(we->time, to); 814 svg_interrupt(we->time, to);
783 else if (from && to && abs(from - to) == 1) 815 else if (from && to && abs(from - to) == 1)
@@ -785,6 +817,9 @@ static void draw_wakeups(void)
785 else 817 else
786 svg_partial_wakeline(we->time, from, task_from, to, task_to); 818 svg_partial_wakeline(we->time, from, task_from, to, task_to);
787 we = we->next; 819 we = we->next;
820
821 free(task_from);
822 free(task_to);
788 } 823 }
789} 824}
790 825
@@ -858,12 +893,89 @@ static void draw_process_bars(void)
858 } 893 }
859} 894}
860 895
896static void add_process_filter(const char *string)
897{
898 struct process_filter *filt;
899 int pid;
900
901 pid = strtoull(string, NULL, 10);
902 filt = malloc(sizeof(struct process_filter));
903 if (!filt)
904 return;
905
906 filt->name = strdup(string);
907 filt->pid = pid;
908 filt->next = process_filter;
909
910 process_filter = filt;
911}
912
913static int passes_filter(struct per_pid *p, struct per_pidcomm *c)
914{
915 struct process_filter *filt;
916 if (!process_filter)
917 return 1;
918
919 filt = process_filter;
920 while (filt) {
921 if (filt->pid && p->pid == filt->pid)
922 return 1;
923 if (strcmp(filt->name, c->comm) == 0)
924 return 1;
925 filt = filt->next;
926 }
927 return 0;
928}
929
930static int determine_display_tasks_filtered(void)
931{
932 struct per_pid *p;
933 struct per_pidcomm *c;
934 int count = 0;
935
936 p = all_data;
937 while (p) {
938 p->display = 0;
939 if (p->start_time == 1)
940 p->start_time = first_time;
941
942 /* no exit marker, task kept running to the end */
943 if (p->end_time == 0)
944 p->end_time = last_time;
945
946 c = p->all;
947
948 while (c) {
949 c->display = 0;
950
951 if (c->start_time == 1)
952 c->start_time = first_time;
953
954 if (passes_filter(p, c)) {
955 c->display = 1;
956 p->display = 1;
957 count++;
958 }
959
960 if (c->end_time == 0)
961 c->end_time = last_time;
962
963 c = c->next;
964 }
965 p = p->next;
966 }
967 return count;
968}
969
861static int determine_display_tasks(u64 threshold) 970static int determine_display_tasks(u64 threshold)
862{ 971{
863 struct per_pid *p; 972 struct per_pid *p;
864 struct per_pidcomm *c; 973 struct per_pidcomm *c;
865 int count = 0; 974 int count = 0;
866 975
976 if (process_filter)
977 return determine_display_tasks_filtered();
978
867 p = all_data; 979 p = all_data;
868 while (p) { 980 while (p) {
869 p->display = 0; 981 p->display = 0;
@@ -1050,12 +1162,10 @@ more:
1050 size = event->header.size; 1162 size = event->header.size;
1051 1163
1052 if (!size || process_event(event) < 0) { 1164 if (!size || process_event(event) < 0) {
1053 1165 pr_warning("%p [%p]: skipping unknown header type: %d\n",
1054 printf("%p [%p]: skipping unknown header type: %d\n", 1166 (void *)(offset + head),
1055 (void *)(offset + head), 1167 (void *)(long)(event->header.size),
1056 (void *)(long)(event->header.size), 1168 event->header.type);
1057 event->header.type);
1058
1059 /* 1169 /*
1060 * assume we lost track of the stream, check alignment, and 1170 * assume we lost track of the stream, check alignment, and
1061 * increment a single u64 in the hope to catch on again 'soon'. 1171 * increment a single u64 in the hope to catch on again 'soon'.
@@ -1088,7 +1198,8 @@ done:
1088 1198
1089 write_svg_file(output_name); 1199 write_svg_file(output_name);
1090 1200
1091 printf("Written %2.1f seconds of trace to %s.\n", (last_time - first_time) / 1000000000.0, output_name); 1201 pr_info("Written %2.1f seconds of trace to %s.\n",
1202 (last_time - first_time) / 1000000000.0, output_name);
1092 1203
1093 return rc; 1204 return rc;
1094} 1205}
@@ -1129,6 +1240,14 @@ static int __cmd_record(int argc, const char **argv)
1129 return cmd_record(i, rec_argv, NULL); 1240 return cmd_record(i, rec_argv, NULL);
1130} 1241}
1131 1242
1243static int
1244parse_process(const struct option *opt __used, const char *arg, int __used unset)
1245{
1246 if (arg)
1247 add_process_filter(arg);
1248 return 0;
1249}
1250
1132static const struct option options[] = { 1251static const struct option options[] = {
1133 OPT_STRING('i', "input", &input_name, "file", 1252 OPT_STRING('i', "input", &input_name, "file",
1134 "input file name"), 1253 "input file name"),
@@ -1136,8 +1255,11 @@ static const struct option options[] = {
1136 "output file name"), 1255 "output file name"),
1137 OPT_INTEGER('w', "width", &svg_page_width, 1256 OPT_INTEGER('w', "width", &svg_page_width,
1138 "page width"), 1257 "page width"),
1139 OPT_BOOLEAN('p', "power-only", &power_only, 1258 OPT_BOOLEAN('P', "power-only", &power_only,
1140 "output power data only"), 1259 "output power data only"),
1260 OPT_CALLBACK('p', "process", NULL, "process",
1261 "process selector. Pass a pid or process name.",
1262 parse_process),
1141 OPT_END() 1263 OPT_END()
1142}; 1264};
1143 1265
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 37512e93623..4a9fe228be2 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -22,6 +22,7 @@
22 22
23#include "util/symbol.h" 23#include "util/symbol.h"
24#include "util/color.h" 24#include "util/color.h"
25#include "util/thread.h"
25#include "util/util.h" 26#include "util/util.h"
26#include <linux/rbtree.h> 27#include <linux/rbtree.h>
27#include "util/parse-options.h" 28#include "util/parse-options.h"
@@ -54,26 +55,26 @@
54 55
55static int fd[MAX_NR_CPUS][MAX_COUNTERS]; 56static int fd[MAX_NR_CPUS][MAX_COUNTERS];
56 57
57static int system_wide = 0; 58static int system_wide = 0;
58 59
59static int default_interval = 100000; 60static int default_interval = 0;
60 61
61static int count_filter = 5; 62static int count_filter = 5;
62static int print_entries = 15; 63static int print_entries = 15;
63 64
64static int target_pid = -1; 65static int target_pid = -1;
65static int inherit = 0; 66static int inherit = 0;
66static int profile_cpu = -1; 67static int profile_cpu = -1;
67static int nr_cpus = 0; 68static int nr_cpus = 0;
68static unsigned int realtime_prio = 0; 69static unsigned int realtime_prio = 0;
69static int group = 0; 70static int group = 0;
70static unsigned int page_size; 71static unsigned int page_size;
71static unsigned int mmap_pages = 16; 72static unsigned int mmap_pages = 16;
72static int freq = 0; 73static int freq = 1000; /* 1 KHz */
73 74
74static int delay_secs = 2; 75static int delay_secs = 2;
75static int zero; 76static int zero = 0;
76static int dump_symtab; 77static int dump_symtab = 0;
77 78
78/* 79/*
79 * Source 80 * Source
@@ -86,19 +87,16 @@ struct source_line {
86 struct source_line *next; 87 struct source_line *next;
87}; 88};
88 89
89static char *sym_filter = NULL; 90static char *sym_filter = NULL;
90struct sym_entry *sym_filter_entry = NULL; 91struct sym_entry *sym_filter_entry = NULL;
91static int sym_pcnt_filter = 5; 92static int sym_pcnt_filter = 5;
92static int sym_counter = 0; 93static int sym_counter = 0;
93static int display_weighted = -1; 94static int display_weighted = -1;
94 95
95/* 96/*
96 * Symbols 97 * Symbols
97 */ 98 */
98 99
99static u64 min_ip;
100static u64 max_ip = -1ll;
101
102struct sym_entry { 100struct sym_entry {
103 struct rb_node rb_node; 101 struct rb_node rb_node;
104 struct list_head node; 102 struct list_head node;
@@ -106,6 +104,7 @@ struct sym_entry {
106 unsigned long snap_count; 104 unsigned long snap_count;
107 double weight; 105 double weight;
108 int skip; 106 int skip;
107 struct map *map;
109 struct source_line *source; 108 struct source_line *source;
110 struct source_line *lines; 109 struct source_line *lines;
111 struct source_line **lines_tail; 110 struct source_line **lines_tail;
@@ -119,12 +118,11 @@ struct sym_entry {
119static void parse_source(struct sym_entry *syme) 118static void parse_source(struct sym_entry *syme)
120{ 119{
121 struct symbol *sym; 120 struct symbol *sym;
122 struct module *module; 121 struct map *map;
123 struct section *section = NULL;
124 FILE *file; 122 FILE *file;
125 char command[PATH_MAX*2]; 123 char command[PATH_MAX*2];
126 const char *path = vmlinux_name; 124 const char *path;
127 u64 start, end, len; 125 u64 len;
128 126
129 if (!syme) 127 if (!syme)
130 return; 128 return;
@@ -135,27 +133,16 @@ static void parse_source(struct sym_entry *syme)
135 } 133 }
136 134
137 sym = (struct symbol *)(syme + 1); 135 sym = (struct symbol *)(syme + 1);
138 module = sym->module; 136 map = syme->map;
139 137 path = map->dso->long_name;
140 if (module)
141 path = module->path;
142 if (!path)
143 return;
144
145 start = sym->obj_start;
146 if (!start)
147 start = sym->start;
148 138
149 if (module) {
150 section = module->sections->find_section(module->sections, ".text");
151 if (section)
152 start -= section->vma;
153 }
154
155 end = start + sym->end - sym->start + 1;
156 len = sym->end - sym->start; 139 len = sym->end - sym->start;
157 140
158 sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s", start, end, path); 141 sprintf(command,
142 "objdump --start-address=0x%016Lx "
143 "--stop-address=0x%016Lx -dS %s",
144 map->unmap_ip(map, sym->start),
145 map->unmap_ip(map, sym->end), path);
159 146
160 file = popen(command, "r"); 147 file = popen(command, "r");
161 if (!file) 148 if (!file)
@@ -187,13 +174,11 @@ static void parse_source(struct sym_entry *syme)
187 174
188 if (strlen(src->line)>8 && src->line[8] == ':') { 175 if (strlen(src->line)>8 && src->line[8] == ':') {
189 src->eip = strtoull(src->line, NULL, 16); 176 src->eip = strtoull(src->line, NULL, 16);
190 if (section) 177 src->eip = map->unmap_ip(map, src->eip);
191 src->eip += section->vma;
192 } 178 }
193 if (strlen(src->line)>8 && src->line[16] == ':') { 179 if (strlen(src->line)>8 && src->line[16] == ':') {
194 src->eip = strtoull(src->line, NULL, 16); 180 src->eip = strtoull(src->line, NULL, 16);
195 if (section) 181 src->eip = map->unmap_ip(map, src->eip);
196 src->eip += section->vma;
197 } 182 }
198 } 183 }
199 pclose(file); 184 pclose(file);
@@ -245,16 +230,9 @@ static void lookup_sym_source(struct sym_entry *syme)
245 struct symbol *symbol = (struct symbol *)(syme + 1); 230 struct symbol *symbol = (struct symbol *)(syme + 1);
246 struct source_line *line; 231 struct source_line *line;
247 char pattern[PATH_MAX]; 232 char pattern[PATH_MAX];
248 char *idx;
249 233
250 sprintf(pattern, "<%s>:", symbol->name); 234 sprintf(pattern, "<%s>:", symbol->name);
251 235
252 if (symbol->module) {
253 idx = strstr(pattern, "\t");
254 if (idx)
255 *idx = 0;
256 }
257
258 pthread_mutex_lock(&syme->source_lock); 236 pthread_mutex_lock(&syme->source_lock);
259 for (line = syme->lines; line; line = line->next) { 237 for (line = syme->lines; line; line = line->next) {
260 if (strstr(line->line, pattern)) { 238 if (strstr(line->line, pattern)) {
@@ -516,8 +494,8 @@ static void print_sym_table(void)
516 if (verbose) 494 if (verbose)
517 printf(" - %016llx", sym->start); 495 printf(" - %016llx", sym->start);
518 printf(" : %s", sym->name); 496 printf(" : %s", sym->name);
519 if (sym->module) 497 if (syme->map->dso->name[0] == '[')
520 printf("\t[%s]", sym->module->name); 498 printf(" \t%s", syme->map->dso->name);
521 printf("\n"); 499 printf("\n");
522 } 500 }
523} 501}
@@ -686,6 +664,8 @@ static void handle_keypress(int c)
686 switch (c) { 664 switch (c) {
687 case 'd': 665 case 'd':
688 prompt_integer(&delay_secs, "Enter display delay"); 666 prompt_integer(&delay_secs, "Enter display delay");
667 if (delay_secs < 1)
668 delay_secs = 1;
689 break; 669 break;
690 case 'e': 670 case 'e':
691 prompt_integer(&print_entries, "Enter display entries (lines)"); 671 prompt_integer(&print_entries, "Enter display entries (lines)");
@@ -788,7 +768,7 @@ static const char *skip_symbols[] = {
788 NULL 768 NULL
789}; 769};
790 770
791static int symbol_filter(struct dso *self, struct symbol *sym) 771static int symbol_filter(struct map *map, struct symbol *sym)
792{ 772{
793 struct sym_entry *syme; 773 struct sym_entry *syme;
794 const char *name = sym->name; 774 const char *name = sym->name;
@@ -810,7 +790,8 @@ static int symbol_filter(struct dso *self, struct symbol *sym)
810 strstr(name, "_text_end")) 790 strstr(name, "_text_end"))
811 return 1; 791 return 1;
812 792
813 syme = dso__sym_priv(self, sym); 793 syme = dso__sym_priv(map->dso, sym);
794 syme->map = map;
814 pthread_mutex_init(&syme->source_lock, NULL); 795 pthread_mutex_init(&syme->source_lock, NULL);
815 if (!sym_filter_entry && sym_filter && !strcmp(name, sym_filter)) 796 if (!sym_filter_entry && sym_filter && !strcmp(name, sym_filter))
816 sym_filter_entry = syme; 797 sym_filter_entry = syme;
@@ -827,34 +808,14 @@ static int symbol_filter(struct dso *self, struct symbol *sym)
827 808
828static int parse_symbols(void) 809static int parse_symbols(void)
829{ 810{
830 struct rb_node *node; 811 if (dsos__load_kernel(vmlinux_name, sizeof(struct sym_entry),
831 struct symbol *sym; 812 symbol_filter, 1) <= 0)
832 int use_modules = vmlinux_name ? 1 : 0;
833
834 kernel_dso = dso__new("[kernel]", sizeof(struct sym_entry));
835 if (kernel_dso == NULL)
836 return -1; 813 return -1;
837 814
838 if (dso__load_kernel(kernel_dso, vmlinux_name, symbol_filter, verbose, use_modules) <= 0)
839 goto out_delete_dso;
840
841 node = rb_first(&kernel_dso->syms);
842 sym = rb_entry(node, struct symbol, rb_node);
843 min_ip = sym->start;
844
845 node = rb_last(&kernel_dso->syms);
846 sym = rb_entry(node, struct symbol, rb_node);
847 max_ip = sym->end;
848
849 if (dump_symtab) 815 if (dump_symtab)
850 dso__fprintf(kernel_dso, stderr); 816 dsos__fprintf(stderr);
851 817
852 return 0; 818 return 0;
853
854out_delete_dso:
855 dso__delete(kernel_dso);
856 kernel_dso = NULL;
857 return -1;
858} 819}
859 820
860/* 821/*
@@ -862,10 +823,11 @@ out_delete_dso:
862 */ 823 */
863static void record_ip(u64 ip, int counter) 824static void record_ip(u64 ip, int counter)
864{ 825{
865 struct symbol *sym = dso__find_symbol(kernel_dso, ip); 826 struct map *map;
827 struct symbol *sym = kernel_maps__find_symbol(ip, &map);
866 828
867 if (sym != NULL) { 829 if (sym != NULL) {
868 struct sym_entry *syme = dso__sym_priv(kernel_dso, sym); 830 struct sym_entry *syme = dso__sym_priv(map->dso, sym);
869 831
870 if (!syme->skip) { 832 if (!syme->skip) {
871 syme->count[counter]++; 833 syme->count[counter]++;
@@ -911,8 +873,6 @@ static unsigned int mmap_read_head(struct mmap_data *md)
911 return head; 873 return head;
912} 874}
913 875
914struct timeval last_read, this_read;
915
916static void mmap_read_counter(struct mmap_data *md) 876static void mmap_read_counter(struct mmap_data *md)
917{ 877{
918 unsigned int head = mmap_read_head(md); 878 unsigned int head = mmap_read_head(md);
@@ -920,8 +880,6 @@ static void mmap_read_counter(struct mmap_data *md)
920 unsigned char *data = md->base + page_size; 880 unsigned char *data = md->base + page_size;
921 int diff; 881 int diff;
922 882
923 gettimeofday(&this_read, NULL);
924
925 /* 883 /*
926 * If we're further behind than half the buffer, there's a chance 884 * If we're further behind than half the buffer, there's a chance
927 * the writer will bite our tail and mess up the samples under us. 885 * the writer will bite our tail and mess up the samples under us.
@@ -932,14 +890,7 @@ static void mmap_read_counter(struct mmap_data *md)
932 */ 890 */
933 diff = head - old; 891 diff = head - old;
934 if (diff > md->mask / 2 || diff < 0) { 892 if (diff > md->mask / 2 || diff < 0) {
935 struct timeval iv; 893 fprintf(stderr, "WARNING: failed to keep up with mmap data.\n");
936 unsigned long msecs;
937
938 timersub(&this_read, &last_read, &iv);
939 msecs = iv.tv_sec*1000 + iv.tv_usec/1000;
940
941 fprintf(stderr, "WARNING: failed to keep up with mmap data."
942 " Last read %lu msecs ago.\n", msecs);
943 894
944 /* 895 /*
945 * head points to a known good entry, start there. 896 * head points to a known good entry, start there.
@@ -947,8 +898,6 @@ static void mmap_read_counter(struct mmap_data *md)
947 old = head; 898 old = head;
948 } 899 }
949 900
950 last_read = this_read;
951
952 for (; old != head;) { 901 for (; old != head;) {
953 event_t *event = (event_t *)&data[old & md->mask]; 902 event_t *event = (event_t *)&data[old & md->mask];
954 903
@@ -1016,7 +965,13 @@ static void start_counter(int i, int counter)
1016 attr = attrs + counter; 965 attr = attrs + counter;
1017 966
1018 attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID; 967 attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID;
1019 attr->freq = freq; 968
969 if (freq) {
970 attr->sample_type |= PERF_SAMPLE_PERIOD;
971 attr->freq = 1;
972 attr->sample_freq = freq;
973 }
974
1020 attr->inherit = (cpu < 0) && inherit; 975 attr->inherit = (cpu < 0) && inherit;
1021 976
1022try_again: 977try_again:
@@ -1171,11 +1126,6 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1171 if (argc) 1126 if (argc)
1172 usage_with_options(top_usage, options); 1127 usage_with_options(top_usage, options);
1173 1128
1174 if (freq) {
1175 default_interval = freq;
1176 freq = 1;
1177 }
1178
1179 /* CPU and PID are mutually exclusive */ 1129 /* CPU and PID are mutually exclusive */
1180 if (target_pid != -1 && profile_cpu != -1) { 1130 if (target_pid != -1 && profile_cpu != -1) {
1181 printf("WARNING: PID switch overriding CPU\n"); 1131 printf("WARNING: PID switch overriding CPU\n");
@@ -1192,6 +1142,19 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1192 parse_symbols(); 1142 parse_symbols();
1193 parse_source(sym_filter_entry); 1143 parse_source(sym_filter_entry);
1194 1144
1145
1146 /*
1147 * User specified count overrides default frequency.
1148 */
1149 if (default_interval)
1150 freq = 0;
1151 else if (freq) {
1152 default_interval = freq;
1153 } else {
1154 fprintf(stderr, "frequency and count are zero, aborting\n");
1155 exit(EXIT_FAILURE);
1156 }
1157
1195 /* 1158 /*
1196 * Fill in the ones not specifically initialized via -c: 1159 * Fill in the ones not specifically initialized via -c:
1197 */ 1160 */
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 0c5e4f72f2b..e566bbe3f22 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -12,28 +12,24 @@
12#include "util/debug.h" 12#include "util/debug.h"
13 13
14#include "util/trace-event.h" 14#include "util/trace-event.h"
15#include "util/data_map.h"
15 16
16static char const *input_name = "perf.data"; 17static char const *input_name = "perf.data";
17static int input;
18static unsigned long page_size;
19static unsigned long mmap_window = 32;
20 18
21static unsigned long total = 0; 19static unsigned long total = 0;
22static unsigned long total_comm = 0; 20static unsigned long total_comm = 0;
23 21
24static struct rb_root threads;
25static struct thread *last_match;
26
27static struct perf_header *header; 22static struct perf_header *header;
28static u64 sample_type; 23static u64 sample_type;
29 24
25static char *cwd;
26static int cwdlen;
27
30 28
31static int 29static int
32process_comm_event(event_t *event, unsigned long offset, unsigned long head) 30process_comm_event(event_t *event, unsigned long offset, unsigned long head)
33{ 31{
34 struct thread *thread; 32 struct thread *thread = threads__findnew(event->comm.pid);
35
36 thread = threads__findnew(event->comm.pid, &threads, &last_match);
37 33
38 dump_printf("%p [%p]: PERF_RECORD_COMM: %s:%d\n", 34 dump_printf("%p [%p]: PERF_RECORD_COMM: %s:%d\n",
39 (void *)(offset + head), 35 (void *)(offset + head),
@@ -53,18 +49,12 @@ process_comm_event(event_t *event, unsigned long offset, unsigned long head)
53static int 49static int
54process_sample_event(event_t *event, unsigned long offset, unsigned long head) 50process_sample_event(event_t *event, unsigned long offset, unsigned long head)
55{ 51{
56 char level;
57 int show = 0;
58 struct dso *dso = NULL;
59 struct thread *thread;
60 u64 ip = event->ip.ip; 52 u64 ip = event->ip.ip;
61 u64 timestamp = -1; 53 u64 timestamp = -1;
62 u32 cpu = -1; 54 u32 cpu = -1;
63 u64 period = 1; 55 u64 period = 1;
64 void *more_data = event->ip.__more_data; 56 void *more_data = event->ip.__more_data;
65 int cpumode; 57 struct thread *thread = threads__findnew(event->ip.pid);
66
67 thread = threads__findnew(event->ip.pid, &threads, &last_match);
68 58
69 if (sample_type & PERF_SAMPLE_TIME) { 59 if (sample_type & PERF_SAMPLE_TIME) {
70 timestamp = *(u64 *)more_data; 60 timestamp = *(u64 *)more_data;
@@ -90,37 +80,13 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
90 (void *)(long)ip, 80 (void *)(long)ip,
91 (long long)period); 81 (long long)period);
92 82
93 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
94
95 if (thread == NULL) { 83 if (thread == NULL) {
96 eprintf("problem processing %d event, skipping it.\n", 84 pr_debug("problem processing %d event, skipping it.\n",
97 event->header.type); 85 event->header.type);
98 return -1; 86 return -1;
99 } 87 }
100 88
101 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 89 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
102
103 if (cpumode == PERF_RECORD_MISC_KERNEL) {
104 show = SHOW_KERNEL;
105 level = 'k';
106
107 dso = kernel_dso;
108
109 dump_printf(" ...... dso: %s\n", dso->name);
110
111 } else if (cpumode == PERF_RECORD_MISC_USER) {
112
113 show = SHOW_USER;
114 level = '.';
115
116 } else {
117 show = SHOW_HV;
118 level = 'H';
119
120 dso = hypervisor_dso;
121
122 dump_printf(" ...... dso: [hypervisor]\n");
123 }
124 90
125 if (sample_type & PERF_SAMPLE_RAW) { 91 if (sample_type & PERF_SAMPLE_RAW) {
126 struct { 92 struct {
@@ -140,121 +106,32 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
140 return 0; 106 return 0;
141} 107}
142 108
143static int 109static int sample_type_check(u64 type)
144process_event(event_t *event, unsigned long offset, unsigned long head)
145{ 110{
146 trace_event(event); 111 sample_type = type;
147
148 switch (event->header.type) {
149 case PERF_RECORD_MMAP ... PERF_RECORD_LOST:
150 return 0;
151
152 case PERF_RECORD_COMM:
153 return process_comm_event(event, offset, head);
154 112
155 case PERF_RECORD_EXIT ... PERF_RECORD_READ: 113 if (!(sample_type & PERF_SAMPLE_RAW)) {
156 return 0; 114 fprintf(stderr,
157 115 "No trace sample to read. Did you call perf record "
158 case PERF_RECORD_SAMPLE: 116 "without -R?");
159 return process_sample_event(event, offset, head);
160
161 case PERF_RECORD_MAX:
162 default:
163 return -1; 117 return -1;
164 } 118 }
165 119
166 return 0; 120 return 0;
167} 121}
168 122
123static struct perf_file_handler file_handler = {
124 .process_sample_event = process_sample_event,
125 .process_comm_event = process_comm_event,
126 .sample_type_check = sample_type_check,
127};
128
169static int __cmd_trace(void) 129static int __cmd_trace(void)
170{ 130{
171 int ret, rc = EXIT_FAILURE; 131 register_idle_thread();
172 unsigned long offset = 0; 132 register_perf_file_handler(&file_handler);
173 unsigned long head = 0;
174 struct stat perf_stat;
175 event_t *event;
176 uint32_t size;
177 char *buf;
178
179 trace_report();
180 register_idle_thread(&threads, &last_match);
181
182 input = open(input_name, O_RDONLY);
183 if (input < 0) {
184 perror("failed to open file");
185 exit(-1);
186 }
187
188 ret = fstat(input, &perf_stat);
189 if (ret < 0) {
190 perror("failed to stat file");
191 exit(-1);
192 }
193
194 if (!perf_stat.st_size) {
195 fprintf(stderr, "zero-sized file, nothing to do!\n");
196 exit(0);
197 }
198 header = perf_header__read(input);
199 head = header->data_offset;
200 sample_type = perf_header__sample_type(header);
201
202 if (!(sample_type & PERF_SAMPLE_RAW))
203 die("No trace sample to read. Did you call perf record "
204 "without -R?");
205
206 if (load_kernel() < 0) {
207 perror("failed to load kernel symbols");
208 return EXIT_FAILURE;
209 }
210
211remap:
212 buf = (char *)mmap(NULL, page_size * mmap_window, PROT_READ,
213 MAP_SHARED, input, offset);
214 if (buf == MAP_FAILED) {
215 perror("failed to mmap file");
216 exit(-1);
217 }
218
219more:
220 event = (event_t *)(buf + head);
221
222 if (head + event->header.size >= page_size * mmap_window) {
223 unsigned long shift = page_size * (head / page_size);
224 int res;
225
226 res = munmap(buf, page_size * mmap_window);
227 assert(res == 0);
228
229 offset += shift;
230 head -= shift;
231 goto remap;
232 }
233
234 size = event->header.size;
235
236 if (!size || process_event(event, offset, head) < 0) {
237
238 /*
239 * assume we lost track of the stream, check alignment, and
240 * increment a single u64 in the hope to catch on again 'soon'.
241 */
242
243 if (unlikely(head & 7))
244 head &= ~7ULL;
245
246 size = 8;
247 }
248
249 head += size;
250
251 if (offset + head < (unsigned long)perf_stat.st_size)
252 goto more;
253
254 rc = EXIT_SUCCESS;
255 close(input);
256 133
257 return rc; 134 return mmap_dispatch_perf_file(&header, input_name, 0, 0, &cwdlen, &cwd);
258} 135}
259 136
260static const char * const annotate_usage[] = { 137static const char * const annotate_usage[] = {
@@ -267,13 +144,14 @@ static const struct option options[] = {
267 "dump raw trace in ASCII"), 144 "dump raw trace in ASCII"),
268 OPT_BOOLEAN('v', "verbose", &verbose, 145 OPT_BOOLEAN('v', "verbose", &verbose,
269 "be more verbose (show symbol address, etc)"), 146 "be more verbose (show symbol address, etc)"),
147 OPT_BOOLEAN('l', "latency", &latency_format,
148 "show latency attributes (irqs/preemption disabled, etc)"),
270 OPT_END() 149 OPT_END()
271}; 150};
272 151
273int cmd_trace(int argc, const char **argv, const char *prefix __used) 152int cmd_trace(int argc, const char **argv, const char *prefix __used)
274{ 153{
275 symbol__init(); 154 symbol__init();
276 page_size = getpagesize();
277 155
278 argc = parse_options(argc, argv, options, annotate_usage, 0); 156 argc = parse_options(argc, argv, options, annotate_usage, 0);
279 if (argc) { 157 if (argc) {
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index c570d177d5c..9cafe546326 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -89,8 +89,8 @@ static int handle_options(const char*** argv, int* argc, int* envchanged)
89 /* 89 /*
90 * Check remaining flags. 90 * Check remaining flags.
91 */ 91 */
92 if (!prefixcmp(cmd, "--exec-path")) { 92 if (!prefixcmp(cmd, CMD_EXEC_PATH)) {
93 cmd += 11; 93 cmd += strlen(CMD_EXEC_PATH);
94 if (*cmd == '=') 94 if (*cmd == '=')
95 perf_set_argv_exec_path(cmd + 1); 95 perf_set_argv_exec_path(cmd + 1);
96 else { 96 else {
@@ -117,8 +117,8 @@ static int handle_options(const char*** argv, int* argc, int* envchanged)
117 (*argv)++; 117 (*argv)++;
118 (*argc)--; 118 (*argc)--;
119 handled++; 119 handled++;
120 } else if (!prefixcmp(cmd, "--perf-dir=")) { 120 } else if (!prefixcmp(cmd, CMD_PERF_DIR)) {
121 setenv(PERF_DIR_ENVIRONMENT, cmd + 10, 1); 121 setenv(PERF_DIR_ENVIRONMENT, cmd + strlen(CMD_PERF_DIR), 1);
122 if (envchanged) 122 if (envchanged)
123 *envchanged = 1; 123 *envchanged = 1;
124 } else if (!strcmp(cmd, "--work-tree")) { 124 } else if (!strcmp(cmd, "--work-tree")) {
@@ -131,8 +131,8 @@ static int handle_options(const char*** argv, int* argc, int* envchanged)
131 *envchanged = 1; 131 *envchanged = 1;
132 (*argv)++; 132 (*argv)++;
133 (*argc)--; 133 (*argc)--;
134 } else if (!prefixcmp(cmd, "--work-tree=")) { 134 } else if (!prefixcmp(cmd, CMD_WORK_TREE)) {
135 setenv(PERF_WORK_TREE_ENVIRONMENT, cmd + 12, 1); 135 setenv(PERF_WORK_TREE_ENVIRONMENT, cmd + strlen(CMD_WORK_TREE), 1);
136 if (envchanged) 136 if (envchanged)
137 *envchanged = 1; 137 *envchanged = 1;
138 } else if (!strcmp(cmd, "--debugfs-dir")) { 138 } else if (!strcmp(cmd, "--debugfs-dir")) {
@@ -146,8 +146,8 @@ static int handle_options(const char*** argv, int* argc, int* envchanged)
146 *envchanged = 1; 146 *envchanged = 1;
147 (*argv)++; 147 (*argv)++;
148 (*argc)--; 148 (*argc)--;
149 } else if (!prefixcmp(cmd, "--debugfs-dir=")) { 149 } else if (!prefixcmp(cmd, CMD_DEBUGFS_DIR)) {
150 strncpy(debugfs_mntpt, cmd + 14, MAXPATHLEN); 150 strncpy(debugfs_mntpt, cmd + strlen(CMD_DEBUGFS_DIR), MAXPATHLEN);
151 debugfs_mntpt[MAXPATHLEN - 1] = '\0'; 151 debugfs_mntpt[MAXPATHLEN - 1] = '\0';
152 if (envchanged) 152 if (envchanged)
153 *envchanged = 1; 153 *envchanged = 1;
diff --git a/tools/perf/util/PERF-VERSION-GEN b/tools/perf/util/PERF-VERSION-GEN
index c561d1538c0..54552a00a11 100755
--- a/tools/perf/util/PERF-VERSION-GEN
+++ b/tools/perf/util/PERF-VERSION-GEN
@@ -1,7 +1,7 @@
1#!/bin/sh 1#!/bin/sh
2 2
3GVF=PERF-VERSION-FILE 3GVF=PERF-VERSION-FILE
4DEF_VER=v0.0.1.PERF 4DEF_VER=v0.0.2.PERF
5 5
6LF=' 6LF='
7' 7'
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index 6f8ea9d210b..918eb376abe 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -1,10 +1,15 @@
1#ifndef CACHE_H 1#ifndef __PERF_CACHE_H
2#define CACHE_H 2#define __PERF_CACHE_H
3 3
4#include "util.h" 4#include "util.h"
5#include "strbuf.h" 5#include "strbuf.h"
6#include "../perf.h" 6#include "../perf.h"
7 7
8#define CMD_EXEC_PATH "--exec-path"
9#define CMD_PERF_DIR "--perf-dir="
10#define CMD_WORK_TREE "--work-tree="
11#define CMD_DEBUGFS_DIR "--debugfs-dir="
12
8#define PERF_DIR_ENVIRONMENT "PERF_DIR" 13#define PERF_DIR_ENVIRONMENT "PERF_DIR"
9#define PERF_WORK_TREE_ENVIRONMENT "PERF_WORK_TREE" 14#define PERF_WORK_TREE_ENVIRONMENT "PERF_WORK_TREE"
10#define DEFAULT_PERF_DIR_ENVIRONMENT ".perf" 15#define DEFAULT_PERF_DIR_ENVIRONMENT ".perf"
@@ -117,4 +122,4 @@ extern char *perf_pathdup(const char *fmt, ...)
117 122
118extern size_t strlcpy(char *dest, const char *src, size_t size); 123extern size_t strlcpy(char *dest, const char *src, size_t size);
119 124
120#endif /* CACHE_H */ 125#endif /* __PERF_CACHE_H */
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index 3b8380f1b47..b3b71258272 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -206,7 +206,7 @@ fill_node(struct callchain_node *node, struct ip_callchain *chain,
206 } 206 }
207 node->val_nr = chain->nr - start; 207 node->val_nr = chain->nr - start;
208 if (!node->val_nr) 208 if (!node->val_nr)
209 printf("Warning: empty node in callchain tree\n"); 209 pr_warning("Warning: empty node in callchain tree\n");
210} 210}
211 211
212static void 212static void
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index 43cf3ea9e08..ad4626de4c2 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -58,4 +58,4 @@ static inline u64 cumul_hits(struct callchain_node *node)
58int register_callchain_param(struct callchain_param *param); 58int register_callchain_param(struct callchain_param *param);
59void append_chain(struct callchain_node *root, struct ip_callchain *chain, 59void append_chain(struct callchain_node *root, struct ip_callchain *chain,
60 struct symbol **syms); 60 struct symbol **syms);
61#endif 61#endif /* __PERF_CALLCHAIN_H */
diff --git a/tools/perf/util/color.h b/tools/perf/util/color.h
index 58d597564b9..24e8809210b 100644
--- a/tools/perf/util/color.h
+++ b/tools/perf/util/color.h
@@ -1,5 +1,5 @@
1#ifndef COLOR_H 1#ifndef __PERF_COLOR_H
2#define COLOR_H 2#define __PERF_COLOR_H
3 3
4/* "\033[1;38;5;2xx;48;5;2xxm\0" is 23 bytes */ 4/* "\033[1;38;5;2xx;48;5;2xxm\0" is 23 bytes */
5#define COLOR_MAXLEN 24 5#define COLOR_MAXLEN 24
@@ -39,4 +39,4 @@ int color_fwrite_lines(FILE *fp, const char *color, size_t count, const char *bu
39int percent_color_fprintf(FILE *fp, const char *fmt, double percent); 39int percent_color_fprintf(FILE *fp, const char *fmt, double percent);
40const char *get_percent_color(double percent); 40const char *get_percent_color(double percent);
41 41
42#endif /* COLOR_H */ 42#endif /* __PERF_COLOR_H */
diff --git a/tools/perf/util/data_map.c b/tools/perf/util/data_map.c
new file mode 100644
index 00000000000..18accb8fee4
--- /dev/null
+++ b/tools/perf/util/data_map.c
@@ -0,0 +1,222 @@
1#include "data_map.h"
2#include "symbol.h"
3#include "util.h"
4#include "debug.h"
5
6
7static struct perf_file_handler *curr_handler;
8static unsigned long mmap_window = 32;
9static char __cwd[PATH_MAX];
10
11static int
12process_event_stub(event_t *event __used,
13 unsigned long offset __used,
14 unsigned long head __used)
15{
16 return 0;
17}
18
19void register_perf_file_handler(struct perf_file_handler *handler)
20{
21 if (!handler->process_sample_event)
22 handler->process_sample_event = process_event_stub;
23 if (!handler->process_mmap_event)
24 handler->process_mmap_event = process_event_stub;
25 if (!handler->process_comm_event)
26 handler->process_comm_event = process_event_stub;
27 if (!handler->process_fork_event)
28 handler->process_fork_event = process_event_stub;
29 if (!handler->process_exit_event)
30 handler->process_exit_event = process_event_stub;
31 if (!handler->process_lost_event)
32 handler->process_lost_event = process_event_stub;
33 if (!handler->process_read_event)
34 handler->process_read_event = process_event_stub;
35 if (!handler->process_throttle_event)
36 handler->process_throttle_event = process_event_stub;
37 if (!handler->process_unthrottle_event)
38 handler->process_unthrottle_event = process_event_stub;
39
40 curr_handler = handler;
41}
42
43static int
44process_event(event_t *event, unsigned long offset, unsigned long head)
45{
46 trace_event(event);
47
48 switch (event->header.type) {
49 case PERF_RECORD_SAMPLE:
50 return curr_handler->process_sample_event(event, offset, head);
51 case PERF_RECORD_MMAP:
52 return curr_handler->process_mmap_event(event, offset, head);
53 case PERF_RECORD_COMM:
54 return curr_handler->process_comm_event(event, offset, head);
55 case PERF_RECORD_FORK:
56 return curr_handler->process_fork_event(event, offset, head);
57 case PERF_RECORD_EXIT:
58 return curr_handler->process_exit_event(event, offset, head);
59 case PERF_RECORD_LOST:
60 return curr_handler->process_lost_event(event, offset, head);
61 case PERF_RECORD_READ:
62 return curr_handler->process_read_event(event, offset, head);
63 case PERF_RECORD_THROTTLE:
64 return curr_handler->process_throttle_event(event, offset, head);
65 case PERF_RECORD_UNTHROTTLE:
66 return curr_handler->process_unthrottle_event(event, offset, head);
67 default:
68 curr_handler->total_unknown++;
69 return -1;
70 }
71}
72
73int mmap_dispatch_perf_file(struct perf_header **pheader,
74 const char *input_name,
75 int force,
76 int full_paths,
77 int *cwdlen,
78 char **cwd)
79{
80 int ret, rc = EXIT_FAILURE;
81 struct perf_header *header;
82 unsigned long head, shift;
83 unsigned long offset = 0;
84 struct stat input_stat;
85 size_t page_size;
86 u64 sample_type;
87 event_t *event;
88 uint32_t size;
89 int input;
90 char *buf;
91
92 if (!curr_handler)
93 die("Forgot to register perf file handler");
94
95 page_size = getpagesize();
96
97 input = open(input_name, O_RDONLY);
98 if (input < 0) {
99 fprintf(stderr, " failed to open file: %s", input_name);
100 if (!strcmp(input_name, "perf.data"))
101 fprintf(stderr, " (try 'perf record' first)");
102 fprintf(stderr, "\n");
103 exit(-1);
104 }
105
106 ret = fstat(input, &input_stat);
107 if (ret < 0) {
108 perror("failed to stat file");
109 exit(-1);
110 }
111
112 if (!force && input_stat.st_uid && (input_stat.st_uid != geteuid())) {
113 fprintf(stderr, "file: %s not owned by current user or root\n",
114 input_name);
115 exit(-1);
116 }
117
118 if (!input_stat.st_size) {
119 fprintf(stderr, "zero-sized file, nothing to do!\n");
120 exit(0);
121 }
122
123 *pheader = perf_header__read(input);
124 header = *pheader;
125 head = header->data_offset;
126
127 sample_type = perf_header__sample_type(header);
128
129 if (curr_handler->sample_type_check)
130 if (curr_handler->sample_type_check(sample_type) < 0)
131 exit(-1);
132
133 if (load_kernel(0, NULL) < 0) {
134 perror("failed to load kernel symbols");
135 return EXIT_FAILURE;
136 }
137
138 if (!full_paths) {
139 if (getcwd(__cwd, sizeof(__cwd)) == NULL) {
140 perror("failed to get the current directory");
141 return EXIT_FAILURE;
142 }
143 *cwd = __cwd;
144 *cwdlen = strlen(*cwd);
145 } else {
146 *cwd = NULL;
147 *cwdlen = 0;
148 }
149
150 shift = page_size * (head / page_size);
151 offset += shift;
152 head -= shift;
153
154remap:
155 buf = (char *)mmap(NULL, page_size * mmap_window, PROT_READ,
156 MAP_SHARED, input, offset);
157 if (buf == MAP_FAILED) {
158 perror("failed to mmap file");
159 exit(-1);
160 }
161
162more:
163 event = (event_t *)(buf + head);
164
165 size = event->header.size;
166 if (!size)
167 size = 8;
168
169 if (head + event->header.size >= page_size * mmap_window) {
170 int munmap_ret;
171
172 shift = page_size * (head / page_size);
173
174 munmap_ret = munmap(buf, page_size * mmap_window);
175 assert(munmap_ret == 0);
176
177 offset += shift;
178 head -= shift;
179 goto remap;
180 }
181
182 size = event->header.size;
183
184 dump_printf("\n%p [%p]: event: %d\n",
185 (void *)(offset + head),
186 (void *)(long)event->header.size,
187 event->header.type);
188
189 if (!size || process_event(event, offset, head) < 0) {
190
191 dump_printf("%p [%p]: skipping unknown header type: %d\n",
192 (void *)(offset + head),
193 (void *)(long)(event->header.size),
194 event->header.type);
195
196 /*
197 * assume we lost track of the stream, check alignment, and
198 * increment a single u64 in the hope to catch on again 'soon'.
199 */
200
201 if (unlikely(head & 7))
202 head &= ~7ULL;
203
204 size = 8;
205 }
206
207 head += size;
208
209 if (offset + head >= header->data_offset + header->data_size)
210 goto done;
211
212 if (offset + head < (unsigned long)input_stat.st_size)
213 goto more;
214
215done:
216 rc = EXIT_SUCCESS;
217 close(input);
218
219 return rc;
220}
221
222
diff --git a/tools/perf/util/data_map.h b/tools/perf/util/data_map.h
new file mode 100644
index 00000000000..716d1053b07
--- /dev/null
+++ b/tools/perf/util/data_map.h
@@ -0,0 +1,31 @@
1#ifndef __PERF_DATAMAP_H
2#define __PERF_DATAMAP_H
3
4#include "event.h"
5#include "header.h"
6
7typedef int (*event_type_handler_t)(event_t *, unsigned long, unsigned long);
8
9struct perf_file_handler {
10 event_type_handler_t process_sample_event;
11 event_type_handler_t process_mmap_event;
12 event_type_handler_t process_comm_event;
13 event_type_handler_t process_fork_event;
14 event_type_handler_t process_exit_event;
15 event_type_handler_t process_lost_event;
16 event_type_handler_t process_read_event;
17 event_type_handler_t process_throttle_event;
18 event_type_handler_t process_unthrottle_event;
19 int (*sample_type_check)(u64 sample_type);
20 unsigned long total_unknown;
21};
22
23void register_perf_file_handler(struct perf_file_handler *handler);
24int mmap_dispatch_perf_file(struct perf_header **pheader,
25 const char *input_name,
26 int force,
27 int full_paths,
28 int *cwdlen,
29 char **cwd);
30
31#endif
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index e8ca98fe0bd..28d520d5a1f 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -13,12 +13,12 @@
13int verbose = 0; 13int verbose = 0;
14int dump_trace = 0; 14int dump_trace = 0;
15 15
16int eprintf(const char *fmt, ...) 16int eprintf(int level, const char *fmt, ...)
17{ 17{
18 va_list args; 18 va_list args;
19 int ret = 0; 19 int ret = 0;
20 20
21 if (verbose) { 21 if (verbose >= level) {
22 va_start(args, fmt); 22 va_start(args, fmt);
23 ret = vfprintf(stderr, fmt, args); 23 ret = vfprintf(stderr, fmt, args);
24 va_end(args); 24 va_end(args);
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h
index 437eea58ce4..e8b18a1f87a 100644
--- a/tools/perf/util/debug.h
+++ b/tools/perf/util/debug.h
@@ -1,8 +1,13 @@
1/* For debugging general purposes */ 1/* For debugging general purposes */
2#ifndef __PERF_DEBUG_H
3#define __PERF_DEBUG_H
2 4
3extern int verbose; 5extern int verbose;
4extern int dump_trace; 6extern int dump_trace;
5 7
6int eprintf(const char *fmt, ...) __attribute__((format(printf, 1, 2))); 8int eprintf(int level,
9 const char *fmt, ...) __attribute__((format(printf, 2, 3)));
7int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2))); 10int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
8void trace_event(event_t *event); 11void trace_event(event_t *event);
12
13#endif /* __PERF_DEBUG_H */
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 2c9c26d6ded..d972b4b0d38 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -1,14 +1,10 @@
1#ifndef __PERF_RECORD_H 1#ifndef __PERF_RECORD_H
2#define __PERF_RECORD_H 2#define __PERF_RECORD_H
3
3#include "../perf.h" 4#include "../perf.h"
4#include "util.h" 5#include "util.h"
5#include <linux/list.h> 6#include <linux/list.h>
6 7#include <linux/rbtree.h>
7enum {
8 SHOW_KERNEL = 1,
9 SHOW_USER = 2,
10 SHOW_HV = 4,
11};
12 8
13/* 9/*
14 * PERF_SAMPLE_IP | PERF_SAMPLE_TID | * 10 * PERF_SAMPLE_IP | PERF_SAMPLE_TID | *
@@ -78,11 +74,15 @@ typedef union event_union {
78} event_t; 74} event_t;
79 75
80struct map { 76struct map {
81 struct list_head node; 77 union {
78 struct rb_node rb_node;
79 struct list_head node;
80 };
82 u64 start; 81 u64 start;
83 u64 end; 82 u64 end;
84 u64 pgoff; 83 u64 pgoff;
85 u64 (*map_ip)(struct map *, u64); 84 u64 (*map_ip)(struct map *, u64);
85 u64 (*unmap_ip)(struct map *, u64);
86 struct dso *dso; 86 struct dso *dso;
87}; 87};
88 88
@@ -91,14 +91,24 @@ static inline u64 map__map_ip(struct map *map, u64 ip)
91 return ip - map->start + map->pgoff; 91 return ip - map->start + map->pgoff;
92} 92}
93 93
94static inline u64 vdso__map_ip(struct map *map __used, u64 ip) 94static inline u64 map__unmap_ip(struct map *map, u64 ip)
95{
96 return ip + map->start - map->pgoff;
97}
98
99static inline u64 identity__map_ip(struct map *map __used, u64 ip)
95{ 100{
96 return ip; 101 return ip;
97} 102}
98 103
99struct map *map__new(struct mmap_event *event, char *cwd, int cwdlen); 104struct symbol;
105
106typedef int (*symbol_filter_t)(struct map *map, struct symbol *sym);
107
108struct map *map__new(struct mmap_event *event, char *cwd, int cwdlen,
109 unsigned int sym_priv_size, symbol_filter_t filter);
100struct map *map__clone(struct map *self); 110struct map *map__clone(struct map *self);
101int map__overlap(struct map *l, struct map *r); 111int map__overlap(struct map *l, struct map *r);
102size_t map__fprintf(struct map *self, FILE *fp); 112size_t map__fprintf(struct map *self, FILE *fp);
103 113
104#endif 114#endif /* __PERF_RECORD_H */
diff --git a/tools/perf/util/exec_cmd.h b/tools/perf/util/exec_cmd.h
index effe25eb154..31647ac92ed 100644
--- a/tools/perf/util/exec_cmd.h
+++ b/tools/perf/util/exec_cmd.h
@@ -1,5 +1,5 @@
1#ifndef PERF_EXEC_CMD_H 1#ifndef __PERF_EXEC_CMD_H
2#define PERF_EXEC_CMD_H 2#define __PERF_EXEC_CMD_H
3 3
4extern void perf_set_argv_exec_path(const char *exec_path); 4extern void perf_set_argv_exec_path(const char *exec_path);
5extern const char *perf_extract_argv0_path(const char *path); 5extern const char *perf_extract_argv0_path(const char *path);
@@ -10,4 +10,4 @@ extern int execv_perf_cmd(const char **argv); /* NULL terminated */
10extern int execl_perf_cmd(const char *cmd, ...); 10extern int execl_perf_cmd(const char *cmd, ...);
11extern const char *system_path(const char *path); 11extern const char *system_path(const char *path);
12 12
13#endif /* PERF_EXEC_CMD_H */ 13#endif /* __PERF_EXEC_CMD_H */
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index e306857b2c2..7d26659b806 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -5,6 +5,8 @@
5 5
6#include "util.h" 6#include "util.h"
7#include "header.h" 7#include "header.h"
8#include "../perf.h"
9#include "trace-event.h"
8 10
9/* 11/*
10 * Create new perf.data header attribute: 12 * Create new perf.data header attribute:
@@ -46,23 +48,17 @@ void perf_header_attr__add_id(struct perf_header_attr *self, u64 id)
46 */ 48 */
47struct perf_header *perf_header__new(void) 49struct perf_header *perf_header__new(void)
48{ 50{
49 struct perf_header *self = malloc(sizeof(*self)); 51 struct perf_header *self = calloc(sizeof(*self), 1);
50 52
51 if (!self) 53 if (!self)
52 die("nomem"); 54 die("nomem");
53 55
54 self->frozen = 0;
55
56 self->attrs = 0;
57 self->size = 1; 56 self->size = 1;
58 self->attr = malloc(sizeof(void *)); 57 self->attr = malloc(sizeof(void *));
59 58
60 if (!self->attr) 59 if (!self->attr)
61 die("nomem"); 60 die("nomem");
62 61
63 self->data_offset = 0;
64 self->data_size = 0;
65
66 return self; 62 return self;
67} 63}
68 64
@@ -97,7 +93,7 @@ static struct perf_trace_event_type *events;
97void perf_header__push_event(u64 id, const char *name) 93void perf_header__push_event(u64 id, const char *name)
98{ 94{
99 if (strlen(name) > MAX_EVENT_NAME) 95 if (strlen(name) > MAX_EVENT_NAME)
100 printf("Event %s will be truncated\n", name); 96 pr_warning("Event %s will be truncated\n", name);
101 97
102 if (!events) { 98 if (!events) {
103 events = malloc(sizeof(struct perf_trace_event_type)); 99 events = malloc(sizeof(struct perf_trace_event_type));
@@ -145,8 +141,14 @@ struct perf_file_header {
145 struct perf_file_section attrs; 141 struct perf_file_section attrs;
146 struct perf_file_section data; 142 struct perf_file_section data;
147 struct perf_file_section event_types; 143 struct perf_file_section event_types;
144 DECLARE_BITMAP(adds_features, HEADER_FEAT_BITS);
148}; 145};
149 146
147void perf_header__feat_trace_info(struct perf_header *header)
148{
149 set_bit(HEADER_TRACE_INFO, header->adds_features);
150}
151
150static void do_write(int fd, void *buf, size_t size) 152static void do_write(int fd, void *buf, size_t size)
151{ 153{
152 while (size) { 154 while (size) {
@@ -160,6 +162,32 @@ static void do_write(int fd, void *buf, size_t size)
160 } 162 }
161} 163}
162 164
165static void perf_header__adds_write(struct perf_header *self, int fd)
166{
167 struct perf_file_section trace_sec;
168 u64 cur_offset = lseek(fd, 0, SEEK_CUR);
169 unsigned long *feat_mask = self->adds_features;
170
171 if (test_bit(HEADER_TRACE_INFO, feat_mask)) {
172 /* Write trace info */
173 trace_sec.offset = lseek(fd, sizeof(trace_sec), SEEK_CUR);
174 read_tracing_data(fd, attrs, nr_counters);
175 trace_sec.size = lseek(fd, 0, SEEK_CUR) - trace_sec.offset;
176
177 /* Write trace info headers */
178 lseek(fd, cur_offset, SEEK_SET);
179 do_write(fd, &trace_sec, sizeof(trace_sec));
180
181 /*
182 * Update cur_offset. So that other (future)
183 * features can set their own infos in this place. But if we are
184 * the only feature, at least that seeks to the place the data
185 * should begin.
186 */
187 cur_offset = lseek(fd, trace_sec.offset + trace_sec.size, SEEK_SET);
188 }
189};
190
163void perf_header__write(struct perf_header *self, int fd) 191void perf_header__write(struct perf_header *self, int fd)
164{ 192{
165 struct perf_file_header f_header; 193 struct perf_file_header f_header;
@@ -198,6 +226,7 @@ void perf_header__write(struct perf_header *self, int fd)
198 if (events) 226 if (events)
199 do_write(fd, events, self->event_size); 227 do_write(fd, events, self->event_size);
200 228
229 perf_header__adds_write(self, fd);
201 230
202 self->data_offset = lseek(fd, 0, SEEK_CUR); 231 self->data_offset = lseek(fd, 0, SEEK_CUR);
203 232
@@ -219,6 +248,8 @@ void perf_header__write(struct perf_header *self, int fd)
219 }, 248 },
220 }; 249 };
221 250
251 memcpy(&f_header.adds_features, &self->adds_features, sizeof(self->adds_features));
252
222 lseek(fd, 0, SEEK_SET); 253 lseek(fd, 0, SEEK_SET);
223 do_write(fd, &f_header, sizeof(f_header)); 254 do_write(fd, &f_header, sizeof(f_header));
224 lseek(fd, self->data_offset + self->data_size, SEEK_SET); 255 lseek(fd, self->data_offset + self->data_size, SEEK_SET);
@@ -241,6 +272,20 @@ static void do_read(int fd, void *buf, size_t size)
241 } 272 }
242} 273}
243 274
275static void perf_header__adds_read(struct perf_header *self, int fd)
276{
277 const unsigned long *feat_mask = self->adds_features;
278
279 if (test_bit(HEADER_TRACE_INFO, feat_mask)) {
280 struct perf_file_section trace_sec;
281
282 do_read(fd, &trace_sec, sizeof(trace_sec));
283 lseek(fd, trace_sec.offset, SEEK_SET);
284 trace_report(fd);
285 lseek(fd, trace_sec.offset + trace_sec.size, SEEK_SET);
286 }
287};
288
244struct perf_header *perf_header__read(int fd) 289struct perf_header *perf_header__read(int fd)
245{ 290{
246 struct perf_header *self = perf_header__new(); 291 struct perf_header *self = perf_header__new();
@@ -254,10 +299,16 @@ struct perf_header *perf_header__read(int fd)
254 do_read(fd, &f_header, sizeof(f_header)); 299 do_read(fd, &f_header, sizeof(f_header));
255 300
256 if (f_header.magic != PERF_MAGIC || 301 if (f_header.magic != PERF_MAGIC ||
257 f_header.size != sizeof(f_header) ||
258 f_header.attr_size != sizeof(f_attr)) 302 f_header.attr_size != sizeof(f_attr))
259 die("incompatible file format"); 303 die("incompatible file format");
260 304
305 if (f_header.size != sizeof(f_header)) {
306 /* Support the previous format */
307 if (f_header.size == offsetof(typeof(f_header), adds_features))
308 bitmap_zero(f_header.adds_features, HEADER_FEAT_BITS);
309 else
310 die("incompatible file format");
311 }
261 nr_attrs = f_header.attrs.size / sizeof(f_attr); 312 nr_attrs = f_header.attrs.size / sizeof(f_attr);
262 lseek(fd, f_header.attrs.offset, SEEK_SET); 313 lseek(fd, f_header.attrs.offset, SEEK_SET);
263 314
@@ -290,6 +341,11 @@ struct perf_header *perf_header__read(int fd)
290 do_read(fd, events, f_header.event_types.size); 341 do_read(fd, events, f_header.event_types.size);
291 event_count = f_header.event_types.size / sizeof(struct perf_trace_event_type); 342 event_count = f_header.event_types.size / sizeof(struct perf_trace_event_type);
292 } 343 }
344
345 memcpy(&self->adds_features, &f_header.adds_features, sizeof(f_header.adds_features));
346
347 perf_header__adds_read(self, fd);
348
293 self->event_offset = f_header.event_types.offset; 349 self->event_offset = f_header.event_types.offset;
294 self->event_size = f_header.event_types.size; 350 self->event_size = f_header.event_types.size;
295 351
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index a0761bc7863..2ea9dfb1236 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -1,10 +1,12 @@
1#ifndef _PERF_HEADER_H 1#ifndef __PERF_HEADER_H
2#define _PERF_HEADER_H 2#define __PERF_HEADER_H
3 3
4#include "../../../include/linux/perf_event.h" 4#include "../../../include/linux/perf_event.h"
5#include <sys/types.h> 5#include <sys/types.h>
6#include "types.h" 6#include "types.h"
7 7
8#include <linux/bitmap.h>
9
8struct perf_header_attr { 10struct perf_header_attr {
9 struct perf_event_attr attr; 11 struct perf_event_attr attr;
10 int ids, size; 12 int ids, size;
@@ -12,15 +14,20 @@ struct perf_header_attr {
12 off_t id_offset; 14 off_t id_offset;
13}; 15};
14 16
17#define HEADER_TRACE_INFO 1
18
19#define HEADER_FEAT_BITS 256
20
15struct perf_header { 21struct perf_header {
16 int frozen; 22 int frozen;
17 int attrs, size; 23 int attrs, size;
18 struct perf_header_attr **attr; 24 struct perf_header_attr **attr;
19 s64 attr_offset; 25 s64 attr_offset;
20 u64 data_offset; 26 u64 data_offset;
21 u64 data_size; 27 u64 data_size;
22 u64 event_offset; 28 u64 event_offset;
23 u64 event_size; 29 u64 event_size;
30 DECLARE_BITMAP(adds_features, HEADER_FEAT_BITS);
24}; 31};
25 32
26struct perf_header *perf_header__read(int fd); 33struct perf_header *perf_header__read(int fd);
@@ -40,8 +47,8 @@ void perf_header_attr__add_id(struct perf_header_attr *self, u64 id);
40u64 perf_header__sample_type(struct perf_header *header); 47u64 perf_header__sample_type(struct perf_header *header);
41struct perf_event_attr * 48struct perf_event_attr *
42perf_header__find_attr(u64 id, struct perf_header *header); 49perf_header__find_attr(u64 id, struct perf_header *header);
43 50void perf_header__feat_trace_info(struct perf_header *header);
44 51
45struct perf_header *perf_header__new(void); 52struct perf_header *perf_header__new(void);
46 53
47#endif /* _PERF_HEADER_H */ 54#endif /* __PERF_HEADER_H */
diff --git a/tools/perf/util/help.h b/tools/perf/util/help.h
index 7128783637b..7f5c6dedd71 100644
--- a/tools/perf/util/help.h
+++ b/tools/perf/util/help.h
@@ -1,5 +1,5 @@
1#ifndef HELP_H 1#ifndef __PERF_HELP_H
2#define HELP_H 2#define __PERF_HELP_H
3 3
4struct cmdnames { 4struct cmdnames {
5 size_t alloc; 5 size_t alloc;
@@ -26,4 +26,4 @@ int is_in_cmdlist(struct cmdnames *c, const char *s);
26void list_commands(const char *title, struct cmdnames *main_cmds, 26void list_commands(const char *title, struct cmdnames *main_cmds,
27 struct cmdnames *other_cmds); 27 struct cmdnames *other_cmds);
28 28
29#endif /* HELP_H */ 29#endif /* __PERF_HELP_H */
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
new file mode 100644
index 00000000000..7393a02fd8d
--- /dev/null
+++ b/tools/perf/util/hist.c
@@ -0,0 +1,210 @@
1#include "hist.h"
2
3struct rb_root hist;
4struct rb_root collapse_hists;
5struct rb_root output_hists;
6int callchain;
7
8struct callchain_param callchain_param = {
9 .mode = CHAIN_GRAPH_REL,
10 .min_percent = 0.5
11};
12
13unsigned long total;
14unsigned long total_mmap;
15unsigned long total_comm;
16unsigned long total_fork;
17unsigned long total_unknown;
18unsigned long total_lost;
19
20/*
21 * histogram, sorted on item, collects counts
22 */
23
24struct hist_entry *__hist_entry__add(struct thread *thread, struct map *map,
25 struct symbol *sym,
26 struct symbol *sym_parent,
27 u64 ip, u64 count, char level, bool *hit)
28{
29 struct rb_node **p = &hist.rb_node;
30 struct rb_node *parent = NULL;
31 struct hist_entry *he;
32 struct hist_entry entry = {
33 .thread = thread,
34 .map = map,
35 .sym = sym,
36 .ip = ip,
37 .level = level,
38 .count = count,
39 .parent = sym_parent,
40 };
41 int cmp;
42
43 while (*p != NULL) {
44 parent = *p;
45 he = rb_entry(parent, struct hist_entry, rb_node);
46
47 cmp = hist_entry__cmp(&entry, he);
48
49 if (!cmp) {
50 *hit = true;
51 return he;
52 }
53
54 if (cmp < 0)
55 p = &(*p)->rb_left;
56 else
57 p = &(*p)->rb_right;
58 }
59
60 he = malloc(sizeof(*he));
61 if (!he)
62 return NULL;
63 *he = entry;
64 rb_link_node(&he->rb_node, parent, p);
65 rb_insert_color(&he->rb_node, &hist);
66 *hit = false;
67 return he;
68}
69
70int64_t
71hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)
72{
73 struct sort_entry *se;
74 int64_t cmp = 0;
75
76 list_for_each_entry(se, &hist_entry__sort_list, list) {
77 cmp = se->cmp(left, right);
78 if (cmp)
79 break;
80 }
81
82 return cmp;
83}
84
85int64_t
86hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
87{
88 struct sort_entry *se;
89 int64_t cmp = 0;
90
91 list_for_each_entry(se, &hist_entry__sort_list, list) {
92 int64_t (*f)(struct hist_entry *, struct hist_entry *);
93
94 f = se->collapse ?: se->cmp;
95
96 cmp = f(left, right);
97 if (cmp)
98 break;
99 }
100
101 return cmp;
102}
103
104void hist_entry__free(struct hist_entry *he)
105{
106 free(he);
107}
108
109/*
110 * collapse the histogram
111 */
112
113void collapse__insert_entry(struct hist_entry *he)
114{
115 struct rb_node **p = &collapse_hists.rb_node;
116 struct rb_node *parent = NULL;
117 struct hist_entry *iter;
118 int64_t cmp;
119
120 while (*p != NULL) {
121 parent = *p;
122 iter = rb_entry(parent, struct hist_entry, rb_node);
123
124 cmp = hist_entry__collapse(iter, he);
125
126 if (!cmp) {
127 iter->count += he->count;
128 hist_entry__free(he);
129 return;
130 }
131
132 if (cmp < 0)
133 p = &(*p)->rb_left;
134 else
135 p = &(*p)->rb_right;
136 }
137
138 rb_link_node(&he->rb_node, parent, p);
139 rb_insert_color(&he->rb_node, &collapse_hists);
140}
141
142void collapse__resort(void)
143{
144 struct rb_node *next;
145 struct hist_entry *n;
146
147 if (!sort__need_collapse)
148 return;
149
150 next = rb_first(&hist);
151 while (next) {
152 n = rb_entry(next, struct hist_entry, rb_node);
153 next = rb_next(&n->rb_node);
154
155 rb_erase(&n->rb_node, &hist);
156 collapse__insert_entry(n);
157 }
158}
159
160/*
161 * reverse the map, sort on count.
162 */
163
164void output__insert_entry(struct hist_entry *he, u64 min_callchain_hits)
165{
166 struct rb_node **p = &output_hists.rb_node;
167 struct rb_node *parent = NULL;
168 struct hist_entry *iter;
169
170 if (callchain)
171 callchain_param.sort(&he->sorted_chain, &he->callchain,
172 min_callchain_hits, &callchain_param);
173
174 while (*p != NULL) {
175 parent = *p;
176 iter = rb_entry(parent, struct hist_entry, rb_node);
177
178 if (he->count > iter->count)
179 p = &(*p)->rb_left;
180 else
181 p = &(*p)->rb_right;
182 }
183
184 rb_link_node(&he->rb_node, parent, p);
185 rb_insert_color(&he->rb_node, &output_hists);
186}
187
188void output__resort(u64 total_samples)
189{
190 struct rb_node *next;
191 struct hist_entry *n;
192 struct rb_root *tree = &hist;
193 u64 min_callchain_hits;
194
195 min_callchain_hits =
196 total_samples * (callchain_param.min_percent / 100);
197
198 if (sort__need_collapse)
199 tree = &collapse_hists;
200
201 next = rb_first(tree);
202
203 while (next) {
204 n = rb_entry(next, struct hist_entry, rb_node);
205 next = rb_next(&n->rb_node);
206
207 rb_erase(&n->rb_node, tree);
208 output__insert_entry(n, min_callchain_hits);
209 }
210}
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
new file mode 100644
index 00000000000..ac2149c559b
--- /dev/null
+++ b/tools/perf/util/hist.h
@@ -0,0 +1,50 @@
1#ifndef __PERF_HIST_H
2#define __PERF_HIST_H
3#include "../builtin.h"
4
5#include "util.h"
6
7#include "color.h"
8#include <linux/list.h>
9#include "cache.h"
10#include <linux/rbtree.h>
11#include "symbol.h"
12#include "string.h"
13#include "callchain.h"
14#include "strlist.h"
15#include "values.h"
16
17#include "../perf.h"
18#include "debug.h"
19#include "header.h"
20
21#include "parse-options.h"
22#include "parse-events.h"
23
24#include "thread.h"
25#include "sort.h"
26
27extern struct rb_root hist;
28extern struct rb_root collapse_hists;
29extern struct rb_root output_hists;
30extern int callchain;
31extern struct callchain_param callchain_param;
32extern unsigned long total;
33extern unsigned long total_mmap;
34extern unsigned long total_comm;
35extern unsigned long total_fork;
36extern unsigned long total_unknown;
37extern unsigned long total_lost;
38
39struct hist_entry *__hist_entry__add(struct thread *thread, struct map *map,
40 struct symbol *sym, struct symbol *parent,
41 u64 ip, u64 count, char level, bool *hit);
42extern int64_t hist_entry__cmp(struct hist_entry *, struct hist_entry *);
43extern int64_t hist_entry__collapse(struct hist_entry *, struct hist_entry *);
44extern void hist_entry__free(struct hist_entry *);
45extern void collapse__insert_entry(struct hist_entry *);
46extern void collapse__resort(void);
47extern void output__insert_entry(struct hist_entry *, u64);
48extern void output__resort(u64);
49
50#endif /* __PERF_HIST_H */
diff --git a/tools/perf/util/include/asm/asm-offsets.h b/tools/perf/util/include/asm/asm-offsets.h
new file mode 100644
index 00000000000..ed538942523
--- /dev/null
+++ b/tools/perf/util/include/asm/asm-offsets.h
@@ -0,0 +1 @@
/* stub */
diff --git a/tools/perf/util/include/asm/bitops.h b/tools/perf/util/include/asm/bitops.h
new file mode 100644
index 00000000000..58e9817ffae
--- /dev/null
+++ b/tools/perf/util/include/asm/bitops.h
@@ -0,0 +1,18 @@
1#ifndef _PERF_ASM_BITOPS_H_
2#define _PERF_ASM_BITOPS_H_
3
4#include <sys/types.h>
5#include "../../types.h"
6#include <linux/compiler.h>
7
8/* CHECKME: Not sure both always match */
9#define BITS_PER_LONG __WORDSIZE
10
11#include "../../../../include/asm-generic/bitops/__fls.h"
12#include "../../../../include/asm-generic/bitops/fls.h"
13#include "../../../../include/asm-generic/bitops/fls64.h"
14#include "../../../../include/asm-generic/bitops/__ffs.h"
15#include "../../../../include/asm-generic/bitops/ffz.h"
16#include "../../../../include/asm-generic/bitops/hweight.h"
17
18#endif
diff --git a/tools/perf/util/include/asm/byteorder.h b/tools/perf/util/include/asm/byteorder.h
new file mode 100644
index 00000000000..b722abe3a62
--- /dev/null
+++ b/tools/perf/util/include/asm/byteorder.h
@@ -0,0 +1,2 @@
1#include <asm/types.h>
2#include "../../../../include/linux/swab.h"
diff --git a/tools/perf/util/include/asm/swab.h b/tools/perf/util/include/asm/swab.h
new file mode 100644
index 00000000000..ed538942523
--- /dev/null
+++ b/tools/perf/util/include/asm/swab.h
@@ -0,0 +1 @@
/* stub */
diff --git a/tools/perf/util/include/asm/uaccess.h b/tools/perf/util/include/asm/uaccess.h
new file mode 100644
index 00000000000..d0f72b8fcc3
--- /dev/null
+++ b/tools/perf/util/include/asm/uaccess.h
@@ -0,0 +1,14 @@
1#ifndef _PERF_ASM_UACCESS_H_
2#define _PERF_ASM_UACCESS_H_
3
4#define __get_user(src, dest) \
5({ \
6 (src) = *dest; \
7 0; \
8})
9
10#define get_user __get_user
11
12#define access_ok(type, addr, size) 1
13
14#endif
diff --git a/tools/perf/util/include/linux/bitmap.h b/tools/perf/util/include/linux/bitmap.h
new file mode 100644
index 00000000000..821c1033bcc
--- /dev/null
+++ b/tools/perf/util/include/linux/bitmap.h
@@ -0,0 +1,2 @@
1#include "../../../../include/linux/bitmap.h"
2#include "../../../../include/asm-generic/bitops/find.h"
diff --git a/tools/perf/util/include/linux/bitops.h b/tools/perf/util/include/linux/bitops.h
new file mode 100644
index 00000000000..ace57c36d1d
--- /dev/null
+++ b/tools/perf/util/include/linux/bitops.h
@@ -0,0 +1,27 @@
1#ifndef _PERF_LINUX_BITOPS_H_
2#define _PERF_LINUX_BITOPS_H_
3
4#define __KERNEL__
5
6#define CONFIG_GENERIC_FIND_NEXT_BIT
7#define CONFIG_GENERIC_FIND_FIRST_BIT
8#include "../../../../include/linux/bitops.h"
9
10static inline void set_bit(int nr, unsigned long *addr)
11{
12 addr[nr / BITS_PER_LONG] |= 1UL << (nr % BITS_PER_LONG);
13}
14
15static __always_inline int test_bit(unsigned int nr, const unsigned long *addr)
16{
17 return ((1UL << (nr % BITS_PER_LONG)) &
18 (((unsigned long *)addr)[nr / BITS_PER_LONG])) != 0;
19}
20
21unsigned long generic_find_next_zero_le_bit(const unsigned long *addr, unsigned
22 long size, unsigned long offset);
23
24unsigned long generic_find_next_le_bit(const unsigned long *addr, unsigned
25 long size, unsigned long offset);
26
27#endif
diff --git a/tools/perf/util/include/linux/compiler.h b/tools/perf/util/include/linux/compiler.h
new file mode 100644
index 00000000000..dfb0713ed47
--- /dev/null
+++ b/tools/perf/util/include/linux/compiler.h
@@ -0,0 +1,10 @@
1#ifndef _PERF_LINUX_COMPILER_H_
2#define _PERF_LINUX_COMPILER_H_
3
4#ifndef __always_inline
5#define __always_inline inline
6#endif
7#define __user
8#define __attribute_const__
9
10#endif
diff --git a/tools/perf/util/include/linux/ctype.h b/tools/perf/util/include/linux/ctype.h
new file mode 100644
index 00000000000..bae5783282e
--- /dev/null
+++ b/tools/perf/util/include/linux/ctype.h
@@ -0,0 +1 @@
#include "../../../../include/linux/ctype.h"
diff --git a/tools/perf/util/include/linux/kernel.h b/tools/perf/util/include/linux/kernel.h
index a6b87390cb5..21c0274c02f 100644
--- a/tools/perf/util/include/linux/kernel.h
+++ b/tools/perf/util/include/linux/kernel.h
@@ -1,6 +1,16 @@
1#ifndef PERF_LINUX_KERNEL_H_ 1#ifndef PERF_LINUX_KERNEL_H_
2#define PERF_LINUX_KERNEL_H_ 2#define PERF_LINUX_KERNEL_H_
3 3
4#include <stdarg.h>
5#include <stdio.h>
6#include <stdlib.h>
7#include <assert.h>
8
9#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
10
11#define ALIGN(x,a) __ALIGN_MASK(x,(typeof(x))(a)-1)
12#define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask))
13
4#ifndef offsetof 14#ifndef offsetof
5#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) 15#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
6#endif 16#endif
@@ -26,4 +36,70 @@
26 _max1 > _max2 ? _max1 : _max2; }) 36 _max1 > _max2 ? _max1 : _max2; })
27#endif 37#endif
28 38
39#ifndef min
40#define min(x, y) ({ \
41 typeof(x) _min1 = (x); \
42 typeof(y) _min2 = (y); \
43 (void) (&_min1 == &_min2); \
44 _min1 < _min2 ? _min1 : _min2; })
45#endif
46
47#ifndef BUG_ON
48#define BUG_ON(cond) assert(!(cond))
49#endif
50
51/*
52 * Both need more care to handle endianness
53 * (Don't use bitmap_copy_le() for now)
54 */
55#define cpu_to_le64(x) (x)
56#define cpu_to_le32(x) (x)
57
58static inline int
59vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
60{
61 int i;
62 ssize_t ssize = size;
63
64 i = vsnprintf(buf, size, fmt, args);
65
66 return (i >= ssize) ? (ssize - 1) : i;
67}
68
69static inline int scnprintf(char * buf, size_t size, const char * fmt, ...)
70{
71 va_list args;
72 ssize_t ssize = size;
73 int i;
74
75 va_start(args, fmt);
76 i = vsnprintf(buf, size, fmt, args);
77 va_end(args);
78
79 return (i >= ssize) ? (ssize - 1) : i;
80}
81
82static inline unsigned long
83simple_strtoul(const char *nptr, char **endptr, int base)
84{
85 return strtoul(nptr, endptr, base);
86}
87
88#ifndef pr_fmt
89#define pr_fmt(fmt) fmt
90#endif
91
92#define pr_err(fmt, ...) \
93 do { fprintf(stderr, pr_fmt(fmt), ##__VA_ARGS__); } while (0)
94#define pr_warning(fmt, ...) \
95 do { fprintf(stderr, pr_fmt(fmt), ##__VA_ARGS__); } while (0)
96#define pr_info(fmt, ...) \
97 do { fprintf(stderr, pr_fmt(fmt), ##__VA_ARGS__); } while (0)
98#define pr_debug(fmt, ...) \
99 eprintf(1, pr_fmt(fmt), ##__VA_ARGS__)
100#define pr_debugN(n, fmt, ...) \
101 eprintf(n, pr_fmt(fmt), ##__VA_ARGS__)
102#define pr_debug2(fmt, ...) pr_debugN(2, pr_fmt(fmt), ##__VA_ARGS__)
103#define pr_debug3(fmt, ...) pr_debugN(3, pr_fmt(fmt), ##__VA_ARGS__)
104
29#endif 105#endif
diff --git a/tools/perf/util/include/linux/string.h b/tools/perf/util/include/linux/string.h
new file mode 100644
index 00000000000..3b2f5900276
--- /dev/null
+++ b/tools/perf/util/include/linux/string.h
@@ -0,0 +1 @@
#include <string.h>
diff --git a/tools/perf/util/include/linux/types.h b/tools/perf/util/include/linux/types.h
new file mode 100644
index 00000000000..196862a81a2
--- /dev/null
+++ b/tools/perf/util/include/linux/types.h
@@ -0,0 +1,9 @@
1#ifndef _PERF_LINUX_TYPES_H_
2#define _PERF_LINUX_TYPES_H_
3
4#include <asm/types.h>
5
6#define DECLARE_BITMAP(name,bits) \
7 unsigned long name[BITS_TO_LONGS(bits)]
8
9#endif
diff --git a/tools/perf/util/levenshtein.h b/tools/perf/util/levenshtein.h
index 0173abeef52..b0fcb6d8a88 100644
--- a/tools/perf/util/levenshtein.h
+++ b/tools/perf/util/levenshtein.h
@@ -1,8 +1,8 @@
1#ifndef LEVENSHTEIN_H 1#ifndef __PERF_LEVENSHTEIN_H
2#define LEVENSHTEIN_H 2#define __PERF_LEVENSHTEIN_H
3 3
4int levenshtein(const char *string1, const char *string2, 4int levenshtein(const char *string1, const char *string2,
5 int swap_penalty, int substition_penalty, 5 int swap_penalty, int substition_penalty,
6 int insertion_penalty, int deletion_penalty); 6 int insertion_penalty, int deletion_penalty);
7 7
8#endif 8#endif /* __PERF_LEVENSHTEIN_H */
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 804e0238273..c1c55682534 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -3,6 +3,7 @@
3#include <stdlib.h> 3#include <stdlib.h>
4#include <string.h> 4#include <string.h>
5#include <stdio.h> 5#include <stdio.h>
6#include "debug.h"
6 7
7static inline int is_anon_memory(const char *filename) 8static inline int is_anon_memory(const char *filename)
8{ 9{
@@ -19,7 +20,8 @@ static int strcommon(const char *pathname, char *cwd, int cwdlen)
19 return n; 20 return n;
20} 21}
21 22
22 struct map *map__new(struct mmap_event *event, char *cwd, int cwdlen) 23struct map *map__new(struct mmap_event *event, char *cwd, int cwdlen,
24 unsigned int sym_priv_size, symbol_filter_t filter)
23{ 25{
24 struct map *self = malloc(sizeof(*self)); 26 struct map *self = malloc(sizeof(*self));
25 27
@@ -27,6 +29,7 @@ static int strcommon(const char *pathname, char *cwd, int cwdlen)
27 const char *filename = event->filename; 29 const char *filename = event->filename;
28 char newfilename[PATH_MAX]; 30 char newfilename[PATH_MAX];
29 int anon; 31 int anon;
32 bool new_dso;
30 33
31 if (cwd) { 34 if (cwd) {
32 int n = strcommon(filename, cwd, cwdlen); 35 int n = strcommon(filename, cwd, cwdlen);
@@ -49,14 +52,29 @@ static int strcommon(const char *pathname, char *cwd, int cwdlen)
49 self->end = event->start + event->len; 52 self->end = event->start + event->len;
50 self->pgoff = event->pgoff; 53 self->pgoff = event->pgoff;
51 54
52 self->dso = dsos__findnew(filename); 55 self->dso = dsos__findnew(filename, sym_priv_size, &new_dso);
53 if (self->dso == NULL) 56 if (self->dso == NULL)
54 goto out_delete; 57 goto out_delete;
55 58
59 if (new_dso) {
60 int nr = dso__load(self->dso, self, filter);
61
62 if (nr < 0)
63 pr_warning("Failed to open %s, continuing "
64 "without symbols\n",
65 self->dso->long_name);
66 else if (nr == 0)
67 pr_warning("No symbols found in %s, maybe "
68 "install a debug package?\n",
69 self->dso->long_name);
70 }
71
56 if (self->dso == vdso || anon) 72 if (self->dso == vdso || anon)
57 self->map_ip = vdso__map_ip; 73 self->map_ip = self->unmap_ip = identity__map_ip;
58 else 74 else {
59 self->map_ip = map__map_ip; 75 self->map_ip = map__map_ip;
76 self->unmap_ip = map__unmap_ip;
77 }
60 } 78 }
61 return self; 79 return self;
62out_delete: 80out_delete:
diff --git a/tools/perf/util/module.c b/tools/perf/util/module.c
deleted file mode 100644
index 0d8c85defcd..00000000000
--- a/tools/perf/util/module.c
+++ /dev/null
@@ -1,545 +0,0 @@
1#include "util.h"
2#include "../perf.h"
3#include "string.h"
4#include "module.h"
5
6#include <libelf.h>
7#include <libgen.h>
8#include <gelf.h>
9#include <elf.h>
10#include <dirent.h>
11#include <sys/utsname.h>
12
13static unsigned int crc32(const char *p, unsigned int len)
14{
15 int i;
16 unsigned int crc = 0;
17
18 while (len--) {
19 crc ^= *p++;
20 for (i = 0; i < 8; i++)
21 crc = (crc >> 1) ^ ((crc & 1) ? 0xedb88320 : 0);
22 }
23 return crc;
24}
25
26/* module section methods */
27
28struct sec_dso *sec_dso__new_dso(const char *name)
29{
30 struct sec_dso *self = malloc(sizeof(*self) + strlen(name) + 1);
31
32 if (self != NULL) {
33 strcpy(self->name, name);
34 self->secs = RB_ROOT;
35 self->find_section = sec_dso__find_section;
36 }
37
38 return self;
39}
40
41static void sec_dso__delete_section(struct section *self)
42{
43 free(((void *)self));
44}
45
46void sec_dso__delete_sections(struct sec_dso *self)
47{
48 struct section *pos;
49 struct rb_node *next = rb_first(&self->secs);
50
51 while (next) {
52 pos = rb_entry(next, struct section, rb_node);
53 next = rb_next(&pos->rb_node);
54 rb_erase(&pos->rb_node, &self->secs);
55 sec_dso__delete_section(pos);
56 }
57}
58
59void sec_dso__delete_self(struct sec_dso *self)
60{
61 sec_dso__delete_sections(self);
62 free(self);
63}
64
65static void sec_dso__insert_section(struct sec_dso *self, struct section *sec)
66{
67 struct rb_node **p = &self->secs.rb_node;
68 struct rb_node *parent = NULL;
69 const u64 hash = sec->hash;
70 struct section *s;
71
72 while (*p != NULL) {
73 parent = *p;
74 s = rb_entry(parent, struct section, rb_node);
75 if (hash < s->hash)
76 p = &(*p)->rb_left;
77 else
78 p = &(*p)->rb_right;
79 }
80 rb_link_node(&sec->rb_node, parent, p);
81 rb_insert_color(&sec->rb_node, &self->secs);
82}
83
84struct section *sec_dso__find_section(struct sec_dso *self, const char *name)
85{
86 struct rb_node *n;
87 u64 hash;
88 int len;
89
90 if (self == NULL)
91 return NULL;
92
93 len = strlen(name);
94 hash = crc32(name, len);
95
96 n = self->secs.rb_node;
97
98 while (n) {
99 struct section *s = rb_entry(n, struct section, rb_node);
100
101 if (hash < s->hash)
102 n = n->rb_left;
103 else if (hash > s->hash)
104 n = n->rb_right;
105 else {
106 if (!strcmp(name, s->name))
107 return s;
108 else
109 n = rb_next(&s->rb_node);
110 }
111 }
112
113 return NULL;
114}
115
116static size_t sec_dso__fprintf_section(struct section *self, FILE *fp)
117{
118 return fprintf(fp, "name:%s vma:%llx path:%s\n",
119 self->name, self->vma, self->path);
120}
121
122size_t sec_dso__fprintf(struct sec_dso *self, FILE *fp)
123{
124 size_t ret = fprintf(fp, "dso: %s\n", self->name);
125
126 struct rb_node *nd;
127 for (nd = rb_first(&self->secs); nd; nd = rb_next(nd)) {
128 struct section *pos = rb_entry(nd, struct section, rb_node);
129 ret += sec_dso__fprintf_section(pos, fp);
130 }
131
132 return ret;
133}
134
135static struct section *section__new(const char *name, const char *path)
136{
137 struct section *self = calloc(1, sizeof(*self));
138
139 if (!self)
140 goto out_failure;
141
142 self->name = calloc(1, strlen(name) + 1);
143 if (!self->name)
144 goto out_failure;
145
146 self->path = calloc(1, strlen(path) + 1);
147 if (!self->path)
148 goto out_failure;
149
150 strcpy(self->name, name);
151 strcpy(self->path, path);
152 self->hash = crc32(self->name, strlen(name));
153
154 return self;
155
156out_failure:
157 if (self) {
158 if (self->name)
159 free(self->name);
160 if (self->path)
161 free(self->path);
162 free(self);
163 }
164
165 return NULL;
166}
167
168/* module methods */
169
170struct mod_dso *mod_dso__new_dso(const char *name)
171{
172 struct mod_dso *self = malloc(sizeof(*self) + strlen(name) + 1);
173
174 if (self != NULL) {
175 strcpy(self->name, name);
176 self->mods = RB_ROOT;
177 self->find_module = mod_dso__find_module;
178 }
179
180 return self;
181}
182
183static void mod_dso__delete_module(struct module *self)
184{
185 free(((void *)self));
186}
187
188void mod_dso__delete_modules(struct mod_dso *self)
189{
190 struct module *pos;
191 struct rb_node *next = rb_first(&self->mods);
192
193 while (next) {
194 pos = rb_entry(next, struct module, rb_node);
195 next = rb_next(&pos->rb_node);
196 rb_erase(&pos->rb_node, &self->mods);
197 mod_dso__delete_module(pos);
198 }
199}
200
201void mod_dso__delete_self(struct mod_dso *self)
202{
203 mod_dso__delete_modules(self);
204 free(self);
205}
206
207static void mod_dso__insert_module(struct mod_dso *self, struct module *mod)
208{
209 struct rb_node **p = &self->mods.rb_node;
210 struct rb_node *parent = NULL;
211 const u64 hash = mod->hash;
212 struct module *m;
213
214 while (*p != NULL) {
215 parent = *p;
216 m = rb_entry(parent, struct module, rb_node);
217 if (hash < m->hash)
218 p = &(*p)->rb_left;
219 else
220 p = &(*p)->rb_right;
221 }
222 rb_link_node(&mod->rb_node, parent, p);
223 rb_insert_color(&mod->rb_node, &self->mods);
224}
225
226struct module *mod_dso__find_module(struct mod_dso *self, const char *name)
227{
228 struct rb_node *n;
229 u64 hash;
230 int len;
231
232 if (self == NULL)
233 return NULL;
234
235 len = strlen(name);
236 hash = crc32(name, len);
237
238 n = self->mods.rb_node;
239
240 while (n) {
241 struct module *m = rb_entry(n, struct module, rb_node);
242
243 if (hash < m->hash)
244 n = n->rb_left;
245 else if (hash > m->hash)
246 n = n->rb_right;
247 else {
248 if (!strcmp(name, m->name))
249 return m;
250 else
251 n = rb_next(&m->rb_node);
252 }
253 }
254
255 return NULL;
256}
257
258static size_t mod_dso__fprintf_module(struct module *self, FILE *fp)
259{
260 return fprintf(fp, "name:%s path:%s\n", self->name, self->path);
261}
262
263size_t mod_dso__fprintf(struct mod_dso *self, FILE *fp)
264{
265 struct rb_node *nd;
266 size_t ret;
267
268 ret = fprintf(fp, "dso: %s\n", self->name);
269
270 for (nd = rb_first(&self->mods); nd; nd = rb_next(nd)) {
271 struct module *pos = rb_entry(nd, struct module, rb_node);
272
273 ret += mod_dso__fprintf_module(pos, fp);
274 }
275
276 return ret;
277}
278
279static struct module *module__new(const char *name, const char *path)
280{
281 struct module *self = calloc(1, sizeof(*self));
282
283 if (!self)
284 goto out_failure;
285
286 self->name = calloc(1, strlen(name) + 1);
287 if (!self->name)
288 goto out_failure;
289
290 self->path = calloc(1, strlen(path) + 1);
291 if (!self->path)
292 goto out_failure;
293
294 strcpy(self->name, name);
295 strcpy(self->path, path);
296 self->hash = crc32(self->name, strlen(name));
297
298 return self;
299
300out_failure:
301 if (self) {
302 if (self->name)
303 free(self->name);
304 if (self->path)
305 free(self->path);
306 free(self);
307 }
308
309 return NULL;
310}
311
312static int mod_dso__load_sections(struct module *mod)
313{
314 int count = 0, path_len;
315 struct dirent *entry;
316 char *line = NULL;
317 char *dir_path;
318 DIR *dir;
319 size_t n;
320
321 path_len = strlen("/sys/module/");
322 path_len += strlen(mod->name);
323 path_len += strlen("/sections/");
324
325 dir_path = calloc(1, path_len + 1);
326 if (dir_path == NULL)
327 goto out_failure;
328
329 strcat(dir_path, "/sys/module/");
330 strcat(dir_path, mod->name);
331 strcat(dir_path, "/sections/");
332
333 dir = opendir(dir_path);
334 if (dir == NULL)
335 goto out_free;
336
337 while ((entry = readdir(dir))) {
338 struct section *section;
339 char *path, *vma;
340 int line_len;
341 FILE *file;
342
343 if (!strcmp(".", entry->d_name) || !strcmp("..", entry->d_name))
344 continue;
345
346 path = calloc(1, path_len + strlen(entry->d_name) + 1);
347 if (path == NULL)
348 break;
349 strcat(path, dir_path);
350 strcat(path, entry->d_name);
351
352 file = fopen(path, "r");
353 if (file == NULL) {
354 free(path);
355 break;
356 }
357
358 line_len = getline(&line, &n, file);
359 if (line_len < 0) {
360 free(path);
361 fclose(file);
362 break;
363 }
364
365 if (!line) {
366 free(path);
367 fclose(file);
368 break;
369 }
370
371 line[--line_len] = '\0'; /* \n */
372
373 vma = strstr(line, "0x");
374 if (!vma) {
375 free(path);
376 fclose(file);
377 break;
378 }
379 vma += 2;
380
381 section = section__new(entry->d_name, path);
382 if (!section) {
383 fprintf(stderr, "load_sections: allocation error\n");
384 free(path);
385 fclose(file);
386 break;
387 }
388
389 hex2u64(vma, &section->vma);
390 sec_dso__insert_section(mod->sections, section);
391
392 free(path);
393 fclose(file);
394 count++;
395 }
396
397 closedir(dir);
398 free(line);
399 free(dir_path);
400
401 return count;
402
403out_free:
404 free(dir_path);
405
406out_failure:
407 return count;
408}
409
410static int mod_dso__load_module_paths(struct mod_dso *self)
411{
412 struct utsname uts;
413 int count = 0, len, err = -1;
414 char *line = NULL;
415 FILE *file;
416 char *dpath, *dir;
417 size_t n;
418
419 if (uname(&uts) < 0)
420 return err;
421
422 len = strlen("/lib/modules/");
423 len += strlen(uts.release);
424 len += strlen("/modules.dep");
425
426 dpath = calloc(1, len + 1);
427 if (dpath == NULL)
428 return err;
429
430 strcat(dpath, "/lib/modules/");
431 strcat(dpath, uts.release);
432 strcat(dpath, "/modules.dep");
433
434 file = fopen(dpath, "r");
435 if (file == NULL)
436 goto out_failure;
437
438 dir = dirname(dpath);
439 if (!dir)
440 goto out_failure;
441 strcat(dir, "/");
442
443 while (!feof(file)) {
444 struct module *module;
445 char *name, *path, *tmp;
446 FILE *modfile;
447 int line_len;
448
449 line_len = getline(&line, &n, file);
450 if (line_len < 0)
451 break;
452
453 if (!line)
454 break;
455
456 line[--line_len] = '\0'; /* \n */
457
458 path = strchr(line, ':');
459 if (!path)
460 break;
461 *path = '\0';
462
463 path = strdup(line);
464 if (!path)
465 break;
466
467 if (!strstr(path, dir)) {
468 if (strncmp(path, "kernel/", 7))
469 break;
470
471 free(path);
472 path = calloc(1, strlen(dir) + strlen(line) + 1);
473 if (!path)
474 break;
475 strcat(path, dir);
476 strcat(path, line);
477 }
478
479 modfile = fopen(path, "r");
480 if (modfile == NULL)
481 break;
482 fclose(modfile);
483
484 name = strdup(path);
485 if (!name)
486 break;
487
488 name = strtok(name, "/");
489 tmp = name;
490
491 while (tmp) {
492 tmp = strtok(NULL, "/");
493 if (tmp)
494 name = tmp;
495 }
496
497 name = strsep(&name, ".");
498 if (!name)
499 break;
500
501 /* Quirk: replace '-' with '_' in all modules */
502 for (len = strlen(name); len; len--) {
503 if (*(name+len) == '-')
504 *(name+len) = '_';
505 }
506
507 module = module__new(name, path);
508 if (!module)
509 break;
510 mod_dso__insert_module(self, module);
511
512 module->sections = sec_dso__new_dso("sections");
513 if (!module->sections)
514 break;
515
516 module->active = mod_dso__load_sections(module);
517
518 if (module->active > 0)
519 count++;
520 }
521
522 if (feof(file))
523 err = count;
524 else
525 fprintf(stderr, "load_module_paths: modules.dep parsing failure!\n");
526
527out_failure:
528 if (dpath)
529 free(dpath);
530 if (file)
531 fclose(file);
532 if (line)
533 free(line);
534
535 return err;
536}
537
538int mod_dso__load_modules(struct mod_dso *dso)
539{
540 int err;
541
542 err = mod_dso__load_module_paths(dso);
543
544 return err;
545}
diff --git a/tools/perf/util/module.h b/tools/perf/util/module.h
deleted file mode 100644
index 8a592ef641c..00000000000
--- a/tools/perf/util/module.h
+++ /dev/null
@@ -1,53 +0,0 @@
1#ifndef _PERF_MODULE_
2#define _PERF_MODULE_ 1
3
4#include <linux/types.h>
5#include "../types.h"
6#include <linux/list.h>
7#include <linux/rbtree.h>
8
9struct section {
10 struct rb_node rb_node;
11 u64 hash;
12 u64 vma;
13 char *name;
14 char *path;
15};
16
17struct sec_dso {
18 struct list_head node;
19 struct rb_root secs;
20 struct section *(*find_section)(struct sec_dso *, const char *name);
21 char name[0];
22};
23
24struct module {
25 struct rb_node rb_node;
26 u64 hash;
27 char *name;
28 char *path;
29 struct sec_dso *sections;
30 int active;
31};
32
33struct mod_dso {
34 struct list_head node;
35 struct rb_root mods;
36 struct module *(*find_module)(struct mod_dso *, const char *name);
37 char name[0];
38};
39
40struct sec_dso *sec_dso__new_dso(const char *name);
41void sec_dso__delete_sections(struct sec_dso *self);
42void sec_dso__delete_self(struct sec_dso *self);
43size_t sec_dso__fprintf(struct sec_dso *self, FILE *fp);
44struct section *sec_dso__find_section(struct sec_dso *self, const char *name);
45
46struct mod_dso *mod_dso__new_dso(const char *name);
47void mod_dso__delete_modules(struct mod_dso *self);
48void mod_dso__delete_self(struct mod_dso *self);
49size_t mod_dso__fprintf(struct mod_dso *self, FILE *fp);
50struct module *mod_dso__find_module(struct mod_dso *self, const char *name);
51int mod_dso__load_modules(struct mod_dso *dso);
52
53#endif /* _PERF_MODULE_ */
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 8cfb48cbbea..b097570e962 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -8,9 +8,10 @@
8#include "cache.h" 8#include "cache.h"
9#include "header.h" 9#include "header.h"
10 10
11int nr_counters; 11int nr_counters;
12 12
13struct perf_event_attr attrs[MAX_COUNTERS]; 13struct perf_event_attr attrs[MAX_COUNTERS];
14char *filters[MAX_COUNTERS];
14 15
15struct event_symbol { 16struct event_symbol {
16 u8 type; 17 u8 type;
@@ -708,7 +709,6 @@ static void store_event_type(const char *orgname)
708 perf_header__push_event(id, orgname); 709 perf_header__push_event(id, orgname);
709} 710}
710 711
711
712int parse_events(const struct option *opt __used, const char *str, int unset __used) 712int parse_events(const struct option *opt __used, const char *str, int unset __used)
713{ 713{
714 struct perf_event_attr attr; 714 struct perf_event_attr attr;
@@ -745,6 +745,28 @@ int parse_events(const struct option *opt __used, const char *str, int unset __u
745 return 0; 745 return 0;
746} 746}
747 747
748int parse_filter(const struct option *opt __used, const char *str,
749 int unset __used)
750{
751 int i = nr_counters - 1;
752 int len = strlen(str);
753
754 if (i < 0 || attrs[i].type != PERF_TYPE_TRACEPOINT) {
755 fprintf(stderr,
756 "-F option should follow a -e tracepoint option\n");
757 return -1;
758 }
759
760 filters[i] = malloc(len + 1);
761 if (!filters[i]) {
762 fprintf(stderr, "not enough memory to hold filter string\n");
763 return -1;
764 }
765 strcpy(filters[i], str);
766
767 return 0;
768}
769
748static const char * const event_type_descriptors[] = { 770static const char * const event_type_descriptors[] = {
749 "", 771 "",
750 "Hardware event", 772 "Hardware event",
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index 30c60811284..b8c1f64bc93 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -1,5 +1,5 @@
1#ifndef _PARSE_EVENTS_H 1#ifndef __PERF_PARSE_EVENTS_H
2#define _PARSE_EVENTS_H 2#define __PERF_PARSE_EVENTS_H
3/* 3/*
4 * Parse symbolic events/counts passed in as options: 4 * Parse symbolic events/counts passed in as options:
5 */ 5 */
@@ -17,11 +17,13 @@ extern struct tracepoint_path *tracepoint_id_to_path(u64 config);
17extern int nr_counters; 17extern int nr_counters;
18 18
19extern struct perf_event_attr attrs[MAX_COUNTERS]; 19extern struct perf_event_attr attrs[MAX_COUNTERS];
20extern char *filters[MAX_COUNTERS];
20 21
21extern const char *event_name(int ctr); 22extern const char *event_name(int ctr);
22extern const char *__event_name(int type, u64 config); 23extern const char *__event_name(int type, u64 config);
23 24
24extern int parse_events(const struct option *opt, const char *str, int unset); 25extern int parse_events(const struct option *opt, const char *str, int unset);
26extern int parse_filter(const struct option *opt, const char *str, int unset);
25 27
26#define EVENTS_HELP_MAX (128*1024) 28#define EVENTS_HELP_MAX (128*1024)
27 29
@@ -31,4 +33,4 @@ extern char debugfs_path[];
31extern int valid_debugfs_mount(const char *debugfs); 33extern int valid_debugfs_mount(const char *debugfs);
32 34
33 35
34#endif /* _PARSE_EVENTS_H */ 36#endif /* __PERF_PARSE_EVENTS_H */
diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h
index 2ee248ff27e..948805af43c 100644
--- a/tools/perf/util/parse-options.h
+++ b/tools/perf/util/parse-options.h
@@ -1,5 +1,5 @@
1#ifndef PARSE_OPTIONS_H 1#ifndef __PERF_PARSE_OPTIONS_H
2#define PARSE_OPTIONS_H 2#define __PERF_PARSE_OPTIONS_H
3 3
4enum parse_opt_type { 4enum parse_opt_type {
5 /* special types */ 5 /* special types */
@@ -174,4 +174,4 @@ extern int parse_opt_verbosity_cb(const struct option *, const char *, int);
174 174
175extern const char *parse_options_fix_filename(const char *prefix, const char *file); 175extern const char *parse_options_fix_filename(const char *prefix, const char *file);
176 176
177#endif 177#endif /* __PERF_PARSE_OPTIONS_H */
diff --git a/tools/perf/util/quote.h b/tools/perf/util/quote.h
index a5454a1d1c1..b6a01973391 100644
--- a/tools/perf/util/quote.h
+++ b/tools/perf/util/quote.h
@@ -1,5 +1,5 @@
1#ifndef QUOTE_H 1#ifndef __PERF_QUOTE_H
2#define QUOTE_H 2#define __PERF_QUOTE_H
3 3
4#include <stddef.h> 4#include <stddef.h>
5#include <stdio.h> 5#include <stdio.h>
@@ -65,4 +65,4 @@ extern void perl_quote_print(FILE *stream, const char *src);
65extern void python_quote_print(FILE *stream, const char *src); 65extern void python_quote_print(FILE *stream, const char *src);
66extern void tcl_quote_print(FILE *stream, const char *src); 66extern void tcl_quote_print(FILE *stream, const char *src);
67 67
68#endif 68#endif /* __PERF_QUOTE_H */
diff --git a/tools/perf/util/run-command.h b/tools/perf/util/run-command.h
index cc1837deba8..d79028727ce 100644
--- a/tools/perf/util/run-command.h
+++ b/tools/perf/util/run-command.h
@@ -1,5 +1,5 @@
1#ifndef RUN_COMMAND_H 1#ifndef __PERF_RUN_COMMAND_H
2#define RUN_COMMAND_H 2#define __PERF_RUN_COMMAND_H
3 3
4enum { 4enum {
5 ERR_RUN_COMMAND_FORK = 10000, 5 ERR_RUN_COMMAND_FORK = 10000,
@@ -85,4 +85,4 @@ struct async {
85int start_async(struct async *async); 85int start_async(struct async *async);
86int finish_async(struct async *async); 86int finish_async(struct async *async);
87 87
88#endif 88#endif /* __PERF_RUN_COMMAND_H */
diff --git a/tools/perf/util/sigchain.h b/tools/perf/util/sigchain.h
index 618083bce0c..1a53c11265f 100644
--- a/tools/perf/util/sigchain.h
+++ b/tools/perf/util/sigchain.h
@@ -1,5 +1,5 @@
1#ifndef SIGCHAIN_H 1#ifndef __PERF_SIGCHAIN_H
2#define SIGCHAIN_H 2#define __PERF_SIGCHAIN_H
3 3
4typedef void (*sigchain_fun)(int); 4typedef void (*sigchain_fun)(int);
5 5
@@ -8,4 +8,4 @@ int sigchain_pop(int sig);
8 8
9void sigchain_push_common(sigchain_fun f); 9void sigchain_push_common(sigchain_fun f);
10 10
11#endif /* SIGCHAIN_H */ 11#endif /* __PERF_SIGCHAIN_H */
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
new file mode 100644
index 00000000000..b490354d1b2
--- /dev/null
+++ b/tools/perf/util/sort.c
@@ -0,0 +1,290 @@
1#include "sort.h"
2
3regex_t parent_regex;
4char default_parent_pattern[] = "^sys_|^do_page_fault";
5char *parent_pattern = default_parent_pattern;
6char default_sort_order[] = "comm,dso,symbol";
7char *sort_order = default_sort_order;
8int sort__need_collapse = 0;
9int sort__has_parent = 0;
10
11enum sort_type sort__first_dimension;
12
13unsigned int dsos__col_width;
14unsigned int comms__col_width;
15unsigned int threads__col_width;
16static unsigned int parent_symbol__col_width;
17char * field_sep;
18
19LIST_HEAD(hist_entry__sort_list);
20
21struct sort_entry sort_thread = {
22 .header = "Command: Pid",
23 .cmp = sort__thread_cmp,
24 .print = sort__thread_print,
25 .width = &threads__col_width,
26};
27
28struct sort_entry sort_comm = {
29 .header = "Command",
30 .cmp = sort__comm_cmp,
31 .collapse = sort__comm_collapse,
32 .print = sort__comm_print,
33 .width = &comms__col_width,
34};
35
36struct sort_entry sort_dso = {
37 .header = "Shared Object",
38 .cmp = sort__dso_cmp,
39 .print = sort__dso_print,
40 .width = &dsos__col_width,
41};
42
43struct sort_entry sort_sym = {
44 .header = "Symbol",
45 .cmp = sort__sym_cmp,
46 .print = sort__sym_print,
47};
48
49struct sort_entry sort_parent = {
50 .header = "Parent symbol",
51 .cmp = sort__parent_cmp,
52 .print = sort__parent_print,
53 .width = &parent_symbol__col_width,
54};
55
56struct sort_dimension {
57 const char *name;
58 struct sort_entry *entry;
59 int taken;
60};
61
62static struct sort_dimension sort_dimensions[] = {
63 { .name = "pid", .entry = &sort_thread, },
64 { .name = "comm", .entry = &sort_comm, },
65 { .name = "dso", .entry = &sort_dso, },
66 { .name = "symbol", .entry = &sort_sym, },
67 { .name = "parent", .entry = &sort_parent, },
68};
69
70int64_t cmp_null(void *l, void *r)
71{
72 if (!l && !r)
73 return 0;
74 else if (!l)
75 return -1;
76 else
77 return 1;
78}
79
80/* --sort pid */
81
82int64_t
83sort__thread_cmp(struct hist_entry *left, struct hist_entry *right)
84{
85 return right->thread->pid - left->thread->pid;
86}
87
88int repsep_fprintf(FILE *fp, const char *fmt, ...)
89{
90 int n;
91 va_list ap;
92
93 va_start(ap, fmt);
94 if (!field_sep)
95 n = vfprintf(fp, fmt, ap);
96 else {
97 char *bf = NULL;
98 n = vasprintf(&bf, fmt, ap);
99 if (n > 0) {
100 char *sep = bf;
101
102 while (1) {
103 sep = strchr(sep, *field_sep);
104 if (sep == NULL)
105 break;
106 *sep = '.';
107 }
108 }
109 fputs(bf, fp);
110 free(bf);
111 }
112 va_end(ap);
113 return n;
114}
115
116size_t
117sort__thread_print(FILE *fp, struct hist_entry *self, unsigned int width)
118{
119 return repsep_fprintf(fp, "%*s:%5d", width - 6,
120 self->thread->comm ?: "", self->thread->pid);
121}
122
123size_t
124sort__comm_print(FILE *fp, struct hist_entry *self, unsigned int width)
125{
126 return repsep_fprintf(fp, "%*s", width, self->thread->comm);
127}
128
129/* --sort dso */
130
131int64_t
132sort__dso_cmp(struct hist_entry *left, struct hist_entry *right)
133{
134 struct dso *dso_l = left->map ? left->map->dso : NULL;
135 struct dso *dso_r = right->map ? right->map->dso : NULL;
136 const char *dso_name_l, *dso_name_r;
137
138 if (!dso_l || !dso_r)
139 return cmp_null(dso_l, dso_r);
140
141 if (verbose) {
142 dso_name_l = dso_l->long_name;
143 dso_name_r = dso_r->long_name;
144 } else {
145 dso_name_l = dso_l->short_name;
146 dso_name_r = dso_r->short_name;
147 }
148
149 return strcmp(dso_name_l, dso_name_r);
150}
151
152size_t
153sort__dso_print(FILE *fp, struct hist_entry *self, unsigned int width)
154{
155 if (self->map && self->map->dso) {
156 const char *dso_name = !verbose ? self->map->dso->short_name :
157 self->map->dso->long_name;
158 return repsep_fprintf(fp, "%-*s", width, dso_name);
159 }
160
161 return repsep_fprintf(fp, "%*llx", width, (u64)self->ip);
162}
163
164/* --sort symbol */
165
166int64_t
167sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
168{
169 u64 ip_l, ip_r;
170
171 if (left->sym == right->sym)
172 return 0;
173
174 ip_l = left->sym ? left->sym->start : left->ip;
175 ip_r = right->sym ? right->sym->start : right->ip;
176
177 return (int64_t)(ip_r - ip_l);
178}
179
180
181size_t
182sort__sym_print(FILE *fp, struct hist_entry *self, unsigned int width __used)
183{
184 size_t ret = 0;
185
186 if (verbose) {
187 char o = self->map ? dso__symtab_origin(self->map->dso) : '!';
188 ret += repsep_fprintf(fp, "%#018llx %c ", (u64)self->ip, o);
189 }
190
191 ret += repsep_fprintf(fp, "[%c] ", self->level);
192 if (self->sym)
193 ret += repsep_fprintf(fp, "%s", self->sym->name);
194 else
195 ret += repsep_fprintf(fp, "%#016llx", (u64)self->ip);
196
197 return ret;
198}
199
200/* --sort comm */
201
202int64_t
203sort__comm_cmp(struct hist_entry *left, struct hist_entry *right)
204{
205 return right->thread->pid - left->thread->pid;
206}
207
208int64_t
209sort__comm_collapse(struct hist_entry *left, struct hist_entry *right)
210{
211 char *comm_l = left->thread->comm;
212 char *comm_r = right->thread->comm;
213
214 if (!comm_l || !comm_r)
215 return cmp_null(comm_l, comm_r);
216
217 return strcmp(comm_l, comm_r);
218}
219
220/* --sort parent */
221
222int64_t
223sort__parent_cmp(struct hist_entry *left, struct hist_entry *right)
224{
225 struct symbol *sym_l = left->parent;
226 struct symbol *sym_r = right->parent;
227
228 if (!sym_l || !sym_r)
229 return cmp_null(sym_l, sym_r);
230
231 return strcmp(sym_l->name, sym_r->name);
232}
233
234size_t
235sort__parent_print(FILE *fp, struct hist_entry *self, unsigned int width)
236{
237 return repsep_fprintf(fp, "%-*s", width,
238 self->parent ? self->parent->name : "[other]");
239}
240
241int sort_dimension__add(const char *tok)
242{
243 unsigned int i;
244
245 for (i = 0; i < ARRAY_SIZE(sort_dimensions); i++) {
246 struct sort_dimension *sd = &sort_dimensions[i];
247
248 if (sd->taken)
249 continue;
250
251 if (strncasecmp(tok, sd->name, strlen(tok)))
252 continue;
253
254 if (sd->entry->collapse)
255 sort__need_collapse = 1;
256
257 if (sd->entry == &sort_parent) {
258 int ret = regcomp(&parent_regex, parent_pattern, REG_EXTENDED);
259 if (ret) {
260 char err[BUFSIZ];
261
262 regerror(ret, &parent_regex, err, sizeof(err));
263 fprintf(stderr, "Invalid regex: %s\n%s",
264 parent_pattern, err);
265 exit(-1);
266 }
267 sort__has_parent = 1;
268 }
269
270 if (list_empty(&hist_entry__sort_list)) {
271 if (!strcmp(sd->name, "pid"))
272 sort__first_dimension = SORT_PID;
273 else if (!strcmp(sd->name, "comm"))
274 sort__first_dimension = SORT_COMM;
275 else if (!strcmp(sd->name, "dso"))
276 sort__first_dimension = SORT_DSO;
277 else if (!strcmp(sd->name, "symbol"))
278 sort__first_dimension = SORT_SYM;
279 else if (!strcmp(sd->name, "parent"))
280 sort__first_dimension = SORT_PARENT;
281 }
282
283 list_add_tail(&sd->entry->list, &hist_entry__sort_list);
284 sd->taken = 1;
285
286 return 0;
287 }
288
289 return -ESRCH;
290}
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
new file mode 100644
index 00000000000..333e664ff45
--- /dev/null
+++ b/tools/perf/util/sort.h
@@ -0,0 +1,99 @@
1#ifndef __PERF_SORT_H
2#define __PERF_SORT_H
3#include "../builtin.h"
4
5#include "util.h"
6
7#include "color.h"
8#include <linux/list.h>
9#include "cache.h"
10#include <linux/rbtree.h>
11#include "symbol.h"
12#include "string.h"
13#include "callchain.h"
14#include "strlist.h"
15#include "values.h"
16
17#include "../perf.h"
18#include "debug.h"
19#include "header.h"
20
21#include "parse-options.h"
22#include "parse-events.h"
23
24#include "thread.h"
25#include "sort.h"
26
27extern regex_t parent_regex;
28extern char *sort_order;
29extern char default_parent_pattern[];
30extern char *parent_pattern;
31extern char default_sort_order[];
32extern int sort__need_collapse;
33extern int sort__has_parent;
34extern char *field_sep;
35extern struct sort_entry sort_comm;
36extern struct sort_entry sort_dso;
37extern struct sort_entry sort_sym;
38extern struct sort_entry sort_parent;
39extern unsigned int dsos__col_width;
40extern unsigned int comms__col_width;
41extern unsigned int threads__col_width;
42extern enum sort_type sort__first_dimension;
43
44struct hist_entry {
45 struct rb_node rb_node;
46 u64 count;
47 struct thread *thread;
48 struct map *map;
49 struct symbol *sym;
50 u64 ip;
51 char level;
52 struct symbol *parent;
53 struct callchain_node callchain;
54 struct rb_root sorted_chain;
55};
56
57enum sort_type {
58 SORT_PID,
59 SORT_COMM,
60 SORT_DSO,
61 SORT_SYM,
62 SORT_PARENT
63};
64
65/*
66 * configurable sorting bits
67 */
68
69struct sort_entry {
70 struct list_head list;
71
72 const char *header;
73
74 int64_t (*cmp)(struct hist_entry *, struct hist_entry *);
75 int64_t (*collapse)(struct hist_entry *, struct hist_entry *);
76 size_t (*print)(FILE *fp, struct hist_entry *, unsigned int width);
77 unsigned int *width;
78 bool elide;
79};
80
81extern struct sort_entry sort_thread;
82extern struct list_head hist_entry__sort_list;
83
84extern int repsep_fprintf(FILE *fp, const char *fmt, ...);
85extern size_t sort__thread_print(FILE *, struct hist_entry *, unsigned int);
86extern size_t sort__comm_print(FILE *, struct hist_entry *, unsigned int);
87extern size_t sort__dso_print(FILE *, struct hist_entry *, unsigned int);
88extern size_t sort__sym_print(FILE *, struct hist_entry *, unsigned int __used);
89extern int64_t cmp_null(void *, void *);
90extern int64_t sort__thread_cmp(struct hist_entry *, struct hist_entry *);
91extern int64_t sort__comm_cmp(struct hist_entry *, struct hist_entry *);
92extern int64_t sort__comm_collapse(struct hist_entry *, struct hist_entry *);
93extern int64_t sort__dso_cmp(struct hist_entry *, struct hist_entry *);
94extern int64_t sort__sym_cmp(struct hist_entry *, struct hist_entry *);
95extern int64_t sort__parent_cmp(struct hist_entry *, struct hist_entry *);
96extern size_t sort__parent_print(FILE *, struct hist_entry *, unsigned int);
97extern int sort_dimension__add(const char *);
98
99#endif /* __PERF_SORT_H */
diff --git a/tools/perf/util/strbuf.h b/tools/perf/util/strbuf.h
index d2aa86c014c..a3d121d6c83 100644
--- a/tools/perf/util/strbuf.h
+++ b/tools/perf/util/strbuf.h
@@ -1,5 +1,5 @@
1#ifndef STRBUF_H 1#ifndef __PERF_STRBUF_H
2#define STRBUF_H 2#define __PERF_STRBUF_H
3 3
4/* 4/*
5 * Strbuf's can be use in many ways: as a byte array, or to store arbitrary 5 * Strbuf's can be use in many ways: as a byte array, or to store arbitrary
@@ -134,4 +134,4 @@ extern int launch_editor(const char *path, struct strbuf *buffer, const char *co
134extern int strbuf_branchname(struct strbuf *sb, const char *name); 134extern int strbuf_branchname(struct strbuf *sb, const char *name);
135extern int strbuf_check_branch_ref(struct strbuf *sb, const char *name); 135extern int strbuf_check_branch_ref(struct strbuf *sb, const char *name);
136 136
137#endif /* STRBUF_H */ 137#endif /* __PERF_STRBUF_H */
diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c
index c93eca9a7be..04743d3e903 100644
--- a/tools/perf/util/string.c
+++ b/tools/perf/util/string.c
@@ -1,3 +1,4 @@
1#include <string.h>
1#include "string.h" 2#include "string.h"
2 3
3static int hex(char ch) 4static int hex(char ch)
@@ -32,3 +33,13 @@ int hex2u64(const char *ptr, u64 *long_val)
32 33
33 return p - ptr; 34 return p - ptr;
34} 35}
36
37char *strxfrchar(char *s, char from, char to)
38{
39 char *p = s;
40
41 while ((p = strchr(p, from)) != NULL)
42 *p++ = to;
43
44 return s;
45}
diff --git a/tools/perf/util/string.h b/tools/perf/util/string.h
index bf39dfadfd2..2c84bf65ba0 100644
--- a/tools/perf/util/string.h
+++ b/tools/perf/util/string.h
@@ -1,11 +1,12 @@
1#ifndef _PERF_STRING_H_ 1#ifndef __PERF_STRING_H_
2#define _PERF_STRING_H_ 2#define __PERF_STRING_H_
3 3
4#include "types.h" 4#include "types.h"
5 5
6int hex2u64(const char *ptr, u64 *val); 6int hex2u64(const char *ptr, u64 *val);
7char *strxfrchar(char *s, char from, char to);
7 8
8#define _STR(x) #x 9#define _STR(x) #x
9#define STR(x) _STR(x) 10#define STR(x) _STR(x)
10 11
11#endif 12#endif /* __PERF_STRING_H */
diff --git a/tools/perf/util/strlist.h b/tools/perf/util/strlist.h
index 921818e44a5..cb4659306d7 100644
--- a/tools/perf/util/strlist.h
+++ b/tools/perf/util/strlist.h
@@ -1,5 +1,5 @@
1#ifndef STRLIST_H_ 1#ifndef __PERF_STRLIST_H
2#define STRLIST_H_ 2#define __PERF_STRLIST_H
3 3
4#include <linux/rbtree.h> 4#include <linux/rbtree.h>
5#include <stdbool.h> 5#include <stdbool.h>
@@ -36,4 +36,4 @@ static inline unsigned int strlist__nr_entries(const struct strlist *self)
36} 36}
37 37
38int strlist__parse_list(struct strlist *self, const char *s); 38int strlist__parse_list(struct strlist *self, const char *s);
39#endif /* STRLIST_H_ */ 39#endif /* __PERF_STRLIST_H */
diff --git a/tools/perf/util/svghelper.c b/tools/perf/util/svghelper.c
index 856655d8b0b..b3637db025a 100644
--- a/tools/perf/util/svghelper.c
+++ b/tools/perf/util/svghelper.c
@@ -103,7 +103,7 @@ void open_svg(const char *filename, int cpus, int rows, u64 start, u64 end)
103 fprintf(svgfile, " rect.process2 { fill:rgb(180,180,180); fill-opacity:0.9; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); 103 fprintf(svgfile, " rect.process2 { fill:rgb(180,180,180); fill-opacity:0.9; stroke-width:0; stroke:rgb( 0, 0, 0); } \n");
104 fprintf(svgfile, " rect.sample { fill:rgb( 0, 0,255); fill-opacity:0.8; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); 104 fprintf(svgfile, " rect.sample { fill:rgb( 0, 0,255); fill-opacity:0.8; stroke-width:0; stroke:rgb( 0, 0, 0); } \n");
105 fprintf(svgfile, " rect.blocked { fill:rgb(255, 0, 0); fill-opacity:0.5; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); 105 fprintf(svgfile, " rect.blocked { fill:rgb(255, 0, 0); fill-opacity:0.5; stroke-width:0; stroke:rgb( 0, 0, 0); } \n");
106 fprintf(svgfile, " rect.waiting { fill:rgb(214,214, 0); fill-opacity:0.3; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); 106 fprintf(svgfile, " rect.waiting { fill:rgb(224,214, 0); fill-opacity:0.8; stroke-width:0; stroke:rgb( 0, 0, 0); } \n");
107 fprintf(svgfile, " rect.WAITING { fill:rgb(255,214, 48); fill-opacity:0.6; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); 107 fprintf(svgfile, " rect.WAITING { fill:rgb(255,214, 48); fill-opacity:0.6; stroke-width:0; stroke:rgb( 0, 0, 0); } \n");
108 fprintf(svgfile, " rect.cpu { fill:rgb(192,192,192); fill-opacity:0.2; stroke-width:0.5; stroke:rgb(128,128,128); } \n"); 108 fprintf(svgfile, " rect.cpu { fill:rgb(192,192,192); fill-opacity:0.2; stroke-width:0.5; stroke:rgb(128,128,128); } \n");
109 fprintf(svgfile, " rect.pstate { fill:rgb(128,128,128); fill-opacity:0.8; stroke-width:0; } \n"); 109 fprintf(svgfile, " rect.pstate { fill:rgb(128,128,128); fill-opacity:0.8; stroke-width:0; } \n");
diff --git a/tools/perf/util/svghelper.h b/tools/perf/util/svghelper.h
index cd93195aedb..e0781989cc3 100644
--- a/tools/perf/util/svghelper.h
+++ b/tools/perf/util/svghelper.h
@@ -1,5 +1,5 @@
1#ifndef _INCLUDE_GUARD_SVG_HELPER_ 1#ifndef __PERF_SVGHELPER_H
2#define _INCLUDE_GUARD_SVG_HELPER_ 2#define __PERF_SVGHELPER_H
3 3
4#include "types.h" 4#include "types.h"
5 5
@@ -25,4 +25,4 @@ extern void svg_close(void);
25 25
26extern int svg_page_width; 26extern int svg_page_width;
27 27
28#endif 28#endif /* __PERF_SVGHELPER_H */
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 47ea0609a76..8f0208ce237 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -2,14 +2,14 @@
2#include "../perf.h" 2#include "../perf.h"
3#include "string.h" 3#include "string.h"
4#include "symbol.h" 4#include "symbol.h"
5#include "thread.h"
5 6
6#include "debug.h" 7#include "debug.h"
7 8
8#include <libelf.h> 9#include <libelf.h>
9#include <gelf.h> 10#include <gelf.h>
10#include <elf.h> 11#include <elf.h>
11 12#include <sys/utsname.h>
12const char *sym_hist_filter;
13 13
14enum dso_origin { 14enum dso_origin {
15 DSO__ORIG_KERNEL = 0, 15 DSO__ORIG_KERNEL = 0,
@@ -18,12 +18,65 @@ enum dso_origin {
18 DSO__ORIG_UBUNTU, 18 DSO__ORIG_UBUNTU,
19 DSO__ORIG_BUILDID, 19 DSO__ORIG_BUILDID,
20 DSO__ORIG_DSO, 20 DSO__ORIG_DSO,
21 DSO__ORIG_KMODULE,
21 DSO__ORIG_NOT_FOUND, 22 DSO__ORIG_NOT_FOUND,
22}; 23};
23 24
24static struct symbol *symbol__new(u64 start, u64 len, 25static void dsos__add(struct dso *dso);
25 const char *name, unsigned int priv_size, 26static struct dso *dsos__find(const char *name);
26 u64 obj_start, int v) 27static struct map *map__new2(u64 start, struct dso *dso);
28static void kernel_maps__insert(struct map *map);
29
30static struct rb_root kernel_maps;
31
32static void dso__fixup_sym_end(struct dso *self)
33{
34 struct rb_node *nd, *prevnd = rb_first(&self->syms);
35 struct symbol *curr, *prev;
36
37 if (prevnd == NULL)
38 return;
39
40 curr = rb_entry(prevnd, struct symbol, rb_node);
41
42 for (nd = rb_next(prevnd); nd; nd = rb_next(nd)) {
43 prev = curr;
44 curr = rb_entry(nd, struct symbol, rb_node);
45
46 if (prev->end == prev->start)
47 prev->end = curr->start - 1;
48 }
49
50 /* Last entry */
51 if (curr->end == curr->start)
52 curr->end = roundup(curr->start, 4096);
53}
54
55static void kernel_maps__fixup_end(void)
56{
57 struct map *prev, *curr;
58 struct rb_node *nd, *prevnd = rb_first(&kernel_maps);
59
60 if (prevnd == NULL)
61 return;
62
63 curr = rb_entry(prevnd, struct map, rb_node);
64
65 for (nd = rb_next(prevnd); nd; nd = rb_next(nd)) {
66 prev = curr;
67 curr = rb_entry(nd, struct map, rb_node);
68 prev->end = curr->start - 1;
69 }
70
71 nd = rb_last(&curr->dso->syms);
72 if (nd) {
73 struct symbol *sym = rb_entry(nd, struct symbol, rb_node);
74 curr->end = sym->end;
75 }
76}
77
78static struct symbol *symbol__new(u64 start, u64 len, const char *name,
79 unsigned int priv_size)
27{ 80{
28 size_t namelen = strlen(name) + 1; 81 size_t namelen = strlen(name) + 1;
29 struct symbol *self = calloc(1, priv_size + sizeof(*self) + namelen); 82 struct symbol *self = calloc(1, priv_size + sizeof(*self) + namelen);
@@ -31,23 +84,15 @@ static struct symbol *symbol__new(u64 start, u64 len,
31 if (!self) 84 if (!self)
32 return NULL; 85 return NULL;
33 86
34 if (v >= 2)
35 printf("new symbol: %016Lx [%08lx]: %s, hist: %p, obj_start: %p\n",
36 (u64)start, (unsigned long)len, name, self->hist, (void *)(unsigned long)obj_start);
37
38 self->obj_start= obj_start;
39 self->hist = NULL;
40 self->hist_sum = 0;
41
42 if (sym_hist_filter && !strcmp(name, sym_hist_filter))
43 self->hist = calloc(sizeof(u64), len);
44
45 if (priv_size) { 87 if (priv_size) {
46 memset(self, 0, priv_size); 88 memset(self, 0, priv_size);
47 self = ((void *)self) + priv_size; 89 self = ((void *)self) + priv_size;
48 } 90 }
49 self->start = start; 91 self->start = start;
50 self->end = len ? start + len - 1 : start; 92 self->end = len ? start + len - 1 : start;
93
94 pr_debug3("%s: %s %#Lx-%#Lx\n", __func__, name, start, self->end);
95
51 memcpy(self->name, name, namelen); 96 memcpy(self->name, name, namelen);
52 97
53 return self; 98 return self;
@@ -60,12 +105,8 @@ static void symbol__delete(struct symbol *self, unsigned int priv_size)
60 105
61static size_t symbol__fprintf(struct symbol *self, FILE *fp) 106static size_t symbol__fprintf(struct symbol *self, FILE *fp)
62{ 107{
63 if (!self->module) 108 return fprintf(fp, " %llx-%llx %s\n",
64 return fprintf(fp, " %llx-%llx %s\n",
65 self->start, self->end, self->name); 109 self->start, self->end, self->name);
66 else
67 return fprintf(fp, " %llx-%llx %s \t[%s]\n",
68 self->start, self->end, self->name, self->module->name);
69} 110}
70 111
71struct dso *dso__new(const char *name, unsigned int sym_priv_size) 112struct dso *dso__new(const char *name, unsigned int sym_priv_size)
@@ -74,6 +115,8 @@ struct dso *dso__new(const char *name, unsigned int sym_priv_size)
74 115
75 if (self != NULL) { 116 if (self != NULL) {
76 strcpy(self->name, name); 117 strcpy(self->name, name);
118 self->long_name = self->name;
119 self->short_name = self->name;
77 self->syms = RB_ROOT; 120 self->syms = RB_ROOT;
78 self->sym_priv_size = sym_priv_size; 121 self->sym_priv_size = sym_priv_size;
79 self->find_symbol = dso__find_symbol; 122 self->find_symbol = dso__find_symbol;
@@ -100,6 +143,8 @@ static void dso__delete_symbols(struct dso *self)
100void dso__delete(struct dso *self) 143void dso__delete(struct dso *self)
101{ 144{
102 dso__delete_symbols(self); 145 dso__delete_symbols(self);
146 if (self->long_name != self->name)
147 free(self->long_name);
103 free(self); 148 free(self);
104} 149}
105 150
@@ -147,7 +192,7 @@ struct symbol *dso__find_symbol(struct dso *self, u64 ip)
147 192
148size_t dso__fprintf(struct dso *self, FILE *fp) 193size_t dso__fprintf(struct dso *self, FILE *fp)
149{ 194{
150 size_t ret = fprintf(fp, "dso: %s\n", self->name); 195 size_t ret = fprintf(fp, "dso: %s\n", self->short_name);
151 196
152 struct rb_node *nd; 197 struct rb_node *nd;
153 for (nd = rb_first(&self->syms); nd; nd = rb_next(nd)) { 198 for (nd = rb_first(&self->syms); nd; nd = rb_next(nd)) {
@@ -158,13 +203,16 @@ size_t dso__fprintf(struct dso *self, FILE *fp)
158 return ret; 203 return ret;
159} 204}
160 205
161static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int v) 206/*
207 * Loads the function entries in /proc/kallsyms into kernel_map->dso,
208 * so that we can in the next step set the symbol ->end address and then
209 * call kernel_maps__split_kallsyms.
210 */
211static int kernel_maps__load_all_kallsyms(void)
162{ 212{
163 struct rb_node *nd, *prevnd;
164 char *line = NULL; 213 char *line = NULL;
165 size_t n; 214 size_t n;
166 FILE *file = fopen("/proc/kallsyms", "r"); 215 FILE *file = fopen("/proc/kallsyms", "r");
167 int count = 0;
168 216
169 if (file == NULL) 217 if (file == NULL)
170 goto out_failure; 218 goto out_failure;
@@ -174,6 +222,7 @@ static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int v)
174 struct symbol *sym; 222 struct symbol *sym;
175 int line_len, len; 223 int line_len, len;
176 char symbol_type; 224 char symbol_type;
225 char *symbol_name;
177 226
178 line_len = getline(&line, &n, file); 227 line_len = getline(&line, &n, file);
179 if (line_len < 0) 228 if (line_len < 0)
@@ -196,44 +245,24 @@ static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int v)
196 */ 245 */
197 if (symbol_type != 'T' && symbol_type != 'W') 246 if (symbol_type != 'T' && symbol_type != 'W')
198 continue; 247 continue;
248
249 symbol_name = line + len + 2;
199 /* 250 /*
200 * Well fix up the end later, when we have all sorted. 251 * Will fix up the end later, when we have all symbols sorted.
201 */ 252 */
202 sym = symbol__new(start, 0xdead, line + len + 2, 253 sym = symbol__new(start, 0, symbol_name,
203 self->sym_priv_size, 0, v); 254 kernel_map->dso->sym_priv_size);
204 255
205 if (sym == NULL) 256 if (sym == NULL)
206 goto out_delete_line; 257 goto out_delete_line;
207 258
208 if (filter && filter(self, sym)) 259 dso__insert_symbol(kernel_map->dso, sym);
209 symbol__delete(sym, self->sym_priv_size);
210 else {
211 dso__insert_symbol(self, sym);
212 count++;
213 }
214 }
215
216 /*
217 * Now that we have all sorted out, just set the ->end of all
218 * symbols
219 */
220 prevnd = rb_first(&self->syms);
221
222 if (prevnd == NULL)
223 goto out_delete_line;
224
225 for (nd = rb_next(prevnd); nd; nd = rb_next(nd)) {
226 struct symbol *prev = rb_entry(prevnd, struct symbol, rb_node),
227 *curr = rb_entry(nd, struct symbol, rb_node);
228
229 prev->end = curr->start - 1;
230 prevnd = nd;
231 } 260 }
232 261
233 free(line); 262 free(line);
234 fclose(file); 263 fclose(file);
235 264
236 return count; 265 return 0;
237 266
238out_delete_line: 267out_delete_line:
239 free(line); 268 free(line);
@@ -241,14 +270,124 @@ out_failure:
241 return -1; 270 return -1;
242} 271}
243 272
244static int dso__load_perf_map(struct dso *self, symbol_filter_t filter, int v) 273/*
274 * Split the symbols into maps, making sure there are no overlaps, i.e. the
275 * kernel range is broken in several maps, named [kernel].N, as we don't have
276 * the original ELF section names vmlinux have.
277 */
278static int kernel_maps__split_kallsyms(symbol_filter_t filter, int use_modules)
279{
280 struct map *map = kernel_map;
281 struct symbol *pos;
282 int count = 0;
283 struct rb_node *next = rb_first(&kernel_map->dso->syms);
284 int kernel_range = 0;
285
286 while (next) {
287 char *module;
288
289 pos = rb_entry(next, struct symbol, rb_node);
290 next = rb_next(&pos->rb_node);
291
292 module = strchr(pos->name, '\t');
293 if (module) {
294 if (!use_modules)
295 goto delete_symbol;
296
297 *module++ = '\0';
298
299 if (strcmp(map->dso->name, module)) {
300 map = kernel_maps__find_by_dso_name(module);
301 if (!map) {
302 pr_err("/proc/{kallsyms,modules} "
303 "inconsistency!\n");
304 return -1;
305 }
306 }
307 /*
308 * So that we look just like we get from .ko files,
309 * i.e. not prelinked, relative to map->start.
310 */
311 pos->start = map->map_ip(map, pos->start);
312 pos->end = map->map_ip(map, pos->end);
313 } else if (map != kernel_map) {
314 char dso_name[PATH_MAX];
315 struct dso *dso;
316
317 snprintf(dso_name, sizeof(dso_name), "[kernel].%d",
318 kernel_range++);
319
320 dso = dso__new(dso_name,
321 kernel_map->dso->sym_priv_size);
322 if (dso == NULL)
323 return -1;
324
325 map = map__new2(pos->start, dso);
326 if (map == NULL) {
327 dso__delete(dso);
328 return -1;
329 }
330
331 map->map_ip = map->unmap_ip = identity__map_ip;
332 kernel_maps__insert(map);
333 ++kernel_range;
334 }
335
336 if (filter && filter(map, pos)) {
337delete_symbol:
338 rb_erase(&pos->rb_node, &kernel_map->dso->syms);
339 symbol__delete(pos, kernel_map->dso->sym_priv_size);
340 } else {
341 if (map != kernel_map) {
342 rb_erase(&pos->rb_node, &kernel_map->dso->syms);
343 dso__insert_symbol(map->dso, pos);
344 }
345 count++;
346 }
347 }
348
349 return count;
350}
351
352
353static int kernel_maps__load_kallsyms(symbol_filter_t filter, int use_modules)
354{
355 if (kernel_maps__load_all_kallsyms())
356 return -1;
357
358 dso__fixup_sym_end(kernel_map->dso);
359
360 return kernel_maps__split_kallsyms(filter, use_modules);
361}
362
363static size_t kernel_maps__fprintf(FILE *fp)
364{
365 size_t printed = fprintf(fp, "Kernel maps:\n");
366 struct rb_node *nd;
367
368 for (nd = rb_first(&kernel_maps); nd; nd = rb_next(nd)) {
369 struct map *pos = rb_entry(nd, struct map, rb_node);
370
371 printed += fprintf(fp, "Map:");
372 printed += map__fprintf(pos, fp);
373 if (verbose > 1) {
374 printed += dso__fprintf(pos->dso, fp);
375 printed += fprintf(fp, "--\n");
376 }
377 }
378
379 return printed + fprintf(fp, "END kernel maps\n");
380}
381
382static int dso__load_perf_map(struct dso *self, struct map *map,
383 symbol_filter_t filter)
245{ 384{
246 char *line = NULL; 385 char *line = NULL;
247 size_t n; 386 size_t n;
248 FILE *file; 387 FILE *file;
249 int nr_syms = 0; 388 int nr_syms = 0;
250 389
251 file = fopen(self->name, "r"); 390 file = fopen(self->long_name, "r");
252 if (file == NULL) 391 if (file == NULL)
253 goto out_failure; 392 goto out_failure;
254 393
@@ -279,12 +418,12 @@ static int dso__load_perf_map(struct dso *self, symbol_filter_t filter, int v)
279 continue; 418 continue;
280 419
281 sym = symbol__new(start, size, line + len, 420 sym = symbol__new(start, size, line + len,
282 self->sym_priv_size, start, v); 421 self->sym_priv_size);
283 422
284 if (sym == NULL) 423 if (sym == NULL)
285 goto out_delete_line; 424 goto out_delete_line;
286 425
287 if (filter && filter(self, sym)) 426 if (filter && filter(map, sym))
288 symbol__delete(sym, self->sym_priv_size); 427 symbol__delete(sym, self->sym_priv_size);
289 else { 428 else {
290 dso__insert_symbol(self, sym); 429 dso__insert_symbol(self, sym);
@@ -393,7 +532,7 @@ static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
393 * And always look at the original dso, not at debuginfo packages, that 532 * And always look at the original dso, not at debuginfo packages, that
394 * have the PLT data stripped out (shdr_rel_plt.sh_type == SHT_NOBITS). 533 * have the PLT data stripped out (shdr_rel_plt.sh_type == SHT_NOBITS).
395 */ 534 */
396static int dso__synthesize_plt_symbols(struct dso *self, int v) 535static int dso__synthesize_plt_symbols(struct dso *self)
397{ 536{
398 uint32_t nr_rel_entries, idx; 537 uint32_t nr_rel_entries, idx;
399 GElf_Sym sym; 538 GElf_Sym sym;
@@ -409,7 +548,7 @@ static int dso__synthesize_plt_symbols(struct dso *self, int v)
409 Elf *elf; 548 Elf *elf;
410 int nr = 0, symidx, fd, err = 0; 549 int nr = 0, symidx, fd, err = 0;
411 550
412 fd = open(self->name, O_RDONLY); 551 fd = open(self->long_name, O_RDONLY);
413 if (fd < 0) 552 if (fd < 0)
414 goto out; 553 goto out;
415 554
@@ -477,7 +616,7 @@ static int dso__synthesize_plt_symbols(struct dso *self, int v)
477 "%s@plt", elf_sym__name(&sym, symstrs)); 616 "%s@plt", elf_sym__name(&sym, symstrs));
478 617
479 f = symbol__new(plt_offset, shdr_plt.sh_entsize, 618 f = symbol__new(plt_offset, shdr_plt.sh_entsize,
480 sympltname, self->sym_priv_size, 0, v); 619 sympltname, self->sym_priv_size);
481 if (!f) 620 if (!f)
482 goto out_elf_end; 621 goto out_elf_end;
483 622
@@ -495,7 +634,7 @@ static int dso__synthesize_plt_symbols(struct dso *self, int v)
495 "%s@plt", elf_sym__name(&sym, symstrs)); 634 "%s@plt", elf_sym__name(&sym, symstrs));
496 635
497 f = symbol__new(plt_offset, shdr_plt.sh_entsize, 636 f = symbol__new(plt_offset, shdr_plt.sh_entsize,
498 sympltname, self->sym_priv_size, 0, v); 637 sympltname, self->sym_priv_size);
499 if (!f) 638 if (!f)
500 goto out_elf_end; 639 goto out_elf_end;
501 640
@@ -513,14 +652,18 @@ out_close:
513 if (err == 0) 652 if (err == 0)
514 return nr; 653 return nr;
515out: 654out:
516 fprintf(stderr, "%s: problems reading %s PLT info.\n", 655 pr_warning("%s: problems reading %s PLT info.\n",
517 __func__, self->name); 656 __func__, self->long_name);
518 return 0; 657 return 0;
519} 658}
520 659
521static int dso__load_sym(struct dso *self, int fd, const char *name, 660static int dso__load_sym(struct dso *self, struct map *map, const char *name,
522 symbol_filter_t filter, int v, struct module *mod) 661 int fd, symbol_filter_t filter, int kernel,
662 int kmodule)
523{ 663{
664 struct map *curr_map = map;
665 struct dso *curr_dso = self;
666 size_t dso_name_len = strlen(self->short_name);
524 Elf_Data *symstrs, *secstrs; 667 Elf_Data *symstrs, *secstrs;
525 uint32_t nr_syms; 668 uint32_t nr_syms;
526 int err = -1; 669 int err = -1;
@@ -531,19 +674,16 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
531 GElf_Sym sym; 674 GElf_Sym sym;
532 Elf_Scn *sec, *sec_strndx; 675 Elf_Scn *sec, *sec_strndx;
533 Elf *elf; 676 Elf *elf;
534 int nr = 0, kernel = !strcmp("[kernel]", self->name); 677 int nr = 0;
535 678
536 elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); 679 elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
537 if (elf == NULL) { 680 if (elf == NULL) {
538 if (v) 681 pr_err("%s: cannot read %s ELF file.\n", __func__, name);
539 fprintf(stderr, "%s: cannot read %s ELF file.\n",
540 __func__, name);
541 goto out_close; 682 goto out_close;
542 } 683 }
543 684
544 if (gelf_getehdr(elf, &ehdr) == NULL) { 685 if (gelf_getehdr(elf, &ehdr) == NULL) {
545 if (v) 686 pr_err("%s: cannot get elf header.\n", __func__);
546 fprintf(stderr, "%s: cannot get elf header.\n", __func__);
547 goto out_elf_end; 687 goto out_elf_end;
548 } 688 }
549 689
@@ -587,9 +727,7 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
587 elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) { 727 elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) {
588 struct symbol *f; 728 struct symbol *f;
589 const char *elf_name; 729 const char *elf_name;
590 char *demangled; 730 char *demangled = NULL;
591 u64 obj_start;
592 struct section *section = NULL;
593 int is_label = elf_sym__is_label(&sym); 731 int is_label = elf_sym__is_label(&sym);
594 const char *section_name; 732 const char *section_name;
595 733
@@ -605,52 +743,85 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
605 if (is_label && !elf_sec__is_text(&shdr, secstrs)) 743 if (is_label && !elf_sec__is_text(&shdr, secstrs))
606 continue; 744 continue;
607 745
746 elf_name = elf_sym__name(&sym, symstrs);
608 section_name = elf_sec__name(&shdr, secstrs); 747 section_name = elf_sec__name(&shdr, secstrs);
609 obj_start = sym.st_value;
610 748
611 if (self->adjust_symbols) { 749 if (kernel || kmodule) {
612 if (v >= 2) 750 char dso_name[PATH_MAX];
613 printf("adjusting symbol: st_value: %Lx sh_addr: %Lx sh_offset: %Lx\n",
614 (u64)sym.st_value, (u64)shdr.sh_addr, (u64)shdr.sh_offset);
615 751
616 sym.st_value -= shdr.sh_addr - shdr.sh_offset; 752 if (strcmp(section_name,
617 } 753 curr_dso->short_name + dso_name_len) == 0)
754 goto new_symbol;
618 755
619 if (mod) { 756 if (strcmp(section_name, ".text") == 0) {
620 section = mod->sections->find_section(mod->sections, section_name); 757 curr_map = map;
621 if (section) 758 curr_dso = self;
622 sym.st_value += section->vma; 759 goto new_symbol;
623 else {
624 fprintf(stderr, "dso__load_sym() module %s lookup of %s failed\n",
625 mod->name, section_name);
626 goto out_elf_end;
627 } 760 }
761
762 snprintf(dso_name, sizeof(dso_name),
763 "%s%s", self->short_name, section_name);
764
765 curr_map = kernel_maps__find_by_dso_name(dso_name);
766 if (curr_map == NULL) {
767 u64 start = sym.st_value;
768
769 if (kmodule)
770 start += map->start + shdr.sh_offset;
771
772 curr_dso = dso__new(dso_name, self->sym_priv_size);
773 if (curr_dso == NULL)
774 goto out_elf_end;
775 curr_map = map__new2(start, curr_dso);
776 if (curr_map == NULL) {
777 dso__delete(curr_dso);
778 goto out_elf_end;
779 }
780 curr_map->map_ip = identity__map_ip;
781 curr_map->unmap_ip = identity__map_ip;
782 curr_dso->origin = DSO__ORIG_KERNEL;
783 kernel_maps__insert(curr_map);
784 dsos__add(curr_dso);
785 } else
786 curr_dso = curr_map->dso;
787
788 goto new_symbol;
789 }
790
791 if (curr_dso->adjust_symbols) {
792 pr_debug2("adjusting symbol: st_value: %Lx sh_addr: "
793 "%Lx sh_offset: %Lx\n", (u64)sym.st_value,
794 (u64)shdr.sh_addr, (u64)shdr.sh_offset);
795 sym.st_value -= shdr.sh_addr - shdr.sh_offset;
628 } 796 }
629 /* 797 /*
630 * We need to figure out if the object was created from C++ sources 798 * We need to figure out if the object was created from C++ sources
631 * DWARF DW_compile_unit has this, but we don't always have access 799 * DWARF DW_compile_unit has this, but we don't always have access
632 * to it... 800 * to it...
633 */ 801 */
634 elf_name = elf_sym__name(&sym, symstrs);
635 demangled = bfd_demangle(NULL, elf_name, DMGL_PARAMS | DMGL_ANSI); 802 demangled = bfd_demangle(NULL, elf_name, DMGL_PARAMS | DMGL_ANSI);
636 if (demangled != NULL) 803 if (demangled != NULL)
637 elf_name = demangled; 804 elf_name = demangled;
638 805new_symbol:
639 f = symbol__new(sym.st_value, sym.st_size, elf_name, 806 f = symbol__new(sym.st_value, sym.st_size, elf_name,
640 self->sym_priv_size, obj_start, v); 807 curr_dso->sym_priv_size);
641 free(demangled); 808 free(demangled);
642 if (!f) 809 if (!f)
643 goto out_elf_end; 810 goto out_elf_end;
644 811
645 if (filter && filter(self, f)) 812 if (filter && filter(curr_map, f))
646 symbol__delete(f, self->sym_priv_size); 813 symbol__delete(f, curr_dso->sym_priv_size);
647 else { 814 else {
648 f->module = mod; 815 dso__insert_symbol(curr_dso, f);
649 dso__insert_symbol(self, f);
650 nr++; 816 nr++;
651 } 817 }
652 } 818 }
653 819
820 /*
821 * For misannotated, zeroed, ASM function sizes.
822 */
823 if (nr > 0)
824 dso__fixup_sym_end(self);
654 err = nr; 825 err = nr;
655out_elf_end: 826out_elf_end:
656 elf_end(elf); 827 elf_end(elf);
@@ -660,7 +831,7 @@ out_close:
660 831
661#define BUILD_ID_SIZE 128 832#define BUILD_ID_SIZE 128
662 833
663static char *dso__read_build_id(struct dso *self, int v) 834static char *dso__read_build_id(struct dso *self)
664{ 835{
665 int i; 836 int i;
666 GElf_Ehdr ehdr; 837 GElf_Ehdr ehdr;
@@ -670,22 +841,20 @@ static char *dso__read_build_id(struct dso *self, int v)
670 char *build_id = NULL, *bid; 841 char *build_id = NULL, *bid;
671 unsigned char *raw; 842 unsigned char *raw;
672 Elf *elf; 843 Elf *elf;
673 int fd = open(self->name, O_RDONLY); 844 int fd = open(self->long_name, O_RDONLY);
674 845
675 if (fd < 0) 846 if (fd < 0)
676 goto out; 847 goto out;
677 848
678 elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); 849 elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
679 if (elf == NULL) { 850 if (elf == NULL) {
680 if (v) 851 pr_err("%s: cannot read %s ELF file.\n", __func__,
681 fprintf(stderr, "%s: cannot read %s ELF file.\n", 852 self->long_name);
682 __func__, self->name);
683 goto out_close; 853 goto out_close;
684 } 854 }
685 855
686 if (gelf_getehdr(elf, &ehdr) == NULL) { 856 if (gelf_getehdr(elf, &ehdr) == NULL) {
687 if (v) 857 pr_err("%s: cannot get elf header.\n", __func__);
688 fprintf(stderr, "%s: cannot get elf header.\n", __func__);
689 goto out_elf_end; 858 goto out_elf_end;
690 } 859 }
691 860
@@ -707,8 +876,7 @@ static char *dso__read_build_id(struct dso *self, int v)
707 ++raw; 876 ++raw;
708 bid += 2; 877 bid += 2;
709 } 878 }
710 if (v >= 2) 879 pr_debug2("%s(%s): %s\n", __func__, self->long_name, build_id);
711 printf("%s(%s): %s\n", __func__, self->name, build_id);
712out_elf_end: 880out_elf_end:
713 elf_end(elf); 881 elf_end(elf);
714out_close: 882out_close:
@@ -726,6 +894,7 @@ char dso__symtab_origin(const struct dso *self)
726 [DSO__ORIG_UBUNTU] = 'u', 894 [DSO__ORIG_UBUNTU] = 'u',
727 [DSO__ORIG_BUILDID] = 'b', 895 [DSO__ORIG_BUILDID] = 'b',
728 [DSO__ORIG_DSO] = 'd', 896 [DSO__ORIG_DSO] = 'd',
897 [DSO__ORIG_KMODULE] = 'K',
729 }; 898 };
730 899
731 if (self == NULL || self->origin == DSO__ORIG_NOT_FOUND) 900 if (self == NULL || self->origin == DSO__ORIG_NOT_FOUND)
@@ -733,7 +902,7 @@ char dso__symtab_origin(const struct dso *self)
733 return origin[self->origin]; 902 return origin[self->origin];
734} 903}
735 904
736int dso__load(struct dso *self, symbol_filter_t filter, int v) 905int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
737{ 906{
738 int size = PATH_MAX; 907 int size = PATH_MAX;
739 char *name = malloc(size), *build_id = NULL; 908 char *name = malloc(size), *build_id = NULL;
@@ -746,7 +915,7 @@ int dso__load(struct dso *self, symbol_filter_t filter, int v)
746 self->adjust_symbols = 0; 915 self->adjust_symbols = 0;
747 916
748 if (strncmp(self->name, "/tmp/perf-", 10) == 0) { 917 if (strncmp(self->name, "/tmp/perf-", 10) == 0) {
749 ret = dso__load_perf_map(self, filter, v); 918 ret = dso__load_perf_map(self, map, filter);
750 self->origin = ret > 0 ? DSO__ORIG_JAVA_JIT : 919 self->origin = ret > 0 ? DSO__ORIG_JAVA_JIT :
751 DSO__ORIG_NOT_FOUND; 920 DSO__ORIG_NOT_FOUND;
752 return ret; 921 return ret;
@@ -759,13 +928,15 @@ more:
759 self->origin++; 928 self->origin++;
760 switch (self->origin) { 929 switch (self->origin) {
761 case DSO__ORIG_FEDORA: 930 case DSO__ORIG_FEDORA:
762 snprintf(name, size, "/usr/lib/debug%s.debug", self->name); 931 snprintf(name, size, "/usr/lib/debug%s.debug",
932 self->long_name);
763 break; 933 break;
764 case DSO__ORIG_UBUNTU: 934 case DSO__ORIG_UBUNTU:
765 snprintf(name, size, "/usr/lib/debug%s", self->name); 935 snprintf(name, size, "/usr/lib/debug%s",
936 self->long_name);
766 break; 937 break;
767 case DSO__ORIG_BUILDID: 938 case DSO__ORIG_BUILDID:
768 build_id = dso__read_build_id(self, v); 939 build_id = dso__read_build_id(self);
769 if (build_id != NULL) { 940 if (build_id != NULL) {
770 snprintf(name, size, 941 snprintf(name, size,
771 "/usr/lib/debug/.build-id/%.2s/%s.debug", 942 "/usr/lib/debug/.build-id/%.2s/%s.debug",
@@ -776,7 +947,7 @@ more:
776 self->origin++; 947 self->origin++;
777 /* Fall thru */ 948 /* Fall thru */
778 case DSO__ORIG_DSO: 949 case DSO__ORIG_DSO:
779 snprintf(name, size, "%s", self->name); 950 snprintf(name, size, "%s", self->long_name);
780 break; 951 break;
781 952
782 default: 953 default:
@@ -786,7 +957,7 @@ more:
786 fd = open(name, O_RDONLY); 957 fd = open(name, O_RDONLY);
787 } while (fd < 0); 958 } while (fd < 0);
788 959
789 ret = dso__load_sym(self, fd, name, filter, v, NULL); 960 ret = dso__load_sym(self, map, name, fd, filter, 0, 0);
790 close(fd); 961 close(fd);
791 962
792 /* 963 /*
@@ -796,7 +967,7 @@ more:
796 goto more; 967 goto more;
797 968
798 if (ret > 0) { 969 if (ret > 0) {
799 int nr_plt = dso__synthesize_plt_symbols(self, v); 970 int nr_plt = dso__synthesize_plt_symbols(self);
800 if (nr_plt > 0) 971 if (nr_plt > 0)
801 ret += nr_plt; 972 ret += nr_plt;
802 } 973 }
@@ -807,137 +978,321 @@ out:
807 return ret; 978 return ret;
808} 979}
809 980
810static int dso__load_module(struct dso *self, struct mod_dso *mods, const char *name, 981struct map *kernel_map;
811 symbol_filter_t filter, int v) 982
983static void kernel_maps__insert(struct map *map)
812{ 984{
813 struct module *mod = mod_dso__find_module(mods, name); 985 maps__insert(&kernel_maps, map);
814 int err = 0, fd; 986}
815 987
816 if (mod == NULL || !mod->active) 988struct symbol *kernel_maps__find_symbol(u64 ip, struct map **mapp)
817 return err; 989{
990 struct map *map = maps__find(&kernel_maps, ip);
818 991
819 fd = open(mod->path, O_RDONLY); 992 if (mapp)
993 *mapp = map;
820 994
821 if (fd < 0) 995 if (map) {
996 ip = map->map_ip(map, ip);
997 return map->dso->find_symbol(map->dso, ip);
998 }
999
1000 return NULL;
1001}
1002
1003struct map *kernel_maps__find_by_dso_name(const char *name)
1004{
1005 struct rb_node *nd;
1006
1007 for (nd = rb_first(&kernel_maps); nd; nd = rb_next(nd)) {
1008 struct map *map = rb_entry(nd, struct map, rb_node);
1009
1010 if (map->dso && strcmp(map->dso->name, name) == 0)
1011 return map;
1012 }
1013
1014 return NULL;
1015}
1016
1017static int dso__load_module_sym(struct dso *self, struct map *map,
1018 symbol_filter_t filter)
1019{
1020 int err = 0, fd = open(self->long_name, O_RDONLY);
1021
1022 if (fd < 0) {
1023 pr_err("%s: cannot open %s\n", __func__, self->long_name);
822 return err; 1024 return err;
1025 }
823 1026
824 err = dso__load_sym(self, fd, name, filter, v, mod); 1027 err = dso__load_sym(self, map, self->long_name, fd, filter, 0, 1);
825 close(fd); 1028 close(fd);
826 1029
827 return err; 1030 return err;
828} 1031}
829 1032
830int dso__load_modules(struct dso *self, symbol_filter_t filter, int v) 1033static int dsos__load_modules_sym_dir(char *dirname, symbol_filter_t filter)
831{ 1034{
832 struct mod_dso *mods = mod_dso__new_dso("modules"); 1035 struct dirent *dent;
833 struct module *pos; 1036 int nr_symbols = 0, err;
834 struct rb_node *next; 1037 DIR *dir = opendir(dirname);
835 int err, count = 0;
836 1038
837 err = mod_dso__load_modules(mods); 1039 if (!dir) {
1040 pr_err("%s: cannot open %s dir\n", __func__, dirname);
1041 return -1;
1042 }
838 1043
839 if (err <= 0) 1044 while ((dent = readdir(dir)) != NULL) {
840 return err; 1045 char path[PATH_MAX];
1046
1047 if (dent->d_type == DT_DIR) {
1048 if (!strcmp(dent->d_name, ".") ||
1049 !strcmp(dent->d_name, ".."))
1050 continue;
1051
1052 snprintf(path, sizeof(path), "%s/%s",
1053 dirname, dent->d_name);
1054 err = dsos__load_modules_sym_dir(path, filter);
1055 if (err < 0)
1056 goto failure;
1057 } else {
1058 char *dot = strrchr(dent->d_name, '.'),
1059 dso_name[PATH_MAX];
1060 struct map *map;
1061 struct rb_node *last;
1062
1063 if (dot == NULL || strcmp(dot, ".ko"))
1064 continue;
1065 snprintf(dso_name, sizeof(dso_name), "[%.*s]",
1066 (int)(dot - dent->d_name), dent->d_name);
1067
1068 strxfrchar(dso_name, '-', '_');
1069 map = kernel_maps__find_by_dso_name(dso_name);
1070 if (map == NULL)
1071 continue;
1072
1073 snprintf(path, sizeof(path), "%s/%s",
1074 dirname, dent->d_name);
1075
1076 map->dso->long_name = strdup(path);
1077 if (map->dso->long_name == NULL)
1078 goto failure;
1079
1080 err = dso__load_module_sym(map->dso, map, filter);
1081 if (err < 0)
1082 goto failure;
1083 last = rb_last(&map->dso->syms);
1084 if (last) {
1085 struct symbol *sym;
1086 /*
1087 * We do this here as well, even having the
1088 * symbol size found in the symtab because
1089 * misannotated ASM symbols may have the size
1090 * set to zero.
1091 */
1092 dso__fixup_sym_end(map->dso);
1093
1094 sym = rb_entry(last, struct symbol, rb_node);
1095 map->end = map->start + sym->end;
1096 }
1097 }
1098 nr_symbols += err;
1099 }
841 1100
842 /* 1101 return nr_symbols;
843 * Iterate over modules, and load active symbols. 1102failure:
844 */ 1103 closedir(dir);
845 next = rb_first(&mods->mods); 1104 return -1;
846 while (next) { 1105}
847 pos = rb_entry(next, struct module, rb_node);
848 err = dso__load_module(self, mods, pos->name, filter, v);
849 1106
850 if (err < 0) 1107static int dsos__load_modules_sym(symbol_filter_t filter)
851 break; 1108{
1109 struct utsname uts;
1110 char modules_path[PATH_MAX];
852 1111
853 next = rb_next(&pos->rb_node); 1112 if (uname(&uts) < 0)
854 count += err; 1113 return -1;
855 }
856 1114
857 if (err < 0) { 1115 snprintf(modules_path, sizeof(modules_path), "/lib/modules/%s/kernel",
858 mod_dso__delete_modules(mods); 1116 uts.release);
859 mod_dso__delete_self(mods);
860 return err;
861 }
862 1117
863 return count; 1118 return dsos__load_modules_sym_dir(modules_path, filter);
864} 1119}
865 1120
866static inline void dso__fill_symbol_holes(struct dso *self) 1121/*
1122 * Constructor variant for modules (where we know from /proc/modules where
1123 * they are loaded) and for vmlinux, where only after we load all the
1124 * symbols we'll know where it starts and ends.
1125 */
1126static struct map *map__new2(u64 start, struct dso *dso)
867{ 1127{
868 struct symbol *prev = NULL; 1128 struct map *self = malloc(sizeof(*self));
869 struct rb_node *nd;
870 1129
871 for (nd = rb_last(&self->syms); nd; nd = rb_prev(nd)) { 1130 if (self != NULL) {
872 struct symbol *pos = rb_entry(nd, struct symbol, rb_node); 1131 self->start = start;
1132 /*
1133 * Will be filled after we load all the symbols
1134 */
1135 self->end = 0;
873 1136
874 if (prev) { 1137 self->pgoff = 0;
875 u64 hole = 0; 1138 self->dso = dso;
876 int alias = pos->start == prev->start; 1139 self->map_ip = map__map_ip;
1140 self->unmap_ip = map__unmap_ip;
1141 RB_CLEAR_NODE(&self->rb_node);
1142 }
1143 return self;
1144}
877 1145
878 if (!alias) 1146static int dsos__load_modules(unsigned int sym_priv_size)
879 hole = prev->start - pos->end - 1; 1147{
1148 char *line = NULL;
1149 size_t n;
1150 FILE *file = fopen("/proc/modules", "r");
1151 struct map *map;
880 1152
881 if (hole || alias) { 1153 if (file == NULL)
882 if (alias) 1154 return -1;
883 pos->end = prev->end; 1155
884 else if (hole) 1156 while (!feof(file)) {
885 pos->end = prev->start - 1; 1157 char name[PATH_MAX];
886 } 1158 u64 start;
1159 struct dso *dso;
1160 char *sep;
1161 int line_len;
1162
1163 line_len = getline(&line, &n, file);
1164 if (line_len < 0)
1165 break;
1166
1167 if (!line)
1168 goto out_failure;
1169
1170 line[--line_len] = '\0'; /* \n */
1171
1172 sep = strrchr(line, 'x');
1173 if (sep == NULL)
1174 continue;
1175
1176 hex2u64(sep + 1, &start);
1177
1178 sep = strchr(line, ' ');
1179 if (sep == NULL)
1180 continue;
1181
1182 *sep = '\0';
1183
1184 snprintf(name, sizeof(name), "[%s]", line);
1185 dso = dso__new(name, sym_priv_size);
1186
1187 if (dso == NULL)
1188 goto out_delete_line;
1189
1190 map = map__new2(start, dso);
1191 if (map == NULL) {
1192 dso__delete(dso);
1193 goto out_delete_line;
887 } 1194 }
888 prev = pos; 1195
1196 dso->origin = DSO__ORIG_KMODULE;
1197 kernel_maps__insert(map);
1198 dsos__add(dso);
889 } 1199 }
1200
1201 free(line);
1202 fclose(file);
1203
1204 return 0;
1205
1206out_delete_line:
1207 free(line);
1208out_failure:
1209 return -1;
890} 1210}
891 1211
892static int dso__load_vmlinux(struct dso *self, const char *vmlinux, 1212static int dso__load_vmlinux(struct dso *self, struct map *map,
893 symbol_filter_t filter, int v) 1213 const char *vmlinux, symbol_filter_t filter)
894{ 1214{
895 int err, fd = open(vmlinux, O_RDONLY); 1215 int err, fd = open(vmlinux, O_RDONLY);
896 1216
897 if (fd < 0) 1217 if (fd < 0)
898 return -1; 1218 return -1;
899 1219
900 err = dso__load_sym(self, fd, vmlinux, filter, v, NULL); 1220 err = dso__load_sym(self, map, self->long_name, fd, filter, 1, 0);
901
902 if (err > 0)
903 dso__fill_symbol_holes(self);
904 1221
905 close(fd); 1222 close(fd);
906 1223
907 return err; 1224 return err;
908} 1225}
909 1226
910int dso__load_kernel(struct dso *self, const char *vmlinux, 1227int dsos__load_kernel(const char *vmlinux, unsigned int sym_priv_size,
911 symbol_filter_t filter, int v, int use_modules) 1228 symbol_filter_t filter, int use_modules)
912{ 1229{
913 int err = -1; 1230 int err = -1;
1231 struct dso *dso = dso__new(vmlinux, sym_priv_size);
1232
1233 if (dso == NULL)
1234 return -1;
1235
1236 dso->short_name = "[kernel]";
1237 kernel_map = map__new2(0, dso);
1238 if (kernel_map == NULL)
1239 goto out_delete_dso;
1240
1241 kernel_map->map_ip = kernel_map->unmap_ip = identity__map_ip;
1242
1243 if (use_modules && dsos__load_modules(sym_priv_size) < 0) {
1244 pr_warning("Failed to load list of modules in use! "
1245 "Continuing...\n");
1246 use_modules = 0;
1247 }
914 1248
915 if (vmlinux) { 1249 if (vmlinux) {
916 err = dso__load_vmlinux(self, vmlinux, filter, v); 1250 err = dso__load_vmlinux(dso, kernel_map, vmlinux, filter);
917 if (err > 0 && use_modules) { 1251 if (err > 0 && use_modules) {
918 int syms = dso__load_modules(self, filter, v); 1252 int syms = dsos__load_modules_sym(filter);
919 1253
920 if (syms < 0) { 1254 if (syms < 0)
921 fprintf(stderr, "dso__load_modules failed!\n"); 1255 pr_warning("Failed to read module symbols!"
922 return syms; 1256 " Continuing...\n");
923 } 1257 else
924 err += syms; 1258 err += syms;
925 } 1259 }
926 } 1260 }
927 1261
928 if (err <= 0) 1262 if (err <= 0)
929 err = dso__load_kallsyms(self, filter, v); 1263 err = kernel_maps__load_kallsyms(filter, use_modules);
1264
1265 if (err > 0) {
1266 struct rb_node *node = rb_first(&dso->syms);
1267 struct symbol *sym = rb_entry(node, struct symbol, rb_node);
1268
1269 kernel_map->start = sym->start;
1270 node = rb_last(&dso->syms);
1271 sym = rb_entry(node, struct symbol, rb_node);
1272 kernel_map->end = sym->end;
1273
1274 dso->origin = DSO__ORIG_KERNEL;
1275 kernel_maps__insert(kernel_map);
1276 /*
1277 * Now that we have all sorted out, just set the ->end of all
1278 * maps:
1279 */
1280 kernel_maps__fixup_end();
1281 dsos__add(dso);
930 1282
931 if (err > 0) 1283 if (verbose)
932 self->origin = DSO__ORIG_KERNEL; 1284 kernel_maps__fprintf(stderr);
1285 }
933 1286
934 return err; 1287 return err;
1288
1289out_delete_dso:
1290 dso__delete(dso);
1291 return -1;
935} 1292}
936 1293
937LIST_HEAD(dsos); 1294LIST_HEAD(dsos);
938struct dso *kernel_dso;
939struct dso *vdso; 1295struct dso *vdso;
940struct dso *hypervisor_dso;
941 1296
942const char *vmlinux_name = "vmlinux"; 1297const char *vmlinux_name = "vmlinux";
943int modules; 1298int modules;
@@ -957,33 +1312,21 @@ static struct dso *dsos__find(const char *name)
957 return NULL; 1312 return NULL;
958} 1313}
959 1314
960struct dso *dsos__findnew(const char *name) 1315struct dso *dsos__findnew(const char *name, unsigned int sym_priv_size,
1316 bool *is_new)
961{ 1317{
962 struct dso *dso = dsos__find(name); 1318 struct dso *dso = dsos__find(name);
963 int nr;
964 1319
965 if (dso) 1320 if (!dso) {
966 return dso; 1321 dso = dso__new(name, sym_priv_size);
967 1322 if (dso) {
968 dso = dso__new(name, 0); 1323 dsos__add(dso);
969 if (!dso) 1324 *is_new = true;
970 goto out_delete_dso; 1325 }
971 1326 } else
972 nr = dso__load(dso, NULL, verbose); 1327 *is_new = false;
973 if (nr < 0) {
974 eprintf("Failed to open: %s\n", name);
975 goto out_delete_dso;
976 }
977 if (!nr)
978 eprintf("No symbols found in: %s, maybe install a debug package?\n", name);
979
980 dsos__add(dso);
981 1328
982 return dso; 1329 return dso;
983
984out_delete_dso:
985 dso__delete(dso);
986 return NULL;
987} 1330}
988 1331
989void dsos__fprintf(FILE *fp) 1332void dsos__fprintf(FILE *fp)
@@ -994,43 +1337,21 @@ void dsos__fprintf(FILE *fp)
994 dso__fprintf(pos, fp); 1337 dso__fprintf(pos, fp);
995} 1338}
996 1339
997static struct symbol *vdso__find_symbol(struct dso *dso, u64 ip) 1340int load_kernel(unsigned int sym_priv_size, symbol_filter_t filter)
998{
999 return dso__find_symbol(dso, ip);
1000}
1001
1002int load_kernel(void)
1003{ 1341{
1004 int err; 1342 if (dsos__load_kernel(vmlinux_name, sym_priv_size, filter,
1005 1343 modules) <= 0)
1006 kernel_dso = dso__new("[kernel]", 0);
1007 if (!kernel_dso)
1008 return -1; 1344 return -1;
1009 1345
1010 err = dso__load_kernel(kernel_dso, vmlinux_name, NULL, verbose, modules);
1011 if (err <= 0) {
1012 dso__delete(kernel_dso);
1013 kernel_dso = NULL;
1014 } else
1015 dsos__add(kernel_dso);
1016
1017 vdso = dso__new("[vdso]", 0); 1346 vdso = dso__new("[vdso]", 0);
1018 if (!vdso) 1347 if (!vdso)
1019 return -1; 1348 return -1;
1020 1349
1021 vdso->find_symbol = vdso__find_symbol;
1022
1023 dsos__add(vdso); 1350 dsos__add(vdso);
1024 1351
1025 hypervisor_dso = dso__new("[hypervisor]", 0); 1352 return 0;
1026 if (!hypervisor_dso)
1027 return -1;
1028 dsos__add(hypervisor_dso);
1029
1030 return err;
1031} 1353}
1032 1354
1033
1034void symbol__init(void) 1355void symbol__init(void)
1035{ 1356{
1036 elf_version(EV_CURRENT); 1357 elf_version(EV_CURRENT);
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 6e849071640..77b7b3e4241 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -1,11 +1,11 @@
1#ifndef _PERF_SYMBOL_ 1#ifndef __PERF_SYMBOL
2#define _PERF_SYMBOL_ 1 2#define __PERF_SYMBOL 1
3 3
4#include <linux/types.h> 4#include <linux/types.h>
5#include <stdbool.h>
5#include "types.h" 6#include "types.h"
6#include <linux/list.h> 7#include <linux/list.h>
7#include <linux/rbtree.h> 8#include <linux/rbtree.h>
8#include "module.h"
9#include "event.h" 9#include "event.h"
10 10
11#ifdef HAVE_CPLUS_DEMANGLE 11#ifdef HAVE_CPLUS_DEMANGLE
@@ -36,11 +36,6 @@ struct symbol {
36 struct rb_node rb_node; 36 struct rb_node rb_node;
37 u64 start; 37 u64 start;
38 u64 end; 38 u64 end;
39 u64 obj_start;
40 u64 hist_sum;
41 u64 *hist;
42 struct module *module;
43 void *priv;
44 char name[0]; 39 char name[0];
45}; 40};
46 41
@@ -52,13 +47,11 @@ struct dso {
52 unsigned char adjust_symbols; 47 unsigned char adjust_symbols;
53 unsigned char slen_calculated; 48 unsigned char slen_calculated;
54 unsigned char origin; 49 unsigned char origin;
50 const char *short_name;
51 char *long_name;
55 char name[0]; 52 char name[0];
56}; 53};
57 54
58extern const char *sym_hist_filter;
59
60typedef int (*symbol_filter_t)(struct dso *self, struct symbol *sym);
61
62struct dso *dso__new(const char *name, unsigned int sym_priv_size); 55struct dso *dso__new(const char *name, unsigned int sym_priv_size);
63void dso__delete(struct dso *self); 56void dso__delete(struct dso *self);
64 57
@@ -69,24 +62,23 @@ static inline void *dso__sym_priv(struct dso *self, struct symbol *sym)
69 62
70struct symbol *dso__find_symbol(struct dso *self, u64 ip); 63struct symbol *dso__find_symbol(struct dso *self, u64 ip);
71 64
72int dso__load_kernel(struct dso *self, const char *vmlinux, 65int dsos__load_kernel(const char *vmlinux, unsigned int sym_priv_size,
73 symbol_filter_t filter, int verbose, int modules); 66 symbol_filter_t filter, int modules);
74int dso__load_modules(struct dso *self, symbol_filter_t filter, int verbose); 67struct dso *dsos__findnew(const char *name, unsigned int sym_priv_size,
75int dso__load(struct dso *self, symbol_filter_t filter, int verbose); 68 bool *is_new);
76struct dso *dsos__findnew(const char *name); 69int dso__load(struct dso *self, struct map *map, symbol_filter_t filter);
77void dsos__fprintf(FILE *fp); 70void dsos__fprintf(FILE *fp);
78 71
79size_t dso__fprintf(struct dso *self, FILE *fp); 72size_t dso__fprintf(struct dso *self, FILE *fp);
80char dso__symtab_origin(const struct dso *self); 73char dso__symtab_origin(const struct dso *self);
81 74
82int load_kernel(void); 75int load_kernel(unsigned int sym_priv_size, symbol_filter_t filter);
83 76
84void symbol__init(void); 77void symbol__init(void);
85 78
86extern struct list_head dsos; 79extern struct list_head dsos;
87extern struct dso *kernel_dso; 80extern struct map *kernel_map;
88extern struct dso *vdso; 81extern struct dso *vdso;
89extern struct dso *hypervisor_dso;
90extern const char *vmlinux_name; 82extern const char *vmlinux_name;
91extern int modules; 83extern int modules;
92#endif /* _PERF_SYMBOL_ */ 84#endif /* __PERF_SYMBOL */
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 45efb5db0d1..0f6d78c9863 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -6,6 +6,9 @@
6#include "util.h" 6#include "util.h"
7#include "debug.h" 7#include "debug.h"
8 8
9static struct rb_root threads;
10static struct thread *last_match;
11
9static struct thread *thread__new(pid_t pid) 12static struct thread *thread__new(pid_t pid)
10{ 13{
11 struct thread *self = calloc(1, sizeof(*self)); 14 struct thread *self = calloc(1, sizeof(*self));
@@ -15,7 +18,8 @@ static struct thread *thread__new(pid_t pid)
15 self->comm = malloc(32); 18 self->comm = malloc(32);
16 if (self->comm) 19 if (self->comm)
17 snprintf(self->comm, 32, ":%d", self->pid); 20 snprintf(self->comm, 32, ":%d", self->pid);
18 INIT_LIST_HEAD(&self->maps); 21 self->maps = RB_ROOT;
22 INIT_LIST_HEAD(&self->removed_maps);
19 } 23 }
20 24
21 return self; 25 return self;
@@ -29,21 +33,40 @@ int thread__set_comm(struct thread *self, const char *comm)
29 return self->comm ? 0 : -ENOMEM; 33 return self->comm ? 0 : -ENOMEM;
30} 34}
31 35
36int thread__comm_len(struct thread *self)
37{
38 if (!self->comm_len) {
39 if (!self->comm)
40 return 0;
41 self->comm_len = strlen(self->comm);
42 }
43
44 return self->comm_len;
45}
46
32static size_t thread__fprintf(struct thread *self, FILE *fp) 47static size_t thread__fprintf(struct thread *self, FILE *fp)
33{ 48{
49 struct rb_node *nd;
34 struct map *pos; 50 struct map *pos;
35 size_t ret = fprintf(fp, "Thread %d %s\n", self->pid, self->comm); 51 size_t ret = fprintf(fp, "Thread %d %s\nCurrent maps:\n",
52 self->pid, self->comm);
36 53
37 list_for_each_entry(pos, &self->maps, node) 54 for (nd = rb_first(&self->maps); nd; nd = rb_next(nd)) {
55 pos = rb_entry(nd, struct map, rb_node);
56 ret += map__fprintf(pos, fp);
57 }
58
59 ret = fprintf(fp, "Removed maps:\n");
60
61 list_for_each_entry(pos, &self->removed_maps, node)
38 ret += map__fprintf(pos, fp); 62 ret += map__fprintf(pos, fp);
39 63
40 return ret; 64 return ret;
41} 65}
42 66
43struct thread * 67struct thread *threads__findnew(pid_t pid)
44threads__findnew(pid_t pid, struct rb_root *threads, struct thread **last_match)
45{ 68{
46 struct rb_node **p = &threads->rb_node; 69 struct rb_node **p = &threads.rb_node;
47 struct rb_node *parent = NULL; 70 struct rb_node *parent = NULL;
48 struct thread *th; 71 struct thread *th;
49 72
@@ -52,15 +75,15 @@ threads__findnew(pid_t pid, struct rb_root *threads, struct thread **last_match)
52 * so most of the time we dont have to look up 75 * so most of the time we dont have to look up
53 * the full rbtree: 76 * the full rbtree:
54 */ 77 */
55 if (*last_match && (*last_match)->pid == pid) 78 if (last_match && last_match->pid == pid)
56 return *last_match; 79 return last_match;
57 80
58 while (*p != NULL) { 81 while (*p != NULL) {
59 parent = *p; 82 parent = *p;
60 th = rb_entry(parent, struct thread, rb_node); 83 th = rb_entry(parent, struct thread, rb_node);
61 84
62 if (th->pid == pid) { 85 if (th->pid == pid) {
63 *last_match = th; 86 last_match = th;
64 return th; 87 return th;
65 } 88 }
66 89
@@ -73,17 +96,16 @@ threads__findnew(pid_t pid, struct rb_root *threads, struct thread **last_match)
73 th = thread__new(pid); 96 th = thread__new(pid);
74 if (th != NULL) { 97 if (th != NULL) {
75 rb_link_node(&th->rb_node, parent, p); 98 rb_link_node(&th->rb_node, parent, p);
76 rb_insert_color(&th->rb_node, threads); 99 rb_insert_color(&th->rb_node, &threads);
77 *last_match = th; 100 last_match = th;
78 } 101 }
79 102
80 return th; 103 return th;
81} 104}
82 105
83struct thread * 106struct thread *register_idle_thread(void)
84register_idle_thread(struct rb_root *threads, struct thread **last_match)
85{ 107{
86 struct thread *thread = threads__findnew(0, threads, last_match); 108 struct thread *thread = threads__findnew(0);
87 109
88 if (!thread || thread__set_comm(thread, "swapper")) { 110 if (!thread || thread__set_comm(thread, "swapper")) {
89 fprintf(stderr, "problem inserting idle task.\n"); 111 fprintf(stderr, "problem inserting idle task.\n");
@@ -93,42 +115,82 @@ register_idle_thread(struct rb_root *threads, struct thread **last_match)
93 return thread; 115 return thread;
94} 116}
95 117
96void thread__insert_map(struct thread *self, struct map *map) 118static void thread__remove_overlappings(struct thread *self, struct map *map)
97{ 119{
98 struct map *pos, *tmp; 120 struct rb_node *next = rb_first(&self->maps);
99 121
100 list_for_each_entry_safe(pos, tmp, &self->maps, node) { 122 while (next) {
101 if (map__overlap(pos, map)) { 123 struct map *pos = rb_entry(next, struct map, rb_node);
102 if (verbose >= 2) { 124 next = rb_next(&pos->rb_node);
103 printf("overlapping maps:\n"); 125
104 map__fprintf(map, stdout); 126 if (!map__overlap(pos, map))
105 map__fprintf(pos, stdout); 127 continue;
106 } 128
107 129 if (verbose >= 2) {
108 if (map->start <= pos->start && map->end > pos->start) 130 fputs("overlapping maps:\n", stderr);
109 pos->start = map->end; 131 map__fprintf(map, stderr);
110 132 map__fprintf(pos, stderr);
111 if (map->end >= pos->end && map->start < pos->end)
112 pos->end = map->start;
113
114 if (verbose >= 2) {
115 printf("after collision:\n");
116 map__fprintf(pos, stdout);
117 }
118
119 if (pos->start >= pos->end) {
120 list_del_init(&pos->node);
121 free(pos);
122 }
123 } 133 }
134
135 rb_erase(&pos->rb_node, &self->maps);
136 /*
137 * We may have references to this map, for instance in some
138 * hist_entry instances, so just move them to a separate
139 * list.
140 */
141 list_add_tail(&pos->node, &self->removed_maps);
142 }
143}
144
145void maps__insert(struct rb_root *maps, struct map *map)
146{
147 struct rb_node **p = &maps->rb_node;
148 struct rb_node *parent = NULL;
149 const u64 ip = map->start;
150 struct map *m;
151
152 while (*p != NULL) {
153 parent = *p;
154 m = rb_entry(parent, struct map, rb_node);
155 if (ip < m->start)
156 p = &(*p)->rb_left;
157 else
158 p = &(*p)->rb_right;
124 } 159 }
125 160
126 list_add_tail(&map->node, &self->maps); 161 rb_link_node(&map->rb_node, parent, p);
162 rb_insert_color(&map->rb_node, maps);
163}
164
165struct map *maps__find(struct rb_root *maps, u64 ip)
166{
167 struct rb_node **p = &maps->rb_node;
168 struct rb_node *parent = NULL;
169 struct map *m;
170
171 while (*p != NULL) {
172 parent = *p;
173 m = rb_entry(parent, struct map, rb_node);
174 if (ip < m->start)
175 p = &(*p)->rb_left;
176 else if (ip > m->end)
177 p = &(*p)->rb_right;
178 else
179 return m;
180 }
181
182 return NULL;
183}
184
185void thread__insert_map(struct thread *self, struct map *map)
186{
187 thread__remove_overlappings(self, map);
188 maps__insert(&self->maps, map);
127} 189}
128 190
129int thread__fork(struct thread *self, struct thread *parent) 191int thread__fork(struct thread *self, struct thread *parent)
130{ 192{
131 struct map *map; 193 struct rb_node *nd;
132 194
133 if (self->comm) 195 if (self->comm)
134 free(self->comm); 196 free(self->comm);
@@ -136,7 +198,8 @@ int thread__fork(struct thread *self, struct thread *parent)
136 if (!self->comm) 198 if (!self->comm)
137 return -ENOMEM; 199 return -ENOMEM;
138 200
139 list_for_each_entry(map, &parent->maps, node) { 201 for (nd = rb_first(&parent->maps); nd; nd = rb_next(nd)) {
202 struct map *map = rb_entry(nd, struct map, rb_node);
140 struct map *new = map__clone(map); 203 struct map *new = map__clone(map);
141 if (!new) 204 if (!new)
142 return -ENOMEM; 205 return -ENOMEM;
@@ -146,26 +209,12 @@ int thread__fork(struct thread *self, struct thread *parent)
146 return 0; 209 return 0;
147} 210}
148 211
149struct map *thread__find_map(struct thread *self, u64 ip) 212size_t threads__fprintf(FILE *fp)
150{
151 struct map *pos;
152
153 if (self == NULL)
154 return NULL;
155
156 list_for_each_entry(pos, &self->maps, node)
157 if (ip >= pos->start && ip <= pos->end)
158 return pos;
159
160 return NULL;
161}
162
163size_t threads__fprintf(FILE *fp, struct rb_root *threads)
164{ 213{
165 size_t ret = 0; 214 size_t ret = 0;
166 struct rb_node *nd; 215 struct rb_node *nd;
167 216
168 for (nd = rb_first(threads); nd; nd = rb_next(nd)) { 217 for (nd = rb_first(&threads); nd; nd = rb_next(nd)) {
169 struct thread *pos = rb_entry(nd, struct thread, rb_node); 218 struct thread *pos = rb_entry(nd, struct thread, rb_node);
170 219
171 ret += thread__fprintf(pos, fp); 220 ret += thread__fprintf(pos, fp);
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 32aea3c1c2a..53addd77ce8 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -1,22 +1,37 @@
1#ifndef __PERF_THREAD_H
2#define __PERF_THREAD_H
3
1#include <linux/rbtree.h> 4#include <linux/rbtree.h>
2#include <linux/list.h>
3#include <unistd.h> 5#include <unistd.h>
4#include "symbol.h" 6#include "symbol.h"
5 7
6struct thread { 8struct thread {
7 struct rb_node rb_node; 9 struct rb_node rb_node;
8 struct list_head maps; 10 struct rb_root maps;
11 struct list_head removed_maps;
9 pid_t pid; 12 pid_t pid;
10 char shortname[3]; 13 char shortname[3];
11 char *comm; 14 char *comm;
15 int comm_len;
12}; 16};
13 17
14int thread__set_comm(struct thread *self, const char *comm); 18int thread__set_comm(struct thread *self, const char *comm);
15struct thread * 19int thread__comm_len(struct thread *self);
16threads__findnew(pid_t pid, struct rb_root *threads, struct thread **last_match); 20struct thread *threads__findnew(pid_t pid);
17struct thread * 21struct thread *register_idle_thread(void);
18register_idle_thread(struct rb_root *threads, struct thread **last_match);
19void thread__insert_map(struct thread *self, struct map *map); 22void thread__insert_map(struct thread *self, struct map *map);
20int thread__fork(struct thread *self, struct thread *parent); 23int thread__fork(struct thread *self, struct thread *parent);
21struct map *thread__find_map(struct thread *self, u64 ip); 24size_t threads__fprintf(FILE *fp);
22size_t threads__fprintf(FILE *fp, struct rb_root *threads); 25
26void maps__insert(struct rb_root *maps, struct map *map);
27struct map *maps__find(struct rb_root *maps, u64 ip);
28
29struct symbol *kernel_maps__find_symbol(const u64 ip, struct map **mapp);
30struct map *kernel_maps__find_by_dso_name(const char *name);
31
32static inline struct map *thread__find_map(struct thread *self, u64 ip)
33{
34 return self ? maps__find(&self->maps, ip) : NULL;
35}
36
37#endif /* __PERF_THREAD_H */
diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c
index af4b0573b37..831052d4b4f 100644
--- a/tools/perf/util/trace-event-info.c
+++ b/tools/perf/util/trace-event-info.c
@@ -496,14 +496,12 @@ get_tracepoints_path(struct perf_event_attr *pattrs, int nb_events)
496 496
497 return path.next; 497 return path.next;
498} 498}
499void read_tracing_data(struct perf_event_attr *pattrs, int nb_events) 499void read_tracing_data(int fd, struct perf_event_attr *pattrs, int nb_events)
500{ 500{
501 char buf[BUFSIZ]; 501 char buf[BUFSIZ];
502 struct tracepoint_path *tps; 502 struct tracepoint_path *tps;
503 503
504 output_fd = open(output_file, O_WRONLY | O_CREAT | O_TRUNC | O_LARGEFILE, 0644); 504 output_fd = fd;
505 if (output_fd < 0)
506 die("creating file '%s'", output_file);
507 505
508 buf[0] = 23; 506 buf[0] = 23;
509 buf[1] = 8; 507 buf[1] = 8;
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c
index 55c9659a56e..eae56050308 100644
--- a/tools/perf/util/trace-event-parse.c
+++ b/tools/perf/util/trace-event-parse.c
@@ -40,6 +40,8 @@ int header_page_size_size;
40int header_page_data_offset; 40int header_page_data_offset;
41int header_page_data_size; 41int header_page_data_size;
42 42
43int latency_format;
44
43static char *input_buf; 45static char *input_buf;
44static unsigned long long input_buf_ptr; 46static unsigned long long input_buf_ptr;
45static unsigned long long input_buf_siz; 47static unsigned long long input_buf_siz;
@@ -284,18 +286,19 @@ void parse_ftrace_printk(char *file, unsigned int size __unused)
284 char *line; 286 char *line;
285 char *next = NULL; 287 char *next = NULL;
286 char *addr_str; 288 char *addr_str;
287 int ret;
288 int i; 289 int i;
289 290
290 line = strtok_r(file, "\n", &next); 291 line = strtok_r(file, "\n", &next);
291 while (line) { 292 while (line) {
293 addr_str = strsep(&line, ":");
294 if (!line) {
295 warning("error parsing print strings");
296 break;
297 }
292 item = malloc_or_die(sizeof(*item)); 298 item = malloc_or_die(sizeof(*item));
293 ret = sscanf(line, "%as : %as",
294 (float *)(void *)&addr_str, /* workaround gcc warning */
295 (float *)(void *)&item->printk);
296 item->addr = strtoull(addr_str, NULL, 16); 299 item->addr = strtoull(addr_str, NULL, 16);
297 free(addr_str); 300 /* fmt still has a space, skip it */
298 301 item->printk = strdup(line+1);
299 item->next = list; 302 item->next = list;
300 list = item; 303 list = item;
301 line = strtok_r(NULL, "\n", &next); 304 line = strtok_r(NULL, "\n", &next);
@@ -522,7 +525,10 @@ static enum event_type __read_token(char **tok)
522 last_ch = ch; 525 last_ch = ch;
523 ch = __read_char(); 526 ch = __read_char();
524 buf[i++] = ch; 527 buf[i++] = ch;
525 } while (ch != quote_ch && last_ch != '\\'); 528 /* the '\' '\' will cancel itself */
529 if (ch == '\\' && last_ch == '\\')
530 last_ch = 0;
531 } while (ch != quote_ch || last_ch == '\\');
526 /* remove the last quote */ 532 /* remove the last quote */
527 i--; 533 i--;
528 goto out; 534 goto out;
@@ -610,7 +616,7 @@ static enum event_type read_token_item(char **tok)
610static int test_type(enum event_type type, enum event_type expect) 616static int test_type(enum event_type type, enum event_type expect)
611{ 617{
612 if (type != expect) { 618 if (type != expect) {
613 die("Error: expected type %d but read %d", 619 warning("Error: expected type %d but read %d",
614 expect, type); 620 expect, type);
615 return -1; 621 return -1;
616 } 622 }
@@ -621,13 +627,13 @@ static int test_type_token(enum event_type type, char *token,
621 enum event_type expect, const char *expect_tok) 627 enum event_type expect, const char *expect_tok)
622{ 628{
623 if (type != expect) { 629 if (type != expect) {
624 die("Error: expected type %d but read %d", 630 warning("Error: expected type %d but read %d",
625 expect, type); 631 expect, type);
626 return -1; 632 return -1;
627 } 633 }
628 634
629 if (strcmp(token, expect_tok) != 0) { 635 if (strcmp(token, expect_tok) != 0) {
630 die("Error: expected '%s' but read '%s'", 636 warning("Error: expected '%s' but read '%s'",
631 expect_tok, token); 637 expect_tok, token);
632 return -1; 638 return -1;
633 } 639 }
@@ -665,7 +671,7 @@ static int __read_expected(enum event_type expect, const char *str, int newline_
665 671
666 free_token(token); 672 free_token(token);
667 673
668 return 0; 674 return ret;
669} 675}
670 676
671static int read_expected(enum event_type expect, const char *str) 677static int read_expected(enum event_type expect, const char *str)
@@ -682,10 +688,10 @@ static char *event_read_name(void)
682{ 688{
683 char *token; 689 char *token;
684 690
685 if (read_expected(EVENT_ITEM, (char *)"name") < 0) 691 if (read_expected(EVENT_ITEM, "name") < 0)
686 return NULL; 692 return NULL;
687 693
688 if (read_expected(EVENT_OP, (char *)":") < 0) 694 if (read_expected(EVENT_OP, ":") < 0)
689 return NULL; 695 return NULL;
690 696
691 if (read_expect_type(EVENT_ITEM, &token) < 0) 697 if (read_expect_type(EVENT_ITEM, &token) < 0)
@@ -703,10 +709,10 @@ static int event_read_id(void)
703 char *token; 709 char *token;
704 int id; 710 int id;
705 711
706 if (read_expected_item(EVENT_ITEM, (char *)"ID") < 0) 712 if (read_expected_item(EVENT_ITEM, "ID") < 0)
707 return -1; 713 return -1;
708 714
709 if (read_expected(EVENT_OP, (char *)":") < 0) 715 if (read_expected(EVENT_OP, ":") < 0)
710 return -1; 716 return -1;
711 717
712 if (read_expect_type(EVENT_ITEM, &token) < 0) 718 if (read_expect_type(EVENT_ITEM, &token) < 0)
@@ -721,6 +727,24 @@ static int event_read_id(void)
721 return -1; 727 return -1;
722} 728}
723 729
730static int field_is_string(struct format_field *field)
731{
732 if ((field->flags & FIELD_IS_ARRAY) &&
733 (!strstr(field->type, "char") || !strstr(field->type, "u8") ||
734 !strstr(field->type, "s8")))
735 return 1;
736
737 return 0;
738}
739
740static int field_is_dynamic(struct format_field *field)
741{
742 if (!strcmp(field->type, "__data_loc"))
743 return 1;
744
745 return 0;
746}
747
724static int event_read_fields(struct event *event, struct format_field **fields) 748static int event_read_fields(struct event *event, struct format_field **fields)
725{ 749{
726 struct format_field *field = NULL; 750 struct format_field *field = NULL;
@@ -738,7 +762,7 @@ static int event_read_fields(struct event *event, struct format_field **fields)
738 762
739 count++; 763 count++;
740 764
741 if (test_type_token(type, token, EVENT_ITEM, (char *)"field")) 765 if (test_type_token(type, token, EVENT_ITEM, "field"))
742 goto fail; 766 goto fail;
743 free_token(token); 767 free_token(token);
744 768
@@ -753,7 +777,7 @@ static int event_read_fields(struct event *event, struct format_field **fields)
753 type = read_token(&token); 777 type = read_token(&token);
754 } 778 }
755 779
756 if (test_type_token(type, token, EVENT_OP, (char *)":") < 0) 780 if (test_type_token(type, token, EVENT_OP, ":") < 0)
757 return -1; 781 return -1;
758 782
759 if (read_expect_type(EVENT_ITEM, &token) < 0) 783 if (read_expect_type(EVENT_ITEM, &token) < 0)
@@ -865,14 +889,20 @@ static int event_read_fields(struct event *event, struct format_field **fields)
865 free(brackets); 889 free(brackets);
866 } 890 }
867 891
868 if (test_type_token(type, token, EVENT_OP, (char *)";")) 892 if (field_is_string(field)) {
893 field->flags |= FIELD_IS_STRING;
894 if (field_is_dynamic(field))
895 field->flags |= FIELD_IS_DYNAMIC;
896 }
897
898 if (test_type_token(type, token, EVENT_OP, ";"))
869 goto fail; 899 goto fail;
870 free_token(token); 900 free_token(token);
871 901
872 if (read_expected(EVENT_ITEM, (char *)"offset") < 0) 902 if (read_expected(EVENT_ITEM, "offset") < 0)
873 goto fail_expect; 903 goto fail_expect;
874 904
875 if (read_expected(EVENT_OP, (char *)":") < 0) 905 if (read_expected(EVENT_OP, ":") < 0)
876 goto fail_expect; 906 goto fail_expect;
877 907
878 if (read_expect_type(EVENT_ITEM, &token)) 908 if (read_expect_type(EVENT_ITEM, &token))
@@ -880,13 +910,13 @@ static int event_read_fields(struct event *event, struct format_field **fields)
880 field->offset = strtoul(token, NULL, 0); 910 field->offset = strtoul(token, NULL, 0);
881 free_token(token); 911 free_token(token);
882 912
883 if (read_expected(EVENT_OP, (char *)";") < 0) 913 if (read_expected(EVENT_OP, ";") < 0)
884 goto fail_expect; 914 goto fail_expect;
885 915
886 if (read_expected(EVENT_ITEM, (char *)"size") < 0) 916 if (read_expected(EVENT_ITEM, "size") < 0)
887 goto fail_expect; 917 goto fail_expect;
888 918
889 if (read_expected(EVENT_OP, (char *)":") < 0) 919 if (read_expected(EVENT_OP, ":") < 0)
890 goto fail_expect; 920 goto fail_expect;
891 921
892 if (read_expect_type(EVENT_ITEM, &token)) 922 if (read_expect_type(EVENT_ITEM, &token))
@@ -894,11 +924,33 @@ static int event_read_fields(struct event *event, struct format_field **fields)
894 field->size = strtoul(token, NULL, 0); 924 field->size = strtoul(token, NULL, 0);
895 free_token(token); 925 free_token(token);
896 926
897 if (read_expected(EVENT_OP, (char *)";") < 0) 927 if (read_expected(EVENT_OP, ";") < 0)
898 goto fail_expect; 928 goto fail_expect;
899 929
900 if (read_expect_type(EVENT_NEWLINE, &token) < 0) 930 type = read_token(&token);
901 goto fail; 931 if (type != EVENT_NEWLINE) {
932 /* newer versions of the kernel have a "signed" type */
933 if (test_type_token(type, token, EVENT_ITEM, "signed"))
934 goto fail;
935
936 free_token(token);
937
938 if (read_expected(EVENT_OP, ":") < 0)
939 goto fail_expect;
940
941 if (read_expect_type(EVENT_ITEM, &token))
942 goto fail;
943
944 /* add signed type */
945
946 free_token(token);
947 if (read_expected(EVENT_OP, ";") < 0)
948 goto fail_expect;
949
950 if (read_expect_type(EVENT_NEWLINE, &token))
951 goto fail;
952 }
953
902 free_token(token); 954 free_token(token);
903 955
904 *fields = field; 956 *fields = field;
@@ -921,10 +973,10 @@ static int event_read_format(struct event *event)
921 char *token; 973 char *token;
922 int ret; 974 int ret;
923 975
924 if (read_expected_item(EVENT_ITEM, (char *)"format") < 0) 976 if (read_expected_item(EVENT_ITEM, "format") < 0)
925 return -1; 977 return -1;
926 978
927 if (read_expected(EVENT_OP, (char *)":") < 0) 979 if (read_expected(EVENT_OP, ":") < 0)
928 return -1; 980 return -1;
929 981
930 if (read_expect_type(EVENT_NEWLINE, &token)) 982 if (read_expect_type(EVENT_NEWLINE, &token))
@@ -984,7 +1036,7 @@ process_cond(struct event *event, struct print_arg *top, char **tok)
984 1036
985 *tok = NULL; 1037 *tok = NULL;
986 type = process_arg(event, left, &token); 1038 type = process_arg(event, left, &token);
987 if (test_type_token(type, token, EVENT_OP, (char *)":")) 1039 if (test_type_token(type, token, EVENT_OP, ":"))
988 goto out_free; 1040 goto out_free;
989 1041
990 arg->op.op = token; 1042 arg->op.op = token;
@@ -1004,6 +1056,35 @@ out_free:
1004 return EVENT_ERROR; 1056 return EVENT_ERROR;
1005} 1057}
1006 1058
1059static enum event_type
1060process_array(struct event *event, struct print_arg *top, char **tok)
1061{
1062 struct print_arg *arg;
1063 enum event_type type;
1064 char *token = NULL;
1065
1066 arg = malloc_or_die(sizeof(*arg));
1067 memset(arg, 0, sizeof(*arg));
1068
1069 *tok = NULL;
1070 type = process_arg(event, arg, &token);
1071 if (test_type_token(type, token, EVENT_OP, "]"))
1072 goto out_free;
1073
1074 top->op.right = arg;
1075
1076 free_token(token);
1077 type = read_token_item(&token);
1078 *tok = token;
1079
1080 return type;
1081
1082out_free:
1083 free_token(*tok);
1084 free_arg(arg);
1085 return EVENT_ERROR;
1086}
1087
1007static int get_op_prio(char *op) 1088static int get_op_prio(char *op)
1008{ 1089{
1009 if (!op[1]) { 1090 if (!op[1]) {
@@ -1128,6 +1209,8 @@ process_op(struct event *event, struct print_arg *arg, char **tok)
1128 strcmp(token, "*") == 0 || 1209 strcmp(token, "*") == 0 ||
1129 strcmp(token, "^") == 0 || 1210 strcmp(token, "^") == 0 ||
1130 strcmp(token, "/") == 0 || 1211 strcmp(token, "/") == 0 ||
1212 strcmp(token, "<") == 0 ||
1213 strcmp(token, ">") == 0 ||
1131 strcmp(token, "==") == 0 || 1214 strcmp(token, "==") == 0 ||
1132 strcmp(token, "!=") == 0) { 1215 strcmp(token, "!=") == 0) {
1133 1216
@@ -1144,17 +1227,46 @@ process_op(struct event *event, struct print_arg *arg, char **tok)
1144 1227
1145 right = malloc_or_die(sizeof(*right)); 1228 right = malloc_or_die(sizeof(*right));
1146 1229
1147 type = process_arg(event, right, tok); 1230 type = read_token_item(&token);
1231 *tok = token;
1232
1233 /* could just be a type pointer */
1234 if ((strcmp(arg->op.op, "*") == 0) &&
1235 type == EVENT_DELIM && (strcmp(token, ")") == 0)) {
1236 if (left->type != PRINT_ATOM)
1237 die("bad pointer type");
1238 left->atom.atom = realloc(left->atom.atom,
1239 sizeof(left->atom.atom) + 3);
1240 strcat(left->atom.atom, " *");
1241 *arg = *left;
1242 free(arg);
1243
1244 return type;
1245 }
1246
1247 type = process_arg_token(event, right, tok, type);
1148 1248
1149 arg->op.right = right; 1249 arg->op.right = right;
1150 1250
1251 } else if (strcmp(token, "[") == 0) {
1252
1253 left = malloc_or_die(sizeof(*left));
1254 *left = *arg;
1255
1256 arg->type = PRINT_OP;
1257 arg->op.op = token;
1258 arg->op.left = left;
1259
1260 arg->op.prio = 0;
1261 type = process_array(event, arg, tok);
1262
1151 } else { 1263 } else {
1152 die("unknown op '%s'", token); 1264 warning("unknown op '%s'", token);
1265 event->flags |= EVENT_FL_FAILED;
1153 /* the arg is now the left side */ 1266 /* the arg is now the left side */
1154 return EVENT_NONE; 1267 return EVENT_NONE;
1155 } 1268 }
1156 1269
1157
1158 if (type == EVENT_OP) { 1270 if (type == EVENT_OP) {
1159 int prio; 1271 int prio;
1160 1272
@@ -1178,7 +1290,7 @@ process_entry(struct event *event __unused, struct print_arg *arg,
1178 char *field; 1290 char *field;
1179 char *token; 1291 char *token;
1180 1292
1181 if (read_expected(EVENT_OP, (char *)"->") < 0) 1293 if (read_expected(EVENT_OP, "->") < 0)
1182 return EVENT_ERROR; 1294 return EVENT_ERROR;
1183 1295
1184 if (read_expect_type(EVENT_ITEM, &token) < 0) 1296 if (read_expect_type(EVENT_ITEM, &token) < 0)
@@ -1338,14 +1450,14 @@ process_fields(struct event *event, struct print_flag_sym **list, char **tok)
1338 do { 1450 do {
1339 free_token(token); 1451 free_token(token);
1340 type = read_token_item(&token); 1452 type = read_token_item(&token);
1341 if (test_type_token(type, token, EVENT_OP, (char *)"{")) 1453 if (test_type_token(type, token, EVENT_OP, "{"))
1342 break; 1454 break;
1343 1455
1344 arg = malloc_or_die(sizeof(*arg)); 1456 arg = malloc_or_die(sizeof(*arg));
1345 1457
1346 free_token(token); 1458 free_token(token);
1347 type = process_arg(event, arg, &token); 1459 type = process_arg(event, arg, &token);
1348 if (test_type_token(type, token, EVENT_DELIM, (char *)",")) 1460 if (test_type_token(type, token, EVENT_DELIM, ","))
1349 goto out_free; 1461 goto out_free;
1350 1462
1351 field = malloc_or_die(sizeof(*field)); 1463 field = malloc_or_die(sizeof(*field));
@@ -1356,7 +1468,7 @@ process_fields(struct event *event, struct print_flag_sym **list, char **tok)
1356 1468
1357 free_token(token); 1469 free_token(token);
1358 type = process_arg(event, arg, &token); 1470 type = process_arg(event, arg, &token);
1359 if (test_type_token(type, token, EVENT_OP, (char *)"}")) 1471 if (test_type_token(type, token, EVENT_OP, "}"))
1360 goto out_free; 1472 goto out_free;
1361 1473
1362 value = arg_eval(arg); 1474 value = arg_eval(arg);
@@ -1391,13 +1503,13 @@ process_flags(struct event *event, struct print_arg *arg, char **tok)
1391 memset(arg, 0, sizeof(*arg)); 1503 memset(arg, 0, sizeof(*arg));
1392 arg->type = PRINT_FLAGS; 1504 arg->type = PRINT_FLAGS;
1393 1505
1394 if (read_expected_item(EVENT_DELIM, (char *)"(") < 0) 1506 if (read_expected_item(EVENT_DELIM, "(") < 0)
1395 return EVENT_ERROR; 1507 return EVENT_ERROR;
1396 1508
1397 field = malloc_or_die(sizeof(*field)); 1509 field = malloc_or_die(sizeof(*field));
1398 1510
1399 type = process_arg(event, field, &token); 1511 type = process_arg(event, field, &token);
1400 if (test_type_token(type, token, EVENT_DELIM, (char *)",")) 1512 if (test_type_token(type, token, EVENT_DELIM, ","))
1401 goto out_free; 1513 goto out_free;
1402 1514
1403 arg->flags.field = field; 1515 arg->flags.field = field;
@@ -1408,11 +1520,11 @@ process_flags(struct event *event, struct print_arg *arg, char **tok)
1408 type = read_token_item(&token); 1520 type = read_token_item(&token);
1409 } 1521 }
1410 1522
1411 if (test_type_token(type, token, EVENT_DELIM, (char *)",")) 1523 if (test_type_token(type, token, EVENT_DELIM, ","))
1412 goto out_free; 1524 goto out_free;
1413 1525
1414 type = process_fields(event, &arg->flags.flags, &token); 1526 type = process_fields(event, &arg->flags.flags, &token);
1415 if (test_type_token(type, token, EVENT_DELIM, (char *)")")) 1527 if (test_type_token(type, token, EVENT_DELIM, ")"))
1416 goto out_free; 1528 goto out_free;
1417 1529
1418 free_token(token); 1530 free_token(token);
@@ -1434,19 +1546,19 @@ process_symbols(struct event *event, struct print_arg *arg, char **tok)
1434 memset(arg, 0, sizeof(*arg)); 1546 memset(arg, 0, sizeof(*arg));
1435 arg->type = PRINT_SYMBOL; 1547 arg->type = PRINT_SYMBOL;
1436 1548
1437 if (read_expected_item(EVENT_DELIM, (char *)"(") < 0) 1549 if (read_expected_item(EVENT_DELIM, "(") < 0)
1438 return EVENT_ERROR; 1550 return EVENT_ERROR;
1439 1551
1440 field = malloc_or_die(sizeof(*field)); 1552 field = malloc_or_die(sizeof(*field));
1441 1553
1442 type = process_arg(event, field, &token); 1554 type = process_arg(event, field, &token);
1443 if (test_type_token(type, token, EVENT_DELIM, (char *)",")) 1555 if (test_type_token(type, token, EVENT_DELIM, ","))
1444 goto out_free; 1556 goto out_free;
1445 1557
1446 arg->symbol.field = field; 1558 arg->symbol.field = field;
1447 1559
1448 type = process_fields(event, &arg->symbol.symbols, &token); 1560 type = process_fields(event, &arg->symbol.symbols, &token);
1449 if (test_type_token(type, token, EVENT_DELIM, (char *)")")) 1561 if (test_type_token(type, token, EVENT_DELIM, ")"))
1450 goto out_free; 1562 goto out_free;
1451 1563
1452 free_token(token); 1564 free_token(token);
@@ -1463,7 +1575,6 @@ process_paren(struct event *event, struct print_arg *arg, char **tok)
1463{ 1575{
1464 struct print_arg *item_arg; 1576 struct print_arg *item_arg;
1465 enum event_type type; 1577 enum event_type type;
1466 int ptr_cast = 0;
1467 char *token; 1578 char *token;
1468 1579
1469 type = process_arg(event, arg, &token); 1580 type = process_arg(event, arg, &token);
@@ -1471,28 +1582,13 @@ process_paren(struct event *event, struct print_arg *arg, char **tok)
1471 if (type == EVENT_ERROR) 1582 if (type == EVENT_ERROR)
1472 return EVENT_ERROR; 1583 return EVENT_ERROR;
1473 1584
1474 if (type == EVENT_OP) { 1585 if (type == EVENT_OP)
1475 /* handle the ptr casts */ 1586 type = process_op(event, arg, &token);
1476 if (!strcmp(token, "*")) {
1477 /*
1478 * FIXME: should we zapp whitespaces before ')' ?
1479 * (may require a peek_token_item())
1480 */
1481 if (__peek_char() == ')') {
1482 ptr_cast = 1;
1483 free_token(token);
1484 type = read_token_item(&token);
1485 }
1486 }
1487 if (!ptr_cast) {
1488 type = process_op(event, arg, &token);
1489 1587
1490 if (type == EVENT_ERROR) 1588 if (type == EVENT_ERROR)
1491 return EVENT_ERROR; 1589 return EVENT_ERROR;
1492 }
1493 }
1494 1590
1495 if (test_type_token(type, token, EVENT_DELIM, (char *)")")) { 1591 if (test_type_token(type, token, EVENT_DELIM, ")")) {
1496 free_token(token); 1592 free_token(token);
1497 return EVENT_ERROR; 1593 return EVENT_ERROR;
1498 } 1594 }
@@ -1516,13 +1612,6 @@ process_paren(struct event *event, struct print_arg *arg, char **tok)
1516 item_arg = malloc_or_die(sizeof(*item_arg)); 1612 item_arg = malloc_or_die(sizeof(*item_arg));
1517 1613
1518 arg->type = PRINT_TYPE; 1614 arg->type = PRINT_TYPE;
1519 if (ptr_cast) {
1520 char *old = arg->atom.atom;
1521
1522 arg->atom.atom = malloc_or_die(strlen(old + 3));
1523 sprintf(arg->atom.atom, "%s *", old);
1524 free(old);
1525 }
1526 arg->typecast.type = arg->atom.atom; 1615 arg->typecast.type = arg->atom.atom;
1527 arg->typecast.item = item_arg; 1616 arg->typecast.item = item_arg;
1528 type = process_arg_token(event, item_arg, &token, type); 1617 type = process_arg_token(event, item_arg, &token, type);
@@ -1540,7 +1629,7 @@ process_str(struct event *event __unused, struct print_arg *arg, char **tok)
1540 enum event_type type; 1629 enum event_type type;
1541 char *token; 1630 char *token;
1542 1631
1543 if (read_expected(EVENT_DELIM, (char *)"(") < 0) 1632 if (read_expected(EVENT_DELIM, "(") < 0)
1544 return EVENT_ERROR; 1633 return EVENT_ERROR;
1545 1634
1546 if (read_expect_type(EVENT_ITEM, &token) < 0) 1635 if (read_expect_type(EVENT_ITEM, &token) < 0)
@@ -1550,7 +1639,7 @@ process_str(struct event *event __unused, struct print_arg *arg, char **tok)
1550 arg->string.string = token; 1639 arg->string.string = token;
1551 arg->string.offset = -1; 1640 arg->string.offset = -1;
1552 1641
1553 if (read_expected(EVENT_DELIM, (char *)")") < 0) 1642 if (read_expected(EVENT_DELIM, ")") < 0)
1554 return EVENT_ERROR; 1643 return EVENT_ERROR;
1555 1644
1556 type = read_token(&token); 1645 type = read_token(&token);
@@ -1637,12 +1726,18 @@ process_arg_token(struct event *event, struct print_arg *arg,
1637 1726
1638static int event_read_print_args(struct event *event, struct print_arg **list) 1727static int event_read_print_args(struct event *event, struct print_arg **list)
1639{ 1728{
1640 enum event_type type; 1729 enum event_type type = EVENT_ERROR;
1641 struct print_arg *arg; 1730 struct print_arg *arg;
1642 char *token; 1731 char *token;
1643 int args = 0; 1732 int args = 0;
1644 1733
1645 do { 1734 do {
1735 if (type == EVENT_NEWLINE) {
1736 free_token(token);
1737 type = read_token_item(&token);
1738 continue;
1739 }
1740
1646 arg = malloc_or_die(sizeof(*arg)); 1741 arg = malloc_or_die(sizeof(*arg));
1647 memset(arg, 0, sizeof(*arg)); 1742 memset(arg, 0, sizeof(*arg));
1648 1743
@@ -1683,18 +1778,19 @@ static int event_read_print(struct event *event)
1683 char *token; 1778 char *token;
1684 int ret; 1779 int ret;
1685 1780
1686 if (read_expected_item(EVENT_ITEM, (char *)"print") < 0) 1781 if (read_expected_item(EVENT_ITEM, "print") < 0)
1687 return -1; 1782 return -1;
1688 1783
1689 if (read_expected(EVENT_ITEM, (char *)"fmt") < 0) 1784 if (read_expected(EVENT_ITEM, "fmt") < 0)
1690 return -1; 1785 return -1;
1691 1786
1692 if (read_expected(EVENT_OP, (char *)":") < 0) 1787 if (read_expected(EVENT_OP, ":") < 0)
1693 return -1; 1788 return -1;
1694 1789
1695 if (read_expect_type(EVENT_DQUOTE, &token) < 0) 1790 if (read_expect_type(EVENT_DQUOTE, &token) < 0)
1696 goto fail; 1791 goto fail;
1697 1792
1793 concat:
1698 event->print_fmt.format = token; 1794 event->print_fmt.format = token;
1699 event->print_fmt.args = NULL; 1795 event->print_fmt.args = NULL;
1700 1796
@@ -1704,7 +1800,22 @@ static int event_read_print(struct event *event)
1704 if (type == EVENT_NONE) 1800 if (type == EVENT_NONE)
1705 return 0; 1801 return 0;
1706 1802
1707 if (test_type_token(type, token, EVENT_DELIM, (char *)",")) 1803 /* Handle concatination of print lines */
1804 if (type == EVENT_DQUOTE) {
1805 char *cat;
1806
1807 cat = malloc_or_die(strlen(event->print_fmt.format) +
1808 strlen(token) + 1);
1809 strcpy(cat, event->print_fmt.format);
1810 strcat(cat, token);
1811 free_token(token);
1812 free_token(event->print_fmt.format);
1813 event->print_fmt.format = NULL;
1814 token = cat;
1815 goto concat;
1816 }
1817
1818 if (test_type_token(type, token, EVENT_DELIM, ","))
1708 goto fail; 1819 goto fail;
1709 1820
1710 free_token(token); 1821 free_token(token);
@@ -1713,7 +1824,7 @@ static int event_read_print(struct event *event)
1713 if (ret < 0) 1824 if (ret < 0)
1714 return -1; 1825 return -1;
1715 1826
1716 return 0; 1827 return ret;
1717 1828
1718 fail: 1829 fail:
1719 free_token(token); 1830 free_token(token);
@@ -1822,37 +1933,67 @@ static int get_common_info(const char *type, int *offset, int *size)
1822 return 0; 1933 return 0;
1823} 1934}
1824 1935
1825int trace_parse_common_type(void *data) 1936static int __parse_common(void *data, int *size, int *offset,
1937 const char *name)
1826{ 1938{
1827 static int type_offset;
1828 static int type_size;
1829 int ret; 1939 int ret;
1830 1940
1831 if (!type_size) { 1941 if (!*size) {
1832 ret = get_common_info("common_type", 1942 ret = get_common_info(name, offset, size);
1833 &type_offset,
1834 &type_size);
1835 if (ret < 0) 1943 if (ret < 0)
1836 return ret; 1944 return ret;
1837 } 1945 }
1838 return read_size(data + type_offset, type_size); 1946 return read_size(data + *offset, *size);
1947}
1948
1949int trace_parse_common_type(void *data)
1950{
1951 static int type_offset;
1952 static int type_size;
1953
1954 return __parse_common(data, &type_size, &type_offset,
1955 "common_type");
1839} 1956}
1840 1957
1841static int parse_common_pid(void *data) 1958static int parse_common_pid(void *data)
1842{ 1959{
1843 static int pid_offset; 1960 static int pid_offset;
1844 static int pid_size; 1961 static int pid_size;
1962
1963 return __parse_common(data, &pid_size, &pid_offset,
1964 "common_pid");
1965}
1966
1967static int parse_common_pc(void *data)
1968{
1969 static int pc_offset;
1970 static int pc_size;
1971
1972 return __parse_common(data, &pc_size, &pc_offset,
1973 "common_preempt_count");
1974}
1975
1976static int parse_common_flags(void *data)
1977{
1978 static int flags_offset;
1979 static int flags_size;
1980
1981 return __parse_common(data, &flags_size, &flags_offset,
1982 "common_flags");
1983}
1984
1985static int parse_common_lock_depth(void *data)
1986{
1987 static int ld_offset;
1988 static int ld_size;
1845 int ret; 1989 int ret;
1846 1990
1847 if (!pid_size) { 1991 ret = __parse_common(data, &ld_size, &ld_offset,
1848 ret = get_common_info("common_pid", 1992 "common_lock_depth");
1849 &pid_offset, 1993 if (ret < 0)
1850 &pid_size); 1994 return -1;
1851 if (ret < 0)
1852 return ret;
1853 }
1854 1995
1855 return read_size(data + pid_offset, pid_size); 1996 return ret;
1856} 1997}
1857 1998
1858struct event *trace_find_event(int id) 1999struct event *trace_find_event(int id)
@@ -1871,6 +2012,7 @@ static unsigned long long eval_num_arg(void *data, int size,
1871{ 2012{
1872 unsigned long long val = 0; 2013 unsigned long long val = 0;
1873 unsigned long long left, right; 2014 unsigned long long left, right;
2015 struct print_arg *larg;
1874 2016
1875 switch (arg->type) { 2017 switch (arg->type) {
1876 case PRINT_NULL: 2018 case PRINT_NULL:
@@ -1897,6 +2039,26 @@ static unsigned long long eval_num_arg(void *data, int size,
1897 return 0; 2039 return 0;
1898 break; 2040 break;
1899 case PRINT_OP: 2041 case PRINT_OP:
2042 if (strcmp(arg->op.op, "[") == 0) {
2043 /*
2044 * Arrays are special, since we don't want
2045 * to read the arg as is.
2046 */
2047 if (arg->op.left->type != PRINT_FIELD)
2048 goto default_op; /* oops, all bets off */
2049 larg = arg->op.left;
2050 if (!larg->field.field) {
2051 larg->field.field =
2052 find_any_field(event, larg->field.name);
2053 if (!larg->field.field)
2054 die("field %s not found", larg->field.name);
2055 }
2056 right = eval_num_arg(data, size, event, arg->op.right);
2057 val = read_size(data + larg->field.field->offset +
2058 right * long_size, long_size);
2059 break;
2060 }
2061 default_op:
1900 left = eval_num_arg(data, size, event, arg->op.left); 2062 left = eval_num_arg(data, size, event, arg->op.left);
1901 right = eval_num_arg(data, size, event, arg->op.right); 2063 right = eval_num_arg(data, size, event, arg->op.right);
1902 switch (arg->op.op[0]) { 2064 switch (arg->op.op[0]) {
@@ -1947,6 +2109,12 @@ static unsigned long long eval_num_arg(void *data, int size,
1947 die("unknown op '%s'", arg->op.op); 2109 die("unknown op '%s'", arg->op.op);
1948 val = left == right; 2110 val = left == right;
1949 break; 2111 break;
2112 case '-':
2113 val = left - right;
2114 break;
2115 case '+':
2116 val = left + right;
2117 break;
1950 default: 2118 default:
1951 die("unknown op '%s'", arg->op.op); 2119 die("unknown op '%s'", arg->op.op);
1952 } 2120 }
@@ -2145,8 +2313,9 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc
2145 case 'u': 2313 case 'u':
2146 case 'x': 2314 case 'x':
2147 case 'i': 2315 case 'i':
2148 bptr = (void *)(((unsigned long)bptr + (long_size - 1)) & 2316 /* the pointers are always 4 bytes aligned */
2149 ~(long_size - 1)); 2317 bptr = (void *)(((unsigned long)bptr + 3) &
2318 ~3);
2150 switch (ls) { 2319 switch (ls) {
2151 case 0: 2320 case 0:
2152 case 1: 2321 case 1:
@@ -2270,7 +2439,27 @@ static void pretty_print(void *data, int size, struct event *event)
2270 2439
2271 for (; *ptr; ptr++) { 2440 for (; *ptr; ptr++) {
2272 ls = 0; 2441 ls = 0;
2273 if (*ptr == '%') { 2442 if (*ptr == '\\') {
2443 ptr++;
2444 switch (*ptr) {
2445 case 'n':
2446 printf("\n");
2447 break;
2448 case 't':
2449 printf("\t");
2450 break;
2451 case 'r':
2452 printf("\r");
2453 break;
2454 case '\\':
2455 printf("\\");
2456 break;
2457 default:
2458 printf("%c", *ptr);
2459 break;
2460 }
2461
2462 } else if (*ptr == '%') {
2274 saveptr = ptr; 2463 saveptr = ptr;
2275 show_func = 0; 2464 show_func = 0;
2276 cont_process: 2465 cont_process:
@@ -2377,6 +2566,41 @@ static inline int log10_cpu(int nb)
2377 return 1; 2566 return 1;
2378} 2567}
2379 2568
2569static void print_lat_fmt(void *data, int size __unused)
2570{
2571 unsigned int lat_flags;
2572 unsigned int pc;
2573 int lock_depth;
2574 int hardirq;
2575 int softirq;
2576
2577 lat_flags = parse_common_flags(data);
2578 pc = parse_common_pc(data);
2579 lock_depth = parse_common_lock_depth(data);
2580
2581 hardirq = lat_flags & TRACE_FLAG_HARDIRQ;
2582 softirq = lat_flags & TRACE_FLAG_SOFTIRQ;
2583
2584 printf("%c%c%c",
2585 (lat_flags & TRACE_FLAG_IRQS_OFF) ? 'd' :
2586 (lat_flags & TRACE_FLAG_IRQS_NOSUPPORT) ?
2587 'X' : '.',
2588 (lat_flags & TRACE_FLAG_NEED_RESCHED) ?
2589 'N' : '.',
2590 (hardirq && softirq) ? 'H' :
2591 hardirq ? 'h' : softirq ? 's' : '.');
2592
2593 if (pc)
2594 printf("%x", pc);
2595 else
2596 printf(".");
2597
2598 if (lock_depth < 0)
2599 printf(".");
2600 else
2601 printf("%d", lock_depth);
2602}
2603
2380/* taken from Linux, written by Frederic Weisbecker */ 2604/* taken from Linux, written by Frederic Weisbecker */
2381static void print_graph_cpu(int cpu) 2605static void print_graph_cpu(int cpu)
2382{ 2606{
@@ -2620,6 +2844,11 @@ pretty_print_func_ent(void *data, int size, struct event *event,
2620 2844
2621 printf(" | "); 2845 printf(" | ");
2622 2846
2847 if (latency_format) {
2848 print_lat_fmt(data, size);
2849 printf(" | ");
2850 }
2851
2623 field = find_field(event, "func"); 2852 field = find_field(event, "func");
2624 if (!field) 2853 if (!field)
2625 die("function entry does not have func field"); 2854 die("function entry does not have func field");
@@ -2663,6 +2892,11 @@ pretty_print_func_ret(void *data, int size __unused, struct event *event,
2663 2892
2664 printf(" | "); 2893 printf(" | ");
2665 2894
2895 if (latency_format) {
2896 print_lat_fmt(data, size);
2897 printf(" | ");
2898 }
2899
2666 field = find_field(event, "rettime"); 2900 field = find_field(event, "rettime");
2667 if (!field) 2901 if (!field)
2668 die("can't find rettime in return graph"); 2902 die("can't find rettime in return graph");
@@ -2724,7 +2958,7 @@ void print_event(int cpu, void *data, int size, unsigned long long nsecs,
2724 2958
2725 event = trace_find_event(type); 2959 event = trace_find_event(type);
2726 if (!event) { 2960 if (!event) {
2727 printf("ug! no event found for type %d\n", type); 2961 warning("ug! no event found for type %d", type);
2728 return; 2962 return;
2729 } 2963 }
2730 2964
@@ -2734,9 +2968,20 @@ void print_event(int cpu, void *data, int size, unsigned long long nsecs,
2734 return pretty_print_func_graph(data, size, event, cpu, 2968 return pretty_print_func_graph(data, size, event, cpu,
2735 pid, comm, secs, usecs); 2969 pid, comm, secs, usecs);
2736 2970
2737 printf("%16s-%-5d [%03d] %5lu.%09Lu: %s: ", 2971 if (latency_format) {
2738 comm, pid, cpu, 2972 printf("%8.8s-%-5d %3d",
2739 secs, nsecs, event->name); 2973 comm, pid, cpu);
2974 print_lat_fmt(data, size);
2975 } else
2976 printf("%16s-%-5d [%03d]", comm, pid, cpu);
2977
2978 printf(" %5lu.%06lu: %s: ", secs, usecs, event->name);
2979
2980 if (event->flags & EVENT_FL_FAILED) {
2981 printf("EVENT '%s' FAILED TO PARSE\n",
2982 event->name);
2983 return;
2984 }
2740 2985
2741 pretty_print(data, size, event); 2986 pretty_print(data, size, event);
2742 printf("\n"); 2987 printf("\n");
@@ -2807,46 +3052,71 @@ static void print_args(struct print_arg *args)
2807 } 3052 }
2808} 3053}
2809 3054
2810static void parse_header_field(char *type, 3055static void parse_header_field(const char *field,
2811 int *offset, int *size) 3056 int *offset, int *size)
2812{ 3057{
2813 char *token; 3058 char *token;
3059 int type;
2814 3060
2815 if (read_expected(EVENT_ITEM, (char *)"field") < 0) 3061 if (read_expected(EVENT_ITEM, "field") < 0)
2816 return; 3062 return;
2817 if (read_expected(EVENT_OP, (char *)":") < 0) 3063 if (read_expected(EVENT_OP, ":") < 0)
2818 return; 3064 return;
3065
2819 /* type */ 3066 /* type */
2820 if (read_expect_type(EVENT_ITEM, &token) < 0) 3067 if (read_expect_type(EVENT_ITEM, &token) < 0)
2821 return; 3068 goto fail;
2822 free_token(token); 3069 free_token(token);
2823 3070
2824 if (read_expected(EVENT_ITEM, type) < 0) 3071 if (read_expected(EVENT_ITEM, field) < 0)
2825 return; 3072 return;
2826 if (read_expected(EVENT_OP, (char *)";") < 0) 3073 if (read_expected(EVENT_OP, ";") < 0)
2827 return; 3074 return;
2828 if (read_expected(EVENT_ITEM, (char *)"offset") < 0) 3075 if (read_expected(EVENT_ITEM, "offset") < 0)
2829 return; 3076 return;
2830 if (read_expected(EVENT_OP, (char *)":") < 0) 3077 if (read_expected(EVENT_OP, ":") < 0)
2831 return; 3078 return;
2832 if (read_expect_type(EVENT_ITEM, &token) < 0) 3079 if (read_expect_type(EVENT_ITEM, &token) < 0)
2833 return; 3080 goto fail;
2834 *offset = atoi(token); 3081 *offset = atoi(token);
2835 free_token(token); 3082 free_token(token);
2836 if (read_expected(EVENT_OP, (char *)";") < 0) 3083 if (read_expected(EVENT_OP, ";") < 0)
2837 return; 3084 return;
2838 if (read_expected(EVENT_ITEM, (char *)"size") < 0) 3085 if (read_expected(EVENT_ITEM, "size") < 0)
2839 return; 3086 return;
2840 if (read_expected(EVENT_OP, (char *)":") < 0) 3087 if (read_expected(EVENT_OP, ":") < 0)
2841 return; 3088 return;
2842 if (read_expect_type(EVENT_ITEM, &token) < 0) 3089 if (read_expect_type(EVENT_ITEM, &token) < 0)
2843 return; 3090 goto fail;
2844 *size = atoi(token); 3091 *size = atoi(token);
2845 free_token(token); 3092 free_token(token);
2846 if (read_expected(EVENT_OP, (char *)";") < 0) 3093 if (read_expected(EVENT_OP, ";") < 0)
2847 return;
2848 if (read_expect_type(EVENT_NEWLINE, &token) < 0)
2849 return; 3094 return;
3095 type = read_token(&token);
3096 if (type != EVENT_NEWLINE) {
3097 /* newer versions of the kernel have a "signed" type */
3098 if (type != EVENT_ITEM)
3099 goto fail;
3100
3101 if (strcmp(token, "signed") != 0)
3102 goto fail;
3103
3104 free_token(token);
3105
3106 if (read_expected(EVENT_OP, ":") < 0)
3107 return;
3108
3109 if (read_expect_type(EVENT_ITEM, &token))
3110 goto fail;
3111
3112 free_token(token);
3113 if (read_expected(EVENT_OP, ";") < 0)
3114 return;
3115
3116 if (read_expect_type(EVENT_NEWLINE, &token))
3117 goto fail;
3118 }
3119 fail:
2850 free_token(token); 3120 free_token(token);
2851} 3121}
2852 3122
@@ -2854,11 +3124,11 @@ int parse_header_page(char *buf, unsigned long size)
2854{ 3124{
2855 init_input_buf(buf, size); 3125 init_input_buf(buf, size);
2856 3126
2857 parse_header_field((char *)"timestamp", &header_page_ts_offset, 3127 parse_header_field("timestamp", &header_page_ts_offset,
2858 &header_page_ts_size); 3128 &header_page_ts_size);
2859 parse_header_field((char *)"commit", &header_page_size_offset, 3129 parse_header_field("commit", &header_page_size_offset,
2860 &header_page_size_size); 3130 &header_page_size_size);
2861 parse_header_field((char *)"data", &header_page_data_offset, 3131 parse_header_field("data", &header_page_data_offset,
2862 &header_page_data_size); 3132 &header_page_data_size);
2863 3133
2864 return 0; 3134 return 0;
@@ -2909,6 +3179,9 @@ int parse_ftrace_file(char *buf, unsigned long size)
2909 if (ret < 0) 3179 if (ret < 0)
2910 die("failed to read ftrace event print fmt"); 3180 die("failed to read ftrace event print fmt");
2911 3181
3182 /* New ftrace handles args */
3183 if (ret > 0)
3184 return 0;
2912 /* 3185 /*
2913 * The arguments for ftrace files are parsed by the fields. 3186 * The arguments for ftrace files are parsed by the fields.
2914 * Set up the fields as their arguments. 3187 * Set up the fields as their arguments.
@@ -2926,7 +3199,7 @@ int parse_ftrace_file(char *buf, unsigned long size)
2926 return 0; 3199 return 0;
2927} 3200}
2928 3201
2929int parse_event_file(char *buf, unsigned long size, char *system__unused __unused) 3202int parse_event_file(char *buf, unsigned long size, char *sys)
2930{ 3203{
2931 struct event *event; 3204 struct event *event;
2932 int ret; 3205 int ret;
@@ -2946,12 +3219,18 @@ int parse_event_file(char *buf, unsigned long size, char *system__unused __unuse
2946 die("failed to read event id"); 3219 die("failed to read event id");
2947 3220
2948 ret = event_read_format(event); 3221 ret = event_read_format(event);
2949 if (ret < 0) 3222 if (ret < 0) {
2950 die("failed to read event format"); 3223 warning("failed to read event format for %s", event->name);
3224 goto event_failed;
3225 }
2951 3226
2952 ret = event_read_print(event); 3227 ret = event_read_print(event);
2953 if (ret < 0) 3228 if (ret < 0) {
2954 die("failed to read event print fmt"); 3229 warning("failed to read event print fmt for %s", event->name);
3230 goto event_failed;
3231 }
3232
3233 event->system = strdup(sys);
2955 3234
2956#define PRINT_ARGS 0 3235#define PRINT_ARGS 0
2957 if (PRINT_ARGS && event->print_fmt.args) 3236 if (PRINT_ARGS && event->print_fmt.args)
@@ -2959,6 +3238,12 @@ int parse_event_file(char *buf, unsigned long size, char *system__unused __unuse
2959 3238
2960 add_event(event); 3239 add_event(event);
2961 return 0; 3240 return 0;
3241
3242 event_failed:
3243 event->flags |= EVENT_FL_FAILED;
3244 /* still add it even if it failed */
3245 add_event(event);
3246 return -1;
2962} 3247}
2963 3248
2964void parse_set_info(int nr_cpus, int long_sz) 3249void parse_set_info(int nr_cpus, int long_sz)
diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c
index 1b5c847d2c2..44292e06cca 100644
--- a/tools/perf/util/trace-event-read.c
+++ b/tools/perf/util/trace-event-read.c
@@ -458,9 +458,8 @@ struct record *trace_read_data(int cpu)
458 return data; 458 return data;
459} 459}
460 460
461void trace_report(void) 461void trace_report(int fd)
462{ 462{
463 const char *input_file = "trace.info";
464 char buf[BUFSIZ]; 463 char buf[BUFSIZ];
465 char test[] = { 23, 8, 68 }; 464 char test[] = { 23, 8, 68 };
466 char *version; 465 char *version;
@@ -468,9 +467,7 @@ void trace_report(void)
468 int show_funcs = 0; 467 int show_funcs = 0;
469 int show_printk = 0; 468 int show_printk = 0;
470 469
471 input_fd = open(input_file, O_RDONLY); 470 input_fd = fd;
472 if (input_fd < 0)
473 die("opening '%s'\n", input_file);
474 471
475 read_or_die(buf, 3); 472 read_or_die(buf, 3);
476 if (memcmp(buf, test, 3) != 0) 473 if (memcmp(buf, test, 3) != 0)
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index 693f815c942..f6637c2fa1f 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -1,5 +1,5 @@
1#ifndef _TRACE_EVENTS_H 1#ifndef __PERF_TRACE_EVENTS_H
2#define _TRACE_EVENTS_H 2#define __PERF_TRACE_EVENTS_H
3 3
4#include "parse-events.h" 4#include "parse-events.h"
5 5
@@ -26,6 +26,9 @@ enum {
26enum format_flags { 26enum format_flags {
27 FIELD_IS_ARRAY = 1, 27 FIELD_IS_ARRAY = 1,
28 FIELD_IS_POINTER = 2, 28 FIELD_IS_POINTER = 2,
29 FIELD_IS_SIGNED = 4,
30 FIELD_IS_STRING = 8,
31 FIELD_IS_DYNAMIC = 16,
29}; 32};
30 33
31struct format_field { 34struct format_field {
@@ -132,15 +135,18 @@ struct event {
132 int flags; 135 int flags;
133 struct format format; 136 struct format format;
134 struct print_fmt print_fmt; 137 struct print_fmt print_fmt;
138 char *system;
135}; 139};
136 140
137enum { 141enum {
138 EVENT_FL_ISFTRACE = 1, 142 EVENT_FL_ISFTRACE = 0x01,
139 EVENT_FL_ISPRINT = 2, 143 EVENT_FL_ISPRINT = 0x02,
140 EVENT_FL_ISBPRINT = 4, 144 EVENT_FL_ISBPRINT = 0x04,
141 EVENT_FL_ISFUNC = 8, 145 EVENT_FL_ISFUNC = 0x08,
142 EVENT_FL_ISFUNCENT = 16, 146 EVENT_FL_ISFUNCENT = 0x10,
143 EVENT_FL_ISFUNCRET = 32, 147 EVENT_FL_ISFUNCRET = 0x20,
148
149 EVENT_FL_FAILED = 0x80000000
144}; 150};
145 151
146struct record { 152struct record {
@@ -154,7 +160,7 @@ struct record *trace_read_data(int cpu);
154 160
155void parse_set_info(int nr_cpus, int long_sz); 161void parse_set_info(int nr_cpus, int long_sz);
156 162
157void trace_report(void); 163void trace_report(int fd);
158 164
159void *malloc_or_die(unsigned int size); 165void *malloc_or_die(unsigned int size);
160 166
@@ -166,7 +172,7 @@ void print_funcs(void);
166void print_printk(void); 172void print_printk(void);
167 173
168int parse_ftrace_file(char *buf, unsigned long size); 174int parse_ftrace_file(char *buf, unsigned long size);
169int parse_event_file(char *buf, unsigned long size, char *system); 175int parse_event_file(char *buf, unsigned long size, char *sys);
170void print_event(int cpu, void *data, int size, unsigned long long nsecs, 176void print_event(int cpu, void *data, int size, unsigned long long nsecs,
171 char *comm); 177 char *comm);
172 178
@@ -233,6 +239,8 @@ extern int header_page_size_size;
233extern int header_page_data_offset; 239extern int header_page_data_offset;
234extern int header_page_data_size; 240extern int header_page_data_size;
235 241
242extern int latency_format;
243
236int parse_header_page(char *buf, unsigned long size); 244int parse_header_page(char *buf, unsigned long size);
237int trace_parse_common_type(void *data); 245int trace_parse_common_type(void *data);
238struct event *trace_find_event(int id); 246struct event *trace_find_event(int id);
@@ -240,6 +248,15 @@ unsigned long long
240raw_field_value(struct event *event, const char *name, void *data); 248raw_field_value(struct event *event, const char *name, void *data);
241void *raw_field_ptr(struct event *event, const char *name, void *data); 249void *raw_field_ptr(struct event *event, const char *name, void *data);
242 250
243void read_tracing_data(struct perf_event_attr *pattrs, int nb_events); 251void read_tracing_data(int fd, struct perf_event_attr *pattrs, int nb_events);
252
253/* taken from kernel/trace/trace.h */
254enum trace_flag_type {
255 TRACE_FLAG_IRQS_OFF = 0x01,
256 TRACE_FLAG_IRQS_NOSUPPORT = 0x02,
257 TRACE_FLAG_NEED_RESCHED = 0x04,
258 TRACE_FLAG_HARDIRQ = 0x08,
259 TRACE_FLAG_SOFTIRQ = 0x10,
260};
244 261
245#endif /* _TRACE_EVENTS_H */ 262#endif /* __PERF_TRACE_EVENTS_H */
diff --git a/tools/perf/util/types.h b/tools/perf/util/types.h
index 5e75f900594..7d6b8331f89 100644
--- a/tools/perf/util/types.h
+++ b/tools/perf/util/types.h
@@ -1,5 +1,5 @@
1#ifndef _PERF_TYPES_H 1#ifndef __PERF_TYPES_H
2#define _PERF_TYPES_H 2#define __PERF_TYPES_H
3 3
4/* 4/*
5 * We define u64 as unsigned long long for every architecture 5 * We define u64 as unsigned long long for every architecture
@@ -14,4 +14,4 @@ typedef signed short s16;
14typedef unsigned char u8; 14typedef unsigned char u8;
15typedef signed char s8; 15typedef signed char s8;
16 16
17#endif /* _PERF_TYPES_H */ 17#endif /* __PERF_TYPES_H */
diff --git a/tools/perf/util/values.h b/tools/perf/util/values.h
index cadf8cf2a59..2fa967e1a88 100644
--- a/tools/perf/util/values.h
+++ b/tools/perf/util/values.h
@@ -1,5 +1,5 @@
1#ifndef _PERF_VALUES_H 1#ifndef __PERF_VALUES_H
2#define _PERF_VALUES_H 2#define __PERF_VALUES_H
3 3
4#include "types.h" 4#include "types.h"
5 5
@@ -24,4 +24,4 @@ void perf_read_values_add_value(struct perf_read_values *values,
24void perf_read_values_display(FILE *fp, struct perf_read_values *values, 24void perf_read_values_display(FILE *fp, struct perf_read_values *values,
25 int raw); 25 int raw);
26 26
27#endif /* _PERF_VALUES_H */ 27#endif /* __PERF_VALUES_H */