aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/cpu/perf_counter.c253
-rw-r--r--include/linux/perf_counter.h15
-rw-r--r--init/Kconfig2
-rw-r--r--kernel/fork.c9
-rw-r--r--kernel/perf_counter.c185
-rw-r--r--tools/perf/Documentation/perf-report.txt15
-rw-r--r--tools/perf/Makefile2
-rw-r--r--tools/perf/builtin-annotate.c24
-rw-r--r--tools/perf/builtin-record.c13
-rw-r--r--tools/perf/builtin-report.c255
-rw-r--r--tools/perf/builtin-stat.c3
-rw-r--r--tools/perf/builtin-top.c6
-rw-r--r--tools/perf/perf.c77
-rw-r--r--tools/perf/perf.h8
-rw-r--r--tools/perf/util/cache.h1
-rw-r--r--tools/perf/util/header.h2
-rw-r--r--tools/perf/util/include/linux/kernel.h8
-rw-r--r--tools/perf/util/parse-events.c182
-rw-r--r--tools/perf/util/parse-events.h5
-rw-r--r--tools/perf/util/string.h3
-rw-r--r--tools/perf/util/strlist.c20
-rw-r--r--tools/perf/util/strlist.h11
-rw-r--r--tools/perf/util/symbol.c145
-rw-r--r--tools/perf/util/symbol.h1
-rw-r--r--tools/perf/util/util.h2
25 files changed, 948 insertions, 299 deletions
diff --git a/arch/x86/kernel/cpu/perf_counter.c b/arch/x86/kernel/cpu/perf_counter.c
index 36c3dc7b8991..a7aa8f900954 100644
--- a/arch/x86/kernel/cpu/perf_counter.c
+++ b/arch/x86/kernel/cpu/perf_counter.c
@@ -66,6 +66,52 @@ static DEFINE_PER_CPU(struct cpu_hw_counters, cpu_hw_counters) = {
66}; 66};
67 67
68/* 68/*
69 * Not sure about some of these
70 */
71static const u64 p6_perfmon_event_map[] =
72{
73 [PERF_COUNT_HW_CPU_CYCLES] = 0x0079,
74 [PERF_COUNT_HW_INSTRUCTIONS] = 0x00c0,
75 [PERF_COUNT_HW_CACHE_REFERENCES] = 0x0000,
76 [PERF_COUNT_HW_CACHE_MISSES] = 0x0000,
77 [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x00c4,
78 [PERF_COUNT_HW_BRANCH_MISSES] = 0x00c5,
79 [PERF_COUNT_HW_BUS_CYCLES] = 0x0062,
80};
81
82static u64 p6_pmu_event_map(int event)
83{
84 return p6_perfmon_event_map[event];
85}
86
87/*
88 * Counter setting that is specified not to count anything.
89 * We use this to effectively disable a counter.
90 *
91 * L2_RQSTS with 0 MESI unit mask.
92 */
93#define P6_NOP_COUNTER 0x0000002EULL
94
95static u64 p6_pmu_raw_event(u64 event)
96{
97#define P6_EVNTSEL_EVENT_MASK 0x000000FFULL
98#define P6_EVNTSEL_UNIT_MASK 0x0000FF00ULL
99#define P6_EVNTSEL_EDGE_MASK 0x00040000ULL
100#define P6_EVNTSEL_INV_MASK 0x00800000ULL
101#define P6_EVNTSEL_COUNTER_MASK 0xFF000000ULL
102
103#define P6_EVNTSEL_MASK \
104 (P6_EVNTSEL_EVENT_MASK | \
105 P6_EVNTSEL_UNIT_MASK | \
106 P6_EVNTSEL_EDGE_MASK | \
107 P6_EVNTSEL_INV_MASK | \
108 P6_EVNTSEL_COUNTER_MASK)
109
110 return event & P6_EVNTSEL_MASK;
111}
112
113
114/*
69 * Intel PerfMon v3. Used on Core2 and later. 115 * Intel PerfMon v3. Used on Core2 and later.
70 */ 116 */
71static const u64 intel_perfmon_event_map[] = 117static const u64 intel_perfmon_event_map[] =
@@ -666,6 +712,7 @@ static int __hw_perf_counter_init(struct perf_counter *counter)
666{ 712{
667 struct perf_counter_attr *attr = &counter->attr; 713 struct perf_counter_attr *attr = &counter->attr;
668 struct hw_perf_counter *hwc = &counter->hw; 714 struct hw_perf_counter *hwc = &counter->hw;
715 u64 config;
669 int err; 716 int err;
670 717
671 if (!x86_pmu_initialized()) 718 if (!x86_pmu_initialized())
@@ -718,14 +765,40 @@ static int __hw_perf_counter_init(struct perf_counter *counter)
718 765
719 if (attr->config >= x86_pmu.max_events) 766 if (attr->config >= x86_pmu.max_events)
720 return -EINVAL; 767 return -EINVAL;
768
721 /* 769 /*
722 * The generic map: 770 * The generic map:
723 */ 771 */
724 hwc->config |= x86_pmu.event_map(attr->config); 772 config = x86_pmu.event_map(attr->config);
773
774 if (config == 0)
775 return -ENOENT;
776
777 if (config == -1LL)
778 return -EINVAL;
779
780 hwc->config |= config;
725 781
726 return 0; 782 return 0;
727} 783}
728 784
785static void p6_pmu_disable_all(void)
786{
787 struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters);
788 u64 val;
789
790 if (!cpuc->enabled)
791 return;
792
793 cpuc->enabled = 0;
794 barrier();
795
796 /* p6 only has one enable register */
797 rdmsrl(MSR_P6_EVNTSEL0, val);
798 val &= ~ARCH_PERFMON_EVENTSEL0_ENABLE;
799 wrmsrl(MSR_P6_EVNTSEL0, val);
800}
801
729static void intel_pmu_disable_all(void) 802static void intel_pmu_disable_all(void)
730{ 803{
731 wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, 0); 804 wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, 0);
@@ -767,6 +840,23 @@ void hw_perf_disable(void)
767 return x86_pmu.disable_all(); 840 return x86_pmu.disable_all();
768} 841}
769 842
843static void p6_pmu_enable_all(void)
844{
845 struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters);
846 unsigned long val;
847
848 if (cpuc->enabled)
849 return;
850
851 cpuc->enabled = 1;
852 barrier();
853
854 /* p6 only has one enable register */
855 rdmsrl(MSR_P6_EVNTSEL0, val);
856 val |= ARCH_PERFMON_EVENTSEL0_ENABLE;
857 wrmsrl(MSR_P6_EVNTSEL0, val);
858}
859
770static void intel_pmu_enable_all(void) 860static void intel_pmu_enable_all(void)
771{ 861{
772 wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, x86_pmu.intel_ctrl); 862 wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, x86_pmu.intel_ctrl);
@@ -784,13 +874,13 @@ static void amd_pmu_enable_all(void)
784 barrier(); 874 barrier();
785 875
786 for (idx = 0; idx < x86_pmu.num_counters; idx++) { 876 for (idx = 0; idx < x86_pmu.num_counters; idx++) {
877 struct perf_counter *counter = cpuc->counters[idx];
787 u64 val; 878 u64 val;
788 879
789 if (!test_bit(idx, cpuc->active_mask)) 880 if (!test_bit(idx, cpuc->active_mask))
790 continue; 881 continue;
791 rdmsrl(MSR_K7_EVNTSEL0 + idx, val); 882
792 if (val & ARCH_PERFMON_EVENTSEL0_ENABLE) 883 val = counter->hw.config;
793 continue;
794 val |= ARCH_PERFMON_EVENTSEL0_ENABLE; 884 val |= ARCH_PERFMON_EVENTSEL0_ENABLE;
795 wrmsrl(MSR_K7_EVNTSEL0 + idx, val); 885 wrmsrl(MSR_K7_EVNTSEL0 + idx, val);
796 } 886 }
@@ -819,16 +909,13 @@ static inline void intel_pmu_ack_status(u64 ack)
819 909
820static inline void x86_pmu_enable_counter(struct hw_perf_counter *hwc, int idx) 910static inline void x86_pmu_enable_counter(struct hw_perf_counter *hwc, int idx)
821{ 911{
822 int err; 912 (void)checking_wrmsrl(hwc->config_base + idx,
823 err = checking_wrmsrl(hwc->config_base + idx,
824 hwc->config | ARCH_PERFMON_EVENTSEL0_ENABLE); 913 hwc->config | ARCH_PERFMON_EVENTSEL0_ENABLE);
825} 914}
826 915
827static inline void x86_pmu_disable_counter(struct hw_perf_counter *hwc, int idx) 916static inline void x86_pmu_disable_counter(struct hw_perf_counter *hwc, int idx)
828{ 917{
829 int err; 918 (void)checking_wrmsrl(hwc->config_base + idx, hwc->config);
830 err = checking_wrmsrl(hwc->config_base + idx,
831 hwc->config);
832} 919}
833 920
834static inline void 921static inline void
@@ -836,13 +923,24 @@ intel_pmu_disable_fixed(struct hw_perf_counter *hwc, int __idx)
836{ 923{
837 int idx = __idx - X86_PMC_IDX_FIXED; 924 int idx = __idx - X86_PMC_IDX_FIXED;
838 u64 ctrl_val, mask; 925 u64 ctrl_val, mask;
839 int err;
840 926
841 mask = 0xfULL << (idx * 4); 927 mask = 0xfULL << (idx * 4);
842 928
843 rdmsrl(hwc->config_base, ctrl_val); 929 rdmsrl(hwc->config_base, ctrl_val);
844 ctrl_val &= ~mask; 930 ctrl_val &= ~mask;
845 err = checking_wrmsrl(hwc->config_base, ctrl_val); 931 (void)checking_wrmsrl(hwc->config_base, ctrl_val);
932}
933
934static inline void
935p6_pmu_disable_counter(struct hw_perf_counter *hwc, int idx)
936{
937 struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters);
938 u64 val = P6_NOP_COUNTER;
939
940 if (cpuc->enabled)
941 val |= ARCH_PERFMON_EVENTSEL0_ENABLE;
942
943 (void)checking_wrmsrl(hwc->config_base + idx, val);
846} 944}
847 945
848static inline void 946static inline void
@@ -943,6 +1041,19 @@ intel_pmu_enable_fixed(struct hw_perf_counter *hwc, int __idx)
943 err = checking_wrmsrl(hwc->config_base, ctrl_val); 1041 err = checking_wrmsrl(hwc->config_base, ctrl_val);
944} 1042}
945 1043
1044static void p6_pmu_enable_counter(struct hw_perf_counter *hwc, int idx)
1045{
1046 struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters);
1047 u64 val;
1048
1049 val = hwc->config;
1050 if (cpuc->enabled)
1051 val |= ARCH_PERFMON_EVENTSEL0_ENABLE;
1052
1053 (void)checking_wrmsrl(hwc->config_base + idx, val);
1054}
1055
1056
946static void intel_pmu_enable_counter(struct hw_perf_counter *hwc, int idx) 1057static void intel_pmu_enable_counter(struct hw_perf_counter *hwc, int idx)
947{ 1058{
948 if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) { 1059 if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) {
@@ -959,8 +1070,6 @@ static void amd_pmu_enable_counter(struct hw_perf_counter *hwc, int idx)
959 1070
960 if (cpuc->enabled) 1071 if (cpuc->enabled)
961 x86_pmu_enable_counter(hwc, idx); 1072 x86_pmu_enable_counter(hwc, idx);
962 else
963 x86_pmu_disable_counter(hwc, idx);
964} 1073}
965 1074
966static int 1075static int
@@ -1176,6 +1285,49 @@ static void intel_pmu_reset(void)
1176 local_irq_restore(flags); 1285 local_irq_restore(flags);
1177} 1286}
1178 1287
1288static int p6_pmu_handle_irq(struct pt_regs *regs)
1289{
1290 struct perf_sample_data data;
1291 struct cpu_hw_counters *cpuc;
1292 struct perf_counter *counter;
1293 struct hw_perf_counter *hwc;
1294 int idx, handled = 0;
1295 u64 val;
1296
1297 data.regs = regs;
1298 data.addr = 0;
1299
1300 cpuc = &__get_cpu_var(cpu_hw_counters);
1301
1302 for (idx = 0; idx < x86_pmu.num_counters; idx++) {
1303 if (!test_bit(idx, cpuc->active_mask))
1304 continue;
1305
1306 counter = cpuc->counters[idx];
1307 hwc = &counter->hw;
1308
1309 val = x86_perf_counter_update(counter, hwc, idx);
1310 if (val & (1ULL << (x86_pmu.counter_bits - 1)))
1311 continue;
1312
1313 /*
1314 * counter overflow
1315 */
1316 handled = 1;
1317 data.period = counter->hw.last_period;
1318
1319 if (!x86_perf_counter_set_period(counter, hwc, idx))
1320 continue;
1321
1322 if (perf_counter_overflow(counter, 1, &data))
1323 p6_pmu_disable_counter(hwc, idx);
1324 }
1325
1326 if (handled)
1327 inc_irq_stat(apic_perf_irqs);
1328
1329 return handled;
1330}
1179 1331
1180/* 1332/*
1181 * This handler is triggered by the local APIC, so the APIC IRQ handling 1333 * This handler is triggered by the local APIC, so the APIC IRQ handling
@@ -1185,14 +1337,13 @@ static int intel_pmu_handle_irq(struct pt_regs *regs)
1185{ 1337{
1186 struct perf_sample_data data; 1338 struct perf_sample_data data;
1187 struct cpu_hw_counters *cpuc; 1339 struct cpu_hw_counters *cpuc;
1188 int bit, cpu, loops; 1340 int bit, loops;
1189 u64 ack, status; 1341 u64 ack, status;
1190 1342
1191 data.regs = regs; 1343 data.regs = regs;
1192 data.addr = 0; 1344 data.addr = 0;
1193 1345
1194 cpu = smp_processor_id(); 1346 cpuc = &__get_cpu_var(cpu_hw_counters);
1195 cpuc = &per_cpu(cpu_hw_counters, cpu);
1196 1347
1197 perf_disable(); 1348 perf_disable();
1198 status = intel_pmu_get_status(); 1349 status = intel_pmu_get_status();
@@ -1249,14 +1400,13 @@ static int amd_pmu_handle_irq(struct pt_regs *regs)
1249 struct cpu_hw_counters *cpuc; 1400 struct cpu_hw_counters *cpuc;
1250 struct perf_counter *counter; 1401 struct perf_counter *counter;
1251 struct hw_perf_counter *hwc; 1402 struct hw_perf_counter *hwc;
1252 int cpu, idx, handled = 0; 1403 int idx, handled = 0;
1253 u64 val; 1404 u64 val;
1254 1405
1255 data.regs = regs; 1406 data.regs = regs;
1256 data.addr = 0; 1407 data.addr = 0;
1257 1408
1258 cpu = smp_processor_id(); 1409 cpuc = &__get_cpu_var(cpu_hw_counters);
1259 cpuc = &per_cpu(cpu_hw_counters, cpu);
1260 1410
1261 for (idx = 0; idx < x86_pmu.num_counters; idx++) { 1411 for (idx = 0; idx < x86_pmu.num_counters; idx++) {
1262 if (!test_bit(idx, cpuc->active_mask)) 1412 if (!test_bit(idx, cpuc->active_mask))
@@ -1353,6 +1503,32 @@ static __read_mostly struct notifier_block perf_counter_nmi_notifier = {
1353 .priority = 1 1503 .priority = 1
1354}; 1504};
1355 1505
1506static struct x86_pmu p6_pmu = {
1507 .name = "p6",
1508 .handle_irq = p6_pmu_handle_irq,
1509 .disable_all = p6_pmu_disable_all,
1510 .enable_all = p6_pmu_enable_all,
1511 .enable = p6_pmu_enable_counter,
1512 .disable = p6_pmu_disable_counter,
1513 .eventsel = MSR_P6_EVNTSEL0,
1514 .perfctr = MSR_P6_PERFCTR0,
1515 .event_map = p6_pmu_event_map,
1516 .raw_event = p6_pmu_raw_event,
1517 .max_events = ARRAY_SIZE(p6_perfmon_event_map),
1518 .max_period = (1ULL << 31) - 1,
1519 .version = 0,
1520 .num_counters = 2,
1521 /*
1522 * Counters have 40 bits implemented. However they are designed such
1523 * that bits [32-39] are sign extensions of bit 31. As such the
1524 * effective width of a counter for P6-like PMU is 32 bits only.
1525 *
1526 * See IA-32 Intel Architecture Software developer manual Vol 3B
1527 */
1528 .counter_bits = 32,
1529 .counter_mask = (1ULL << 32) - 1,
1530};
1531
1356static struct x86_pmu intel_pmu = { 1532static struct x86_pmu intel_pmu = {
1357 .name = "Intel", 1533 .name = "Intel",
1358 .handle_irq = intel_pmu_handle_irq, 1534 .handle_irq = intel_pmu_handle_irq,
@@ -1392,6 +1568,37 @@ static struct x86_pmu amd_pmu = {
1392 .max_period = (1ULL << 47) - 1, 1568 .max_period = (1ULL << 47) - 1,
1393}; 1569};
1394 1570
1571static int p6_pmu_init(void)
1572{
1573 switch (boot_cpu_data.x86_model) {
1574 case 1:
1575 case 3: /* Pentium Pro */
1576 case 5:
1577 case 6: /* Pentium II */
1578 case 7:
1579 case 8:
1580 case 11: /* Pentium III */
1581 break;
1582 case 9:
1583 case 13:
1584 /* Pentium M */
1585 break;
1586 default:
1587 pr_cont("unsupported p6 CPU model %d ",
1588 boot_cpu_data.x86_model);
1589 return -ENODEV;
1590 }
1591
1592 if (!cpu_has_apic) {
1593 pr_info("no Local APIC, try rebooting with lapic");
1594 return -ENODEV;
1595 }
1596
1597 x86_pmu = p6_pmu;
1598
1599 return 0;
1600}
1601
1395static int intel_pmu_init(void) 1602static int intel_pmu_init(void)
1396{ 1603{
1397 union cpuid10_edx edx; 1604 union cpuid10_edx edx;
@@ -1400,8 +1607,14 @@ static int intel_pmu_init(void)
1400 unsigned int ebx; 1607 unsigned int ebx;
1401 int version; 1608 int version;
1402 1609
1403 if (!cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) 1610 if (!cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) {
1611 /* check for P6 processor family */
1612 if (boot_cpu_data.x86 == 6) {
1613 return p6_pmu_init();
1614 } else {
1404 return -ENODEV; 1615 return -ENODEV;
1616 }
1617 }
1405 1618
1406 /* 1619 /*
1407 * Check whether the Architectural PerfMon supports 1620 * Check whether the Architectural PerfMon supports
diff --git a/include/linux/perf_counter.h b/include/linux/perf_counter.h
index 5e970c7d3fd5..bd15d7a5f5ce 100644
--- a/include/linux/perf_counter.h
+++ b/include/linux/perf_counter.h
@@ -120,8 +120,9 @@ enum perf_counter_sample_format {
120 PERF_SAMPLE_ID = 1U << 6, 120 PERF_SAMPLE_ID = 1U << 6,
121 PERF_SAMPLE_CPU = 1U << 7, 121 PERF_SAMPLE_CPU = 1U << 7,
122 PERF_SAMPLE_PERIOD = 1U << 8, 122 PERF_SAMPLE_PERIOD = 1U << 8,
123 PERF_SAMPLE_STREAM_ID = 1U << 9,
123 124
124 PERF_SAMPLE_MAX = 1U << 9, /* non-ABI */ 125 PERF_SAMPLE_MAX = 1U << 10, /* non-ABI */
125}; 126};
126 127
127/* 128/*
@@ -312,16 +313,7 @@ enum perf_event_type {
312 * struct perf_event_header header; 313 * struct perf_event_header header;
313 * u64 time; 314 * u64 time;
314 * u64 id; 315 * u64 id;
315 * u64 sample_period; 316 * u64 stream_id;
316 * };
317 */
318 PERF_EVENT_PERIOD = 4,
319
320 /*
321 * struct {
322 * struct perf_event_header header;
323 * u64 time;
324 * u64 id;
325 * }; 317 * };
326 */ 318 */
327 PERF_EVENT_THROTTLE = 5, 319 PERF_EVENT_THROTTLE = 5,
@@ -356,6 +348,7 @@ enum perf_event_type {
356 * { u64 time; } && PERF_SAMPLE_TIME 348 * { u64 time; } && PERF_SAMPLE_TIME
357 * { u64 addr; } && PERF_SAMPLE_ADDR 349 * { u64 addr; } && PERF_SAMPLE_ADDR
358 * { u64 id; } && PERF_SAMPLE_ID 350 * { u64 id; } && PERF_SAMPLE_ID
351 * { u64 stream_id;} && PERF_SAMPLE_STREAM_ID
359 * { u32 cpu, res; } && PERF_SAMPLE_CPU 352 * { u32 cpu, res; } && PERF_SAMPLE_CPU
360 * { u64 period; } && PERF_SAMPLE_PERIOD 353 * { u64 period; } && PERF_SAMPLE_PERIOD
361 * 354 *
diff --git a/init/Kconfig b/init/Kconfig
index 1ce05a4cb5f6..cb2c09270226 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -962,7 +962,7 @@ config PERF_COUNTERS
962 962
963config EVENT_PROFILE 963config EVENT_PROFILE
964 bool "Tracepoint profile sources" 964 bool "Tracepoint profile sources"
965 depends on PERF_COUNTERS && EVENT_TRACER 965 depends on PERF_COUNTERS && EVENT_TRACING
966 default y 966 default y
967 967
968endmenu 968endmenu
diff --git a/kernel/fork.c b/kernel/fork.c
index bd2959228871..9b42695f0d14 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1407,14 +1407,11 @@ long do_fork(unsigned long clone_flags,
1407 if (clone_flags & CLONE_VFORK) { 1407 if (clone_flags & CLONE_VFORK) {
1408 p->vfork_done = &vfork; 1408 p->vfork_done = &vfork;
1409 init_completion(&vfork); 1409 init_completion(&vfork);
1410 } else if (!(clone_flags & CLONE_VM)) {
1411 /*
1412 * vfork will do an exec which will call
1413 * set_task_comm()
1414 */
1415 perf_counter_fork(p);
1416 } 1410 }
1417 1411
1412 if (!(clone_flags & CLONE_THREAD))
1413 perf_counter_fork(p);
1414
1418 audit_finish_fork(p); 1415 audit_finish_fork(p);
1419 tracehook_report_clone(regs, clone_flags, nr, p); 1416 tracehook_report_clone(regs, clone_flags, nr, p);
1420 1417
diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c
index 7bc888dfd06a..950931041954 100644
--- a/kernel/perf_counter.c
+++ b/kernel/perf_counter.c
@@ -146,6 +146,28 @@ static void put_ctx(struct perf_counter_context *ctx)
146 } 146 }
147} 147}
148 148
149static void unclone_ctx(struct perf_counter_context *ctx)
150{
151 if (ctx->parent_ctx) {
152 put_ctx(ctx->parent_ctx);
153 ctx->parent_ctx = NULL;
154 }
155}
156
157/*
158 * If we inherit counters we want to return the parent counter id
159 * to userspace.
160 */
161static u64 primary_counter_id(struct perf_counter *counter)
162{
163 u64 id = counter->id;
164
165 if (counter->parent)
166 id = counter->parent->id;
167
168 return id;
169}
170
149/* 171/*
150 * Get the perf_counter_context for a task and lock it. 172 * Get the perf_counter_context for a task and lock it.
151 * This has to cope with with the fact that until it is locked, 173 * This has to cope with with the fact that until it is locked,
@@ -1288,7 +1310,6 @@ static void perf_counter_cpu_sched_in(struct perf_cpu_context *cpuctx, int cpu)
1288#define MAX_INTERRUPTS (~0ULL) 1310#define MAX_INTERRUPTS (~0ULL)
1289 1311
1290static void perf_log_throttle(struct perf_counter *counter, int enable); 1312static void perf_log_throttle(struct perf_counter *counter, int enable);
1291static void perf_log_period(struct perf_counter *counter, u64 period);
1292 1313
1293static void perf_adjust_period(struct perf_counter *counter, u64 events) 1314static void perf_adjust_period(struct perf_counter *counter, u64 events)
1294{ 1315{
@@ -1307,8 +1328,6 @@ static void perf_adjust_period(struct perf_counter *counter, u64 events)
1307 if (!sample_period) 1328 if (!sample_period)
1308 sample_period = 1; 1329 sample_period = 1;
1309 1330
1310 perf_log_period(counter, sample_period);
1311
1312 hwc->sample_period = sample_period; 1331 hwc->sample_period = sample_period;
1313} 1332}
1314 1333
@@ -1463,10 +1482,8 @@ static void perf_counter_enable_on_exec(struct task_struct *task)
1463 /* 1482 /*
1464 * Unclone this context if we enabled any counter. 1483 * Unclone this context if we enabled any counter.
1465 */ 1484 */
1466 if (enabled && ctx->parent_ctx) { 1485 if (enabled)
1467 put_ctx(ctx->parent_ctx); 1486 unclone_ctx(ctx);
1468 ctx->parent_ctx = NULL;
1469 }
1470 1487
1471 spin_unlock(&ctx->lock); 1488 spin_unlock(&ctx->lock);
1472 1489
@@ -1526,7 +1543,6 @@ __perf_counter_init_context(struct perf_counter_context *ctx,
1526 1543
1527static struct perf_counter_context *find_get_context(pid_t pid, int cpu) 1544static struct perf_counter_context *find_get_context(pid_t pid, int cpu)
1528{ 1545{
1529 struct perf_counter_context *parent_ctx;
1530 struct perf_counter_context *ctx; 1546 struct perf_counter_context *ctx;
1531 struct perf_cpu_context *cpuctx; 1547 struct perf_cpu_context *cpuctx;
1532 struct task_struct *task; 1548 struct task_struct *task;
@@ -1586,11 +1602,7 @@ static struct perf_counter_context *find_get_context(pid_t pid, int cpu)
1586 retry: 1602 retry:
1587 ctx = perf_lock_task_context(task, &flags); 1603 ctx = perf_lock_task_context(task, &flags);
1588 if (ctx) { 1604 if (ctx) {
1589 parent_ctx = ctx->parent_ctx; 1605 unclone_ctx(ctx);
1590 if (parent_ctx) {
1591 put_ctx(parent_ctx);
1592 ctx->parent_ctx = NULL; /* no longer a clone */
1593 }
1594 spin_unlock_irqrestore(&ctx->lock, flags); 1606 spin_unlock_irqrestore(&ctx->lock, flags);
1595 } 1607 }
1596 1608
@@ -1704,7 +1716,7 @@ perf_read_hw(struct perf_counter *counter, char __user *buf, size_t count)
1704 values[n++] = counter->total_time_running + 1716 values[n++] = counter->total_time_running +
1705 atomic64_read(&counter->child_total_time_running); 1717 atomic64_read(&counter->child_total_time_running);
1706 if (counter->attr.read_format & PERF_FORMAT_ID) 1718 if (counter->attr.read_format & PERF_FORMAT_ID)
1707 values[n++] = counter->id; 1719 values[n++] = primary_counter_id(counter);
1708 mutex_unlock(&counter->child_mutex); 1720 mutex_unlock(&counter->child_mutex);
1709 1721
1710 if (count < n * sizeof(u64)) 1722 if (count < n * sizeof(u64))
@@ -1811,8 +1823,6 @@ static int perf_counter_period(struct perf_counter *counter, u64 __user *arg)
1811 1823
1812 counter->attr.sample_freq = value; 1824 counter->attr.sample_freq = value;
1813 } else { 1825 } else {
1814 perf_log_period(counter, value);
1815
1816 counter->attr.sample_period = value; 1826 counter->attr.sample_period = value;
1817 counter->hw.sample_period = value; 1827 counter->hw.sample_period = value;
1818 } 1828 }
@@ -2661,6 +2671,9 @@ static void perf_counter_output(struct perf_counter *counter, int nmi,
2661 if (sample_type & PERF_SAMPLE_ID) 2671 if (sample_type & PERF_SAMPLE_ID)
2662 header.size += sizeof(u64); 2672 header.size += sizeof(u64);
2663 2673
2674 if (sample_type & PERF_SAMPLE_STREAM_ID)
2675 header.size += sizeof(u64);
2676
2664 if (sample_type & PERF_SAMPLE_CPU) { 2677 if (sample_type & PERF_SAMPLE_CPU) {
2665 header.size += sizeof(cpu_entry); 2678 header.size += sizeof(cpu_entry);
2666 2679
@@ -2704,7 +2717,13 @@ static void perf_counter_output(struct perf_counter *counter, int nmi,
2704 if (sample_type & PERF_SAMPLE_ADDR) 2717 if (sample_type & PERF_SAMPLE_ADDR)
2705 perf_output_put(&handle, data->addr); 2718 perf_output_put(&handle, data->addr);
2706 2719
2707 if (sample_type & PERF_SAMPLE_ID) 2720 if (sample_type & PERF_SAMPLE_ID) {
2721 u64 id = primary_counter_id(counter);
2722
2723 perf_output_put(&handle, id);
2724 }
2725
2726 if (sample_type & PERF_SAMPLE_STREAM_ID)
2708 perf_output_put(&handle, counter->id); 2727 perf_output_put(&handle, counter->id);
2709 2728
2710 if (sample_type & PERF_SAMPLE_CPU) 2729 if (sample_type & PERF_SAMPLE_CPU)
@@ -2727,7 +2746,7 @@ static void perf_counter_output(struct perf_counter *counter, int nmi,
2727 if (sub != counter) 2746 if (sub != counter)
2728 sub->pmu->read(sub); 2747 sub->pmu->read(sub);
2729 2748
2730 group_entry.id = sub->id; 2749 group_entry.id = primary_counter_id(sub);
2731 group_entry.counter = atomic64_read(&sub->count); 2750 group_entry.counter = atomic64_read(&sub->count);
2732 2751
2733 perf_output_put(&handle, group_entry); 2752 perf_output_put(&handle, group_entry);
@@ -2787,15 +2806,8 @@ perf_counter_read_event(struct perf_counter *counter,
2787 } 2806 }
2788 2807
2789 if (counter->attr.read_format & PERF_FORMAT_ID) { 2808 if (counter->attr.read_format & PERF_FORMAT_ID) {
2790 u64 id;
2791
2792 event.header.size += sizeof(u64); 2809 event.header.size += sizeof(u64);
2793 if (counter->parent) 2810 event.format[i++] = primary_counter_id(counter);
2794 id = counter->parent->id;
2795 else
2796 id = counter->id;
2797
2798 event.format[i++] = id;
2799 } 2811 }
2800 2812
2801 ret = perf_output_begin(&handle, counter, event.header.size, 0, 0); 2813 ret = perf_output_begin(&handle, counter, event.header.size, 0, 0);
@@ -2896,8 +2908,11 @@ void perf_counter_fork(struct task_struct *task)
2896 .event = { 2908 .event = {
2897 .header = { 2909 .header = {
2898 .type = PERF_EVENT_FORK, 2910 .type = PERF_EVENT_FORK,
2911 .misc = 0,
2899 .size = sizeof(fork_event.event), 2912 .size = sizeof(fork_event.event),
2900 }, 2913 },
2914 /* .pid */
2915 /* .ppid */
2901 }, 2916 },
2902 }; 2917 };
2903 2918
@@ -2969,8 +2984,10 @@ static void perf_counter_comm_event(struct perf_comm_event *comm_event)
2969 struct perf_cpu_context *cpuctx; 2984 struct perf_cpu_context *cpuctx;
2970 struct perf_counter_context *ctx; 2985 struct perf_counter_context *ctx;
2971 unsigned int size; 2986 unsigned int size;
2972 char *comm = comm_event->task->comm; 2987 char comm[TASK_COMM_LEN];
2973 2988
2989 memset(comm, 0, sizeof(comm));
2990 strncpy(comm, comm_event->task->comm, sizeof(comm));
2974 size = ALIGN(strlen(comm)+1, sizeof(u64)); 2991 size = ALIGN(strlen(comm)+1, sizeof(u64));
2975 2992
2976 comm_event->comm = comm; 2993 comm_event->comm = comm;
@@ -3005,8 +3022,16 @@ void perf_counter_comm(struct task_struct *task)
3005 3022
3006 comm_event = (struct perf_comm_event){ 3023 comm_event = (struct perf_comm_event){
3007 .task = task, 3024 .task = task,
3025 /* .comm */
3026 /* .comm_size */
3008 .event = { 3027 .event = {
3009 .header = { .type = PERF_EVENT_COMM, }, 3028 .header = {
3029 .type = PERF_EVENT_COMM,
3030 .misc = 0,
3031 /* .size */
3032 },
3033 /* .pid */
3034 /* .tid */
3010 }, 3035 },
3011 }; 3036 };
3012 3037
@@ -3089,8 +3114,15 @@ static void perf_counter_mmap_event(struct perf_mmap_event *mmap_event)
3089 char *buf = NULL; 3114 char *buf = NULL;
3090 const char *name; 3115 const char *name;
3091 3116
3117 memset(tmp, 0, sizeof(tmp));
3118
3092 if (file) { 3119 if (file) {
3093 buf = kzalloc(PATH_MAX, GFP_KERNEL); 3120 /*
3121 * d_path works from the end of the buffer backwards, so we
3122 * need to add enough zero bytes after the string to handle
3123 * the 64bit alignment we do later.
3124 */
3125 buf = kzalloc(PATH_MAX + sizeof(u64), GFP_KERNEL);
3094 if (!buf) { 3126 if (!buf) {
3095 name = strncpy(tmp, "//enomem", sizeof(tmp)); 3127 name = strncpy(tmp, "//enomem", sizeof(tmp));
3096 goto got_name; 3128 goto got_name;
@@ -3101,9 +3133,11 @@ static void perf_counter_mmap_event(struct perf_mmap_event *mmap_event)
3101 goto got_name; 3133 goto got_name;
3102 } 3134 }
3103 } else { 3135 } else {
3104 name = arch_vma_name(mmap_event->vma); 3136 if (arch_vma_name(mmap_event->vma)) {
3105 if (name) 3137 name = strncpy(tmp, arch_vma_name(mmap_event->vma),
3138 sizeof(tmp));
3106 goto got_name; 3139 goto got_name;
3140 }
3107 3141
3108 if (!vma->vm_mm) { 3142 if (!vma->vm_mm) {
3109 name = strncpy(tmp, "[vdso]", sizeof(tmp)); 3143 name = strncpy(tmp, "[vdso]", sizeof(tmp));
@@ -3148,8 +3182,16 @@ void __perf_counter_mmap(struct vm_area_struct *vma)
3148 3182
3149 mmap_event = (struct perf_mmap_event){ 3183 mmap_event = (struct perf_mmap_event){
3150 .vma = vma, 3184 .vma = vma,
3185 /* .file_name */
3186 /* .file_size */
3151 .event = { 3187 .event = {
3152 .header = { .type = PERF_EVENT_MMAP, }, 3188 .header = {
3189 .type = PERF_EVENT_MMAP,
3190 .misc = 0,
3191 /* .size */
3192 },
3193 /* .pid */
3194 /* .tid */
3153 .start = vma->vm_start, 3195 .start = vma->vm_start,
3154 .len = vma->vm_end - vma->vm_start, 3196 .len = vma->vm_end - vma->vm_start,
3155 .pgoff = vma->vm_pgoff, 3197 .pgoff = vma->vm_pgoff,
@@ -3160,49 +3202,6 @@ void __perf_counter_mmap(struct vm_area_struct *vma)
3160} 3202}
3161 3203
3162/* 3204/*
3163 * Log sample_period changes so that analyzing tools can re-normalize the
3164 * event flow.
3165 */
3166
3167struct freq_event {
3168 struct perf_event_header header;
3169 u64 time;
3170 u64 id;
3171 u64 period;
3172};
3173
3174static void perf_log_period(struct perf_counter *counter, u64 period)
3175{
3176 struct perf_output_handle handle;
3177 struct freq_event event;
3178 int ret;
3179
3180 if (counter->hw.sample_period == period)
3181 return;
3182
3183 if (counter->attr.sample_type & PERF_SAMPLE_PERIOD)
3184 return;
3185
3186 event = (struct freq_event) {
3187 .header = {
3188 .type = PERF_EVENT_PERIOD,
3189 .misc = 0,
3190 .size = sizeof(event),
3191 },
3192 .time = sched_clock(),
3193 .id = counter->id,
3194 .period = period,
3195 };
3196
3197 ret = perf_output_begin(&handle, counter, sizeof(event), 1, 0);
3198 if (ret)
3199 return;
3200
3201 perf_output_put(&handle, event);
3202 perf_output_end(&handle);
3203}
3204
3205/*
3206 * IRQ throttle logging 3205 * IRQ throttle logging
3207 */ 3206 */
3208 3207
@@ -3215,16 +3214,21 @@ static void perf_log_throttle(struct perf_counter *counter, int enable)
3215 struct perf_event_header header; 3214 struct perf_event_header header;
3216 u64 time; 3215 u64 time;
3217 u64 id; 3216 u64 id;
3217 u64 stream_id;
3218 } throttle_event = { 3218 } throttle_event = {
3219 .header = { 3219 .header = {
3220 .type = PERF_EVENT_THROTTLE + 1, 3220 .type = PERF_EVENT_THROTTLE,
3221 .misc = 0, 3221 .misc = 0,
3222 .size = sizeof(throttle_event), 3222 .size = sizeof(throttle_event),
3223 }, 3223 },
3224 .time = sched_clock(), 3224 .time = sched_clock(),
3225 .id = counter->id, 3225 .id = primary_counter_id(counter),
3226 .stream_id = counter->id,
3226 }; 3227 };
3227 3228
3229 if (enable)
3230 throttle_event.header.type = PERF_EVENT_UNTHROTTLE;
3231
3228 ret = perf_output_begin(&handle, counter, sizeof(throttle_event), 1, 0); 3232 ret = perf_output_begin(&handle, counter, sizeof(throttle_event), 1, 0);
3229 if (ret) 3233 if (ret)
3230 return; 3234 return;
@@ -3672,7 +3676,7 @@ static const struct pmu perf_ops_task_clock = {
3672void perf_tpcounter_event(int event_id) 3676void perf_tpcounter_event(int event_id)
3673{ 3677{
3674 struct perf_sample_data data = { 3678 struct perf_sample_data data = {
3675 .regs = get_irq_regs(); 3679 .regs = get_irq_regs(),
3676 .addr = 0, 3680 .addr = 0,
3677 }; 3681 };
3678 3682
@@ -3688,16 +3692,12 @@ extern void ftrace_profile_disable(int);
3688 3692
3689static void tp_perf_counter_destroy(struct perf_counter *counter) 3693static void tp_perf_counter_destroy(struct perf_counter *counter)
3690{ 3694{
3691 ftrace_profile_disable(perf_event_id(&counter->attr)); 3695 ftrace_profile_disable(counter->attr.config);
3692} 3696}
3693 3697
3694static const struct pmu *tp_perf_counter_init(struct perf_counter *counter) 3698static const struct pmu *tp_perf_counter_init(struct perf_counter *counter)
3695{ 3699{
3696 int event_id = perf_event_id(&counter->attr); 3700 if (ftrace_profile_enable(counter->attr.config))
3697 int ret;
3698
3699 ret = ftrace_profile_enable(event_id);
3700 if (ret)
3701 return NULL; 3701 return NULL;
3702 3702
3703 counter->destroy = tp_perf_counter_destroy; 3703 counter->destroy = tp_perf_counter_destroy;
@@ -4256,15 +4256,12 @@ void perf_counter_exit_task(struct task_struct *child)
4256 */ 4256 */
4257 spin_lock(&child_ctx->lock); 4257 spin_lock(&child_ctx->lock);
4258 child->perf_counter_ctxp = NULL; 4258 child->perf_counter_ctxp = NULL;
4259 if (child_ctx->parent_ctx) { 4259 /*
4260 /* 4260 * If this context is a clone; unclone it so it can't get
4261 * This context is a clone; unclone it so it can't get 4261 * swapped to another process while we're removing all
4262 * swapped to another process while we're removing all 4262 * the counters from it.
4263 * the counters from it. 4263 */
4264 */ 4264 unclone_ctx(child_ctx);
4265 put_ctx(child_ctx->parent_ctx);
4266 child_ctx->parent_ctx = NULL;
4267 }
4268 spin_unlock(&child_ctx->lock); 4265 spin_unlock(&child_ctx->lock);
4269 local_irq_restore(flags); 4266 local_irq_restore(flags);
4270 4267
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 8aa3f8c88707..e72e93110782 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -24,6 +24,9 @@ OPTIONS
24--dsos=:: 24--dsos=::
25 Only consider symbols in these dsos. CSV that understands 25 Only consider symbols in these dsos. CSV that understands
26 file://filename entries. 26 file://filename entries.
27-n
28--show-nr-samples
29 Show the number of samples for each symbol
27-C:: 30-C::
28--comms=:: 31--comms=::
29 Only consider symbols in these comms. CSV that understands 32 Only consider symbols in these comms. CSV that understands
@@ -33,6 +36,18 @@ OPTIONS
33 Only consider these symbols. CSV that understands 36 Only consider these symbols. CSV that understands
34 file://filename entries. 37 file://filename entries.
35 38
39-w::
40--field-width=::
41 Force each column width to the provided list, for large terminal
42 readability.
43
44-t::
45--field-separator=::
46
47 Use a special separator character and don't pad with spaces, replacing
48 all occurances of this separator in symbol names (and other output)
49 with a '.' character, that thus it's the only non valid separator.
50
36SEE ALSO 51SEE ALSO
37-------- 52--------
38linkperf:perf-stat[1] 53linkperf:perf-stat[1]
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 7822b3d6baca..a5e9b876ca09 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -345,7 +345,7 @@ BUILTIN_OBJS += builtin-stat.o
345BUILTIN_OBJS += builtin-top.o 345BUILTIN_OBJS += builtin-top.o
346 346
347PERFLIBS = $(LIB_FILE) 347PERFLIBS = $(LIB_FILE)
348EXTLIBS = 348EXTLIBS = -lbfd
349 349
350# 350#
351# Platform specific tweaks 351# Platform specific tweaks
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 5f9eefecc574..1dba568e1941 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -74,20 +74,12 @@ struct fork_event {
74 u32 pid, ppid; 74 u32 pid, ppid;
75}; 75};
76 76
77struct period_event {
78 struct perf_event_header header;
79 u64 time;
80 u64 id;
81 u64 sample_period;
82};
83
84typedef union event_union { 77typedef union event_union {
85 struct perf_event_header header; 78 struct perf_event_header header;
86 struct ip_event ip; 79 struct ip_event ip;
87 struct mmap_event mmap; 80 struct mmap_event mmap;
88 struct comm_event comm; 81 struct comm_event comm;
89 struct fork_event fork; 82 struct fork_event fork;
90 struct period_event period;
91} event_t; 83} event_t;
92 84
93 85
@@ -998,19 +990,6 @@ process_fork_event(event_t *event, unsigned long offset, unsigned long head)
998} 990}
999 991
1000static int 992static int
1001process_period_event(event_t *event, unsigned long offset, unsigned long head)
1002{
1003 dprintf("%p [%p]: PERF_EVENT_PERIOD: time:%Ld, id:%Ld: period:%Ld\n",
1004 (void *)(offset + head),
1005 (void *)(long)(event->header.size),
1006 event->period.time,
1007 event->period.id,
1008 event->period.sample_period);
1009
1010 return 0;
1011}
1012
1013static int
1014process_event(event_t *event, unsigned long offset, unsigned long head) 993process_event(event_t *event, unsigned long offset, unsigned long head)
1015{ 994{
1016 switch (event->header.type) { 995 switch (event->header.type) {
@@ -1025,9 +1004,6 @@ process_event(event_t *event, unsigned long offset, unsigned long head)
1025 1004
1026 case PERF_EVENT_FORK: 1005 case PERF_EVENT_FORK:
1027 return process_fork_event(event, offset, head); 1006 return process_fork_event(event, offset, head);
1028
1029 case PERF_EVENT_PERIOD:
1030 return process_period_event(event, offset, head);
1031 /* 1007 /*
1032 * We dont process them right now but they are fine: 1008 * We dont process them right now but they are fine:
1033 */ 1009 */
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 4ef78a5e6f32..6da09928130f 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -43,6 +43,7 @@ static int call_graph = 0;
43static int verbose = 0; 43static int verbose = 0;
44static int inherit_stat = 0; 44static int inherit_stat = 0;
45static int no_samples = 0; 45static int no_samples = 0;
46static int sample_address = 0;
46 47
47static long samples; 48static long samples;
48static struct timeval last_read; 49static struct timeval last_read;
@@ -313,6 +314,10 @@ static void pid_synthesize_mmap_samples(pid_t pid)
313 if (*pbf == 'x') { /* vm_exec */ 314 if (*pbf == 'x') { /* vm_exec */
314 char *execname = strchr(bf, '/'); 315 char *execname = strchr(bf, '/');
315 316
317 /* Catch VDSO */
318 if (execname == NULL)
319 execname = strstr(bf, "[vdso]");
320
316 if (execname == NULL) 321 if (execname == NULL)
317 continue; 322 continue;
318 323
@@ -401,6 +406,9 @@ static void create_counter(int counter, int cpu, pid_t pid)
401 if (inherit_stat) 406 if (inherit_stat)
402 attr->inherit_stat = 1; 407 attr->inherit_stat = 1;
403 408
409 if (sample_address)
410 attr->sample_type |= PERF_SAMPLE_ADDR;
411
404 if (call_graph) 412 if (call_graph)
405 attr->sample_type |= PERF_SAMPLE_CALLCHAIN; 413 attr->sample_type |= PERF_SAMPLE_CALLCHAIN;
406 414
@@ -645,6 +653,8 @@ static const struct option options[] = {
645 "be more verbose (show counter open errors, etc)"), 653 "be more verbose (show counter open errors, etc)"),
646 OPT_BOOLEAN('s', "stat", &inherit_stat, 654 OPT_BOOLEAN('s', "stat", &inherit_stat,
647 "per thread counts"), 655 "per thread counts"),
656 OPT_BOOLEAN('d', "data", &sample_address,
657 "Sample addresses"),
648 OPT_BOOLEAN('n', "no-samples", &no_samples, 658 OPT_BOOLEAN('n', "no-samples", &no_samples,
649 "don't sample"), 659 "don't sample"),
650 OPT_END() 660 OPT_END()
@@ -654,7 +664,8 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
654{ 664{
655 int counter; 665 int counter;
656 666
657 argc = parse_options(argc, argv, options, record_usage, 0); 667 argc = parse_options(argc, argv, options, record_usage,
668 PARSE_OPT_STOP_AT_NON_OPTION);
658 if (!argc && target_pid == -1 && !system_wide) 669 if (!argc && target_pid == -1 && !system_wide)
659 usage_with_options(record_usage, options); 670 usage_with_options(record_usage, options);
660 671
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 4e5cc266311e..b20a4b6e31b7 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -33,8 +33,10 @@ static char *vmlinux = NULL;
33 33
34static char default_sort_order[] = "comm,dso"; 34static char default_sort_order[] = "comm,dso";
35static char *sort_order = default_sort_order; 35static char *sort_order = default_sort_order;
36static char *dso_list_str, *comm_list_str, *sym_list_str; 36static char *dso_list_str, *comm_list_str, *sym_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;
39static char *field_sep;
38 40
39static int input; 41static int input;
40static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV; 42static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV;
@@ -49,6 +51,7 @@ static int verbose;
49static int modules; 51static int modules;
50 52
51static int full_paths; 53static int full_paths;
54static int show_nr_samples;
52 55
53static unsigned long page_size; 56static unsigned long page_size;
54static unsigned long mmap_window = 32; 57static unsigned long mmap_window = 32;
@@ -98,13 +101,6 @@ struct fork_event {
98 u32 pid, ppid; 101 u32 pid, ppid;
99}; 102};
100 103
101struct period_event {
102 struct perf_event_header header;
103 u64 time;
104 u64 id;
105 u64 sample_period;
106};
107
108struct lost_event { 104struct lost_event {
109 struct perf_event_header header; 105 struct perf_event_header header;
110 u64 id; 106 u64 id;
@@ -124,11 +120,37 @@ typedef union event_union {
124 struct mmap_event mmap; 120 struct mmap_event mmap;
125 struct comm_event comm; 121 struct comm_event comm;
126 struct fork_event fork; 122 struct fork_event fork;
127 struct period_event period;
128 struct lost_event lost; 123 struct lost_event lost;
129 struct read_event read; 124 struct read_event read;
130} event_t; 125} event_t;
131 126
127static int repsep_fprintf(FILE *fp, const char *fmt, ...)
128{
129 int n;
130 va_list ap;
131
132 va_start(ap, fmt);
133 if (!field_sep)
134 n = vfprintf(fp, fmt, ap);
135 else {
136 char *bf = NULL;
137 n = vasprintf(&bf, fmt, ap);
138 if (n > 0) {
139 char *sep = bf;
140 while (1) {
141 sep = strchr(sep, *field_sep);
142 if (sep == NULL)
143 break;
144 *sep = '.';
145 }
146 }
147 fputs(bf, fp);
148 free(bf);
149 }
150 va_end(ap);
151 return n;
152}
153
132static LIST_HEAD(dsos); 154static LIST_HEAD(dsos);
133static struct dso *kernel_dso; 155static struct dso *kernel_dso;
134static struct dso *vdso; 156static struct dso *vdso;
@@ -360,12 +382,28 @@ static struct thread *thread__new(pid_t pid)
360 return self; 382 return self;
361} 383}
362 384
385static unsigned int dsos__col_width,
386 comms__col_width,
387 threads__col_width;
388
363static int thread__set_comm(struct thread *self, const char *comm) 389static int thread__set_comm(struct thread *self, const char *comm)
364{ 390{
365 if (self->comm) 391 if (self->comm)
366 free(self->comm); 392 free(self->comm);
367 self->comm = strdup(comm); 393 self->comm = strdup(comm);
368 return self->comm ? 0 : -ENOMEM; 394 if (!self->comm)
395 return -ENOMEM;
396
397 if (!col_width_list_str && !field_sep &&
398 (!comm_list || strlist__has_entry(comm_list, comm))) {
399 unsigned int slen = strlen(comm);
400 if (slen > comms__col_width) {
401 comms__col_width = slen;
402 threads__col_width = slen + 6;
403 }
404 }
405
406 return 0;
369} 407}
370 408
371static size_t thread__fprintf(struct thread *self, FILE *fp) 409static size_t thread__fprintf(struct thread *self, FILE *fp)
@@ -536,7 +574,9 @@ struct sort_entry {
536 574
537 int64_t (*cmp)(struct hist_entry *, struct hist_entry *); 575 int64_t (*cmp)(struct hist_entry *, struct hist_entry *);
538 int64_t (*collapse)(struct hist_entry *, struct hist_entry *); 576 int64_t (*collapse)(struct hist_entry *, struct hist_entry *);
539 size_t (*print)(FILE *fp, struct hist_entry *); 577 size_t (*print)(FILE *fp, struct hist_entry *, unsigned int width);
578 unsigned int *width;
579 bool elide;
540}; 580};
541 581
542static int64_t cmp_null(void *l, void *r) 582static int64_t cmp_null(void *l, void *r)
@@ -558,15 +598,17 @@ sort__thread_cmp(struct hist_entry *left, struct hist_entry *right)
558} 598}
559 599
560static size_t 600static size_t
561sort__thread_print(FILE *fp, struct hist_entry *self) 601sort__thread_print(FILE *fp, struct hist_entry *self, unsigned int width)
562{ 602{
563 return fprintf(fp, "%16s:%5d", self->thread->comm ?: "", self->thread->pid); 603 return repsep_fprintf(fp, "%*s:%5d", width - 6,
604 self->thread->comm ?: "", self->thread->pid);
564} 605}
565 606
566static struct sort_entry sort_thread = { 607static struct sort_entry sort_thread = {
567 .header = " Command: Pid", 608 .header = "Command: Pid",
568 .cmp = sort__thread_cmp, 609 .cmp = sort__thread_cmp,
569 .print = sort__thread_print, 610 .print = sort__thread_print,
611 .width = &threads__col_width,
570}; 612};
571 613
572/* --sort comm */ 614/* --sort comm */
@@ -590,16 +632,17 @@ sort__comm_collapse(struct hist_entry *left, struct hist_entry *right)
590} 632}
591 633
592static size_t 634static size_t
593sort__comm_print(FILE *fp, struct hist_entry *self) 635sort__comm_print(FILE *fp, struct hist_entry *self, unsigned int width)
594{ 636{
595 return fprintf(fp, "%16s", self->thread->comm); 637 return repsep_fprintf(fp, "%*s", width, self->thread->comm);
596} 638}
597 639
598static struct sort_entry sort_comm = { 640static struct sort_entry sort_comm = {
599 .header = " Command", 641 .header = "Command",
600 .cmp = sort__comm_cmp, 642 .cmp = sort__comm_cmp,
601 .collapse = sort__comm_collapse, 643 .collapse = sort__comm_collapse,
602 .print = sort__comm_print, 644 .print = sort__comm_print,
645 .width = &comms__col_width,
603}; 646};
604 647
605/* --sort dso */ 648/* --sort dso */
@@ -617,18 +660,19 @@ sort__dso_cmp(struct hist_entry *left, struct hist_entry *right)
617} 660}
618 661
619static size_t 662static size_t
620sort__dso_print(FILE *fp, struct hist_entry *self) 663sort__dso_print(FILE *fp, struct hist_entry *self, unsigned int width)
621{ 664{
622 if (self->dso) 665 if (self->dso)
623 return fprintf(fp, "%-25s", self->dso->name); 666 return repsep_fprintf(fp, "%-*s", width, self->dso->name);
624 667
625 return fprintf(fp, "%016llx ", (u64)self->ip); 668 return repsep_fprintf(fp, "%*llx", width, (u64)self->ip);
626} 669}
627 670
628static struct sort_entry sort_dso = { 671static struct sort_entry sort_dso = {
629 .header = "Shared Object ", 672 .header = "Shared Object",
630 .cmp = sort__dso_cmp, 673 .cmp = sort__dso_cmp,
631 .print = sort__dso_print, 674 .print = sort__dso_print,
675 .width = &dsos__col_width,
632}; 676};
633 677
634/* --sort symbol */ 678/* --sort symbol */
@@ -648,22 +692,22 @@ sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
648} 692}
649 693
650static size_t 694static size_t
651sort__sym_print(FILE *fp, struct hist_entry *self) 695sort__sym_print(FILE *fp, struct hist_entry *self, unsigned int width __used)
652{ 696{
653 size_t ret = 0; 697 size_t ret = 0;
654 698
655 if (verbose) 699 if (verbose)
656 ret += fprintf(fp, "%#018llx ", (u64)self->ip); 700 ret += repsep_fprintf(fp, "%#018llx ", (u64)self->ip);
657 701
702 ret += repsep_fprintf(fp, "[%c] ", self->level);
658 if (self->sym) { 703 if (self->sym) {
659 ret += fprintf(fp, "[%c] %s", 704 ret += repsep_fprintf(fp, "%s", self->sym->name);
660 self->dso == kernel_dso ? 'k' :
661 self->dso == hypervisor_dso ? 'h' : '.', self->sym->name);
662 705
663 if (self->sym->module) 706 if (self->sym->module)
664 ret += fprintf(fp, "\t[%s]", self->sym->module->name); 707 ret += repsep_fprintf(fp, "\t[%s]",
708 self->sym->module->name);
665 } else { 709 } else {
666 ret += fprintf(fp, "%#016llx", (u64)self->ip); 710 ret += repsep_fprintf(fp, "%#016llx", (u64)self->ip);
667 } 711 }
668 712
669 return ret; 713 return ret;
@@ -690,19 +734,19 @@ sort__parent_cmp(struct hist_entry *left, struct hist_entry *right)
690} 734}
691 735
692static size_t 736static size_t
693sort__parent_print(FILE *fp, struct hist_entry *self) 737sort__parent_print(FILE *fp, struct hist_entry *self, unsigned int width)
694{ 738{
695 size_t ret = 0; 739 return repsep_fprintf(fp, "%-*s", width,
696 740 self->parent ? self->parent->name : "[other]");
697 ret += fprintf(fp, "%-20s", self->parent ? self->parent->name : "[other]");
698
699 return ret;
700} 741}
701 742
743static unsigned int parent_symbol__col_width;
744
702static struct sort_entry sort_parent = { 745static struct sort_entry sort_parent = {
703 .header = "Parent symbol ", 746 .header = "Parent symbol",
704 .cmp = sort__parent_cmp, 747 .cmp = sort__parent_cmp,
705 .print = sort__parent_print, 748 .print = sort__parent_print,
749 .width = &parent_symbol__col_width,
706}; 750};
707 751
708static int sort__need_collapse = 0; 752static int sort__need_collapse = 0;
@@ -967,17 +1011,25 @@ hist_entry__fprintf(FILE *fp, struct hist_entry *self, u64 total_samples)
967 return 0; 1011 return 0;
968 1012
969 if (total_samples) 1013 if (total_samples)
970 ret = percent_color_fprintf(fp, " %6.2f%%", 1014 ret = percent_color_fprintf(fp,
971 (self->count * 100.0) / total_samples); 1015 field_sep ? "%.2f" : " %6.2f%%",
1016 (self->count * 100.0) / total_samples);
972 else 1017 else
973 ret = fprintf(fp, "%12Ld ", self->count); 1018 ret = fprintf(fp, field_sep ? "%lld" : "%12lld ", self->count);
1019
1020 if (show_nr_samples) {
1021 if (field_sep)
1022 fprintf(fp, "%c%lld", *field_sep, self->count);
1023 else
1024 fprintf(fp, "%11lld", self->count);
1025 }
974 1026
975 list_for_each_entry(se, &hist_entry__sort_list, list) { 1027 list_for_each_entry(se, &hist_entry__sort_list, list) {
976 if (exclude_other && (se == &sort_parent)) 1028 if (se->elide)
977 continue; 1029 continue;
978 1030
979 fprintf(fp, " "); 1031 fprintf(fp, "%s", field_sep ?: " ");
980 ret += se->print(fp, self); 1032 ret += se->print(fp, self, se->width ? *se->width : 0);
981 } 1033 }
982 1034
983 ret += fprintf(fp, "\n"); 1035 ret += fprintf(fp, "\n");
@@ -992,6 +1044,18 @@ hist_entry__fprintf(FILE *fp, struct hist_entry *self, u64 total_samples)
992 * 1044 *
993 */ 1045 */
994 1046
1047static void dso__calc_col_width(struct dso *self)
1048{
1049 if (!col_width_list_str && !field_sep &&
1050 (!dso_list || strlist__has_entry(dso_list, self->name))) {
1051 unsigned int slen = strlen(self->name);
1052 if (slen > dsos__col_width)
1053 dsos__col_width = slen;
1054 }
1055
1056 self->slen_calculated = 1;
1057}
1058
995static struct symbol * 1059static struct symbol *
996resolve_symbol(struct thread *thread, struct map **mapp, 1060resolve_symbol(struct thread *thread, struct map **mapp,
997 struct dso **dsop, u64 *ipp) 1061 struct dso **dsop, u64 *ipp)
@@ -1011,6 +1075,14 @@ resolve_symbol(struct thread *thread, struct map **mapp,
1011 1075
1012 map = thread__find_map(thread, ip); 1076 map = thread__find_map(thread, ip);
1013 if (map != NULL) { 1077 if (map != NULL) {
1078 /*
1079 * We have to do this here as we may have a dso
1080 * with no symbol hit that has a name longer than
1081 * the ones with symbols sampled.
1082 */
1083 if (!sort_dso.elide && !map->dso->slen_calculated)
1084 dso__calc_col_width(map->dso);
1085
1014 if (mapp) 1086 if (mapp)
1015 *mapp = map; 1087 *mapp = map;
1016got_map: 1088got_map:
@@ -1282,35 +1354,67 @@ static size_t output__fprintf(FILE *fp, u64 total_samples)
1282 struct sort_entry *se; 1354 struct sort_entry *se;
1283 struct rb_node *nd; 1355 struct rb_node *nd;
1284 size_t ret = 0; 1356 size_t ret = 0;
1357 unsigned int width;
1358 char *col_width = col_width_list_str;
1285 1359
1286 fprintf(fp, "\n"); 1360 fprintf(fp, "# Samples: %Ld\n", (u64)total_samples);
1287 fprintf(fp, "#\n");
1288 fprintf(fp, "# (%Ld samples)\n", (u64)total_samples);
1289 fprintf(fp, "#\n"); 1361 fprintf(fp, "#\n");
1290 1362
1291 fprintf(fp, "# Overhead"); 1363 fprintf(fp, "# Overhead");
1364 if (show_nr_samples) {
1365 if (field_sep)
1366 fprintf(fp, "%cSamples", *field_sep);
1367 else
1368 fputs(" Samples ", fp);
1369 }
1292 list_for_each_entry(se, &hist_entry__sort_list, list) { 1370 list_for_each_entry(se, &hist_entry__sort_list, list) {
1293 if (exclude_other && (se == &sort_parent)) 1371 if (se->elide)
1294 continue; 1372 continue;
1295 fprintf(fp, " %s", se->header); 1373 if (field_sep) {
1374 fprintf(fp, "%c%s", *field_sep, se->header);
1375 continue;
1376 }
1377 width = strlen(se->header);
1378 if (se->width) {
1379 if (col_width_list_str) {
1380 if (col_width) {
1381 *se->width = atoi(col_width);
1382 col_width = strchr(col_width, ',');
1383 if (col_width)
1384 ++col_width;
1385 }
1386 }
1387 width = *se->width = max(*se->width, width);
1388 }
1389 fprintf(fp, " %*s", width, se->header);
1296 } 1390 }
1297 fprintf(fp, "\n"); 1391 fprintf(fp, "\n");
1298 1392
1393 if (field_sep)
1394 goto print_entries;
1395
1299 fprintf(fp, "# ........"); 1396 fprintf(fp, "# ........");
1397 if (show_nr_samples)
1398 fprintf(fp, " ..........");
1300 list_for_each_entry(se, &hist_entry__sort_list, list) { 1399 list_for_each_entry(se, &hist_entry__sort_list, list) {
1301 unsigned int i; 1400 unsigned int i;
1302 1401
1303 if (exclude_other && (se == &sort_parent)) 1402 if (se->elide)
1304 continue; 1403 continue;
1305 1404
1306 fprintf(fp, " "); 1405 fprintf(fp, " ");
1307 for (i = 0; i < strlen(se->header); i++) 1406 if (se->width)
1407 width = *se->width;
1408 else
1409 width = strlen(se->header);
1410 for (i = 0; i < width; i++)
1308 fprintf(fp, "."); 1411 fprintf(fp, ".");
1309 } 1412 }
1310 fprintf(fp, "\n"); 1413 fprintf(fp, "\n");
1311 1414
1312 fprintf(fp, "#\n"); 1415 fprintf(fp, "#\n");
1313 1416
1417print_entries:
1314 for (nd = rb_first(&output_hists); nd; nd = rb_next(nd)) { 1418 for (nd = rb_first(&output_hists); nd; nd = rb_next(nd)) {
1315 pos = rb_entry(nd, struct hist_entry, rb_node); 1419 pos = rb_entry(nd, struct hist_entry, rb_node);
1316 ret += hist_entry__fprintf(fp, pos, total_samples); 1420 ret += hist_entry__fprintf(fp, pos, total_samples);
@@ -1524,19 +1628,6 @@ process_fork_event(event_t *event, unsigned long offset, unsigned long head)
1524} 1628}
1525 1629
1526static int 1630static int
1527process_period_event(event_t *event, unsigned long offset, unsigned long head)
1528{
1529 dprintf("%p [%p]: PERF_EVENT_PERIOD: time:%Ld, id:%Ld: period:%Ld\n",
1530 (void *)(offset + head),
1531 (void *)(long)(event->header.size),
1532 event->period.time,
1533 event->period.id,
1534 event->period.sample_period);
1535
1536 return 0;
1537}
1538
1539static int
1540process_lost_event(event_t *event, unsigned long offset, unsigned long head) 1631process_lost_event(event_t *event, unsigned long offset, unsigned long head)
1541{ 1632{
1542 dprintf("%p [%p]: PERF_EVENT_LOST: id:%Ld: lost:%Ld\n", 1633 dprintf("%p [%p]: PERF_EVENT_LOST: id:%Ld: lost:%Ld\n",
@@ -1617,9 +1708,6 @@ process_event(event_t *event, unsigned long offset, unsigned long head)
1617 case PERF_EVENT_FORK: 1708 case PERF_EVENT_FORK:
1618 return process_fork_event(event, offset, head); 1709 return process_fork_event(event, offset, head);
1619 1710
1620 case PERF_EVENT_PERIOD:
1621 return process_period_event(event, offset, head);
1622
1623 case PERF_EVENT_LOST: 1711 case PERF_EVENT_LOST:
1624 return process_lost_event(event, offset, head); 1712 return process_lost_event(event, offset, head);
1625 1713
@@ -1883,6 +1971,8 @@ static const struct option options[] = {
1883 OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"), 1971 OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"),
1884 OPT_BOOLEAN('m', "modules", &modules, 1972 OPT_BOOLEAN('m', "modules", &modules,
1885 "load module symbols - WARNING: use only with -k and LIVE kernel"), 1973 "load module symbols - WARNING: use only with -k and LIVE kernel"),
1974 OPT_BOOLEAN('n', "show-nr-samples", &show_nr_samples,
1975 "Show a column with the number of samples"),
1886 OPT_STRING('s', "sort", &sort_order, "key[,key2...]", 1976 OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
1887 "sort by key(s): pid, comm, dso, symbol, parent"), 1977 "sort by key(s): pid, comm, dso, symbol, parent"),
1888 OPT_BOOLEAN('P', "full-paths", &full_paths, 1978 OPT_BOOLEAN('P', "full-paths", &full_paths,
@@ -1891,15 +1981,21 @@ static const struct option options[] = {
1891 "regex filter to identify parent, see: '--sort parent'"), 1981 "regex filter to identify parent, see: '--sort parent'"),
1892 OPT_BOOLEAN('x', "exclude-other", &exclude_other, 1982 OPT_BOOLEAN('x', "exclude-other", &exclude_other,
1893 "Only display entries with parent-match"), 1983 "Only display entries with parent-match"),
1894 OPT_CALLBACK_DEFAULT('c', "callchain", NULL, "output_type,min_percent", 1984 OPT_CALLBACK_DEFAULT('g', "call-graph", NULL, "output_type,min_percent",
1895 "Display callchains using output_type and min percent threshold. " 1985 "Display callchains using output_type and min percent threshold. "
1896 "Default: flat,0", &parse_callchain_opt, callchain_default_opt), 1986 "Default: fractal,0.5", &parse_callchain_opt, callchain_default_opt),
1897 OPT_STRING('d', "dsos", &dso_list_str, "dso[,dso...]", 1987 OPT_STRING('d', "dsos", &dso_list_str, "dso[,dso...]",
1898 "only consider symbols in these dsos"), 1988 "only consider symbols in these dsos"),
1899 OPT_STRING('C', "comms", &comm_list_str, "comm[,comm...]", 1989 OPT_STRING('C', "comms", &comm_list_str, "comm[,comm...]",
1900 "only consider symbols in these comms"), 1990 "only consider symbols in these comms"),
1901 OPT_STRING('S', "symbols", &sym_list_str, "symbol[,symbol...]", 1991 OPT_STRING('S', "symbols", &sym_list_str, "symbol[,symbol...]",
1902 "only consider these symbols"), 1992 "only consider these symbols"),
1993 OPT_STRING('w', "column-widths", &col_width_list_str,
1994 "width[,width...]",
1995 "don't try to adjust column width, use these fixed values"),
1996 OPT_STRING('t', "field-separator", &field_sep, "separator",
1997 "separator for columns, no spaces will be added between "
1998 "columns '.' is reserved."),
1903 OPT_END() 1999 OPT_END()
1904}; 2000};
1905 2001
@@ -1919,7 +2015,8 @@ static void setup_sorting(void)
1919} 2015}
1920 2016
1921static void setup_list(struct strlist **list, const char *list_str, 2017static void setup_list(struct strlist **list, const char *list_str,
1922 const char *list_name) 2018 struct sort_entry *se, const char *list_name,
2019 FILE *fp)
1923{ 2020{
1924 if (list_str) { 2021 if (list_str) {
1925 *list = strlist__new(true, list_str); 2022 *list = strlist__new(true, list_str);
@@ -1928,6 +2025,11 @@ static void setup_list(struct strlist **list, const char *list_str,
1928 list_name); 2025 list_name);
1929 exit(129); 2026 exit(129);
1930 } 2027 }
2028 if (strlist__nr_entries(*list) == 1) {
2029 fprintf(fp, "# %s: %s\n", list_name,
2030 strlist__entry(*list, 0)->s);
2031 se->elide = true;
2032 }
1931 } 2033 }
1932} 2034}
1933 2035
@@ -1941,9 +2043,10 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
1941 2043
1942 setup_sorting(); 2044 setup_sorting();
1943 2045
1944 if (parent_pattern != default_parent_pattern) 2046 if (parent_pattern != default_parent_pattern) {
1945 sort_dimension__add("parent"); 2047 sort_dimension__add("parent");
1946 else 2048 sort_parent.elide = 1;
2049 } else
1947 exclude_other = 0; 2050 exclude_other = 0;
1948 2051
1949 /* 2052 /*
@@ -1952,11 +2055,17 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
1952 if (argc) 2055 if (argc)
1953 usage_with_options(report_usage, options); 2056 usage_with_options(report_usage, options);
1954 2057
1955 setup_list(&dso_list, dso_list_str, "dso");
1956 setup_list(&comm_list, comm_list_str, "comm");
1957 setup_list(&sym_list, sym_list_str, "symbol");
1958
1959 setup_pager(); 2058 setup_pager();
1960 2059
2060 setup_list(&dso_list, dso_list_str, &sort_dso, "dso", stdout);
2061 setup_list(&comm_list, comm_list_str, &sort_comm, "comm", stdout);
2062 setup_list(&sym_list, sym_list_str, &sort_sym, "symbol", stdout);
2063
2064 if (field_sep && *field_sep == '.') {
2065 fputs("'.' is the only non valid --field-separator argument\n",
2066 stderr);
2067 exit(129);
2068 }
2069
1961 return __cmd_report(); 2070 return __cmd_report();
1962} 2071}
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 27921a8ce1a9..f9510eeeb6c7 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -511,7 +511,8 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
511{ 511{
512 int status; 512 int status;
513 513
514 argc = parse_options(argc, argv, options, stat_usage, 0); 514 argc = parse_options(argc, argv, options, stat_usage,
515 PARSE_OPT_STOP_AT_NON_OPTION);
515 if (!argc) 516 if (!argc)
516 usage_with_options(stat_usage, options); 517 usage_with_options(stat_usage, options);
517 if (run_count <= 0 || run_count > MAX_RUN) 518 if (run_count <= 0 || run_count > MAX_RUN)
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 95d5c0ae375a..c0a423004e15 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -58,6 +58,7 @@ static u64 count_filter = 5;
58static int print_entries = 15; 58static int print_entries = 15;
59 59
60static int target_pid = -1; 60static int target_pid = -1;
61static int inherit = 0;
61static int profile_cpu = -1; 62static int profile_cpu = -1;
62static int nr_cpus = 0; 63static int nr_cpus = 0;
63static unsigned int realtime_prio = 0; 64static unsigned int realtime_prio = 0;
@@ -549,7 +550,7 @@ int group_fd;
549static void start_counter(int i, int counter) 550static void start_counter(int i, int counter)
550{ 551{
551 struct perf_counter_attr *attr; 552 struct perf_counter_attr *attr;
552 unsigned int cpu; 553 int cpu;
553 554
554 cpu = profile_cpu; 555 cpu = profile_cpu;
555 if (target_pid == -1 && profile_cpu == -1) 556 if (target_pid == -1 && profile_cpu == -1)
@@ -559,6 +560,7 @@ static void start_counter(int i, int counter)
559 560
560 attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID; 561 attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID;
561 attr->freq = freq; 562 attr->freq = freq;
563 attr->inherit = (cpu < 0) && inherit;
562 564
563try_again: 565try_again:
564 fd[i][counter] = sys_perf_counter_open(attr, target_pid, cpu, group_fd, 0); 566 fd[i][counter] = sys_perf_counter_open(attr, target_pid, cpu, group_fd, 0);
@@ -685,6 +687,8 @@ static const struct option options[] = {
685 "only display functions with more events than this"), 687 "only display functions with more events than this"),
686 OPT_BOOLEAN('g', "group", &group, 688 OPT_BOOLEAN('g', "group", &group,
687 "put the counters into a counter group"), 689 "put the counters into a counter group"),
690 OPT_BOOLEAN('i', "inherit", &inherit,
691 "child tasks inherit counters"),
688 OPT_STRING('s', "sym-filter", &sym_filter, "pattern", 692 OPT_STRING('s', "sym-filter", &sym_filter, "pattern",
689 "only display symbols matchig this pattern"), 693 "only display symbols matchig this pattern"),
690 OPT_BOOLEAN('z', "zero", &zero, 694 OPT_BOOLEAN('z', "zero", &zero,
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index c5656784c61d..31982ad064b4 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -12,6 +12,8 @@
12#include "util/cache.h" 12#include "util/cache.h"
13#include "util/quote.h" 13#include "util/quote.h"
14#include "util/run-command.h" 14#include "util/run-command.h"
15#include "util/parse-events.h"
16#include "util/string.h"
15 17
16const char perf_usage_string[] = 18const char perf_usage_string[] =
17 "perf [--version] [--help] COMMAND [ARGS]"; 19 "perf [--version] [--help] COMMAND [ARGS]";
@@ -25,6 +27,8 @@ struct pager_config {
25 int val; 27 int val;
26}; 28};
27 29
30static char debugfs_mntpt[MAXPATHLEN];
31
28static int pager_command_config(const char *var, const char *value, void *data) 32static int pager_command_config(const char *var, const char *value, void *data)
29{ 33{
30 struct pager_config *c = data; 34 struct pager_config *c = data;
@@ -56,6 +60,15 @@ static void commit_pager_choice(void) {
56 } 60 }
57} 61}
58 62
63static void set_debugfs_path(void)
64{
65 char *path;
66
67 path = getenv(PERF_DEBUGFS_ENVIRONMENT);
68 snprintf(debugfs_path, MAXPATHLEN, "%s/%s", path ?: debugfs_mntpt,
69 "tracing/events");
70}
71
59static int handle_options(const char*** argv, int* argc, int* envchanged) 72static int handle_options(const char*** argv, int* argc, int* envchanged)
60{ 73{
61 int handled = 0; 74 int handled = 0;
@@ -122,6 +135,22 @@ static int handle_options(const char*** argv, int* argc, int* envchanged)
122 setenv(PERF_WORK_TREE_ENVIRONMENT, cmd + 12, 1); 135 setenv(PERF_WORK_TREE_ENVIRONMENT, cmd + 12, 1);
123 if (envchanged) 136 if (envchanged)
124 *envchanged = 1; 137 *envchanged = 1;
138 } else if (!strcmp(cmd, "--debugfs-dir")) {
139 if (*argc < 2) {
140 fprintf(stderr, "No directory given for --debugfs-dir.\n");
141 usage(perf_usage_string);
142 }
143 strncpy(debugfs_mntpt, (*argv)[1], MAXPATHLEN);
144 debugfs_mntpt[MAXPATHLEN - 1] = '\0';
145 if (envchanged)
146 *envchanged = 1;
147 (*argv)++;
148 (*argc)--;
149 } else if (!prefixcmp(cmd, "--debugfs-dir=")) {
150 strncpy(debugfs_mntpt, cmd + 14, MAXPATHLEN);
151 debugfs_mntpt[MAXPATHLEN - 1] = '\0';
152 if (envchanged)
153 *envchanged = 1;
125 } else { 154 } else {
126 fprintf(stderr, "Unknown option: %s\n", cmd); 155 fprintf(stderr, "Unknown option: %s\n", cmd);
127 usage(perf_usage_string); 156 usage(perf_usage_string);
@@ -228,6 +257,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
228 if (use_pager == -1 && p->option & USE_PAGER) 257 if (use_pager == -1 && p->option & USE_PAGER)
229 use_pager = 1; 258 use_pager = 1;
230 commit_pager_choice(); 259 commit_pager_choice();
260 set_debugfs_path();
231 261
232 status = p->fn(argc, argv, prefix); 262 status = p->fn(argc, argv, prefix);
233 if (status) 263 if (status)
@@ -346,6 +376,49 @@ static int run_argv(int *argcp, const char ***argv)
346 return done_alias; 376 return done_alias;
347} 377}
348 378
379/* mini /proc/mounts parser: searching for "^blah /mount/point debugfs" */
380static void get_debugfs_mntpt(void)
381{
382 FILE *file;
383 char fs_type[100];
384 char debugfs[MAXPATHLEN];
385
386 /*
387 * try the standard location
388 */
389 if (valid_debugfs_mount("/sys/kernel/debug/") == 0) {
390 strcpy(debugfs_mntpt, "/sys/kernel/debug/");
391 return;
392 }
393
394 /*
395 * try the sane location
396 */
397 if (valid_debugfs_mount("/debug/") == 0) {
398 strcpy(debugfs_mntpt, "/debug/");
399 return;
400 }
401
402 /*
403 * give up and parse /proc/mounts
404 */
405 file = fopen("/proc/mounts", "r");
406 if (file == NULL)
407 return;
408
409 while (fscanf(file, "%*s %"
410 STR(MAXPATHLEN)
411 "s %99s %*s %*d %*d\n",
412 debugfs, fs_type) == 2) {
413 if (strcmp(fs_type, "debugfs") == 0)
414 break;
415 }
416 fclose(file);
417 if (strcmp(fs_type, "debugfs") == 0) {
418 strncpy(debugfs_mntpt, debugfs, MAXPATHLEN);
419 debugfs_mntpt[MAXPATHLEN - 1] = '\0';
420 }
421}
349 422
350int main(int argc, const char **argv) 423int main(int argc, const char **argv)
351{ 424{
@@ -354,7 +427,8 @@ int main(int argc, const char **argv)
354 cmd = perf_extract_argv0_path(argv[0]); 427 cmd = perf_extract_argv0_path(argv[0]);
355 if (!cmd) 428 if (!cmd)
356 cmd = "perf-help"; 429 cmd = "perf-help";
357 430 /* get debugfs mount point from /proc/mounts */
431 get_debugfs_mntpt();
358 /* 432 /*
359 * "perf-xxxx" is the same as "perf xxxx", but we obviously: 433 * "perf-xxxx" is the same as "perf xxxx", but we obviously:
360 * 434 *
@@ -377,6 +451,7 @@ int main(int argc, const char **argv)
377 argc--; 451 argc--;
378 handle_options(&argv, &argc, NULL); 452 handle_options(&argv, &argc, NULL);
379 commit_pager_choice(); 453 commit_pager_choice();
454 set_debugfs_path();
380 if (argc > 0) { 455 if (argc > 0) {
381 if (!prefixcmp(argv[0], "--")) 456 if (!prefixcmp(argv[0], "--"))
382 argv[0] += 2; 457 argv[0] += 2;
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 63e67cc5487b..e5148e2b6134 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -1,7 +1,13 @@
1#ifndef _PERF_PERF_H 1#ifndef _PERF_PERF_H
2#define _PERF_PERF_H 2#define _PERF_PERF_H
3 3
4#if defined(__x86_64__) || defined(__i386__) 4#if defined(__i386__)
5#include "../../arch/x86/include/asm/unistd.h"
6#define rmb() asm volatile("lock; addl $0,0(%%esp)" ::: "memory")
7#define cpu_relax() asm volatile("rep; nop" ::: "memory");
8#endif
9
10#if defined(__x86_64__)
5#include "../../arch/x86/include/asm/unistd.h" 11#include "../../arch/x86/include/asm/unistd.h"
6#define rmb() asm volatile("lfence" ::: "memory") 12#define rmb() asm volatile("lfence" ::: "memory")
7#define cpu_relax() asm volatile("rep; nop" ::: "memory"); 13#define cpu_relax() asm volatile("rep; nop" ::: "memory");
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index 161d5f413e28..4b50c412b9c5 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -18,6 +18,7 @@
18#define PERFATTRIBUTES_FILE ".perfattributes" 18#define PERFATTRIBUTES_FILE ".perfattributes"
19#define INFOATTRIBUTES_FILE "info/attributes" 19#define INFOATTRIBUTES_FILE "info/attributes"
20#define ATTRIBUTE_MACRO_PREFIX "[attr]" 20#define ATTRIBUTE_MACRO_PREFIX "[attr]"
21#define PERF_DEBUGFS_ENVIRONMENT "PERF_DEBUGFS_DIR"
21 22
22typedef int (*config_fn_t)(const char *, const char *, void *); 23typedef int (*config_fn_t)(const char *, const char *, void *);
23extern int perf_default_config(const char *, const char *, void *); 24extern int perf_default_config(const char *, const char *, void *);
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index b5ef53ad4c7a..bf280449fcfd 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -16,7 +16,7 @@ struct perf_header {
16 int frozen; 16 int frozen;
17 int attrs, size; 17 int attrs, size;
18 struct perf_header_attr **attr; 18 struct perf_header_attr **attr;
19 off_t attr_offset; 19 s64 attr_offset;
20 u64 data_offset; 20 u64 data_offset;
21 u64 data_size; 21 u64 data_size;
22}; 22};
diff --git a/tools/perf/util/include/linux/kernel.h b/tools/perf/util/include/linux/kernel.h
index 99c1b3d1edd9..a6b87390cb52 100644
--- a/tools/perf/util/include/linux/kernel.h
+++ b/tools/perf/util/include/linux/kernel.h
@@ -18,4 +18,12 @@
18 (type *)((char *)__mptr - offsetof(type, member)); }) 18 (type *)((char *)__mptr - offsetof(type, member)); })
19#endif 19#endif
20 20
21#ifndef max
22#define max(x, y) ({ \
23 typeof(x) _max1 = (x); \
24 typeof(y) _max2 = (y); \
25 (void) (&_max1 == &_max2); \
26 _max1 > _max2 ? _max1 : _max2; })
27#endif
28
21#endif 29#endif
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 5184959e0615..7bdad8df22a6 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -5,6 +5,7 @@
5#include "parse-events.h" 5#include "parse-events.h"
6#include "exec_cmd.h" 6#include "exec_cmd.h"
7#include "string.h" 7#include "string.h"
8#include "cache.h"
8 9
9extern char *strcasestr(const char *haystack, const char *needle); 10extern char *strcasestr(const char *haystack, const char *needle);
10 11
@@ -19,6 +20,8 @@ struct event_symbol {
19 char *alias; 20 char *alias;
20}; 21};
21 22
23char debugfs_path[MAXPATHLEN];
24
22#define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x 25#define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x
23#define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x 26#define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x
24 27
@@ -71,8 +74,8 @@ static char *sw_event_names[] = {
71#define MAX_ALIASES 8 74#define MAX_ALIASES 8
72 75
73static char *hw_cache[][MAX_ALIASES] = { 76static char *hw_cache[][MAX_ALIASES] = {
74 { "L1-d$", "l1-d", "l1d", "L1-data", }, 77 { "L1-dcache", "l1-d", "l1d", "L1-data", },
75 { "L1-i$", "l1-i", "l1i", "L1-instruction", }, 78 { "L1-icache", "l1-i", "l1i", "L1-instruction", },
76 { "LLC", "L2" }, 79 { "LLC", "L2" },
77 { "dTLB", "d-tlb", "Data-TLB", }, 80 { "dTLB", "d-tlb", "Data-TLB", },
78 { "iTLB", "i-tlb", "Instruction-TLB", }, 81 { "iTLB", "i-tlb", "Instruction-TLB", },
@@ -110,6 +113,88 @@ static unsigned long hw_cache_stat[C(MAX)] = {
110 [C(BPU)] = (CACHE_READ), 113 [C(BPU)] = (CACHE_READ),
111}; 114};
112 115
116#define for_each_subsystem(sys_dir, sys_dirent, sys_next, file, st) \
117 while (!readdir_r(sys_dir, &sys_dirent, &sys_next) && sys_next) \
118 if (snprintf(file, MAXPATHLEN, "%s/%s", debugfs_path, \
119 sys_dirent.d_name) && \
120 (!stat(file, &st)) && (S_ISDIR(st.st_mode)) && \
121 (strcmp(sys_dirent.d_name, ".")) && \
122 (strcmp(sys_dirent.d_name, "..")))
123
124#define for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next, file, st) \
125 while (!readdir_r(evt_dir, &evt_dirent, &evt_next) && evt_next) \
126 if (snprintf(file, MAXPATHLEN, "%s/%s/%s", debugfs_path, \
127 sys_dirent.d_name, evt_dirent.d_name) && \
128 (!stat(file, &st)) && (S_ISDIR(st.st_mode)) && \
129 (strcmp(evt_dirent.d_name, ".")) && \
130 (strcmp(evt_dirent.d_name, "..")))
131
132#define MAX_EVENT_LENGTH 30
133
134int valid_debugfs_mount(const char *debugfs)
135{
136 struct statfs st_fs;
137
138 if (statfs(debugfs, &st_fs) < 0)
139 return -ENOENT;
140 else if (st_fs.f_type != (long) DEBUGFS_MAGIC)
141 return -ENOENT;
142 return 0;
143}
144
145static char *tracepoint_id_to_name(u64 config)
146{
147 static char tracepoint_name[2 * MAX_EVENT_LENGTH];
148 DIR *sys_dir, *evt_dir;
149 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
150 struct stat st;
151 char id_buf[4];
152 int fd;
153 u64 id;
154 char evt_path[MAXPATHLEN];
155
156 if (valid_debugfs_mount(debugfs_path))
157 return "unkown";
158
159 sys_dir = opendir(debugfs_path);
160 if (!sys_dir)
161 goto cleanup;
162
163 for_each_subsystem(sys_dir, sys_dirent, sys_next, evt_path, st) {
164 evt_dir = opendir(evt_path);
165 if (!evt_dir)
166 goto cleanup;
167 for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next,
168 evt_path, st) {
169 snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id",
170 debugfs_path, sys_dirent.d_name,
171 evt_dirent.d_name);
172 fd = open(evt_path, O_RDONLY);
173 if (fd < 0)
174 continue;
175 if (read(fd, id_buf, sizeof(id_buf)) < 0) {
176 close(fd);
177 continue;
178 }
179 close(fd);
180 id = atoll(id_buf);
181 if (id == config) {
182 closedir(evt_dir);
183 closedir(sys_dir);
184 snprintf(tracepoint_name, 2 * MAX_EVENT_LENGTH,
185 "%s:%s", sys_dirent.d_name,
186 evt_dirent.d_name);
187 return tracepoint_name;
188 }
189 }
190 closedir(evt_dir);
191 }
192
193cleanup:
194 closedir(sys_dir);
195 return "unkown";
196}
197
113static int is_cache_op_valid(u8 cache_type, u8 cache_op) 198static int is_cache_op_valid(u8 cache_type, u8 cache_op)
114{ 199{
115 if (hw_cache_stat[cache_type] & COP(cache_op)) 200 if (hw_cache_stat[cache_type] & COP(cache_op))
@@ -177,6 +262,9 @@ char *event_name(int counter)
177 return sw_event_names[config]; 262 return sw_event_names[config];
178 return "unknown-software"; 263 return "unknown-software";
179 264
265 case PERF_TYPE_TRACEPOINT:
266 return tracepoint_id_to_name(config);
267
180 default: 268 default:
181 break; 269 break;
182 } 270 }
@@ -265,6 +353,53 @@ parse_generic_hw_event(const char **str, struct perf_counter_attr *attr)
265 return 1; 353 return 1;
266} 354}
267 355
356static int parse_tracepoint_event(const char **strp,
357 struct perf_counter_attr *attr)
358{
359 const char *evt_name;
360 char sys_name[MAX_EVENT_LENGTH];
361 char id_buf[4];
362 int fd;
363 unsigned int sys_length, evt_length;
364 u64 id;
365 char evt_path[MAXPATHLEN];
366
367 if (valid_debugfs_mount(debugfs_path))
368 return 0;
369
370 evt_name = strchr(*strp, ':');
371 if (!evt_name)
372 return 0;
373
374 sys_length = evt_name - *strp;
375 if (sys_length >= MAX_EVENT_LENGTH)
376 return 0;
377
378 strncpy(sys_name, *strp, sys_length);
379 sys_name[sys_length] = '\0';
380 evt_name = evt_name + 1;
381 evt_length = strlen(evt_name);
382 if (evt_length >= MAX_EVENT_LENGTH)
383 return 0;
384
385 snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path,
386 sys_name, evt_name);
387 fd = open(evt_path, O_RDONLY);
388 if (fd < 0)
389 return 0;
390
391 if (read(fd, id_buf, sizeof(id_buf)) < 0) {
392 close(fd);
393 return 0;
394 }
395 close(fd);
396 id = atoll(id_buf);
397 attr->config = id;
398 attr->type = PERF_TYPE_TRACEPOINT;
399 *strp = evt_name + evt_length;
400 return 1;
401}
402
268static int check_events(const char *str, unsigned int i) 403static int check_events(const char *str, unsigned int i)
269{ 404{
270 int n; 405 int n;
@@ -374,7 +509,8 @@ parse_event_modifier(const char **strp, struct perf_counter_attr *attr)
374 */ 509 */
375static int parse_event_symbols(const char **str, struct perf_counter_attr *attr) 510static int parse_event_symbols(const char **str, struct perf_counter_attr *attr)
376{ 511{
377 if (!(parse_raw_event(str, attr) || 512 if (!(parse_tracepoint_event(str, attr) ||
513 parse_raw_event(str, attr) ||
378 parse_numeric_event(str, attr) || 514 parse_numeric_event(str, attr) ||
379 parse_symbolic_event(str, attr) || 515 parse_symbolic_event(str, attr) ||
380 parse_generic_hw_event(str, attr))) 516 parse_generic_hw_event(str, attr)))
@@ -423,6 +559,42 @@ static const char * const event_type_descriptors[] = {
423}; 559};
424 560
425/* 561/*
562 * Print the events from <debugfs_mount_point>/tracing/events
563 */
564
565static void print_tracepoint_events(void)
566{
567 DIR *sys_dir, *evt_dir;
568 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
569 struct stat st;
570 char evt_path[MAXPATHLEN];
571
572 if (valid_debugfs_mount(debugfs_path))
573 return;
574
575 sys_dir = opendir(debugfs_path);
576 if (!sys_dir)
577 goto cleanup;
578
579 for_each_subsystem(sys_dir, sys_dirent, sys_next, evt_path, st) {
580 evt_dir = opendir(evt_path);
581 if (!evt_dir)
582 goto cleanup;
583 for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next,
584 evt_path, st) {
585 snprintf(evt_path, MAXPATHLEN, "%s:%s",
586 sys_dirent.d_name, evt_dirent.d_name);
587 fprintf(stderr, " %-40s [%s]\n", evt_path,
588 event_type_descriptors[PERF_TYPE_TRACEPOINT+1]);
589 }
590 closedir(evt_dir);
591 }
592
593cleanup:
594 closedir(sys_dir);
595}
596
597/*
426 * Print the help text for the event symbols: 598 * Print the help text for the event symbols:
427 */ 599 */
428void print_events(void) 600void print_events(void)
@@ -436,7 +608,7 @@ void print_events(void)
436 608
437 for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) { 609 for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) {
438 type = syms->type + 1; 610 type = syms->type + 1;
439 if (type > ARRAY_SIZE(event_type_descriptors)) 611 if (type >= ARRAY_SIZE(event_type_descriptors))
440 type = 0; 612 type = 0;
441 613
442 if (type != prev_type) 614 if (type != prev_type)
@@ -472,5 +644,7 @@ void print_events(void)
472 "rNNN"); 644 "rNNN");
473 fprintf(stderr, "\n"); 645 fprintf(stderr, "\n");
474 646
647 print_tracepoint_events();
648
475 exit(129); 649 exit(129);
476} 650}
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index e3d552908e60..1ea5d09b6eb1 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -3,6 +3,8 @@
3 * Parse symbolic events/counts passed in as options: 3 * Parse symbolic events/counts passed in as options:
4 */ 4 */
5 5
6struct option;
7
6extern int nr_counters; 8extern int nr_counters;
7 9
8extern struct perf_counter_attr attrs[MAX_COUNTERS]; 10extern struct perf_counter_attr attrs[MAX_COUNTERS];
@@ -15,3 +17,6 @@ extern int parse_events(const struct option *opt, const char *str, int unset);
15 17
16extern void print_events(void); 18extern void print_events(void);
17 19
20extern char debugfs_path[];
21extern int valid_debugfs_mount(const char *debugfs);
22
diff --git a/tools/perf/util/string.h b/tools/perf/util/string.h
index 3dca2f654cd0..bf39dfadfd24 100644
--- a/tools/perf/util/string.h
+++ b/tools/perf/util/string.h
@@ -5,4 +5,7 @@
5 5
6int hex2u64(const char *ptr, u64 *val); 6int hex2u64(const char *ptr, u64 *val);
7 7
8#define _STR(x) #x
9#define STR(x) _STR(x)
10
8#endif 11#endif
diff --git a/tools/perf/util/strlist.c b/tools/perf/util/strlist.c
index 025a78edfffe..7ad38171dc2b 100644
--- a/tools/perf/util/strlist.c
+++ b/tools/perf/util/strlist.c
@@ -64,6 +64,7 @@ int strlist__add(struct strlist *self, const char *new_entry)
64 64
65 rb_link_node(&sn->rb_node, parent, p); 65 rb_link_node(&sn->rb_node, parent, p);
66 rb_insert_color(&sn->rb_node, &self->entries); 66 rb_insert_color(&sn->rb_node, &self->entries);
67 ++self->nr_entries;
67 68
68 return 0; 69 return 0;
69} 70}
@@ -155,8 +156,9 @@ struct strlist *strlist__new(bool dupstr, const char *slist)
155 struct strlist *self = malloc(sizeof(*self)); 156 struct strlist *self = malloc(sizeof(*self));
156 157
157 if (self != NULL) { 158 if (self != NULL) {
158 self->entries = RB_ROOT; 159 self->entries = RB_ROOT;
159 self->dupstr = dupstr; 160 self->dupstr = dupstr;
161 self->nr_entries = 0;
160 if (slist && strlist__parse_list(self, slist) != 0) 162 if (slist && strlist__parse_list(self, slist) != 0)
161 goto out_error; 163 goto out_error;
162 } 164 }
@@ -182,3 +184,17 @@ void strlist__delete(struct strlist *self)
182 free(self); 184 free(self);
183 } 185 }
184} 186}
187
188struct str_node *strlist__entry(const struct strlist *self, unsigned int idx)
189{
190 struct rb_node *nd;
191
192 for (nd = rb_first(&self->entries); nd; nd = rb_next(nd)) {
193 struct str_node *pos = rb_entry(nd, struct str_node, rb_node);
194
195 if (!idx--)
196 return pos;
197 }
198
199 return NULL;
200}
diff --git a/tools/perf/util/strlist.h b/tools/perf/util/strlist.h
index 2fdcfee87586..921818e44a54 100644
--- a/tools/perf/util/strlist.h
+++ b/tools/perf/util/strlist.h
@@ -11,7 +11,8 @@ struct str_node {
11 11
12struct strlist { 12struct strlist {
13 struct rb_root entries; 13 struct rb_root entries;
14 bool dupstr; 14 unsigned int nr_entries;
15 bool dupstr;
15}; 16};
16 17
17struct strlist *strlist__new(bool dupstr, const char *slist); 18struct strlist *strlist__new(bool dupstr, const char *slist);
@@ -21,11 +22,17 @@ void strlist__remove(struct strlist *self, struct str_node *sn);
21int strlist__load(struct strlist *self, const char *filename); 22int strlist__load(struct strlist *self, const char *filename);
22int strlist__add(struct strlist *self, const char *str); 23int strlist__add(struct strlist *self, const char *str);
23 24
25struct str_node *strlist__entry(const struct strlist *self, unsigned int idx);
24bool strlist__has_entry(struct strlist *self, const char *entry); 26bool strlist__has_entry(struct strlist *self, const char *entry);
25 27
26static inline bool strlist__empty(const struct strlist *self) 28static inline bool strlist__empty(const struct strlist *self)
27{ 29{
28 return rb_first(&self->entries) == NULL; 30 return self->nr_entries == 0;
31}
32
33static inline unsigned int strlist__nr_entries(const struct strlist *self)
34{
35 return self->nr_entries;
29} 36}
30 37
31int strlist__parse_list(struct strlist *self, const char *s); 38int strlist__parse_list(struct strlist *self, const char *s);
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 4683b67b5ee4..28106059bf12 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -6,9 +6,15 @@
6#include <libelf.h> 6#include <libelf.h>
7#include <gelf.h> 7#include <gelf.h>
8#include <elf.h> 8#include <elf.h>
9#include <bfd.h>
9 10
10const char *sym_hist_filter; 11const char *sym_hist_filter;
11 12
13#ifndef DMGL_PARAMS
14#define DMGL_PARAMS (1 << 0) /* Include function args */
15#define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */
16#endif
17
12static struct symbol *symbol__new(u64 start, u64 len, 18static struct symbol *symbol__new(u64 start, u64 len,
13 const char *name, unsigned int priv_size, 19 const char *name, unsigned int priv_size,
14 u64 obj_start, int verbose) 20 u64 obj_start, int verbose)
@@ -65,6 +71,7 @@ struct dso *dso__new(const char *name, unsigned int sym_priv_size)
65 self->syms = RB_ROOT; 71 self->syms = RB_ROOT;
66 self->sym_priv_size = sym_priv_size; 72 self->sym_priv_size = sym_priv_size;
67 self->find_symbol = dso__find_symbol; 73 self->find_symbol = dso__find_symbol;
74 self->slen_calculated = 0;
68 } 75 }
69 76
70 return self; 77 return self;
@@ -373,36 +380,61 @@ static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
373 idx < nr_entries; \ 380 idx < nr_entries; \
374 ++idx, pos = gelf_getrela(reldata, idx, &pos_mem)) 381 ++idx, pos = gelf_getrela(reldata, idx, &pos_mem))
375 382
376static int dso__synthesize_plt_symbols(struct dso *self, Elf *elf, 383/*
377 GElf_Ehdr *ehdr, Elf_Scn *scn_dynsym, 384 * We need to check if we have a .dynsym, so that we can handle the
378 GElf_Shdr *shdr_dynsym, 385 * .plt, synthesizing its symbols, that aren't on the symtabs (be it
379 size_t dynsym_idx, int verbose) 386 * .dynsym or .symtab).
387 * And always look at the original dso, not at debuginfo packages, that
388 * have the PLT data stripped out (shdr_rel_plt.sh_type == SHT_NOBITS).
389 */
390static int dso__synthesize_plt_symbols(struct dso *self, int verbose)
380{ 391{
381 uint32_t nr_rel_entries, idx; 392 uint32_t nr_rel_entries, idx;
382 GElf_Sym sym; 393 GElf_Sym sym;
383 u64 plt_offset; 394 u64 plt_offset;
384 GElf_Shdr shdr_plt; 395 GElf_Shdr shdr_plt;
385 struct symbol *f; 396 struct symbol *f;
386 GElf_Shdr shdr_rel_plt; 397 GElf_Shdr shdr_rel_plt, shdr_dynsym;
387 Elf_Data *reldata, *syms, *symstrs; 398 Elf_Data *reldata, *syms, *symstrs;
388 Elf_Scn *scn_plt_rel, *scn_symstrs; 399 Elf_Scn *scn_plt_rel, *scn_symstrs, *scn_dynsym;
400 size_t dynsym_idx;
401 GElf_Ehdr ehdr;
389 char sympltname[1024]; 402 char sympltname[1024];
390 int nr = 0, symidx; 403 Elf *elf;
404 int nr = 0, symidx, fd, err = 0;
405
406 fd = open(self->name, O_RDONLY);
407 if (fd < 0)
408 goto out;
409
410 elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
411 if (elf == NULL)
412 goto out_close;
413
414 if (gelf_getehdr(elf, &ehdr) == NULL)
415 goto out_elf_end;
416
417 scn_dynsym = elf_section_by_name(elf, &ehdr, &shdr_dynsym,
418 ".dynsym", &dynsym_idx);
419 if (scn_dynsym == NULL)
420 goto out_elf_end;
391 421
392 scn_plt_rel = elf_section_by_name(elf, ehdr, &shdr_rel_plt, 422 scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt,
393 ".rela.plt", NULL); 423 ".rela.plt", NULL);
394 if (scn_plt_rel == NULL) { 424 if (scn_plt_rel == NULL) {
395 scn_plt_rel = elf_section_by_name(elf, ehdr, &shdr_rel_plt, 425 scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt,
396 ".rel.plt", NULL); 426 ".rel.plt", NULL);
397 if (scn_plt_rel == NULL) 427 if (scn_plt_rel == NULL)
398 return 0; 428 goto out_elf_end;
399 } 429 }
400 430
431 err = -1;
432
401 if (shdr_rel_plt.sh_link != dynsym_idx) 433 if (shdr_rel_plt.sh_link != dynsym_idx)
402 return 0; 434 goto out_elf_end;
403 435
404 if (elf_section_by_name(elf, ehdr, &shdr_plt, ".plt", NULL) == NULL) 436 if (elf_section_by_name(elf, &ehdr, &shdr_plt, ".plt", NULL) == NULL)
405 return 0; 437 goto out_elf_end;
406 438
407 /* 439 /*
408 * Fetch the relocation section to find the indexes to the GOT 440 * Fetch the relocation section to find the indexes to the GOT
@@ -410,19 +442,19 @@ static int dso__synthesize_plt_symbols(struct dso *self, Elf *elf,
410 */ 442 */
411 reldata = elf_getdata(scn_plt_rel, NULL); 443 reldata = elf_getdata(scn_plt_rel, NULL);
412 if (reldata == NULL) 444 if (reldata == NULL)
413 return -1; 445 goto out_elf_end;
414 446
415 syms = elf_getdata(scn_dynsym, NULL); 447 syms = elf_getdata(scn_dynsym, NULL);
416 if (syms == NULL) 448 if (syms == NULL)
417 return -1; 449 goto out_elf_end;
418 450
419 scn_symstrs = elf_getscn(elf, shdr_dynsym->sh_link); 451 scn_symstrs = elf_getscn(elf, shdr_dynsym.sh_link);
420 if (scn_symstrs == NULL) 452 if (scn_symstrs == NULL)
421 return -1; 453 goto out_elf_end;
422 454
423 symstrs = elf_getdata(scn_symstrs, NULL); 455 symstrs = elf_getdata(scn_symstrs, NULL);
424 if (symstrs == NULL) 456 if (symstrs == NULL)
425 return -1; 457 goto out_elf_end;
426 458
427 nr_rel_entries = shdr_rel_plt.sh_size / shdr_rel_plt.sh_entsize; 459 nr_rel_entries = shdr_rel_plt.sh_size / shdr_rel_plt.sh_entsize;
428 plt_offset = shdr_plt.sh_offset; 460 plt_offset = shdr_plt.sh_offset;
@@ -441,7 +473,7 @@ static int dso__synthesize_plt_symbols(struct dso *self, Elf *elf,
441 f = symbol__new(plt_offset, shdr_plt.sh_entsize, 473 f = symbol__new(plt_offset, shdr_plt.sh_entsize,
442 sympltname, self->sym_priv_size, 0, verbose); 474 sympltname, self->sym_priv_size, 0, verbose);
443 if (!f) 475 if (!f)
444 return -1; 476 goto out_elf_end;
445 477
446 dso__insert_symbol(self, f); 478 dso__insert_symbol(self, f);
447 ++nr; 479 ++nr;
@@ -459,19 +491,25 @@ static int dso__synthesize_plt_symbols(struct dso *self, Elf *elf,
459 f = symbol__new(plt_offset, shdr_plt.sh_entsize, 491 f = symbol__new(plt_offset, shdr_plt.sh_entsize,
460 sympltname, self->sym_priv_size, 0, verbose); 492 sympltname, self->sym_priv_size, 0, verbose);
461 if (!f) 493 if (!f)
462 return -1; 494 goto out_elf_end;
463 495
464 dso__insert_symbol(self, f); 496 dso__insert_symbol(self, f);
465 ++nr; 497 ++nr;
466 } 498 }
467 } else {
468 /*
469 * TODO: There are still one more shdr_rel_plt.sh_type
470 * I have to investigate, but probably should be ignored.
471 */
472 } 499 }
473 500
474 return nr; 501 err = 0;
502out_elf_end:
503 elf_end(elf);
504out_close:
505 close(fd);
506
507 if (err == 0)
508 return nr;
509out:
510 fprintf(stderr, "%s: problems reading %s PLT info.\n",
511 __func__, self->name);
512 return 0;
475} 513}
476 514
477static int dso__load_sym(struct dso *self, int fd, const char *name, 515static int dso__load_sym(struct dso *self, int fd, const char *name,
@@ -485,10 +523,9 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
485 GElf_Shdr shdr; 523 GElf_Shdr shdr;
486 Elf_Data *syms; 524 Elf_Data *syms;
487 GElf_Sym sym; 525 GElf_Sym sym;
488 Elf_Scn *sec, *sec_dynsym, *sec_strndx; 526 Elf_Scn *sec, *sec_strndx;
489 Elf *elf; 527 Elf *elf;
490 size_t dynsym_idx; 528 int nr = 0, kernel = !strcmp("[kernel]", self->name);
491 int nr = 0;
492 529
493 elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); 530 elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
494 if (elf == NULL) { 531 if (elf == NULL) {
@@ -504,32 +541,11 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
504 goto out_elf_end; 541 goto out_elf_end;
505 } 542 }
506 543
507 /*
508 * We need to check if we have a .dynsym, so that we can handle the
509 * .plt, synthesizing its symbols, that aren't on the symtabs (be it
510 * .dynsym or .symtab)
511 */
512 sec_dynsym = elf_section_by_name(elf, &ehdr, &shdr,
513 ".dynsym", &dynsym_idx);
514 if (sec_dynsym != NULL) {
515 nr = dso__synthesize_plt_symbols(self, elf, &ehdr,
516 sec_dynsym, &shdr,
517 dynsym_idx, verbose);
518 if (nr < 0)
519 goto out_elf_end;
520 }
521
522 /*
523 * But if we have a full .symtab (that is a superset of .dynsym) we
524 * should add the symbols not in the .dynsyn
525 */
526 sec = elf_section_by_name(elf, &ehdr, &shdr, ".symtab", NULL); 544 sec = elf_section_by_name(elf, &ehdr, &shdr, ".symtab", NULL);
527 if (sec == NULL) { 545 if (sec == NULL) {
528 if (sec_dynsym == NULL) 546 sec = elf_section_by_name(elf, &ehdr, &shdr, ".dynsym", NULL);
547 if (sec == NULL)
529 goto out_elf_end; 548 goto out_elf_end;
530
531 sec = sec_dynsym;
532 gelf_getshdr(sec, &shdr);
533 } 549 }
534 550
535 syms = elf_getdata(sec, NULL); 551 syms = elf_getdata(sec, NULL);
@@ -555,12 +571,17 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
555 nr_syms = shdr.sh_size / shdr.sh_entsize; 571 nr_syms = shdr.sh_size / shdr.sh_entsize;
556 572
557 memset(&sym, 0, sizeof(sym)); 573 memset(&sym, 0, sizeof(sym));
558 self->adjust_symbols = (ehdr.e_type == ET_EXEC || 574 if (!kernel) {
575 self->adjust_symbols = (ehdr.e_type == ET_EXEC ||
559 elf_section_by_name(elf, &ehdr, &shdr, 576 elf_section_by_name(elf, &ehdr, &shdr,
560 ".gnu.prelink_undo", 577 ".gnu.prelink_undo",
561 NULL) != NULL); 578 NULL) != NULL);
579 } else self->adjust_symbols = 0;
580
562 elf_symtab__for_each_symbol(syms, nr_syms, index, sym) { 581 elf_symtab__for_each_symbol(syms, nr_syms, index, sym) {
563 struct symbol *f; 582 struct symbol *f;
583 const char *name;
584 char *demangled;
564 u64 obj_start; 585 u64 obj_start;
565 struct section *section = NULL; 586 struct section *section = NULL;
566 int is_label = elf_sym__is_label(&sym); 587 int is_label = elf_sym__is_label(&sym);
@@ -599,10 +620,19 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
599 goto out_elf_end; 620 goto out_elf_end;
600 } 621 }
601 } 622 }
623 /*
624 * We need to figure out if the object was created from C++ sources
625 * DWARF DW_compile_unit has this, but we don't always have access
626 * to it...
627 */
628 name = elf_sym__name(&sym, symstrs);
629 demangled = bfd_demangle(NULL, name, DMGL_PARAMS | DMGL_ANSI);
630 if (demangled != NULL)
631 name = demangled;
602 632
603 f = symbol__new(sym.st_value, sym.st_size, 633 f = symbol__new(sym.st_value, sym.st_size, name,
604 elf_sym__name(&sym, symstrs),
605 self->sym_priv_size, obj_start, verbose); 634 self->sym_priv_size, obj_start, verbose);
635 free(demangled);
606 if (!f) 636 if (!f)
607 goto out_elf_end; 637 goto out_elf_end;
608 638
@@ -668,6 +698,11 @@ more:
668 if (!ret) 698 if (!ret)
669 goto more; 699 goto more;
670 700
701 if (ret > 0) {
702 int nr_plt = dso__synthesize_plt_symbols(self, verbose);
703 if (nr_plt > 0)
704 ret += nr_plt;
705 }
671out: 706out:
672 free(name); 707 free(name);
673 return ret; 708 return ret;
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 7918cffb23cd..2f92b21c712d 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -25,6 +25,7 @@ struct dso {
25 struct symbol *(*find_symbol)(struct dso *, u64 ip); 25 struct symbol *(*find_symbol)(struct dso *, u64 ip);
26 unsigned int sym_priv_size; 26 unsigned int sym_priv_size;
27 unsigned char adjust_symbols; 27 unsigned char adjust_symbols;
28 unsigned char slen_calculated;
28 char name[0]; 29 char name[0];
29}; 30};
30 31
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index b4be6071c105..68fe157d72fb 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -50,6 +50,7 @@
50#include <unistd.h> 50#include <unistd.h>
51#include <stdio.h> 51#include <stdio.h>
52#include <sys/stat.h> 52#include <sys/stat.h>
53#include <sys/statfs.h>
53#include <fcntl.h> 54#include <fcntl.h>
54#include <stddef.h> 55#include <stddef.h>
55#include <stdlib.h> 56#include <stdlib.h>
@@ -80,6 +81,7 @@
80#include <netdb.h> 81#include <netdb.h>
81#include <pwd.h> 82#include <pwd.h>
82#include <inttypes.h> 83#include <inttypes.h>
84#include "../../../include/linux/magic.h"
83 85
84#ifndef NO_ICONV 86#ifndef NO_ICONV
85#include <iconv.h> 87#include <iconv.h>