Merge branch 'perf/core' of git://git.kernel.org/pub/scm/linux/kernel/git/frederic/random-tracing into perf/core
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 739c441..0ef5cfe 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -377,9 +377,9 @@
 LIB_H += util/include/linux/string.h
 LIB_H += util/include/linux/types.h
 LIB_H += util/include/asm/asm-offsets.h
-LIB_H += util/include/asm/bitops.h
 LIB_H += util/include/asm/bug.h
 LIB_H += util/include/asm/byteorder.h
+LIB_H += util/include/asm/hweight.h
 LIB_H += util/include/asm/swab.h
 LIB_H += util/include/asm/system.h
 LIB_H += util/include/asm/uaccess.h
@@ -435,7 +435,6 @@
 LIB_OBJS += $(OUTPUT)util/rbtree.o
 LIB_OBJS += $(OUTPUT)util/bitmap.o
 LIB_OBJS += $(OUTPUT)util/hweight.o
-LIB_OBJS += $(OUTPUT)util/find_next_bit.o
 LIB_OBJS += $(OUTPUT)util/run-command.o
 LIB_OBJS += $(OUTPUT)util/quote.o
 LIB_OBJS += $(OUTPUT)util/strbuf.o
@@ -491,6 +490,7 @@
 BUILTIN_OBJS += $(OUTPUT)builtin-lock.o
 BUILTIN_OBJS += $(OUTPUT)builtin-kvm.o
 BUILTIN_OBJS += $(OUTPUT)builtin-test.o
+BUILTIN_OBJS += $(OUTPUT)builtin-inject.o
 
 PERFLIBS = $(LIB_FILE)
 
@@ -948,19 +948,6 @@
 $(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS
 	$(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
 
-# some perf warning policies can't fit to lib/bitmap.c, eg: it warns about variable shadowing
-# from <string.h> that comes from kernel headers wrapping.
-KBITMAP_FLAGS=`echo $(ALL_CFLAGS) | sed s/-Wshadow// | sed s/-Wswitch-default// | sed s/-Wextra//`
-
-$(OUTPUT)util/bitmap.o: ../../lib/bitmap.c $(OUTPUT)PERF-CFLAGS
-	$(QUIET_CC)$(CC) -o $@ -c $(KBITMAP_FLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
-
-$(OUTPUT)util/hweight.o: ../../lib/hweight.c $(OUTPUT)PERF-CFLAGS
-	$(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
-
-$(OUTPUT)util/find_next_bit.o: ../../lib/find_next_bit.c $(OUTPUT)PERF-CFLAGS
-	$(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
-
 $(OUTPUT)util/scripting-engines/trace-event-perl.o: util/scripting-engines/trace-event-perl.c $(OUTPUT)PERF-CFLAGS
 	$(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow $<
 
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index b57dbcf..ee154b5 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -554,7 +554,7 @@
 	int ret;
 	struct perf_session *session;
 
-	session = perf_session__new(input_name, O_RDONLY, force);
+	session = perf_session__new(input_name, O_RDONLY, force, false);
 	if (session == NULL)
 		return -ENOMEM;
 
diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
index 7dc3b2e..44a47e1 100644
--- a/tools/perf/builtin-buildid-list.c
+++ b/tools/perf/builtin-buildid-list.c
@@ -39,7 +39,7 @@
 	int err = -1;
 	struct perf_session *session;
 
-	session = perf_session__new(input_name, O_RDONLY, force);
+	session = perf_session__new(input_name, O_RDONLY, force, false);
 	if (session == NULL)
 		return -1;
 
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 207e860..4cce68f 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -156,8 +156,8 @@
 	int ret, i;
 	struct perf_session *session[2];
 
-	session[0] = perf_session__new(input_old, O_RDONLY, force);
-	session[1] = perf_session__new(input_new, O_RDONLY, force);
+	session[0] = perf_session__new(input_old, O_RDONLY, force, false);
+	session[1] = perf_session__new(input_new, O_RDONLY, force, false);
 	if (session[0] == NULL || session[1] == NULL)
 		return -ENOMEM;
 
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
new file mode 100644
index 0000000..59e981a
--- /dev/null
+++ b/tools/perf/builtin-inject.c
@@ -0,0 +1,228 @@
+/*
+ * builtin-inject.c
+ *
+ * Builtin inject command: Examine the live mode (stdin) event stream
+ * and repipe it to stdout while optionally injecting additional
+ * events into it.
+ */
+#include "builtin.h"
+
+#include "perf.h"
+#include "util/session.h"
+#include "util/debug.h"
+
+#include "util/parse-options.h"
+
+static char		const *input_name = "-";
+static bool		inject_build_ids;
+
+static int event__repipe(event_t *event __used,
+			 struct perf_session *session __used)
+{
+	uint32_t size;
+	void *buf = event;
+
+	size = event->header.size;
+
+	while (size) {
+		int ret = write(STDOUT_FILENO, buf, size);
+		if (ret < 0)
+			return -errno;
+
+		size -= ret;
+		buf += ret;
+	}
+
+	return 0;
+}
+
+static int event__repipe_mmap(event_t *self, struct perf_session *session)
+{
+	int err;
+
+	err = event__process_mmap(self, session);
+	event__repipe(self, session);
+
+	return err;
+}
+
+static int event__repipe_task(event_t *self, struct perf_session *session)
+{
+	int err;
+
+	err = event__process_task(self, session);
+	event__repipe(self, session);
+
+	return err;
+}
+
+static int event__repipe_tracing_data(event_t *self,
+				      struct perf_session *session)
+{
+	int err;
+
+	event__repipe(self, session);
+	err = event__process_tracing_data(self, session);
+
+	return err;
+}
+
+static int dso__read_build_id(struct dso *self)
+{
+	if (self->has_build_id)
+		return 0;
+
+	if (filename__read_build_id(self->long_name, self->build_id,
+				    sizeof(self->build_id)) > 0) {
+		self->has_build_id = true;
+		return 0;
+	}
+
+	return -1;
+}
+
+static int dso__inject_build_id(struct dso *self, struct perf_session *session)
+{
+	u16 misc = PERF_RECORD_MISC_USER;
+	struct machine *machine;
+	int err;
+
+	if (dso__read_build_id(self) < 0) {
+		pr_debug("no build_id found for %s\n", self->long_name);
+		return -1;
+	}
+
+	machine = perf_session__find_host_machine(session);
+	if (machine == NULL) {
+		pr_err("Can't find machine for session\n");
+		return -1;
+	}
+
+	if (self->kernel)
+		misc = PERF_RECORD_MISC_KERNEL;
+
+	err = event__synthesize_build_id(self, misc, event__repipe,
+					 machine, session);
+	if (err) {
+		pr_err("Can't synthesize build_id event for %s\n", self->long_name);
+		return -1;
+	}
+
+	return 0;
+}
+
+static int event__inject_buildid(event_t *event, struct perf_session *session)
+{
+	struct addr_location al;
+	struct thread *thread;
+	u8 cpumode;
+
+	cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
+
+	thread = perf_session__findnew(session, event->ip.pid);
+	if (thread == NULL) {
+		pr_err("problem processing %d event, skipping it.\n",
+		       event->header.type);
+		goto repipe;
+	}
+
+	thread__find_addr_map(thread, session, cpumode, MAP__FUNCTION,
+			      event->ip.pid, event->ip.ip, &al);
+
+	if (al.map != NULL) {
+		if (!al.map->dso->hit) {
+			al.map->dso->hit = 1;
+			if (map__load(al.map, NULL) >= 0) {
+				dso__inject_build_id(al.map->dso, session);
+				/*
+				 * If this fails, too bad, let the other side
+				 * account this as unresolved.
+				 */
+			} else
+				pr_warning("no symbols found in %s, maybe "
+					   "install a debug package?\n",
+					   al.map->dso->long_name);
+		}
+	}
+
+repipe:
+	event__repipe(event, session);
+	return 0;
+}
+
+struct perf_event_ops inject_ops = {
+	.sample		= event__repipe,
+	.mmap		= event__repipe,
+	.comm		= event__repipe,
+	.fork		= event__repipe,
+	.exit		= event__repipe,
+	.lost		= event__repipe,
+	.read		= event__repipe,
+	.throttle	= event__repipe,
+	.unthrottle	= event__repipe,
+	.attr		= event__repipe,
+	.event_type 	= event__repipe,
+	.tracing_data 	= event__repipe,
+	.build_id 	= event__repipe,
+};
+
+extern volatile int session_done;
+
+static void sig_handler(int sig __attribute__((__unused__)))
+{
+	session_done = 1;
+}
+
+static int __cmd_inject(void)
+{
+	struct perf_session *session;
+	int ret = -EINVAL;
+
+	signal(SIGINT, sig_handler);
+
+	if (inject_build_ids) {
+		inject_ops.sample	= event__inject_buildid;
+		inject_ops.mmap		= event__repipe_mmap;
+		inject_ops.fork		= event__repipe_task;
+		inject_ops.tracing_data	= event__repipe_tracing_data;
+	}
+
+	session = perf_session__new(input_name, O_RDONLY, false, true);
+	if (session == NULL)
+		return -ENOMEM;
+
+	ret = perf_session__process_events(session, &inject_ops);
+
+	perf_session__delete(session);
+
+	return ret;
+}
+
+static const char * const report_usage[] = {
+	"perf inject [<options>]",
+	NULL
+};
+
+static const struct option options[] = {
+	OPT_BOOLEAN('b', "inject build-ids", &inject_build_ids,
+		    "Inject build-ids into the output stream"),
+	OPT_INCR('v', "verbose", &verbose,
+		 "be more verbose (show build ids, etc)"),
+	OPT_END()
+};
+
+int cmd_inject(int argc, const char **argv, const char *prefix __used)
+{
+	argc = parse_options(argc, argv, options, report_usage, 0);
+
+	/*
+	 * Any (unrecognized) arguments left?
+	 */
+	if (argc)
+		usage_with_options(report_usage, options);
+
+	if (symbol__init() < 0)
+		return -1;
+
+	return __cmd_inject();
+}
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index ee05dba..31f60a2 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -492,7 +492,7 @@
 static int __cmd_kmem(void)
 {
 	int err = -EINVAL;
-	struct perf_session *session = perf_session__new(input_name, O_RDONLY, 0);
+	struct perf_session *session = perf_session__new(input_name, O_RDONLY, 0, false);
 	if (session == NULL)
 		return -ENOMEM;
 
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index ce27675..6605000 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -818,7 +818,7 @@
 
 static int read_events(void)
 {
-	session = perf_session__new(input_name, O_RDONLY, 0);
+	session = perf_session__new(input_name, O_RDONLY, 0, false);
 	if (!session)
 		die("Initializing perf session failed\n");
 
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 83b308a..ac989e9 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -446,13 +446,6 @@
 
 		process_buildids();
 		perf_header__write(&session->header, output, true);
-	} else {
-		int err;
-
-		err = event__synthesize_build_ids(process_synthesized_event,
-						  session);
-		if (err < 0)
-			pr_err("Couldn't synthesize build ids.\n");
 	}
 }
 
@@ -555,7 +548,7 @@
 	}
 
 	session = perf_session__new(output_name, O_WRONLY,
-				    write_mode == WRITE_FORCE);
+				    write_mode == WRITE_FORCE, false);
 	if (session == NULL) {
 		pr_err("Not enough memory for reading perf file header\n");
 		return -1;
@@ -673,12 +666,15 @@
 						     nr_counters,
 						     process_synthesized_event,
 						     session);
-		if (err <= 0) {
-			pr_err("Couldn't record tracing data.\n");
-			return err;
-		}
-
-		advance_output(err);
+		/*
+		 * FIXME err <= 0 here actually means that there were no tracepoints
+		 * so its not really an error, just that we don't need to synthesize
+		 * anything.
+		 * We really have to return this more properly and also propagate
+		 * errors that now are calling die()
+		 */
+		if (err > 0)
+			advance_output(err);
 	}
 
 	machine = perf_session__find_host_machine(session);
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index f1b46eb..0152b54 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -289,7 +289,7 @@
 
 	signal(SIGINT, sig_handler);
 
-	session = perf_session__new(input_name, O_RDONLY, force);
+	session = perf_session__new(input_name, O_RDONLY, force, false);
 	if (session == NULL)
 		return -ENOMEM;
 
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 94453f1..aef6ed0 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -1660,7 +1660,7 @@
 static int read_events(void)
 {
 	int err = -EINVAL;
-	struct perf_session *session = perf_session__new(input_name, O_RDONLY, 0);
+	struct perf_session *session = perf_session__new(input_name, O_RDONLY, 0, false);
 	if (session == NULL)
 		return -ENOMEM;
 
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index c35aa44..5a52ed9 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -936,7 +936,7 @@
 
 static int __cmd_timechart(void)
 {
-	struct perf_session *session = perf_session__new(input_name, O_RDONLY, 0);
+	struct perf_session *session = perf_session__new(input_name, O_RDONLY, 0, false);
 	int ret = -EINVAL;
 
 	if (session == NULL)
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index d95281f..3de3977 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -1287,7 +1287,7 @@
 	 * FIXME: perf_session__new should allow passing a O_MMAP, so that all this
 	 * mmap reading, etc is encapsulated in it. Use O_WRONLY for now.
 	 */
-	struct perf_session *session = perf_session__new(NULL, O_WRONLY, false);
+	struct perf_session *session = perf_session__new(NULL, O_WRONLY, false, false);
 	if (session == NULL)
 		return -ENOMEM;
 
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 77f556f..9c483e9 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -661,7 +661,7 @@
 	if (!script_name)
 		setup_pager();
 
-	session = perf_session__new(input_name, O_RDONLY, 0);
+	session = perf_session__new(input_name, O_RDONLY, 0, false);
 	if (session == NULL)
 		return -ENOMEM;
 
diff --git a/tools/perf/builtin.h b/tools/perf/builtin.h
index 34a8a9a..921245b 100644
--- a/tools/perf/builtin.h
+++ b/tools/perf/builtin.h
@@ -34,5 +34,6 @@
 extern int cmd_lock(int argc, const char **argv, const char *prefix);
 extern int cmd_kvm(int argc, const char **argv, const char *prefix);
 extern int cmd_test(int argc, const char **argv, const char *prefix);
+extern int cmd_inject(int argc, const char **argv, const char *prefix);
 
 #endif
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 5ff9b5b..08e0e5d 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -309,6 +309,7 @@
 		{ "lock",	cmd_lock,	0 },
 		{ "kvm",	cmd_kvm,	0 },
 		{ "test",	cmd_test,	0 },
+		{ "inject",	cmd_inject,	0 },
 	};
 	unsigned int i;
 	static const char ext[] = STRIP_EXTENSION;
diff --git a/tools/perf/util/bitmap.c b/tools/perf/util/bitmap.c
new file mode 100644
index 0000000..5e230ac
--- /dev/null
+++ b/tools/perf/util/bitmap.c
@@ -0,0 +1,21 @@
+/*
+ * From lib/bitmap.c
+ * Helper functions for bitmap.h.
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2.  See the file COPYING for more details.
+ */
+#include <linux/bitmap.h>
+
+int __bitmap_weight(const unsigned long *bitmap, int bits)
+{
+	int k, w = 0, lim = bits/BITS_PER_LONG;
+
+	for (k = 0; k < lim; k++)
+		w += hweight_long(bitmap[k]);
+
+	if (bits % BITS_PER_LONG)
+		w += hweight_long(bitmap[k] & BITMAP_LAST_WORD_MASK(bits));
+
+	return w;
+}
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 6227dc4..79da0e5 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -713,10 +713,18 @@
 
 	dso = __dsos__findnew(head, filename);
 	if (dso != NULL) {
+		char sbuild_id[BUILD_ID_SIZE * 2 + 1];
+
 		dso__set_build_id(dso, &bev->build_id);
-			if (filename[0] == '[')
-				dso->kernel = dso_type;
-		}
+
+		if (filename[0] == '[')
+			dso->kernel = dso_type;
+
+		build_id__sprintf(dso->build_id, sizeof(dso->build_id),
+				  sbuild_id);
+		pr_debug("build id event received for %s: %s\n",
+			 dso->long_name, sbuild_id);
+	}
 
 	err = 0;
 out:
@@ -767,7 +775,7 @@
 
 	switch (feat) {
 	case HEADER_TRACE_INFO:
-		trace_report(fd);
+		trace_report(fd, false);
 		break;
 
 	case HEADER_BUILD_ID:
@@ -782,12 +790,16 @@
 }
 
 static int perf_file_header__read_pipe(struct perf_pipe_file_header *self,
-				       struct perf_header *ph, int fd)
+				       struct perf_header *ph, int fd,
+				       bool repipe)
 {
 	if (do_read(fd, self, sizeof(*self)) <= 0 ||
 	    memcmp(&self->magic, __perf_magic, sizeof(self->magic)))
 		return -1;
 
+	if (repipe && do_write(STDOUT_FILENO, self, sizeof(*self)) < 0)
+		return -1;
+
 	if (self->size != sizeof(*self)) {
 		u64 size = bswap_64(self->size);
 
@@ -805,7 +817,8 @@
 	struct perf_header *self = &session->header;
 	struct perf_pipe_file_header f_header;
 
-	if (perf_file_header__read_pipe(&f_header, self, fd) < 0) {
+	if (perf_file_header__read_pipe(&f_header, self, fd,
+					session->repipe) < 0) {
 		pr_debug("incompatible file format\n");
 		return -EINVAL;
 	}
@@ -1096,12 +1109,17 @@
 	lseek(session->fd, offset + sizeof(struct tracing_data_event),
 	      SEEK_SET);
 
-	size_read = trace_report(session->fd);
+	size_read = trace_report(session->fd, session->repipe);
 
 	padding = ALIGN(size_read, sizeof(u64)) - size_read;
 
 	if (read(session->fd, buf, padding) < 0)
 		die("reading input file");
+	if (session->repipe) {
+		int retw = write(STDOUT_FILENO, buf, padding);
+		if (retw <= 0 || retw != padding)
+			die("repiping tracing data padding");
+	}
 
 	if (size_read + padding != size)
 		die("tracing data size mismatch");
@@ -1110,7 +1128,8 @@
 }
 
 int event__synthesize_build_id(struct dso *pos, u16 misc,
-			       event__handler_t process, struct machine *machine,
+			       event__handler_t process,
+			       struct machine *machine,
 			       struct perf_session *session)
 {
 	event_t ev;
@@ -1136,67 +1155,6 @@
 	return err;
 }
 
-static int __event_synthesize_build_ids(struct list_head *head, u16 misc,
-					event__handler_t process,
-					struct machine *machine,
-					struct perf_session *session)
-{
-	struct dso *pos;
-
-	dsos__for_each_with_build_id(pos, head) {
-		int err;
-		if (!pos->hit)
-			continue;
-
-		err = event__synthesize_build_id(pos, misc, process,
-						 machine, session);
-		if (err < 0)
-			return err;
-	}
-
-	return 0;
-}
-
-int event__synthesize_build_ids(event__handler_t process,
-				struct perf_session *session)
-{
-	int err = 0;
-	u16 kmisc, umisc;
-	struct machine *pos;
-	struct rb_node *nd;
-
-	if (!dsos__read_build_ids(&session->header, true))
-		return 0;
-
-	for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) {
-		pos = rb_entry(nd, struct machine, rb_node);
-		if (machine__is_host(pos)) {
-			kmisc = PERF_RECORD_MISC_KERNEL;
-			umisc = PERF_RECORD_MISC_USER;
-		} else {
-			kmisc = PERF_RECORD_MISC_GUEST_KERNEL;
-			umisc = PERF_RECORD_MISC_GUEST_USER;
-		}
-
-		err = __event_synthesize_build_ids(&pos->kernel_dsos, kmisc,
-						   process, pos, session);
-		if (err == 0)
-			err = __event_synthesize_build_ids(&pos->user_dsos, umisc,
-							   process, pos, session);
-		if (err)
-			break;
-	}
-
-	if (err < 0) {
-		pr_debug("failed to synthesize build ids\n");
-		return err;
-	}
-
-	dsos__cache_build_ids(&session->header);
-
-	return 0;
-}
-
 int event__process_build_id(event_t *self,
 			    struct perf_session *session)
 {
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index f39443d..402ac24 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -122,8 +122,6 @@
 			       event__handler_t process,
 			       struct machine *machine,
 			       struct perf_session *session);
-int event__synthesize_build_ids(event__handler_t process,
-				struct perf_session *session);
 int event__process_build_id(event_t *self, struct perf_session *session);
 
 #endif /* __PERF_HEADER_H */
diff --git a/tools/perf/util/hweight.c b/tools/perf/util/hweight.c
new file mode 100644
index 0000000..5c1d0d0
--- /dev/null
+++ b/tools/perf/util/hweight.c
@@ -0,0 +1,31 @@
+#include <linux/bitops.h>
+
+/**
+ * hweightN - returns the hamming weight of a N-bit word
+ * @x: the word to weigh
+ *
+ * The Hamming Weight of a number is the total number of bits set in it.
+ */
+
+unsigned int hweight32(unsigned int w)
+{
+	unsigned int res = w - ((w >> 1) & 0x55555555);
+	res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
+	res = (res + (res >> 4)) & 0x0F0F0F0F;
+	res = res + (res >> 8);
+	return (res + (res >> 16)) & 0x000000FF;
+}
+
+unsigned long hweight64(__u64 w)
+{
+#if BITS_PER_LONG == 32
+	return hweight32((unsigned int)(w >> 32)) + hweight32((unsigned int)w);
+#elif BITS_PER_LONG == 64
+	__u64 res = w - ((w >> 1) & 0x5555555555555555ul);
+	res = (res & 0x3333333333333333ul) + ((res >> 2) & 0x3333333333333333ul);
+	res = (res + (res >> 4)) & 0x0F0F0F0F0F0F0F0Ful;
+	res = res + (res >> 8);
+	res = res + (res >> 16);
+	return (res + (res >> 32)) & 0x00000000000000FFul;
+#endif
+}
diff --git a/tools/perf/util/include/asm/bitops.h b/tools/perf/util/include/asm/bitops.h
deleted file mode 100644
index 58e9817..0000000
--- a/tools/perf/util/include/asm/bitops.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef _PERF_ASM_BITOPS_H_
-#define _PERF_ASM_BITOPS_H_
-
-#include <sys/types.h>
-#include "../../types.h"
-#include <linux/compiler.h>
-
-/* CHECKME: Not sure both always match */
-#define BITS_PER_LONG	__WORDSIZE
-
-#include "../../../../include/asm-generic/bitops/__fls.h"
-#include "../../../../include/asm-generic/bitops/fls.h"
-#include "../../../../include/asm-generic/bitops/fls64.h"
-#include "../../../../include/asm-generic/bitops/__ffs.h"
-#include "../../../../include/asm-generic/bitops/ffz.h"
-#include "../../../../include/asm-generic/bitops/hweight.h"
-
-#endif
diff --git a/tools/perf/util/include/asm/hweight.h b/tools/perf/util/include/asm/hweight.h
new file mode 100644
index 0000000..36cf26d
--- /dev/null
+++ b/tools/perf/util/include/asm/hweight.h
@@ -0,0 +1,8 @@
+#ifndef PERF_HWEIGHT_H
+#define PERF_HWEIGHT_H
+
+#include <linux/types.h>
+unsigned int hweight32(unsigned int w);
+unsigned long hweight64(__u64 w);
+
+#endif /* PERF_HWEIGHT_H */
diff --git a/tools/perf/util/include/linux/bitmap.h b/tools/perf/util/include/linux/bitmap.h
index 9450763..eda4416 100644
--- a/tools/perf/util/include/linux/bitmap.h
+++ b/tools/perf/util/include/linux/bitmap.h
@@ -1,3 +1,35 @@
-#include "../../../../include/linux/bitmap.h"
-#include "../../../../include/asm-generic/bitops/find.h"
-#include <linux/errno.h>
+#ifndef _PERF_BITOPS_H
+#define _PERF_BITOPS_H
+
+#include <string.h>
+#include <linux/bitops.h>
+
+int __bitmap_weight(const unsigned long *bitmap, int bits);
+
+#define BITMAP_LAST_WORD_MASK(nbits)					\
+(									\
+	((nbits) % BITS_PER_LONG) ?					\
+		(1UL<<((nbits) % BITS_PER_LONG))-1 : ~0UL		\
+)
+
+#define small_const_nbits(nbits) \
+	(__builtin_constant_p(nbits) && (nbits) <= BITS_PER_LONG)
+
+static inline void bitmap_zero(unsigned long *dst, int nbits)
+{
+	if (small_const_nbits(nbits))
+		*dst = 0UL;
+	else {
+		int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long);
+		memset(dst, 0, len);
+	}
+}
+
+static inline int bitmap_weight(const unsigned long *src, int nbits)
+{
+	if (small_const_nbits(nbits))
+		return hweight_long(*src & BITMAP_LAST_WORD_MASK(nbits));
+	return __bitmap_weight(src, nbits);
+}
+
+#endif /* _PERF_BITOPS_H */
diff --git a/tools/perf/util/include/linux/bitops.h b/tools/perf/util/include/linux/bitops.h
index 8d63116..bb4ac2e 100644
--- a/tools/perf/util/include/linux/bitops.h
+++ b/tools/perf/util/include/linux/bitops.h
@@ -1,13 +1,12 @@
 #ifndef _PERF_LINUX_BITOPS_H_
 #define _PERF_LINUX_BITOPS_H_
 
-#define __KERNEL__
+#include <linux/kernel.h>
+#include <asm/hweight.h>
 
-#define CONFIG_GENERIC_FIND_NEXT_BIT
-#define CONFIG_GENERIC_FIND_FIRST_BIT
-#include "../../../../include/linux/bitops.h"
-
-#undef __KERNEL__
+#define BITS_PER_LONG __WORDSIZE
+#define BITS_PER_BYTE           8
+#define BITS_TO_LONGS(nr)       DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
 
 static inline void set_bit(int nr, unsigned long *addr)
 {
@@ -20,10 +19,9 @@
 		(((unsigned long *)addr)[nr / BITS_PER_LONG])) != 0;
 }
 
-unsigned long generic_find_next_zero_le_bit(const unsigned long *addr, unsigned
-		long size, unsigned long offset);
-
-unsigned long generic_find_next_le_bit(const unsigned long *addr, unsigned
-		long size, unsigned long offset);
+static inline unsigned long hweight_long(unsigned long w)
+{
+	return sizeof(w) == 4 ? hweight32(w) : hweight64(w);
+}
 
 #endif
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index a8dd73e..5d353e7 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -77,7 +77,7 @@
 	return ret;
 }
 
-struct perf_session *perf_session__new(const char *filename, int mode, bool force)
+struct perf_session *perf_session__new(const char *filename, int mode, bool force, bool repipe)
 {
 	size_t len = filename ? strlen(filename) + 1 : 0;
 	struct perf_session *self = zalloc(sizeof(*self) + len);
@@ -97,6 +97,7 @@
 	self->cwdlen = 0;
 	self->unknown_events = 0;
 	self->machines = RB_ROOT;
+	self->repipe = repipe;
 	self->ordered_samples.flush_limit = ULLONG_MAX;
 	INIT_LIST_HEAD(&self->ordered_samples.samples_head);
 
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 61ca92e..f2b2c6a 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -34,6 +34,7 @@
 	u64			sample_type;
 	int			fd;
 	bool			fd_pipe;
+	bool			repipe;
 	int			cwdlen;
 	char			*cwd;
 	struct ordered_samples	ordered_samples;
@@ -59,7 +60,7 @@
 	bool	ordered_samples;
 };
 
-struct perf_session *perf_session__new(const char *filename, int mode, bool force);
+struct perf_session *perf_session__new(const char *filename, int mode, bool force, bool repipe);
 void perf_session__delete(struct perf_session *self);
 
 void perf_event_header__bswap(struct perf_event_header *self);
diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c
index 4606639..cb54cd0 100644
--- a/tools/perf/util/trace-event-read.c
+++ b/tools/perf/util/trace-event-read.c
@@ -51,6 +51,7 @@
 static unsigned long	page_size;
 
 static ssize_t calc_data_size;
+static bool repipe;
 
 /* If it fails, the next read will report it */
 static void skip(int size)
@@ -68,6 +69,13 @@
 		if (ret <= 0)
 			return -1;
 
+		if (repipe) {
+			int retw = write(STDOUT_FILENO, buf, ret);
+
+			if (retw <= 0 || retw != ret)
+				die("repiping input file");
+		}
+
 		size -= ret;
 		buf += ret;
 	}
@@ -122,6 +130,13 @@
 		if (!r)
 			die("no data");
 
+		if (repipe) {
+			int retw = write(STDOUT_FILENO, &c, 1);
+
+			if (retw <= 0 || retw != r)
+				die("repiping input file string");
+		}
+
 		buf[size++] = c;
 
 		if (!c)
@@ -456,7 +471,7 @@
 	return data;
 }
 
-ssize_t trace_report(int fd)
+ssize_t trace_report(int fd, bool __repipe)
 {
 	char buf[BUFSIZ];
 	char test[] = { 23, 8, 68 };
@@ -467,6 +482,7 @@
 	ssize_t size;
 
 	calc_data_size = 1;
+	repipe = __repipe;
 
 	input_fd = fd;
 
@@ -501,6 +517,7 @@
 
 	size = calc_data_size - 1;
 	calc_data_size = 0;
+	repipe = false;
 
 	if (show_funcs) {
 		print_funcs();
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index 4e1acc3..406d452 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -163,7 +163,7 @@
 
 void parse_set_info(int nr_cpus, int long_sz);
 
-ssize_t trace_report(int fd);
+ssize_t trace_report(int fd, bool repipe);
 
 void *malloc_or_die(unsigned int size);