Release 4.10 tools/perf/util/header.c
#include "util.h"
#include <sys/types.h>
#include <byteswap.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <linux/list.h>
#include <linux/kernel.h>
#include <linux/bitops.h>
#include <sys/utsname.h>
#include "evlist.h"
#include "evsel.h"
#include "header.h"
#include "../perf.h"
#include "trace-event.h"
#include "session.h"
#include "symbol.h"
#include "debug.h"
#include "cpumap.h"
#include "pmu.h"
#include "vdso.h"
#include "strbuf.h"
#include "build-id.h"
#include "data.h"
#include <api/fs/fs.h>
#include "asm/bug.h"
/*
* magic2 = "PERFILE2"
* must be a numerical value to let the endianness
* determine the memory layout. That way we are able
* to detect endianness when reading the perf.data file
* back.
*
* we check for legacy (PERFFILE) format.
*/
static const char *__perf_magic1 = "PERFFILE";
static const u64 __perf_magic2 = 0x32454c4946524550ULL;
static const u64 __perf_magic2_sw = 0x50455246494c4532ULL;
#define PERF_MAGIC __perf_magic2
struct perf_file_attr {
struct perf_event_attr attr;
struct perf_file_section ids;
};
void perf_header__set_feat(struct perf_header *header, int feat)
{
set_bit(feat, header->adds_features);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
arnaldo carvalho de melo | arnaldo carvalho de melo | 22 | 100.00% | 2 | 100.00% |
| Total | 22 | 100.00% | 2 | 100.00% |
void perf_header__clear_feat(struct perf_header *header, int feat)
{
clear_bit(feat, header->adds_features);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
arnaldo carvalho de melo | arnaldo carvalho de melo | 22 | 100.00% | 2 | 100.00% |
| Total | 22 | 100.00% | 2 | 100.00% |
bool perf_header__has_feat(const struct perf_header *header, int feat)
{
return test_bit(feat, header->adds_features);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
arnaldo carvalho de melo | arnaldo carvalho de melo | 24 | 100.00% | 2 | 100.00% |
| Total | 24 | 100.00% | 2 | 100.00% |
static int do_write(int fd, const void *buf, size_t size)
{
while (size) {
int ret = write(fd, buf, size);
if (ret < 0)
return -errno;
size -= ret;
buf += ret;
}
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
peter zijlstra | peter zijlstra | 47 | 83.93% | 1 | 33.33% |
arnaldo carvalho de melo | arnaldo carvalho de melo | 9 | 16.07% | 2 | 66.67% |
| Total | 56 | 100.00% | 3 | 100.00% |
int write_padded(int fd, const void *bf, size_t count, size_t count_aligned)
{
static const char zero_buf[NAME_ALIGN];
int err = do_write(fd, bf, count);
if (!err)
err = do_write(fd, zero_buf, count_aligned - count);
return err;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
arnaldo carvalho de melo | arnaldo carvalho de melo | 60 | 100.00% | 1 | 100.00% |
| Total | 60 | 100.00% | 1 | 100.00% |
#define string_size(str) \
(PERF_ALIGN((strlen(str) + 1), NAME_ALIGN) + sizeof(u32))
static int do_write_string(int fd, const char *str)
{
u32 len, olen;
int ret;
olen = strlen(str) + 1;
len = PERF_ALIGN(olen, NAME_ALIGN);
/* write len, incl. \0 */
ret = do_write(fd, &len, sizeof(len));
if (ret < 0)
return ret;
return write_padded(fd, str, olen, len);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
stephane eranian | stephane eranian | 26 | 33.77% | 1 | 10.00% |
arnaldo carvalho de melo | arnaldo carvalho de melo | 25 | 32.47% | 5 | 50.00% |
frederic weisbecker | frederic weisbecker | 23 | 29.87% | 2 | 20.00% |
hirofumi ogawa | hirofumi ogawa | 2 | 2.60% | 1 | 10.00% |
irina tirdea | irina tirdea | 1 | 1.30% | 1 | 10.00% |
| Total | 77 | 100.00% | 10 | 100.00% |
static char *do_read_string(int fd, struct perf_header *ph)
{
ssize_t sz, ret;
u32 len;
char *buf;
sz = readn(fd, &len, sizeof(len));
if (sz < (ssize_t)sizeof(len))
return NULL;
if (ph->needs_swap)
len = bswap_32(len);
buf = malloc(len);
if (!buf)
return NULL;
ret = readn(fd, buf, len);
if (ret == (ssize_t)len) {
/*
* strings are padded by zeroes
* thus the actual strlen of buf
* may be less than len
*/
return buf;
}
free(buf);
return NULL;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
stephane eranian | stephane eranian | 107 | 89.92% | 1 | 33.33% |
arnaldo carvalho de melo | arnaldo carvalho de melo | 10 | 8.40% | 1 | 33.33% |
namhyung kim | namhyung kim | 2 | 1.68% | 1 | 33.33% |
| Total | 119 | 100.00% | 3 | 100.00% |
static int write_tracing_data(int fd, struct perf_header *h __maybe_unused,
struct perf_evlist *evlist)
{
return read_tracing_data(fd, &evlist->entries);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
robert richter | robert richter | 19 | 61.29% | 1 | 25.00% |
stephane eranian | stephane eranian | 11 | 35.48% | 2 | 50.00% |
irina tirdea | irina tirdea | 1 | 3.23% | 1 | 25.00% |
| Total | 31 | 100.00% | 4 | 100.00% |
static int write_build_id(int fd, struct perf_header *h,
struct perf_evlist *evlist __maybe_unused)
{
struct perf_session *session;
int err;
session = container_of(h, struct perf_session, header);
if (!perf_session__read_build_ids(session, true))
return -1;
err = perf_session__write_buildid_table(session, fd);
if (err < 0) {
pr_debug("failed to write buildid table\n");
return err;
}
perf_session__cache_build_ids(session);
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
robert richter | robert richter | 58 | 66.67% | 2 | 40.00% |
stephane eranian | stephane eranian | 26 | 29.89% | 1 | 20.00% |
namhyung kim | namhyung kim | 2 | 2.30% | 1 | 20.00% |
irina tirdea | irina tirdea | 1 | 1.15% | 1 | 20.00% |
| Total | 87 | 100.00% | 5 | 100.00% |
static int write_hostname(int fd, struct perf_header *h __maybe_unused,
struct perf_evlist *evlist __maybe_unused)
{
struct utsname uts;
int ret;
ret = uname(&uts);
if (ret < 0)
return -1;
return do_write_string(fd, uts.nodename);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
robert richter | robert richter | 38 | 67.86% | 1 | 33.33% |
stephane eranian | stephane eranian | 16 | 28.57% | 1 | 33.33% |
irina tirdea | irina tirdea | 2 | 3.57% | 1 | 33.33% |
| Total | 56 | 100.00% | 3 | 100.00% |
static int write_osrelease(int fd, struct perf_header *h __maybe_unused,
struct perf_evlist *evlist __maybe_unused)
{
struct utsname uts;
int ret;
ret = uname(&uts);
if (ret < 0)
return -1;
return do_write_string(fd, uts.release);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
stephane eranian | stephane eranian | 35 | 62.50% | 1 | 33.33% |
robert richter | robert richter | 19 | 33.93% | 1 | 33.33% |
irina tirdea | irina tirdea | 2 | 3.57% | 1 | 33.33% |
| Total | 56 | 100.00% | 3 | 100.00% |
static int write_arch(int fd, struct perf_header *h __maybe_unused,
struct perf_evlist *evlist __maybe_unused)
{
struct utsname uts;
int ret;
ret = uname(&uts);
if (ret < 0)
return -1;
return do_write_string(fd, uts.machine);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
robert richter | robert richter | 40 | 71.43% | 1 | 33.33% |
stephane eranian | stephane eranian | 14 | 25.00% | 1 | 33.33% |
irina tirdea | irina tirdea | 2 | 3.57% | 1 | 33.33% |
| Total | 56 | 100.00% | 3 | 100.00% |
static int write_version(int fd, struct perf_header *h __maybe_unused,
struct perf_evlist *evlist __maybe_unused)
{
return do_write_string(fd, perf_version_string);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
robert richter | robert richter | 18 | 62.07% | 1 | 33.33% |
stephane eranian | stephane eranian | 9 | 31.03% | 1 | 33.33% |
irina tirdea | irina tirdea | 2 | 6.90% | 1 | 33.33% |
| Total | 29 | 100.00% | 3 | 100.00% |
static int __write_cpudesc(int fd, const char *cpuinfo_proc)
{
FILE *file;
char *buf = NULL;
char *s, *p;
const char *search = cpuinfo_proc;
size_t len = 0;
int ret = -1;
if (!search)
return -1;
file = fopen("/proc/cpuinfo", "r");
if (!file)
return -1;
while (getline(&buf, &len, file) > 0) {
ret = strncmp(buf, search, strlen(search));
if (!ret)
break;
}
if (ret) {
ret = -1;
goto done;
}
s = buf;
p = strchr(buf, ':');
if (p && *(p+1) == ' ' && *(p+2))
s = p + 2;
p = strchr(s, '\n');
if (p)
*p = '\0';
/* squash extra space characters (branding string) */
p = s;
while (*p) {
if (isspace(*p)) {
char *r = p + 1;
char *q = r;
*p = ' ';
while (*q && isspace(*q))
q++;
if (q != (p+1))
while ((*r++ = *q++));
}
p++;
}
ret = do_write_string(fd, s);
done:
free(buf);
fclose(file);
return ret;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
robert richter | robert richter | 146 | 50.52% | 1 | 25.00% |
stephane eranian | stephane eranian | 131 | 45.33% | 1 | 25.00% |
wang nan | wang nan | 12 | 4.15% | 2 | 50.00% |
| Total | 289 | 100.00% | 4 | 100.00% |
static int write_cpudesc(int fd, struct perf_header *h __maybe_unused,
struct perf_evlist *evlist __maybe_unused)
{
#ifndef CPUINFO_PROC
#define CPUINFO_PROC {"model name", }
#endif
const char *cpuinfo_procs[] = CPUINFO_PROC;
unsigned int i;
for (i = 0; i < ARRAY_SIZE(cpuinfo_procs); i++) {
int ret;
ret = __write_cpudesc(fd, cpuinfo_procs[i]);
if (ret >= 0)
return ret;
}
return -1;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
wang nan | wang nan | 88 | 100.00% | 1 | 100.00% |
| Total | 88 | 100.00% | 1 | 100.00% |
static int write_nrcpus(int fd, struct perf_header *h __maybe_unused,
struct perf_evlist *evlist __maybe_unused)
{
long nr;
u32 nrc, nra;
int ret;
nr = sysconf(_SC_NPROCESSORS_CONF);
if (nr < 0)
return -1;
nrc = (u32)(nr & UINT_MAX);
nr = sysconf(_SC_NPROCESSORS_ONLN);
if (nr < 0)
return -1;
nra = (u32)(nr & UINT_MAX);
ret = do_write(fd, &nrc, sizeof(nrc));
if (ret < 0)
return ret;
return do_write(fd, &nra, sizeof(nra));
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
robert richter | robert richter | 84 | 66.67% | 1 | 33.33% |
stephane eranian | stephane eranian | 40 | 31.75% | 1 | 33.33% |
irina tirdea | irina tirdea | 2 | 1.59% | 1 | 33.33% |
| Total | 126 | 100.00% | 3 | 100.00% |
static int write_event_desc(int fd, struct perf_header *h __maybe_unused,
struct perf_evlist *evlist)
{
struct perf_evsel *evsel;
u32 nre, nri, sz;
int ret;
nre = evlist->nr_entries;
/*
* write number of events
*/
ret = do_write(fd, &nre, sizeof(nre));
if (ret < 0)
return ret;
/*
* size of perf_event_attr struct
*/
sz = (u32)sizeof(evsel->attr);
ret = do_write(fd, &sz, sizeof(sz));
if (ret < 0)
return ret;
evlist__for_each_entry(evlist, evsel) {
ret = do_write(fd, &evsel->attr, sz);
if (ret < 0)
return ret;
/*
* write number of unique id per event
* there is one id per instance of an event
*
* copy into an nri to be independent of the
* type of ids,
*/
nri = evsel->ids;
ret = do_write(fd, &nri, sizeof(nri));
if (ret < 0)
return ret;
/*
* write event string as passed on cmdline
*/
ret = do_write_string(fd, perf_evsel__name(evsel));
if (ret < 0)
return ret;
/*
* write unique ids for this event
*/
ret = do_write(fd, evsel->id, evsel->ids * sizeof(u64));
if (ret < 0)
return ret;
}
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
stephane eranian | stephane eranian | 111 | 50.45% | 1 | 12.50% |
robert richter | robert richter | 100 | 45.45% | 2 | 25.00% |
arnaldo carvalho de melo | arnaldo carvalho de melo | 4 | 1.82% | 3 | 37.50% |
namhyung kim | namhyung kim | 4 | 1.82% | 1 | 12.50% |
irina tirdea | irina tirdea | 1 | 0.45% | 1 | 12.50% |
| Total | 220 | 100.00% | 8 | 100.00% |
static int write_cmdline(int fd, struct perf_header *h __maybe_unused,
struct perf_evlist *evlist __maybe_unused)
{
char buf[MAXPATHLEN];
char proc[32];
u32 n;
int i, ret;
/*
* actual atual path to perf binary
*/
sprintf(proc, "/proc/%d/exe", getpid());
ret = readlink(proc, buf, sizeof(buf));
if (ret <= 0)
return -1;
/* readlink() does not add null termination */
buf[ret] = '\0';
/* account for binary path */
n = perf_env.nr_cmdline + 1;
ret = do_write(fd, &n, sizeof(n));
if (ret < 0)
return ret;
ret = do_write_string(fd, buf);
if (ret < 0)
return ret;
for (i = 0 ; i < perf_env.nr_cmdline; i++) {
ret = do_write_string(fd, perf_env.cmdline_argv[i]);
if (ret < 0)
return ret;
}
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
robert richter | robert richter | 110 | 61.80% | 1 | 25.00% |
stephane eranian | stephane eranian | 55 | 30.90% | 1 | 25.00% |
arnaldo carvalho de melo | arnaldo carvalho de melo | 11 | 6.18% | 1 | 25.00% |
irina tirdea | irina tirdea | 2 | 1.12% | 1 | 25.00% |
| Total | 178 | 100.00% | 4 | 100.00% |
#define CORE_SIB_FMT \
"/sys/devices/system/cpu/cpu%d/topology/core_siblings_list"
#define THRD_SIB_FMT \
"/sys/devices/system/cpu/cpu%d/topology/thread_siblings_list"
struct cpu_topo {
u32 cpu_nr;
u32 core_sib;
u32 thread_sib;
char **core_siblings;
char **thread_siblings;
};
static int build_cpu_topo(struct cpu_topo *tp, int cpu)
{
FILE *fp;
char filename[MAXPATHLEN];
char *buf = NULL, *p;
size_t len = 0;
ssize_t sret;
u32 i = 0;
int ret = -1;
sprintf(filename, CORE_SIB_FMT, cpu);
fp = fopen(filename, "r");
if (!fp)
goto try_threads;
sret = getline(&buf, &len, fp);
fclose(fp);
if (sret <= 0)
goto try_threads;
p = strchr(buf, '\n');
if (p)
*p = '\0';
for (i = 0; i < tp->core_sib; i++) {
if (!strcmp(buf, tp->core_siblings[i]))
break;
}
if (i == tp->core_sib) {
tp->core_siblings[i] = buf;
tp->core_sib++;
buf = NULL;
len = 0;
}
ret = 0;
try_threads:
sprintf(filename, THRD_SIB_FMT, cpu);
fp = fopen(filename, "r");
if (!fp)
goto done;
if (getline(&buf, &len, fp) <= 0)
goto done;
p = strchr(buf, '\n');
if (p)
*p = '\0';
for (i = 0; i < tp->thread_sib; i++) {
if (!strcmp(buf, tp->thread_siblings[i]))
break;
}
if (i == tp->thread_sib) {
tp->thread_siblings[i] = buf;
tp->thread_sib++;
buf = NULL;
}
ret = 0;
done:
if(fp)
fclose(fp);
free(buf);
return ret;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
robert richter | robert richter | 237 | 69.71% | 1 | 33.33% |
stephane eranian | stephane eranian | 103 | 30.29% | 2 | 66.67% |
| Total | 340 | 100.00% | 3 | 100.00% |
static void free_cpu_topo(struct cpu_topo *tp)
{
u32 i;
if (!tp)
return;
for (i = 0 ; i < tp->core_sib; i++)
zfree(&tp->core_siblings[i]);
for (i = 0 ; i < tp->thread_sib; i++)
zfree(&tp->thread_siblings[i]);
free(tp);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
stephane eranian | stephane eranian | 37 | 48.05% | 1 | 33.33% |
robert richter | robert richter | 36 | 46.75% | 1 | 33.33% |
arnaldo carvalho de melo | arnaldo carvalho de melo | 4 | 5.19% | 1 | 33.33% |
| Total | 77 | 100.00% | 3 | 100.00% |
static struct cpu_topo *build_cpu_topology(void)
{
struct cpu_topo *tp;
void *addr;
u32 nr, i;
size_t sz;
long ncpus;
int ret = -1;
ncpus = sysconf(_SC_NPROCESSORS_CONF);
if (ncpus < 0)
return NULL;
nr = (u32)(ncpus & UINT_MAX);
sz = nr * sizeof(char *);
addr = calloc(1, sizeof(*tp) + 2 * sz);
if (!addr)
return NULL;
tp = addr;
tp->cpu_nr = nr;
addr += sizeof(*tp);
tp->core_siblings = addr;
addr += sz;
tp->thread_siblings = addr;
for (i = 0; i < nr; i++) {
ret = build_cpu_topo(tp, i);
if (ret < 0)
break;
}
if (ret) {
free_cpu_topo(tp);
tp = NULL;
}
return tp;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
robert richter | robert richter | 106 | 58.56% | 1 | 33.33% |
stephane eranian | stephane eranian | 69 | 38.12% | 1 | 33.33% |
kan liang | kan liang | 6 | 3.31% | 1 | 33.33% |
| Total | 181 | 100.00% | 3 | 100.00% |
static int write_cpu_topology(int fd, struct perf_header *h __maybe_unused,
struct perf_evlist *evlist __maybe_unused)
{
struct cpu_topo *tp;
u32 i;
int ret, j;
tp = build_cpu_topology();
if (!tp)
return -1;
ret = do_write(fd, &tp->core_sib, sizeof(tp->core_sib));
if (ret < 0)
goto done;
for (i = 0; i < tp->core_sib; i++) {
ret = do_write_string(fd, tp->core_siblings[i]);
if (ret < 0)
goto done;
}
ret = do_write(fd, &tp->thread_sib, sizeof(tp->thread_sib));
if (ret < 0)
goto done;
for (i = 0; i < tp->thread_sib; i++) {
ret = do_write_string(fd, tp->thread_siblings[i]);
if (ret < 0)
break;
}
ret = perf_env__read_cpu_topology_map(&perf_env);
if (ret < 0)
goto done;
for (j = 0; j < perf_env.nr_cpus_avail; j++) {
ret = do_write(fd, &perf_env.cpu[j].core_id,
sizeof(perf_env.cpu[j].core_id));
if (ret < 0)
return ret;
ret = do_write(fd, &perf_env.cpu[j].socket_id,
sizeof(perf_env.cpu[j].socket_id));
if (ret < 0)
return ret;
}
done:
free_cpu_topo(tp);
return ret;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
robert richter | robert richter | 102 | 33.77% | 1 | 20.00% |
stephane eranian | stephane eranian | 86 | 28.48% | 1 | 20.00% |
kan liang | kan liang | 59 | 19.54% | 1 | 20.00% |
arnaldo carvalho de melo | arnaldo carvalho de melo | 53 | 17.55% | 1 | 20.00% |
irina tirdea | irina tirdea | 2 | 0.66% | 1 | 20.00% |
| Total | 302 | 100.00% | 5 | 100.00% |
static int write_total_mem(int fd, struct perf_header *h __maybe_unused,
struct perf_evlist *evlist __maybe_unused)
{
char *buf = NULL;
FILE *fp;
size_t len = 0;
int ret = -1, n;
uint64_t mem;
fp = fopen("/proc/meminfo", "r");
if (!fp)
return -1;
while (getline(&buf, &len, fp) > 0) {
ret = strncmp(buf, "MemTotal:", 9);
if (!ret)
break;
}
if (!ret) {
n = sscanf(buf, "%*s %"PRIu64, &mem);
if (n == 1)
ret = do_write(fd, &mem, sizeof(mem));
} else
ret = -1;
free(buf);
fclose(fp);
return ret;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
robert richter | robert richter | 112 | 70.44% | 1 | 25.00% |
stephane eranian | stephane eranian | 39 | 24.53% | 1 | 25.00% |
wang nan | wang nan | 6 | 3.77% | 1 | 25.00% |
irina tirdea | irina tirdea | 2 | 1.26% | 1 | 25.00% |
| Total | 159 | 100.00% | 4 | 100.00% |
static int write_topo_node(int fd, int node)
{
char str[MAXPATHLEN];
char field[32];
char *buf = NULL, *p;
size_t len = 0;
FILE *fp;
u64 mem_total, mem_free, mem;
int ret = -1;
sprintf(str, "/sys/devices/system/node/node%d/meminfo", node);
fp = fopen(str,