#include <errno.h>#include <inttypes.h>#include "util.h"#include "string2.h"#include <sys/param.h>#include <sys/types.h>#include <byteswap.h>#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <linux/compiler.h>#include <linux/list.h>#include <linux/kernel.h>#include <linux/bitops.h>#include <sys/stat.h>#include <sys/types.h>#include <sys/utsname.h>#include <unistd.h> #include "evlist.h"#include "evsel.h"#include "header.h"#include "memswap.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" #include "sane_ctype.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 const char perf_version_string[] = PERF_VERSION; 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);} void perf_header__clear_feat(struct perf_header *header, int feat){ clear_bit(feat, header->adds_features);} bool perf_header__has_feat(const struct perf_header *header, int feat){ return test_bit(feat, header->adds_features);} 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;} 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;} #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);} 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;} static int write_tracing_data(int fd, struct perf_header *h __maybe_unused, struct perf_evlist *evlist){ return read_tracing_data(fd, &evlist->entries);} 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;} 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);} 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);} 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);} 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);} 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;} 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;} 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; nrc = cpu__max_present_cpu(); 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));} 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;} static int write_cmdline(int fd, struct perf_header *h __maybe_unused, struct perf_evlist *evlist __maybe_unused){ char buf[MAXPATHLEN]; u32 n; int i, ret; /* actual path to perf binary */ ret = readlink("/proc/self/exe", buf, sizeof(buf) - 1); 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;} #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;} static void free_cpu_topo(struct cpu_topo *tp){ u32 i; if (!tp) return; for (i = 0 ; i < tp->core_sib; i++)Lines 1–500 of 3371. Load more
#include <errno.h> #include <inttypes.h> #include "util.h" #include "string2.h" #include <sys/param.h> #include <sys/types.h> #include <byteswap.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <linux/compiler.h> #include <linux/list.h> #include <linux/kernel.h> #include <linux/bitops.h> #include <sys/stat.h> #include <sys/types.h> #include <sys/utsname.h> #include <unistd.h> #include "evlist.h" #include "evsel.h" #include "header.h" #include "memswap.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" #include "sane_ctype.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 const char perf_version_string[] = PERF_VERSION; 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); } void perf_header__clear_feat(struct perf_header *header, int feat) { clear_bit(feat, header->adds_features); } bool perf_header__has_feat(const struct perf_header *header, int feat) { return test_bit(feat, header->adds_features); } 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; } 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; } #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); } 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; } static int write_tracing_data(int fd, struct perf_header *h __maybe_unused, struct perf_evlist *evlist) { return read_tracing_data(fd, &evlist->entries); } 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; } 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); } 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); } 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); } 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); } 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; } 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; } 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; nrc = cpu__max_present_cpu(); 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)); } 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; } static int write_cmdline(int fd, struct perf_header *h __maybe_unused, struct perf_evlist *evlist __maybe_unused) { char buf[MAXPATHLEN]; u32 n; int i, ret; /* actual path to perf binary */ ret = readlink("/proc/self/exe", buf, sizeof(buf) - 1); 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; } #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; } static void free_cpu_topo(struct cpu_topo *tp) { u32 i; if (!tp) return; for (i = 0 ; i < tp->core_sib; i++)