Skip to content

Commit

Permalink
Merge branch 'perf-tools-for-linus' of git://github.com/acmel/linux
Browse files Browse the repository at this point in the history
* 'perf-tools-for-linus' of git://github.com/acmel/linux:
  perf tools: Add support for disabling -Werror via WERROR=0
  perf top: Fix userspace sample addr map offset
  perf symbols: Fix issue with binaries using 16-bytes buildids (v2)
  perf tool: Fix endianness handling of u32 data in samples
  perf sort: Fix symbol sort output by separating unresolved samples by type
  perf symbols: Synthesize anonymous mmap events
  perf record: Create events initially disabled and enable after init
  perf symbols: Add some heuristics for choosing the best duplicate symbol
  perf symbols: Preserve symbol scope when parsing /proc/kallsyms
  perf symbols: /proc/kallsyms does not sort module symbols
  perf symbols: Fix ppc64 SEGV in dso__load_sym with debuginfo files
  perf probe: Fix regression of variable finder
  • Loading branch information
Linus Torvalds committed Sep 23, 2011
2 parents f35f3dc + 9e59e09 commit eab8bcb
Show file tree
Hide file tree
Showing 13 changed files with 209 additions and 57 deletions.
9 changes: 8 additions & 1 deletion tools/perf/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ endif
# Define EXTRA_CFLAGS=-m64 or EXTRA_CFLAGS=-m32 as appropriate for cross-builds.
#
# Define NO_DWARF if you do not want debug-info analysis feature at all.
#
# Define WERROR=0 to disable treating any warnings as errors.

$(OUTPUT)PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE
@$(SHELL_PATH) util/PERF-VERSION-GEN $(OUTPUT)
Expand Down Expand Up @@ -63,6 +65,11 @@ ifeq ($(ARCH),x86_64)
endif
endif

# Treat warnings as errors unless directed not to
ifneq ($(WERROR),0)
CFLAGS_WERROR := -Werror
endif

#
# Include saner warnings here, which can catch bugs:
#
Expand Down Expand Up @@ -95,7 +102,7 @@ ifndef PERF_DEBUG
CFLAGS_OPTIMIZE = -O6
endif

CFLAGS = -fno-omit-frame-pointer -ggdb3 -Wall -Wextra -std=gnu99 -Werror $(CFLAGS_OPTIMIZE) -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS)
CFLAGS = -fno-omit-frame-pointer -ggdb3 -Wall -Wextra -std=gnu99 $(CFLAGS_WERROR) $(CFLAGS_OPTIMIZE) -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS)
EXTLIBS = -lpthread -lrt -lelf -lm
ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
ALL_LDFLAGS = $(LDFLAGS)
Expand Down
3 changes: 3 additions & 0 deletions tools/perf/builtin-record.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ static void config_attr(struct perf_evsel *evsel, struct perf_evlist *evlist)
struct perf_event_attr *attr = &evsel->attr;
int track = !evsel->idx; /* only the first counter needs these */

attr->disabled = 1;
attr->inherit = !no_inherit;
attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
PERF_FORMAT_TOTAL_TIME_RUNNING |
Expand Down Expand Up @@ -671,6 +672,8 @@ static int __cmd_record(int argc, const char **argv)
}
}

perf_evlist__enable(evsel_list);

/*
* Let the child rip
*/
Expand Down
2 changes: 1 addition & 1 deletion tools/perf/builtin-test.c
Original file line number Diff line number Diff line change
Expand Up @@ -561,7 +561,7 @@ static int test__basic_mmap(void)
}

err = perf_event__parse_sample(event, attr.sample_type, sample_size,
false, &sample);
false, &sample, false);
if (err) {
pr_err("Can't parse sample, err = %d\n", err);
goto out_munmap;
Expand Down
9 changes: 5 additions & 4 deletions tools/perf/builtin-top.c
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,8 @@ static void __zero_source_counters(struct sym_entry *syme)
symbol__annotate_zero_histograms(sym);
}

static void record_precise_ip(struct sym_entry *syme, int counter, u64 ip)
static void record_precise_ip(struct sym_entry *syme, struct map *map,
int counter, u64 ip)
{
struct annotation *notes;
struct symbol *sym;
Expand All @@ -205,8 +206,8 @@ static void record_precise_ip(struct sym_entry *syme, int counter, u64 ip)
if (pthread_mutex_trylock(&notes->lock))
return;

ip = syme->map->map_ip(syme->map, ip);
symbol__inc_addr_samples(sym, syme->map, counter, ip);
ip = map->map_ip(map, ip);
symbol__inc_addr_samples(sym, map, counter, ip);

pthread_mutex_unlock(&notes->lock);
}
Expand Down Expand Up @@ -810,7 +811,7 @@ static void perf_event__process_sample(const union perf_event *event,
evsel = perf_evlist__id2evsel(top.evlist, sample->id);
assert(evsel != NULL);
syme->count[evsel->idx]++;
record_precise_ip(syme, evsel->idx, ip);
record_precise_ip(syme, al.map, evsel->idx, ip);
pthread_mutex_lock(&top.active_symbols_lock);
if (list_empty(&syme->node) || !syme->node.next) {
static bool first = true;
Expand Down
5 changes: 5 additions & 0 deletions tools/perf/util/event.c
Original file line number Diff line number Diff line change
Expand Up @@ -169,12 +169,17 @@ static int perf_event__synthesize_mmap_events(union perf_event *event,
continue;
pbf += n + 3;
if (*pbf == 'x') { /* vm_exec */
char anonstr[] = "//anon\n";
char *execname = strchr(bf, '/');

/* Catch VDSO */
if (execname == NULL)
execname = strstr(bf, "[vdso]");

/* Catch anonymous mmaps */
if ((execname == NULL) && !strstr(bf, "["))
execname = anonstr;

if (execname == NULL)
continue;

Expand Down
2 changes: 1 addition & 1 deletion tools/perf/util/event.h
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,6 @@ const char *perf_event__name(unsigned int id);

int perf_event__parse_sample(const union perf_event *event, u64 type,
int sample_size, bool sample_id_all,
struct perf_sample *sample);
struct perf_sample *sample, bool swapped);

#endif /* __PERF_RECORD_H */
13 changes: 13 additions & 0 deletions tools/perf/util/evlist.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,19 @@ void perf_evlist__disable(struct perf_evlist *evlist)
}
}

void perf_evlist__enable(struct perf_evlist *evlist)
{
int cpu, thread;
struct perf_evsel *pos;

for (cpu = 0; cpu < evlist->cpus->nr; cpu++) {
list_for_each_entry(pos, &evlist->entries, node) {
for (thread = 0; thread < evlist->threads->nr; thread++)
ioctl(FD(pos, cpu, thread), PERF_EVENT_IOC_ENABLE);
}
}
}

int perf_evlist__alloc_pollfd(struct perf_evlist *evlist)
{
int nfds = evlist->cpus->nr * evlist->threads->nr * evlist->nr_entries;
Expand Down
1 change: 1 addition & 0 deletions tools/perf/util/evlist.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ int perf_evlist__mmap(struct perf_evlist *evlist, int pages, bool overwrite);
void perf_evlist__munmap(struct perf_evlist *evlist);

void perf_evlist__disable(struct perf_evlist *evlist);
void perf_evlist__enable(struct perf_evlist *evlist);

static inline void perf_evlist__set_maps(struct perf_evlist *evlist,
struct cpu_map *cpus,
Expand Down
54 changes: 43 additions & 11 deletions tools/perf/util/evsel.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
* Released under the GPL v2. (and only v2, not any later version)
*/

#include <byteswap.h>
#include "asm/bug.h"
#include "evsel.h"
#include "evlist.h"
#include "util.h"
Expand Down Expand Up @@ -342,10 +344,20 @@ static bool sample_overlap(const union perf_event *event,

int perf_event__parse_sample(const union perf_event *event, u64 type,
int sample_size, bool sample_id_all,
struct perf_sample *data)
struct perf_sample *data, bool swapped)
{
const u64 *array;

/*
* used for cross-endian analysis. See git commit 65014ab3
* for why this goofiness is needed.
*/
union {
u64 val64;
u32 val32[2];
} u;


data->cpu = data->pid = data->tid = -1;
data->stream_id = data->id = data->time = -1ULL;

Expand All @@ -366,9 +378,16 @@ int perf_event__parse_sample(const union perf_event *event, u64 type,
}

if (type & PERF_SAMPLE_TID) {
u32 *p = (u32 *)array;
data->pid = p[0];
data->tid = p[1];
u.val64 = *array;
if (swapped) {
/* undo swap of u64, then swap on individual u32s */
u.val64 = bswap_64(u.val64);
u.val32[0] = bswap_32(u.val32[0]);
u.val32[1] = bswap_32(u.val32[1]);
}

data->pid = u.val32[0];
data->tid = u.val32[1];
array++;
}

Expand All @@ -395,8 +414,15 @@ int perf_event__parse_sample(const union perf_event *event, u64 type,
}

if (type & PERF_SAMPLE_CPU) {
u32 *p = (u32 *)array;
data->cpu = *p;

u.val64 = *array;
if (swapped) {
/* undo swap of u64, then swap on individual u32s */
u.val64 = bswap_64(u.val64);
u.val32[0] = bswap_32(u.val32[0]);
}

data->cpu = u.val32[0];
array++;
}

Expand All @@ -423,18 +449,24 @@ int perf_event__parse_sample(const union perf_event *event, u64 type,
}

if (type & PERF_SAMPLE_RAW) {
u32 *p = (u32 *)array;
u.val64 = *array;
if (WARN_ONCE(swapped,
"Endianness of raw data not corrected!\n")) {
/* undo swap of u64, then swap on individual u32s */
u.val64 = bswap_64(u.val64);
u.val32[0] = bswap_32(u.val32[0]);
u.val32[1] = bswap_32(u.val32[1]);
}

if (sample_overlap(event, array, sizeof(u32)))
return -EFAULT;

data->raw_size = *p;
p++;
data->raw_size = u.val32[0];

if (sample_overlap(event, p, data->raw_size))
if (sample_overlap(event, &u.val32[1], data->raw_size))
return -EFAULT;

data->raw_data = p;
data->raw_data = &u.val32[1];
}

return 0;
Expand Down
2 changes: 1 addition & 1 deletion tools/perf/util/probe-finder.c
Original file line number Diff line number Diff line change
Expand Up @@ -659,7 +659,7 @@ static int find_variable(Dwarf_Die *sc_die, struct probe_finder *pf)
if (!die_find_variable_at(&pf->cu_die, pf->pvar->var, 0, &vr_die))
ret = -ENOENT;
}
if (ret == 0)
if (ret >= 0)
ret = convert_variable(&vr_die, pf);

if (ret < 0)
Expand Down
3 changes: 2 additions & 1 deletion tools/perf/util/session.h
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,8 @@ static inline int perf_session__parse_sample(struct perf_session *session,
{
return perf_event__parse_sample(event, session->sample_type,
session->sample_size,
session->sample_id_all, sample);
session->sample_id_all, sample,
session->header.needs_swap);
}

struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
Expand Down
10 changes: 8 additions & 2 deletions tools/perf/util/sort.c
Original file line number Diff line number Diff line change
Expand Up @@ -151,11 +151,17 @@ sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
{
u64 ip_l, ip_r;

if (!left->ms.sym && !right->ms.sym)
return right->level - left->level;

if (!left->ms.sym || !right->ms.sym)
return cmp_null(left->ms.sym, right->ms.sym);

if (left->ms.sym == right->ms.sym)
return 0;

ip_l = left->ms.sym ? left->ms.sym->start : left->ip;
ip_r = right->ms.sym ? right->ms.sym->start : right->ip;
ip_l = left->ms.sym->start;
ip_r = right->ms.sym->start;

return (int64_t)(ip_r - ip_l);
}
Expand Down
Loading

0 comments on commit eab8bcb

Please sign in to comment.