lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1342889135-14825-2-git-send-email-namhyung@kernel.org>
Date:	Sun, 22 Jul 2012 01:45:32 +0900
From:	Namhyung Kim <namhyung@...nel.org>
To:	Arnaldo Carvalho de Melo <acme@...stprotocols.net>
Cc:	Ingo Molnar <mingo@...nel.org>,
	Peter Zijlstra <peterz@...radead.org>,
	LKML <linux-kernel@...r.kernel.org>,
	Stephane Eranian <eranian@...gle.com>
Subject: [PATCH 2/5] perf header: add ->process callbacks to most of features

>From now for each feature information is processed and saved in perf
header so that it can be used wherever needed. The EVENT_DESC and
BRANCH_STACK features are exceptions since they need nothing to be done.

Cc: Stephane Eranian <eranian@...gle.com>
Signed-off-by: Namhyung Kim <namhyung@...nel.org>
---
 tools/perf/util/header.c |  360 ++++++++++++++++++++++++++++++++++++++++++++--
 tools/perf/util/header.h |   13 ++
 2 files changed, 363 insertions(+), 10 deletions(-)

diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 193aa089f9a6..1a30f2831616 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -1377,6 +1377,346 @@ static int process_build_id(struct perf_file_section *section,
 	return 0;
 }
 
+static int process_hostname(struct perf_file_section *section __used,
+			    struct perf_header *ph, int feat __used, int fd,
+			    void *data __used)
+{
+	ph->hostname = do_read_string(fd, ph);
+	return ph->hostname ? 0 : -ENOMEM;
+}
+
+static int process_osrelease(struct perf_file_section *section __used,
+			     struct perf_header *ph, int feat __used, int fd,
+			     void *data __used)
+{
+
+	ph->os_release = do_read_string(fd, ph);
+	return ph->os_release ? 0 : -ENOMEM;
+}
+
+static int process_arch(struct perf_file_section *section __used,
+			struct perf_header *ph, int feat __used, int fd,
+			void *data __used)
+{
+	ph->arch = do_read_string(fd, ph);
+	return ph->arch ? 0 : -ENOMEM;
+}
+
+static int process_cpudesc(struct perf_file_section *section __used,
+			   struct perf_header *ph, int feat __used, int fd,
+			   void *data __used)
+{
+	ph->cpu_desc = do_read_string(fd, ph);
+	return ph->cpu_desc ? 0 : -ENOMEM;
+}
+
+static int process_nrcpus(struct perf_file_section *section __used,
+			  struct perf_header *ph, int feat __used, int fd,
+			  void *data __used)
+{
+	ssize_t ret;
+	u32 nr;
+
+	ret = read(fd, &nr, sizeof(nr));
+	if (ret != (ssize_t)sizeof(nr))
+		nr = -1; /* interpreted as error */
+
+	if (ph->needs_swap)
+		nr = bswap_32(nr);
+
+	ph->nr_cpus_online = nr;
+
+	ret = read(fd, &nr, sizeof(nr));
+	if (ret != (ssize_t)sizeof(nr))
+		nr = -1; /* interpreted as error */
+
+	if (ph->needs_swap)
+		nr = bswap_32(nr);
+
+	ph->nr_cpus_avail = nr;
+
+	return 0;
+}
+
+static int process_version(struct perf_file_section *section __used,
+			   struct perf_header *ph, int feat __used, int fd,
+			   void *data __used)
+{
+	ph->version = do_read_string(fd, ph);
+	return ph->version ? 0 : -ENOMEM;
+}
+
+/* Each argv would be separated by a NULL character */
+static int process_cmdline(struct perf_file_section *section __used,
+			   struct perf_header *ph, int feat __used, int fd,
+			   void *data __used)
+{
+	ssize_t ret;
+	char *str, *tmp;
+	u32 nr, i;
+	char *cmdline = NULL;
+	size_t len = 0;
+
+	ret = read(fd, &nr, sizeof(nr));
+	if (ret != (ssize_t)sizeof(nr))
+		return -1;
+
+	if (ph->needs_swap)
+		nr = bswap_32(nr);
+
+	ph->cmdline_argc = nr;
+
+	for (i = 0; i < nr; i++) {
+		str = do_read_string(fd, ph);
+		if (!str)
+			goto error;
+
+		tmp = realloc(cmdline, len + strlen(str) + 1);
+		if (!tmp)
+			goto error;
+		cmdline = tmp;
+
+		/* include null character at the end */
+		strcpy(cmdline + len, str);
+
+		len += strlen(str) + 1;
+		free(str);
+	}
+	ph->cmdline = cmdline;
+	return 0;
+
+error:
+	free(cmdline);
+	free(str);
+	return -1;
+}
+
+#define TOPO_STR_LEN  ((size_t) 256)
+#define TOPO_STR_DELIM ':'
+
+#define check_topo_len(topo, allocated, used, len)			\
+({									\
+	if (len > allocated - used) {					\
+		char *tmp = realloc(topo, allocated + TOPO_STR_LEN);	\
+		if (!tmp)						\
+			goto error;					\
+		topo = tmp;						\
+		allocated += TOPO_STR_LEN;				\
+	}								\
+})
+
+/*
+ * The topology string looks like below (':' is used for delimiter):
+ *
+ * 	"NR_CORE_SIBLINGS(N):SIBLING[0]:SIBLING[1]:...:SIBLING[N-1]\n"
+ *	"NR_THREAD_SIBLINGS(M):SIBLING[0]:SIBLING[1]:...:SIBLING[M-1]\n"
+ */
+static int process_cpu_topology(struct perf_file_section *section __used,
+				struct perf_header *ph, int feat __used,
+				int fd,	void *data __used)
+{
+	ssize_t ret;
+	u32 nr, i;
+	char *str;
+	char buf[128];
+	char *topo = NULL;
+	size_t allocated = 0, used, len;
+
+	ret = read(fd, &nr, sizeof(nr));
+	if (ret != (ssize_t)sizeof(nr))
+		return -1;
+
+	if (ph->needs_swap)
+		nr = bswap_32(nr);
+
+	allocated = TOPO_STR_LEN;
+	topo = malloc(TOPO_STR_LEN);
+	if (!topo)
+		return -ENOMEM;
+
+	/* core siblings */
+	used = scnprintf(topo, allocated, "%u", nr);
+
+	for (i = 0; i < nr; i++) {
+		str = do_read_string(fd, ph);
+		if (!str)
+			goto error;
+
+		len = strlen(str) + 1;
+		check_topo_len(topo, allocated, used, len);
+
+		scnprintf(topo + used, allocated - used, "%c%s",
+			  TOPO_STR_DELIM, str);
+		used += len;
+		free(str);
+	}
+	check_topo_len(topo, allocated, used, 1);
+	scnprintf(topo + used, allocated - used, "\n");
+	used++;
+
+	/* thread siblings */
+	ret = read(fd, &nr, sizeof(nr));
+	if (ret != (ssize_t)sizeof(nr))
+		goto error;
+
+	if (ph->needs_swap)
+		nr = bswap_32(nr);
+
+	len = scnprintf(buf, sizeof(buf), "%u", nr);
+	check_topo_len(topo, allocated, used, len);
+
+	strcat(topo, buf);
+	used += len;
+
+	for (i = 0; i < nr; i++) {
+		str = do_read_string(fd, ph);
+		if (!str)
+			goto error;
+
+		len = strlen(str) + 1;
+		check_topo_len(topo, allocated, used, len);
+
+		scnprintf(topo + used, allocated - used, "%c%s",
+			  TOPO_STR_DELIM, str);
+		used += len;
+		free(str);
+	}
+	check_topo_len(topo, allocated, used, 1);
+	scnprintf(topo + used, allocated - used, "\n");
+
+	ph->cpu_topology = topo;
+	return 0;
+
+error:
+	free(topo);
+	return -1;
+}
+
+/*
+ * The topology string looks like below (':' is used for delimiter):
+ *
+ *	"NR_NODES(N)\n
+ *	"NODE_NUM(0):MEM_TOTAL:MEM_FREE:CPULIST\n"
+ *	"NODE_NUM(1):MEM_TOTAL:MEM_FREE:CPULIST\n"
+ *	...
+ *	"NODE_NUM(N-1):MEM_TOTAL:MEM_FREE:CPULIST\n"
+ */
+static int process_numa_topology(struct perf_file_section *section __used,
+				 struct perf_header *ph, int feat __used,
+				 int fd, void *data __used)
+{
+	ssize_t ret;
+	u32 nr, node, i;
+	char *str;
+	uint64_t mem_total, mem_free;
+	char *topo = NULL;
+	size_t allocated = 0, used, len;
+
+	/* nr nodes */
+	ret = read(fd, &nr, sizeof(nr));
+	if (ret != (ssize_t)sizeof(nr))
+		goto error;
+
+	if (ph->needs_swap)
+		nr = bswap_32(nr);
+
+	allocated = TOPO_STR_LEN;
+	topo = malloc(TOPO_STR_LEN);
+	if (!topo)
+		return -ENOMEM;
+
+	used = scnprintf(topo, allocated, "%u\n", nr);
+
+	for (i = 0; i < nr; i++) {
+		char buf[128];
+
+		/* node number */
+		ret = read(fd, &node, sizeof(node));
+		if (ret != (ssize_t)sizeof(node))
+			goto error;
+
+		if (ph->needs_swap)
+			node = bswap_32(node);
+
+		len = scnprintf(buf, sizeof(buf), "%u%c", node, TOPO_STR_DELIM);
+		check_topo_len(topo, allocated, used, len);
+
+		scnprintf(topo + used, allocated - used, "%s", buf);
+		used += len;
+
+		ret = read(fd, &mem_total, sizeof(u64));
+		if (ret != sizeof(u64))
+			goto error;
+
+		if (ph->needs_swap)
+			mem_total = bswap_64(mem_total);
+
+		len = scnprintf(buf, sizeof(buf), "%"PRIu64"%c",
+				mem_total, TOPO_STR_DELIM);
+		check_topo_len(topo, allocated, used, len);
+
+		scnprintf(topo + used, allocated - used, "%s", buf);
+		used += len;
+
+		ret = read(fd, &mem_free, sizeof(u64));
+		if (ret != sizeof(u64))
+			goto error;
+
+		if (ph->needs_swap)
+			mem_free = bswap_64(mem_free);
+
+		len = scnprintf(buf, sizeof(buf), "%"PRIu64"%c",
+				mem_total, TOPO_STR_DELIM);
+		check_topo_len(topo, allocated, used, len);
+
+		scnprintf(topo + used, allocated - used, "%s", buf);
+		used += len;
+
+		str = do_read_string(fd, ph);
+		if (!str)
+			goto error;
+
+		len = strlen(str) + 1;
+		check_topo_len(topo, allocated, used, len);
+
+		scnprintf(topo + used, allocated - used, "%s\n", str);
+		used += len;
+		free(str);
+	}
+
+	ph->numa_topology = topo;
+	return 0;
+error:
+	free(topo);
+	return -1;
+}
+
+static int process_cpuid(struct perf_file_section *section __used,
+			 struct perf_header *ph, int feat __used, int fd,
+			 void *data __used)
+{
+	ph->cpuid = do_read_string(fd, ph);
+	return ph->cpuid ? 0 : -ENOMEM;
+}
+
+static int process_total_mem(struct perf_file_section *section __used,
+			     struct perf_header *ph, int feat __used, int fd,
+			     void *data __used)
+{
+	uint64_t mem;
+	ssize_t ret;
+
+	ret = read(fd, &mem, sizeof(mem));
+	if (ret != sizeof(mem))
+		return -1;
+
+	if (ph->needs_swap)
+		mem = bswap_64(mem);
+
+	ph->total_mem = mem;
+	return 0;
+}
+
 struct feature_ops {
 	int (*write)(int fd, struct perf_header *h, struct perf_evlist *evlist);
 	void (*print)(struct perf_header *h, int fd, FILE *fp);
@@ -1393,7 +1733,7 @@ struct feature_ops {
 		.process = process_##func }
 #define FEAT_OPF(n, func) \
 	[n] = { .name = #n, .write = write_##func, .print = print_##func, \
-		.full_only = true }
+		.process = process_##func, .full_only = true }
 
 /* feature_ops not implemented: */
 #define print_tracing_data	NULL
@@ -1402,16 +1742,16 @@ struct feature_ops {
 static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
 	FEAT_OPP(HEADER_TRACING_DATA,	tracing_data),
 	FEAT_OPP(HEADER_BUILD_ID,	build_id),
-	FEAT_OPA(HEADER_HOSTNAME,	hostname),
-	FEAT_OPA(HEADER_OSRELEASE,	osrelease),
-	FEAT_OPA(HEADER_VERSION,	version),
-	FEAT_OPA(HEADER_ARCH,		arch),
-	FEAT_OPA(HEADER_NRCPUS,		nrcpus),
-	FEAT_OPA(HEADER_CPUDESC,	cpudesc),
-	FEAT_OPA(HEADER_CPUID,		cpuid),
-	FEAT_OPA(HEADER_TOTAL_MEM,	total_mem),
+	FEAT_OPP(HEADER_HOSTNAME,	hostname),
+	FEAT_OPP(HEADER_OSRELEASE,	osrelease),
+	FEAT_OPP(HEADER_VERSION,	version),
+	FEAT_OPP(HEADER_ARCH,		arch),
+	FEAT_OPP(HEADER_NRCPUS,		nrcpus),
+	FEAT_OPP(HEADER_CPUDESC,	cpudesc),
+	FEAT_OPP(HEADER_CPUID,		cpuid),
+	FEAT_OPP(HEADER_TOTAL_MEM,	total_mem),
 	FEAT_OPA(HEADER_EVENT_DESC,	event_desc),
-	FEAT_OPA(HEADER_CMDLINE,	cmdline),
+	FEAT_OPP(HEADER_CMDLINE,	cmdline),
 	FEAT_OPF(HEADER_CPU_TOPOLOGY,	cpu_topology),
 	FEAT_OPF(HEADER_NUMA_TOPOLOGY,	numa_topology),
 	FEAT_OPA(HEADER_BRANCH_STACK,	branch_stack),
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 2d42b3e1826f..6e4f14eb3c95 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -66,6 +66,19 @@ struct perf_header {
 	u64			event_offset;
 	u64			event_size;
 	DECLARE_BITMAP(adds_features, HEADER_FEAT_BITS);
+	char			*hostname;
+	char			*os_release;
+	char			*version;
+	char			*arch;
+	u32			nr_cpus_online;
+	u32			nr_cpus_avail;
+	char			*cpu_desc;
+	char			*cpuid;
+	u64			total_mem;
+	int			cmdline_argc;
+	char			*cmdline;
+	char			*cpu_topology;
+	char			*numa_topology;
 };
 
 struct perf_evlist;
-- 
1.7.9.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ