All of lore.kernel.org
 help / color / mirror / Atom feed
* [GIT PULL 00/10] perf/core improvements
@ 2015-12-17  0:47 Arnaldo Carvalho de Melo
  2015-12-17  0:47 ` [PATCH 01/10] perf record: Add record.build-id config option Arnaldo Carvalho de Melo
                   ` (10 more replies)
  0 siblings, 11 replies; 14+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17  0:47 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Arnaldo Carvalho de Melo, David Ahern, Jiri Olsa,
	Josh Poimboeuf, Namhyung Kim, Peter Zijlstra, Taeung Song,
	Arnaldo Carvalho de Melo

Hi Ingo,

	Please consider pulling, this is on top of the perf-core-for-mingo
tag, that is not yet merged.

- Arnaldo

The following changes since commit 7efe0e034c713716060bc7794c7e332589980c70:

  perf record: Support custom vmlinux path (2015-12-14 13:04:12 -0300)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git tags/perf-core-for-mingo-2

for you to fetch changes up to 5c560cfcf1c0f897f78aa5955e3eb05418891f34:

  tools subcmd: Rename subcmd header include guards (2015-12-16 21:39:01 -0300)

----------------------------------------------------------------
perf/core improvements

User visible:

- Add record.build-id config option to 'perf record', to allow configuring
  in the ~/.perfconfig file if and how build-ids should be processed, allowing
  a permanent setting for options such as -B and -N: (Namhyung Kim)

  $ perf record -h -B -N

   Usage: perf record [<options>] [<command>]
      or: perf record [<options>] -- <command> [<options>]

      -B, --no-buildid       do not collect buildids in perf.data
      -N, --no-buildid-cache do not update the buildid cache

  $

Infrastructure:

- Move code for options parsing and subcommand handling from tools/perf/
  to tools/lib/subcmd/, so that it can be used by other tools/ living
  utilities (Josh Poimboeuf)

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

----------------------------------------------------------------
Josh Poimboeuf (9):
      tools build: Fix feature Makefile issues with 'O='
      perf tools: Move strlcpy() from perf to tools/lib/string.c
      perf tools: Document the fact that parse_options*() may exit
      perf tools: Provide subcmd configuration at runtime
      perf tools: Remove subcmd dependencies on strbuf
      perf tools: Remove 'perf' from subcmd function and variable names
      perf tools: Finalize subcmd independence
      perf subcmd: Create subcmd library
      tools subcmd: Rename subcmd header include guards

Namhyung Kim (1):
      perf record: Add record.build-id config option

 tools/build/Makefile.feature                    |   2 +-
 tools/build/feature/Makefile                    |  93 +++++------
 tools/include/linux/string.h                    |   4 +
 tools/lib/string.c                              |  27 +++
 tools/lib/subcmd/Build                          |   7 +
 tools/lib/subcmd/Makefile                       |  48 ++++++
 tools/lib/subcmd/exec-cmd.c                     | 209 ++++++++++++++++++++++++
 tools/lib/subcmd/exec-cmd.h                     |  16 ++
 tools/{perf/util => lib/subcmd}/help.c          |  63 +++++--
 tools/{perf/util => lib/subcmd}/help.h          |  10 +-
 tools/{perf/util => lib/subcmd}/pager.c         |  15 +-
 tools/lib/subcmd/pager.h                        |   9 +
 tools/{perf/util => lib/subcmd}/parse-options.c | 116 +++++++------
 tools/{perf/util => lib/subcmd}/parse-options.h |  12 +-
 tools/{perf/util => lib/subcmd}/run-command.c   |  24 ++-
 tools/{perf/util => lib/subcmd}/run-command.h   |  12 +-
 tools/{perf/util => lib/subcmd}/sigchain.c      |   3 +-
 tools/{perf/util => lib/subcmd}/sigchain.h      |   6 +-
 tools/lib/subcmd/subcmd-config.c                |  11 ++
 tools/lib/subcmd/subcmd-config.h                |  14 ++
 tools/lib/subcmd/subcmd-util.h                  |  91 +++++++++++
 tools/perf/Build                                |   5 +-
 tools/perf/Documentation/perf-record.txt        |  14 +-
 tools/perf/MANIFEST                             |   1 +
 tools/perf/Makefile.perf                        |  20 ++-
 tools/perf/arch/x86/util/intel-pt.c             |   2 +-
 tools/perf/bench/futex-hash.c                   |   2 +-
 tools/perf/bench/futex-lock-pi.c                |   2 +-
 tools/perf/bench/futex-requeue.c                |   2 +-
 tools/perf/bench/futex-wake-parallel.c          |   2 +-
 tools/perf/bench/futex-wake.c                   |   2 +-
 tools/perf/bench/mem-functions.c                |   2 +-
 tools/perf/bench/numa.c                         |   2 +-
 tools/perf/bench/sched-messaging.c              |   2 +-
 tools/perf/bench/sched-pipe.c                   |   2 +-
 tools/perf/builtin-annotate.c                   |   2 +-
 tools/perf/builtin-bench.c                      |   2 +-
 tools/perf/builtin-buildid-cache.c              |   2 +-
 tools/perf/builtin-buildid-list.c               |   2 +-
 tools/perf/builtin-config.c                     |   2 +-
 tools/perf/builtin-data.c                       |   2 +-
 tools/perf/builtin-evlist.c                     |   2 +-
 tools/perf/builtin-help.c                       |  10 +-
 tools/perf/builtin-inject.c                     |   2 +-
 tools/perf/builtin-kmem.c                       |   2 +-
 tools/perf/builtin-kvm.c                        |   2 +-
 tools/perf/builtin-list.c                       |   2 +-
 tools/perf/builtin-lock.c                       |   2 +-
 tools/perf/builtin-mem.c                        |   2 +-
 tools/perf/builtin-probe.c                      |   2 +-
 tools/perf/builtin-record.c                     |  15 +-
 tools/perf/builtin-report.c                     |   2 +-
 tools/perf/builtin-sched.c                      |   2 +-
 tools/perf/builtin-script.c                     |  12 +-
 tools/perf/builtin-stat.c                       |   2 +-
 tools/perf/builtin-timechart.c                  |   2 +-
 tools/perf/builtin-top.c                        |   2 +-
 tools/perf/builtin-trace.c                      |   4 +-
 tools/perf/perf.c                               |  18 +-
 tools/perf/tests/attr.c                         |   4 +-
 tools/perf/tests/builtin-test.c                 |   2 +-
 tools/perf/util/Build                           |   7 -
 tools/perf/util/auxtrace.c                      |   2 +-
 tools/perf/util/cache.h                         |  10 +-
 tools/perf/util/cgroup.c                        |   2 +-
 tools/perf/util/config.c                        |   2 +-
 tools/perf/util/evlist.c                        |   2 +-
 tools/perf/util/exec_cmd.c                      | 149 -----------------
 tools/perf/util/exec_cmd.h                      |  13 --
 tools/perf/util/help-unknown-cmd.c              |   2 +-
 tools/perf/util/pager.h                         |   7 -
 tools/perf/util/parse-branch-options.c          |   2 +-
 tools/perf/util/parse-events.c                  |   4 +-
 tools/perf/util/parse-regs-options.c            |   2 +-
 tools/perf/util/path.c                          |  18 --
 tools/perf/util/sort.h                          |   2 +-
 tools/perf/util/util.h                          |  14 --
 77 files changed, 775 insertions(+), 418 deletions(-)
 create mode 100644 tools/lib/subcmd/Build
 create mode 100644 tools/lib/subcmd/Makefile
 create mode 100644 tools/lib/subcmd/exec-cmd.c
 create mode 100644 tools/lib/subcmd/exec-cmd.h
 rename tools/{perf/util => lib/subcmd}/help.c (81%)
 rename tools/{perf/util => lib/subcmd}/help.h (87%)
 rename tools/{perf/util => lib/subcmd}/pager.c (85%)
 create mode 100644 tools/lib/subcmd/pager.h
 rename tools/{perf/util => lib/subcmd}/parse-options.c (90%)
 rename tools/{perf/util => lib/subcmd}/parse-options.h (96%)
 rename tools/{perf/util => lib/subcmd}/run-command.c (90%)
 rename tools/{perf/util => lib/subcmd}/run-command.h (86%)
 rename tools/{perf/util => lib/subcmd}/sigchain.c (95%)
 rename tools/{perf/util => lib/subcmd}/sigchain.h (55%)
 create mode 100644 tools/lib/subcmd/subcmd-config.c
 create mode 100644 tools/lib/subcmd/subcmd-config.h
 create mode 100644 tools/lib/subcmd/subcmd-util.h
 delete mode 100644 tools/perf/util/exec_cmd.c
 delete mode 100644 tools/perf/util/exec_cmd.h
 delete mode 100644 tools/perf/util/pager.h

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 01/10] perf record: Add record.build-id config option
  2015-12-17  0:47 [GIT PULL 00/10] perf/core improvements Arnaldo Carvalho de Melo
@ 2015-12-17  0:47 ` Arnaldo Carvalho de Melo
  2015-12-17  0:47 ` [PATCH 02/10] tools build: Fix feature Makefile issues with 'O=' Arnaldo Carvalho de Melo
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17  0:47 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Namhyung Kim, David Ahern, Taeung Song,
	Arnaldo Carvalho de Melo

From: Namhyung Kim <namhyung@kernel.org>

Post processing at 'perf record' takes a long time on big machines.

What it does is to find the build-id of binaries found in the event
stream, so that it can make sure, at 'report' time, that the symtabs (be
it ELF, kallsyms, etc) being used to resolve symbols are the ones
matching the binaries found at 'record' time.

Sometimes we just want to skip this processing of events at the end of
the session to get quicker results, making sure the binaries haven't
changed from 'record' to 'report' time.

Add a new config option to control this behavior.

The record.build-id config variable can have one of the following
values:

 - cache: post-process data and save/update the binaries into the
          build-id cache (in ~/.debug).  This is the default.
 - no-cache: post-process the data but not update the build-id cache.
             Same effect as using the -N option.
 - skip: skip post-processing and do not update the cache.
         Same effect as using the -B option.

Reported-and-Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Taeung Song <treeze.taeung@gmail.com>
Link: http://lkml.kernel.org/r/1450144196-22957-1-git-send-email-namhyung@kernel.org
[ Added some more text to the documentation ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/Documentation/perf-record.txt | 14 +++++++++++++-
 tools/perf/builtin-record.c              | 13 +++++++++++++
 2 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 8d032f4e50bf..3a1a32f5479f 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -207,11 +207,23 @@ comma-separated list with no space: 0,1. Ranges of CPUs are specified with -: 0-
 In per-thread mode with inheritance mode on (default), samples are captured only when
 the thread executes on the designated CPUs. Default is to monitor all CPUs.
 
+-B::
+--no-buildid::
+Do not save the build ids of binaries in the perf.data files. This skips
+post processing after recording, which sometimes makes the final step in
+the recording process to take a long time, as it needs to process all
+events looking for mmap records. The downside is that it can misresolve
+symbols if the workload binaries used when recording get locally rebuilt
+or upgraded, because the only key available in this case is the
+pathname. You can also set the "record.build-id" config variable to
+'skip to have this behaviour permanently.
+
 -N::
 --no-buildid-cache::
 Do not update the buildid cache. This saves some overhead in situations
 where the information in the perf.data file (which includes buildids)
-is sufficient.
+is sufficient.  You can also set the "record.build-id" config variable to
+'no-cache' to have the same effect.
 
 -G name,...::
 --cgroup name,...::
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 3ef3c79e7534..a3b4930737c6 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -837,6 +837,19 @@ int record_callchain_opt(const struct option *opt,
 
 static int perf_record_config(const char *var, const char *value, void *cb)
 {
+	struct record *rec = cb;
+
+	if (!strcmp(var, "record.build-id")) {
+		if (!strcmp(value, "cache"))
+			rec->no_buildid_cache = false;
+		else if (!strcmp(value, "no-cache"))
+			rec->no_buildid_cache = true;
+		else if (!strcmp(value, "skip"))
+			rec->no_buildid = true;
+		else
+			return -1;
+		return 0;
+	}
 	if (!strcmp(var, "record.call-graph"))
 		var = "call-graph.record-mode"; /* fall-through */
 
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 02/10] tools build: Fix feature Makefile issues with 'O='
  2015-12-17  0:47 [GIT PULL 00/10] perf/core improvements Arnaldo Carvalho de Melo
  2015-12-17  0:47 ` [PATCH 01/10] perf record: Add record.build-id config option Arnaldo Carvalho de Melo
@ 2015-12-17  0:47 ` Arnaldo Carvalho de Melo
  2015-12-17  0:47 ` [PATCH 03/10] perf tools: Move strlcpy() from perf to tools/lib/string.c Arnaldo Carvalho de Melo
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17  0:47 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Josh Poimboeuf, Namhyung Kim, Peter Zijlstra,
	Arnaldo Carvalho de Melo

From: Josh Poimboeuf <jpoimboe@redhat.com>

When building perf binaries outside the source tree with 'make O=<dir>',
the auto-detected features get re-tested for every build, which is
unnecessary and inconsistent with the behavior seen when building
directly in the source tree.

Another issue is that 'make O=<dir> clean' doesn't remove the feature
files from the object tree.

Fix these problems by looking for the binaries in the $(OUTPUT)
directory.

Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/113bd01530e9761778c60a75a96c65fc59860f68.1450193761.git.jpoimboe@redhat.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/build/Makefile.feature |  2 +-
 tools/build/feature/Makefile | 93 ++++++++++++++++++++++----------------------
 2 files changed, 48 insertions(+), 47 deletions(-)

diff --git a/tools/build/Makefile.feature b/tools/build/Makefile.feature
index b8c31ece2d96..6c0519de765d 100644
--- a/tools/build/Makefile.feature
+++ b/tools/build/Makefile.feature
@@ -7,7 +7,7 @@ endif
 
 feature_check = $(eval $(feature_check_code))
 define feature_check_code
-  feature-$(1) := $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS) $(FEATURE_CHECK_CFLAGS-$(1))" LDFLAGS="$(LDFLAGS) $(FEATURE_CHECK_LDFLAGS-$(1))" -C $(feature_dir) test-$1.bin >/dev/null 2>/dev/null && echo 1 || echo 0)
+  feature-$(1) := $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS) $(FEATURE_CHECK_CFLAGS-$(1))" LDFLAGS="$(LDFLAGS) $(FEATURE_CHECK_LDFLAGS-$(1))" -C $(feature_dir) $(OUTPUT_FEATURES)test-$1.bin >/dev/null 2>/dev/null && echo 1 || echo 0)
 endef
 
 feature_set = $(eval $(feature_set_code))
diff --git a/tools/build/feature/Makefile b/tools/build/feature/Makefile
index cea04ce9f35c..bf8f0352264d 100644
--- a/tools/build/feature/Makefile
+++ b/tools/build/feature/Makefile
@@ -1,4 +1,3 @@
-
 FILES=					\
 	test-all.bin			\
 	test-backtrace.bin		\
@@ -38,38 +37,40 @@ FILES=					\
 	test-bpf.bin			\
 	test-get_cpuid.bin
 
+FILES := $(addprefix $(OUTPUT),$(FILES))
+
 CC := $(CROSS_COMPILE)gcc -MD
 PKG_CONFIG := $(CROSS_COMPILE)pkg-config
 
 all: $(FILES)
 
-__BUILD = $(CC) $(CFLAGS) -Wall -Werror -o $(OUTPUT)$@ $(patsubst %.bin,%.c,$@) $(LDFLAGS)
-  BUILD = $(__BUILD) > $(OUTPUT)$(@:.bin=.make.output) 2>&1
+__BUILD = $(CC) $(CFLAGS) -Wall -Werror -o $@ $(patsubst %.bin,%.c,$(@F)) $(LDFLAGS)
+  BUILD = $(__BUILD) > $(@:.bin=.make.output) 2>&1
 
 ###############################
 
-test-all.bin:
+$(OUTPUT)test-all.bin:
 	$(BUILD) -fstack-protector-all -O2 -D_FORTIFY_SOURCE=2 -ldw -lelf -lnuma -lelf -laudit -I/usr/include/slang -lslang $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null) $(FLAGS_PERL_EMBED) $(FLAGS_PYTHON_EMBED) -DPACKAGE='"perf"' -lbfd -ldl -lz -llzma
 
-test-hello.bin:
+$(OUTPUT)test-hello.bin:
 	$(BUILD)
 
-test-pthread-attr-setaffinity-np.bin:
+$(OUTPUT)test-pthread-attr-setaffinity-np.bin:
 	$(BUILD) -D_GNU_SOURCE -lpthread
 
-test-stackprotector-all.bin:
+$(OUTPUT)test-stackprotector-all.bin:
 	$(BUILD) -fstack-protector-all
 
-test-fortify-source.bin:
+$(OUTPUT)test-fortify-source.bin:
 	$(BUILD) -O2 -D_FORTIFY_SOURCE=2
 
-test-bionic.bin:
+$(OUTPUT)test-bionic.bin:
 	$(BUILD)
 
-test-libelf.bin:
+$(OUTPUT)test-libelf.bin:
 	$(BUILD) -lelf
 
-test-glibc.bin:
+$(OUTPUT)test-glibc.bin:
 	$(BUILD)
 
 DWARFLIBS := -ldw
@@ -77,37 +78,37 @@ ifeq ($(findstring -static,${LDFLAGS}),-static)
 DWARFLIBS += -lelf -lebl -lz -llzma -lbz2
 endif
 
-test-dwarf.bin:
+$(OUTPUT)test-dwarf.bin:
 	$(BUILD) $(DWARFLIBS)
 
-test-libelf-mmap.bin:
+$(OUTPUT)test-libelf-mmap.bin:
 	$(BUILD) -lelf
 
-test-libelf-getphdrnum.bin:
+$(OUTPUT)test-libelf-getphdrnum.bin:
 	$(BUILD) -lelf
 
-test-libnuma.bin:
+$(OUTPUT)test-libnuma.bin:
 	$(BUILD) -lnuma
 
-test-numa_num_possible_cpus.bin:
+$(OUTPUT)test-numa_num_possible_cpus.bin:
 	$(BUILD) -lnuma
 
-test-libunwind.bin:
+$(OUTPUT)test-libunwind.bin:
 	$(BUILD) -lelf
 
-test-libunwind-debug-frame.bin:
+$(OUTPUT)test-libunwind-debug-frame.bin:
 	$(BUILD) -lelf
 
-test-libaudit.bin:
+$(OUTPUT)test-libaudit.bin:
 	$(BUILD) -laudit
 
-test-libslang.bin:
+$(OUTPUT)test-libslang.bin:
 	$(BUILD) -I/usr/include/slang -lslang
 
-test-gtk2.bin:
+$(OUTPUT)test-gtk2.bin:
 	$(BUILD) $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null)
 
-test-gtk2-infobar.bin:
+$(OUTPUT)test-gtk2-infobar.bin:
 	$(BUILD) $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null)
 
 grep-libs  = $(filter -l%,$(1))
@@ -119,63 +120,63 @@ PERL_EMBED_LIBADD = $(call grep-libs,$(PERL_EMBED_LDOPTS))
 PERL_EMBED_CCOPTS = `perl -MExtUtils::Embed -e ccopts 2>/dev/null`
 FLAGS_PERL_EMBED=$(PERL_EMBED_CCOPTS) $(PERL_EMBED_LDOPTS)
 
-test-libperl.bin:
+$(OUTPUT)test-libperl.bin:
 	$(BUILD) $(FLAGS_PERL_EMBED)
 
-test-libpython.bin:
+$(OUTPUT)test-libpython.bin:
 	$(BUILD)
 
-test-libpython-version.bin:
+$(OUTPUT)test-libpython-version.bin:
 	$(BUILD)
 
-test-libbfd.bin:
+$(OUTPUT)test-libbfd.bin:
 	$(BUILD) -DPACKAGE='"perf"' -lbfd -lz -liberty -ldl
 
-test-liberty.bin:
-	$(CC) $(CFLAGS) -Wall -Werror -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' $(LDFLAGS) -lbfd -ldl -liberty
+$(OUTPUT)test-liberty.bin:
+	$(CC) $(CFLAGS) -Wall -Werror -o $@ test-libbfd.c -DPACKAGE='"perf"' $(LDFLAGS) -lbfd -ldl -liberty
 
-test-liberty-z.bin:
-	$(CC) $(CFLAGS) -Wall -Werror -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' $(LDFLAGS) -lbfd -ldl -liberty -lz
+$(OUTPUT)test-liberty-z.bin:
+	$(CC) $(CFLAGS) -Wall -Werror -o $@ test-libbfd.c -DPACKAGE='"perf"' $(LDFLAGS) -lbfd -ldl -liberty -lz
 
-test-cplus-demangle.bin:
+$(OUTPUT)test-cplus-demangle.bin:
 	$(BUILD) -liberty
 
-test-backtrace.bin:
+$(OUTPUT)test-backtrace.bin:
 	$(BUILD)
 
-test-timerfd.bin:
+$(OUTPUT)test-timerfd.bin:
 	$(BUILD)
 
-test-libdw-dwarf-unwind.bin:
+$(OUTPUT)test-libdw-dwarf-unwind.bin:
 	$(BUILD) # -ldw provided by $(FEATURE_CHECK_LDFLAGS-libdw-dwarf-unwind)
 
-test-libbabeltrace.bin:
+$(OUTPUT)test-libbabeltrace.bin:
 	$(BUILD) # -lbabeltrace provided by $(FEATURE_CHECK_LDFLAGS-libbabeltrace)
 
-test-sync-compare-and-swap.bin:
+$(OUTPUT)test-sync-compare-and-swap.bin:
 	$(BUILD)
 
-test-compile-32.bin:
-	$(CC) -m32 -o $(OUTPUT)$@ test-compile.c
+$(OUTPUT)test-compile-32.bin:
+	$(CC) -m32 -o $@ test-compile.c
 
-test-compile-x32.bin:
-	$(CC) -mx32 -o $(OUTPUT)$@ test-compile.c
+$(OUTPUT)test-compile-x32.bin:
+	$(CC) -mx32 -o $@ test-compile.c
 
-test-zlib.bin:
+$(OUTPUT)test-zlib.bin:
 	$(BUILD) -lz
 
-test-lzma.bin:
+$(OUTPUT)test-lzma.bin:
 	$(BUILD) -llzma
 
-test-get_cpuid.bin:
+$(OUTPUT)test-get_cpuid.bin:
 	$(BUILD)
 
-test-bpf.bin:
+$(OUTPUT)test-bpf.bin:
 	$(BUILD)
 
--include *.d
+-include $(OUTPUT)*.d
 
 ###############################
 
 clean:
-	rm -f $(FILES) *.d $(FILES:.bin=.make.output)
+	rm -f $(FILES) $(OUTPUT)*.d $(FILES:.bin=.make.output)
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 03/10] perf tools: Move strlcpy() from perf to tools/lib/string.c
  2015-12-17  0:47 [GIT PULL 00/10] perf/core improvements Arnaldo Carvalho de Melo
  2015-12-17  0:47 ` [PATCH 01/10] perf record: Add record.build-id config option Arnaldo Carvalho de Melo
  2015-12-17  0:47 ` [PATCH 02/10] tools build: Fix feature Makefile issues with 'O=' Arnaldo Carvalho de Melo
@ 2015-12-17  0:47 ` Arnaldo Carvalho de Melo
  2015-12-17  0:47 ` [PATCH 04/10] perf tools: Document the fact that parse_options*() may exit Arnaldo Carvalho de Melo
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17  0:47 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Josh Poimboeuf, Jiri Olsa, Namhyung Kim,
	Peter Zijlstra, Arnaldo Carvalho de Melo

From: Josh Poimboeuf <jpoimboe@redhat.com>

strlcpy() will be needed by the subcmd library.  Move it to the shared
tools/lib/string.c file which can be used by other tools.

Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/71e2804b973bf39ad3d3b9be10f99f2ea630be46.1450193761.git.jpoimboe@redhat.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/include/linux/string.h |  4 ++++
 tools/lib/string.c           | 27 +++++++++++++++++++++++++++
 tools/perf/util/cache.h      |  7 ++-----
 tools/perf/util/path.c       | 18 ------------------
 4 files changed, 33 insertions(+), 23 deletions(-)

diff --git a/tools/include/linux/string.h b/tools/include/linux/string.h
index 2e2f736c039c..e26223f1f287 100644
--- a/tools/include/linux/string.h
+++ b/tools/include/linux/string.h
@@ -8,4 +8,8 @@ void *memdup(const void *src, size_t len);
 
 int strtobool(const char *s, bool *res);
 
+#ifndef __UCLIBC__
+extern size_t strlcpy(char *dest, const char *src, size_t size);
+#endif
+
 #endif /* _LINUX_STRING_H_ */
diff --git a/tools/lib/string.c b/tools/lib/string.c
index 065e54f42d8f..bd239bc1d557 100644
--- a/tools/lib/string.c
+++ b/tools/lib/string.c
@@ -16,6 +16,7 @@
 #include <string.h>
 #include <errno.h>
 #include <linux/string.h>
+#include <linux/compiler.h>
 
 /**
  * memdup - duplicate region of memory
@@ -60,3 +61,29 @@ int strtobool(const char *s, bool *res)
 	}
 	return 0;
 }
+
+/**
+ * strlcpy - Copy a C-string into a sized buffer
+ * @dest: Where to copy the string to
+ * @src: Where to copy the string from
+ * @size: size of destination buffer
+ *
+ * Compatible with *BSD: the result is always a valid
+ * NUL-terminated string that fits in the buffer (unless,
+ * of course, the buffer size is zero). It does not pad
+ * out the result like strncpy() does.
+ *
+ * If libc has strlcpy() then that version will override this
+ * implementation:
+ */
+size_t __weak strlcpy(char *dest, const char *src, size_t size)
+{
+	size_t ret = strlen(src);
+
+	if (size) {
+		size_t len = (ret >= size) ? size - 1 : ret;
+		memcpy(dest, src, len);
+		dest[len] = '\0';
+	}
+	return ret;
+}
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index 9ca4a58f160d..d723ecb9b959 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -8,6 +8,8 @@
 #include "../perf.h"
 #include "../ui/ui.h"
 
+#include <linux/string.h>
+
 #define CMD_EXEC_PATH "--exec-path"
 #define CMD_PERF_DIR "--perf-dir="
 #define CMD_WORK_TREE "--work-tree="
@@ -67,9 +69,4 @@ extern char *perf_path(const char *fmt, ...) __attribute__((format (printf, 1, 2
 extern char *perf_pathdup(const char *fmt, ...)
 	__attribute__((format (printf, 1, 2)));
 
-#ifndef __UCLIBC__
-/* Matches the libc/libbsd function attribute so we declare this unconditionally: */
-extern size_t strlcpy(char *dest, const char *src, size_t size);
-#endif
-
 #endif /* __PERF_CACHE_H */
diff --git a/tools/perf/util/path.c b/tools/perf/util/path.c
index 5d13cb45b317..3654d964e49d 100644
--- a/tools/perf/util/path.c
+++ b/tools/perf/util/path.c
@@ -22,24 +22,6 @@ static const char *get_perf_dir(void)
 	return ".";
 }
 
-/*
- * If libc has strlcpy() then that version will override this
- * implementation:
- */
-size_t __weak strlcpy(char *dest, const char *src, size_t size)
-{
-	size_t ret = strlen(src);
-
-	if (size) {
-		size_t len = (ret >= size) ? size - 1 : ret;
-
-		memcpy(dest, src, len);
-		dest[len] = '\0';
-	}
-
-	return ret;
-}
-
 static char *get_pathname(void)
 {
 	static char pathname_array[4][PATH_MAX];
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 04/10] perf tools: Document the fact that parse_options*() may exit
  2015-12-17  0:47 [GIT PULL 00/10] perf/core improvements Arnaldo Carvalho de Melo
                   ` (2 preceding siblings ...)
  2015-12-17  0:47 ` [PATCH 03/10] perf tools: Move strlcpy() from perf to tools/lib/string.c Arnaldo Carvalho de Melo
@ 2015-12-17  0:47 ` Arnaldo Carvalho de Melo
  2015-12-17  0:47 ` [PATCH 05/10] perf tools: Provide subcmd configuration at runtime Arnaldo Carvalho de Melo
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17  0:47 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Josh Poimboeuf, Jiri Olsa, Namhyung Kim,
	Peter Zijlstra, Arnaldo Carvalho de Melo

From: Josh Poimboeuf <jpoimboe@redhat.com>

Generally, calling exit() from a library is bad practice.  Eventually
these functions might be redesigned so that they don't exit.  For now,
just document the fact that they do.

Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/97b1af06cc3b18dd0f49e655d6d659eaa64ecde5.1450193761.git.jpoimboe@redhat.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/parse-options.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h
index 1231960d6148..d1544069c7c0 100644
--- a/tools/perf/util/parse-options.h
+++ b/tools/perf/util/parse-options.h
@@ -152,6 +152,9 @@ struct option {
 /* parse_options() will filter out the processed options and leave the
  * non-option argments in argv[].
  * Returns the number of arguments left in argv[].
+ *
+ * NOTE: parse_options() and parse_options_subcommand() may call exit() in the
+ * case of an error (or for 'special' options like --list-cmds or --list-opts).
  */
 extern int parse_options(int argc, const char **argv,
                          const struct option *options,
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 05/10] perf tools: Provide subcmd configuration at runtime
  2015-12-17  0:47 [GIT PULL 00/10] perf/core improvements Arnaldo Carvalho de Melo
                   ` (3 preceding siblings ...)
  2015-12-17  0:47 ` [PATCH 04/10] perf tools: Document the fact that parse_options*() may exit Arnaldo Carvalho de Melo
@ 2015-12-17  0:47 ` Arnaldo Carvalho de Melo
  2015-12-17  0:47 ` [PATCH 06/10] perf tools: Remove subcmd dependencies on strbuf Arnaldo Carvalho de Melo
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17  0:47 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Josh Poimboeuf, Jiri Olsa, Namhyung Kim,
	Peter Zijlstra, Arnaldo Carvalho de Melo

From: Josh Poimboeuf <jpoimboe@redhat.com>

Create init functions for exec_cmd.c and pager.c.  This allows their
configuration to be specified at runtime so they can be split out into a
separate library which can be used by other programs.  Their
configuration is stored in a shared subcmd_config struct.

Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/21f5f6b38da72c985a8dcfa185700d03e7eecd1d.1450193761.git.jpoimboe@redhat.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/Build                |  5 ++++-
 tools/perf/perf.c               |  6 +++++-
 tools/perf/util/Build           |  2 +-
 tools/perf/util/cache.h         |  1 +
 tools/perf/util/exec_cmd.c      | 23 ++++++++++++++++-------
 tools/perf/util/exec_cmd.h      |  3 +++
 tools/perf/util/pager.c         |  8 +++++++-
 tools/perf/util/pager.h         |  2 ++
 tools/perf/util/parse-options.c |  4 +++-
 tools/perf/util/subcmd-config.c | 11 +++++++++++
 tools/perf/util/subcmd-config.h | 14 ++++++++++++++
 11 files changed, 67 insertions(+), 12 deletions(-)
 create mode 100644 tools/perf/util/subcmd-config.c
 create mode 100644 tools/perf/util/subcmd-config.h

diff --git a/tools/perf/Build b/tools/perf/Build
index 2a41217e9d88..00c4b8c3d8ca 100644
--- a/tools/perf/Build
+++ b/tools/perf/Build
@@ -36,7 +36,10 @@ paths += -DPERF_MAN_PATH="BUILD_STR($(mandir_SQ))"
 
 CFLAGS_builtin-help.o      += $(paths)
 CFLAGS_builtin-timechart.o += $(paths)
-CFLAGS_perf.o              += -DPERF_HTML_PATH="BUILD_STR($(htmldir_SQ))" -include $(OUTPUT)PERF-VERSION-FILE
+CFLAGS_perf.o              += -DPERF_HTML_PATH="BUILD_STR($(htmldir_SQ))"	\
+			      -DPERF_EXEC_PATH="BUILD_STR($(perfexecdir_SQ))"	\
+			      -DPREFIX="BUILD_STR($(prefix_SQ))"		\
+			      -include $(OUTPUT)PERF-VERSION-FILE
 CFLAGS_builtin-trace.o	   += -DSTRACE_GROUPS_DIR="BUILD_STR($(STRACE_GROUPS_DIR_SQ))"
 
 libperf-y += util/
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 59ea48c7e26c..783a3310a9d8 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -119,7 +119,7 @@ static void commit_pager_choice(void)
 {
 	switch (use_pager) {
 	case 0:
-		setenv("PERF_PAGER", "cat", 1);
+		setenv(PERF_PAGER_ENVIRONMENT, "cat", 1);
 		break;
 	case 1:
 		/* setup_pager(); */
@@ -530,6 +530,10 @@ int main(int argc, const char **argv)
 	const char *cmd;
 	char sbuf[STRERR_BUFSIZE];
 
+	/* libsubcmd init */
+	exec_cmd_init("perf", PREFIX, PERF_EXEC_PATH, EXEC_PATH_ENVIRONMENT);
+	pager_init(PERF_PAGER_ENVIRONMENT);
+
 	/* The page_size is placed in util object. */
 	page_size = sysconf(_SC_PAGE_SIZE);
 	cacheline_size = sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index 99b3dae57806..196beefa16a9 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -88,6 +88,7 @@ libperf-y += parse-branch-options.o
 libperf-y += parse-regs-options.o
 libperf-y += term.o
 libperf-y += help-unknown-cmd.o
+libperf-y += subcmd-config.o
 
 libperf-$(CONFIG_LIBBPF) += bpf-loader.o
 libperf-$(CONFIG_BPF_PROLOGUE) += bpf-prologue.o
@@ -113,7 +114,6 @@ libperf-$(CONFIG_ZLIB) += zlib.o
 libperf-$(CONFIG_LZMA) += lzma.o
 
 CFLAGS_config.o   += -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))"
-CFLAGS_exec_cmd.o += -DPERF_EXEC_PATH="BUILD_STR($(perfexecdir_SQ))" -DPREFIX="BUILD_STR($(prefix_SQ))"
 
 $(OUTPUT)util/parse-events-flex.c: util/parse-events.l $(OUTPUT)util/parse-events-bison.c
 	$(call rule_mkdir)
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index d723ecb9b959..fc6a745d2ec6 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -21,6 +21,7 @@
 #define DEFAULT_PERF_DIR_ENVIRONMENT ".perf"
 #define PERF_DEBUGFS_ENVIRONMENT "PERF_DEBUGFS_DIR"
 #define PERF_TRACEFS_ENVIRONMENT "PERF_TRACEFS_DIR"
+#define PERF_PAGER_ENVIRONMENT "PERF_PAGER"
 
 typedef int (*config_fn_t)(const char *, const char *, void *);
 extern int perf_default_config(const char *, const char *, void *);
diff --git a/tools/perf/util/exec_cmd.c b/tools/perf/util/exec_cmd.c
index 1099e92f5ee1..b935e4ce62a2 100644
--- a/tools/perf/util/exec_cmd.c
+++ b/tools/perf/util/exec_cmd.c
@@ -1,6 +1,7 @@
 #include "cache.h"
 #include "exec_cmd.h"
 #include "quote.h"
+#include "subcmd-config.h"
 
 #include <string.h>
 
@@ -9,15 +10,23 @@
 static const char *argv_exec_path;
 static const char *argv0_path;
 
+void exec_cmd_init(const char *exec_name, const char *prefix,
+		   const char *exec_path, const char *exec_path_env)
+{
+	subcmd_config.exec_name		= exec_name;
+	subcmd_config.prefix		= prefix;
+	subcmd_config.exec_path		= exec_path;
+	subcmd_config.exec_path_env	= exec_path_env;
+}
+
 char *system_path(const char *path)
 {
-	static const char *prefix = PREFIX;
 	struct strbuf d = STRBUF_INIT;
 
 	if (is_absolute_path(path))
 		return strdup(path);
 
-	strbuf_addf(&d, "%s/%s", prefix, path);
+	strbuf_addf(&d, "%s/%s", subcmd_config.prefix, path);
 	path = strbuf_detach(&d, NULL);
 	return (char *)path;
 }
@@ -47,7 +56,7 @@ void perf_set_argv_exec_path(const char *exec_path)
 	/*
 	 * Propagate this setting to external programs.
 	 */
-	setenv(EXEC_PATH_ENVIRONMENT, exec_path, 1);
+	setenv(subcmd_config.exec_path_env, exec_path, 1);
 }
 
 
@@ -59,11 +68,11 @@ char *perf_exec_path(void)
 	if (argv_exec_path)
 		return strdup(argv_exec_path);
 
-	env = getenv(EXEC_PATH_ENVIRONMENT);
+	env = getenv(subcmd_config.exec_path_env);
 	if (env && *env)
 		return strdup(env);
 
-	return system_path(PERF_EXEC_PATH);
+	return system_path(subcmd_config.exec_path);
 }
 
 static void add_path(struct strbuf *out, const char *path)
@@ -107,7 +116,7 @@ static const char **prepare_perf_cmd(const char **argv)
 		; /* just counting */
 	nargv = malloc(sizeof(*nargv) * (argc + 2));
 
-	nargv[0] = "perf";
+	nargv[0] = subcmd_config.exec_name;
 	for (argc = 0; argv[argc]; argc++)
 		nargv[argc + 1] = argv[argc];
 	nargv[argc + 1] = NULL;
@@ -118,7 +127,7 @@ int execv_perf_cmd(const char **argv) {
 	const char **nargv = prepare_perf_cmd(argv);
 
 	/* execvp() can only ever return if it fails */
-	execvp("perf", (char **)nargv);
+	execvp(subcmd_config.exec_name, (char **)nargv);
 
 	free(nargv);
 	return -1;
diff --git a/tools/perf/util/exec_cmd.h b/tools/perf/util/exec_cmd.h
index 48b4175f1e11..fd4434e48d21 100644
--- a/tools/perf/util/exec_cmd.h
+++ b/tools/perf/util/exec_cmd.h
@@ -1,6 +1,9 @@
 #ifndef __PERF_EXEC_CMD_H
 #define __PERF_EXEC_CMD_H
 
+extern void exec_cmd_init(const char *exec_name, const char *prefix,
+			  const char *exec_path, const char *exec_path_env);
+
 extern void perf_set_argv_exec_path(const char *exec_path);
 extern const char *perf_extract_argv0_path(const char *path);
 extern void setup_path(void);
diff --git a/tools/perf/util/pager.c b/tools/perf/util/pager.c
index 7dcbef64b609..d5ef62eaa413 100644
--- a/tools/perf/util/pager.c
+++ b/tools/perf/util/pager.c
@@ -1,6 +1,7 @@
 #include "cache.h"
 #include "run-command.h"
 #include "sigchain.h"
+#include "subcmd-config.h"
 
 /*
  * This is split up from the rest of git so that we can do
@@ -9,6 +10,11 @@
 
 static int spawned_pager;
 
+void pager_init(const char *pager_env)
+{
+	subcmd_config.pager_env = pager_env;
+}
+
 static void pager_preexec(void)
 {
 	/*
@@ -46,7 +52,7 @@ static void wait_for_pager_signal(int signo)
 
 void setup_pager(void)
 {
-	const char *pager = getenv("PERF_PAGER");
+	const char *pager = getenv(subcmd_config.pager_env);
 
 	if (!isatty(1))
 		return;
diff --git a/tools/perf/util/pager.h b/tools/perf/util/pager.h
index 2794a83b7e85..d6a591a4c017 100644
--- a/tools/perf/util/pager.h
+++ b/tools/perf/util/pager.h
@@ -1,6 +1,8 @@
 #ifndef __PERF_PAGER_H
 #define __PERF_PAGER_H
 
+extern void pager_init(const char *pager_env);
+
 extern void setup_pager(void);
 extern int pager_in_use(void);
 
diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c
index 0ad1384783dd..da4ba21cad21 100644
--- a/tools/perf/util/parse-options.c
+++ b/tools/perf/util/parse-options.c
@@ -2,6 +2,7 @@
 #include "parse-options.h"
 #include "cache.h"
 #include "header.h"
+#include "subcmd-config.h"
 #include <linux/string.h>
 
 #define OPT_SHORT 1
@@ -577,7 +578,8 @@ int parse_options_subcommand(int argc, const char **argv, const struct option *o
 	if (subcommands && !usagestr[0]) {
 		struct strbuf buf = STRBUF_INIT;
 
-		strbuf_addf(&buf, "perf %s [<options>] {", argv[0]);
+		strbuf_addf(&buf, "%s %s [<options>] {",
+			    subcmd_config.exec_name, argv[0]);
 		for (int i = 0; subcommands[i]; i++) {
 			if (i)
 				strbuf_addstr(&buf, "|");
diff --git a/tools/perf/util/subcmd-config.c b/tools/perf/util/subcmd-config.c
new file mode 100644
index 000000000000..d017c728bd1b
--- /dev/null
+++ b/tools/perf/util/subcmd-config.c
@@ -0,0 +1,11 @@
+#include "subcmd-config.h"
+
+#define UNDEFINED "SUBCMD_HAS_NOT_BEEN_INITIALIZED"
+
+struct subcmd_config subcmd_config = {
+	.exec_name	= UNDEFINED,
+	.prefix		= UNDEFINED,
+	.exec_path	= UNDEFINED,
+	.exec_path_env	= UNDEFINED,
+	.pager_env	= UNDEFINED,
+};
diff --git a/tools/perf/util/subcmd-config.h b/tools/perf/util/subcmd-config.h
new file mode 100644
index 000000000000..cc8514030b5c
--- /dev/null
+++ b/tools/perf/util/subcmd-config.h
@@ -0,0 +1,14 @@
+#ifndef __PERF_SUBCMD_CONFIG_H
+#define __PERF_SUBCMD_CONFIG_H
+
+struct subcmd_config {
+	const char *exec_name;
+	const char *prefix;
+	const char *exec_path;
+	const char *exec_path_env;
+	const char *pager_env;
+};
+
+extern struct subcmd_config subcmd_config;
+
+#endif /* __PERF_SUBCMD_CONFIG_H */
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 06/10] perf tools: Remove subcmd dependencies on strbuf
  2015-12-17  0:47 [GIT PULL 00/10] perf/core improvements Arnaldo Carvalho de Melo
                   ` (4 preceding siblings ...)
  2015-12-17  0:47 ` [PATCH 05/10] perf tools: Provide subcmd configuration at runtime Arnaldo Carvalho de Melo
@ 2015-12-17  0:47 ` Arnaldo Carvalho de Melo
  2015-12-17  0:48 ` [PATCH 07/10] perf tools: Remove 'perf' from subcmd function and variable names Arnaldo Carvalho de Melo
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17  0:47 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Josh Poimboeuf, Jiri Olsa, Namhyung Kim,
	Peter Zijlstra, Arnaldo Carvalho de Melo

From: Josh Poimboeuf <jpoimboe@redhat.com>

Introduce and use new astrcat() and astrcatf() functions which replace
the strbuf functionality for subcmd.

For now they duplicate strbuf's die-on-allocation-error policy.

Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/957d207e1254406fa11fc2e405e75a7e405aad8f.1450193761.git.jpoimboe@redhat.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/exec_cmd.c      | 27 +++++++++++++-------------
 tools/perf/util/help.c          | 14 ++++++--------
 tools/perf/util/parse-options.c | 42 +++++++++++++++++++++--------------------
 tools/perf/util/subcmd-util.h   | 24 +++++++++++++++++++++++
 4 files changed, 66 insertions(+), 41 deletions(-)
 create mode 100644 tools/perf/util/subcmd-util.h

diff --git a/tools/perf/util/exec_cmd.c b/tools/perf/util/exec_cmd.c
index b935e4ce62a2..65d86dcaa984 100644
--- a/tools/perf/util/exec_cmd.c
+++ b/tools/perf/util/exec_cmd.c
@@ -4,6 +4,7 @@
 #include "subcmd-config.h"
 
 #include <string.h>
+#include "subcmd-util.h"
 
 #define MAX_ARGS	32
 
@@ -21,14 +22,14 @@ void exec_cmd_init(const char *exec_name, const char *prefix,
 
 char *system_path(const char *path)
 {
-	struct strbuf d = STRBUF_INIT;
+	char *buf = NULL;
 
 	if (is_absolute_path(path))
 		return strdup(path);
 
-	strbuf_addf(&d, "%s/%s", subcmd_config.prefix, path);
-	path = strbuf_detach(&d, NULL);
-	return (char *)path;
+	astrcatf(&buf, "%s/%s", subcmd_config.prefix, path);
+
+	return buf;
 }
 
 const char *perf_extract_argv0_path(const char *argv0)
@@ -75,22 +76,22 @@ char *perf_exec_path(void)
 	return system_path(subcmd_config.exec_path);
 }
 
-static void add_path(struct strbuf *out, const char *path)
+static void add_path(char **out, const char *path)
 {
 	if (path && *path) {
 		if (is_absolute_path(path))
-			strbuf_addstr(out, path);
+			astrcat(out, path);
 		else
-			strbuf_addstr(out, make_nonrelative_path(path));
+			astrcat(out, make_nonrelative_path(path));
 
-		strbuf_addch(out, PATH_SEP);
+		astrcat(out, ":");
 	}
 }
 
 void setup_path(void)
 {
 	const char *old_path = getenv("PATH");
-	struct strbuf new_path = STRBUF_INIT;
+	char *new_path = NULL;
 	char *tmp = perf_exec_path();
 
 	add_path(&new_path, tmp);
@@ -98,13 +99,13 @@ void setup_path(void)
 	free(tmp);
 
 	if (old_path)
-		strbuf_addstr(&new_path, old_path);
+		astrcat(&new_path, old_path);
 	else
-		strbuf_addstr(&new_path, "/usr/local/bin:/usr/bin:/bin");
+		astrcat(&new_path, "/usr/local/bin:/usr/bin:/bin");
 
-	setenv("PATH", new_path.buf, 1);
+	setenv("PATH", new_path, 1);
 
-	strbuf_release(&new_path);
+	free(new_path);
 }
 
 static const char **prepare_perf_cmd(const char **argv)
diff --git a/tools/perf/util/help.c b/tools/perf/util/help.c
index 8d74f7d05674..8e5e0ce3870e 100644
--- a/tools/perf/util/help.c
+++ b/tools/perf/util/help.c
@@ -2,6 +2,7 @@
 #include "../builtin.h"
 #include "exec_cmd.h"
 #include "help.h"
+#include "subcmd-util.h"
 
 void add_cmdname(struct cmdnames *cmds, const char *name, size_t len)
 {
@@ -119,8 +120,7 @@ static void list_commands_in_dir(struct cmdnames *cmds,
 	int prefix_len;
 	DIR *dir = opendir(path);
 	struct dirent *de;
-	struct strbuf buf = STRBUF_INIT;
-	int len;
+	char *buf = NULL;
 
 	if (!dir)
 		return;
@@ -128,8 +128,7 @@ static void list_commands_in_dir(struct cmdnames *cmds,
 		prefix = "perf-";
 	prefix_len = strlen(prefix);
 
-	strbuf_addf(&buf, "%s/", path);
-	len = buf.len;
+	astrcatf(&buf, "%s/", path);
 
 	while ((de = readdir(dir)) != NULL) {
 		int entlen;
@@ -137,9 +136,8 @@ static void list_commands_in_dir(struct cmdnames *cmds,
 		if (prefixcmp(de->d_name, prefix))
 			continue;
 
-		strbuf_setlen(&buf, len);
-		strbuf_addstr(&buf, de->d_name);
-		if (!is_executable(buf.buf))
+		astrcat(&buf, de->d_name);
+		if (!is_executable(buf))
 			continue;
 
 		entlen = strlen(de->d_name) - prefix_len;
@@ -149,7 +147,7 @@ static void list_commands_in_dir(struct cmdnames *cmds,
 		add_cmdname(cmds, de->d_name + prefix_len, entlen);
 	}
 	closedir(dir);
-	strbuf_release(&buf);
+	free(buf);
 }
 
 void load_command_list(const char *prefix,
diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c
index da4ba21cad21..c1da2a53ed4e 100644
--- a/tools/perf/util/parse-options.c
+++ b/tools/perf/util/parse-options.c
@@ -1,4 +1,5 @@
 #include "util.h"
+#include "subcmd-util.h"
 #include "parse-options.h"
 #include "cache.h"
 #include "header.h"
@@ -8,7 +9,7 @@
 #define OPT_SHORT 1
 #define OPT_UNSET 2
 
-static struct strbuf error_buf = STRBUF_INIT;
+char *error_buf;
 
 static int opterror(const struct option *opt, const char *reason, int flags)
 {
@@ -576,19 +577,18 @@ int parse_options_subcommand(int argc, const char **argv, const struct option *o
 
 	/* build usage string if it's not provided */
 	if (subcommands && !usagestr[0]) {
-		struct strbuf buf = STRBUF_INIT;
+		char *buf = NULL;
+
+		astrcatf(&buf, "%s %s [<options>] {", subcmd_config.exec_name, argv[0]);
 
-		strbuf_addf(&buf, "%s %s [<options>] {",
-			    subcmd_config.exec_name, argv[0]);
 		for (int i = 0; subcommands[i]; i++) {
 			if (i)
-				strbuf_addstr(&buf, "|");
-			strbuf_addstr(&buf, subcommands[i]);
+				astrcat(&buf, "|");
+			astrcat(&buf, subcommands[i]);
 		}
-		strbuf_addstr(&buf, "}");
+		astrcat(&buf, "}");
 
-		usagestr[0] = strdup(buf.buf);
-		strbuf_release(&buf);
+		usagestr[0] = buf;
 	}
 
 	parse_options_start(&ctx, argc, argv, flags);
@@ -613,13 +613,11 @@ int parse_options_subcommand(int argc, const char **argv, const struct option *o
 		putchar('\n');
 		exit(130);
 	default: /* PARSE_OPT_UNKNOWN */
-		if (ctx.argv[0][1] == '-') {
-			strbuf_addf(&error_buf, "unknown option `%s'",
-				    ctx.argv[0] + 2);
-		} else {
-			strbuf_addf(&error_buf, "unknown switch `%c'",
-				    *ctx.opt);
-		}
+		if (ctx.argv[0][1] == '-')
+			astrcatf(&error_buf, "unknown option `%s'",
+				 ctx.argv[0] + 2);
+		else
+			astrcatf(&error_buf, "unknown switch `%c'", *ctx.opt);
 		usage_with_options(usagestr, options);
 	}
 
@@ -806,9 +804,9 @@ static int usage_with_options_internal(const char * const *usagestr,
 
 	setup_pager();
 
-	if (strbuf_avail(&error_buf)) {
-		fprintf(stderr, "  Error: %s\n", error_buf.buf);
-		strbuf_release(&error_buf);
+	if (error_buf) {
+		fprintf(stderr, "  Error: %s\n", error_buf);
+		zfree(&error_buf);
 	}
 
 	fprintf(stderr, "\n Usage: %s\n", *usagestr++);
@@ -852,11 +850,15 @@ void usage_with_options_msg(const char * const *usagestr,
 			    const struct option *opts, const char *fmt, ...)
 {
 	va_list ap;
+	char *tmp = error_buf;
 
 	va_start(ap, fmt);
-	strbuf_addv(&error_buf, fmt, ap);
+	if (vasprintf(&error_buf, fmt, ap) == -1)
+		die("vasprintf failed");
 	va_end(ap);
 
+	free(tmp);
+
 	usage_with_options_internal(usagestr, opts, 0, NULL);
 	exit(129);
 }
diff --git a/tools/perf/util/subcmd-util.h b/tools/perf/util/subcmd-util.h
new file mode 100644
index 000000000000..98fb9f9270eb
--- /dev/null
+++ b/tools/perf/util/subcmd-util.h
@@ -0,0 +1,24 @@
+#ifndef __PERF_SUBCMD_UTIL_H
+#define __PERF_SUBCMD_UTIL_H
+
+#include <stdio.h>
+
+#define astrcatf(out, fmt, ...)						\
+({									\
+	char *tmp = *(out);						\
+	if (asprintf((out), "%s" fmt, tmp ?: "", ## __VA_ARGS__) == -1)	\
+		die("asprintf failed");					\
+	free(tmp);							\
+})
+
+static inline void astrcat(char **out, const char *add)
+{
+	char *tmp = *out;
+
+	if (asprintf(out, "%s%s", tmp ?: "", add) == -1)
+		die("asprintf failed");
+
+	free(tmp);
+}
+
+#endif /* __PERF_SUBCMD_UTIL_H */
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 07/10] perf tools: Remove 'perf' from subcmd function and variable names
  2015-12-17  0:47 [GIT PULL 00/10] perf/core improvements Arnaldo Carvalho de Melo
                   ` (5 preceding siblings ...)
  2015-12-17  0:47 ` [PATCH 06/10] perf tools: Remove subcmd dependencies on strbuf Arnaldo Carvalho de Melo
@ 2015-12-17  0:48 ` Arnaldo Carvalho de Melo
  2015-12-17  0:48 ` [PATCH 08/10] perf tools: Finalize subcmd independence Arnaldo Carvalho de Melo
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17  0:48 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Josh Poimboeuf, Jiri Olsa, Namhyung Kim,
	Peter Zijlstra, Arnaldo Carvalho de Melo

From: Josh Poimboeuf <jpoimboe@redhat.com>

In preparation for moving exec_cmd.c and run-command.c out of perf and
into a library, remove 'perf' from all the symbol names.

Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/bc3ee82b40b8f396b644fa49e0f7260ce442635b.1450193761.git.jpoimboe@redhat.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-help.c     |  2 +-
 tools/perf/builtin-script.c   |  8 ++++----
 tools/perf/perf.c             |  6 +++---
 tools/perf/tests/attr.c       |  2 +-
 tools/perf/util/exec_cmd.c    | 20 ++++++++++----------
 tools/perf/util/exec_cmd.h    | 12 ++++++------
 tools/perf/util/help.c        |  4 ++--
 tools/perf/util/run-command.c |  6 +++---
 tools/perf/util/run-command.h |  4 ++--
 9 files changed, 32 insertions(+), 32 deletions(-)

diff --git a/tools/perf/builtin-help.c b/tools/perf/builtin-help.c
index a7d588bf3cdd..275aa641c31c 100644
--- a/tools/perf/builtin-help.c
+++ b/tools/perf/builtin-help.c
@@ -407,7 +407,7 @@ static int get_html_page_path(struct strbuf *page_path, const char *page)
 #ifndef open_html
 static void open_html(const char *path)
 {
-	execl_perf_cmd("web--browse", "-c", "help.browser", path, NULL);
+	execl_cmd("web--browse", "-c", "help.browser", path, NULL);
 }
 #endif
 
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index d259e9aa3a71..571016f16c5a 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -1408,7 +1408,7 @@ static int list_available_scripts(const struct option *opt __maybe_unused,
 	char first_half[BUFSIZ];
 	char *script_root;
 
-	snprintf(scripts_path, MAXPATHLEN, "%s/scripts", perf_exec_path());
+	snprintf(scripts_path, MAXPATHLEN, "%s/scripts", get_argv_exec_path());
 
 	scripts_dir = opendir(scripts_path);
 	if (!scripts_dir)
@@ -1529,7 +1529,7 @@ int find_scripts(char **scripts_array, char **scripts_path_array)
 	if (!session)
 		return -1;
 
-	snprintf(scripts_path, MAXPATHLEN, "%s/scripts", perf_exec_path());
+	snprintf(scripts_path, MAXPATHLEN, "%s/scripts", get_argv_exec_path());
 
 	scripts_dir = opendir(scripts_path);
 	if (!scripts_dir) {
@@ -1587,7 +1587,7 @@ static char *get_script_path(const char *script_root, const char *suffix)
 	char lang_path[MAXPATHLEN];
 	char *__script_root;
 
-	snprintf(scripts_path, MAXPATHLEN, "%s/scripts", perf_exec_path());
+	snprintf(scripts_path, MAXPATHLEN, "%s/scripts", get_argv_exec_path());
 
 	scripts_dir = opendir(scripts_path);
 	if (!scripts_dir)
@@ -1823,7 +1823,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
 		scripting_max_stack = itrace_synth_opts.callchain_sz;
 
 	/* make sure PERF_EXEC_PATH is set for scripts */
-	perf_set_argv_exec_path(perf_exec_path());
+	set_argv_exec_path(get_argv_exec_path());
 
 	if (argc && !script_name && !rec_script_path && !rep_script_path) {
 		int live_pipe[2];
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 783a3310a9d8..6894325fe921 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -183,9 +183,9 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
 		if (!prefixcmp(cmd, CMD_EXEC_PATH)) {
 			cmd += strlen(CMD_EXEC_PATH);
 			if (*cmd == '=')
-				perf_set_argv_exec_path(cmd + 1);
+				set_argv_exec_path(cmd + 1);
 			else {
-				puts(perf_exec_path());
+				puts(get_argv_exec_path());
 				exit(0);
 			}
 		} else if (!strcmp(cmd, "--html-path")) {
@@ -538,7 +538,7 @@ int main(int argc, const char **argv)
 	page_size = sysconf(_SC_PAGE_SIZE);
 	cacheline_size = sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
 
-	cmd = perf_extract_argv0_path(argv[0]);
+	cmd = extract_argv0_path(argv[0]);
 	if (!cmd)
 		cmd = "perf-help";
 
diff --git a/tools/perf/tests/attr.c b/tools/perf/tests/attr.c
index b66730eb94e3..6337f1c07f02 100644
--- a/tools/perf/tests/attr.c
+++ b/tools/perf/tests/attr.c
@@ -164,7 +164,7 @@ int test__attr(int subtest __maybe_unused)
 		return run_dir("./tests", "./perf");
 
 	/* Then installed path. */
-	snprintf(path_dir,  PATH_MAX, "%s/tests", perf_exec_path());
+	snprintf(path_dir,  PATH_MAX, "%s/tests", get_argv_exec_path());
 	snprintf(path_perf, PATH_MAX, "%s/perf", BINDIR);
 
 	if (!lstat(path_dir, &st) &&
diff --git a/tools/perf/util/exec_cmd.c b/tools/perf/util/exec_cmd.c
index 65d86dcaa984..701111ac7699 100644
--- a/tools/perf/util/exec_cmd.c
+++ b/tools/perf/util/exec_cmd.c
@@ -32,7 +32,7 @@ char *system_path(const char *path)
 	return buf;
 }
 
-const char *perf_extract_argv0_path(const char *argv0)
+const char *extract_argv0_path(const char *argv0)
 {
 	const char *slash;
 
@@ -51,7 +51,7 @@ const char *perf_extract_argv0_path(const char *argv0)
 	return argv0;
 }
 
-void perf_set_argv_exec_path(const char *exec_path)
+void set_argv_exec_path(const char *exec_path)
 {
 	argv_exec_path = exec_path;
 	/*
@@ -61,8 +61,8 @@ void perf_set_argv_exec_path(const char *exec_path)
 }
 
 
-/* Returns the highest-priority, location to look for perf programs. */
-char *perf_exec_path(void)
+/* Returns the highest-priority location to look for subprograms. */
+char *get_argv_exec_path(void)
 {
 	char *env;
 
@@ -92,7 +92,7 @@ void setup_path(void)
 {
 	const char *old_path = getenv("PATH");
 	char *new_path = NULL;
-	char *tmp = perf_exec_path();
+	char *tmp = get_argv_exec_path();
 
 	add_path(&new_path, tmp);
 	add_path(&new_path, argv0_path);
@@ -108,7 +108,7 @@ void setup_path(void)
 	free(new_path);
 }
 
-static const char **prepare_perf_cmd(const char **argv)
+static const char **prepare_exec_cmd(const char **argv)
 {
 	int argc;
 	const char **nargv;
@@ -124,8 +124,8 @@ static const char **prepare_perf_cmd(const char **argv)
 	return nargv;
 }
 
-int execv_perf_cmd(const char **argv) {
-	const char **nargv = prepare_perf_cmd(argv);
+int execv_cmd(const char **argv) {
+	const char **nargv = prepare_exec_cmd(argv);
 
 	/* execvp() can only ever return if it fails */
 	execvp(subcmd_config.exec_name, (char **)nargv);
@@ -135,7 +135,7 @@ int execv_perf_cmd(const char **argv) {
 }
 
 
-int execl_perf_cmd(const char *cmd,...)
+int execl_cmd(const char *cmd,...)
 {
 	int argc;
 	const char *argv[MAX_ARGS + 1];
@@ -155,5 +155,5 @@ int execl_perf_cmd(const char *cmd,...)
 		return error("too many args to run %s", cmd);
 
 	argv[argc] = NULL;
-	return execv_perf_cmd(argv);
+	return execv_cmd(argv);
 }
diff --git a/tools/perf/util/exec_cmd.h b/tools/perf/util/exec_cmd.h
index fd4434e48d21..f1bd3436ad5f 100644
--- a/tools/perf/util/exec_cmd.h
+++ b/tools/perf/util/exec_cmd.h
@@ -4,13 +4,13 @@
 extern void exec_cmd_init(const char *exec_name, const char *prefix,
 			  const char *exec_path, const char *exec_path_env);
 
-extern void perf_set_argv_exec_path(const char *exec_path);
-extern const char *perf_extract_argv0_path(const char *path);
+extern void set_argv_exec_path(const char *exec_path);
+extern const char *extract_argv0_path(const char *path);
 extern void setup_path(void);
-extern int execv_perf_cmd(const char **argv); /* NULL terminated */
-extern int execl_perf_cmd(const char *cmd, ...);
-/* perf_exec_path and system_path return malloc'd string, caller must free it */
-extern char *perf_exec_path(void);
+extern int execv_cmd(const char **argv); /* NULL terminated */
+extern int execl_cmd(const char *cmd, ...);
+/* get_argv_exec_path and system_path return malloc'd string, caller must free it */
+extern char *get_argv_exec_path(void);
 extern char *system_path(const char *path);
 
 #endif /* __PERF_EXEC_CMD_H */
diff --git a/tools/perf/util/help.c b/tools/perf/util/help.c
index 8e5e0ce3870e..303a347ee234 100644
--- a/tools/perf/util/help.c
+++ b/tools/perf/util/help.c
@@ -155,7 +155,7 @@ void load_command_list(const char *prefix,
 		struct cmdnames *other_cmds)
 {
 	const char *env_path = getenv("PATH");
-	char *exec_path = perf_exec_path();
+	char *exec_path = get_argv_exec_path();
 
 	if (exec_path) {
 		list_commands_in_dir(main_cmds, exec_path, prefix);
@@ -200,7 +200,7 @@ void list_commands(const char *title, struct cmdnames *main_cmds,
 			longest = other_cmds->names[i]->len;
 
 	if (main_cmds->cnt) {
-		char *exec_path = perf_exec_path();
+		char *exec_path = get_argv_exec_path();
 		printf("available %s in '%s'\n", title, exec_path);
 		printf("----------------");
 		mput_char('-', strlen(title) + strlen(exec_path));
diff --git a/tools/perf/util/run-command.c b/tools/perf/util/run-command.c
index 34622b53e733..910c0f6479f4 100644
--- a/tools/perf/util/run-command.c
+++ b/tools/perf/util/run-command.c
@@ -112,8 +112,8 @@ int start_command(struct child_process *cmd)
 		}
 		if (cmd->preexec_cb)
 			cmd->preexec_cb();
-		if (cmd->perf_cmd) {
-			execv_perf_cmd(cmd->argv);
+		if (cmd->exec_cmd) {
+			execv_cmd(cmd->argv);
 		} else {
 			execvp(cmd->argv[0], (char *const*) cmd->argv);
 		}
@@ -207,7 +207,7 @@ static void prepare_run_command_v_opt(struct child_process *cmd,
 	memset(cmd, 0, sizeof(*cmd));
 	cmd->argv = argv;
 	cmd->no_stdin = opt & RUN_COMMAND_NO_STDIN ? 1 : 0;
-	cmd->perf_cmd = opt & RUN_PERF_CMD ? 1 : 0;
+	cmd->exec_cmd = opt & RUN_EXEC_CMD ? 1 : 0;
 	cmd->stdout_to_stderr = opt & RUN_COMMAND_STDOUT_TO_STDERR ? 1 : 0;
 }
 
diff --git a/tools/perf/util/run-command.h b/tools/perf/util/run-command.h
index 1ef264d5069c..cf7d655ee2a3 100644
--- a/tools/perf/util/run-command.h
+++ b/tools/perf/util/run-command.h
@@ -41,7 +41,7 @@ struct child_process {
 	unsigned no_stdin:1;
 	unsigned no_stdout:1;
 	unsigned no_stderr:1;
-	unsigned perf_cmd:1; /* if this is to be perf sub-command */
+	unsigned exec_cmd:1; /* if this is to be external sub-command */
 	unsigned stdout_to_stderr:1;
 	void (*preexec_cb)(void);
 };
@@ -51,7 +51,7 @@ int finish_command(struct child_process *);
 int run_command(struct child_process *);
 
 #define RUN_COMMAND_NO_STDIN 1
-#define RUN_PERF_CMD	     2	/*If this is to be perf sub-command */
+#define RUN_EXEC_CMD	     2	/*If this is to be external sub-command */
 #define RUN_COMMAND_STDOUT_TO_STDERR 4
 int run_command_v_opt(const char **argv, int opt);
 
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 08/10] perf tools: Finalize subcmd independence
  2015-12-17  0:47 [GIT PULL 00/10] perf/core improvements Arnaldo Carvalho de Melo
                   ` (6 preceding siblings ...)
  2015-12-17  0:48 ` [PATCH 07/10] perf tools: Remove 'perf' from subcmd function and variable names Arnaldo Carvalho de Melo
@ 2015-12-17  0:48 ` Arnaldo Carvalho de Melo
  2015-12-17  0:48 ` [PATCH 09/10] perf subcmd: Create subcmd library Arnaldo Carvalho de Melo
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17  0:48 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Josh Poimboeuf, Jiri Olsa, Namhyung Kim,
	Peter Zijlstra, Arnaldo Carvalho de Melo

From: Josh Poimboeuf <jpoimboe@redhat.com>

For the files that will be moved to the subcmd library, remove all their
perf-specific includes and duplicate any needed functionality.

Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/6e12946f0f26ce4d543d34db68d9dae3c8551cb9.1450193761.git.jpoimboe@redhat.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/exec_cmd.c      | 64 +++++++++++++++++++++++++++++++----
 tools/perf/util/help.c          | 47 +++++++++++++++++++++++---
 tools/perf/util/help.h          |  4 ++-
 tools/perf/util/pager.c         |  7 +++-
 tools/perf/util/parse-options.c | 74 +++++++++++++++++++++++++----------------
 tools/perf/util/parse-options.h |  2 +-
 tools/perf/util/run-command.c   | 16 ++++++---
 tools/perf/util/run-command.h   |  2 ++
 tools/perf/util/sigchain.c      |  3 +-
 tools/perf/util/subcmd-util.h   | 67 +++++++++++++++++++++++++++++++++++++
 tools/perf/util/util.h          | 14 --------
 11 files changed, 238 insertions(+), 62 deletions(-)

diff --git a/tools/perf/util/exec_cmd.c b/tools/perf/util/exec_cmd.c
index 701111ac7699..e7f9ed7943e3 100644
--- a/tools/perf/util/exec_cmd.c
+++ b/tools/perf/util/exec_cmd.c
@@ -1,12 +1,17 @@
-#include "cache.h"
-#include "exec_cmd.h"
-#include "quote.h"
-#include "subcmd-config.h"
-
+#include <linux/compiler.h>
+#include <linux/string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
 #include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
 #include "subcmd-util.h"
+#include "exec_cmd.h"
+#include "subcmd-config.h"
 
 #define MAX_ARGS	32
+#define PATH_MAX	4096
 
 static const char *argv_exec_path;
 static const char *argv0_path;
@@ -20,6 +25,49 @@ void exec_cmd_init(const char *exec_name, const char *prefix,
 	subcmd_config.exec_path_env	= exec_path_env;
 }
 
+#define is_dir_sep(c) ((c) == '/')
+
+static int is_absolute_path(const char *path)
+{
+	return path[0] == '/';
+}
+
+static const char *get_pwd_cwd(void)
+{
+	static char cwd[PATH_MAX + 1];
+	char *pwd;
+	struct stat cwd_stat, pwd_stat;
+	if (getcwd(cwd, PATH_MAX) == NULL)
+		return NULL;
+	pwd = getenv("PWD");
+	if (pwd && strcmp(pwd, cwd)) {
+		stat(cwd, &cwd_stat);
+		if (!stat(pwd, &pwd_stat) &&
+		    pwd_stat.st_dev == cwd_stat.st_dev &&
+		    pwd_stat.st_ino == cwd_stat.st_ino) {
+			strlcpy(cwd, pwd, PATH_MAX);
+		}
+	}
+	return cwd;
+}
+
+static const char *make_nonrelative_path(const char *path)
+{
+	static char buf[PATH_MAX + 1];
+
+	if (is_absolute_path(path)) {
+		if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX)
+			die("Too long path: %.*s", 60, path);
+	} else {
+		const char *cwd = get_pwd_cwd();
+		if (!cwd)
+			die("Cannot determine the current working directory");
+		if (snprintf(buf, PATH_MAX, "%s/%s", cwd, path) >= PATH_MAX)
+			die("Too long path: %.*s", 60, path);
+	}
+	return buf;
+}
+
 char *system_path(const char *path)
 {
 	char *buf = NULL;
@@ -151,8 +199,10 @@ int execl_cmd(const char *cmd,...)
 			break;
 	}
 	va_end(param);
-	if (MAX_ARGS <= argc)
-		return error("too many args to run %s", cmd);
+	if (MAX_ARGS <= argc) {
+		fprintf(stderr, " Error: too many args to run %s\n", cmd);
+		return -1;
+	}
 
 	argv[argc] = NULL;
 	return execv_cmd(argv);
diff --git a/tools/perf/util/help.c b/tools/perf/util/help.c
index 303a347ee234..8169480066c6 100644
--- a/tools/perf/util/help.c
+++ b/tools/perf/util/help.c
@@ -1,8 +1,15 @@
-#include "cache.h"
-#include "../builtin.h"
-#include "exec_cmd.h"
-#include "help.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <dirent.h>
 #include "subcmd-util.h"
+#include "help.h"
+#include "exec_cmd.h"
 
 void add_cmdname(struct cmdnames *cmds, const char *name, size_t len)
 {
@@ -70,6 +77,28 @@ void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes)
 	cmds->cnt = cj;
 }
 
+static void get_term_dimensions(struct winsize *ws)
+{
+	char *s = getenv("LINES");
+
+	if (s != NULL) {
+		ws->ws_row = atoi(s);
+		s = getenv("COLUMNS");
+		if (s != NULL) {
+			ws->ws_col = atoi(s);
+			if (ws->ws_row && ws->ws_col)
+				return;
+		}
+	}
+#ifdef TIOCGWINSZ
+	if (ioctl(1, TIOCGWINSZ, ws) == 0 &&
+	    ws->ws_row && ws->ws_col)
+		return;
+#endif
+	ws->ws_row = 25;
+	ws->ws_col = 80;
+}
+
 static void pretty_print_string_list(struct cmdnames *cmds, int longest)
 {
 	int cols = 1, rows;
@@ -113,6 +142,14 @@ static int is_executable(const char *name)
 	return st.st_mode & S_IXUSR;
 }
 
+static int has_extension(const char *filename, const char *ext)
+{
+	size_t len = strlen(filename);
+	size_t extlen = strlen(ext);
+
+	return len > extlen && !memcmp(filename + len - extlen, ext, extlen);
+}
+
 static void list_commands_in_dir(struct cmdnames *cmds,
 					 const char *path,
 					 const char *prefix)
@@ -168,7 +205,7 @@ void load_command_list(const char *prefix,
 		char *paths, *path, *colon;
 		path = paths = strdup(env_path);
 		while (1) {
-			if ((colon = strchr(path, PATH_SEP)))
+			if ((colon = strchr(path, ':')))
 				*colon = 0;
 			if (!exec_path || strcmp(path, exec_path))
 				list_commands_in_dir(other_cmds, path, prefix);
diff --git a/tools/perf/util/help.h b/tools/perf/util/help.h
index 14851b0e44f5..096c8bc45cd7 100644
--- a/tools/perf/util/help.h
+++ b/tools/perf/util/help.h
@@ -1,12 +1,14 @@
 #ifndef __PERF_HELP_H
 #define __PERF_HELP_H
 
+#include <sys/types.h>
+
 struct cmdnames {
 	size_t alloc;
 	size_t cnt;
 	struct cmdname {
 		size_t len; /* also used for similarity index in help.c */
-		char name[FLEX_ARRAY];
+		char name[];
 	} **names;
 };
 
diff --git a/tools/perf/util/pager.c b/tools/perf/util/pager.c
index d5ef62eaa413..d50f3b58606b 100644
--- a/tools/perf/util/pager.c
+++ b/tools/perf/util/pager.c
@@ -1,4 +1,9 @@
-#include "cache.h"
+#include <sys/select.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include "pager.h"
 #include "run-command.h"
 #include "sigchain.h"
 #include "subcmd-config.h"
diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c
index c1da2a53ed4e..f4240275714a 100644
--- a/tools/perf/util/parse-options.c
+++ b/tools/perf/util/parse-options.c
@@ -1,33 +1,47 @@
-#include "util.h"
+#include <linux/compiler.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <ctype.h>
 #include "subcmd-util.h"
 #include "parse-options.h"
-#include "cache.h"
-#include "header.h"
 #include "subcmd-config.h"
-#include <linux/string.h>
+#include "pager.h"
 
 #define OPT_SHORT 1
 #define OPT_UNSET 2
 
+typedef uint64_t u64;
+
 char *error_buf;
 
 static int opterror(const struct option *opt, const char *reason, int flags)
 {
 	if (flags & OPT_SHORT)
-		return error("switch `%c' %s", opt->short_name, reason);
-	if (flags & OPT_UNSET)
-		return error("option `no-%s' %s", opt->long_name, reason);
-	return error("option `%s' %s", opt->long_name, reason);
+		fprintf(stderr, " Error: switch `%c' %s", opt->short_name, reason);
+	else if (flags & OPT_UNSET)
+		fprintf(stderr, " Error: option `no-%s' %s", opt->long_name, reason);
+	else
+		fprintf(stderr, " Error: option `%s' %s", opt->long_name, reason);
+
+	return -1;
+}
+
+static const char *skip_prefix(const char *str, const char *prefix)
+{
+	size_t len = strlen(prefix);
+	return strncmp(str, prefix, len) ? NULL : str + len;
 }
 
 static void optwarning(const struct option *opt, const char *reason, int flags)
 {
 	if (flags & OPT_SHORT)
-		warning("switch `%c' %s", opt->short_name, reason);
+		fprintf(stderr, " Warning: switch `%c' %s", opt->short_name, reason);
 	else if (flags & OPT_UNSET)
-		warning("option `no-%s' %s", opt->long_name, reason);
+		fprintf(stderr, " Warning: option `no-%s' %s", opt->long_name, reason);
 	else
-		warning("option `%s' %s", opt->long_name, reason);
+		fprintf(stderr, " Warning: option `%s' %s", opt->long_name, reason);
 }
 
 static int get_arg(struct parse_opt_ctx_t *p, const struct option *opt,
@@ -71,11 +85,11 @@ static int get_value(struct parse_opt_ctx_t *p,
 
 			if (((flags & OPT_SHORT) && p->excl_opt->short_name) ||
 			    p->excl_opt->long_name == NULL) {
-				scnprintf(msg, sizeof(msg), "cannot be used with switch `%c'",
-					  p->excl_opt->short_name);
+				snprintf(msg, sizeof(msg), "cannot be used with switch `%c'",
+					 p->excl_opt->short_name);
 			} else {
-				scnprintf(msg, sizeof(msg), "cannot be used with %s",
-					  p->excl_opt->long_name);
+				snprintf(msg, sizeof(msg), "cannot be used with %s",
+					 p->excl_opt->long_name);
 			}
 			opterror(opt, msg, flags);
 			return -3;
@@ -401,14 +415,16 @@ match:
 		return get_value(p, options, flags);
 	}
 
-	if (ambiguous_option)
-		return error("Ambiguous option: %s "
-			"(could be --%s%s or --%s%s)",
-			arg,
-			(ambiguous_flags & OPT_UNSET) ?  "no-" : "",
-			ambiguous_option->long_name,
-			(abbrev_flags & OPT_UNSET) ?  "no-" : "",
-			abbrev_option->long_name);
+	if (ambiguous_option) {
+		 fprintf(stderr,
+			 " Error: Ambiguous option: %s (could be --%s%s or --%s%s)",
+			 arg,
+			 (ambiguous_flags & OPT_UNSET) ?  "no-" : "",
+			 ambiguous_option->long_name,
+			 (abbrev_flags & OPT_UNSET) ?  "no-" : "",
+			 abbrev_option->long_name);
+		 return -1;
+	}
 	if (abbrev_option)
 		return get_value(p, abbrev_option, abbrev_flags);
 	return -2;
@@ -420,7 +436,7 @@ static void check_typos(const char *arg, const struct option *options)
 		return;
 
 	if (!prefixcmp(arg, "no-")) {
-		error ("did you mean `--%s` (with two dashes ?)", arg);
+		fprintf(stderr, " Error: did you mean `--%s` (with two dashes ?)", arg);
 		exit(129);
 	}
 
@@ -428,7 +444,7 @@ static void check_typos(const char *arg, const struct option *options)
 		if (!options->long_name)
 			continue;
 		if (!prefixcmp(options->long_name, arg)) {
-			error ("did you mean `--%s` (with two dashes ?)", arg);
+			fprintf(stderr, " Error: did you mean `--%s` (with two dashes ?)", arg);
 			exit(129);
 		}
 	}
@@ -746,16 +762,18 @@ static int option__cmp(const void *va, const void *vb)
 
 static struct option *options__order(const struct option *opts)
 {
-	int nr_opts = 0;
+	int nr_opts = 0, len;
 	const struct option *o = opts;
 	struct option *ordered;
 
 	for (o = opts; o->type != OPTION_END; o++)
 		++nr_opts;
 
-	ordered = memdup(opts, sizeof(*o) * (nr_opts + 1));
-	if (ordered == NULL)
+	len = sizeof(*o) * (nr_opts + 1);
+	ordered = malloc(len);
+	if (!ordered)
 		goto out;
+	memcpy(ordered, opts, len);
 
 	qsort(ordered, nr_opts, sizeof(*o), option__cmp);
 out:
diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h
index d1544069c7c0..dec893f10477 100644
--- a/tools/perf/util/parse-options.h
+++ b/tools/perf/util/parse-options.h
@@ -1,8 +1,8 @@
 #ifndef __PERF_PARSE_OPTIONS_H
 #define __PERF_PARSE_OPTIONS_H
 
-#include <linux/kernel.h>
 #include <stdbool.h>
+#include <stdint.h>
 
 enum parse_opt_type {
 	/* special types */
diff --git a/tools/perf/util/run-command.c b/tools/perf/util/run-command.c
index 910c0f6479f4..fed37d6ae070 100644
--- a/tools/perf/util/run-command.c
+++ b/tools/perf/util/run-command.c
@@ -1,7 +1,15 @@
-#include "cache.h"
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/wait.h>
+#include "subcmd-util.h"
 #include "run-command.h"
 #include "exec_cmd.h"
-#include "debug.h"
+
+#define STRERR_BUFSIZE 128
 
 static inline void close_pair(int fd[2])
 {
@@ -164,8 +172,8 @@ static int wait_or_whine(pid_t pid)
 		if (waiting < 0) {
 			if (errno == EINTR)
 				continue;
-			error("waitpid failed (%s)",
-			      strerror_r(errno, sbuf, sizeof(sbuf)));
+			fprintf(stderr, " Error: waitpid failed (%s)",
+				strerror_r(errno, sbuf, sizeof(sbuf)));
 			return -ERR_RUN_COMMAND_WAITPID;
 		}
 		if (waiting != pid)
diff --git a/tools/perf/util/run-command.h b/tools/perf/util/run-command.h
index cf7d655ee2a3..4a55393a6547 100644
--- a/tools/perf/util/run-command.h
+++ b/tools/perf/util/run-command.h
@@ -1,6 +1,8 @@
 #ifndef __PERF_RUN_COMMAND_H
 #define __PERF_RUN_COMMAND_H
 
+#include <unistd.h>
+
 enum {
 	ERR_RUN_COMMAND_FORK = 10000,
 	ERR_RUN_COMMAND_EXEC,
diff --git a/tools/perf/util/sigchain.c b/tools/perf/util/sigchain.c
index ba785e9b1841..3537c348a18e 100644
--- a/tools/perf/util/sigchain.c
+++ b/tools/perf/util/sigchain.c
@@ -1,5 +1,6 @@
+#include <signal.h>
+#include "subcmd-util.h"
 #include "sigchain.h"
-#include "cache.h"
 
 #define SIGCHAIN_MAX_SIGNALS 32
 
diff --git a/tools/perf/util/subcmd-util.h b/tools/perf/util/subcmd-util.h
index 98fb9f9270eb..321aeb11a381 100644
--- a/tools/perf/util/subcmd-util.h
+++ b/tools/perf/util/subcmd-util.h
@@ -1,8 +1,66 @@
 #ifndef __PERF_SUBCMD_UTIL_H
 #define __PERF_SUBCMD_UTIL_H
 
+#include <stdarg.h>
+#include <stdlib.h>
 #include <stdio.h>
 
+#define NORETURN __attribute__((__noreturn__))
+
+static inline void report(const char *prefix, const char *err, va_list params)
+{
+	char msg[1024];
+	vsnprintf(msg, sizeof(msg), err, params);
+	fprintf(stderr, " %s%s\n", prefix, msg);
+}
+
+static NORETURN inline void die(const char *err, ...)
+{
+	va_list params;
+
+	va_start(params, err);
+	report(" Fatal: ", err, params);
+	exit(128);
+	va_end(params);
+}
+
+#define zfree(ptr) ({ free(*ptr); *ptr = NULL; })
+
+#define alloc_nr(x) (((x)+16)*3/2)
+
+/*
+ * Realloc the buffer pointed at by variable 'x' so that it can hold
+ * at least 'nr' entries; the number of entries currently allocated
+ * is 'alloc', using the standard growing factor alloc_nr() macro.
+ *
+ * DO NOT USE any expression with side-effect for 'x' or 'alloc'.
+ */
+#define ALLOC_GROW(x, nr, alloc) \
+	do { \
+		if ((nr) > alloc) { \
+			if (alloc_nr(alloc) < (nr)) \
+				alloc = (nr); \
+			else \
+				alloc = alloc_nr(alloc); \
+			x = xrealloc((x), alloc * sizeof(*(x))); \
+		} \
+	} while(0)
+
+static inline void *xrealloc(void *ptr, size_t size)
+{
+	void *ret = realloc(ptr, size);
+	if (!ret && !size)
+		ret = realloc(ptr, 1);
+	if (!ret) {
+		ret = realloc(ptr, size);
+		if (!ret && !size)
+			ret = realloc(ptr, 1);
+		if (!ret)
+			die("Out of memory, realloc failed");
+	}
+	return ret;
+}
+
 #define astrcatf(out, fmt, ...)						\
 ({									\
 	char *tmp = *(out);						\
@@ -21,4 +79,13 @@ static inline void astrcat(char **out, const char *add)
 	free(tmp);
 }
 
+static inline int prefixcmp(const char *str, const char *prefix)
+{
+	for (; ; str++, prefix++)
+		if (!*prefix)
+			return 0;
+		else if (*str != *prefix)
+			return (unsigned char)*prefix - (unsigned char)*str;
+}
+
 #endif /* __PERF_SUBCMD_UTIL_H */
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 150858f3b4f0..4b519c59bdc3 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -151,12 +151,6 @@ extern void set_warning_routine(void (*routine)(const char *err, va_list params)
 extern int prefixcmp(const char *str, const char *prefix);
 extern void set_buildid_dir(const char *dir);
 
-static inline const char *skip_prefix(const char *str, const char *prefix)
-{
-	size_t len = strlen(prefix);
-	return strncmp(str, prefix, len) ? NULL : str + len;
-}
-
 #ifdef __GLIBC_PREREQ
 #if __GLIBC_PREREQ(2, 1)
 #define HAVE_STRCHRNUL
@@ -187,14 +181,6 @@ static inline void *zalloc(size_t size)
 
 #define zfree(ptr) ({ free(*ptr); *ptr = NULL; })
 
-static inline int has_extension(const char *filename, const char *ext)
-{
-	size_t len = strlen(filename);
-	size_t extlen = strlen(ext);
-
-	return len > extlen && !memcmp(filename + len - extlen, ext, extlen);
-}
-
 /* Sane ctype - no locale, and works with signed chars */
 #undef isascii
 #undef isspace
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 09/10] perf subcmd: Create subcmd library
  2015-12-17  0:47 [GIT PULL 00/10] perf/core improvements Arnaldo Carvalho de Melo
                   ` (7 preceding siblings ...)
  2015-12-17  0:48 ` [PATCH 08/10] perf tools: Finalize subcmd independence Arnaldo Carvalho de Melo
@ 2015-12-17  0:48 ` Arnaldo Carvalho de Melo
  2015-12-17  0:48 ` [PATCH 10/10] tools subcmd: Rename subcmd header include guards Arnaldo Carvalho de Melo
  2015-12-17 17:37 ` [GIT PULL 00/10] perf/core improvements Arnaldo Carvalho de Melo
  10 siblings, 0 replies; 14+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17  0:48 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Josh Poimboeuf, Jiri Olsa, Namhyung Kim,
	Peter Zijlstra, Arnaldo Carvalho de Melo

From: Josh Poimboeuf <jpoimboe@redhat.com>

Move the subcommand-related files from perf to a new library named
libsubcmd.a.

Since we're moving files anyway, go ahead and rename 'exec_cmd.*' to
'exec-cmd.*' to be consistent with the naming of all the other files.

Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/c0a838d4c878ab17fee50998811612b2281355c1.1450193761.git.jpoimboe@redhat.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/lib/subcmd/Build                 |   7 +
 tools/lib/subcmd/Makefile              |  48 ++
 tools/lib/subcmd/exec-cmd.c            | 209 +++++++
 tools/lib/subcmd/exec-cmd.h            |  16 +
 tools/lib/subcmd/help.c                | 268 +++++++++
 tools/lib/subcmd/help.h                |  34 ++
 tools/lib/subcmd/pager.c               | 100 ++++
 tools/lib/subcmd/pager.h               |   9 +
 tools/lib/subcmd/parse-options.c       | 984 +++++++++++++++++++++++++++++++++
 tools/lib/subcmd/parse-options.h       | 228 ++++++++
 tools/lib/subcmd/run-command.c         | 227 ++++++++
 tools/lib/subcmd/run-command.h         |  60 ++
 tools/lib/subcmd/sigchain.c            |  53 ++
 tools/lib/subcmd/sigchain.h            |  10 +
 tools/lib/subcmd/subcmd-config.c       |  11 +
 tools/lib/subcmd/subcmd-config.h       |  14 +
 tools/lib/subcmd/subcmd-util.h         |  91 +++
 tools/perf/MANIFEST                    |   1 +
 tools/perf/Makefile.perf               |  20 +-
 tools/perf/arch/x86/util/intel-pt.c    |   2 +-
 tools/perf/bench/futex-hash.c          |   2 +-
 tools/perf/bench/futex-lock-pi.c       |   2 +-
 tools/perf/bench/futex-requeue.c       |   2 +-
 tools/perf/bench/futex-wake-parallel.c |   2 +-
 tools/perf/bench/futex-wake.c          |   2 +-
 tools/perf/bench/mem-functions.c       |   2 +-
 tools/perf/bench/numa.c                |   2 +-
 tools/perf/bench/sched-messaging.c     |   2 +-
 tools/perf/bench/sched-pipe.c          |   2 +-
 tools/perf/builtin-annotate.c          |   2 +-
 tools/perf/builtin-bench.c             |   2 +-
 tools/perf/builtin-buildid-cache.c     |   2 +-
 tools/perf/builtin-buildid-list.c      |   2 +-
 tools/perf/builtin-config.c            |   2 +-
 tools/perf/builtin-data.c              |   2 +-
 tools/perf/builtin-evlist.c            |   2 +-
 tools/perf/builtin-help.c              |   8 +-
 tools/perf/builtin-inject.c            |   2 +-
 tools/perf/builtin-kmem.c              |   2 +-
 tools/perf/builtin-kvm.c               |   2 +-
 tools/perf/builtin-list.c              |   2 +-
 tools/perf/builtin-lock.c              |   2 +-
 tools/perf/builtin-mem.c               |   2 +-
 tools/perf/builtin-probe.c             |   2 +-
 tools/perf/builtin-record.c            |   2 +-
 tools/perf/builtin-report.c            |   2 +-
 tools/perf/builtin-sched.c             |   2 +-
 tools/perf/builtin-script.c            |   4 +-
 tools/perf/builtin-stat.c              |   2 +-
 tools/perf/builtin-timechart.c         |   2 +-
 tools/perf/builtin-top.c               |   2 +-
 tools/perf/builtin-trace.c             |   4 +-
 tools/perf/perf.c                      |   6 +-
 tools/perf/tests/attr.c                |   2 +-
 tools/perf/tests/builtin-test.c        |   2 +-
 tools/perf/util/Build                  |   7 -
 tools/perf/util/auxtrace.c             |   2 +-
 tools/perf/util/cache.h                |   2 +-
 tools/perf/util/cgroup.c               |   2 +-
 tools/perf/util/config.c               |   2 +-
 tools/perf/util/evlist.c               |   2 +-
 tools/perf/util/exec_cmd.c             | 209 -------
 tools/perf/util/exec_cmd.h             |  16 -
 tools/perf/util/help-unknown-cmd.c     |   2 +-
 tools/perf/util/help.c                 | 268 ---------
 tools/perf/util/help.h                 |  34 --
 tools/perf/util/pager.c                | 100 ----
 tools/perf/util/pager.h                |   9 -
 tools/perf/util/parse-branch-options.c |   2 +-
 tools/perf/util/parse-events.c         |   4 +-
 tools/perf/util/parse-options.c        | 984 ---------------------------------
 tools/perf/util/parse-options.h        | 228 --------
 tools/perf/util/parse-regs-options.c   |   2 +-
 tools/perf/util/run-command.c          | 227 --------
 tools/perf/util/run-command.h          |  60 --
 tools/perf/util/sigchain.c             |  53 --
 tools/perf/util/sigchain.h             |  10 -
 tools/perf/util/sort.h                 |   2 +-
 tools/perf/util/subcmd-config.c        |  11 -
 tools/perf/util/subcmd-config.h        |  14 -
 tools/perf/util/subcmd-util.h          |  91 ---
 81 files changed, 2440 insertions(+), 2379 deletions(-)
 create mode 100644 tools/lib/subcmd/Build
 create mode 100644 tools/lib/subcmd/Makefile
 create mode 100644 tools/lib/subcmd/exec-cmd.c
 create mode 100644 tools/lib/subcmd/exec-cmd.h
 create mode 100644 tools/lib/subcmd/help.c
 create mode 100644 tools/lib/subcmd/help.h
 create mode 100644 tools/lib/subcmd/pager.c
 create mode 100644 tools/lib/subcmd/pager.h
 create mode 100644 tools/lib/subcmd/parse-options.c
 create mode 100644 tools/lib/subcmd/parse-options.h
 create mode 100644 tools/lib/subcmd/run-command.c
 create mode 100644 tools/lib/subcmd/run-command.h
 create mode 100644 tools/lib/subcmd/sigchain.c
 create mode 100644 tools/lib/subcmd/sigchain.h
 create mode 100644 tools/lib/subcmd/subcmd-config.c
 create mode 100644 tools/lib/subcmd/subcmd-config.h
 create mode 100644 tools/lib/subcmd/subcmd-util.h
 delete mode 100644 tools/perf/util/exec_cmd.c
 delete mode 100644 tools/perf/util/exec_cmd.h
 delete mode 100644 tools/perf/util/help.c
 delete mode 100644 tools/perf/util/help.h
 delete mode 100644 tools/perf/util/pager.c
 delete mode 100644 tools/perf/util/pager.h
 delete mode 100644 tools/perf/util/parse-options.c
 delete mode 100644 tools/perf/util/parse-options.h
 delete mode 100644 tools/perf/util/run-command.c
 delete mode 100644 tools/perf/util/run-command.h
 delete mode 100644 tools/perf/util/sigchain.c
 delete mode 100644 tools/perf/util/sigchain.h
 delete mode 100644 tools/perf/util/subcmd-config.c
 delete mode 100644 tools/perf/util/subcmd-config.h
 delete mode 100644 tools/perf/util/subcmd-util.h

diff --git a/tools/lib/subcmd/Build b/tools/lib/subcmd/Build
new file mode 100644
index 000000000000..ee31288788c1
--- /dev/null
+++ b/tools/lib/subcmd/Build
@@ -0,0 +1,7 @@
+libsubcmd-y += exec-cmd.o
+libsubcmd-y += help.o
+libsubcmd-y += pager.o
+libsubcmd-y += parse-options.o
+libsubcmd-y += run-command.o
+libsubcmd-y += sigchain.o
+libsubcmd-y += subcmd-config.o
diff --git a/tools/lib/subcmd/Makefile b/tools/lib/subcmd/Makefile
new file mode 100644
index 000000000000..629cf8c14e68
--- /dev/null
+++ b/tools/lib/subcmd/Makefile
@@ -0,0 +1,48 @@
+include ../../scripts/Makefile.include
+include ../../perf/config/utilities.mak		# QUIET_CLEAN
+
+ifeq ($(srctree),)
+srctree := $(patsubst %/,%,$(dir $(shell pwd)))
+srctree := $(patsubst %/,%,$(dir $(srctree)))
+srctree := $(patsubst %/,%,$(dir $(srctree)))
+#$(info Determined 'srctree' to be $(srctree))
+endif
+
+CC = $(CROSS_COMPILE)gcc
+AR = $(CROSS_COMPILE)ar
+RM = rm -f
+
+MAKEFLAGS += --no-print-directory
+
+LIBFILE = $(OUTPUT)libsubcmd.a
+
+CFLAGS := $(EXTRA_WARNINGS) $(EXTRA_CFLAGS)
+CFLAGS += -ggdb3 -Wall -Wextra -std=gnu99 -Werror -O6 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fPIC
+CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
+
+CFLAGS += -I$(srctree)/tools/include/
+CFLAGS += -I$(srctree)/include/uapi
+CFLAGS += -I$(srctree)/include
+
+SUBCMD_IN := $(OUTPUT)libsubcmd-in.o
+
+all:
+
+export srctree OUTPUT CC LD CFLAGS V
+include $(srctree)/tools/build/Makefile.include
+
+all: fixdep $(LIBFILE)
+
+$(SUBCMD_IN): FORCE
+	@$(MAKE) $(build)=libsubcmd
+
+$(LIBFILE): $(SUBCMD_IN)
+	$(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(SUBCMD_IN)
+
+clean:
+	$(call QUIET_CLEAN, libsubcmd) $(RM) $(LIBFILE); \
+	find $(if $(OUTPUT),$(OUTPUT),.) -name \*.o -or -name \*.o.cmd -or -name \*.o.d | xargs $(RM)
+
+FORCE:
+
+.PHONY: clean FORCE
diff --git a/tools/lib/subcmd/exec-cmd.c b/tools/lib/subcmd/exec-cmd.c
new file mode 100644
index 000000000000..1ae833af1a4a
--- /dev/null
+++ b/tools/lib/subcmd/exec-cmd.c
@@ -0,0 +1,209 @@
+#include <linux/compiler.h>
+#include <linux/string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "subcmd-util.h"
+#include "exec-cmd.h"
+#include "subcmd-config.h"
+
+#define MAX_ARGS	32
+#define PATH_MAX	4096
+
+static const char *argv_exec_path;
+static const char *argv0_path;
+
+void exec_cmd_init(const char *exec_name, const char *prefix,
+		   const char *exec_path, const char *exec_path_env)
+{
+	subcmd_config.exec_name		= exec_name;
+	subcmd_config.prefix		= prefix;
+	subcmd_config.exec_path		= exec_path;
+	subcmd_config.exec_path_env	= exec_path_env;
+}
+
+#define is_dir_sep(c) ((c) == '/')
+
+static int is_absolute_path(const char *path)
+{
+	return path[0] == '/';
+}
+
+static const char *get_pwd_cwd(void)
+{
+	static char cwd[PATH_MAX + 1];
+	char *pwd;
+	struct stat cwd_stat, pwd_stat;
+	if (getcwd(cwd, PATH_MAX) == NULL)
+		return NULL;
+	pwd = getenv("PWD");
+	if (pwd && strcmp(pwd, cwd)) {
+		stat(cwd, &cwd_stat);
+		if (!stat(pwd, &pwd_stat) &&
+		    pwd_stat.st_dev == cwd_stat.st_dev &&
+		    pwd_stat.st_ino == cwd_stat.st_ino) {
+			strlcpy(cwd, pwd, PATH_MAX);
+		}
+	}
+	return cwd;
+}
+
+static const char *make_nonrelative_path(const char *path)
+{
+	static char buf[PATH_MAX + 1];
+
+	if (is_absolute_path(path)) {
+		if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX)
+			die("Too long path: %.*s", 60, path);
+	} else {
+		const char *cwd = get_pwd_cwd();
+		if (!cwd)
+			die("Cannot determine the current working directory");
+		if (snprintf(buf, PATH_MAX, "%s/%s", cwd, path) >= PATH_MAX)
+			die("Too long path: %.*s", 60, path);
+	}
+	return buf;
+}
+
+char *system_path(const char *path)
+{
+	char *buf = NULL;
+
+	if (is_absolute_path(path))
+		return strdup(path);
+
+	astrcatf(&buf, "%s/%s", subcmd_config.prefix, path);
+
+	return buf;
+}
+
+const char *extract_argv0_path(const char *argv0)
+{
+	const char *slash;
+
+	if (!argv0 || !*argv0)
+		return NULL;
+	slash = argv0 + strlen(argv0);
+
+	while (argv0 <= slash && !is_dir_sep(*slash))
+		slash--;
+
+	if (slash >= argv0) {
+		argv0_path = strndup(argv0, slash - argv0);
+		return argv0_path ? slash + 1 : NULL;
+	}
+
+	return argv0;
+}
+
+void set_argv_exec_path(const char *exec_path)
+{
+	argv_exec_path = exec_path;
+	/*
+	 * Propagate this setting to external programs.
+	 */
+	setenv(subcmd_config.exec_path_env, exec_path, 1);
+}
+
+
+/* Returns the highest-priority location to look for subprograms. */
+char *get_argv_exec_path(void)
+{
+	char *env;
+
+	if (argv_exec_path)
+		return strdup(argv_exec_path);
+
+	env = getenv(subcmd_config.exec_path_env);
+	if (env && *env)
+		return strdup(env);
+
+	return system_path(subcmd_config.exec_path);
+}
+
+static void add_path(char **out, const char *path)
+{
+	if (path && *path) {
+		if (is_absolute_path(path))
+			astrcat(out, path);
+		else
+			astrcat(out, make_nonrelative_path(path));
+
+		astrcat(out, ":");
+	}
+}
+
+void setup_path(void)
+{
+	const char *old_path = getenv("PATH");
+	char *new_path = NULL;
+	char *tmp = get_argv_exec_path();
+
+	add_path(&new_path, tmp);
+	add_path(&new_path, argv0_path);
+	free(tmp);
+
+	if (old_path)
+		astrcat(&new_path, old_path);
+	else
+		astrcat(&new_path, "/usr/local/bin:/usr/bin:/bin");
+
+	setenv("PATH", new_path, 1);
+
+	free(new_path);
+}
+
+static const char **prepare_exec_cmd(const char **argv)
+{
+	int argc;
+	const char **nargv;
+
+	for (argc = 0; argv[argc]; argc++)
+		; /* just counting */
+	nargv = malloc(sizeof(*nargv) * (argc + 2));
+
+	nargv[0] = subcmd_config.exec_name;
+	for (argc = 0; argv[argc]; argc++)
+		nargv[argc + 1] = argv[argc];
+	nargv[argc + 1] = NULL;
+	return nargv;
+}
+
+int execv_cmd(const char **argv) {
+	const char **nargv = prepare_exec_cmd(argv);
+
+	/* execvp() can only ever return if it fails */
+	execvp(subcmd_config.exec_name, (char **)nargv);
+
+	free(nargv);
+	return -1;
+}
+
+
+int execl_cmd(const char *cmd,...)
+{
+	int argc;
+	const char *argv[MAX_ARGS + 1];
+	const char *arg;
+	va_list param;
+
+	va_start(param, cmd);
+	argv[0] = cmd;
+	argc = 1;
+	while (argc < MAX_ARGS) {
+		arg = argv[argc++] = va_arg(param, char *);
+		if (!arg)
+			break;
+	}
+	va_end(param);
+	if (MAX_ARGS <= argc) {
+		fprintf(stderr, " Error: too many args to run %s\n", cmd);
+		return -1;
+	}
+
+	argv[argc] = NULL;
+	return execv_cmd(argv);
+}
diff --git a/tools/lib/subcmd/exec-cmd.h b/tools/lib/subcmd/exec-cmd.h
new file mode 100644
index 000000000000..f1bd3436ad5f
--- /dev/null
+++ b/tools/lib/subcmd/exec-cmd.h
@@ -0,0 +1,16 @@
+#ifndef __PERF_EXEC_CMD_H
+#define __PERF_EXEC_CMD_H
+
+extern void exec_cmd_init(const char *exec_name, const char *prefix,
+			  const char *exec_path, const char *exec_path_env);
+
+extern void set_argv_exec_path(const char *exec_path);
+extern const char *extract_argv0_path(const char *path);
+extern void setup_path(void);
+extern int execv_cmd(const char **argv); /* NULL terminated */
+extern int execl_cmd(const char *cmd, ...);
+/* get_argv_exec_path and system_path return malloc'd string, caller must free it */
+extern char *get_argv_exec_path(void);
+extern char *system_path(const char *path);
+
+#endif /* __PERF_EXEC_CMD_H */
diff --git a/tools/lib/subcmd/help.c b/tools/lib/subcmd/help.c
new file mode 100644
index 000000000000..e228c3cb3716
--- /dev/null
+++ b/tools/lib/subcmd/help.c
@@ -0,0 +1,268 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <dirent.h>
+#include "subcmd-util.h"
+#include "help.h"
+#include "exec-cmd.h"
+
+void add_cmdname(struct cmdnames *cmds, const char *name, size_t len)
+{
+	struct cmdname *ent = malloc(sizeof(*ent) + len + 1);
+
+	ent->len = len;
+	memcpy(ent->name, name, len);
+	ent->name[len] = 0;
+
+	ALLOC_GROW(cmds->names, cmds->cnt + 1, cmds->alloc);
+	cmds->names[cmds->cnt++] = ent;
+}
+
+void clean_cmdnames(struct cmdnames *cmds)
+{
+	unsigned int i;
+
+	for (i = 0; i < cmds->cnt; ++i)
+		zfree(&cmds->names[i]);
+	zfree(&cmds->names);
+	cmds->cnt = 0;
+	cmds->alloc = 0;
+}
+
+int cmdname_compare(const void *a_, const void *b_)
+{
+	struct cmdname *a = *(struct cmdname **)a_;
+	struct cmdname *b = *(struct cmdname **)b_;
+	return strcmp(a->name, b->name);
+}
+
+void uniq(struct cmdnames *cmds)
+{
+	unsigned int i, j;
+
+	if (!cmds->cnt)
+		return;
+
+	for (i = j = 1; i < cmds->cnt; i++)
+		if (strcmp(cmds->names[i]->name, cmds->names[i-1]->name))
+			cmds->names[j++] = cmds->names[i];
+
+	cmds->cnt = j;
+}
+
+void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes)
+{
+	size_t ci, cj, ei;
+	int cmp;
+
+	ci = cj = ei = 0;
+	while (ci < cmds->cnt && ei < excludes->cnt) {
+		cmp = strcmp(cmds->names[ci]->name, excludes->names[ei]->name);
+		if (cmp < 0)
+			cmds->names[cj++] = cmds->names[ci++];
+		else if (cmp == 0)
+			ci++, ei++;
+		else if (cmp > 0)
+			ei++;
+	}
+
+	while (ci < cmds->cnt)
+		cmds->names[cj++] = cmds->names[ci++];
+
+	cmds->cnt = cj;
+}
+
+static void get_term_dimensions(struct winsize *ws)
+{
+	char *s = getenv("LINES");
+
+	if (s != NULL) {
+		ws->ws_row = atoi(s);
+		s = getenv("COLUMNS");
+		if (s != NULL) {
+			ws->ws_col = atoi(s);
+			if (ws->ws_row && ws->ws_col)
+				return;
+		}
+	}
+#ifdef TIOCGWINSZ
+	if (ioctl(1, TIOCGWINSZ, ws) == 0 &&
+	    ws->ws_row && ws->ws_col)
+		return;
+#endif
+	ws->ws_row = 25;
+	ws->ws_col = 80;
+}
+
+static void pretty_print_string_list(struct cmdnames *cmds, int longest)
+{
+	int cols = 1, rows;
+	int space = longest + 1; /* min 1 SP between words */
+	struct winsize win;
+	int max_cols;
+	int i, j;
+
+	get_term_dimensions(&win);
+	max_cols = win.ws_col - 1; /* don't print *on* the edge */
+
+	if (space < max_cols)
+		cols = max_cols / space;
+	rows = (cmds->cnt + cols - 1) / cols;
+
+	for (i = 0; i < rows; i++) {
+		printf("  ");
+
+		for (j = 0; j < cols; j++) {
+			unsigned int n = j * rows + i;
+			unsigned int size = space;
+
+			if (n >= cmds->cnt)
+				break;
+			if (j == cols-1 || n + rows >= cmds->cnt)
+				size = 1;
+			printf("%-*s", size, cmds->names[n]->name);
+		}
+		putchar('\n');
+	}
+}
+
+static int is_executable(const char *name)
+{
+	struct stat st;
+
+	if (stat(name, &st) || /* stat, not lstat */
+	    !S_ISREG(st.st_mode))
+		return 0;
+
+	return st.st_mode & S_IXUSR;
+}
+
+static int has_extension(const char *filename, const char *ext)
+{
+	size_t len = strlen(filename);
+	size_t extlen = strlen(ext);
+
+	return len > extlen && !memcmp(filename + len - extlen, ext, extlen);
+}
+
+static void list_commands_in_dir(struct cmdnames *cmds,
+					 const char *path,
+					 const char *prefix)
+{
+	int prefix_len;
+	DIR *dir = opendir(path);
+	struct dirent *de;
+	char *buf = NULL;
+
+	if (!dir)
+		return;
+	if (!prefix)
+		prefix = "perf-";
+	prefix_len = strlen(prefix);
+
+	astrcatf(&buf, "%s/", path);
+
+	while ((de = readdir(dir)) != NULL) {
+		int entlen;
+
+		if (prefixcmp(de->d_name, prefix))
+			continue;
+
+		astrcat(&buf, de->d_name);
+		if (!is_executable(buf))
+			continue;
+
+		entlen = strlen(de->d_name) - prefix_len;
+		if (has_extension(de->d_name, ".exe"))
+			entlen -= 4;
+
+		add_cmdname(cmds, de->d_name + prefix_len, entlen);
+	}
+	closedir(dir);
+	free(buf);
+}
+
+void load_command_list(const char *prefix,
+		struct cmdnames *main_cmds,
+		struct cmdnames *other_cmds)
+{
+	const char *env_path = getenv("PATH");
+	char *exec_path = get_argv_exec_path();
+
+	if (exec_path) {
+		list_commands_in_dir(main_cmds, exec_path, prefix);
+		qsort(main_cmds->names, main_cmds->cnt,
+		      sizeof(*main_cmds->names), cmdname_compare);
+		uniq(main_cmds);
+	}
+
+	if (env_path) {
+		char *paths, *path, *colon;
+		path = paths = strdup(env_path);
+		while (1) {
+			if ((colon = strchr(path, ':')))
+				*colon = 0;
+			if (!exec_path || strcmp(path, exec_path))
+				list_commands_in_dir(other_cmds, path, prefix);
+
+			if (!colon)
+				break;
+			path = colon + 1;
+		}
+		free(paths);
+
+		qsort(other_cmds->names, other_cmds->cnt,
+		      sizeof(*other_cmds->names), cmdname_compare);
+		uniq(other_cmds);
+	}
+	free(exec_path);
+	exclude_cmds(other_cmds, main_cmds);
+}
+
+void list_commands(const char *title, struct cmdnames *main_cmds,
+		   struct cmdnames *other_cmds)
+{
+	unsigned int i, longest = 0;
+
+	for (i = 0; i < main_cmds->cnt; i++)
+		if (longest < main_cmds->names[i]->len)
+			longest = main_cmds->names[i]->len;
+	for (i = 0; i < other_cmds->cnt; i++)
+		if (longest < other_cmds->names[i]->len)
+			longest = other_cmds->names[i]->len;
+
+	if (main_cmds->cnt) {
+		char *exec_path = get_argv_exec_path();
+		printf("available %s in '%s'\n", title, exec_path);
+		printf("----------------");
+		mput_char('-', strlen(title) + strlen(exec_path));
+		putchar('\n');
+		pretty_print_string_list(main_cmds, longest);
+		putchar('\n');
+		free(exec_path);
+	}
+
+	if (other_cmds->cnt) {
+		printf("%s available from elsewhere on your $PATH\n", title);
+		printf("---------------------------------------");
+		mput_char('-', strlen(title));
+		putchar('\n');
+		pretty_print_string_list(other_cmds, longest);
+		putchar('\n');
+	}
+}
+
+int is_in_cmdlist(struct cmdnames *c, const char *s)
+{
+	unsigned int i;
+
+	for (i = 0; i < c->cnt; i++)
+		if (!strcmp(s, c->names[i]->name))
+			return 1;
+	return 0;
+}
diff --git a/tools/lib/subcmd/help.h b/tools/lib/subcmd/help.h
new file mode 100644
index 000000000000..096c8bc45cd7
--- /dev/null
+++ b/tools/lib/subcmd/help.h
@@ -0,0 +1,34 @@
+#ifndef __PERF_HELP_H
+#define __PERF_HELP_H
+
+#include <sys/types.h>
+
+struct cmdnames {
+	size_t alloc;
+	size_t cnt;
+	struct cmdname {
+		size_t len; /* also used for similarity index in help.c */
+		char name[];
+	} **names;
+};
+
+static inline void mput_char(char c, unsigned int num)
+{
+	while(num--)
+		putchar(c);
+}
+
+void load_command_list(const char *prefix,
+		struct cmdnames *main_cmds,
+		struct cmdnames *other_cmds);
+void add_cmdname(struct cmdnames *cmds, const char *name, size_t len);
+void clean_cmdnames(struct cmdnames *cmds);
+int cmdname_compare(const void *a, const void *b);
+void uniq(struct cmdnames *cmds);
+/* Here we require that excludes is a sorted list. */
+void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes);
+int is_in_cmdlist(struct cmdnames *c, const char *s);
+void list_commands(const char *title, struct cmdnames *main_cmds,
+		   struct cmdnames *other_cmds);
+
+#endif /* __PERF_HELP_H */
diff --git a/tools/lib/subcmd/pager.c b/tools/lib/subcmd/pager.c
new file mode 100644
index 000000000000..d50f3b58606b
--- /dev/null
+++ b/tools/lib/subcmd/pager.c
@@ -0,0 +1,100 @@
+#include <sys/select.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include "pager.h"
+#include "run-command.h"
+#include "sigchain.h"
+#include "subcmd-config.h"
+
+/*
+ * This is split up from the rest of git so that we can do
+ * something different on Windows.
+ */
+
+static int spawned_pager;
+
+void pager_init(const char *pager_env)
+{
+	subcmd_config.pager_env = pager_env;
+}
+
+static void pager_preexec(void)
+{
+	/*
+	 * Work around bug in "less" by not starting it until we
+	 * have real input
+	 */
+	fd_set in;
+
+	FD_ZERO(&in);
+	FD_SET(0, &in);
+	select(1, &in, NULL, &in, NULL);
+
+	setenv("LESS", "FRSX", 0);
+}
+
+static const char *pager_argv[] = { "sh", "-c", NULL, NULL };
+static struct child_process pager_process;
+
+static void wait_for_pager(void)
+{
+	fflush(stdout);
+	fflush(stderr);
+	/* signal EOF to pager */
+	close(1);
+	close(2);
+	finish_command(&pager_process);
+}
+
+static void wait_for_pager_signal(int signo)
+{
+	wait_for_pager();
+	sigchain_pop(signo);
+	raise(signo);
+}
+
+void setup_pager(void)
+{
+	const char *pager = getenv(subcmd_config.pager_env);
+
+	if (!isatty(1))
+		return;
+	if (!pager)
+		pager = getenv("PAGER");
+	if (!(pager || access("/usr/bin/pager", X_OK)))
+		pager = "/usr/bin/pager";
+	if (!(pager || access("/usr/bin/less", X_OK)))
+		pager = "/usr/bin/less";
+	if (!pager)
+		pager = "cat";
+	if (!*pager || !strcmp(pager, "cat"))
+		return;
+
+	spawned_pager = 1; /* means we are emitting to terminal */
+
+	/* spawn the pager */
+	pager_argv[2] = pager;
+	pager_process.argv = pager_argv;
+	pager_process.in = -1;
+	pager_process.preexec_cb = pager_preexec;
+
+	if (start_command(&pager_process))
+		return;
+
+	/* original process continues, but writes to the pipe */
+	dup2(pager_process.in, 1);
+	if (isatty(2))
+		dup2(pager_process.in, 2);
+	close(pager_process.in);
+
+	/* this makes sure that the parent terminates after the pager */
+	sigchain_push_common(wait_for_pager_signal);
+	atexit(wait_for_pager);
+}
+
+int pager_in_use(void)
+{
+	return spawned_pager;
+}
diff --git a/tools/lib/subcmd/pager.h b/tools/lib/subcmd/pager.h
new file mode 100644
index 000000000000..d6a591a4c017
--- /dev/null
+++ b/tools/lib/subcmd/pager.h
@@ -0,0 +1,9 @@
+#ifndef __PERF_PAGER_H
+#define __PERF_PAGER_H
+
+extern void pager_init(const char *pager_env);
+
+extern void setup_pager(void);
+extern int pager_in_use(void);
+
+#endif /* __PERF_PAGER_H */
diff --git a/tools/lib/subcmd/parse-options.c b/tools/lib/subcmd/parse-options.c
new file mode 100644
index 000000000000..f4240275714a
--- /dev/null
+++ b/tools/lib/subcmd/parse-options.c
@@ -0,0 +1,984 @@
+#include <linux/compiler.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <ctype.h>
+#include "subcmd-util.h"
+#include "parse-options.h"
+#include "subcmd-config.h"
+#include "pager.h"
+
+#define OPT_SHORT 1
+#define OPT_UNSET 2
+
+typedef uint64_t u64;
+
+char *error_buf;
+
+static int opterror(const struct option *opt, const char *reason, int flags)
+{
+	if (flags & OPT_SHORT)
+		fprintf(stderr, " Error: switch `%c' %s", opt->short_name, reason);
+	else if (flags & OPT_UNSET)
+		fprintf(stderr, " Error: option `no-%s' %s", opt->long_name, reason);
+	else
+		fprintf(stderr, " Error: option `%s' %s", opt->long_name, reason);
+
+	return -1;
+}
+
+static const char *skip_prefix(const char *str, const char *prefix)
+{
+	size_t len = strlen(prefix);
+	return strncmp(str, prefix, len) ? NULL : str + len;
+}
+
+static void optwarning(const struct option *opt, const char *reason, int flags)
+{
+	if (flags & OPT_SHORT)
+		fprintf(stderr, " Warning: switch `%c' %s", opt->short_name, reason);
+	else if (flags & OPT_UNSET)
+		fprintf(stderr, " Warning: option `no-%s' %s", opt->long_name, reason);
+	else
+		fprintf(stderr, " Warning: option `%s' %s", opt->long_name, reason);
+}
+
+static int get_arg(struct parse_opt_ctx_t *p, const struct option *opt,
+		   int flags, const char **arg)
+{
+	const char *res;
+
+	if (p->opt) {
+		res = p->opt;
+		p->opt = NULL;
+	} else if ((opt->flags & PARSE_OPT_LASTARG_DEFAULT) && (p->argc == 1 ||
+		    **(p->argv + 1) == '-')) {
+		res = (const char *)opt->defval;
+	} else if (p->argc > 1) {
+		p->argc--;
+		res = *++p->argv;
+	} else
+		return opterror(opt, "requires a value", flags);
+	if (arg)
+		*arg = res;
+	return 0;
+}
+
+static int get_value(struct parse_opt_ctx_t *p,
+		     const struct option *opt, int flags)
+{
+	const char *s, *arg = NULL;
+	const int unset = flags & OPT_UNSET;
+	int err;
+
+	if (unset && p->opt)
+		return opterror(opt, "takes no value", flags);
+	if (unset && (opt->flags & PARSE_OPT_NONEG))
+		return opterror(opt, "isn't available", flags);
+	if (opt->flags & PARSE_OPT_DISABLED)
+		return opterror(opt, "is not usable", flags);
+
+	if (opt->flags & PARSE_OPT_EXCLUSIVE) {
+		if (p->excl_opt && p->excl_opt != opt) {
+			char msg[128];
+
+			if (((flags & OPT_SHORT) && p->excl_opt->short_name) ||
+			    p->excl_opt->long_name == NULL) {
+				snprintf(msg, sizeof(msg), "cannot be used with switch `%c'",
+					 p->excl_opt->short_name);
+			} else {
+				snprintf(msg, sizeof(msg), "cannot be used with %s",
+					 p->excl_opt->long_name);
+			}
+			opterror(opt, msg, flags);
+			return -3;
+		}
+		p->excl_opt = opt;
+	}
+	if (!(flags & OPT_SHORT) && p->opt) {
+		switch (opt->type) {
+		case OPTION_CALLBACK:
+			if (!(opt->flags & PARSE_OPT_NOARG))
+				break;
+			/* FALLTHROUGH */
+		case OPTION_BOOLEAN:
+		case OPTION_INCR:
+		case OPTION_BIT:
+		case OPTION_SET_UINT:
+		case OPTION_SET_PTR:
+			return opterror(opt, "takes no value", flags);
+		case OPTION_END:
+		case OPTION_ARGUMENT:
+		case OPTION_GROUP:
+		case OPTION_STRING:
+		case OPTION_INTEGER:
+		case OPTION_UINTEGER:
+		case OPTION_LONG:
+		case OPTION_U64:
+		default:
+			break;
+		}
+	}
+
+	if (opt->flags & PARSE_OPT_NOBUILD) {
+		char reason[128];
+		bool noarg = false;
+
+		err = snprintf(reason, sizeof(reason),
+				opt->flags & PARSE_OPT_CANSKIP ?
+					"is being ignored because %s " :
+					"is not available because %s",
+				opt->build_opt);
+		reason[sizeof(reason) - 1] = '\0';
+
+		if (err < 0)
+			strncpy(reason, opt->flags & PARSE_OPT_CANSKIP ?
+					"is being ignored" :
+					"is not available",
+					sizeof(reason));
+
+		if (!(opt->flags & PARSE_OPT_CANSKIP))
+			return opterror(opt, reason, flags);
+
+		err = 0;
+		if (unset)
+			noarg = true;
+		if (opt->flags & PARSE_OPT_NOARG)
+			noarg = true;
+		if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
+			noarg = true;
+
+		switch (opt->type) {
+		case OPTION_BOOLEAN:
+		case OPTION_INCR:
+		case OPTION_BIT:
+		case OPTION_SET_UINT:
+		case OPTION_SET_PTR:
+		case OPTION_END:
+		case OPTION_ARGUMENT:
+		case OPTION_GROUP:
+			noarg = true;
+			break;
+		case OPTION_CALLBACK:
+		case OPTION_STRING:
+		case OPTION_INTEGER:
+		case OPTION_UINTEGER:
+		case OPTION_LONG:
+		case OPTION_U64:
+		default:
+			break;
+		}
+
+		if (!noarg)
+			err = get_arg(p, opt, flags, NULL);
+		if (err)
+			return err;
+
+		optwarning(opt, reason, flags);
+		return 0;
+	}
+
+	switch (opt->type) {
+	case OPTION_BIT:
+		if (unset)
+			*(int *)opt->value &= ~opt->defval;
+		else
+			*(int *)opt->value |= opt->defval;
+		return 0;
+
+	case OPTION_BOOLEAN:
+		*(bool *)opt->value = unset ? false : true;
+		if (opt->set)
+			*(bool *)opt->set = true;
+		return 0;
+
+	case OPTION_INCR:
+		*(int *)opt->value = unset ? 0 : *(int *)opt->value + 1;
+		return 0;
+
+	case OPTION_SET_UINT:
+		*(unsigned int *)opt->value = unset ? 0 : opt->defval;
+		return 0;
+
+	case OPTION_SET_PTR:
+		*(void **)opt->value = unset ? NULL : (void *)opt->defval;
+		return 0;
+
+	case OPTION_STRING:
+		err = 0;
+		if (unset)
+			*(const char **)opt->value = NULL;
+		else if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
+			*(const char **)opt->value = (const char *)opt->defval;
+		else
+			err = get_arg(p, opt, flags, (const char **)opt->value);
+
+		/* PARSE_OPT_NOEMPTY: Allow NULL but disallow empty string. */
+		if (opt->flags & PARSE_OPT_NOEMPTY) {
+			const char *val = *(const char **)opt->value;
+
+			if (!val)
+				return err;
+
+			/* Similar to unset if we are given an empty string. */
+			if (val[0] == '\0') {
+				*(const char **)opt->value = NULL;
+				return 0;
+			}
+		}
+
+		return err;
+
+	case OPTION_CALLBACK:
+		if (unset)
+			return (*opt->callback)(opt, NULL, 1) ? (-1) : 0;
+		if (opt->flags & PARSE_OPT_NOARG)
+			return (*opt->callback)(opt, NULL, 0) ? (-1) : 0;
+		if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
+			return (*opt->callback)(opt, NULL, 0) ? (-1) : 0;
+		if (get_arg(p, opt, flags, &arg))
+			return -1;
+		return (*opt->callback)(opt, arg, 0) ? (-1) : 0;
+
+	case OPTION_INTEGER:
+		if (unset) {
+			*(int *)opt->value = 0;
+			return 0;
+		}
+		if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
+			*(int *)opt->value = opt->defval;
+			return 0;
+		}
+		if (get_arg(p, opt, flags, &arg))
+			return -1;
+		*(int *)opt->value = strtol(arg, (char **)&s, 10);
+		if (*s)
+			return opterror(opt, "expects a numerical value", flags);
+		return 0;
+
+	case OPTION_UINTEGER:
+		if (unset) {
+			*(unsigned int *)opt->value = 0;
+			return 0;
+		}
+		if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
+			*(unsigned int *)opt->value = opt->defval;
+			return 0;
+		}
+		if (get_arg(p, opt, flags, &arg))
+			return -1;
+		*(unsigned int *)opt->value = strtol(arg, (char **)&s, 10);
+		if (*s)
+			return opterror(opt, "expects a numerical value", flags);
+		return 0;
+
+	case OPTION_LONG:
+		if (unset) {
+			*(long *)opt->value = 0;
+			return 0;
+		}
+		if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
+			*(long *)opt->value = opt->defval;
+			return 0;
+		}
+		if (get_arg(p, opt, flags, &arg))
+			return -1;
+		*(long *)opt->value = strtol(arg, (char **)&s, 10);
+		if (*s)
+			return opterror(opt, "expects a numerical value", flags);
+		return 0;
+
+	case OPTION_U64:
+		if (unset) {
+			*(u64 *)opt->value = 0;
+			return 0;
+		}
+		if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
+			*(u64 *)opt->value = opt->defval;
+			return 0;
+		}
+		if (get_arg(p, opt, flags, &arg))
+			return -1;
+		*(u64 *)opt->value = strtoull(arg, (char **)&s, 10);
+		if (*s)
+			return opterror(opt, "expects a numerical value", flags);
+		return 0;
+
+	case OPTION_END:
+	case OPTION_ARGUMENT:
+	case OPTION_GROUP:
+	default:
+		die("should not happen, someone must be hit on the forehead");
+	}
+}
+
+static int parse_short_opt(struct parse_opt_ctx_t *p, const struct option *options)
+{
+	for (; options->type != OPTION_END; options++) {
+		if (options->short_name == *p->opt) {
+			p->opt = p->opt[1] ? p->opt + 1 : NULL;
+			return get_value(p, options, OPT_SHORT);
+		}
+	}
+	return -2;
+}
+
+static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg,
+                          const struct option *options)
+{
+	const char *arg_end = strchr(arg, '=');
+	const struct option *abbrev_option = NULL, *ambiguous_option = NULL;
+	int abbrev_flags = 0, ambiguous_flags = 0;
+
+	if (!arg_end)
+		arg_end = arg + strlen(arg);
+
+	for (; options->type != OPTION_END; options++) {
+		const char *rest;
+		int flags = 0;
+
+		if (!options->long_name)
+			continue;
+
+		rest = skip_prefix(arg, options->long_name);
+		if (options->type == OPTION_ARGUMENT) {
+			if (!rest)
+				continue;
+			if (*rest == '=')
+				return opterror(options, "takes no value", flags);
+			if (*rest)
+				continue;
+			p->out[p->cpidx++] = arg - 2;
+			return 0;
+		}
+		if (!rest) {
+			if (!prefixcmp(options->long_name, "no-")) {
+				/*
+				 * The long name itself starts with "no-", so
+				 * accept the option without "no-" so that users
+				 * do not have to enter "no-no-" to get the
+				 * negation.
+				 */
+				rest = skip_prefix(arg, options->long_name + 3);
+				if (rest) {
+					flags |= OPT_UNSET;
+					goto match;
+				}
+				/* Abbreviated case */
+				if (!prefixcmp(options->long_name + 3, arg)) {
+					flags |= OPT_UNSET;
+					goto is_abbreviated;
+				}
+			}
+			/* abbreviated? */
+			if (!strncmp(options->long_name, arg, arg_end - arg)) {
+is_abbreviated:
+				if (abbrev_option) {
+					/*
+					 * If this is abbreviated, it is
+					 * ambiguous. So when there is no
+					 * exact match later, we need to
+					 * error out.
+					 */
+					ambiguous_option = abbrev_option;
+					ambiguous_flags = abbrev_flags;
+				}
+				if (!(flags & OPT_UNSET) && *arg_end)
+					p->opt = arg_end + 1;
+				abbrev_option = options;
+				abbrev_flags = flags;
+				continue;
+			}
+			/* negated and abbreviated very much? */
+			if (!prefixcmp("no-", arg)) {
+				flags |= OPT_UNSET;
+				goto is_abbreviated;
+			}
+			/* negated? */
+			if (strncmp(arg, "no-", 3))
+				continue;
+			flags |= OPT_UNSET;
+			rest = skip_prefix(arg + 3, options->long_name);
+			/* abbreviated and negated? */
+			if (!rest && !prefixcmp(options->long_name, arg + 3))
+				goto is_abbreviated;
+			if (!rest)
+				continue;
+		}
+match:
+		if (*rest) {
+			if (*rest != '=')
+				continue;
+			p->opt = rest + 1;
+		}
+		return get_value(p, options, flags);
+	}
+
+	if (ambiguous_option) {
+		 fprintf(stderr,
+			 " Error: Ambiguous option: %s (could be --%s%s or --%s%s)",
+			 arg,
+			 (ambiguous_flags & OPT_UNSET) ?  "no-" : "",
+			 ambiguous_option->long_name,
+			 (abbrev_flags & OPT_UNSET) ?  "no-" : "",
+			 abbrev_option->long_name);
+		 return -1;
+	}
+	if (abbrev_option)
+		return get_value(p, abbrev_option, abbrev_flags);
+	return -2;
+}
+
+static void check_typos(const char *arg, const struct option *options)
+{
+	if (strlen(arg) < 3)
+		return;
+
+	if (!prefixcmp(arg, "no-")) {
+		fprintf(stderr, " Error: did you mean `--%s` (with two dashes ?)", arg);
+		exit(129);
+	}
+
+	for (; options->type != OPTION_END; options++) {
+		if (!options->long_name)
+			continue;
+		if (!prefixcmp(options->long_name, arg)) {
+			fprintf(stderr, " Error: did you mean `--%s` (with two dashes ?)", arg);
+			exit(129);
+		}
+	}
+}
+
+static void parse_options_start(struct parse_opt_ctx_t *ctx,
+				int argc, const char **argv, int flags)
+{
+	memset(ctx, 0, sizeof(*ctx));
+	ctx->argc = argc - 1;
+	ctx->argv = argv + 1;
+	ctx->out  = argv;
+	ctx->cpidx = ((flags & PARSE_OPT_KEEP_ARGV0) != 0);
+	ctx->flags = flags;
+	if ((flags & PARSE_OPT_KEEP_UNKNOWN) &&
+	    (flags & PARSE_OPT_STOP_AT_NON_OPTION))
+		die("STOP_AT_NON_OPTION and KEEP_UNKNOWN don't go together");
+}
+
+static int usage_with_options_internal(const char * const *,
+				       const struct option *, int,
+				       struct parse_opt_ctx_t *);
+
+static int parse_options_step(struct parse_opt_ctx_t *ctx,
+			      const struct option *options,
+			      const char * const usagestr[])
+{
+	int internal_help = !(ctx->flags & PARSE_OPT_NO_INTERNAL_HELP);
+	int excl_short_opt = 1;
+	const char *arg;
+
+	/* we must reset ->opt, unknown short option leave it dangling */
+	ctx->opt = NULL;
+
+	for (; ctx->argc; ctx->argc--, ctx->argv++) {
+		arg = ctx->argv[0];
+		if (*arg != '-' || !arg[1]) {
+			if (ctx->flags & PARSE_OPT_STOP_AT_NON_OPTION)
+				break;
+			ctx->out[ctx->cpidx++] = ctx->argv[0];
+			continue;
+		}
+
+		if (arg[1] != '-') {
+			ctx->opt = ++arg;
+			if (internal_help && *ctx->opt == 'h') {
+				return usage_with_options_internal(usagestr, options, 0, ctx);
+			}
+			switch (parse_short_opt(ctx, options)) {
+			case -1:
+				return parse_options_usage(usagestr, options, arg, 1);
+			case -2:
+				goto unknown;
+			case -3:
+				goto exclusive;
+			default:
+				break;
+			}
+			if (ctx->opt)
+				check_typos(arg, options);
+			while (ctx->opt) {
+				if (internal_help && *ctx->opt == 'h')
+					return usage_with_options_internal(usagestr, options, 0, ctx);
+				arg = ctx->opt;
+				switch (parse_short_opt(ctx, options)) {
+				case -1:
+					return parse_options_usage(usagestr, options, arg, 1);
+				case -2:
+					/* fake a short option thing to hide the fact that we may have
+					 * started to parse aggregated stuff
+					 *
+					 * This is leaky, too bad.
+					 */
+					ctx->argv[0] = strdup(ctx->opt - 1);
+					*(char *)ctx->argv[0] = '-';
+					goto unknown;
+				case -3:
+					goto exclusive;
+				default:
+					break;
+				}
+			}
+			continue;
+		}
+
+		if (!arg[2]) { /* "--" */
+			if (!(ctx->flags & PARSE_OPT_KEEP_DASHDASH)) {
+				ctx->argc--;
+				ctx->argv++;
+			}
+			break;
+		}
+
+		arg += 2;
+		if (internal_help && !strcmp(arg, "help-all"))
+			return usage_with_options_internal(usagestr, options, 1, ctx);
+		if (internal_help && !strcmp(arg, "help"))
+			return usage_with_options_internal(usagestr, options, 0, ctx);
+		if (!strcmp(arg, "list-opts"))
+			return PARSE_OPT_LIST_OPTS;
+		if (!strcmp(arg, "list-cmds"))
+			return PARSE_OPT_LIST_SUBCMDS;
+		switch (parse_long_opt(ctx, arg, options)) {
+		case -1:
+			return parse_options_usage(usagestr, options, arg, 0);
+		case -2:
+			goto unknown;
+		case -3:
+			excl_short_opt = 0;
+			goto exclusive;
+		default:
+			break;
+		}
+		continue;
+unknown:
+		if (!(ctx->flags & PARSE_OPT_KEEP_UNKNOWN))
+			return PARSE_OPT_UNKNOWN;
+		ctx->out[ctx->cpidx++] = ctx->argv[0];
+		ctx->opt = NULL;
+	}
+	return PARSE_OPT_DONE;
+
+exclusive:
+	parse_options_usage(usagestr, options, arg, excl_short_opt);
+	if ((excl_short_opt && ctx->excl_opt->short_name) ||
+	    ctx->excl_opt->long_name == NULL) {
+		char opt = ctx->excl_opt->short_name;
+		parse_options_usage(NULL, options, &opt, 1);
+	} else {
+		parse_options_usage(NULL, options, ctx->excl_opt->long_name, 0);
+	}
+	return PARSE_OPT_HELP;
+}
+
+static int parse_options_end(struct parse_opt_ctx_t *ctx)
+{
+	memmove(ctx->out + ctx->cpidx, ctx->argv, ctx->argc * sizeof(*ctx->out));
+	ctx->out[ctx->cpidx + ctx->argc] = NULL;
+	return ctx->cpidx + ctx->argc;
+}
+
+int parse_options_subcommand(int argc, const char **argv, const struct option *options,
+			const char *const subcommands[], const char *usagestr[], int flags)
+{
+	struct parse_opt_ctx_t ctx;
+
+	/* build usage string if it's not provided */
+	if (subcommands && !usagestr[0]) {
+		char *buf = NULL;
+
+		astrcatf(&buf, "%s %s [<options>] {", subcmd_config.exec_name, argv[0]);
+
+		for (int i = 0; subcommands[i]; i++) {
+			if (i)
+				astrcat(&buf, "|");
+			astrcat(&buf, subcommands[i]);
+		}
+		astrcat(&buf, "}");
+
+		usagestr[0] = buf;
+	}
+
+	parse_options_start(&ctx, argc, argv, flags);
+	switch (parse_options_step(&ctx, options, usagestr)) {
+	case PARSE_OPT_HELP:
+		exit(129);
+	case PARSE_OPT_DONE:
+		break;
+	case PARSE_OPT_LIST_OPTS:
+		while (options->type != OPTION_END) {
+			if (options->long_name)
+				printf("--%s ", options->long_name);
+			options++;
+		}
+		putchar('\n');
+		exit(130);
+	case PARSE_OPT_LIST_SUBCMDS:
+		if (subcommands) {
+			for (int i = 0; subcommands[i]; i++)
+				printf("%s ", subcommands[i]);
+		}
+		putchar('\n');
+		exit(130);
+	default: /* PARSE_OPT_UNKNOWN */
+		if (ctx.argv[0][1] == '-')
+			astrcatf(&error_buf, "unknown option `%s'",
+				 ctx.argv[0] + 2);
+		else
+			astrcatf(&error_buf, "unknown switch `%c'", *ctx.opt);
+		usage_with_options(usagestr, options);
+	}
+
+	return parse_options_end(&ctx);
+}
+
+int parse_options(int argc, const char **argv, const struct option *options,
+		  const char * const usagestr[], int flags)
+{
+	return parse_options_subcommand(argc, argv, options, NULL,
+					(const char **) usagestr, flags);
+}
+
+#define USAGE_OPTS_WIDTH 24
+#define USAGE_GAP         2
+
+static void print_option_help(const struct option *opts, int full)
+{
+	size_t pos;
+	int pad;
+
+	if (opts->type == OPTION_GROUP) {
+		fputc('\n', stderr);
+		if (*opts->help)
+			fprintf(stderr, "%s\n", opts->help);
+		return;
+	}
+	if (!full && (opts->flags & PARSE_OPT_HIDDEN))
+		return;
+	if (opts->flags & PARSE_OPT_DISABLED)
+		return;
+
+	pos = fprintf(stderr, "    ");
+	if (opts->short_name)
+		pos += fprintf(stderr, "-%c", opts->short_name);
+	else
+		pos += fprintf(stderr, "    ");
+
+	if (opts->long_name && opts->short_name)
+		pos += fprintf(stderr, ", ");
+	if (opts->long_name)
+		pos += fprintf(stderr, "--%s", opts->long_name);
+
+	switch (opts->type) {
+	case OPTION_ARGUMENT:
+		break;
+	case OPTION_LONG:
+	case OPTION_U64:
+	case OPTION_INTEGER:
+	case OPTION_UINTEGER:
+		if (opts->flags & PARSE_OPT_OPTARG)
+			if (opts->long_name)
+				pos += fprintf(stderr, "[=<n>]");
+			else
+				pos += fprintf(stderr, "[<n>]");
+		else
+			pos += fprintf(stderr, " <n>");
+		break;
+	case OPTION_CALLBACK:
+		if (opts->flags & PARSE_OPT_NOARG)
+			break;
+		/* FALLTHROUGH */
+	case OPTION_STRING:
+		if (opts->argh) {
+			if (opts->flags & PARSE_OPT_OPTARG)
+				if (opts->long_name)
+					pos += fprintf(stderr, "[=<%s>]", opts->argh);
+				else
+					pos += fprintf(stderr, "[<%s>]", opts->argh);
+			else
+				pos += fprintf(stderr, " <%s>", opts->argh);
+		} else {
+			if (opts->flags & PARSE_OPT_OPTARG)
+				if (opts->long_name)
+					pos += fprintf(stderr, "[=...]");
+				else
+					pos += fprintf(stderr, "[...]");
+			else
+				pos += fprintf(stderr, " ...");
+		}
+		break;
+	default: /* OPTION_{BIT,BOOLEAN,SET_UINT,SET_PTR} */
+	case OPTION_END:
+	case OPTION_GROUP:
+	case OPTION_BIT:
+	case OPTION_BOOLEAN:
+	case OPTION_INCR:
+	case OPTION_SET_UINT:
+	case OPTION_SET_PTR:
+		break;
+	}
+
+	if (pos <= USAGE_OPTS_WIDTH)
+		pad = USAGE_OPTS_WIDTH - pos;
+	else {
+		fputc('\n', stderr);
+		pad = USAGE_OPTS_WIDTH;
+	}
+	fprintf(stderr, "%*s%s\n", pad + USAGE_GAP, "", opts->help);
+	if (opts->flags & PARSE_OPT_NOBUILD)
+		fprintf(stderr, "%*s(not built-in because %s)\n",
+			USAGE_OPTS_WIDTH + USAGE_GAP, "",
+			opts->build_opt);
+}
+
+static int option__cmp(const void *va, const void *vb)
+{
+	const struct option *a = va, *b = vb;
+	int sa = tolower(a->short_name), sb = tolower(b->short_name), ret;
+
+	if (sa == 0)
+		sa = 'z' + 1;
+	if (sb == 0)
+		sb = 'z' + 1;
+
+	ret = sa - sb;
+
+	if (ret == 0) {
+		const char *la = a->long_name ?: "",
+			   *lb = b->long_name ?: "";
+		ret = strcmp(la, lb);
+	}
+
+	return ret;
+}
+
+static struct option *options__order(const struct option *opts)
+{
+	int nr_opts = 0, len;
+	const struct option *o = opts;
+	struct option *ordered;
+
+	for (o = opts; o->type != OPTION_END; o++)
+		++nr_opts;
+
+	len = sizeof(*o) * (nr_opts + 1);
+	ordered = malloc(len);
+	if (!ordered)
+		goto out;
+	memcpy(ordered, opts, len);
+
+	qsort(ordered, nr_opts, sizeof(*o), option__cmp);
+out:
+	return ordered;
+}
+
+static bool option__in_argv(const struct option *opt, const struct parse_opt_ctx_t *ctx)
+{
+	int i;
+
+	for (i = 1; i < ctx->argc; ++i) {
+		const char *arg = ctx->argv[i];
+
+		if (arg[0] != '-') {
+			if (arg[1] == '\0') {
+				if (arg[0] == opt->short_name)
+					return true;
+				continue;
+			}
+
+			if (opt->long_name && strcmp(opt->long_name, arg) == 0)
+				return true;
+
+			if (opt->help && strcasestr(opt->help, arg) != NULL)
+				return true;
+
+			continue;
+		}
+
+		if (arg[1] == opt->short_name ||
+		    (arg[1] == '-' && opt->long_name && strcmp(opt->long_name, arg + 2) == 0))
+			return true;
+	}
+
+	return false;
+}
+
+static int usage_with_options_internal(const char * const *usagestr,
+				       const struct option *opts, int full,
+				       struct parse_opt_ctx_t *ctx)
+{
+	struct option *ordered;
+
+	if (!usagestr)
+		return PARSE_OPT_HELP;
+
+	setup_pager();
+
+	if (error_buf) {
+		fprintf(stderr, "  Error: %s\n", error_buf);
+		zfree(&error_buf);
+	}
+
+	fprintf(stderr, "\n Usage: %s\n", *usagestr++);
+	while (*usagestr && **usagestr)
+		fprintf(stderr, "    or: %s\n", *usagestr++);
+	while (*usagestr) {
+		fprintf(stderr, "%s%s\n",
+				**usagestr ? "    " : "",
+				*usagestr);
+		usagestr++;
+	}
+
+	if (opts->type != OPTION_GROUP)
+		fputc('\n', stderr);
+
+	ordered = options__order(opts);
+	if (ordered)
+		opts = ordered;
+
+	for (  ; opts->type != OPTION_END; opts++) {
+		if (ctx && ctx->argc > 1 && !option__in_argv(opts, ctx))
+			continue;
+		print_option_help(opts, full);
+	}
+
+	fputc('\n', stderr);
+
+	free(ordered);
+
+	return PARSE_OPT_HELP;
+}
+
+void usage_with_options(const char * const *usagestr,
+			const struct option *opts)
+{
+	usage_with_options_internal(usagestr, opts, 0, NULL);
+	exit(129);
+}
+
+void usage_with_options_msg(const char * const *usagestr,
+			    const struct option *opts, const char *fmt, ...)
+{
+	va_list ap;
+	char *tmp = error_buf;
+
+	va_start(ap, fmt);
+	if (vasprintf(&error_buf, fmt, ap) == -1)
+		die("vasprintf failed");
+	va_end(ap);
+
+	free(tmp);
+
+	usage_with_options_internal(usagestr, opts, 0, NULL);
+	exit(129);
+}
+
+int parse_options_usage(const char * const *usagestr,
+			const struct option *opts,
+			const char *optstr, bool short_opt)
+{
+	if (!usagestr)
+		goto opt;
+
+	fprintf(stderr, "\n Usage: %s\n", *usagestr++);
+	while (*usagestr && **usagestr)
+		fprintf(stderr, "    or: %s\n", *usagestr++);
+	while (*usagestr) {
+		fprintf(stderr, "%s%s\n",
+				**usagestr ? "    " : "",
+				*usagestr);
+		usagestr++;
+	}
+	fputc('\n', stderr);
+
+opt:
+	for (  ; opts->type != OPTION_END; opts++) {
+		if (short_opt) {
+			if (opts->short_name == *optstr) {
+				print_option_help(opts, 0);
+				break;
+			}
+			continue;
+		}
+
+		if (opts->long_name == NULL)
+			continue;
+
+		if (!prefixcmp(opts->long_name, optstr))
+			print_option_help(opts, 0);
+		if (!prefixcmp("no-", optstr) &&
+		    !prefixcmp(opts->long_name, optstr + 3))
+			print_option_help(opts, 0);
+	}
+
+	return PARSE_OPT_HELP;
+}
+
+
+int parse_opt_verbosity_cb(const struct option *opt,
+			   const char *arg __maybe_unused,
+			   int unset)
+{
+	int *target = opt->value;
+
+	if (unset)
+		/* --no-quiet, --no-verbose */
+		*target = 0;
+	else if (opt->short_name == 'v') {
+		if (*target >= 0)
+			(*target)++;
+		else
+			*target = 1;
+	} else {
+		if (*target <= 0)
+			(*target)--;
+		else
+			*target = -1;
+	}
+	return 0;
+}
+
+static struct option *
+find_option(struct option *opts, int shortopt, const char *longopt)
+{
+	for (; opts->type != OPTION_END; opts++) {
+		if ((shortopt && opts->short_name == shortopt) ||
+		    (opts->long_name && longopt &&
+		     !strcmp(opts->long_name, longopt)))
+			return opts;
+	}
+	return NULL;
+}
+
+void set_option_flag(struct option *opts, int shortopt, const char *longopt,
+		     int flag)
+{
+	struct option *opt = find_option(opts, shortopt, longopt);
+
+	if (opt)
+		opt->flags |= flag;
+	return;
+}
+
+void set_option_nobuild(struct option *opts, int shortopt,
+			const char *longopt,
+			const char *build_opt,
+			bool can_skip)
+{
+	struct option *opt = find_option(opts, shortopt, longopt);
+
+	if (!opt)
+		return;
+
+	opt->flags |= PARSE_OPT_NOBUILD;
+	opt->flags |= can_skip ? PARSE_OPT_CANSKIP : 0;
+	opt->build_opt = build_opt;
+}
diff --git a/tools/lib/subcmd/parse-options.h b/tools/lib/subcmd/parse-options.h
new file mode 100644
index 000000000000..dec893f10477
--- /dev/null
+++ b/tools/lib/subcmd/parse-options.h
@@ -0,0 +1,228 @@
+#ifndef __PERF_PARSE_OPTIONS_H
+#define __PERF_PARSE_OPTIONS_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+enum parse_opt_type {
+	/* special types */
+	OPTION_END,
+	OPTION_ARGUMENT,
+	OPTION_GROUP,
+	/* options with no arguments */
+	OPTION_BIT,
+	OPTION_BOOLEAN,
+	OPTION_INCR,
+	OPTION_SET_UINT,
+	OPTION_SET_PTR,
+	/* options with arguments (usually) */
+	OPTION_STRING,
+	OPTION_INTEGER,
+	OPTION_LONG,
+	OPTION_CALLBACK,
+	OPTION_U64,
+	OPTION_UINTEGER,
+};
+
+enum parse_opt_flags {
+	PARSE_OPT_KEEP_DASHDASH = 1,
+	PARSE_OPT_STOP_AT_NON_OPTION = 2,
+	PARSE_OPT_KEEP_ARGV0 = 4,
+	PARSE_OPT_KEEP_UNKNOWN = 8,
+	PARSE_OPT_NO_INTERNAL_HELP = 16,
+};
+
+enum parse_opt_option_flags {
+	PARSE_OPT_OPTARG  = 1,
+	PARSE_OPT_NOARG   = 2,
+	PARSE_OPT_NONEG   = 4,
+	PARSE_OPT_HIDDEN  = 8,
+	PARSE_OPT_LASTARG_DEFAULT = 16,
+	PARSE_OPT_DISABLED = 32,
+	PARSE_OPT_EXCLUSIVE = 64,
+	PARSE_OPT_NOEMPTY  = 128,
+	PARSE_OPT_NOBUILD  = 256,
+	PARSE_OPT_CANSKIP  = 512,
+};
+
+struct option;
+typedef int parse_opt_cb(const struct option *, const char *arg, int unset);
+
+/*
+ * `type`::
+ *   holds the type of the option, you must have an OPTION_END last in your
+ *   array.
+ *
+ * `short_name`::
+ *   the character to use as a short option name, '\0' if none.
+ *
+ * `long_name`::
+ *   the long option name, without the leading dashes, NULL if none.
+ *
+ * `value`::
+ *   stores pointers to the values to be filled.
+ *
+ * `argh`::
+ *   token to explain the kind of argument this option wants. Keep it
+ *   homogenous across the repository.
+ *
+ * `help`::
+ *   the short help associated to what the option does.
+ *   Must never be NULL (except for OPTION_END).
+ *   OPTION_GROUP uses this pointer to store the group header.
+ *
+ * `flags`::
+ *   mask of parse_opt_option_flags.
+ *   PARSE_OPT_OPTARG: says that the argument is optionnal (not for BOOLEANs)
+ *   PARSE_OPT_NOARG: says that this option takes no argument, for CALLBACKs
+ *   PARSE_OPT_NONEG: says that this option cannot be negated
+ *   PARSE_OPT_HIDDEN this option is skipped in the default usage, showed in
+ *                    the long one.
+ *
+ * `callback`::
+ *   pointer to the callback to use for OPTION_CALLBACK.
+ *
+ * `defval`::
+ *   default value to fill (*->value) with for PARSE_OPT_OPTARG.
+ *   OPTION_{BIT,SET_UINT,SET_PTR} store the {mask,integer,pointer} to put in
+ *   the value when met.
+ *   CALLBACKS can use it like they want.
+ *
+ * `set`::
+ *   whether an option was set by the user
+ */
+struct option {
+	enum parse_opt_type type;
+	int short_name;
+	const char *long_name;
+	void *value;
+	const char *argh;
+	const char *help;
+	const char *build_opt;
+
+	int flags;
+	parse_opt_cb *callback;
+	intptr_t defval;
+	bool *set;
+	void *data;
+};
+
+#define check_vtype(v, type) ( BUILD_BUG_ON_ZERO(!__builtin_types_compatible_p(typeof(v), type)) + v )
+
+#define OPT_END()                   { .type = OPTION_END }
+#define OPT_ARGUMENT(l, h)          { .type = OPTION_ARGUMENT, .long_name = (l), .help = (h) }
+#define OPT_GROUP(h)                { .type = OPTION_GROUP, .help = (h) }
+#define OPT_BIT(s, l, v, h, b)      { .type = OPTION_BIT, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h), .defval = (b) }
+#define OPT_BOOLEAN(s, l, v, h)     { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), .value = check_vtype(v, bool *), .help = (h) }
+#define OPT_BOOLEAN_FLAG(s, l, v, h, f)     { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), .value = check_vtype(v, bool *), .help = (h), .flags = (f) }
+#define OPT_BOOLEAN_SET(s, l, v, os, h) \
+	{ .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), \
+	.value = check_vtype(v, bool *), .help = (h), \
+	.set = check_vtype(os, bool *)}
+#define OPT_INCR(s, l, v, h)        { .type = OPTION_INCR, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h) }
+#define OPT_SET_UINT(s, l, v, h, i)  { .type = OPTION_SET_UINT, .short_name = (s), .long_name = (l), .value = check_vtype(v, unsigned int *), .help = (h), .defval = (i) }
+#define OPT_SET_PTR(s, l, v, h, p)  { .type = OPTION_SET_PTR, .short_name = (s), .long_name = (l), .value = (v), .help = (h), .defval = (p) }
+#define OPT_INTEGER(s, l, v, h)     { .type = OPTION_INTEGER, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h) }
+#define OPT_UINTEGER(s, l, v, h)    { .type = OPTION_UINTEGER, .short_name = (s), .long_name = (l), .value = check_vtype(v, unsigned int *), .help = (h) }
+#define OPT_LONG(s, l, v, h)        { .type = OPTION_LONG, .short_name = (s), .long_name = (l), .value = check_vtype(v, long *), .help = (h) }
+#define OPT_U64(s, l, v, h)         { .type = OPTION_U64, .short_name = (s), .long_name = (l), .value = check_vtype(v, u64 *), .help = (h) }
+#define OPT_STRING(s, l, v, a, h)   { .type = OPTION_STRING,  .short_name = (s), .long_name = (l), .value = check_vtype(v, const char **), (a), .help = (h) }
+#define OPT_STRING_OPTARG(s, l, v, a, h, d) \
+	{ .type = OPTION_STRING,  .short_name = (s), .long_name = (l), \
+	  .value = check_vtype(v, const char **), (a), .help = (h), \
+	  .flags = PARSE_OPT_OPTARG, .defval = (intptr_t)(d) }
+#define OPT_STRING_NOEMPTY(s, l, v, a, h)   { .type = OPTION_STRING,  .short_name = (s), .long_name = (l), .value = check_vtype(v, const char **), (a), .help = (h), .flags = PARSE_OPT_NOEMPTY}
+#define OPT_DATE(s, l, v, h) \
+	{ .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = "time", .help = (h), .callback = parse_opt_approxidate_cb }
+#define OPT_CALLBACK(s, l, v, a, h, f) \
+	{ .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h), .callback = (f) }
+#define OPT_CALLBACK_NOOPT(s, l, v, a, h, f) \
+	{ .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h), .callback = (f), .flags = PARSE_OPT_NOARG }
+#define OPT_CALLBACK_DEFAULT(s, l, v, a, h, f, d) \
+	{ .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h), .callback = (f), .defval = (intptr_t)d, .flags = PARSE_OPT_LASTARG_DEFAULT }
+#define OPT_CALLBACK_DEFAULT_NOOPT(s, l, v, a, h, f, d) \
+	{ .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l),\
+	.value = (v), (a), .help = (h), .callback = (f), .defval = (intptr_t)d,\
+	.flags = PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NOARG}
+#define OPT_CALLBACK_OPTARG(s, l, v, d, a, h, f) \
+	{ .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), \
+	  .value = (v), (a), .help = (h), .callback = (f), \
+	  .flags = PARSE_OPT_OPTARG, .data = (d) }
+
+/* parse_options() will filter out the processed options and leave the
+ * non-option argments in argv[].
+ * Returns the number of arguments left in argv[].
+ *
+ * NOTE: parse_options() and parse_options_subcommand() may call exit() in the
+ * case of an error (or for 'special' options like --list-cmds or --list-opts).
+ */
+extern int parse_options(int argc, const char **argv,
+                         const struct option *options,
+                         const char * const usagestr[], int flags);
+
+extern int parse_options_subcommand(int argc, const char **argv,
+				const struct option *options,
+				const char *const subcommands[],
+				const char *usagestr[], int flags);
+
+extern NORETURN void usage_with_options(const char * const *usagestr,
+                                        const struct option *options);
+extern NORETURN __attribute__((format(printf,3,4)))
+void usage_with_options_msg(const char * const *usagestr,
+			    const struct option *options,
+			    const char *fmt, ...);
+
+/*----- incremantal advanced APIs -----*/
+
+enum {
+	PARSE_OPT_HELP = -1,
+	PARSE_OPT_DONE,
+	PARSE_OPT_LIST_OPTS,
+	PARSE_OPT_LIST_SUBCMDS,
+	PARSE_OPT_UNKNOWN,
+};
+
+/*
+ * It's okay for the caller to consume argv/argc in the usual way.
+ * Other fields of that structure are private to parse-options and should not
+ * be modified in any way.
+ */
+struct parse_opt_ctx_t {
+	const char **argv;
+	const char **out;
+	int argc, cpidx;
+	const char *opt;
+	const struct option *excl_opt;
+	int flags;
+};
+
+extern int parse_options_usage(const char * const *usagestr,
+			       const struct option *opts,
+			       const char *optstr,
+			       bool short_opt);
+
+
+/*----- some often used options -----*/
+extern int parse_opt_abbrev_cb(const struct option *, const char *, int);
+extern int parse_opt_approxidate_cb(const struct option *, const char *, int);
+extern int parse_opt_verbosity_cb(const struct option *, const char *, int);
+
+#define OPT__VERBOSE(var)  OPT_BOOLEAN('v', "verbose", (var), "be verbose")
+#define OPT__QUIET(var)    OPT_BOOLEAN('q', "quiet",   (var), "be quiet")
+#define OPT__VERBOSITY(var) \
+	{ OPTION_CALLBACK, 'v', "verbose", (var), NULL, "be more verbose", \
+	  PARSE_OPT_NOARG, &parse_opt_verbosity_cb, 0 }, \
+	{ OPTION_CALLBACK, 'q', "quiet", (var), NULL, "be more quiet", \
+	  PARSE_OPT_NOARG, &parse_opt_verbosity_cb, 0 }
+#define OPT__DRY_RUN(var)  OPT_BOOLEAN('n', "dry-run", (var), "dry run")
+#define OPT__ABBREV(var)  \
+	{ OPTION_CALLBACK, 0, "abbrev", (var), "n", \
+	  "use <n> digits to display SHA-1s", \
+	  PARSE_OPT_OPTARG, &parse_opt_abbrev_cb, 0 }
+
+extern const char *parse_options_fix_filename(const char *prefix, const char *file);
+
+void set_option_flag(struct option *opts, int sopt, const char *lopt, int flag);
+void set_option_nobuild(struct option *opts, int shortopt, const char *longopt,
+			const char *build_opt, bool can_skip);
+#endif /* __PERF_PARSE_OPTIONS_H */
diff --git a/tools/lib/subcmd/run-command.c b/tools/lib/subcmd/run-command.c
new file mode 100644
index 000000000000..f4f6c9eb8e59
--- /dev/null
+++ b/tools/lib/subcmd/run-command.c
@@ -0,0 +1,227 @@
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/wait.h>
+#include "subcmd-util.h"
+#include "run-command.h"
+#include "exec-cmd.h"
+
+#define STRERR_BUFSIZE 128
+
+static inline void close_pair(int fd[2])
+{
+	close(fd[0]);
+	close(fd[1]);
+}
+
+static inline void dup_devnull(int to)
+{
+	int fd = open("/dev/null", O_RDWR);
+	dup2(fd, to);
+	close(fd);
+}
+
+int start_command(struct child_process *cmd)
+{
+	int need_in, need_out, need_err;
+	int fdin[2], fdout[2], fderr[2];
+	char sbuf[STRERR_BUFSIZE];
+
+	/*
+	 * In case of errors we must keep the promise to close FDs
+	 * that have been passed in via ->in and ->out.
+	 */
+
+	need_in = !cmd->no_stdin && cmd->in < 0;
+	if (need_in) {
+		if (pipe(fdin) < 0) {
+			if (cmd->out > 0)
+				close(cmd->out);
+			return -ERR_RUN_COMMAND_PIPE;
+		}
+		cmd->in = fdin[1];
+	}
+
+	need_out = !cmd->no_stdout
+		&& !cmd->stdout_to_stderr
+		&& cmd->out < 0;
+	if (need_out) {
+		if (pipe(fdout) < 0) {
+			if (need_in)
+				close_pair(fdin);
+			else if (cmd->in)
+				close(cmd->in);
+			return -ERR_RUN_COMMAND_PIPE;
+		}
+		cmd->out = fdout[0];
+	}
+
+	need_err = !cmd->no_stderr && cmd->err < 0;
+	if (need_err) {
+		if (pipe(fderr) < 0) {
+			if (need_in)
+				close_pair(fdin);
+			else if (cmd->in)
+				close(cmd->in);
+			if (need_out)
+				close_pair(fdout);
+			else if (cmd->out)
+				close(cmd->out);
+			return -ERR_RUN_COMMAND_PIPE;
+		}
+		cmd->err = fderr[0];
+	}
+
+	fflush(NULL);
+	cmd->pid = fork();
+	if (!cmd->pid) {
+		if (cmd->no_stdin)
+			dup_devnull(0);
+		else if (need_in) {
+			dup2(fdin[0], 0);
+			close_pair(fdin);
+		} else if (cmd->in) {
+			dup2(cmd->in, 0);
+			close(cmd->in);
+		}
+
+		if (cmd->no_stderr)
+			dup_devnull(2);
+		else if (need_err) {
+			dup2(fderr[1], 2);
+			close_pair(fderr);
+		}
+
+		if (cmd->no_stdout)
+			dup_devnull(1);
+		else if (cmd->stdout_to_stderr)
+			dup2(2, 1);
+		else if (need_out) {
+			dup2(fdout[1], 1);
+			close_pair(fdout);
+		} else if (cmd->out > 1) {
+			dup2(cmd->out, 1);
+			close(cmd->out);
+		}
+
+		if (cmd->dir && chdir(cmd->dir))
+			die("exec %s: cd to %s failed (%s)", cmd->argv[0],
+			    cmd->dir, strerror_r(errno, sbuf, sizeof(sbuf)));
+		if (cmd->env) {
+			for (; *cmd->env; cmd->env++) {
+				if (strchr(*cmd->env, '='))
+					putenv((char*)*cmd->env);
+				else
+					unsetenv(*cmd->env);
+			}
+		}
+		if (cmd->preexec_cb)
+			cmd->preexec_cb();
+		if (cmd->exec_cmd) {
+			execv_cmd(cmd->argv);
+		} else {
+			execvp(cmd->argv[0], (char *const*) cmd->argv);
+		}
+		exit(127);
+	}
+
+	if (cmd->pid < 0) {
+		int err = errno;
+		if (need_in)
+			close_pair(fdin);
+		else if (cmd->in)
+			close(cmd->in);
+		if (need_out)
+			close_pair(fdout);
+		else if (cmd->out)
+			close(cmd->out);
+		if (need_err)
+			close_pair(fderr);
+		return err == ENOENT ?
+			-ERR_RUN_COMMAND_EXEC :
+			-ERR_RUN_COMMAND_FORK;
+	}
+
+	if (need_in)
+		close(fdin[0]);
+	else if (cmd->in)
+		close(cmd->in);
+
+	if (need_out)
+		close(fdout[1]);
+	else if (cmd->out)
+		close(cmd->out);
+
+	if (need_err)
+		close(fderr[1]);
+
+	return 0;
+}
+
+static int wait_or_whine(pid_t pid)
+{
+	char sbuf[STRERR_BUFSIZE];
+
+	for (;;) {
+		int status, code;
+		pid_t waiting = waitpid(pid, &status, 0);
+
+		if (waiting < 0) {
+			if (errno == EINTR)
+				continue;
+			fprintf(stderr, " Error: waitpid failed (%s)",
+				strerror_r(errno, sbuf, sizeof(sbuf)));
+			return -ERR_RUN_COMMAND_WAITPID;
+		}
+		if (waiting != pid)
+			return -ERR_RUN_COMMAND_WAITPID_WRONG_PID;
+		if (WIFSIGNALED(status))
+			return -ERR_RUN_COMMAND_WAITPID_SIGNAL;
+
+		if (!WIFEXITED(status))
+			return -ERR_RUN_COMMAND_WAITPID_NOEXIT;
+		code = WEXITSTATUS(status);
+		switch (code) {
+		case 127:
+			return -ERR_RUN_COMMAND_EXEC;
+		case 0:
+			return 0;
+		default:
+			return -code;
+		}
+	}
+}
+
+int finish_command(struct child_process *cmd)
+{
+	return wait_or_whine(cmd->pid);
+}
+
+int run_command(struct child_process *cmd)
+{
+	int code = start_command(cmd);
+	if (code)
+		return code;
+	return finish_command(cmd);
+}
+
+static void prepare_run_command_v_opt(struct child_process *cmd,
+				      const char **argv,
+				      int opt)
+{
+	memset(cmd, 0, sizeof(*cmd));
+	cmd->argv = argv;
+	cmd->no_stdin = opt & RUN_COMMAND_NO_STDIN ? 1 : 0;
+	cmd->exec_cmd = opt & RUN_EXEC_CMD ? 1 : 0;
+	cmd->stdout_to_stderr = opt & RUN_COMMAND_STDOUT_TO_STDERR ? 1 : 0;
+}
+
+int run_command_v_opt(const char **argv, int opt)
+{
+	struct child_process cmd;
+	prepare_run_command_v_opt(&cmd, argv, opt);
+	return run_command(&cmd);
+}
diff --git a/tools/lib/subcmd/run-command.h b/tools/lib/subcmd/run-command.h
new file mode 100644
index 000000000000..4a55393a6547
--- /dev/null
+++ b/tools/lib/subcmd/run-command.h
@@ -0,0 +1,60 @@
+#ifndef __PERF_RUN_COMMAND_H
+#define __PERF_RUN_COMMAND_H
+
+#include <unistd.h>
+
+enum {
+	ERR_RUN_COMMAND_FORK = 10000,
+	ERR_RUN_COMMAND_EXEC,
+	ERR_RUN_COMMAND_PIPE,
+	ERR_RUN_COMMAND_WAITPID,
+	ERR_RUN_COMMAND_WAITPID_WRONG_PID,
+	ERR_RUN_COMMAND_WAITPID_SIGNAL,
+	ERR_RUN_COMMAND_WAITPID_NOEXIT,
+};
+#define IS_RUN_COMMAND_ERR(x) (-(x) >= ERR_RUN_COMMAND_FORK)
+
+struct child_process {
+	const char **argv;
+	pid_t pid;
+	/*
+	 * Using .in, .out, .err:
+	 * - Specify 0 for no redirections (child inherits stdin, stdout,
+	 *   stderr from parent).
+	 * - Specify -1 to have a pipe allocated as follows:
+	 *     .in: returns the writable pipe end; parent writes to it,
+	 *          the readable pipe end becomes child's stdin
+	 *     .out, .err: returns the readable pipe end; parent reads from
+	 *          it, the writable pipe end becomes child's stdout/stderr
+	 *   The caller of start_command() must close the returned FDs
+	 *   after it has completed reading from/writing to it!
+	 * - Specify > 0 to set a channel to a particular FD as follows:
+	 *     .in: a readable FD, becomes child's stdin
+	 *     .out: a writable FD, becomes child's stdout/stderr
+	 *     .err > 0 not supported
+	 *   The specified FD is closed by start_command(), even in case
+	 *   of errors!
+	 */
+	int in;
+	int out;
+	int err;
+	const char *dir;
+	const char *const *env;
+	unsigned no_stdin:1;
+	unsigned no_stdout:1;
+	unsigned no_stderr:1;
+	unsigned exec_cmd:1; /* if this is to be external sub-command */
+	unsigned stdout_to_stderr:1;
+	void (*preexec_cb)(void);
+};
+
+int start_command(struct child_process *);
+int finish_command(struct child_process *);
+int run_command(struct child_process *);
+
+#define RUN_COMMAND_NO_STDIN 1
+#define RUN_EXEC_CMD	     2	/*If this is to be external sub-command */
+#define RUN_COMMAND_STDOUT_TO_STDERR 4
+int run_command_v_opt(const char **argv, int opt);
+
+#endif /* __PERF_RUN_COMMAND_H */
diff --git a/tools/lib/subcmd/sigchain.c b/tools/lib/subcmd/sigchain.c
new file mode 100644
index 000000000000..3537c348a18e
--- /dev/null
+++ b/tools/lib/subcmd/sigchain.c
@@ -0,0 +1,53 @@
+#include <signal.h>
+#include "subcmd-util.h"
+#include "sigchain.h"
+
+#define SIGCHAIN_MAX_SIGNALS 32
+
+struct sigchain_signal {
+	sigchain_fun *old;
+	int n;
+	int alloc;
+};
+static struct sigchain_signal signals[SIGCHAIN_MAX_SIGNALS];
+
+static void check_signum(int sig)
+{
+	if (sig < 1 || sig >= SIGCHAIN_MAX_SIGNALS)
+		die("BUG: signal out of range: %d", sig);
+}
+
+static int sigchain_push(int sig, sigchain_fun f)
+{
+	struct sigchain_signal *s = signals + sig;
+	check_signum(sig);
+
+	ALLOC_GROW(s->old, s->n + 1, s->alloc);
+	s->old[s->n] = signal(sig, f);
+	if (s->old[s->n] == SIG_ERR)
+		return -1;
+	s->n++;
+	return 0;
+}
+
+int sigchain_pop(int sig)
+{
+	struct sigchain_signal *s = signals + sig;
+	check_signum(sig);
+	if (s->n < 1)
+		return 0;
+
+	if (signal(sig, s->old[s->n - 1]) == SIG_ERR)
+		return -1;
+	s->n--;
+	return 0;
+}
+
+void sigchain_push_common(sigchain_fun f)
+{
+	sigchain_push(SIGINT, f);
+	sigchain_push(SIGHUP, f);
+	sigchain_push(SIGTERM, f);
+	sigchain_push(SIGQUIT, f);
+	sigchain_push(SIGPIPE, f);
+}
diff --git a/tools/lib/subcmd/sigchain.h b/tools/lib/subcmd/sigchain.h
new file mode 100644
index 000000000000..959d64eb5557
--- /dev/null
+++ b/tools/lib/subcmd/sigchain.h
@@ -0,0 +1,10 @@
+#ifndef __PERF_SIGCHAIN_H
+#define __PERF_SIGCHAIN_H
+
+typedef void (*sigchain_fun)(int);
+
+int sigchain_pop(int sig);
+
+void sigchain_push_common(sigchain_fun f);
+
+#endif /* __PERF_SIGCHAIN_H */
diff --git a/tools/lib/subcmd/subcmd-config.c b/tools/lib/subcmd/subcmd-config.c
new file mode 100644
index 000000000000..d017c728bd1b
--- /dev/null
+++ b/tools/lib/subcmd/subcmd-config.c
@@ -0,0 +1,11 @@
+#include "subcmd-config.h"
+
+#define UNDEFINED "SUBCMD_HAS_NOT_BEEN_INITIALIZED"
+
+struct subcmd_config subcmd_config = {
+	.exec_name	= UNDEFINED,
+	.prefix		= UNDEFINED,
+	.exec_path	= UNDEFINED,
+	.exec_path_env	= UNDEFINED,
+	.pager_env	= UNDEFINED,
+};
diff --git a/tools/lib/subcmd/subcmd-config.h b/tools/lib/subcmd/subcmd-config.h
new file mode 100644
index 000000000000..cc8514030b5c
--- /dev/null
+++ b/tools/lib/subcmd/subcmd-config.h
@@ -0,0 +1,14 @@
+#ifndef __PERF_SUBCMD_CONFIG_H
+#define __PERF_SUBCMD_CONFIG_H
+
+struct subcmd_config {
+	const char *exec_name;
+	const char *prefix;
+	const char *exec_path;
+	const char *exec_path_env;
+	const char *pager_env;
+};
+
+extern struct subcmd_config subcmd_config;
+
+#endif /* __PERF_SUBCMD_CONFIG_H */
diff --git a/tools/lib/subcmd/subcmd-util.h b/tools/lib/subcmd/subcmd-util.h
new file mode 100644
index 000000000000..321aeb11a381
--- /dev/null
+++ b/tools/lib/subcmd/subcmd-util.h
@@ -0,0 +1,91 @@
+#ifndef __PERF_SUBCMD_UTIL_H
+#define __PERF_SUBCMD_UTIL_H
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define NORETURN __attribute__((__noreturn__))
+
+static inline void report(const char *prefix, const char *err, va_list params)
+{
+	char msg[1024];
+	vsnprintf(msg, sizeof(msg), err, params);
+	fprintf(stderr, " %s%s\n", prefix, msg);
+}
+
+static NORETURN inline void die(const char *err, ...)
+{
+	va_list params;
+
+	va_start(params, err);
+	report(" Fatal: ", err, params);
+	exit(128);
+	va_end(params);
+}
+
+#define zfree(ptr) ({ free(*ptr); *ptr = NULL; })
+
+#define alloc_nr(x) (((x)+16)*3/2)
+
+/*
+ * Realloc the buffer pointed at by variable 'x' so that it can hold
+ * at least 'nr' entries; the number of entries currently allocated
+ * is 'alloc', using the standard growing factor alloc_nr() macro.
+ *
+ * DO NOT USE any expression with side-effect for 'x' or 'alloc'.
+ */
+#define ALLOC_GROW(x, nr, alloc) \
+	do { \
+		if ((nr) > alloc) { \
+			if (alloc_nr(alloc) < (nr)) \
+				alloc = (nr); \
+			else \
+				alloc = alloc_nr(alloc); \
+			x = xrealloc((x), alloc * sizeof(*(x))); \
+		} \
+	} while(0)
+
+static inline void *xrealloc(void *ptr, size_t size)
+{
+	void *ret = realloc(ptr, size);
+	if (!ret && !size)
+		ret = realloc(ptr, 1);
+	if (!ret) {
+		ret = realloc(ptr, size);
+		if (!ret && !size)
+			ret = realloc(ptr, 1);
+		if (!ret)
+			die("Out of memory, realloc failed");
+	}
+	return ret;
+}
+
+#define astrcatf(out, fmt, ...)						\
+({									\
+	char *tmp = *(out);						\
+	if (asprintf((out), "%s" fmt, tmp ?: "", ## __VA_ARGS__) == -1)	\
+		die("asprintf failed");					\
+	free(tmp);							\
+})
+
+static inline void astrcat(char **out, const char *add)
+{
+	char *tmp = *out;
+
+	if (asprintf(out, "%s%s", tmp ?: "", add) == -1)
+		die("asprintf failed");
+
+	free(tmp);
+}
+
+static inline int prefixcmp(const char *str, const char *prefix)
+{
+	for (; ; str++, prefix++)
+		if (!*prefix)
+			return 0;
+		else if (*str != *prefix)
+			return (unsigned char)*prefix - (unsigned char)*str;
+}
+
+#endif /* __PERF_SUBCMD_UTIL_H */
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST
index 2562eac6451d..ce3932ee4893 100644
--- a/tools/perf/MANIFEST
+++ b/tools/perf/MANIFEST
@@ -20,6 +20,7 @@ tools/lib/traceevent
 tools/lib/bpf
 tools/lib/api
 tools/lib/bpf
+tools/lib/subcmd
 tools/lib/hweight.c
 tools/lib/rbtree.c
 tools/lib/string.c
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 388ec64fa39b..569fcf022531 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -145,9 +145,10 @@ BISON   = bison
 STRIP   = strip
 AWK     = awk
 
-LIB_DIR          = $(srctree)/tools/lib/api/
+LIB_DIR		= $(srctree)/tools/lib/api/
 TRACE_EVENT_DIR = $(srctree)/tools/lib/traceevent/
-BPF_DIR = $(srctree)/tools/lib/bpf/
+BPF_DIR		= $(srctree)/tools/lib/bpf/
+SUBCMD_DIR	= $(srctree)/tools/lib/subcmd/
 
 # include config/Makefile by default and rule out
 # non-config cases
@@ -184,6 +185,7 @@ strip-libs = $(filter-out -l%,$(1))
 ifneq ($(OUTPUT),)
   TE_PATH=$(OUTPUT)
   BPF_PATH=$(OUTPUT)
+  SUBCMD_PATH=$(OUTPUT)
 ifneq ($(subdir),)
   API_PATH=$(OUTPUT)/../lib/api/
 else
@@ -193,6 +195,7 @@ else
   TE_PATH=$(TRACE_EVENT_DIR)
   API_PATH=$(LIB_DIR)
   BPF_PATH=$(BPF_DIR)
+  SUBCMD_PATH=$(SUBCMD_DIR)
 endif
 
 LIBTRACEEVENT = $(TE_PATH)libtraceevent.a
@@ -206,6 +209,8 @@ export LIBAPI
 
 LIBBPF = $(BPF_PATH)libbpf.a
 
+LIBSUBCMD = $(SUBCMD_PATH)libsubcmd.a
+
 # python extension build directories
 PYTHON_EXTBUILD     := $(OUTPUT)python_ext_build/
 PYTHON_EXTBUILD_LIB := $(PYTHON_EXTBUILD)lib/
@@ -257,7 +262,7 @@ export PERL_PATH
 
 LIB_FILE=$(OUTPUT)libperf.a
 
-PERFLIBS = $(LIB_FILE) $(LIBAPI) $(LIBTRACEEVENT)
+PERFLIBS = $(LIB_FILE) $(LIBAPI) $(LIBTRACEEVENT) $(LIBSUBCMD)
 ifndef NO_LIBBPF
   PERFLIBS += $(LIBBPF)
 endif
@@ -437,6 +442,13 @@ $(LIBBPF)-clean:
 	$(call QUIET_CLEAN, libbpf)
 	$(Q)$(MAKE) -C $(BPF_DIR) O=$(OUTPUT) clean >/dev/null
 
+$(LIBSUBCMD): fixdep FORCE
+	$(Q)$(MAKE) -C $(SUBCMD_DIR) O=$(OUTPUT) $(OUTPUT)libsubcmd.a
+
+$(LIBSUBCMD)-clean:
+	$(call QUIET_CLEAN, libsubcmd)
+	$(Q)$(MAKE) -C $(SUBCMD_DIR) O=$(OUTPUT) clean
+
 help:
 	@echo 'Perf make targets:'
 	@echo '  doc		- make *all* documentation (see below)'
@@ -584,7 +596,7 @@ config-clean:
 	$(call QUIET_CLEAN, config)
 	$(Q)$(MAKE) -C $(srctree)/tools/build/feature/ $(if $(OUTPUT),OUTPUT=$(OUTPUT)feature/,) clean >/dev/null
 
-clean: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean config-clean
+clean: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clean config-clean
 	$(call QUIET_CLEAN, core-objs)  $(RM) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(LANG_BINDINGS)
 	$(Q)find $(if $(OUTPUT),$(OUTPUT),.) -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete
 	$(Q)$(RM) $(OUTPUT).config-detected
diff --git a/tools/perf/arch/x86/util/intel-pt.c b/tools/perf/arch/x86/util/intel-pt.c
index b02af064f0f9..b64d46285ebb 100644
--- a/tools/perf/arch/x86/util/intel-pt.c
+++ b/tools/perf/arch/x86/util/intel-pt.c
@@ -26,7 +26,7 @@
 #include "../../util/evlist.h"
 #include "../../util/evsel.h"
 #include "../../util/cpumap.h"
-#include "../../util/parse-options.h"
+#include <subcmd/parse-options.h>
 #include "../../util/parse-events.h"
 #include "../../util/pmu.h"
 #include "../../util/debug.h"
diff --git a/tools/perf/bench/futex-hash.c b/tools/perf/bench/futex-hash.c
index fc9bebd2cca0..0999ac536d86 100644
--- a/tools/perf/bench/futex-hash.c
+++ b/tools/perf/bench/futex-hash.c
@@ -11,7 +11,7 @@
 #include "../perf.h"
 #include "../util/util.h"
 #include "../util/stat.h"
-#include "../util/parse-options.h"
+#include <subcmd/parse-options.h>
 #include "../util/header.h"
 #include "bench.h"
 #include "futex.h"
diff --git a/tools/perf/bench/futex-lock-pi.c b/tools/perf/bench/futex-lock-pi.c
index bc6a16adbca8..6a18ce21f865 100644
--- a/tools/perf/bench/futex-lock-pi.c
+++ b/tools/perf/bench/futex-lock-pi.c
@@ -5,7 +5,7 @@
 #include "../perf.h"
 #include "../util/util.h"
 #include "../util/stat.h"
-#include "../util/parse-options.h"
+#include <subcmd/parse-options.h>
 #include "../util/header.h"
 #include "bench.h"
 #include "futex.h"
diff --git a/tools/perf/bench/futex-requeue.c b/tools/perf/bench/futex-requeue.c
index ad0d9b5342fb..718238683013 100644
--- a/tools/perf/bench/futex-requeue.c
+++ b/tools/perf/bench/futex-requeue.c
@@ -11,7 +11,7 @@
 #include "../perf.h"
 #include "../util/util.h"
 #include "../util/stat.h"
-#include "../util/parse-options.h"
+#include <subcmd/parse-options.h>
 #include "../util/header.h"
 #include "bench.h"
 #include "futex.h"
diff --git a/tools/perf/bench/futex-wake-parallel.c b/tools/perf/bench/futex-wake-parallel.c
index 6d8c9fa2a16c..91aaf2a1fa90 100644
--- a/tools/perf/bench/futex-wake-parallel.c
+++ b/tools/perf/bench/futex-wake-parallel.c
@@ -10,7 +10,7 @@
 #include "../perf.h"
 #include "../util/util.h"
 #include "../util/stat.h"
-#include "../util/parse-options.h"
+#include <subcmd/parse-options.h>
 #include "../util/header.h"
 #include "bench.h"
 #include "futex.h"
diff --git a/tools/perf/bench/futex-wake.c b/tools/perf/bench/futex-wake.c
index e5e41d3bdce7..f416bd705f66 100644
--- a/tools/perf/bench/futex-wake.c
+++ b/tools/perf/bench/futex-wake.c
@@ -11,7 +11,7 @@
 #include "../perf.h"
 #include "../util/util.h"
 #include "../util/stat.h"
-#include "../util/parse-options.h"
+#include <subcmd/parse-options.h>
 #include "../util/header.h"
 #include "bench.h"
 #include "futex.h"
diff --git a/tools/perf/bench/mem-functions.c b/tools/perf/bench/mem-functions.c
index 9419b944220f..a91aa85d80ff 100644
--- a/tools/perf/bench/mem-functions.c
+++ b/tools/perf/bench/mem-functions.c
@@ -8,7 +8,7 @@
 
 #include "../perf.h"
 #include "../util/util.h"
-#include "../util/parse-options.h"
+#include <subcmd/parse-options.h>
 #include "../util/header.h"
 #include "../util/cloexec.h"
 #include "bench.h"
diff --git a/tools/perf/bench/numa.c b/tools/perf/bench/numa.c
index 492df2752a2d..5049d6357a46 100644
--- a/tools/perf/bench/numa.c
+++ b/tools/perf/bench/numa.c
@@ -7,7 +7,7 @@
 #include "../perf.h"
 #include "../builtin.h"
 #include "../util/util.h"
-#include "../util/parse-options.h"
+#include <subcmd/parse-options.h>
 #include "../util/cloexec.h"
 
 #include "bench.h"
diff --git a/tools/perf/bench/sched-messaging.c b/tools/perf/bench/sched-messaging.c
index d4ff1b539cfd..bfaf9503de8e 100644
--- a/tools/perf/bench/sched-messaging.c
+++ b/tools/perf/bench/sched-messaging.c
@@ -11,7 +11,7 @@
 
 #include "../perf.h"
 #include "../util/util.h"
-#include "../util/parse-options.h"
+#include <subcmd/parse-options.h>
 #include "../builtin.h"
 #include "bench.h"
 
diff --git a/tools/perf/bench/sched-pipe.c b/tools/perf/bench/sched-pipe.c
index 005cc283790c..1dc2d13cc272 100644
--- a/tools/perf/bench/sched-pipe.c
+++ b/tools/perf/bench/sched-pipe.c
@@ -10,7 +10,7 @@
  */
 #include "../perf.h"
 #include "../util/util.h"
-#include "../util/parse-options.h"
+#include <subcmd/parse-options.h>
 #include "../builtin.h"
 #include "bench.h"
 
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 1f00dc7cecba..e18f1b995ffd 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -21,7 +21,7 @@
 #include "util/evsel.h"
 #include "util/annotate.h"
 #include "util/event.h"
-#include "util/parse-options.h"
+#include <subcmd/parse-options.h>
 #include "util/parse-events.h"
 #include "util/thread.h"
 #include "util/sort.h"
diff --git a/tools/perf/builtin-bench.c b/tools/perf/builtin-bench.c
index b17aed36ca16..a1cddc6bbf0f 100644
--- a/tools/perf/builtin-bench.c
+++ b/tools/perf/builtin-bench.c
@@ -16,7 +16,7 @@
  */
 #include "perf.h"
 #include "util/util.h"
-#include "util/parse-options.h"
+#include <subcmd/parse-options.h>
 #include "builtin.h"
 #include "bench/bench.h"
 
diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c
index 7b8450cd33c2..d93bff7fc0e4 100644
--- a/tools/perf/builtin-buildid-cache.c
+++ b/tools/perf/builtin-buildid-cache.c
@@ -16,7 +16,7 @@
 #include "util/cache.h"
 #include "util/debug.h"
 #include "util/header.h"
-#include "util/parse-options.h"
+#include <subcmd/parse-options.h>
 #include "util/strlist.h"
 #include "util/build-id.h"
 #include "util/session.h"
diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
index 6419f57b0850..5e914ee79eb3 100644
--- a/tools/perf/builtin-buildid-list.c
+++ b/tools/perf/builtin-buildid-list.c
@@ -12,7 +12,7 @@
 #include "util/build-id.h"
 #include "util/cache.h"
 #include "util/debug.h"
-#include "util/parse-options.h"
+#include <subcmd/parse-options.h>
 #include "util/session.h"
 #include "util/symbol.h"
 #include "util/data.h"
diff --git a/tools/perf/builtin-config.c b/tools/perf/builtin-config.c
index 427ea7a705b8..f04e804a9fad 100644
--- a/tools/perf/builtin-config.c
+++ b/tools/perf/builtin-config.c
@@ -9,7 +9,7 @@
 #include "perf.h"
 
 #include "util/cache.h"
-#include "util/parse-options.h"
+#include <subcmd/parse-options.h>
 #include "util/util.h"
 #include "util/debug.h"
 
diff --git a/tools/perf/builtin-data.c b/tools/perf/builtin-data.c
index d6525bc54d13..b97bc1518b44 100644
--- a/tools/perf/builtin-data.c
+++ b/tools/perf/builtin-data.c
@@ -2,7 +2,7 @@
 #include "builtin.h"
 #include "perf.h"
 #include "debug.h"
-#include "parse-options.h"
+#include <subcmd/parse-options.h>
 #include "data-convert-bt.h"
 
 typedef int (*data_cmd_fn_t)(int argc, const char **argv, const char *prefix);
diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c
index f4d62510acbb..08a7d36a2cf8 100644
--- a/tools/perf/builtin-evlist.c
+++ b/tools/perf/builtin-evlist.c
@@ -12,7 +12,7 @@
 #include "util/evlist.h"
 #include "util/evsel.h"
 #include "util/parse-events.h"
-#include "util/parse-options.h"
+#include <subcmd/parse-options.h>
 #include "util/session.h"
 #include "util/data.h"
 #include "util/debug.h"
diff --git a/tools/perf/builtin-help.c b/tools/perf/builtin-help.c
index 275aa641c31c..96c1a4cfbbbf 100644
--- a/tools/perf/builtin-help.c
+++ b/tools/perf/builtin-help.c
@@ -6,11 +6,11 @@
 #include "perf.h"
 #include "util/cache.h"
 #include "builtin.h"
-#include "util/exec_cmd.h"
+#include <subcmd/exec-cmd.h>
 #include "common-cmds.h"
-#include "util/parse-options.h"
-#include "util/run-command.h"
-#include "util/help.h"
+#include <subcmd/parse-options.h>
+#include <subcmd/run-command.h>
+#include <subcmd/help.h>
 #include "util/debug.h"
 
 static struct man_viewer_list {
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 99d127fe9c35..0022e02ed31a 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -18,7 +18,7 @@
 #include "util/data.h"
 #include "util/auxtrace.h"
 
-#include "util/parse-options.h"
+#include <subcmd/parse-options.h>
 
 #include <linux/list.h>
 
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index 93ce665f976f..118010553d0c 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -12,7 +12,7 @@
 #include "util/tool.h"
 #include "util/callchain.h"
 
-#include "util/parse-options.h"
+#include <subcmd/parse-options.h>
 #include "util/trace-event.h"
 #include "util/data.h"
 #include "util/cpumap.h"
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 031f9f55c281..4418d9214872 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -10,7 +10,7 @@
 #include "util/header.h"
 #include "util/session.h"
 #include "util/intlist.h"
-#include "util/parse-options.h"
+#include <subcmd/parse-options.h>
 #include "util/trace-event.h"
 #include "util/debug.h"
 #include "util/tool.h"
diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c
index bf679e2c978b..5e22db4684b8 100644
--- a/tools/perf/builtin-list.c
+++ b/tools/perf/builtin-list.c
@@ -14,7 +14,7 @@
 #include "util/parse-events.h"
 #include "util/cache.h"
 #include "util/pmu.h"
-#include "util/parse-options.h"
+#include <subcmd/parse-options.h>
 
 int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
 {
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index de16aaed516e..ce3bfb48b26f 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -9,7 +9,7 @@
 #include "util/thread.h"
 #include "util/header.h"
 
-#include "util/parse-options.h"
+#include <subcmd/parse-options.h>
 #include "util/trace-event.h"
 
 #include "util/debug.h"
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c
index 80170aace5d4..390170041696 100644
--- a/tools/perf/builtin-mem.c
+++ b/tools/perf/builtin-mem.c
@@ -1,7 +1,7 @@
 #include "builtin.h"
 #include "perf.h"
 
-#include "util/parse-options.h"
+#include <subcmd/parse-options.h>
 #include "util/trace-event.h"
 #include "util/tool.h"
 #include "util/session.h"
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index dbe2ea5a2932..9af859b28b15 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -37,7 +37,7 @@
 #include "util/strfilter.h"
 #include "util/symbol.h"
 #include "util/debug.h"
-#include "util/parse-options.h"
+#include <subcmd/parse-options.h>
 #include "util/probe-finder.h"
 #include "util/probe-event.h"
 #include "util/probe-file.h"
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index a3b4930737c6..1435ef6265b6 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -11,7 +11,7 @@
 
 #include "util/build-id.h"
 #include "util/util.h"
-#include "util/parse-options.h"
+#include <subcmd/parse-options.h>
 #include "util/parse-events.h"
 
 #include "util/callchain.h"
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 5a454669d075..2a7330b99b82 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -27,7 +27,7 @@
 #include "util/session.h"
 #include "util/tool.h"
 
-#include "util/parse-options.h"
+#include <subcmd/parse-options.h>
 #include "util/parse-events.h"
 
 #include "util/thread.h"
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index e3d3e32c0a93..871b55ae22a4 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -12,7 +12,7 @@
 #include "util/tool.h"
 #include "util/cloexec.h"
 
-#include "util/parse-options.h"
+#include <subcmd/parse-options.h>
 #include "util/trace-event.h"
 
 #include "util/debug.h"
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 571016f16c5a..bcc3542d9df5 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -3,9 +3,9 @@
 #include "perf.h"
 #include "util/cache.h"
 #include "util/debug.h"
-#include "util/exec_cmd.h"
+#include <subcmd/exec-cmd.h>
 #include "util/header.h"
-#include "util/parse-options.h"
+#include <subcmd/parse-options.h>
 #include "util/perf_regs.h"
 #include "util/session.h"
 #include "util/tool.h"
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 25a95f49c36e..bbf42eefd5e5 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -45,7 +45,7 @@
 #include "builtin.h"
 #include "util/cgroup.h"
 #include "util/util.h"
-#include "util/parse-options.h"
+#include <subcmd/parse-options.h>
 #include "util/parse-events.h"
 #include "util/pmu.h"
 #include "util/event.h"
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index 30e59620179d..bd7a7757176f 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -30,7 +30,7 @@
 
 #include "perf.h"
 #include "util/header.h"
-#include "util/parse-options.h"
+#include <subcmd/parse-options.h>
 #include "util/parse-events.h"
 #include "util/event.h"
 #include "util/session.h"
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 92fe963e43c4..9ebd67a42ede 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -34,7 +34,7 @@
 #include "util/top.h"
 #include "util/util.h"
 #include <linux/rbtree.h>
-#include "util/parse-options.h"
+#include <subcmd/parse-options.h>
 #include "util/parse-events.h"
 #include "util/cpumap.h"
 #include "util/xyarray.h"
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index c783d8fd3a80..20916dd77aac 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -22,11 +22,11 @@
 #include "util/color.h"
 #include "util/debug.h"
 #include "util/evlist.h"
-#include "util/exec_cmd.h"
+#include <subcmd/exec-cmd.h>
 #include "util/machine.h"
 #include "util/session.h"
 #include "util/thread.h"
-#include "util/parse-options.h"
+#include <subcmd/parse-options.h>
 #include "util/strlist.h"
 #include "util/intlist.h"
 #include "util/thread_map.h"
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 6894325fe921..cb1d2499c45c 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -9,12 +9,12 @@
 #include "builtin.h"
 
 #include "util/env.h"
-#include "util/exec_cmd.h"
+#include <subcmd/exec-cmd.h>
 #include "util/cache.h"
 #include "util/quote.h"
-#include "util/run-command.h"
+#include <subcmd/run-command.h>
 #include "util/parse-events.h"
-#include "util/parse-options.h"
+#include <subcmd/parse-options.h>
 #include "util/bpf-loader.h"
 #include "util/debug.h"
 #include <api/fs/tracing_path.h>
diff --git a/tools/perf/tests/attr.c b/tools/perf/tests/attr.c
index 6337f1c07f02..28d1605b0338 100644
--- a/tools/perf/tests/attr.c
+++ b/tools/perf/tests/attr.c
@@ -24,7 +24,7 @@
 #include <linux/kernel.h>
 #include "../perf.h"
 #include "util.h"
-#include "exec_cmd.h"
+#include <subcmd/exec-cmd.h>
 #include "tests.h"
 
 #define ENV "PERF_TEST_ATTR"
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index fa98406c92e2..0372d5945910 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -11,7 +11,7 @@
 #include "tests.h"
 #include "debug.h"
 #include "color.h"
-#include "parse-options.h"
+#include <subcmd/parse-options.h>
 #include "symbol.h"
 
 struct test __weak arch_tests[] = {
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index 196beefa16a9..94b1099f2c22 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -9,13 +9,10 @@ libperf-y += env.o
 libperf-y += event.o
 libperf-y += evlist.o
 libperf-y += evsel.o
-libperf-y += exec_cmd.o
 libperf-y += find_next_bit.o
-libperf-y += help.o
 libperf-y += kallsyms.o
 libperf-y += levenshtein.o
 libperf-y += llvm-utils.o
-libperf-y += parse-options.o
 libperf-y += parse-events.o
 libperf-y += perf_regs.o
 libperf-y += path.o
@@ -23,7 +20,6 @@ libperf-y += rbtree.o
 libperf-y += libstring.o
 libperf-y += bitmap.o
 libperf-y += hweight.o
-libperf-y += run-command.o
 libperf-y += quote.o
 libperf-y += strbuf.o
 libperf-y += string.o
@@ -32,11 +28,9 @@ libperf-y += strfilter.o
 libperf-y += top.o
 libperf-y += usage.o
 libperf-y += wrapper.o
-libperf-y += sigchain.o
 libperf-y += dso.o
 libperf-y += symbol.o
 libperf-y += color.o
-libperf-y += pager.o
 libperf-y += header.o
 libperf-y += callchain.o
 libperf-y += values.o
@@ -88,7 +82,6 @@ libperf-y += parse-branch-options.o
 libperf-y += parse-regs-options.o
 libperf-y += term.o
 libperf-y += help-unknown-cmd.o
-libperf-y += subcmd-config.o
 
 libperf-$(CONFIG_LIBBPF) += bpf-loader.o
 libperf-$(CONFIG_BPF_PROLOGUE) += bpf-prologue.o
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
index 7f10430af39c..360fda01f3b0 100644
--- a/tools/perf/util/auxtrace.c
+++ b/tools/perf/util/auxtrace.c
@@ -45,7 +45,7 @@
 #include "event.h"
 #include "session.h"
 #include "debug.h"
-#include "parse-options.h"
+#include <subcmd/parse-options.h>
 
 #include "intel-pt.h"
 #include "intel-bts.h"
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index fc6a745d2ec6..07b5d63947b1 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -4,7 +4,7 @@
 #include <stdbool.h>
 #include "util.h"
 #include "strbuf.h"
-#include "pager.h"
+#include <subcmd/pager.h>
 #include "../perf.h"
 #include "../ui/ui.h"
 
diff --git a/tools/perf/util/cgroup.c b/tools/perf/util/cgroup.c
index 32e12ecfe9c5..90aa1b46b2e5 100644
--- a/tools/perf/util/cgroup.c
+++ b/tools/perf/util/cgroup.c
@@ -1,6 +1,6 @@
 #include "util.h"
 #include "../perf.h"
-#include "parse-options.h"
+#include <subcmd/parse-options.h>
 #include "evsel.h"
 #include "cgroup.h"
 #include "evlist.h"
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c
index 2e452ac1353d..d3e12e30e1d5 100644
--- a/tools/perf/util/config.c
+++ b/tools/perf/util/config.c
@@ -10,7 +10,7 @@
  */
 #include "util.h"
 #include "cache.h"
-#include "exec_cmd.h"
+#include <subcmd/exec-cmd.h>
 #include "util/hist.h"  /* perf_hist_config */
 #include "util/llvm-utils.h"   /* perf_llvm_config */
 
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index d1b6c206bb93..8c44aadb9810 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -18,7 +18,7 @@
 #include <unistd.h>
 
 #include "parse-events.h"
-#include "parse-options.h"
+#include <subcmd/parse-options.h>
 
 #include <sys/mman.h>
 
diff --git a/tools/perf/util/exec_cmd.c b/tools/perf/util/exec_cmd.c
deleted file mode 100644
index e7f9ed7943e3..000000000000
--- a/tools/perf/util/exec_cmd.c
+++ /dev/null
@@ -1,209 +0,0 @@
-#include <linux/compiler.h>
-#include <linux/string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include "subcmd-util.h"
-#include "exec_cmd.h"
-#include "subcmd-config.h"
-
-#define MAX_ARGS	32
-#define PATH_MAX	4096
-
-static const char *argv_exec_path;
-static const char *argv0_path;
-
-void exec_cmd_init(const char *exec_name, const char *prefix,
-		   const char *exec_path, const char *exec_path_env)
-{
-	subcmd_config.exec_name		= exec_name;
-	subcmd_config.prefix		= prefix;
-	subcmd_config.exec_path		= exec_path;
-	subcmd_config.exec_path_env	= exec_path_env;
-}
-
-#define is_dir_sep(c) ((c) == '/')
-
-static int is_absolute_path(const char *path)
-{
-	return path[0] == '/';
-}
-
-static const char *get_pwd_cwd(void)
-{
-	static char cwd[PATH_MAX + 1];
-	char *pwd;
-	struct stat cwd_stat, pwd_stat;
-	if (getcwd(cwd, PATH_MAX) == NULL)
-		return NULL;
-	pwd = getenv("PWD");
-	if (pwd && strcmp(pwd, cwd)) {
-		stat(cwd, &cwd_stat);
-		if (!stat(pwd, &pwd_stat) &&
-		    pwd_stat.st_dev == cwd_stat.st_dev &&
-		    pwd_stat.st_ino == cwd_stat.st_ino) {
-			strlcpy(cwd, pwd, PATH_MAX);
-		}
-	}
-	return cwd;
-}
-
-static const char *make_nonrelative_path(const char *path)
-{
-	static char buf[PATH_MAX + 1];
-
-	if (is_absolute_path(path)) {
-		if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX)
-			die("Too long path: %.*s", 60, path);
-	} else {
-		const char *cwd = get_pwd_cwd();
-		if (!cwd)
-			die("Cannot determine the current working directory");
-		if (snprintf(buf, PATH_MAX, "%s/%s", cwd, path) >= PATH_MAX)
-			die("Too long path: %.*s", 60, path);
-	}
-	return buf;
-}
-
-char *system_path(const char *path)
-{
-	char *buf = NULL;
-
-	if (is_absolute_path(path))
-		return strdup(path);
-
-	astrcatf(&buf, "%s/%s", subcmd_config.prefix, path);
-
-	return buf;
-}
-
-const char *extract_argv0_path(const char *argv0)
-{
-	const char *slash;
-
-	if (!argv0 || !*argv0)
-		return NULL;
-	slash = argv0 + strlen(argv0);
-
-	while (argv0 <= slash && !is_dir_sep(*slash))
-		slash--;
-
-	if (slash >= argv0) {
-		argv0_path = strndup(argv0, slash - argv0);
-		return argv0_path ? slash + 1 : NULL;
-	}
-
-	return argv0;
-}
-
-void set_argv_exec_path(const char *exec_path)
-{
-	argv_exec_path = exec_path;
-	/*
-	 * Propagate this setting to external programs.
-	 */
-	setenv(subcmd_config.exec_path_env, exec_path, 1);
-}
-
-
-/* Returns the highest-priority location to look for subprograms. */
-char *get_argv_exec_path(void)
-{
-	char *env;
-
-	if (argv_exec_path)
-		return strdup(argv_exec_path);
-
-	env = getenv(subcmd_config.exec_path_env);
-	if (env && *env)
-		return strdup(env);
-
-	return system_path(subcmd_config.exec_path);
-}
-
-static void add_path(char **out, const char *path)
-{
-	if (path && *path) {
-		if (is_absolute_path(path))
-			astrcat(out, path);
-		else
-			astrcat(out, make_nonrelative_path(path));
-
-		astrcat(out, ":");
-	}
-}
-
-void setup_path(void)
-{
-	const char *old_path = getenv("PATH");
-	char *new_path = NULL;
-	char *tmp = get_argv_exec_path();
-
-	add_path(&new_path, tmp);
-	add_path(&new_path, argv0_path);
-	free(tmp);
-
-	if (old_path)
-		astrcat(&new_path, old_path);
-	else
-		astrcat(&new_path, "/usr/local/bin:/usr/bin:/bin");
-
-	setenv("PATH", new_path, 1);
-
-	free(new_path);
-}
-
-static const char **prepare_exec_cmd(const char **argv)
-{
-	int argc;
-	const char **nargv;
-
-	for (argc = 0; argv[argc]; argc++)
-		; /* just counting */
-	nargv = malloc(sizeof(*nargv) * (argc + 2));
-
-	nargv[0] = subcmd_config.exec_name;
-	for (argc = 0; argv[argc]; argc++)
-		nargv[argc + 1] = argv[argc];
-	nargv[argc + 1] = NULL;
-	return nargv;
-}
-
-int execv_cmd(const char **argv) {
-	const char **nargv = prepare_exec_cmd(argv);
-
-	/* execvp() can only ever return if it fails */
-	execvp(subcmd_config.exec_name, (char **)nargv);
-
-	free(nargv);
-	return -1;
-}
-
-
-int execl_cmd(const char *cmd,...)
-{
-	int argc;
-	const char *argv[MAX_ARGS + 1];
-	const char *arg;
-	va_list param;
-
-	va_start(param, cmd);
-	argv[0] = cmd;
-	argc = 1;
-	while (argc < MAX_ARGS) {
-		arg = argv[argc++] = va_arg(param, char *);
-		if (!arg)
-			break;
-	}
-	va_end(param);
-	if (MAX_ARGS <= argc) {
-		fprintf(stderr, " Error: too many args to run %s\n", cmd);
-		return -1;
-	}
-
-	argv[argc] = NULL;
-	return execv_cmd(argv);
-}
diff --git a/tools/perf/util/exec_cmd.h b/tools/perf/util/exec_cmd.h
deleted file mode 100644
index f1bd3436ad5f..000000000000
--- a/tools/perf/util/exec_cmd.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef __PERF_EXEC_CMD_H
-#define __PERF_EXEC_CMD_H
-
-extern void exec_cmd_init(const char *exec_name, const char *prefix,
-			  const char *exec_path, const char *exec_path_env);
-
-extern void set_argv_exec_path(const char *exec_path);
-extern const char *extract_argv0_path(const char *path);
-extern void setup_path(void);
-extern int execv_cmd(const char **argv); /* NULL terminated */
-extern int execl_cmd(const char *cmd, ...);
-/* get_argv_exec_path and system_path return malloc'd string, caller must free it */
-extern char *get_argv_exec_path(void);
-extern char *system_path(const char *path);
-
-#endif /* __PERF_EXEC_CMD_H */
diff --git a/tools/perf/util/help-unknown-cmd.c b/tools/perf/util/help-unknown-cmd.c
index a0820f16f511..dc1e41c9b054 100644
--- a/tools/perf/util/help-unknown-cmd.c
+++ b/tools/perf/util/help-unknown-cmd.c
@@ -1,5 +1,5 @@
 #include "cache.h"
-#include "help.h"
+#include <subcmd/help.h>
 #include "../builtin.h"
 #include "levenshtein.h"
 
diff --git a/tools/perf/util/help.c b/tools/perf/util/help.c
deleted file mode 100644
index 8169480066c6..000000000000
--- a/tools/perf/util/help.c
+++ /dev/null
@@ -1,268 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <dirent.h>
-#include "subcmd-util.h"
-#include "help.h"
-#include "exec_cmd.h"
-
-void add_cmdname(struct cmdnames *cmds, const char *name, size_t len)
-{
-	struct cmdname *ent = malloc(sizeof(*ent) + len + 1);
-
-	ent->len = len;
-	memcpy(ent->name, name, len);
-	ent->name[len] = 0;
-
-	ALLOC_GROW(cmds->names, cmds->cnt + 1, cmds->alloc);
-	cmds->names[cmds->cnt++] = ent;
-}
-
-void clean_cmdnames(struct cmdnames *cmds)
-{
-	unsigned int i;
-
-	for (i = 0; i < cmds->cnt; ++i)
-		zfree(&cmds->names[i]);
-	zfree(&cmds->names);
-	cmds->cnt = 0;
-	cmds->alloc = 0;
-}
-
-int cmdname_compare(const void *a_, const void *b_)
-{
-	struct cmdname *a = *(struct cmdname **)a_;
-	struct cmdname *b = *(struct cmdname **)b_;
-	return strcmp(a->name, b->name);
-}
-
-void uniq(struct cmdnames *cmds)
-{
-	unsigned int i, j;
-
-	if (!cmds->cnt)
-		return;
-
-	for (i = j = 1; i < cmds->cnt; i++)
-		if (strcmp(cmds->names[i]->name, cmds->names[i-1]->name))
-			cmds->names[j++] = cmds->names[i];
-
-	cmds->cnt = j;
-}
-
-void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes)
-{
-	size_t ci, cj, ei;
-	int cmp;
-
-	ci = cj = ei = 0;
-	while (ci < cmds->cnt && ei < excludes->cnt) {
-		cmp = strcmp(cmds->names[ci]->name, excludes->names[ei]->name);
-		if (cmp < 0)
-			cmds->names[cj++] = cmds->names[ci++];
-		else if (cmp == 0)
-			ci++, ei++;
-		else if (cmp > 0)
-			ei++;
-	}
-
-	while (ci < cmds->cnt)
-		cmds->names[cj++] = cmds->names[ci++];
-
-	cmds->cnt = cj;
-}
-
-static void get_term_dimensions(struct winsize *ws)
-{
-	char *s = getenv("LINES");
-
-	if (s != NULL) {
-		ws->ws_row = atoi(s);
-		s = getenv("COLUMNS");
-		if (s != NULL) {
-			ws->ws_col = atoi(s);
-			if (ws->ws_row && ws->ws_col)
-				return;
-		}
-	}
-#ifdef TIOCGWINSZ
-	if (ioctl(1, TIOCGWINSZ, ws) == 0 &&
-	    ws->ws_row && ws->ws_col)
-		return;
-#endif
-	ws->ws_row = 25;
-	ws->ws_col = 80;
-}
-
-static void pretty_print_string_list(struct cmdnames *cmds, int longest)
-{
-	int cols = 1, rows;
-	int space = longest + 1; /* min 1 SP between words */
-	struct winsize win;
-	int max_cols;
-	int i, j;
-
-	get_term_dimensions(&win);
-	max_cols = win.ws_col - 1; /* don't print *on* the edge */
-
-	if (space < max_cols)
-		cols = max_cols / space;
-	rows = (cmds->cnt + cols - 1) / cols;
-
-	for (i = 0; i < rows; i++) {
-		printf("  ");
-
-		for (j = 0; j < cols; j++) {
-			unsigned int n = j * rows + i;
-			unsigned int size = space;
-
-			if (n >= cmds->cnt)
-				break;
-			if (j == cols-1 || n + rows >= cmds->cnt)
-				size = 1;
-			printf("%-*s", size, cmds->names[n]->name);
-		}
-		putchar('\n');
-	}
-}
-
-static int is_executable(const char *name)
-{
-	struct stat st;
-
-	if (stat(name, &st) || /* stat, not lstat */
-	    !S_ISREG(st.st_mode))
-		return 0;
-
-	return st.st_mode & S_IXUSR;
-}
-
-static int has_extension(const char *filename, const char *ext)
-{
-	size_t len = strlen(filename);
-	size_t extlen = strlen(ext);
-
-	return len > extlen && !memcmp(filename + len - extlen, ext, extlen);
-}
-
-static void list_commands_in_dir(struct cmdnames *cmds,
-					 const char *path,
-					 const char *prefix)
-{
-	int prefix_len;
-	DIR *dir = opendir(path);
-	struct dirent *de;
-	char *buf = NULL;
-
-	if (!dir)
-		return;
-	if (!prefix)
-		prefix = "perf-";
-	prefix_len = strlen(prefix);
-
-	astrcatf(&buf, "%s/", path);
-
-	while ((de = readdir(dir)) != NULL) {
-		int entlen;
-
-		if (prefixcmp(de->d_name, prefix))
-			continue;
-
-		astrcat(&buf, de->d_name);
-		if (!is_executable(buf))
-			continue;
-
-		entlen = strlen(de->d_name) - prefix_len;
-		if (has_extension(de->d_name, ".exe"))
-			entlen -= 4;
-
-		add_cmdname(cmds, de->d_name + prefix_len, entlen);
-	}
-	closedir(dir);
-	free(buf);
-}
-
-void load_command_list(const char *prefix,
-		struct cmdnames *main_cmds,
-		struct cmdnames *other_cmds)
-{
-	const char *env_path = getenv("PATH");
-	char *exec_path = get_argv_exec_path();
-
-	if (exec_path) {
-		list_commands_in_dir(main_cmds, exec_path, prefix);
-		qsort(main_cmds->names, main_cmds->cnt,
-		      sizeof(*main_cmds->names), cmdname_compare);
-		uniq(main_cmds);
-	}
-
-	if (env_path) {
-		char *paths, *path, *colon;
-		path = paths = strdup(env_path);
-		while (1) {
-			if ((colon = strchr(path, ':')))
-				*colon = 0;
-			if (!exec_path || strcmp(path, exec_path))
-				list_commands_in_dir(other_cmds, path, prefix);
-
-			if (!colon)
-				break;
-			path = colon + 1;
-		}
-		free(paths);
-
-		qsort(other_cmds->names, other_cmds->cnt,
-		      sizeof(*other_cmds->names), cmdname_compare);
-		uniq(other_cmds);
-	}
-	free(exec_path);
-	exclude_cmds(other_cmds, main_cmds);
-}
-
-void list_commands(const char *title, struct cmdnames *main_cmds,
-		   struct cmdnames *other_cmds)
-{
-	unsigned int i, longest = 0;
-
-	for (i = 0; i < main_cmds->cnt; i++)
-		if (longest < main_cmds->names[i]->len)
-			longest = main_cmds->names[i]->len;
-	for (i = 0; i < other_cmds->cnt; i++)
-		if (longest < other_cmds->names[i]->len)
-			longest = other_cmds->names[i]->len;
-
-	if (main_cmds->cnt) {
-		char *exec_path = get_argv_exec_path();
-		printf("available %s in '%s'\n", title, exec_path);
-		printf("----------------");
-		mput_char('-', strlen(title) + strlen(exec_path));
-		putchar('\n');
-		pretty_print_string_list(main_cmds, longest);
-		putchar('\n');
-		free(exec_path);
-	}
-
-	if (other_cmds->cnt) {
-		printf("%s available from elsewhere on your $PATH\n", title);
-		printf("---------------------------------------");
-		mput_char('-', strlen(title));
-		putchar('\n');
-		pretty_print_string_list(other_cmds, longest);
-		putchar('\n');
-	}
-}
-
-int is_in_cmdlist(struct cmdnames *c, const char *s)
-{
-	unsigned int i;
-
-	for (i = 0; i < c->cnt; i++)
-		if (!strcmp(s, c->names[i]->name))
-			return 1;
-	return 0;
-}
diff --git a/tools/perf/util/help.h b/tools/perf/util/help.h
deleted file mode 100644
index 096c8bc45cd7..000000000000
--- a/tools/perf/util/help.h
+++ /dev/null
@@ -1,34 +0,0 @@
-#ifndef __PERF_HELP_H
-#define __PERF_HELP_H
-
-#include <sys/types.h>
-
-struct cmdnames {
-	size_t alloc;
-	size_t cnt;
-	struct cmdname {
-		size_t len; /* also used for similarity index in help.c */
-		char name[];
-	} **names;
-};
-
-static inline void mput_char(char c, unsigned int num)
-{
-	while(num--)
-		putchar(c);
-}
-
-void load_command_list(const char *prefix,
-		struct cmdnames *main_cmds,
-		struct cmdnames *other_cmds);
-void add_cmdname(struct cmdnames *cmds, const char *name, size_t len);
-void clean_cmdnames(struct cmdnames *cmds);
-int cmdname_compare(const void *a, const void *b);
-void uniq(struct cmdnames *cmds);
-/* Here we require that excludes is a sorted list. */
-void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes);
-int is_in_cmdlist(struct cmdnames *c, const char *s);
-void list_commands(const char *title, struct cmdnames *main_cmds,
-		   struct cmdnames *other_cmds);
-
-#endif /* __PERF_HELP_H */
diff --git a/tools/perf/util/pager.c b/tools/perf/util/pager.c
deleted file mode 100644
index d50f3b58606b..000000000000
--- a/tools/perf/util/pager.c
+++ /dev/null
@@ -1,100 +0,0 @@
-#include <sys/select.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <signal.h>
-#include "pager.h"
-#include "run-command.h"
-#include "sigchain.h"
-#include "subcmd-config.h"
-
-/*
- * This is split up from the rest of git so that we can do
- * something different on Windows.
- */
-
-static int spawned_pager;
-
-void pager_init(const char *pager_env)
-{
-	subcmd_config.pager_env = pager_env;
-}
-
-static void pager_preexec(void)
-{
-	/*
-	 * Work around bug in "less" by not starting it until we
-	 * have real input
-	 */
-	fd_set in;
-
-	FD_ZERO(&in);
-	FD_SET(0, &in);
-	select(1, &in, NULL, &in, NULL);
-
-	setenv("LESS", "FRSX", 0);
-}
-
-static const char *pager_argv[] = { "sh", "-c", NULL, NULL };
-static struct child_process pager_process;
-
-static void wait_for_pager(void)
-{
-	fflush(stdout);
-	fflush(stderr);
-	/* signal EOF to pager */
-	close(1);
-	close(2);
-	finish_command(&pager_process);
-}
-
-static void wait_for_pager_signal(int signo)
-{
-	wait_for_pager();
-	sigchain_pop(signo);
-	raise(signo);
-}
-
-void setup_pager(void)
-{
-	const char *pager = getenv(subcmd_config.pager_env);
-
-	if (!isatty(1))
-		return;
-	if (!pager)
-		pager = getenv("PAGER");
-	if (!(pager || access("/usr/bin/pager", X_OK)))
-		pager = "/usr/bin/pager";
-	if (!(pager || access("/usr/bin/less", X_OK)))
-		pager = "/usr/bin/less";
-	if (!pager)
-		pager = "cat";
-	if (!*pager || !strcmp(pager, "cat"))
-		return;
-
-	spawned_pager = 1; /* means we are emitting to terminal */
-
-	/* spawn the pager */
-	pager_argv[2] = pager;
-	pager_process.argv = pager_argv;
-	pager_process.in = -1;
-	pager_process.preexec_cb = pager_preexec;
-
-	if (start_command(&pager_process))
-		return;
-
-	/* original process continues, but writes to the pipe */
-	dup2(pager_process.in, 1);
-	if (isatty(2))
-		dup2(pager_process.in, 2);
-	close(pager_process.in);
-
-	/* this makes sure that the parent terminates after the pager */
-	sigchain_push_common(wait_for_pager_signal);
-	atexit(wait_for_pager);
-}
-
-int pager_in_use(void)
-{
-	return spawned_pager;
-}
diff --git a/tools/perf/util/pager.h b/tools/perf/util/pager.h
deleted file mode 100644
index d6a591a4c017..000000000000
--- a/tools/perf/util/pager.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef __PERF_PAGER_H
-#define __PERF_PAGER_H
-
-extern void pager_init(const char *pager_env);
-
-extern void setup_pager(void);
-extern int pager_in_use(void);
-
-#endif /* __PERF_PAGER_H */
diff --git a/tools/perf/util/parse-branch-options.c b/tools/perf/util/parse-branch-options.c
index 355eecf6bf59..afc088dd7d20 100644
--- a/tools/perf/util/parse-branch-options.c
+++ b/tools/perf/util/parse-branch-options.c
@@ -1,7 +1,7 @@
 #include "perf.h"
 #include "util/util.h"
 #include "util/debug.h"
-#include "util/parse-options.h"
+#include <subcmd/parse-options.h>
 #include "util/parse-branch-options.h"
 
 #define BRANCH_OPT(n, m) \
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 6fc8cd753e1a..4f7b0efdde2f 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -4,9 +4,9 @@
 #include "../perf.h"
 #include "evlist.h"
 #include "evsel.h"
-#include "parse-options.h"
+#include <subcmd/parse-options.h>
 #include "parse-events.h"
-#include "exec_cmd.h"
+#include <subcmd/exec-cmd.h>
 #include "string.h"
 #include "symbol.h"
 #include "cache.h"
diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c
deleted file mode 100644
index f4240275714a..000000000000
--- a/tools/perf/util/parse-options.c
+++ /dev/null
@@ -1,984 +0,0 @@
-#include <linux/compiler.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <string.h>
-#include <ctype.h>
-#include "subcmd-util.h"
-#include "parse-options.h"
-#include "subcmd-config.h"
-#include "pager.h"
-
-#define OPT_SHORT 1
-#define OPT_UNSET 2
-
-typedef uint64_t u64;
-
-char *error_buf;
-
-static int opterror(const struct option *opt, const char *reason, int flags)
-{
-	if (flags & OPT_SHORT)
-		fprintf(stderr, " Error: switch `%c' %s", opt->short_name, reason);
-	else if (flags & OPT_UNSET)
-		fprintf(stderr, " Error: option `no-%s' %s", opt->long_name, reason);
-	else
-		fprintf(stderr, " Error: option `%s' %s", opt->long_name, reason);
-
-	return -1;
-}
-
-static const char *skip_prefix(const char *str, const char *prefix)
-{
-	size_t len = strlen(prefix);
-	return strncmp(str, prefix, len) ? NULL : str + len;
-}
-
-static void optwarning(const struct option *opt, const char *reason, int flags)
-{
-	if (flags & OPT_SHORT)
-		fprintf(stderr, " Warning: switch `%c' %s", opt->short_name, reason);
-	else if (flags & OPT_UNSET)
-		fprintf(stderr, " Warning: option `no-%s' %s", opt->long_name, reason);
-	else
-		fprintf(stderr, " Warning: option `%s' %s", opt->long_name, reason);
-}
-
-static int get_arg(struct parse_opt_ctx_t *p, const struct option *opt,
-		   int flags, const char **arg)
-{
-	const char *res;
-
-	if (p->opt) {
-		res = p->opt;
-		p->opt = NULL;
-	} else if ((opt->flags & PARSE_OPT_LASTARG_DEFAULT) && (p->argc == 1 ||
-		    **(p->argv + 1) == '-')) {
-		res = (const char *)opt->defval;
-	} else if (p->argc > 1) {
-		p->argc--;
-		res = *++p->argv;
-	} else
-		return opterror(opt, "requires a value", flags);
-	if (arg)
-		*arg = res;
-	return 0;
-}
-
-static int get_value(struct parse_opt_ctx_t *p,
-		     const struct option *opt, int flags)
-{
-	const char *s, *arg = NULL;
-	const int unset = flags & OPT_UNSET;
-	int err;
-
-	if (unset && p->opt)
-		return opterror(opt, "takes no value", flags);
-	if (unset && (opt->flags & PARSE_OPT_NONEG))
-		return opterror(opt, "isn't available", flags);
-	if (opt->flags & PARSE_OPT_DISABLED)
-		return opterror(opt, "is not usable", flags);
-
-	if (opt->flags & PARSE_OPT_EXCLUSIVE) {
-		if (p->excl_opt && p->excl_opt != opt) {
-			char msg[128];
-
-			if (((flags & OPT_SHORT) && p->excl_opt->short_name) ||
-			    p->excl_opt->long_name == NULL) {
-				snprintf(msg, sizeof(msg), "cannot be used with switch `%c'",
-					 p->excl_opt->short_name);
-			} else {
-				snprintf(msg, sizeof(msg), "cannot be used with %s",
-					 p->excl_opt->long_name);
-			}
-			opterror(opt, msg, flags);
-			return -3;
-		}
-		p->excl_opt = opt;
-	}
-	if (!(flags & OPT_SHORT) && p->opt) {
-		switch (opt->type) {
-		case OPTION_CALLBACK:
-			if (!(opt->flags & PARSE_OPT_NOARG))
-				break;
-			/* FALLTHROUGH */
-		case OPTION_BOOLEAN:
-		case OPTION_INCR:
-		case OPTION_BIT:
-		case OPTION_SET_UINT:
-		case OPTION_SET_PTR:
-			return opterror(opt, "takes no value", flags);
-		case OPTION_END:
-		case OPTION_ARGUMENT:
-		case OPTION_GROUP:
-		case OPTION_STRING:
-		case OPTION_INTEGER:
-		case OPTION_UINTEGER:
-		case OPTION_LONG:
-		case OPTION_U64:
-		default:
-			break;
-		}
-	}
-
-	if (opt->flags & PARSE_OPT_NOBUILD) {
-		char reason[128];
-		bool noarg = false;
-
-		err = snprintf(reason, sizeof(reason),
-				opt->flags & PARSE_OPT_CANSKIP ?
-					"is being ignored because %s " :
-					"is not available because %s",
-				opt->build_opt);
-		reason[sizeof(reason) - 1] = '\0';
-
-		if (err < 0)
-			strncpy(reason, opt->flags & PARSE_OPT_CANSKIP ?
-					"is being ignored" :
-					"is not available",
-					sizeof(reason));
-
-		if (!(opt->flags & PARSE_OPT_CANSKIP))
-			return opterror(opt, reason, flags);
-
-		err = 0;
-		if (unset)
-			noarg = true;
-		if (opt->flags & PARSE_OPT_NOARG)
-			noarg = true;
-		if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
-			noarg = true;
-
-		switch (opt->type) {
-		case OPTION_BOOLEAN:
-		case OPTION_INCR:
-		case OPTION_BIT:
-		case OPTION_SET_UINT:
-		case OPTION_SET_PTR:
-		case OPTION_END:
-		case OPTION_ARGUMENT:
-		case OPTION_GROUP:
-			noarg = true;
-			break;
-		case OPTION_CALLBACK:
-		case OPTION_STRING:
-		case OPTION_INTEGER:
-		case OPTION_UINTEGER:
-		case OPTION_LONG:
-		case OPTION_U64:
-		default:
-			break;
-		}
-
-		if (!noarg)
-			err = get_arg(p, opt, flags, NULL);
-		if (err)
-			return err;
-
-		optwarning(opt, reason, flags);
-		return 0;
-	}
-
-	switch (opt->type) {
-	case OPTION_BIT:
-		if (unset)
-			*(int *)opt->value &= ~opt->defval;
-		else
-			*(int *)opt->value |= opt->defval;
-		return 0;
-
-	case OPTION_BOOLEAN:
-		*(bool *)opt->value = unset ? false : true;
-		if (opt->set)
-			*(bool *)opt->set = true;
-		return 0;
-
-	case OPTION_INCR:
-		*(int *)opt->value = unset ? 0 : *(int *)opt->value + 1;
-		return 0;
-
-	case OPTION_SET_UINT:
-		*(unsigned int *)opt->value = unset ? 0 : opt->defval;
-		return 0;
-
-	case OPTION_SET_PTR:
-		*(void **)opt->value = unset ? NULL : (void *)opt->defval;
-		return 0;
-
-	case OPTION_STRING:
-		err = 0;
-		if (unset)
-			*(const char **)opt->value = NULL;
-		else if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
-			*(const char **)opt->value = (const char *)opt->defval;
-		else
-			err = get_arg(p, opt, flags, (const char **)opt->value);
-
-		/* PARSE_OPT_NOEMPTY: Allow NULL but disallow empty string. */
-		if (opt->flags & PARSE_OPT_NOEMPTY) {
-			const char *val = *(const char **)opt->value;
-
-			if (!val)
-				return err;
-
-			/* Similar to unset if we are given an empty string. */
-			if (val[0] == '\0') {
-				*(const char **)opt->value = NULL;
-				return 0;
-			}
-		}
-
-		return err;
-
-	case OPTION_CALLBACK:
-		if (unset)
-			return (*opt->callback)(opt, NULL, 1) ? (-1) : 0;
-		if (opt->flags & PARSE_OPT_NOARG)
-			return (*opt->callback)(opt, NULL, 0) ? (-1) : 0;
-		if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
-			return (*opt->callback)(opt, NULL, 0) ? (-1) : 0;
-		if (get_arg(p, opt, flags, &arg))
-			return -1;
-		return (*opt->callback)(opt, arg, 0) ? (-1) : 0;
-
-	case OPTION_INTEGER:
-		if (unset) {
-			*(int *)opt->value = 0;
-			return 0;
-		}
-		if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
-			*(int *)opt->value = opt->defval;
-			return 0;
-		}
-		if (get_arg(p, opt, flags, &arg))
-			return -1;
-		*(int *)opt->value = strtol(arg, (char **)&s, 10);
-		if (*s)
-			return opterror(opt, "expects a numerical value", flags);
-		return 0;
-
-	case OPTION_UINTEGER:
-		if (unset) {
-			*(unsigned int *)opt->value = 0;
-			return 0;
-		}
-		if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
-			*(unsigned int *)opt->value = opt->defval;
-			return 0;
-		}
-		if (get_arg(p, opt, flags, &arg))
-			return -1;
-		*(unsigned int *)opt->value = strtol(arg, (char **)&s, 10);
-		if (*s)
-			return opterror(opt, "expects a numerical value", flags);
-		return 0;
-
-	case OPTION_LONG:
-		if (unset) {
-			*(long *)opt->value = 0;
-			return 0;
-		}
-		if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
-			*(long *)opt->value = opt->defval;
-			return 0;
-		}
-		if (get_arg(p, opt, flags, &arg))
-			return -1;
-		*(long *)opt->value = strtol(arg, (char **)&s, 10);
-		if (*s)
-			return opterror(opt, "expects a numerical value", flags);
-		return 0;
-
-	case OPTION_U64:
-		if (unset) {
-			*(u64 *)opt->value = 0;
-			return 0;
-		}
-		if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
-			*(u64 *)opt->value = opt->defval;
-			return 0;
-		}
-		if (get_arg(p, opt, flags, &arg))
-			return -1;
-		*(u64 *)opt->value = strtoull(arg, (char **)&s, 10);
-		if (*s)
-			return opterror(opt, "expects a numerical value", flags);
-		return 0;
-
-	case OPTION_END:
-	case OPTION_ARGUMENT:
-	case OPTION_GROUP:
-	default:
-		die("should not happen, someone must be hit on the forehead");
-	}
-}
-
-static int parse_short_opt(struct parse_opt_ctx_t *p, const struct option *options)
-{
-	for (; options->type != OPTION_END; options++) {
-		if (options->short_name == *p->opt) {
-			p->opt = p->opt[1] ? p->opt + 1 : NULL;
-			return get_value(p, options, OPT_SHORT);
-		}
-	}
-	return -2;
-}
-
-static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg,
-                          const struct option *options)
-{
-	const char *arg_end = strchr(arg, '=');
-	const struct option *abbrev_option = NULL, *ambiguous_option = NULL;
-	int abbrev_flags = 0, ambiguous_flags = 0;
-
-	if (!arg_end)
-		arg_end = arg + strlen(arg);
-
-	for (; options->type != OPTION_END; options++) {
-		const char *rest;
-		int flags = 0;
-
-		if (!options->long_name)
-			continue;
-
-		rest = skip_prefix(arg, options->long_name);
-		if (options->type == OPTION_ARGUMENT) {
-			if (!rest)
-				continue;
-			if (*rest == '=')
-				return opterror(options, "takes no value", flags);
-			if (*rest)
-				continue;
-			p->out[p->cpidx++] = arg - 2;
-			return 0;
-		}
-		if (!rest) {
-			if (!prefixcmp(options->long_name, "no-")) {
-				/*
-				 * The long name itself starts with "no-", so
-				 * accept the option without "no-" so that users
-				 * do not have to enter "no-no-" to get the
-				 * negation.
-				 */
-				rest = skip_prefix(arg, options->long_name + 3);
-				if (rest) {
-					flags |= OPT_UNSET;
-					goto match;
-				}
-				/* Abbreviated case */
-				if (!prefixcmp(options->long_name + 3, arg)) {
-					flags |= OPT_UNSET;
-					goto is_abbreviated;
-				}
-			}
-			/* abbreviated? */
-			if (!strncmp(options->long_name, arg, arg_end - arg)) {
-is_abbreviated:
-				if (abbrev_option) {
-					/*
-					 * If this is abbreviated, it is
-					 * ambiguous. So when there is no
-					 * exact match later, we need to
-					 * error out.
-					 */
-					ambiguous_option = abbrev_option;
-					ambiguous_flags = abbrev_flags;
-				}
-				if (!(flags & OPT_UNSET) && *arg_end)
-					p->opt = arg_end + 1;
-				abbrev_option = options;
-				abbrev_flags = flags;
-				continue;
-			}
-			/* negated and abbreviated very much? */
-			if (!prefixcmp("no-", arg)) {
-				flags |= OPT_UNSET;
-				goto is_abbreviated;
-			}
-			/* negated? */
-			if (strncmp(arg, "no-", 3))
-				continue;
-			flags |= OPT_UNSET;
-			rest = skip_prefix(arg + 3, options->long_name);
-			/* abbreviated and negated? */
-			if (!rest && !prefixcmp(options->long_name, arg + 3))
-				goto is_abbreviated;
-			if (!rest)
-				continue;
-		}
-match:
-		if (*rest) {
-			if (*rest != '=')
-				continue;
-			p->opt = rest + 1;
-		}
-		return get_value(p, options, flags);
-	}
-
-	if (ambiguous_option) {
-		 fprintf(stderr,
-			 " Error: Ambiguous option: %s (could be --%s%s or --%s%s)",
-			 arg,
-			 (ambiguous_flags & OPT_UNSET) ?  "no-" : "",
-			 ambiguous_option->long_name,
-			 (abbrev_flags & OPT_UNSET) ?  "no-" : "",
-			 abbrev_option->long_name);
-		 return -1;
-	}
-	if (abbrev_option)
-		return get_value(p, abbrev_option, abbrev_flags);
-	return -2;
-}
-
-static void check_typos(const char *arg, const struct option *options)
-{
-	if (strlen(arg) < 3)
-		return;
-
-	if (!prefixcmp(arg, "no-")) {
-		fprintf(stderr, " Error: did you mean `--%s` (with two dashes ?)", arg);
-		exit(129);
-	}
-
-	for (; options->type != OPTION_END; options++) {
-		if (!options->long_name)
-			continue;
-		if (!prefixcmp(options->long_name, arg)) {
-			fprintf(stderr, " Error: did you mean `--%s` (with two dashes ?)", arg);
-			exit(129);
-		}
-	}
-}
-
-static void parse_options_start(struct parse_opt_ctx_t *ctx,
-				int argc, const char **argv, int flags)
-{
-	memset(ctx, 0, sizeof(*ctx));
-	ctx->argc = argc - 1;
-	ctx->argv = argv + 1;
-	ctx->out  = argv;
-	ctx->cpidx = ((flags & PARSE_OPT_KEEP_ARGV0) != 0);
-	ctx->flags = flags;
-	if ((flags & PARSE_OPT_KEEP_UNKNOWN) &&
-	    (flags & PARSE_OPT_STOP_AT_NON_OPTION))
-		die("STOP_AT_NON_OPTION and KEEP_UNKNOWN don't go together");
-}
-
-static int usage_with_options_internal(const char * const *,
-				       const struct option *, int,
-				       struct parse_opt_ctx_t *);
-
-static int parse_options_step(struct parse_opt_ctx_t *ctx,
-			      const struct option *options,
-			      const char * const usagestr[])
-{
-	int internal_help = !(ctx->flags & PARSE_OPT_NO_INTERNAL_HELP);
-	int excl_short_opt = 1;
-	const char *arg;
-
-	/* we must reset ->opt, unknown short option leave it dangling */
-	ctx->opt = NULL;
-
-	for (; ctx->argc; ctx->argc--, ctx->argv++) {
-		arg = ctx->argv[0];
-		if (*arg != '-' || !arg[1]) {
-			if (ctx->flags & PARSE_OPT_STOP_AT_NON_OPTION)
-				break;
-			ctx->out[ctx->cpidx++] = ctx->argv[0];
-			continue;
-		}
-
-		if (arg[1] != '-') {
-			ctx->opt = ++arg;
-			if (internal_help && *ctx->opt == 'h') {
-				return usage_with_options_internal(usagestr, options, 0, ctx);
-			}
-			switch (parse_short_opt(ctx, options)) {
-			case -1:
-				return parse_options_usage(usagestr, options, arg, 1);
-			case -2:
-				goto unknown;
-			case -3:
-				goto exclusive;
-			default:
-				break;
-			}
-			if (ctx->opt)
-				check_typos(arg, options);
-			while (ctx->opt) {
-				if (internal_help && *ctx->opt == 'h')
-					return usage_with_options_internal(usagestr, options, 0, ctx);
-				arg = ctx->opt;
-				switch (parse_short_opt(ctx, options)) {
-				case -1:
-					return parse_options_usage(usagestr, options, arg, 1);
-				case -2:
-					/* fake a short option thing to hide the fact that we may have
-					 * started to parse aggregated stuff
-					 *
-					 * This is leaky, too bad.
-					 */
-					ctx->argv[0] = strdup(ctx->opt - 1);
-					*(char *)ctx->argv[0] = '-';
-					goto unknown;
-				case -3:
-					goto exclusive;
-				default:
-					break;
-				}
-			}
-			continue;
-		}
-
-		if (!arg[2]) { /* "--" */
-			if (!(ctx->flags & PARSE_OPT_KEEP_DASHDASH)) {
-				ctx->argc--;
-				ctx->argv++;
-			}
-			break;
-		}
-
-		arg += 2;
-		if (internal_help && !strcmp(arg, "help-all"))
-			return usage_with_options_internal(usagestr, options, 1, ctx);
-		if (internal_help && !strcmp(arg, "help"))
-			return usage_with_options_internal(usagestr, options, 0, ctx);
-		if (!strcmp(arg, "list-opts"))
-			return PARSE_OPT_LIST_OPTS;
-		if (!strcmp(arg, "list-cmds"))
-			return PARSE_OPT_LIST_SUBCMDS;
-		switch (parse_long_opt(ctx, arg, options)) {
-		case -1:
-			return parse_options_usage(usagestr, options, arg, 0);
-		case -2:
-			goto unknown;
-		case -3:
-			excl_short_opt = 0;
-			goto exclusive;
-		default:
-			break;
-		}
-		continue;
-unknown:
-		if (!(ctx->flags & PARSE_OPT_KEEP_UNKNOWN))
-			return PARSE_OPT_UNKNOWN;
-		ctx->out[ctx->cpidx++] = ctx->argv[0];
-		ctx->opt = NULL;
-	}
-	return PARSE_OPT_DONE;
-
-exclusive:
-	parse_options_usage(usagestr, options, arg, excl_short_opt);
-	if ((excl_short_opt && ctx->excl_opt->short_name) ||
-	    ctx->excl_opt->long_name == NULL) {
-		char opt = ctx->excl_opt->short_name;
-		parse_options_usage(NULL, options, &opt, 1);
-	} else {
-		parse_options_usage(NULL, options, ctx->excl_opt->long_name, 0);
-	}
-	return PARSE_OPT_HELP;
-}
-
-static int parse_options_end(struct parse_opt_ctx_t *ctx)
-{
-	memmove(ctx->out + ctx->cpidx, ctx->argv, ctx->argc * sizeof(*ctx->out));
-	ctx->out[ctx->cpidx + ctx->argc] = NULL;
-	return ctx->cpidx + ctx->argc;
-}
-
-int parse_options_subcommand(int argc, const char **argv, const struct option *options,
-			const char *const subcommands[], const char *usagestr[], int flags)
-{
-	struct parse_opt_ctx_t ctx;
-
-	/* build usage string if it's not provided */
-	if (subcommands && !usagestr[0]) {
-		char *buf = NULL;
-
-		astrcatf(&buf, "%s %s [<options>] {", subcmd_config.exec_name, argv[0]);
-
-		for (int i = 0; subcommands[i]; i++) {
-			if (i)
-				astrcat(&buf, "|");
-			astrcat(&buf, subcommands[i]);
-		}
-		astrcat(&buf, "}");
-
-		usagestr[0] = buf;
-	}
-
-	parse_options_start(&ctx, argc, argv, flags);
-	switch (parse_options_step(&ctx, options, usagestr)) {
-	case PARSE_OPT_HELP:
-		exit(129);
-	case PARSE_OPT_DONE:
-		break;
-	case PARSE_OPT_LIST_OPTS:
-		while (options->type != OPTION_END) {
-			if (options->long_name)
-				printf("--%s ", options->long_name);
-			options++;
-		}
-		putchar('\n');
-		exit(130);
-	case PARSE_OPT_LIST_SUBCMDS:
-		if (subcommands) {
-			for (int i = 0; subcommands[i]; i++)
-				printf("%s ", subcommands[i]);
-		}
-		putchar('\n');
-		exit(130);
-	default: /* PARSE_OPT_UNKNOWN */
-		if (ctx.argv[0][1] == '-')
-			astrcatf(&error_buf, "unknown option `%s'",
-				 ctx.argv[0] + 2);
-		else
-			astrcatf(&error_buf, "unknown switch `%c'", *ctx.opt);
-		usage_with_options(usagestr, options);
-	}
-
-	return parse_options_end(&ctx);
-}
-
-int parse_options(int argc, const char **argv, const struct option *options,
-		  const char * const usagestr[], int flags)
-{
-	return parse_options_subcommand(argc, argv, options, NULL,
-					(const char **) usagestr, flags);
-}
-
-#define USAGE_OPTS_WIDTH 24
-#define USAGE_GAP         2
-
-static void print_option_help(const struct option *opts, int full)
-{
-	size_t pos;
-	int pad;
-
-	if (opts->type == OPTION_GROUP) {
-		fputc('\n', stderr);
-		if (*opts->help)
-			fprintf(stderr, "%s\n", opts->help);
-		return;
-	}
-	if (!full && (opts->flags & PARSE_OPT_HIDDEN))
-		return;
-	if (opts->flags & PARSE_OPT_DISABLED)
-		return;
-
-	pos = fprintf(stderr, "    ");
-	if (opts->short_name)
-		pos += fprintf(stderr, "-%c", opts->short_name);
-	else
-		pos += fprintf(stderr, "    ");
-
-	if (opts->long_name && opts->short_name)
-		pos += fprintf(stderr, ", ");
-	if (opts->long_name)
-		pos += fprintf(stderr, "--%s", opts->long_name);
-
-	switch (opts->type) {
-	case OPTION_ARGUMENT:
-		break;
-	case OPTION_LONG:
-	case OPTION_U64:
-	case OPTION_INTEGER:
-	case OPTION_UINTEGER:
-		if (opts->flags & PARSE_OPT_OPTARG)
-			if (opts->long_name)
-				pos += fprintf(stderr, "[=<n>]");
-			else
-				pos += fprintf(stderr, "[<n>]");
-		else
-			pos += fprintf(stderr, " <n>");
-		break;
-	case OPTION_CALLBACK:
-		if (opts->flags & PARSE_OPT_NOARG)
-			break;
-		/* FALLTHROUGH */
-	case OPTION_STRING:
-		if (opts->argh) {
-			if (opts->flags & PARSE_OPT_OPTARG)
-				if (opts->long_name)
-					pos += fprintf(stderr, "[=<%s>]", opts->argh);
-				else
-					pos += fprintf(stderr, "[<%s>]", opts->argh);
-			else
-				pos += fprintf(stderr, " <%s>", opts->argh);
-		} else {
-			if (opts->flags & PARSE_OPT_OPTARG)
-				if (opts->long_name)
-					pos += fprintf(stderr, "[=...]");
-				else
-					pos += fprintf(stderr, "[...]");
-			else
-				pos += fprintf(stderr, " ...");
-		}
-		break;
-	default: /* OPTION_{BIT,BOOLEAN,SET_UINT,SET_PTR} */
-	case OPTION_END:
-	case OPTION_GROUP:
-	case OPTION_BIT:
-	case OPTION_BOOLEAN:
-	case OPTION_INCR:
-	case OPTION_SET_UINT:
-	case OPTION_SET_PTR:
-		break;
-	}
-
-	if (pos <= USAGE_OPTS_WIDTH)
-		pad = USAGE_OPTS_WIDTH - pos;
-	else {
-		fputc('\n', stderr);
-		pad = USAGE_OPTS_WIDTH;
-	}
-	fprintf(stderr, "%*s%s\n", pad + USAGE_GAP, "", opts->help);
-	if (opts->flags & PARSE_OPT_NOBUILD)
-		fprintf(stderr, "%*s(not built-in because %s)\n",
-			USAGE_OPTS_WIDTH + USAGE_GAP, "",
-			opts->build_opt);
-}
-
-static int option__cmp(const void *va, const void *vb)
-{
-	const struct option *a = va, *b = vb;
-	int sa = tolower(a->short_name), sb = tolower(b->short_name), ret;
-
-	if (sa == 0)
-		sa = 'z' + 1;
-	if (sb == 0)
-		sb = 'z' + 1;
-
-	ret = sa - sb;
-
-	if (ret == 0) {
-		const char *la = a->long_name ?: "",
-			   *lb = b->long_name ?: "";
-		ret = strcmp(la, lb);
-	}
-
-	return ret;
-}
-
-static struct option *options__order(const struct option *opts)
-{
-	int nr_opts = 0, len;
-	const struct option *o = opts;
-	struct option *ordered;
-
-	for (o = opts; o->type != OPTION_END; o++)
-		++nr_opts;
-
-	len = sizeof(*o) * (nr_opts + 1);
-	ordered = malloc(len);
-	if (!ordered)
-		goto out;
-	memcpy(ordered, opts, len);
-
-	qsort(ordered, nr_opts, sizeof(*o), option__cmp);
-out:
-	return ordered;
-}
-
-static bool option__in_argv(const struct option *opt, const struct parse_opt_ctx_t *ctx)
-{
-	int i;
-
-	for (i = 1; i < ctx->argc; ++i) {
-		const char *arg = ctx->argv[i];
-
-		if (arg[0] != '-') {
-			if (arg[1] == '\0') {
-				if (arg[0] == opt->short_name)
-					return true;
-				continue;
-			}
-
-			if (opt->long_name && strcmp(opt->long_name, arg) == 0)
-				return true;
-
-			if (opt->help && strcasestr(opt->help, arg) != NULL)
-				return true;
-
-			continue;
-		}
-
-		if (arg[1] == opt->short_name ||
-		    (arg[1] == '-' && opt->long_name && strcmp(opt->long_name, arg + 2) == 0))
-			return true;
-	}
-
-	return false;
-}
-
-static int usage_with_options_internal(const char * const *usagestr,
-				       const struct option *opts, int full,
-				       struct parse_opt_ctx_t *ctx)
-{
-	struct option *ordered;
-
-	if (!usagestr)
-		return PARSE_OPT_HELP;
-
-	setup_pager();
-
-	if (error_buf) {
-		fprintf(stderr, "  Error: %s\n", error_buf);
-		zfree(&error_buf);
-	}
-
-	fprintf(stderr, "\n Usage: %s\n", *usagestr++);
-	while (*usagestr && **usagestr)
-		fprintf(stderr, "    or: %s\n", *usagestr++);
-	while (*usagestr) {
-		fprintf(stderr, "%s%s\n",
-				**usagestr ? "    " : "",
-				*usagestr);
-		usagestr++;
-	}
-
-	if (opts->type != OPTION_GROUP)
-		fputc('\n', stderr);
-
-	ordered = options__order(opts);
-	if (ordered)
-		opts = ordered;
-
-	for (  ; opts->type != OPTION_END; opts++) {
-		if (ctx && ctx->argc > 1 && !option__in_argv(opts, ctx))
-			continue;
-		print_option_help(opts, full);
-	}
-
-	fputc('\n', stderr);
-
-	free(ordered);
-
-	return PARSE_OPT_HELP;
-}
-
-void usage_with_options(const char * const *usagestr,
-			const struct option *opts)
-{
-	usage_with_options_internal(usagestr, opts, 0, NULL);
-	exit(129);
-}
-
-void usage_with_options_msg(const char * const *usagestr,
-			    const struct option *opts, const char *fmt, ...)
-{
-	va_list ap;
-	char *tmp = error_buf;
-
-	va_start(ap, fmt);
-	if (vasprintf(&error_buf, fmt, ap) == -1)
-		die("vasprintf failed");
-	va_end(ap);
-
-	free(tmp);
-
-	usage_with_options_internal(usagestr, opts, 0, NULL);
-	exit(129);
-}
-
-int parse_options_usage(const char * const *usagestr,
-			const struct option *opts,
-			const char *optstr, bool short_opt)
-{
-	if (!usagestr)
-		goto opt;
-
-	fprintf(stderr, "\n Usage: %s\n", *usagestr++);
-	while (*usagestr && **usagestr)
-		fprintf(stderr, "    or: %s\n", *usagestr++);
-	while (*usagestr) {
-		fprintf(stderr, "%s%s\n",
-				**usagestr ? "    " : "",
-				*usagestr);
-		usagestr++;
-	}
-	fputc('\n', stderr);
-
-opt:
-	for (  ; opts->type != OPTION_END; opts++) {
-		if (short_opt) {
-			if (opts->short_name == *optstr) {
-				print_option_help(opts, 0);
-				break;
-			}
-			continue;
-		}
-
-		if (opts->long_name == NULL)
-			continue;
-
-		if (!prefixcmp(opts->long_name, optstr))
-			print_option_help(opts, 0);
-		if (!prefixcmp("no-", optstr) &&
-		    !prefixcmp(opts->long_name, optstr + 3))
-			print_option_help(opts, 0);
-	}
-
-	return PARSE_OPT_HELP;
-}
-
-
-int parse_opt_verbosity_cb(const struct option *opt,
-			   const char *arg __maybe_unused,
-			   int unset)
-{
-	int *target = opt->value;
-
-	if (unset)
-		/* --no-quiet, --no-verbose */
-		*target = 0;
-	else if (opt->short_name == 'v') {
-		if (*target >= 0)
-			(*target)++;
-		else
-			*target = 1;
-	} else {
-		if (*target <= 0)
-			(*target)--;
-		else
-			*target = -1;
-	}
-	return 0;
-}
-
-static struct option *
-find_option(struct option *opts, int shortopt, const char *longopt)
-{
-	for (; opts->type != OPTION_END; opts++) {
-		if ((shortopt && opts->short_name == shortopt) ||
-		    (opts->long_name && longopt &&
-		     !strcmp(opts->long_name, longopt)))
-			return opts;
-	}
-	return NULL;
-}
-
-void set_option_flag(struct option *opts, int shortopt, const char *longopt,
-		     int flag)
-{
-	struct option *opt = find_option(opts, shortopt, longopt);
-
-	if (opt)
-		opt->flags |= flag;
-	return;
-}
-
-void set_option_nobuild(struct option *opts, int shortopt,
-			const char *longopt,
-			const char *build_opt,
-			bool can_skip)
-{
-	struct option *opt = find_option(opts, shortopt, longopt);
-
-	if (!opt)
-		return;
-
-	opt->flags |= PARSE_OPT_NOBUILD;
-	opt->flags |= can_skip ? PARSE_OPT_CANSKIP : 0;
-	opt->build_opt = build_opt;
-}
diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h
deleted file mode 100644
index dec893f10477..000000000000
--- a/tools/perf/util/parse-options.h
+++ /dev/null
@@ -1,228 +0,0 @@
-#ifndef __PERF_PARSE_OPTIONS_H
-#define __PERF_PARSE_OPTIONS_H
-
-#include <stdbool.h>
-#include <stdint.h>
-
-enum parse_opt_type {
-	/* special types */
-	OPTION_END,
-	OPTION_ARGUMENT,
-	OPTION_GROUP,
-	/* options with no arguments */
-	OPTION_BIT,
-	OPTION_BOOLEAN,
-	OPTION_INCR,
-	OPTION_SET_UINT,
-	OPTION_SET_PTR,
-	/* options with arguments (usually) */
-	OPTION_STRING,
-	OPTION_INTEGER,
-	OPTION_LONG,
-	OPTION_CALLBACK,
-	OPTION_U64,
-	OPTION_UINTEGER,
-};
-
-enum parse_opt_flags {
-	PARSE_OPT_KEEP_DASHDASH = 1,
-	PARSE_OPT_STOP_AT_NON_OPTION = 2,
-	PARSE_OPT_KEEP_ARGV0 = 4,
-	PARSE_OPT_KEEP_UNKNOWN = 8,
-	PARSE_OPT_NO_INTERNAL_HELP = 16,
-};
-
-enum parse_opt_option_flags {
-	PARSE_OPT_OPTARG  = 1,
-	PARSE_OPT_NOARG   = 2,
-	PARSE_OPT_NONEG   = 4,
-	PARSE_OPT_HIDDEN  = 8,
-	PARSE_OPT_LASTARG_DEFAULT = 16,
-	PARSE_OPT_DISABLED = 32,
-	PARSE_OPT_EXCLUSIVE = 64,
-	PARSE_OPT_NOEMPTY  = 128,
-	PARSE_OPT_NOBUILD  = 256,
-	PARSE_OPT_CANSKIP  = 512,
-};
-
-struct option;
-typedef int parse_opt_cb(const struct option *, const char *arg, int unset);
-
-/*
- * `type`::
- *   holds the type of the option, you must have an OPTION_END last in your
- *   array.
- *
- * `short_name`::
- *   the character to use as a short option name, '\0' if none.
- *
- * `long_name`::
- *   the long option name, without the leading dashes, NULL if none.
- *
- * `value`::
- *   stores pointers to the values to be filled.
- *
- * `argh`::
- *   token to explain the kind of argument this option wants. Keep it
- *   homogenous across the repository.
- *
- * `help`::
- *   the short help associated to what the option does.
- *   Must never be NULL (except for OPTION_END).
- *   OPTION_GROUP uses this pointer to store the group header.
- *
- * `flags`::
- *   mask of parse_opt_option_flags.
- *   PARSE_OPT_OPTARG: says that the argument is optionnal (not for BOOLEANs)
- *   PARSE_OPT_NOARG: says that this option takes no argument, for CALLBACKs
- *   PARSE_OPT_NONEG: says that this option cannot be negated
- *   PARSE_OPT_HIDDEN this option is skipped in the default usage, showed in
- *                    the long one.
- *
- * `callback`::
- *   pointer to the callback to use for OPTION_CALLBACK.
- *
- * `defval`::
- *   default value to fill (*->value) with for PARSE_OPT_OPTARG.
- *   OPTION_{BIT,SET_UINT,SET_PTR} store the {mask,integer,pointer} to put in
- *   the value when met.
- *   CALLBACKS can use it like they want.
- *
- * `set`::
- *   whether an option was set by the user
- */
-struct option {
-	enum parse_opt_type type;
-	int short_name;
-	const char *long_name;
-	void *value;
-	const char *argh;
-	const char *help;
-	const char *build_opt;
-
-	int flags;
-	parse_opt_cb *callback;
-	intptr_t defval;
-	bool *set;
-	void *data;
-};
-
-#define check_vtype(v, type) ( BUILD_BUG_ON_ZERO(!__builtin_types_compatible_p(typeof(v), type)) + v )
-
-#define OPT_END()                   { .type = OPTION_END }
-#define OPT_ARGUMENT(l, h)          { .type = OPTION_ARGUMENT, .long_name = (l), .help = (h) }
-#define OPT_GROUP(h)                { .type = OPTION_GROUP, .help = (h) }
-#define OPT_BIT(s, l, v, h, b)      { .type = OPTION_BIT, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h), .defval = (b) }
-#define OPT_BOOLEAN(s, l, v, h)     { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), .value = check_vtype(v, bool *), .help = (h) }
-#define OPT_BOOLEAN_FLAG(s, l, v, h, f)     { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), .value = check_vtype(v, bool *), .help = (h), .flags = (f) }
-#define OPT_BOOLEAN_SET(s, l, v, os, h) \
-	{ .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), \
-	.value = check_vtype(v, bool *), .help = (h), \
-	.set = check_vtype(os, bool *)}
-#define OPT_INCR(s, l, v, h)        { .type = OPTION_INCR, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h) }
-#define OPT_SET_UINT(s, l, v, h, i)  { .type = OPTION_SET_UINT, .short_name = (s), .long_name = (l), .value = check_vtype(v, unsigned int *), .help = (h), .defval = (i) }
-#define OPT_SET_PTR(s, l, v, h, p)  { .type = OPTION_SET_PTR, .short_name = (s), .long_name = (l), .value = (v), .help = (h), .defval = (p) }
-#define OPT_INTEGER(s, l, v, h)     { .type = OPTION_INTEGER, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h) }
-#define OPT_UINTEGER(s, l, v, h)    { .type = OPTION_UINTEGER, .short_name = (s), .long_name = (l), .value = check_vtype(v, unsigned int *), .help = (h) }
-#define OPT_LONG(s, l, v, h)        { .type = OPTION_LONG, .short_name = (s), .long_name = (l), .value = check_vtype(v, long *), .help = (h) }
-#define OPT_U64(s, l, v, h)         { .type = OPTION_U64, .short_name = (s), .long_name = (l), .value = check_vtype(v, u64 *), .help = (h) }
-#define OPT_STRING(s, l, v, a, h)   { .type = OPTION_STRING,  .short_name = (s), .long_name = (l), .value = check_vtype(v, const char **), (a), .help = (h) }
-#define OPT_STRING_OPTARG(s, l, v, a, h, d) \
-	{ .type = OPTION_STRING,  .short_name = (s), .long_name = (l), \
-	  .value = check_vtype(v, const char **), (a), .help = (h), \
-	  .flags = PARSE_OPT_OPTARG, .defval = (intptr_t)(d) }
-#define OPT_STRING_NOEMPTY(s, l, v, a, h)   { .type = OPTION_STRING,  .short_name = (s), .long_name = (l), .value = check_vtype(v, const char **), (a), .help = (h), .flags = PARSE_OPT_NOEMPTY}
-#define OPT_DATE(s, l, v, h) \
-	{ .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = "time", .help = (h), .callback = parse_opt_approxidate_cb }
-#define OPT_CALLBACK(s, l, v, a, h, f) \
-	{ .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h), .callback = (f) }
-#define OPT_CALLBACK_NOOPT(s, l, v, a, h, f) \
-	{ .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h), .callback = (f), .flags = PARSE_OPT_NOARG }
-#define OPT_CALLBACK_DEFAULT(s, l, v, a, h, f, d) \
-	{ .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h), .callback = (f), .defval = (intptr_t)d, .flags = PARSE_OPT_LASTARG_DEFAULT }
-#define OPT_CALLBACK_DEFAULT_NOOPT(s, l, v, a, h, f, d) \
-	{ .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l),\
-	.value = (v), (a), .help = (h), .callback = (f), .defval = (intptr_t)d,\
-	.flags = PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NOARG}
-#define OPT_CALLBACK_OPTARG(s, l, v, d, a, h, f) \
-	{ .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), \
-	  .value = (v), (a), .help = (h), .callback = (f), \
-	  .flags = PARSE_OPT_OPTARG, .data = (d) }
-
-/* parse_options() will filter out the processed options and leave the
- * non-option argments in argv[].
- * Returns the number of arguments left in argv[].
- *
- * NOTE: parse_options() and parse_options_subcommand() may call exit() in the
- * case of an error (or for 'special' options like --list-cmds or --list-opts).
- */
-extern int parse_options(int argc, const char **argv,
-                         const struct option *options,
-                         const char * const usagestr[], int flags);
-
-extern int parse_options_subcommand(int argc, const char **argv,
-				const struct option *options,
-				const char *const subcommands[],
-				const char *usagestr[], int flags);
-
-extern NORETURN void usage_with_options(const char * const *usagestr,
-                                        const struct option *options);
-extern NORETURN __attribute__((format(printf,3,4)))
-void usage_with_options_msg(const char * const *usagestr,
-			    const struct option *options,
-			    const char *fmt, ...);
-
-/*----- incremantal advanced APIs -----*/
-
-enum {
-	PARSE_OPT_HELP = -1,
-	PARSE_OPT_DONE,
-	PARSE_OPT_LIST_OPTS,
-	PARSE_OPT_LIST_SUBCMDS,
-	PARSE_OPT_UNKNOWN,
-};
-
-/*
- * It's okay for the caller to consume argv/argc in the usual way.
- * Other fields of that structure are private to parse-options and should not
- * be modified in any way.
- */
-struct parse_opt_ctx_t {
-	const char **argv;
-	const char **out;
-	int argc, cpidx;
-	const char *opt;
-	const struct option *excl_opt;
-	int flags;
-};
-
-extern int parse_options_usage(const char * const *usagestr,
-			       const struct option *opts,
-			       const char *optstr,
-			       bool short_opt);
-
-
-/*----- some often used options -----*/
-extern int parse_opt_abbrev_cb(const struct option *, const char *, int);
-extern int parse_opt_approxidate_cb(const struct option *, const char *, int);
-extern int parse_opt_verbosity_cb(const struct option *, const char *, int);
-
-#define OPT__VERBOSE(var)  OPT_BOOLEAN('v', "verbose", (var), "be verbose")
-#define OPT__QUIET(var)    OPT_BOOLEAN('q', "quiet",   (var), "be quiet")
-#define OPT__VERBOSITY(var) \
-	{ OPTION_CALLBACK, 'v', "verbose", (var), NULL, "be more verbose", \
-	  PARSE_OPT_NOARG, &parse_opt_verbosity_cb, 0 }, \
-	{ OPTION_CALLBACK, 'q', "quiet", (var), NULL, "be more quiet", \
-	  PARSE_OPT_NOARG, &parse_opt_verbosity_cb, 0 }
-#define OPT__DRY_RUN(var)  OPT_BOOLEAN('n', "dry-run", (var), "dry run")
-#define OPT__ABBREV(var)  \
-	{ OPTION_CALLBACK, 0, "abbrev", (var), "n", \
-	  "use <n> digits to display SHA-1s", \
-	  PARSE_OPT_OPTARG, &parse_opt_abbrev_cb, 0 }
-
-extern const char *parse_options_fix_filename(const char *prefix, const char *file);
-
-void set_option_flag(struct option *opts, int sopt, const char *lopt, int flag);
-void set_option_nobuild(struct option *opts, int shortopt, const char *longopt,
-			const char *build_opt, bool can_skip);
-#endif /* __PERF_PARSE_OPTIONS_H */
diff --git a/tools/perf/util/parse-regs-options.c b/tools/perf/util/parse-regs-options.c
index 4f2c1c255d81..646ecf736aad 100644
--- a/tools/perf/util/parse-regs-options.c
+++ b/tools/perf/util/parse-regs-options.c
@@ -1,7 +1,7 @@
 #include "perf.h"
 #include "util/util.h"
 #include "util/debug.h"
-#include "util/parse-options.h"
+#include <subcmd/parse-options.h>
 #include "util/parse-regs-options.h"
 
 int
diff --git a/tools/perf/util/run-command.c b/tools/perf/util/run-command.c
deleted file mode 100644
index fed37d6ae070..000000000000
--- a/tools/perf/util/run-command.c
+++ /dev/null
@@ -1,227 +0,0 @@
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/wait.h>
-#include "subcmd-util.h"
-#include "run-command.h"
-#include "exec_cmd.h"
-
-#define STRERR_BUFSIZE 128
-
-static inline void close_pair(int fd[2])
-{
-	close(fd[0]);
-	close(fd[1]);
-}
-
-static inline void dup_devnull(int to)
-{
-	int fd = open("/dev/null", O_RDWR);
-	dup2(fd, to);
-	close(fd);
-}
-
-int start_command(struct child_process *cmd)
-{
-	int need_in, need_out, need_err;
-	int fdin[2], fdout[2], fderr[2];
-	char sbuf[STRERR_BUFSIZE];
-
-	/*
-	 * In case of errors we must keep the promise to close FDs
-	 * that have been passed in via ->in and ->out.
-	 */
-
-	need_in = !cmd->no_stdin && cmd->in < 0;
-	if (need_in) {
-		if (pipe(fdin) < 0) {
-			if (cmd->out > 0)
-				close(cmd->out);
-			return -ERR_RUN_COMMAND_PIPE;
-		}
-		cmd->in = fdin[1];
-	}
-
-	need_out = !cmd->no_stdout
-		&& !cmd->stdout_to_stderr
-		&& cmd->out < 0;
-	if (need_out) {
-		if (pipe(fdout) < 0) {
-			if (need_in)
-				close_pair(fdin);
-			else if (cmd->in)
-				close(cmd->in);
-			return -ERR_RUN_COMMAND_PIPE;
-		}
-		cmd->out = fdout[0];
-	}
-
-	need_err = !cmd->no_stderr && cmd->err < 0;
-	if (need_err) {
-		if (pipe(fderr) < 0) {
-			if (need_in)
-				close_pair(fdin);
-			else if (cmd->in)
-				close(cmd->in);
-			if (need_out)
-				close_pair(fdout);
-			else if (cmd->out)
-				close(cmd->out);
-			return -ERR_RUN_COMMAND_PIPE;
-		}
-		cmd->err = fderr[0];
-	}
-
-	fflush(NULL);
-	cmd->pid = fork();
-	if (!cmd->pid) {
-		if (cmd->no_stdin)
-			dup_devnull(0);
-		else if (need_in) {
-			dup2(fdin[0], 0);
-			close_pair(fdin);
-		} else if (cmd->in) {
-			dup2(cmd->in, 0);
-			close(cmd->in);
-		}
-
-		if (cmd->no_stderr)
-			dup_devnull(2);
-		else if (need_err) {
-			dup2(fderr[1], 2);
-			close_pair(fderr);
-		}
-
-		if (cmd->no_stdout)
-			dup_devnull(1);
-		else if (cmd->stdout_to_stderr)
-			dup2(2, 1);
-		else if (need_out) {
-			dup2(fdout[1], 1);
-			close_pair(fdout);
-		} else if (cmd->out > 1) {
-			dup2(cmd->out, 1);
-			close(cmd->out);
-		}
-
-		if (cmd->dir && chdir(cmd->dir))
-			die("exec %s: cd to %s failed (%s)", cmd->argv[0],
-			    cmd->dir, strerror_r(errno, sbuf, sizeof(sbuf)));
-		if (cmd->env) {
-			for (; *cmd->env; cmd->env++) {
-				if (strchr(*cmd->env, '='))
-					putenv((char*)*cmd->env);
-				else
-					unsetenv(*cmd->env);
-			}
-		}
-		if (cmd->preexec_cb)
-			cmd->preexec_cb();
-		if (cmd->exec_cmd) {
-			execv_cmd(cmd->argv);
-		} else {
-			execvp(cmd->argv[0], (char *const*) cmd->argv);
-		}
-		exit(127);
-	}
-
-	if (cmd->pid < 0) {
-		int err = errno;
-		if (need_in)
-			close_pair(fdin);
-		else if (cmd->in)
-			close(cmd->in);
-		if (need_out)
-			close_pair(fdout);
-		else if (cmd->out)
-			close(cmd->out);
-		if (need_err)
-			close_pair(fderr);
-		return err == ENOENT ?
-			-ERR_RUN_COMMAND_EXEC :
-			-ERR_RUN_COMMAND_FORK;
-	}
-
-	if (need_in)
-		close(fdin[0]);
-	else if (cmd->in)
-		close(cmd->in);
-
-	if (need_out)
-		close(fdout[1]);
-	else if (cmd->out)
-		close(cmd->out);
-
-	if (need_err)
-		close(fderr[1]);
-
-	return 0;
-}
-
-static int wait_or_whine(pid_t pid)
-{
-	char sbuf[STRERR_BUFSIZE];
-
-	for (;;) {
-		int status, code;
-		pid_t waiting = waitpid(pid, &status, 0);
-
-		if (waiting < 0) {
-			if (errno == EINTR)
-				continue;
-			fprintf(stderr, " Error: waitpid failed (%s)",
-				strerror_r(errno, sbuf, sizeof(sbuf)));
-			return -ERR_RUN_COMMAND_WAITPID;
-		}
-		if (waiting != pid)
-			return -ERR_RUN_COMMAND_WAITPID_WRONG_PID;
-		if (WIFSIGNALED(status))
-			return -ERR_RUN_COMMAND_WAITPID_SIGNAL;
-
-		if (!WIFEXITED(status))
-			return -ERR_RUN_COMMAND_WAITPID_NOEXIT;
-		code = WEXITSTATUS(status);
-		switch (code) {
-		case 127:
-			return -ERR_RUN_COMMAND_EXEC;
-		case 0:
-			return 0;
-		default:
-			return -code;
-		}
-	}
-}
-
-int finish_command(struct child_process *cmd)
-{
-	return wait_or_whine(cmd->pid);
-}
-
-int run_command(struct child_process *cmd)
-{
-	int code = start_command(cmd);
-	if (code)
-		return code;
-	return finish_command(cmd);
-}
-
-static void prepare_run_command_v_opt(struct child_process *cmd,
-				      const char **argv,
-				      int opt)
-{
-	memset(cmd, 0, sizeof(*cmd));
-	cmd->argv = argv;
-	cmd->no_stdin = opt & RUN_COMMAND_NO_STDIN ? 1 : 0;
-	cmd->exec_cmd = opt & RUN_EXEC_CMD ? 1 : 0;
-	cmd->stdout_to_stderr = opt & RUN_COMMAND_STDOUT_TO_STDERR ? 1 : 0;
-}
-
-int run_command_v_opt(const char **argv, int opt)
-{
-	struct child_process cmd;
-	prepare_run_command_v_opt(&cmd, argv, opt);
-	return run_command(&cmd);
-}
diff --git a/tools/perf/util/run-command.h b/tools/perf/util/run-command.h
deleted file mode 100644
index 4a55393a6547..000000000000
--- a/tools/perf/util/run-command.h
+++ /dev/null
@@ -1,60 +0,0 @@
-#ifndef __PERF_RUN_COMMAND_H
-#define __PERF_RUN_COMMAND_H
-
-#include <unistd.h>
-
-enum {
-	ERR_RUN_COMMAND_FORK = 10000,
-	ERR_RUN_COMMAND_EXEC,
-	ERR_RUN_COMMAND_PIPE,
-	ERR_RUN_COMMAND_WAITPID,
-	ERR_RUN_COMMAND_WAITPID_WRONG_PID,
-	ERR_RUN_COMMAND_WAITPID_SIGNAL,
-	ERR_RUN_COMMAND_WAITPID_NOEXIT,
-};
-#define IS_RUN_COMMAND_ERR(x) (-(x) >= ERR_RUN_COMMAND_FORK)
-
-struct child_process {
-	const char **argv;
-	pid_t pid;
-	/*
-	 * Using .in, .out, .err:
-	 * - Specify 0 for no redirections (child inherits stdin, stdout,
-	 *   stderr from parent).
-	 * - Specify -1 to have a pipe allocated as follows:
-	 *     .in: returns the writable pipe end; parent writes to it,
-	 *          the readable pipe end becomes child's stdin
-	 *     .out, .err: returns the readable pipe end; parent reads from
-	 *          it, the writable pipe end becomes child's stdout/stderr
-	 *   The caller of start_command() must close the returned FDs
-	 *   after it has completed reading from/writing to it!
-	 * - Specify > 0 to set a channel to a particular FD as follows:
-	 *     .in: a readable FD, becomes child's stdin
-	 *     .out: a writable FD, becomes child's stdout/stderr
-	 *     .err > 0 not supported
-	 *   The specified FD is closed by start_command(), even in case
-	 *   of errors!
-	 */
-	int in;
-	int out;
-	int err;
-	const char *dir;
-	const char *const *env;
-	unsigned no_stdin:1;
-	unsigned no_stdout:1;
-	unsigned no_stderr:1;
-	unsigned exec_cmd:1; /* if this is to be external sub-command */
-	unsigned stdout_to_stderr:1;
-	void (*preexec_cb)(void);
-};
-
-int start_command(struct child_process *);
-int finish_command(struct child_process *);
-int run_command(struct child_process *);
-
-#define RUN_COMMAND_NO_STDIN 1
-#define RUN_EXEC_CMD	     2	/*If this is to be external sub-command */
-#define RUN_COMMAND_STDOUT_TO_STDERR 4
-int run_command_v_opt(const char **argv, int opt);
-
-#endif /* __PERF_RUN_COMMAND_H */
diff --git a/tools/perf/util/sigchain.c b/tools/perf/util/sigchain.c
deleted file mode 100644
index 3537c348a18e..000000000000
--- a/tools/perf/util/sigchain.c
+++ /dev/null
@@ -1,53 +0,0 @@
-#include <signal.h>
-#include "subcmd-util.h"
-#include "sigchain.h"
-
-#define SIGCHAIN_MAX_SIGNALS 32
-
-struct sigchain_signal {
-	sigchain_fun *old;
-	int n;
-	int alloc;
-};
-static struct sigchain_signal signals[SIGCHAIN_MAX_SIGNALS];
-
-static void check_signum(int sig)
-{
-	if (sig < 1 || sig >= SIGCHAIN_MAX_SIGNALS)
-		die("BUG: signal out of range: %d", sig);
-}
-
-static int sigchain_push(int sig, sigchain_fun f)
-{
-	struct sigchain_signal *s = signals + sig;
-	check_signum(sig);
-
-	ALLOC_GROW(s->old, s->n + 1, s->alloc);
-	s->old[s->n] = signal(sig, f);
-	if (s->old[s->n] == SIG_ERR)
-		return -1;
-	s->n++;
-	return 0;
-}
-
-int sigchain_pop(int sig)
-{
-	struct sigchain_signal *s = signals + sig;
-	check_signum(sig);
-	if (s->n < 1)
-		return 0;
-
-	if (signal(sig, s->old[s->n - 1]) == SIG_ERR)
-		return -1;
-	s->n--;
-	return 0;
-}
-
-void sigchain_push_common(sigchain_fun f)
-{
-	sigchain_push(SIGINT, f);
-	sigchain_push(SIGHUP, f);
-	sigchain_push(SIGTERM, f);
-	sigchain_push(SIGQUIT, f);
-	sigchain_push(SIGPIPE, f);
-}
diff --git a/tools/perf/util/sigchain.h b/tools/perf/util/sigchain.h
deleted file mode 100644
index 959d64eb5557..000000000000
--- a/tools/perf/util/sigchain.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef __PERF_SIGCHAIN_H
-#define __PERF_SIGCHAIN_H
-
-typedef void (*sigchain_fun)(int);
-
-int sigchain_pop(int sig);
-
-void sigchain_push_common(sigchain_fun f);
-
-#endif /* __PERF_SIGCHAIN_H */
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 31228851e397..86f05e7a5566 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -18,7 +18,7 @@
 #include "debug.h"
 #include "header.h"
 
-#include "parse-options.h"
+#include <subcmd/parse-options.h>
 #include "parse-events.h"
 #include "hist.h"
 #include "thread.h"
diff --git a/tools/perf/util/subcmd-config.c b/tools/perf/util/subcmd-config.c
deleted file mode 100644
index d017c728bd1b..000000000000
--- a/tools/perf/util/subcmd-config.c
+++ /dev/null
@@ -1,11 +0,0 @@
-#include "subcmd-config.h"
-
-#define UNDEFINED "SUBCMD_HAS_NOT_BEEN_INITIALIZED"
-
-struct subcmd_config subcmd_config = {
-	.exec_name	= UNDEFINED,
-	.prefix		= UNDEFINED,
-	.exec_path	= UNDEFINED,
-	.exec_path_env	= UNDEFINED,
-	.pager_env	= UNDEFINED,
-};
diff --git a/tools/perf/util/subcmd-config.h b/tools/perf/util/subcmd-config.h
deleted file mode 100644
index cc8514030b5c..000000000000
--- a/tools/perf/util/subcmd-config.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef __PERF_SUBCMD_CONFIG_H
-#define __PERF_SUBCMD_CONFIG_H
-
-struct subcmd_config {
-	const char *exec_name;
-	const char *prefix;
-	const char *exec_path;
-	const char *exec_path_env;
-	const char *pager_env;
-};
-
-extern struct subcmd_config subcmd_config;
-
-#endif /* __PERF_SUBCMD_CONFIG_H */
diff --git a/tools/perf/util/subcmd-util.h b/tools/perf/util/subcmd-util.h
deleted file mode 100644
index 321aeb11a381..000000000000
--- a/tools/perf/util/subcmd-util.h
+++ /dev/null
@@ -1,91 +0,0 @@
-#ifndef __PERF_SUBCMD_UTIL_H
-#define __PERF_SUBCMD_UTIL_H
-
-#include <stdarg.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#define NORETURN __attribute__((__noreturn__))
-
-static inline void report(const char *prefix, const char *err, va_list params)
-{
-	char msg[1024];
-	vsnprintf(msg, sizeof(msg), err, params);
-	fprintf(stderr, " %s%s\n", prefix, msg);
-}
-
-static NORETURN inline void die(const char *err, ...)
-{
-	va_list params;
-
-	va_start(params, err);
-	report(" Fatal: ", err, params);
-	exit(128);
-	va_end(params);
-}
-
-#define zfree(ptr) ({ free(*ptr); *ptr = NULL; })
-
-#define alloc_nr(x) (((x)+16)*3/2)
-
-/*
- * Realloc the buffer pointed at by variable 'x' so that it can hold
- * at least 'nr' entries; the number of entries currently allocated
- * is 'alloc', using the standard growing factor alloc_nr() macro.
- *
- * DO NOT USE any expression with side-effect for 'x' or 'alloc'.
- */
-#define ALLOC_GROW(x, nr, alloc) \
-	do { \
-		if ((nr) > alloc) { \
-			if (alloc_nr(alloc) < (nr)) \
-				alloc = (nr); \
-			else \
-				alloc = alloc_nr(alloc); \
-			x = xrealloc((x), alloc * sizeof(*(x))); \
-		} \
-	} while(0)
-
-static inline void *xrealloc(void *ptr, size_t size)
-{
-	void *ret = realloc(ptr, size);
-	if (!ret && !size)
-		ret = realloc(ptr, 1);
-	if (!ret) {
-		ret = realloc(ptr, size);
-		if (!ret && !size)
-			ret = realloc(ptr, 1);
-		if (!ret)
-			die("Out of memory, realloc failed");
-	}
-	return ret;
-}
-
-#define astrcatf(out, fmt, ...)						\
-({									\
-	char *tmp = *(out);						\
-	if (asprintf((out), "%s" fmt, tmp ?: "", ## __VA_ARGS__) == -1)	\
-		die("asprintf failed");					\
-	free(tmp);							\
-})
-
-static inline void astrcat(char **out, const char *add)
-{
-	char *tmp = *out;
-
-	if (asprintf(out, "%s%s", tmp ?: "", add) == -1)
-		die("asprintf failed");
-
-	free(tmp);
-}
-
-static inline int prefixcmp(const char *str, const char *prefix)
-{
-	for (; ; str++, prefix++)
-		if (!*prefix)
-			return 0;
-		else if (*str != *prefix)
-			return (unsigned char)*prefix - (unsigned char)*str;
-}
-
-#endif /* __PERF_SUBCMD_UTIL_H */
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 10/10] tools subcmd: Rename subcmd header include guards
  2015-12-17  0:47 [GIT PULL 00/10] perf/core improvements Arnaldo Carvalho de Melo
                   ` (8 preceding siblings ...)
  2015-12-17  0:48 ` [PATCH 09/10] perf subcmd: Create subcmd library Arnaldo Carvalho de Melo
@ 2015-12-17  0:48 ` Arnaldo Carvalho de Melo
  2015-12-17 17:37 ` [GIT PULL 00/10] perf/core improvements Arnaldo Carvalho de Melo
  10 siblings, 0 replies; 14+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17  0:48 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Josh Poimboeuf, Jiri Olsa, Namhyung Kim,
	Peter Zijlstra, Arnaldo Carvalho de Melo

From: Josh Poimboeuf <jpoimboe@redhat.com>

Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/d8081e7528b25ad91f4154b6a3fd063e93c108ec.1450193761.git.jpoimboe@redhat.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/lib/subcmd/exec-cmd.h      | 6 +++---
 tools/lib/subcmd/help.h          | 6 +++---
 tools/lib/subcmd/pager.h         | 6 +++---
 tools/lib/subcmd/parse-options.h | 7 ++++---
 tools/lib/subcmd/run-command.h   | 6 +++---
 tools/lib/subcmd/sigchain.h      | 6 +++---
 tools/lib/subcmd/subcmd-util.h   | 6 +++---
 7 files changed, 22 insertions(+), 21 deletions(-)

diff --git a/tools/lib/subcmd/exec-cmd.h b/tools/lib/subcmd/exec-cmd.h
index f1bd3436ad5f..5d08bda31d90 100644
--- a/tools/lib/subcmd/exec-cmd.h
+++ b/tools/lib/subcmd/exec-cmd.h
@@ -1,5 +1,5 @@
-#ifndef __PERF_EXEC_CMD_H
-#define __PERF_EXEC_CMD_H
+#ifndef __SUBCMD_EXEC_CMD_H
+#define __SUBCMD_EXEC_CMD_H
 
 extern void exec_cmd_init(const char *exec_name, const char *prefix,
 			  const char *exec_path, const char *exec_path_env);
@@ -13,4 +13,4 @@ extern int execl_cmd(const char *cmd, ...);
 extern char *get_argv_exec_path(void);
 extern char *system_path(const char *path);
 
-#endif /* __PERF_EXEC_CMD_H */
+#endif /* __SUBCMD_EXEC_CMD_H */
diff --git a/tools/lib/subcmd/help.h b/tools/lib/subcmd/help.h
index 096c8bc45cd7..e145a020780c 100644
--- a/tools/lib/subcmd/help.h
+++ b/tools/lib/subcmd/help.h
@@ -1,5 +1,5 @@
-#ifndef __PERF_HELP_H
-#define __PERF_HELP_H
+#ifndef __SUBCMD_HELP_H
+#define __SUBCMD_HELP_H
 
 #include <sys/types.h>
 
@@ -31,4 +31,4 @@ int is_in_cmdlist(struct cmdnames *c, const char *s);
 void list_commands(const char *title, struct cmdnames *main_cmds,
 		   struct cmdnames *other_cmds);
 
-#endif /* __PERF_HELP_H */
+#endif /* __SUBCMD_HELP_H */
diff --git a/tools/lib/subcmd/pager.h b/tools/lib/subcmd/pager.h
index d6a591a4c017..8b83714ecf73 100644
--- a/tools/lib/subcmd/pager.h
+++ b/tools/lib/subcmd/pager.h
@@ -1,9 +1,9 @@
-#ifndef __PERF_PAGER_H
-#define __PERF_PAGER_H
+#ifndef __SUBCMD_PAGER_H
+#define __SUBCMD_PAGER_H
 
 extern void pager_init(const char *pager_env);
 
 extern void setup_pager(void);
 extern int pager_in_use(void);
 
-#endif /* __PERF_PAGER_H */
+#endif /* __SUBCMD_PAGER_H */
diff --git a/tools/lib/subcmd/parse-options.h b/tools/lib/subcmd/parse-options.h
index dec893f10477..13a2cc1d6140 100644
--- a/tools/lib/subcmd/parse-options.h
+++ b/tools/lib/subcmd/parse-options.h
@@ -1,5 +1,5 @@
-#ifndef __PERF_PARSE_OPTIONS_H
-#define __PERF_PARSE_OPTIONS_H
+#ifndef __SUBCMD_PARSE_OPTIONS_H
+#define __SUBCMD_PARSE_OPTIONS_H
 
 #include <stdbool.h>
 #include <stdint.h>
@@ -225,4 +225,5 @@ extern const char *parse_options_fix_filename(const char *prefix, const char *fi
 void set_option_flag(struct option *opts, int sopt, const char *lopt, int flag);
 void set_option_nobuild(struct option *opts, int shortopt, const char *longopt,
 			const char *build_opt, bool can_skip);
-#endif /* __PERF_PARSE_OPTIONS_H */
+
+#endif /* __SUBCMD_PARSE_OPTIONS_H */
diff --git a/tools/lib/subcmd/run-command.h b/tools/lib/subcmd/run-command.h
index 4a55393a6547..fe2befea1e73 100644
--- a/tools/lib/subcmd/run-command.h
+++ b/tools/lib/subcmd/run-command.h
@@ -1,5 +1,5 @@
-#ifndef __PERF_RUN_COMMAND_H
-#define __PERF_RUN_COMMAND_H
+#ifndef __SUBCMD_RUN_COMMAND_H
+#define __SUBCMD_RUN_COMMAND_H
 
 #include <unistd.h>
 
@@ -57,4 +57,4 @@ int run_command(struct child_process *);
 #define RUN_COMMAND_STDOUT_TO_STDERR 4
 int run_command_v_opt(const char **argv, int opt);
 
-#endif /* __PERF_RUN_COMMAND_H */
+#endif /* __SUBCMD_RUN_COMMAND_H */
diff --git a/tools/lib/subcmd/sigchain.h b/tools/lib/subcmd/sigchain.h
index 959d64eb5557..0c919f2874ca 100644
--- a/tools/lib/subcmd/sigchain.h
+++ b/tools/lib/subcmd/sigchain.h
@@ -1,5 +1,5 @@
-#ifndef __PERF_SIGCHAIN_H
-#define __PERF_SIGCHAIN_H
+#ifndef __SUBCMD_SIGCHAIN_H
+#define __SUBCMD_SIGCHAIN_H
 
 typedef void (*sigchain_fun)(int);
 
@@ -7,4 +7,4 @@ int sigchain_pop(int sig);
 
 void sigchain_push_common(sigchain_fun f);
 
-#endif /* __PERF_SIGCHAIN_H */
+#endif /* __SUBCMD_SIGCHAIN_H */
diff --git a/tools/lib/subcmd/subcmd-util.h b/tools/lib/subcmd/subcmd-util.h
index 321aeb11a381..fc2e45d8aaf1 100644
--- a/tools/lib/subcmd/subcmd-util.h
+++ b/tools/lib/subcmd/subcmd-util.h
@@ -1,5 +1,5 @@
-#ifndef __PERF_SUBCMD_UTIL_H
-#define __PERF_SUBCMD_UTIL_H
+#ifndef __SUBCMD_UTIL_H
+#define __SUBCMD_UTIL_H
 
 #include <stdarg.h>
 #include <stdlib.h>
@@ -88,4 +88,4 @@ static inline int prefixcmp(const char *str, const char *prefix)
 			return (unsigned char)*prefix - (unsigned char)*str;
 }
 
-#endif /* __PERF_SUBCMD_UTIL_H */
+#endif /* __SUBCMD_UTIL_H */
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [GIT PULL 00/10] perf/core improvements
  2015-12-17  0:47 [GIT PULL 00/10] perf/core improvements Arnaldo Carvalho de Melo
                   ` (9 preceding siblings ...)
  2015-12-17  0:48 ` [PATCH 10/10] tools subcmd: Rename subcmd header include guards Arnaldo Carvalho de Melo
@ 2015-12-17 17:37 ` Arnaldo Carvalho de Melo
  2015-12-18  8:39   ` Ingo Molnar
  10 siblings, 1 reply; 14+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-12-17 17:37 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, David Ahern, Jiri Olsa, Josh Poimboeuf,
	Namhyung Kim, Peter Zijlstra, Taeung Song

Em Wed, Dec 16, 2015 at 09:47:53PM -0300, Arnaldo Carvalho de Melo escreveu:
> Hi Ingo,
> 
> 	Please consider pulling, this is on top of the perf-core-for-mingo
> tag, that is not yet merged.

Ingo, this wasn't building on older distros such as RHEL6.7 due to a
typedef problem, a one-liner, so to preserve bisection in such systems,
I ammended the commit, kept this perf-core-for-mingo-2 tag, but now
there is a perf-core-for-mingo-2.1 signed tag pointing to the good
stuff, take your pick.

- Arnaldo
 
> - Arnaldo
> 
> The following changes since commit 7efe0e034c713716060bc7794c7e332589980c70:
> 
>   perf record: Support custom vmlinux path (2015-12-14 13:04:12 -0300)
> 
> are available in the git repository at:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git tags/perf-core-for-mingo-2
> 
> for you to fetch changes up to 5c560cfcf1c0f897f78aa5955e3eb05418891f34:
> 
>   tools subcmd: Rename subcmd header include guards (2015-12-16 21:39:01 -0300)
> 
> ----------------------------------------------------------------
> perf/core improvements
> 
> User visible:
> 
> - Add record.build-id config option to 'perf record', to allow configuring
>   in the ~/.perfconfig file if and how build-ids should be processed, allowing
>   a permanent setting for options such as -B and -N: (Namhyung Kim)
> 
>   $ perf record -h -B -N
> 
>    Usage: perf record [<options>] [<command>]
>       or: perf record [<options>] -- <command> [<options>]
> 
>       -B, --no-buildid       do not collect buildids in perf.data
>       -N, --no-buildid-cache do not update the buildid cache
> 
>   $
> 
> Infrastructure:
> 
> - Move code for options parsing and subcommand handling from tools/perf/
>   to tools/lib/subcmd/, so that it can be used by other tools/ living
>   utilities (Josh Poimboeuf)
> 
> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
> 
> ----------------------------------------------------------------
> Josh Poimboeuf (9):
>       tools build: Fix feature Makefile issues with 'O='
>       perf tools: Move strlcpy() from perf to tools/lib/string.c
>       perf tools: Document the fact that parse_options*() may exit
>       perf tools: Provide subcmd configuration at runtime
>       perf tools: Remove subcmd dependencies on strbuf
>       perf tools: Remove 'perf' from subcmd function and variable names
>       perf tools: Finalize subcmd independence
>       perf subcmd: Create subcmd library
>       tools subcmd: Rename subcmd header include guards
> 
> Namhyung Kim (1):
>       perf record: Add record.build-id config option
> 
>  tools/build/Makefile.feature                    |   2 +-
>  tools/build/feature/Makefile                    |  93 +++++------
>  tools/include/linux/string.h                    |   4 +
>  tools/lib/string.c                              |  27 +++
>  tools/lib/subcmd/Build                          |   7 +
>  tools/lib/subcmd/Makefile                       |  48 ++++++
>  tools/lib/subcmd/exec-cmd.c                     | 209 ++++++++++++++++++++++++
>  tools/lib/subcmd/exec-cmd.h                     |  16 ++
>  tools/{perf/util => lib/subcmd}/help.c          |  63 +++++--
>  tools/{perf/util => lib/subcmd}/help.h          |  10 +-
>  tools/{perf/util => lib/subcmd}/pager.c         |  15 +-
>  tools/lib/subcmd/pager.h                        |   9 +
>  tools/{perf/util => lib/subcmd}/parse-options.c | 116 +++++++------
>  tools/{perf/util => lib/subcmd}/parse-options.h |  12 +-
>  tools/{perf/util => lib/subcmd}/run-command.c   |  24 ++-
>  tools/{perf/util => lib/subcmd}/run-command.h   |  12 +-
>  tools/{perf/util => lib/subcmd}/sigchain.c      |   3 +-
>  tools/{perf/util => lib/subcmd}/sigchain.h      |   6 +-
>  tools/lib/subcmd/subcmd-config.c                |  11 ++
>  tools/lib/subcmd/subcmd-config.h                |  14 ++
>  tools/lib/subcmd/subcmd-util.h                  |  91 +++++++++++
>  tools/perf/Build                                |   5 +-
>  tools/perf/Documentation/perf-record.txt        |  14 +-
>  tools/perf/MANIFEST                             |   1 +
>  tools/perf/Makefile.perf                        |  20 ++-
>  tools/perf/arch/x86/util/intel-pt.c             |   2 +-
>  tools/perf/bench/futex-hash.c                   |   2 +-
>  tools/perf/bench/futex-lock-pi.c                |   2 +-
>  tools/perf/bench/futex-requeue.c                |   2 +-
>  tools/perf/bench/futex-wake-parallel.c          |   2 +-
>  tools/perf/bench/futex-wake.c                   |   2 +-
>  tools/perf/bench/mem-functions.c                |   2 +-
>  tools/perf/bench/numa.c                         |   2 +-
>  tools/perf/bench/sched-messaging.c              |   2 +-
>  tools/perf/bench/sched-pipe.c                   |   2 +-
>  tools/perf/builtin-annotate.c                   |   2 +-
>  tools/perf/builtin-bench.c                      |   2 +-
>  tools/perf/builtin-buildid-cache.c              |   2 +-
>  tools/perf/builtin-buildid-list.c               |   2 +-
>  tools/perf/builtin-config.c                     |   2 +-
>  tools/perf/builtin-data.c                       |   2 +-
>  tools/perf/builtin-evlist.c                     |   2 +-
>  tools/perf/builtin-help.c                       |  10 +-
>  tools/perf/builtin-inject.c                     |   2 +-
>  tools/perf/builtin-kmem.c                       |   2 +-
>  tools/perf/builtin-kvm.c                        |   2 +-
>  tools/perf/builtin-list.c                       |   2 +-
>  tools/perf/builtin-lock.c                       |   2 +-
>  tools/perf/builtin-mem.c                        |   2 +-
>  tools/perf/builtin-probe.c                      |   2 +-
>  tools/perf/builtin-record.c                     |  15 +-
>  tools/perf/builtin-report.c                     |   2 +-
>  tools/perf/builtin-sched.c                      |   2 +-
>  tools/perf/builtin-script.c                     |  12 +-
>  tools/perf/builtin-stat.c                       |   2 +-
>  tools/perf/builtin-timechart.c                  |   2 +-
>  tools/perf/builtin-top.c                        |   2 +-
>  tools/perf/builtin-trace.c                      |   4 +-
>  tools/perf/perf.c                               |  18 +-
>  tools/perf/tests/attr.c                         |   4 +-
>  tools/perf/tests/builtin-test.c                 |   2 +-
>  tools/perf/util/Build                           |   7 -
>  tools/perf/util/auxtrace.c                      |   2 +-
>  tools/perf/util/cache.h                         |  10 +-
>  tools/perf/util/cgroup.c                        |   2 +-
>  tools/perf/util/config.c                        |   2 +-
>  tools/perf/util/evlist.c                        |   2 +-
>  tools/perf/util/exec_cmd.c                      | 149 -----------------
>  tools/perf/util/exec_cmd.h                      |  13 --
>  tools/perf/util/help-unknown-cmd.c              |   2 +-
>  tools/perf/util/pager.h                         |   7 -
>  tools/perf/util/parse-branch-options.c          |   2 +-
>  tools/perf/util/parse-events.c                  |   4 +-
>  tools/perf/util/parse-regs-options.c            |   2 +-
>  tools/perf/util/path.c                          |  18 --
>  tools/perf/util/sort.h                          |   2 +-
>  tools/perf/util/util.h                          |  14 --
>  77 files changed, 775 insertions(+), 418 deletions(-)
>  create mode 100644 tools/lib/subcmd/Build
>  create mode 100644 tools/lib/subcmd/Makefile
>  create mode 100644 tools/lib/subcmd/exec-cmd.c
>  create mode 100644 tools/lib/subcmd/exec-cmd.h
>  rename tools/{perf/util => lib/subcmd}/help.c (81%)
>  rename tools/{perf/util => lib/subcmd}/help.h (87%)
>  rename tools/{perf/util => lib/subcmd}/pager.c (85%)
>  create mode 100644 tools/lib/subcmd/pager.h
>  rename tools/{perf/util => lib/subcmd}/parse-options.c (90%)
>  rename tools/{perf/util => lib/subcmd}/parse-options.h (96%)
>  rename tools/{perf/util => lib/subcmd}/run-command.c (90%)
>  rename tools/{perf/util => lib/subcmd}/run-command.h (86%)
>  rename tools/{perf/util => lib/subcmd}/sigchain.c (95%)
>  rename tools/{perf/util => lib/subcmd}/sigchain.h (55%)
>  create mode 100644 tools/lib/subcmd/subcmd-config.c
>  create mode 100644 tools/lib/subcmd/subcmd-config.h
>  create mode 100644 tools/lib/subcmd/subcmd-util.h
>  delete mode 100644 tools/perf/util/exec_cmd.c
>  delete mode 100644 tools/perf/util/exec_cmd.h
>  delete mode 100644 tools/perf/util/pager.h
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [GIT PULL 00/10] perf/core improvements
  2015-12-17 17:37 ` [GIT PULL 00/10] perf/core improvements Arnaldo Carvalho de Melo
@ 2015-12-18  8:39   ` Ingo Molnar
  0 siblings, 0 replies; 14+ messages in thread
From: Ingo Molnar @ 2015-12-18  8:39 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: linux-kernel, David Ahern, Jiri Olsa, Josh Poimboeuf,
	Namhyung Kim, Peter Zijlstra, Taeung Song


* Arnaldo Carvalho de Melo <acme@kernel.org> wrote:

> Em Wed, Dec 16, 2015 at 09:47:53PM -0300, Arnaldo Carvalho de Melo escreveu:
> > Hi Ingo,
> > 
> > 	Please consider pulling, this is on top of the perf-core-for-mingo
> > tag, that is not yet merged.
> 
> Ingo, this wasn't building on older distros such as RHEL6.7 due to a
> typedef problem, a one-liner, so to preserve bisection in such systems,
> I ammended the commit, kept this perf-core-for-mingo-2 tag, but now
> there is a perf-core-for-mingo-2.1 signed tag pointing to the good
> stuff, take your pick.

I pulled perf-core-for-mingo-2.1, thanks a lot Arnaldo!

	Ingo

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [GIT PULL 00/10] perf/core improvements
@ 2010-12-09 18:12 Arnaldo Carvalho de Melo
  0 siblings, 0 replies; 14+ messages in thread
From: Arnaldo Carvalho de Melo @ 2010-12-09 18:12 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, Arnaldo Carvalho de Melo, David Ahern,
	Frederic Weisbecker, Ian Munsie, Ingo Molnar, Peter Zijlstra,
	Thomas Gleixner, Arnaldo Carvalho de Melo

Hi Ingo,

        Please pull from:

git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux-2.6 perf/core

Regards,

- Arnaldo

Arnaldo Carvalho de Melo (1):
  perf session: Remove unneeded dump_printf calls

David Ahern (1):
  perf report: Allow user to specify path to kallsyms file

Thomas Gleixner (8):
  perf event: Prevent unbound event__name array access
  perf session: Dont queue events w/o timestamps
  perf session: Consolidate the dump code
  perf session: Store file offset in sample_queue
  perf session: Add file_offset to event delivery function
  perf session: Move dump code to event delivery path
  perf session: Split out sample preprocessing
  perf session: Split out user event processing

 tools/perf/Documentation/perf-report.txt |    3 +
 tools/perf/builtin-report.c              |    2 +
 tools/perf/util/event.c                  |   12 ++-
 tools/perf/util/event.h                  |    3 +-
 tools/perf/util/hist.c                   |    9 +-
 tools/perf/util/session.c                |  154 ++++++++++++++++++-----------
 tools/perf/util/symbol.c                 |    9 ++-
 tools/perf/util/symbol.h                 |    1 +
 8 files changed, 127 insertions(+), 66 deletions(-)


^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2015-12-18  8:39 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-12-17  0:47 [GIT PULL 00/10] perf/core improvements Arnaldo Carvalho de Melo
2015-12-17  0:47 ` [PATCH 01/10] perf record: Add record.build-id config option Arnaldo Carvalho de Melo
2015-12-17  0:47 ` [PATCH 02/10] tools build: Fix feature Makefile issues with 'O=' Arnaldo Carvalho de Melo
2015-12-17  0:47 ` [PATCH 03/10] perf tools: Move strlcpy() from perf to tools/lib/string.c Arnaldo Carvalho de Melo
2015-12-17  0:47 ` [PATCH 04/10] perf tools: Document the fact that parse_options*() may exit Arnaldo Carvalho de Melo
2015-12-17  0:47 ` [PATCH 05/10] perf tools: Provide subcmd configuration at runtime Arnaldo Carvalho de Melo
2015-12-17  0:47 ` [PATCH 06/10] perf tools: Remove subcmd dependencies on strbuf Arnaldo Carvalho de Melo
2015-12-17  0:48 ` [PATCH 07/10] perf tools: Remove 'perf' from subcmd function and variable names Arnaldo Carvalho de Melo
2015-12-17  0:48 ` [PATCH 08/10] perf tools: Finalize subcmd independence Arnaldo Carvalho de Melo
2015-12-17  0:48 ` [PATCH 09/10] perf subcmd: Create subcmd library Arnaldo Carvalho de Melo
2015-12-17  0:48 ` [PATCH 10/10] tools subcmd: Rename subcmd header include guards Arnaldo Carvalho de Melo
2015-12-17 17:37 ` [GIT PULL 00/10] perf/core improvements Arnaldo Carvalho de Melo
2015-12-18  8:39   ` Ingo Molnar
  -- strict thread matches above, loose matches on Subject: below --
2010-12-09 18:12 Arnaldo Carvalho de Melo

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.