Commit 8a26ce4e authored by Ingo Molnar's avatar Ingo Molnar

Merge tag 'perf-core-for-mingo' of...

Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core

Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo:

User visible changes:

  - No need to explicitely enable evsels for workload started from perf, let it
    be enabled via perf_event_attr.enable_on_exec, removing some events that take
    place in the 'perf trace' before a workload is really started by it.
    (Arnaldo Carvalho de Melo)

  - Fix to handle optimized not-inlined functions in 'perf probe' (Masami Hiramatsu)

  - Update 'perf probe' man page (Masami Hiramatsu)

  - 'perf trace': Allow mixing with tracepoints and suppressing plain syscalls
    (Arnaldo Carvalho de Melo)

Infrastructure changes:

  - Introduce {trace_seq_do,event_format_}_fprintf functions to allow
    a default tracepoint field list printer to be used in tools that allows
    redirecting output to a file. (Arnaldo Carvalho de Melo)

  - The man page for pthread_attr_set_affinity_np states that _GNU_SOURCE
    must be defined before pthread.h, do it to fix the build in some
    systems (Josh Boyer)

  - Cleanups in 'perf buildid-cache' (Masami Hiramatsu)

  - Fix dso cache test case (Namhyung Kim)

  - Do Not rely on dso__data_read_offset() to open DSO (Namhyung Kim)

  - Make perf aware of tracefs (Steven Rostedt).

  - Fix build by defining STT_GNU_IFUNC for glibc 2.9 and older (Vinson Lee)

  - AArch64 symbol resolution fixes (Victor Kamensky)

  - Kconfig beachhead (Jiri Olsa)

  - Simplify nr_pages validity (Kaixu Xia)

  - Fixup header positioning in 'perf list' (Yunlong Song)
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parents acba3c7e 726f3234
...@@ -4446,7 +4446,7 @@ static int perf_mmap(struct file *file, struct vm_area_struct *vma) ...@@ -4446,7 +4446,7 @@ static int perf_mmap(struct file *file, struct vm_area_struct *vma)
* If we have rb pages ensure they're a power-of-two number, so we * If we have rb pages ensure they're a power-of-two number, so we
* can do bitmasks instead of modulo. * can do bitmasks instead of modulo.
*/ */
if (nr_pages != 0 && !is_power_of_2(nr_pages)) if (!is_power_of_2(nr_pages))
return -EINVAL; return -EINVAL;
if (vma_size != PAGE_SIZE * (1 + nr_pages)) if (vma_size != PAGE_SIZE * (1 + nr_pages))
......
###
# build: Generic definitions
#
# Lots of this code have been borrowed or heavily inspired from parts
# of kbuild code, which is not credited, but mostly developed by:
#
# Copyright (C) Sam Ravnborg <sam@mars.ravnborg.org>, 2015
# Copyright (C) Linus Torvalds <torvalds@linux-foundation.org>, 2015
#
###
# Convenient variables
comma := ,
squote := '
###
# Name of target with a '.' as filename prefix. foo/bar.o => foo/.bar.o
dot-target = $(dir $@).$(notdir $@)
###
# filename of target with directory and extension stripped
basetarget = $(basename $(notdir $@))
###
# The temporary file to save gcc -MD generated dependencies must not
# contain a comma
depfile = $(subst $(comma),_,$(dot-target).d)
###
# Check if both arguments has same arguments. Result is empty string if equal.
arg-check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \
$(filter-out $(cmd_$@), $(cmd_$(1))) )
###
# Escape single quote for use in echo statements
escsq = $(subst $(squote),'\$(squote)',$1)
# Echo command
# Short version is used, if $(quiet) equals `quiet_', otherwise full one.
echo-cmd = $(if $($(quiet)cmd_$(1)),\
echo ' $(call escsq,$($(quiet)cmd_$(1)))';)
###
# Replace >$< with >$$< to preserve $ when reloading the .cmd file
# (needed for make)
# Replace >#< with >\#< to avoid starting a comment in the .cmd file
# (needed for make)
# Replace >'< with >'\''< to be able to enclose the whole string in '...'
# (needed for the shell)
make-cmd = $(call escsq,$(subst \#,\\\#,$(subst $$,$$$$,$(cmd_$(1)))))
###
# Find any prerequisites that is newer than target or that does not exist.
# PHONY targets skipped in both cases.
any-prereq = $(filter-out $(PHONY),$?) $(filter-out $(PHONY) $(wildcard $^),$^)
###
# if_changed_dep - execute command if any prerequisite is newer than
# target, or command line has changed and update
# dependencies in the cmd file
if_changed_dep = $(if $(strip $(any-prereq) $(arg-check)), \
@set -e; \
$(echo-cmd) $(cmd_$(1)); \
cat $(depfile) > $(dot-target).cmd; \
printf '%s\n' 'cmd_$@ := $(make-cmd)' >> $(dot-target).cmd)
# if_changed - execute command if any prerequisite is newer than
# target, or command line has changed
if_changed = $(if $(strip $(any-prereq) $(arg-check)), \
@set -e; \
$(echo-cmd) $(cmd_$(1)); \
printf '%s\n' 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd)
###
# C flags to be used in rule definitions, includes:
# - depfile generation
# - global $(CFLAGS)
# - per target C flags
# - per object C flags
# - BUILD_STR macro to allow '-D"$(variable)"' constructs
c_flags = -Wp,-MD,$(depfile),-MT,$@ $(CFLAGS) -D"BUILD_STR(s)=\#s" $(CFLAGS_$(basetarget).o) $(CFLAGS_$(obj))
Build Framework
===============
The perf build framework was adopted from the kernel build system, hence the
idea and the way how objects are built is the same.
Basically the user provides set of 'Build' files that list objects and
directories to nest for specific target to be build.
Unlike the kernel we don't have a single build object 'obj-y' list that where
we setup source objects, but we support more. This allows one 'Build' file to
carry a sources list for multiple build objects.
a) Build framework makefiles
----------------------------
The build framework consists of 2 Makefiles:
Build.include
Makefile.build
While the 'Build.include' file contains just some generic definitions, the
'Makefile.build' file is the makefile used from the outside. It's
interface/usage is following:
$ make -f tools/build/Makefile srctree=$(KSRC) dir=$(DIR) obj=$(OBJECT)
where:
KSRC - is the path to kernel sources
DIR - is the path to the project to be built
OBJECT - is the name of the build object
When succefully finished the $(DIR) directory contains the final object file
called $(OBJECT)-in.o:
$ ls $(DIR)/$(OBJECT)-in.o
which includes all compiled sources described in 'Build' makefiles.
a) Build makefiles
------------------
The user supplies 'Build' makefiles that contains a objects list, and connects
the build to nested directories.
Assume we have the following project structure:
ex/a.c
/b.c
/c.c
/d.c
/arch/e.c
/arch/f.c
Out of which you build the 'ex' binary ' and the 'libex.a' library:
'ex' - consists of 'a.o', 'b.o' and libex.a
'libex.a' - consists of 'c.o', 'd.o', 'e.o' and 'f.o'
The build framework does not create the 'ex' and 'libex.a' binaries for you, it
only prepares proper objects to be compiled and grouped together.
To follow the above example, the user provides following 'Build' files:
ex/Build:
ex-y += a.o
ex-y += b.o
libex-y += c.o
libex-y += d.o
libex-y += arch/
ex/arch/Build:
libex-y += e.o
libex-y += f.o
and runs:
$ make -f tools/build/Makefile.build dir=. obj=ex
$ make -f tools/build/Makefile.build dir=. obj=libex
which creates the following objects:
ex/ex-in.o
ex/libex-in.o
that contain request objects names in Build files.
It's only a matter of 2 single commands to create the final binaries:
$ ar rcs libex.a libex-in.o
$ gcc -o ex ex-in.o libex.a
You can check the 'ex' example in 'tools/build/tests/ex' for more details.
b) Rules
--------
The build framework provides standard compilation rules to handle .S and .c
compilation.
It's possible to include special rule if needed (like we do for flex or bison
code generation).
c) CFLAGS
---------
It's possible to alter the standard object C flags in the following way:
CFLAGS_perf.o += '...' - alters CFLAGS for perf.o object
CFLAGS_gtk += '...' - alters CFLAGS for gtk build object
This C flags changes has the scope of the Build makefile they are defined in.
d) Dependencies
---------------
For each built object file 'a.o' the '.a.cmd' is created and holds:
- Command line used to built that object
(for each object)
- Dependency rules generated by 'gcc -Wp,-MD,...'
(for compiled object)
All existing '.cmd' files are included in the Build process to follow properly
the dependencies and trigger a rebuild when necessary.
e) Single rules
---------------
It's possible to build single object file by choice, like:
$ make util/map.o # objects
$ make util/map.i # preprocessor
$ make util/map.s # assembly
###
# Main build makefile.
#
# Lots of this code have been borrowed or heavily inspired from parts
# of kbuild code, which is not credited, but mostly developed by:
#
# Copyright (C) Sam Ravnborg <sam@mars.ravnborg.org>, 2015
# Copyright (C) Linus Torvalds <torvalds@linux-foundation.org>, 2015
#
PHONY := __build
__build:
ifeq ($(V),1)
quiet =
Q =
else
quiet=quiet_
Q=@
endif
build-dir := $(srctree)/tools/build
# Generic definitions
include $(build-dir)/Build.include
# do not force detected configuration
-include .config-detected
# Init all relevant variables used in build files so
# 1) they have correct type
# 2) they do not inherit any value from the environment
subdir-y :=
obj-y :=
subdir-y :=
subdir-obj-y :=
# Build definitions
build-file := $(dir)/Build
include $(build-file)
quiet_cmd_flex = FLEX $@
quiet_cmd_bison = BISON $@
# Create directory unless it exists
quiet_cmd_mkdir = MKDIR $(dir $@)
cmd_mkdir = mkdir -p $(dir $@)
rule_mkdir = $(if $(wildcard $(dir $@)),,@$(call echo-cmd,mkdir) $(cmd_mkdir))
# Compile command
quiet_cmd_cc_o_c = CC $@
cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $<
quiet_cmd_cc_i_c = CPP $@
cmd_cc_i_c = $(CC) $(c_flags) -E -o $@ $<
quiet_cmd_cc_s_c = AS $@
cmd_cc_s_c = $(CC) $(c_flags) -S -o $@ $<
# Link agregate command
# If there's nothing to link, create empty $@ object.
quiet_cmd_ld_multi = LD $@
cmd_ld_multi = $(if $(strip $(obj-y)),\
$(LD) -r -o $@ $(obj-y),rm -f $@; $(AR) rcs $@)
# Build rules
$(OUTPUT)%.o: %.c FORCE
$(call rule_mkdir)
$(call if_changed_dep,cc_o_c)
$(OUTPUT)%.o: %.S FORCE
$(call rule_mkdir)
$(call if_changed_dep,cc_o_c)
$(OUTPUT)%.i: %.c FORCE
$(call rule_mkdir)
$(call if_changed_dep,cc_i_c)
$(OUTPUT)%.i: %.S FORCE
$(call rule_mkdir)
$(call if_changed_dep,cc_i_c)
$(OUTPUT)%.s: %.c FORCE
$(call rule_mkdir)
$(call if_changed_dep,cc_s_c)
# Gather build data:
# obj-y - list of build objects
# subdir-y - list of directories to nest
# subdir-obj-y - list of directories objects 'dir/$(obj)-in.o'
obj-y := $($(obj)-y)
subdir-y := $(patsubst %/,%,$(filter %/, $(obj-y)))
obj-y := $(patsubst %/, %/$(obj)-in.o, $(obj-y))
subdir-obj-y := $(filter %/$(obj)-in.o, $(obj-y))
# '$(OUTPUT)/dir' prefix to all objects
prefix := $(subst ./,,$(OUTPUT)$(dir)/)
obj-y := $(addprefix $(prefix),$(obj-y))
subdir-obj-y := $(addprefix $(prefix),$(subdir-obj-y))
# Final '$(obj)-in.o' object
in-target := $(prefix)$(obj)-in.o
PHONY += $(subdir-y)
$(subdir-y):
$(Q)$(MAKE) -f $(build-dir)/Makefile.build dir=$(dir)/$@ obj=$(obj)
$(sort $(subdir-obj-y)): $(subdir-y) ;
$(in-target): $(obj-y) FORCE
$(call rule_mkdir)
$(call if_changed,ld_multi)
__build: $(in-target)
@:
PHONY += FORCE
FORCE:
# Include all cmd files to get all the dependency rules
# for all objects included
targets := $(wildcard $(sort $(obj-y) $(in-target) $(MAKECMDGOALS)))
cmd_files := $(wildcard $(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd))
ifneq ($(cmd_files),)
include $(cmd_files)
endif
.PHONY: $(PHONY)
ex-y += ex.o
ex-y += a.o
ex-y += b.o
ex-y += empty/
libex-y += c.o
libex-y += d.o
libex-y += arch/
export srctree := ../../../..
export CC := gcc
export LD := ld
export AR := ar
build := -f $(srctree)/tools/build/Makefile.build dir=. obj
ex: ex-in.o libex-in.o
gcc -o $@ $^
ex.%: FORCE
make -f $(srctree)/tools/build/Makefile.build dir=. $@
ex-in.o: FORCE
make $(build)=ex
libex-in.o: FORCE
make $(build)=libex
clean:
find . -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete
rm -f ex ex.i ex.s
.PHONY: FORCE
int a(void)
{
return 0;
}
libex-y += e.o
libex-y += f.o
int e(void)
{
return 0;
}
int f(void)
{
return 0;
}
int b(void)
{
return 0;
}
int c(void)
{
return 0;
}
int d(void)
{
return 0;
}
int a(void);
int b(void);
int c(void);
int d(void);
int e(void);
int f(void);
int main(void)
{
a();
b();
c();
d();
e();
f();
return 0;
}
#!/bin/sh
function test_ex {
make -C ex V=1 clean > ex.out 2>&1
make -C ex V=1 >> ex.out 2>&1
if [ ! -x ./ex/ex ]; then
echo FAILED
exit -1
fi
make -C ex V=1 clean > /dev/null 2>&1
rm -f ex.out
}
function test_ex_suffix {
make -C ex V=1 clean > ex.out 2>&1
# use -rR to disable make's builtin rules
make -rR -C ex V=1 ex.o >> ex.out 2>&1
make -rR -C ex V=1 ex.i >> ex.out 2>&1
make -rR -C ex V=1 ex.s >> ex.out 2>&1
if [ -x ./ex/ex ]; then
echo FAILED
exit -1
fi
if [ ! -f ./ex/ex.o -o ! -f ./ex/ex.i -o ! -f ./ex/ex.s ]; then
echo FAILED
exit -1
fi
make -C ex V=1 clean > /dev/null 2>&1
rm -f ex.out
}
echo -n Testing..
test_ex
test_ex_suffix
echo OK
libapi-y += fd/
libapi-y += fs/
include ../../scripts/Makefile.include include ../../scripts/Makefile.include
include ../../perf/config/utilities.mak # QUIET_CLEAN 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 CC = $(CROSS_COMPILE)gcc
AR = $(CROSS_COMPILE)ar AR = $(CROSS_COMPILE)ar
# guard against environment variables MAKEFLAGS += --no-print-directory
LIB_H=
LIB_OBJS=
LIB_H += fs/debugfs.h
LIB_H += fs/fs.h
# See comment below about piggybacking...
LIB_H += fd/array.h
LIB_OBJS += $(OUTPUT)fs/debugfs.o
LIB_OBJS += $(OUTPUT)fs/fs.o
# XXX piggybacking here, need to introduce libapikfd, or rename this
# to plain libapik.a and make it have it all api goodies
LIB_OBJS += $(OUTPUT)fd/array.o
LIBFILE = libapikfs.a LIBFILE = $(OUTPUT)libapi.a
CFLAGS = -ggdb3 -Wall -Wextra -std=gnu99 -Werror -O6 -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) -fPIC CFLAGS := $(EXTRA_WARNINGS) $(EXTRA_CFLAGS)
EXTLIBS = -lelf -lpthread -lrt -lm CFLAGS += -ggdb3 -Wall -Wextra -std=gnu99 -Werror -O6 -D_FORTIFY_SOURCE=2 -fPIC
ALL_CFLAGS = $(CFLAGS) $(BASIC_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
ALL_LDFLAGS = $(LDFLAGS)
RM = rm -f RM = rm -f
$(LIBFILE): $(LIB_OBJS) build := -f $(srctree)/tools/build/Makefile.build dir=. obj
$(QUIET_AR)$(RM) $@ && $(AR) rcs $(OUTPUT)$@ $(LIB_OBJS) API_IN := $(OUTPUT)libapi-in.o
$(LIB_OBJS): $(LIB_H) export srctree OUTPUT CC LD CFLAGS V
libapi_dirs: all: $(LIBFILE)
$(QUIET_MKDIR)mkdir -p $(OUTPUT)fd $(OUTPUT)fs
$(OUTPUT)%.o: %.c libapi_dirs $(API_IN): FORCE
$(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $< @$(MAKE) $(build)=libapi
$(OUTPUT)%.s: %.c libapi_dirs
$(QUIET_CC)$(CC) -S $(ALL_CFLAGS) $< $(LIBFILE): $(API_IN)
$(OUTPUT)%.o: %.S libapi_dirs $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(API_IN)
$(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $<
clean: clean:
$(call QUIET_CLEAN, libapi) $(RM) $(LIB_OBJS) $(LIBFILE) $(call QUIET_CLEAN, libapi) $(RM) $(LIBFILE); \
find $(if $(OUTPUT),$(OUTPUT),.) -name \*.o | xargs $(RM)
FORCE:
.PHONY: clean .PHONY: clean FORCE
libapi-y += array.o
libapi-y += fs.o
libapi-y += debugfs.o
libapi-y += findfs.o
libapi-y += tracefs.o
...@@ -3,75 +3,50 @@ ...@@ -3,75 +3,50 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#include <stdbool.h> #include <stdbool.h>
#include <sys/vfs.h> #include <sys/vfs.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mount.h> #include <sys/mount.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include "debugfs.h" #include "debugfs.h"
char debugfs_mountpoint[PATH_MAX + 1] = "/sys/kernel/debug"; #ifndef DEBUGFS_DEFAULT_PATH
#define DEBUGFS_DEFAULT_PATH "/sys/kernel/debug"
#endif
char debugfs_mountpoint[PATH_MAX + 1] = DEBUGFS_DEFAULT_PATH;
static const char * const debugfs_known_mountpoints[] = { static const char * const debugfs_known_mountpoints[] = {
"/sys/kernel/debug", DEBUGFS_DEFAULT_PATH,
"/debug", "/debug",
0, 0,
}; };
static bool debugfs_found; static bool debugfs_found;
bool debugfs_configured(void)
{
return debugfs_find_mountpoint() != NULL;
}
/* find the path to the mounted debugfs */ /* find the path to the mounted debugfs */
const char *debugfs_find_mountpoint(void) const char *debugfs_find_mountpoint(void)
{ {
const char * const *ptr; const char *ret;
char type[100];
FILE *fp;
if (debugfs_found) if (debugfs_found)
return (const char *)debugfs_mountpoint; return (const char *)debugfs_mountpoint;
ptr = debugfs_known_mountpoints; ret = find_mountpoint("debugfs", (long) DEBUGFS_MAGIC,
while (*ptr) { debugfs_mountpoint, PATH_MAX + 1,
if (debugfs_valid_mountpoint(*ptr) == 0) { debugfs_known_mountpoints);
debugfs_found = true; if (ret)
strcpy(debugfs_mountpoint, *ptr); debugfs_found = true;
return debugfs_mountpoint;
}
ptr++;
}
/* give up and parse /proc/mounts */
fp = fopen("/proc/mounts", "r");
if (fp == NULL)
return NULL;
while (fscanf(fp, "%*s %" STR(PATH_MAX) "s %99s %*s %*d %*d\n",
debugfs_mountpoint, type) == 2) {
if (strcmp(type, "debugfs") == 0)
break;
}
fclose(fp);
if (strcmp(type, "debugfs") != 0) return ret;
return NULL;
debugfs_found = true;
return debugfs_mountpoint;
}
/* verify that a mountpoint is actually a debugfs instance */
int debugfs_valid_mountpoint(const char *debugfs)
{
struct statfs st_fs;
if (statfs(debugfs, &st_fs) < 0)
return -ENOENT;
else if ((long)st_fs.f_type != (long)DEBUGFS_MAGIC)
return -ENOENT;
return 0;
} }
/* mount the debugfs somewhere if it's not mounted */ /* mount the debugfs somewhere if it's not mounted */
...@@ -87,7 +62,7 @@ char *debugfs_mount(const char *mountpoint) ...@@ -87,7 +62,7 @@ char *debugfs_mount(const char *mountpoint)
mountpoint = getenv(PERF_DEBUGFS_ENVIRONMENT); mountpoint = getenv(PERF_DEBUGFS_ENVIRONMENT);
/* if no environment variable, use default */ /* if no environment variable, use default */
if (mountpoint == NULL) if (mountpoint == NULL)
mountpoint = "/sys/kernel/debug"; mountpoint = DEBUGFS_DEFAULT_PATH;
} }
if (mount(NULL, mountpoint, "debugfs", 0, NULL) < 0) if (mount(NULL, mountpoint, "debugfs", 0, NULL) < 0)
......
#ifndef __API_DEBUGFS_H__ #ifndef __API_DEBUGFS_H__
#define __API_DEBUGFS_H__ #define __API_DEBUGFS_H__
#define _STR(x) #x #include "findfs.h"
#define STR(x) _STR(x)
/*
* On most systems <limits.h> would have given us this, but not on some systems
* (e.g. GNU/Hurd).
*/
#ifndef PATH_MAX
#define PATH_MAX 4096
#endif
#ifndef DEBUGFS_MAGIC #ifndef DEBUGFS_MAGIC
#define DEBUGFS_MAGIC 0x64626720 #define DEBUGFS_MAGIC 0x64626720
...@@ -20,8 +11,8 @@ ...@@ -20,8 +11,8 @@
#define PERF_DEBUGFS_ENVIRONMENT "PERF_DEBUGFS_DIR" #define PERF_DEBUGFS_ENVIRONMENT "PERF_DEBUGFS_DIR"
#endif #endif
bool debugfs_configured(void);
const char *debugfs_find_mountpoint(void); const char *debugfs_find_mountpoint(void);
int debugfs_valid_mountpoint(const char *debugfs);
char *debugfs_mount(const char *mountpoint); char *debugfs_mount(const char *mountpoint);
extern char debugfs_mountpoint[]; extern char debugfs_mountpoint[];
......
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <sys/vfs.h>
#include "findfs.h"
/* verify that a mountpoint is actually the type we want */
int valid_mountpoint(const char *mount, long magic)
{
struct statfs st_fs;
if (statfs(mount, &st_fs) < 0)
return -ENOENT;
else if ((long)st_fs.f_type != magic)
return -ENOENT;
return 0;
}
/* find the path to a mounted file system */
const char *find_mountpoint(const char *fstype, long magic,
char *mountpoint, int len,
const char * const *known_mountpoints)
{
const char * const *ptr;
char format[128];
char type[100];
FILE *fp;
if (known_mountpoints) {
ptr = known_mountpoints;
while (*ptr) {
if (valid_mountpoint(*ptr, magic) == 0) {
strncpy(mountpoint, *ptr, len - 1);
mountpoint[len-1] = 0;
return mountpoint;
}
ptr++;
}
}
/* give up and parse /proc/mounts */
fp = fopen("/proc/mounts", "r");
if (fp == NULL)
return NULL;
snprintf(format, 128, "%%*s %%%ds %%99s %%*s %%*d %%*d\n", len);
while (fscanf(fp, format, mountpoint, type) == 2) {
if (strcmp(type, fstype) == 0)
break;
}
fclose(fp);
if (strcmp(type, fstype) != 0)
return NULL;
return mountpoint;
}
#ifndef __API_FINDFS_H__
#define __API_FINDFS_H__
#include <stdbool.h>
#define _STR(x) #x
#define STR(x) _STR(x)
/*
* On most systems <limits.h> would have given us this, but not on some systems
* (e.g. GNU/Hurd).
*/
#ifndef PATH_MAX
#define PATH_MAX 4096
#endif
const char *find_mountpoint(const char *fstype, long magic,
char *mountpoint, int len,
const char * const *known_mountpoints);
int valid_mountpoint(const char *mount, long magic);
#endif /* __API_FINDFS_H__ */
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdbool.h>
#include <sys/vfs.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mount.h>
#include <linux/kernel.h>
#include "tracefs.h"
#ifndef TRACEFS_DEFAULT_PATH
#define TRACEFS_DEFAULT_PATH "/sys/kernel/tracing"
#endif
char tracefs_mountpoint[PATH_MAX + 1] = TRACEFS_DEFAULT_PATH;
static const char * const tracefs_known_mountpoints[] = {
TRACEFS_DEFAULT_PATH,
"/sys/kernel/debug/tracing",
"/tracing",
"/trace",
0,
};
static bool tracefs_found;
bool tracefs_configured(void)
{
return tracefs_find_mountpoint() != NULL;
}
/* find the path to the mounted tracefs */
const char *tracefs_find_mountpoint(void)
{
const char *ret;
if (tracefs_found)
return (const char *)tracefs_mountpoint;
ret = find_mountpoint("tracefs", (long) TRACEFS_MAGIC,
tracefs_mountpoint, PATH_MAX + 1,
tracefs_known_mountpoints);
if (ret)
tracefs_found = true;
return ret;
}
/* mount the tracefs somewhere if it's not mounted */
char *tracefs_mount(const char *mountpoint)
{
/* see if it's already mounted */
if (tracefs_find_mountpoint())
goto out;
/* if not mounted and no argument */
if (mountpoint == NULL) {
/* see if environment variable set */
mountpoint = getenv(PERF_TRACEFS_ENVIRONMENT);
/* if no environment variable, use default */
if (mountpoint == NULL)
mountpoint = TRACEFS_DEFAULT_PATH;
}
if (mount(NULL, mountpoint, "tracefs", 0, NULL) < 0)
return NULL;
/* save the mountpoint */
tracefs_found = true;
strncpy(tracefs_mountpoint, mountpoint, sizeof(tracefs_mountpoint));
out:
return tracefs_mountpoint;
}
#ifndef __API_TRACEFS_H__
#define __API_TRACEFS_H__
#include "findfs.h"
#ifndef TRACEFS_MAGIC
#define TRACEFS_MAGIC 0x74726163
#endif
#ifndef PERF_TRACEFS_ENVIRONMENT
#define PERF_TRACEFS_ENVIRONMENT "PERF_TRACEFS_DIR"
#endif
bool tracefs_configured(void);
const char *tracefs_find_mountpoint(void);
int tracefs_valid_mountpoint(const char *debugfs);
char *tracefs_mount(const char *mountpoint);
extern char tracefs_mountpoint[];
#endif /* __API_DEBUGFS_H__ */
liblockdep-y += common.o lockdep.o preload.o rbtree.o
...@@ -35,6 +35,10 @@ bindir = $(prefix)/$(bindir_relative) ...@@ -35,6 +35,10 @@ bindir = $(prefix)/$(bindir_relative)
export DESTDIR DESTDIR_SQ INSTALL export DESTDIR DESTDIR_SQ INSTALL
MAKEFLAGS += --no-print-directory
include ../../scripts/Makefile.include
# copy a bit from Linux kbuild # copy a bit from Linux kbuild
ifeq ("$(origin V)", "command line") ifeq ("$(origin V)", "command line")
...@@ -44,56 +48,21 @@ ifndef VERBOSE ...@@ -44,56 +48,21 @@ ifndef VERBOSE
VERBOSE = 0 VERBOSE = 0
endif endif
ifeq ("$(origin O)", "command line") ifeq ($(srctree),)
BUILD_OUTPUT := $(O) srctree := $(patsubst %/,%,$(dir $(shell pwd)))
srctree := $(patsubst %/,%,$(dir $(srctree)))
srctree := $(patsubst %/,%,$(dir $(srctree)))
#$(info Determined 'srctree' to be $(srctree))
endif endif
ifeq ($(BUILD_SRC),)
ifneq ($(BUILD_OUTPUT),)
define build_output
$(if $(VERBOSE:1=),@)$(MAKE) -C $(BUILD_OUTPUT) \
BUILD_SRC=$(CURDIR) -f $(CURDIR)/Makefile $1
endef
saved-output := $(BUILD_OUTPUT)
BUILD_OUTPUT := $(shell cd $(BUILD_OUTPUT) && /bin/pwd)
$(if $(BUILD_OUTPUT),, \
$(error output directory "$(saved-output)" does not exist))
all: sub-make
gui: force
$(call build_output, all_cmd)
$(filter-out gui,$(MAKECMDGOALS)): sub-make
sub-make: force
$(call build_output, $(MAKECMDGOALS))
# Leave processing to above invocation of make
skip-makefile := 1
endif # BUILD_OUTPUT
endif # BUILD_SRC
# We process the rest of the Makefile if this is the final invocation of make
ifeq ($(skip-makefile),)
srctree := $(realpath $(if $(BUILD_SRC),$(BUILD_SRC),$(CURDIR)))
objtree := $(realpath $(CURDIR))
src := $(srctree)
obj := $(objtree)
export prefix libdir bindir src obj
# Shell quotes # Shell quotes
libdir_SQ = $(subst ','\'',$(libdir)) libdir_SQ = $(subst ','\'',$(libdir))
bindir_SQ = $(subst ','\'',$(bindir)) bindir_SQ = $(subst ','\'',$(bindir))
LIB_FILE = liblockdep.a liblockdep.so.$(LIBLOCKDEP_VERSION) LIB_IN := $(OUTPUT)liblockdep-in.o
BIN_FILE = lockdep BIN_FILE = lockdep
LIB_FILE = $(OUTPUT)liblockdep.a $(OUTPUT)liblockdep.so.$(LIBLOCKDEP_VERSION)
CONFIG_INCLUDES = CONFIG_INCLUDES =
CONFIG_LIBS = CONFIG_LIBS =
...@@ -108,33 +77,23 @@ INCLUDES = -I. -I/usr/local/include -I./uinclude -I./include -I../../include $(C ...@@ -108,33 +77,23 @@ INCLUDES = -I. -I/usr/local/include -I./uinclude -I./include -I../../include $(C
# Set compile option CFLAGS if not set elsewhere # Set compile option CFLAGS if not set elsewhere
CFLAGS ?= -g -DCONFIG_LOCKDEP -DCONFIG_STACKTRACE -DCONFIG_PROVE_LOCKING -DBITS_PER_LONG=__WORDSIZE -DLIBLOCKDEP_VERSION='"$(LIBLOCKDEP_VERSION)"' -rdynamic -O0 -g CFLAGS ?= -g -DCONFIG_LOCKDEP -DCONFIG_STACKTRACE -DCONFIG_PROVE_LOCKING -DBITS_PER_LONG=__WORDSIZE -DLIBLOCKDEP_VERSION='"$(LIBLOCKDEP_VERSION)"' -rdynamic -O0 -g
CFLAGS += -fPIC
override CFLAGS += $(CONFIG_FLAGS) $(INCLUDES) $(PLUGIN_DIR_SQ) override CFLAGS += $(CONFIG_FLAGS) $(INCLUDES) $(PLUGIN_DIR_SQ)
ifeq ($(VERBOSE),1) ifeq ($(VERBOSE),1)
Q = Q =
print_compile =
print_app_build =
print_fpic_compile =
print_shared_lib_compile = print_shared_lib_compile =
print_install = print_install =
else else
Q = @ Q = @
print_compile = echo ' CC '$(OBJ); print_shared_lib_compile = echo ' LD '$(OBJ);
print_app_build = echo ' BUILD '$(OBJ); print_static_lib_build = echo ' LD '$(OBJ);
print_fpic_compile = echo ' CC FPIC '$(OBJ); print_install = echo ' INSTALL '$1' to $(DESTDIR_SQ)$2';
print_shared_lib_compile = echo ' BUILD SHARED LIB '$(OBJ);
print_static_lib_build = echo ' BUILD STATIC LIB '$(OBJ);
print_install = echo ' INSTALL '$1' to $(DESTDIR_SQ)$2';
endif endif
do_fpic_compile = \ export srctree OUTPUT CC LD CFLAGS V
($(print_fpic_compile) \ build := -f $(srctree)/tools/build/Makefile.build dir=. obj
$(CC) -c $(CFLAGS) $(EXT) -fPIC $< -o $@)
do_app_build = \
($(print_app_build) \
$(CC) $^ -rdynamic -o $@ $(CONFIG_LIBS) $(LIBS))
do_compile_shared_library = \ do_compile_shared_library = \
($(print_shared_lib_compile) \ ($(print_shared_lib_compile) \
...@@ -144,22 +103,6 @@ do_build_static_lib = \ ...@@ -144,22 +103,6 @@ do_build_static_lib = \
($(print_static_lib_build) \ ($(print_static_lib_build) \
$(RM) $@; $(AR) rcs $@ $^) $(RM) $@; $(AR) rcs $@ $^)
define do_compile
$(print_compile) \
$(CC) -c $(CFLAGS) $(EXT) $< -o $(obj)/$@;
endef
$(obj)/%.o: $(src)/%.c
$(Q)$(call do_compile)
%.o: $(src)/%.c
$(Q)$(call do_compile)
PEVENT_LIB_OBJS = common.o lockdep.o preload.o rbtree.o
ALL_OBJS = $(PEVENT_LIB_OBJS)
CMD_TARGETS = $(LIB_FILE) CMD_TARGETS = $(LIB_FILE)
TARGETS = $(CMD_TARGETS) TARGETS = $(CMD_TARGETS)
...@@ -169,42 +112,15 @@ all: all_cmd ...@@ -169,42 +112,15 @@ all: all_cmd
all_cmd: $(CMD_TARGETS) all_cmd: $(CMD_TARGETS)
liblockdep.so.$(LIBLOCKDEP_VERSION): $(PEVENT_LIB_OBJS) $(LIB_IN): force
$(Q)$(MAKE) $(build)=liblockdep
liblockdep.so.$(LIBLOCKDEP_VERSION): $(LIB_IN)
$(Q)$(do_compile_shared_library) $(Q)$(do_compile_shared_library)
liblockdep.a: $(PEVENT_LIB_OBJS) liblockdep.a: $(LIB_IN)
$(Q)$(do_build_static_lib) $(Q)$(do_build_static_lib)
$(PEVENT_LIB_OBJS): %.o: $(src)/%.c
$(Q)$(do_fpic_compile)
## make deps
all_objs := $(sort $(ALL_OBJS))
all_deps := $(all_objs:%.o=.%.d)
# let .d file also depends on the source and header files
define check_deps
@set -e; $(RM) $@; \
$(CC) -MM $(CFLAGS) $< > $@.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
$(RM) $@.$$$$
endef
$(all_deps): .%.d: $(src)/%.c
$(Q)$(call check_deps)
$(all_objs) : %.o : .%.d
dep_includes := $(wildcard $(all_deps))
ifneq ($(dep_includes),)
include $(dep_includes)
endif
### Detect environment changes
TRACK_CFLAGS = $(subst ','\'',$(CFLAGS)):$(ARCH):$(CROSS_COMPILE)
tags: force tags: force
$(RM) tags $(RM) tags
find . -name '*.[ch]' | xargs ctags --extra=+f --c-kinds=+px \ find . -name '*.[ch]' | xargs ctags --extra=+f --c-kinds=+px \
...@@ -233,8 +149,6 @@ clean: ...@@ -233,8 +149,6 @@ clean:
$(RM) *.o *~ $(TARGETS) *.a *liblockdep*.so* $(VERSION_FILES) .*.d $(RM) *.o *~ $(TARGETS) *.a *liblockdep*.so* $(VERSION_FILES) .*.d
$(RM) tags TAGS $(RM) tags TAGS
endif # skip-makefile
PHONY += force PHONY += force
force: force:
......
libtraceevent-y += event-parse.o
libtraceevent-y += event-plugin.o
libtraceevent-y += trace-seq.o
libtraceevent-y += parse-filter.o
libtraceevent-y += parse-utils.o
libtraceevent-y += kbuffer-parse.o
plugin_jbd2-y += plugin_jbd2.o
plugin_hrtimer-y += plugin_hrtimer.o
plugin_kmem-y += plugin_kmem.o
plugin_kvm-y += plugin_kvm.o
plugin_mac80211-y += plugin_mac80211.o
plugin_sched_switch-y += plugin_sched_switch.o
plugin_function-y += plugin_function.o
plugin_xen-y += plugin_xen.o
plugin_scsi-y += plugin_scsi.o
plugin_cfg80211-y += plugin_cfg80211.o
...@@ -67,7 +67,7 @@ PLUGIN_DIR = -DPLUGIN_DIR="$(plugin_dir)" ...@@ -67,7 +67,7 @@ PLUGIN_DIR = -DPLUGIN_DIR="$(plugin_dir)"
PLUGIN_DIR_SQ = '$(subst ','\'',$(PLUGIN_DIR))' PLUGIN_DIR_SQ = '$(subst ','\'',$(PLUGIN_DIR))'
endif endif
include $(if $(BUILD_SRC),$(BUILD_SRC)/)../../scripts/Makefile.include include ../../scripts/Makefile.include
# copy a bit from Linux kbuild # copy a bit from Linux kbuild
...@@ -78,40 +78,13 @@ ifndef VERBOSE ...@@ -78,40 +78,13 @@ ifndef VERBOSE
VERBOSE = 0 VERBOSE = 0
endif endif
ifeq ("$(origin O)", "command line") ifeq ($(srctree),)
BUILD_OUTPUT := $(O) srctree := $(patsubst %/,%,$(dir $(shell pwd)))
srctree := $(patsubst %/,%,$(dir $(srctree)))
srctree := $(patsubst %/,%,$(dir $(srctree)))
#$(info Determined 'srctree' to be $(srctree))
endif endif
ifeq ($(BUILD_SRC),)
ifneq ($(OUTPUT),)
define build_output
$(if $(VERBOSE:1=),@)+$(MAKE) -C $(OUTPUT) \
BUILD_SRC=$(CURDIR)/ -f $(CURDIR)/Makefile $1
endef
all: sub-make
$(MAKECMDGOALS): sub-make
sub-make: force
$(call build_output, $(MAKECMDGOALS))
# Leave processing to above invocation of make
skip-makefile := 1
endif # OUTPUT
endif # BUILD_SRC
# We process the rest of the Makefile if this is the final invocation of make
ifeq ($(skip-makefile),)
srctree := $(if $(BUILD_SRC),$(BUILD_SRC),$(CURDIR))
objtree := $(CURDIR)
src := $(srctree)
obj := $(objtree)
export prefix bindir src obj export prefix bindir src obj
# Shell quotes # Shell quotes
...@@ -132,16 +105,19 @@ EXTRAVERSION = $(EP_EXTRAVERSION) ...@@ -132,16 +105,19 @@ EXTRAVERSION = $(EP_EXTRAVERSION)
OBJ = $@ OBJ = $@
N = N =
export Q VERBOSE
EVENT_PARSE_VERSION = $(EP_VERSION).$(EP_PATCHLEVEL).$(EP_EXTRAVERSION) EVENT_PARSE_VERSION = $(EP_VERSION).$(EP_PATCHLEVEL).$(EP_EXTRAVERSION)
INCLUDES = -I. -I $(srctree)/../../include $(CONFIG_INCLUDES) INCLUDES = -I. -I $(srctree)/tools/include $(CONFIG_INCLUDES)
# Set compile option CFLAGS if not set elsewhere # Set compile option CFLAGS
CFLAGS ?= -g -Wall ifdef EXTRA_CFLAGS
CFLAGS := $(EXTRA_CFLAGS)
else
CFLAGS := -g -Wall
endif
# Append required CFLAGS # Append required CFLAGS
override CFLAGS += -fPIC
override CFLAGS += $(CONFIG_FLAGS) $(INCLUDES) $(PLUGIN_DIR_SQ) override CFLAGS += $(CONFIG_FLAGS) $(INCLUDES) $(PLUGIN_DIR_SQ)
override CFLAGS += $(udis86-flags) -D_GNU_SOURCE override CFLAGS += $(udis86-flags) -D_GNU_SOURCE
...@@ -151,74 +127,58 @@ else ...@@ -151,74 +127,58 @@ else
Q = @ Q = @
endif endif
do_compile_shared_library = \ # Disable command line variables (CFLAGS) overide from top
($(print_shared_lib_compile) \ # level Makefile (perf), otherwise build Makefile will get
$(CC) --shared $^ -o $@) # the same command line setup.
MAKEOVERRIDES=
do_plugin_build = \
($(print_plugin_build) \
$(CC) $(CFLAGS) -shared -nostartfiles -o $@ $<)
do_build_static_lib = \
($(print_static_lib_build) \
$(RM) $@; $(AR) rcs $@ $^)
do_compile = $(QUIET_CC)$(CC) -c $(CFLAGS) $(EXT) $< -o $(obj)/$@;
$(obj)/%.o: $(src)/%.c export srctree OUTPUT CC LD CFLAGS V
$(call do_compile) build := -f $(srctree)/tools/build/Makefile.build dir=. obj
%.o: $(src)/%.c PLUGINS = plugin_jbd2.so
$(call do_compile) PLUGINS += plugin_hrtimer.so
PLUGINS += plugin_kmem.so
PLUGINS += plugin_kvm.so
PLUGINS += plugin_mac80211.so
PLUGINS += plugin_sched_switch.so
PLUGINS += plugin_function.so
PLUGINS += plugin_xen.so
PLUGINS += plugin_scsi.so
PLUGINS += plugin_cfg80211.so
PEVENT_LIB_OBJS = event-parse.o PLUGINS := $(addprefix $(OUTPUT),$(PLUGINS))
PEVENT_LIB_OBJS += event-plugin.o PLUGINS_IN := $(PLUGINS:.so=-in.o)
PEVENT_LIB_OBJS += trace-seq.o
PEVENT_LIB_OBJS += parse-filter.o
PEVENT_LIB_OBJS += parse-utils.o
PEVENT_LIB_OBJS += kbuffer-parse.o
PLUGIN_OBJS = plugin_jbd2.o TE_IN := $(OUTPUT)libtraceevent-in.o
PLUGIN_OBJS += plugin_hrtimer.o LIB_FILE := $(addprefix $(OUTPUT),$(LIB_FILE))
PLUGIN_OBJS += plugin_kmem.o
PLUGIN_OBJS += plugin_kvm.o
PLUGIN_OBJS += plugin_mac80211.o
PLUGIN_OBJS += plugin_sched_switch.o
PLUGIN_OBJS += plugin_function.o
PLUGIN_OBJS += plugin_xen.o
PLUGIN_OBJS += plugin_scsi.o
PLUGIN_OBJS += plugin_cfg80211.o
PLUGINS := $(PLUGIN_OBJS:.o=.so)
ALL_OBJS = $(PEVENT_LIB_OBJS) $(PLUGIN_OBJS)
CMD_TARGETS = $(LIB_FILE) $(PLUGINS) CMD_TARGETS = $(LIB_FILE) $(PLUGINS)
TARGETS = $(CMD_TARGETS) TARGETS = $(CMD_TARGETS)
all: all_cmd all: all_cmd
all_cmd: $(CMD_TARGETS) all_cmd: $(CMD_TARGETS)
libtraceevent.so: $(PEVENT_LIB_OBJS) $(TE_IN): force
$(Q)$(MAKE) $(build)=libtraceevent
$(OUTPUT)libtraceevent.so: $(TE_IN)
$(QUIET_LINK)$(CC) --shared $^ -o $@ $(QUIET_LINK)$(CC) --shared $^ -o $@
libtraceevent.a: $(PEVENT_LIB_OBJS) $(OUTPUT)libtraceevent.a: $(TE_IN)
$(QUIET_LINK)$(RM) $@; $(AR) rcs $@ $^ $(QUIET_LINK)$(RM) $@; $(AR) rcs $@ $^
plugins: $(PLUGINS) plugins: $(PLUGINS)
$(PEVENT_LIB_OBJS): %.o: $(src)/%.c TRACEEVENT-CFLAGS __plugin_obj = $(notdir $@)
$(QUIET_CC_FPIC)$(CC) -c $(CFLAGS) $(EXT) -fPIC $< -o $@ plugin_obj = $(__plugin_obj:-in.o=)
$(PLUGIN_OBJS): %.o : $(src)/%.c $(PLUGINS_IN): force
$(QUIET_CC_FPIC)$(CC) -c $(CFLAGS) -fPIC -o $@ $< $(Q)$(MAKE) $(build)=$(plugin_obj)
$(PLUGINS): %.so: %.o $(OUTPUT)%.so: $(OUTPUT)%-in.o
$(QUIET_LINK)$(CC) $(CFLAGS) -shared -nostartfiles -o $@ $< $(QUIET_LINK)$(CC) $(CFLAGS) -shared -nostartfiles -o $@ $^
define make_version.h define make_version.h
(echo '/* This file is automatically generated. Do not modify. */'; \ (echo '/* This file is automatically generated. Do not modify. */'; \
...@@ -255,40 +215,6 @@ define update_dir ...@@ -255,40 +215,6 @@ define update_dir
fi); fi);
endef endef
## make deps
all_objs := $(sort $(ALL_OBJS))
all_deps := $(all_objs:%.o=.%.d)
# let .d file also depends on the source and header files
define check_deps
@set -e; $(RM) $@; \
$(CC) -MM $(CFLAGS) $< > $@.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
$(RM) $@.$$$$
endef
$(all_deps): .%.d: $(src)/%.c
$(Q)$(call check_deps)
$(all_objs) : %.o : .%.d
dep_includes := $(wildcard $(all_deps))
ifneq ($(dep_includes),)
include $(dep_includes)
endif
### Detect environment changes
TRACK_CFLAGS = $(subst ','\'',$(CFLAGS)):$(ARCH):$(CROSS_COMPILE)
TRACEEVENT-CFLAGS: force
@FLAGS='$(TRACK_CFLAGS)'; \
if test x"$$FLAGS" != x"`cat TRACEEVENT-CFLAGS 2>/dev/null`" ; then \
echo 1>&2 " FLAGS: * new build flags or cross compiler"; \
echo "$$FLAGS" >TRACEEVENT-CFLAGS; \
fi
tags: force tags: force
$(RM) tags $(RM) tags
find . -name '*.[ch]' | xargs ctags --extra=+f --c-kinds=+px \ find . -name '*.[ch]' | xargs ctags --extra=+f --c-kinds=+px \
...@@ -327,14 +253,9 @@ clean: ...@@ -327,14 +253,9 @@ clean:
$(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES) .*.d \ $(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES) .*.d \
$(RM) TRACEEVENT-CFLAGS tags TAGS $(RM) TRACEEVENT-CFLAGS tags TAGS
endif # skip-makefile
PHONY += force plugins PHONY += force plugins
force: force:
plugins:
@echo > /dev/null
# Declare the contents of the .PHONY variable as phony. We keep that # Declare the contents of the .PHONY variable as phony. We keep that
# information in a variable so we can use it in if_changed and friends. # information in a variable so we can use it in if_changed and friends.
.PHONY: $(PHONY) .PHONY: $(PHONY)
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h>
#include <regex.h> #include <regex.h>
#include <string.h> #include <string.h>
...@@ -91,6 +92,7 @@ extern int trace_seq_putc(struct trace_seq *s, unsigned char c); ...@@ -91,6 +92,7 @@ extern int trace_seq_putc(struct trace_seq *s, unsigned char c);
extern void trace_seq_terminate(struct trace_seq *s); extern void trace_seq_terminate(struct trace_seq *s);
extern int trace_seq_do_fprintf(struct trace_seq *s, FILE *fp);
extern int trace_seq_do_printf(struct trace_seq *s); extern int trace_seq_do_printf(struct trace_seq *s);
......
...@@ -231,19 +231,24 @@ void trace_seq_terminate(struct trace_seq *s) ...@@ -231,19 +231,24 @@ void trace_seq_terminate(struct trace_seq *s)
s->buffer[s->len] = 0; s->buffer[s->len] = 0;
} }
int trace_seq_do_printf(struct trace_seq *s) int trace_seq_do_fprintf(struct trace_seq *s, FILE *fp)
{ {
TRACE_SEQ_CHECK(s); TRACE_SEQ_CHECK(s);
switch (s->state) { switch (s->state) {
case TRACE_SEQ__GOOD: case TRACE_SEQ__GOOD:
return printf("%.*s", s->len, s->buffer); return fprintf(fp, "%.*s", s->len, s->buffer);
case TRACE_SEQ__BUFFER_POISONED: case TRACE_SEQ__BUFFER_POISONED:
puts("Usage of trace_seq after it was destroyed"); fprintf(fp, "%s\n", "Usage of trace_seq after it was destroyed");
break; break;
case TRACE_SEQ__MEM_ALLOC_FAILED: case TRACE_SEQ__MEM_ALLOC_FAILED:
puts("Can't allocate trace_seq buffer memory"); fprintf(fp, "%s\n", "Can't allocate trace_seq buffer memory");
break; break;
} }
return -1; return -1;
} }
int trace_seq_do_printf(struct trace_seq *s)
{
return trace_seq_do_fprintf(s, stdout);
}
perf-y += builtin-bench.o
perf-y += builtin-annotate.o
perf-y += builtin-diff.o
perf-y += builtin-evlist.o
perf-y += builtin-help.o
perf-y += builtin-sched.o
perf-y += builtin-buildid-list.o
perf-y += builtin-buildid-cache.o
perf-y += builtin-list.o
perf-y += builtin-record.o
perf-y += builtin-report.o
perf-y += builtin-stat.o
perf-y += builtin-timechart.o
perf-y += builtin-top.o
perf-y += builtin-script.o
perf-y += builtin-kmem.o
perf-y += builtin-lock.o
perf-y += builtin-kvm.o
perf-y += builtin-inject.o
perf-y += builtin-mem.o
perf-$(CONFIG_AUDIT) += builtin-trace.o
perf-$(CONFIG_LIBELF) += builtin-probe.o
perf-y += bench/
perf-y += tests/
perf-y += perf.o
paths += -DPERF_HTML_PATH="BUILD_STR($(htmldir_SQ))"
paths += -DPERF_INFO_PATH="BUILD_STR($(infodir_SQ))"
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
libperf-y += util/
libperf-y += arch/
libperf-y += ui/
libperf-y += scripts/
gtk-y += ui/gtk/
1) perf build
=============
The perf build process consists of several separated building blocks,
which are linked together to form the perf binary:
- libperf library (static)
- perf builtin commands
- traceevent library (static)
- GTK ui library
Several makefiles govern the perf build:
- Makefile
top level Makefile working as a wrapper that calls the main
Makefile.perf with a -j option to do parallel builds.
- Makefile.perf
main makefile that triggers build of all perf objects including
installation and documentation processing.
- tools/build/Makefile.build
main makefile of the build framework
- tools/build/Build.include
build framework generic definitions
- Build makefiles
makefiles that defines build objects
Please refer to tools/build/Documentation/Build.txt for more
information about build framework.
2) perf build
=============
The Makefile.perf triggers the build framework for build objects:
perf, libperf, gtk
resulting in following objects:
$ ls *-in.o
gtk-in.o libperf-in.o perf-in.o
Those objects are then used in final linking:
libperf-gtk.so <- gtk-in.o libperf-in.o
perf <- perf-in.o libperf-in.o
NOTE this description is omitting other libraries involved, only
focusing on build framework outcomes
...@@ -47,6 +47,12 @@ OPTIONS ...@@ -47,6 +47,12 @@ OPTIONS
-v:: -v::
--verbose:: --verbose::
Be more verbose (show parsed arguments, etc). Be more verbose (show parsed arguments, etc).
Can not use with -q.
-q::
--quiet::
Be quiet (do not show any messages including errors).
Can not use with -v.
-a:: -a::
--add=:: --add=::
...@@ -96,7 +102,7 @@ OPTIONS ...@@ -96,7 +102,7 @@ OPTIONS
Dry run. With this option, --add and --del doesn't execute actual Dry run. With this option, --add and --del doesn't execute actual
adding and removal operations. adding and removal operations.
--max-probes:: --max-probes=NUM::
Set the maximum number of probe points for an event. Default is 128. Set the maximum number of probe points for an event. Default is 128.
-x:: -x::
...@@ -104,8 +110,13 @@ OPTIONS ...@@ -104,8 +110,13 @@ OPTIONS
Specify path to the executable or shared library file for user Specify path to the executable or shared library file for user
space tracing. Can also be used with --funcs option. space tracing. Can also be used with --funcs option.
--demangle::
Demangle application symbols. --no-demangle is also available
for disabling demangling.
--demangle-kernel:: --demangle-kernel::
Demangle kernel symbols. Demangle kernel symbols. --no-demangle-kernel is also available
for disabling kernel demangling.
In absence of -m/-x options, perf probe checks if the first argument after In absence of -m/-x options, perf probe checks if the first argument after
the options is an absolute path name. If its an absolute path, perf probe the options is an absolute path name. If its an absolute path, perf probe
...@@ -137,6 +148,7 @@ Each probe argument follows below syntax. ...@@ -137,6 +148,7 @@ Each probe argument follows below syntax.
[NAME=]LOCALVAR|$retval|%REG|@SYMBOL[:TYPE] [NAME=]LOCALVAR|$retval|%REG|@SYMBOL[:TYPE]
'NAME' specifies the name of this argument (optional). You can use the name of local variable, local data structure member (e.g. var->field, var.field2), local array with fixed index (e.g. array[1], var->array[0], var->pointer[2]), or kprobe-tracer argument format (e.g. $retval, %ax, etc). Note that the name of this argument will be set as the last member name if you specify a local data structure member (e.g. field2 for 'var->field1.field2'.) 'NAME' specifies the name of this argument (optional). You can use the name of local variable, local data structure member (e.g. var->field, var.field2), local array with fixed index (e.g. array[1], var->array[0], var->pointer[2]), or kprobe-tracer argument format (e.g. $retval, %ax, etc). Note that the name of this argument will be set as the last member name if you specify a local data structure member (e.g. field2 for 'var->field1.field2'.)
'$vars' special argument is also available for NAME, it is expanded to the local variables which can access at given probe point.
'TYPE' casts the type of this argument (optional). If omitted, perf probe automatically set the type based on debuginfo. You can specify 'string' type only for the local variable or structure member which is an array of or a pointer to 'char' or 'unsigned char' type. 'TYPE' casts the type of this argument (optional). If omitted, perf probe automatically set the type based on debuginfo. You can specify 'string' type only for the local variable or structure member which is an array of or a pointer to 'char' or 'unsigned char' type.
On x86 systems %REG is always the short form of the register: for example %AX. %RAX or %EAX is not valid. On x86 systems %REG is always the short form of the register: for example %AX. %RAX or %EAX is not valid.
......
tools/perf tools/perf
tools/scripts tools/scripts
tools/build
tools/lib/traceevent tools/lib/traceevent
tools/lib/api tools/lib/api
tools/lib/symbol/kallsyms.c tools/lib/symbol/kallsyms.c
......
This diff is collapsed.
libperf-y += common.o
libperf-y += $(ARCH)/
libperf-y += util/
libperf-$(CONFIG_DWARF_UNWIND) += tests/
ifndef NO_DWARF ifndef NO_DWARF
PERF_HAVE_DWARF_REGS := 1 PERF_HAVE_DWARF_REGS := 1
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
endif
ifndef NO_LIBUNWIND
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind-libunwind.o
endif
ifndef NO_LIBDW_DWARF_UNWIND
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind-libdw.o
endif
ifndef NO_DWARF_UNWIND
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/tests/regs_load.o
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/tests/dwarf-unwind.o
endif endif
libperf-y += regs_load.o
libperf-y += dwarf-unwind.o
libperf-$(CONFIG_DWARF) += dwarf-regs.o
libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o
libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
ifndef NO_DWARF ifndef NO_DWARF
PERF_HAVE_DWARF_REGS := 1 PERF_HAVE_DWARF_REGS := 1
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
endif
ifndef NO_LIBUNWIND
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind-libunwind.o
endif endif
libperf-$(CONFIG_DWARF) += dwarf-regs.o
libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o
ifndef NO_DWARF ifndef NO_DWARF
PERF_HAVE_DWARF_REGS := 1 PERF_HAVE_DWARF_REGS := 1
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/skip-callchain-idx.o
endif endif
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o
libperf-y += header.o
libperf-$(CONFIG_DWARF) += dwarf-regs.o
libperf-$(CONFIG_DWARF) += skip-callchain-idx.o
ifndef NO_DWARF ifndef NO_DWARF
PERF_HAVE_DWARF_REGS := 1 PERF_HAVE_DWARF_REGS := 1
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
endif endif
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o
HAVE_KVM_STAT_SUPPORT := 1 HAVE_KVM_STAT_SUPPORT := 1
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/kvm-stat.o
libperf-y += header.o
libperf-y += kvm-stat.o
libperf-$(CONFIG_DWARF) += dwarf-regs.o
libperf-y += util/
ifndef NO_DWARF ifndef NO_DWARF
PERF_HAVE_DWARF_REGS := 1 PERF_HAVE_DWARF_REGS := 1
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
endif endif
libperf-$(CONFIG_DWARF) += dwarf-regs.o
ifndef NO_DWARF ifndef NO_DWARF
PERF_HAVE_DWARF_REGS := 1 PERF_HAVE_DWARF_REGS := 1
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
endif endif
libperf-$(CONFIG_DWARF) += dwarf-regs.o
libperf-y += util/
libperf-$(CONFIG_DWARF_UNWIND) += tests/
ifndef NO_DWARF ifndef NO_DWARF
PERF_HAVE_DWARF_REGS := 1 PERF_HAVE_DWARF_REGS := 1
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
endif endif
ifndef NO_LIBUNWIND
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind-libunwind.o
endif
ifndef NO_LIBDW_DWARF_UNWIND
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind-libdw.o
endif
ifndef NO_DWARF_UNWIND
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/tests/regs_load.o
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/tests/dwarf-unwind.o
endif
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/tsc.o
LIB_H += arch/$(ARCH)/util/tsc.h
HAVE_KVM_STAT_SUPPORT := 1 HAVE_KVM_STAT_SUPPORT := 1
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/kvm-stat.o
libperf-y += regs_load.o
libperf-y += dwarf-unwind.o
libperf-y += header.o
libperf-y += tsc.o
libperf-y += kvm-stat.o
libperf-$(CONFIG_DWARF) += dwarf-regs.o
libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o
libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
perf-y += sched-messaging.o
perf-y += sched-pipe.o
perf-y += mem-memcpy.o
perf-y += futex-hash.o
perf-y += futex-wake.o
perf-y += futex-requeue.o
perf-$(CONFIG_X86_64) += mem-memcpy-x86-64-asm.o
perf-$(CONFIG_X86_64) += mem-memset-x86-64-asm.o
perf-$(CONFIG_NUMA) += numa.o
...@@ -125,8 +125,7 @@ static int build_id_cache__kcore_existing(const char *from_dir, char *to_dir, ...@@ -125,8 +125,7 @@ static int build_id_cache__kcore_existing(const char *from_dir, char *to_dir,
return ret; return ret;
} }
static int build_id_cache__add_kcore(const char *filename, const char *debugdir, static int build_id_cache__add_kcore(const char *filename, bool force)
bool force)
{ {
char dir[32], sbuildid[BUILD_ID_SIZE * 2 + 1]; char dir[32], sbuildid[BUILD_ID_SIZE * 2 + 1];
char from_dir[PATH_MAX], to_dir[PATH_MAX]; char from_dir[PATH_MAX], to_dir[PATH_MAX];
...@@ -143,7 +142,7 @@ static int build_id_cache__add_kcore(const char *filename, const char *debugdir, ...@@ -143,7 +142,7 @@ static int build_id_cache__add_kcore(const char *filename, const char *debugdir,
return -1; return -1;
scnprintf(to_dir, sizeof(to_dir), "%s/[kernel.kcore]/%s", scnprintf(to_dir, sizeof(to_dir), "%s/[kernel.kcore]/%s",
debugdir, sbuildid); buildid_dir, sbuildid);
if (!force && if (!force &&
!build_id_cache__kcore_existing(from_dir, to_dir, sizeof(to_dir))) { !build_id_cache__kcore_existing(from_dir, to_dir, sizeof(to_dir))) {
...@@ -155,7 +154,7 @@ static int build_id_cache__add_kcore(const char *filename, const char *debugdir, ...@@ -155,7 +154,7 @@ static int build_id_cache__add_kcore(const char *filename, const char *debugdir,
return -1; return -1;
scnprintf(to_dir, sizeof(to_dir), "%s/[kernel.kcore]/%s/%s", scnprintf(to_dir, sizeof(to_dir), "%s/[kernel.kcore]/%s/%s",
debugdir, sbuildid, dir); buildid_dir, sbuildid, dir);
if (mkdir_p(to_dir, 0755)) if (mkdir_p(to_dir, 0755))
return -1; return -1;
...@@ -183,7 +182,7 @@ static int build_id_cache__add_kcore(const char *filename, const char *debugdir, ...@@ -183,7 +182,7 @@ static int build_id_cache__add_kcore(const char *filename, const char *debugdir,
return 0; return 0;
} }
static int build_id_cache__add_file(const char *filename, const char *debugdir) static int build_id_cache__add_file(const char *filename)
{ {
char sbuild_id[BUILD_ID_SIZE * 2 + 1]; char sbuild_id[BUILD_ID_SIZE * 2 + 1];
u8 build_id[BUILD_ID_SIZE]; u8 build_id[BUILD_ID_SIZE];
...@@ -195,7 +194,7 @@ static int build_id_cache__add_file(const char *filename, const char *debugdir) ...@@ -195,7 +194,7 @@ static int build_id_cache__add_file(const char *filename, const char *debugdir)
} }
build_id__sprintf(build_id, sizeof(build_id), sbuild_id); build_id__sprintf(build_id, sizeof(build_id), sbuild_id);
err = build_id_cache__add_s(sbuild_id, debugdir, filename, err = build_id_cache__add_s(sbuild_id, filename,
false, false); false, false);
if (verbose) if (verbose)
pr_info("Adding %s %s: %s\n", sbuild_id, filename, pr_info("Adding %s %s: %s\n", sbuild_id, filename,
...@@ -203,8 +202,7 @@ static int build_id_cache__add_file(const char *filename, const char *debugdir) ...@@ -203,8 +202,7 @@ static int build_id_cache__add_file(const char *filename, const char *debugdir)
return err; return err;
} }
static int build_id_cache__remove_file(const char *filename, static int build_id_cache__remove_file(const char *filename)
const char *debugdir)
{ {
u8 build_id[BUILD_ID_SIZE]; u8 build_id[BUILD_ID_SIZE];
char sbuild_id[BUILD_ID_SIZE * 2 + 1]; char sbuild_id[BUILD_ID_SIZE * 2 + 1];
...@@ -217,7 +215,7 @@ static int build_id_cache__remove_file(const char *filename, ...@@ -217,7 +215,7 @@ static int build_id_cache__remove_file(const char *filename,
} }
build_id__sprintf(build_id, sizeof(build_id), sbuild_id); build_id__sprintf(build_id, sizeof(build_id), sbuild_id);
err = build_id_cache__remove_s(sbuild_id, debugdir); err = build_id_cache__remove_s(sbuild_id);
if (verbose) if (verbose)
pr_info("Removing %s %s: %s\n", sbuild_id, filename, pr_info("Removing %s %s: %s\n", sbuild_id, filename,
err ? "FAIL" : "Ok"); err ? "FAIL" : "Ok");
...@@ -252,8 +250,7 @@ static int build_id_cache__fprintf_missing(struct perf_session *session, FILE *f ...@@ -252,8 +250,7 @@ static int build_id_cache__fprintf_missing(struct perf_session *session, FILE *f
return 0; return 0;
} }
static int build_id_cache__update_file(const char *filename, static int build_id_cache__update_file(const char *filename)
const char *debugdir)
{ {
u8 build_id[BUILD_ID_SIZE]; u8 build_id[BUILD_ID_SIZE];
char sbuild_id[BUILD_ID_SIZE * 2 + 1]; char sbuild_id[BUILD_ID_SIZE * 2 + 1];
...@@ -266,11 +263,10 @@ static int build_id_cache__update_file(const char *filename, ...@@ -266,11 +263,10 @@ static int build_id_cache__update_file(const char *filename,
} }
build_id__sprintf(build_id, sizeof(build_id), sbuild_id); build_id__sprintf(build_id, sizeof(build_id), sbuild_id);
err = build_id_cache__remove_s(sbuild_id, debugdir); err = build_id_cache__remove_s(sbuild_id);
if (!err) { if (!err)
err = build_id_cache__add_s(sbuild_id, debugdir, filename, err = build_id_cache__add_s(sbuild_id, filename, false, false);
false, false);
}
if (verbose) if (verbose)
pr_info("Updating %s %s: %s\n", sbuild_id, filename, pr_info("Updating %s %s: %s\n", sbuild_id, filename,
err ? "FAIL" : "Ok"); err ? "FAIL" : "Ok");
...@@ -338,7 +334,7 @@ int cmd_buildid_cache(int argc, const char **argv, ...@@ -338,7 +334,7 @@ int cmd_buildid_cache(int argc, const char **argv,
list = strlist__new(true, add_name_list_str); list = strlist__new(true, add_name_list_str);
if (list) { if (list) {
strlist__for_each(pos, list) strlist__for_each(pos, list)
if (build_id_cache__add_file(pos->s, buildid_dir)) { if (build_id_cache__add_file(pos->s)) {
if (errno == EEXIST) { if (errno == EEXIST) {
pr_debug("%s already in the cache\n", pr_debug("%s already in the cache\n",
pos->s); pos->s);
...@@ -356,7 +352,7 @@ int cmd_buildid_cache(int argc, const char **argv, ...@@ -356,7 +352,7 @@ int cmd_buildid_cache(int argc, const char **argv,
list = strlist__new(true, remove_name_list_str); list = strlist__new(true, remove_name_list_str);
if (list) { if (list) {
strlist__for_each(pos, list) strlist__for_each(pos, list)
if (build_id_cache__remove_file(pos->s, buildid_dir)) { if (build_id_cache__remove_file(pos->s)) {
if (errno == ENOENT) { if (errno == ENOENT) {
pr_debug("%s wasn't in the cache\n", pr_debug("%s wasn't in the cache\n",
pos->s); pos->s);
...@@ -377,7 +373,7 @@ int cmd_buildid_cache(int argc, const char **argv, ...@@ -377,7 +373,7 @@ int cmd_buildid_cache(int argc, const char **argv,
list = strlist__new(true, update_name_list_str); list = strlist__new(true, update_name_list_str);
if (list) { if (list) {
strlist__for_each(pos, list) strlist__for_each(pos, list)
if (build_id_cache__update_file(pos->s, buildid_dir)) { if (build_id_cache__update_file(pos->s)) {
if (errno == ENOENT) { if (errno == ENOENT) {
pr_debug("%s wasn't in the cache\n", pr_debug("%s wasn't in the cache\n",
pos->s); pos->s);
...@@ -391,8 +387,7 @@ int cmd_buildid_cache(int argc, const char **argv, ...@@ -391,8 +387,7 @@ int cmd_buildid_cache(int argc, const char **argv,
} }
} }
if (kcore_filename && if (kcore_filename && build_id_cache__add_kcore(kcore_filename, force))
build_id_cache__add_kcore(kcore_filename, buildid_dir, force))
pr_warning("Couldn't add %s\n", kcore_filename); pr_warning("Couldn't add %s\n", kcore_filename);
out: out:
......
...@@ -41,6 +41,9 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused) ...@@ -41,6 +41,9 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
return 0; return 0;
} }
if (!raw_dump)
printf("\nList of pre-defined events (to be used in -e):\n\n");
if (argc == 0) { if (argc == 0) {
print_events(NULL, false); print_events(NULL, false);
return 0; return 0;
......
...@@ -1219,7 +1219,9 @@ struct trace { ...@@ -1219,7 +1219,9 @@ struct trace {
struct syscall *table; struct syscall *table;
} syscalls; } syscalls;
struct record_opts opts; struct record_opts opts;
struct perf_evlist *evlist;
struct machine *host; struct machine *host;
struct thread *current;
u64 base_time; u64 base_time;
FILE *output; FILE *output;
unsigned long nr_events; unsigned long nr_events;
...@@ -1642,6 +1644,29 @@ static void thread__update_stats(struct thread_trace *ttrace, ...@@ -1642,6 +1644,29 @@ static void thread__update_stats(struct thread_trace *ttrace,
update_stats(stats, duration); update_stats(stats, duration);
} }
static int trace__printf_interrupted_entry(struct trace *trace, struct perf_sample *sample)
{
struct thread_trace *ttrace;
u64 duration;
size_t printed;
if (trace->current == NULL)
return 0;
ttrace = thread__priv(trace->current);
if (!ttrace->entry_pending)
return 0;
duration = sample->time - ttrace->entry_time;
printed = trace__fprintf_entry_head(trace, trace->current, duration, sample->time, trace->output);
printed += fprintf(trace->output, "%-70s) ...\n", ttrace->entry_str);
ttrace->entry_pending = false;
return printed;
}
static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel, static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
union perf_event *event __maybe_unused, union perf_event *event __maybe_unused,
struct perf_sample *sample) struct perf_sample *sample)
...@@ -1673,6 +1698,8 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel, ...@@ -1673,6 +1698,8 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
return -1; return -1;
} }
printed += trace__printf_interrupted_entry(trace, sample);
ttrace->entry_time = sample->time; ttrace->entry_time = sample->time;
msg = ttrace->entry_str; msg = ttrace->entry_str;
printed += scnprintf(msg + printed, 1024 - printed, "%s(", sc->name); printed += scnprintf(msg + printed, 1024 - printed, "%s(", sc->name);
...@@ -1688,6 +1715,8 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel, ...@@ -1688,6 +1715,8 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
} else } else
ttrace->entry_pending = true; ttrace->entry_pending = true;
trace->current = thread;
return 0; return 0;
} }
...@@ -1805,6 +1834,24 @@ static int trace__sched_stat_runtime(struct trace *trace, struct perf_evsel *evs ...@@ -1805,6 +1834,24 @@ static int trace__sched_stat_runtime(struct trace *trace, struct perf_evsel *evs
return 0; return 0;
} }
static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
union perf_event *event __maybe_unused,
struct perf_sample *sample)
{
trace__printf_interrupted_entry(trace, sample);
trace__fprintf_tstamp(trace, sample->time, trace->output);
fprintf(trace->output, "(%9.9s): %s:", " ", evsel->name);
if (evsel->tp_format) {
event_format__fprintf(evsel->tp_format, sample->cpu,
sample->raw_data, sample->raw_size,
trace->output);
}
fprintf(trace->output, ")\n");
return 0;
}
static void print_location(FILE *f, struct perf_sample *sample, static void print_location(FILE *f, struct perf_sample *sample,
struct addr_location *al, struct addr_location *al,
bool print_dso, bool print_sym) bool print_dso, bool print_sym)
...@@ -2039,7 +2086,7 @@ static int perf_evlist__add_pgfault(struct perf_evlist *evlist, ...@@ -2039,7 +2086,7 @@ static int perf_evlist__add_pgfault(struct perf_evlist *evlist,
static int trace__run(struct trace *trace, int argc, const char **argv) static int trace__run(struct trace *trace, int argc, const char **argv)
{ {
struct perf_evlist *evlist = perf_evlist__new(); struct perf_evlist *evlist = trace->evlist;
struct perf_evsel *evsel; struct perf_evsel *evsel;
int err = -1, i; int err = -1, i;
unsigned long before; unsigned long before;
...@@ -2048,11 +2095,6 @@ static int trace__run(struct trace *trace, int argc, const char **argv) ...@@ -2048,11 +2095,6 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
trace->live = true; trace->live = true;
if (evlist == NULL) {
fprintf(trace->output, "Not enough memory to run!\n");
goto out;
}
if (trace->trace_syscalls && if (trace->trace_syscalls &&
perf_evlist__add_syscall_newtp(evlist, trace__sys_enter, perf_evlist__add_syscall_newtp(evlist, trace__sys_enter,
trace__sys_exit)) trace__sys_exit))
...@@ -2109,12 +2151,14 @@ static int trace__run(struct trace *trace, int argc, const char **argv) ...@@ -2109,12 +2151,14 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
if (err < 0) if (err < 0)
goto out_error_mmap; goto out_error_mmap;
perf_evlist__enable(evlist);
if (forks) if (forks)
perf_evlist__start_workload(evlist); perf_evlist__start_workload(evlist);
else
perf_evlist__enable(evlist);
trace->multiple_threads = evlist->threads->map[0] == -1 || evlist->threads->nr > 1; trace->multiple_threads = evlist->threads->map[0] == -1 ||
evlist->threads->nr > 1 ||
perf_evlist__first(evlist)->attr.inherit;
again: again:
before = trace->nr_events; before = trace->nr_events;
...@@ -2197,7 +2241,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv) ...@@ -2197,7 +2241,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
out_delete_evlist: out_delete_evlist:
perf_evlist__delete(evlist); perf_evlist__delete(evlist);
out: trace->evlist = NULL;
trace->live = false; trace->live = false;
return err; return err;
{ {
...@@ -2468,6 +2512,14 @@ static int parse_pagefaults(const struct option *opt, const char *str, ...@@ -2468,6 +2512,14 @@ static int parse_pagefaults(const struct option *opt, const char *str,
return 0; return 0;
} }
static void evlist__set_evsel_handler(struct perf_evlist *evlist, void *handler)
{
struct perf_evsel *evsel;
evlist__for_each(evlist, evsel)
evsel->handler = handler;
}
int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
{ {
const char * const trace_usage[] = { const char * const trace_usage[] = {
...@@ -2502,6 +2554,9 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) ...@@ -2502,6 +2554,9 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
const char *output_name = NULL; const char *output_name = NULL;
const char *ev_qualifier_str = NULL; const char *ev_qualifier_str = NULL;
const struct option trace_options[] = { const struct option trace_options[] = {
OPT_CALLBACK(0, "event", &trace.evlist, "event",
"event selector. use 'perf list' to list available events",
parse_events_option),
OPT_BOOLEAN(0, "comm", &trace.show_comm, OPT_BOOLEAN(0, "comm", &trace.show_comm,
"show the thread COMM next to its id"), "show the thread COMM next to its id"),
OPT_BOOLEAN(0, "tool_stats", &trace.show_tool_stats, "show tool stats"), OPT_BOOLEAN(0, "tool_stats", &trace.show_tool_stats, "show tool stats"),
...@@ -2543,6 +2598,15 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) ...@@ -2543,6 +2598,15 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
int err; int err;
char bf[BUFSIZ]; char bf[BUFSIZ];
trace.evlist = perf_evlist__new();
if (trace.evlist == NULL)
return -ENOMEM;
if (trace.evlist == NULL) {
pr_err("Not enough memory to run!\n");
goto out;
}
argc = parse_options(argc, argv, trace_options, trace_usage, argc = parse_options(argc, argv, trace_options, trace_usage,
PARSE_OPT_STOP_AT_NON_OPTION); PARSE_OPT_STOP_AT_NON_OPTION);
...@@ -2551,6 +2615,9 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) ...@@ -2551,6 +2615,9 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
trace.opts.sample_time = true; trace.opts.sample_time = true;
} }
if (trace.evlist->nr_entries > 0)
evlist__set_evsel_handler(trace.evlist, trace__event_handler);
if ((argc >= 1) && (strcmp(argv[0], "record") == 0)) if ((argc >= 1) && (strcmp(argv[0], "record") == 0))
return trace__record(&trace, argc-1, &argv[1]); return trace__record(&trace, argc-1, &argv[1]);
...@@ -2558,7 +2625,8 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) ...@@ -2558,7 +2625,8 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
if (trace.summary_only) if (trace.summary_only)
trace.summary = trace.summary_only; trace.summary = trace.summary_only;
if (!trace.trace_syscalls && !trace.trace_pgfaults) { if (!trace.trace_syscalls && !trace.trace_pgfaults &&
trace.evlist->nr_entries == 0 /* Was --events used? */) {
pr_err("Please specify something to trace.\n"); pr_err("Please specify something to trace.\n");
return -1; return -1;
} }
......
...@@ -11,19 +11,27 @@ ifneq ($(obj-perf),) ...@@ -11,19 +11,27 @@ ifneq ($(obj-perf),)
obj-perf := $(abspath $(obj-perf))/ obj-perf := $(abspath $(obj-perf))/
endif endif
$(shell echo -n > .config-detected)
detected = $(shell echo "$(1)=y" >> .config-detected)
detected_var = $(shell echo "$(1)=$($(1))" >> .config-detected)
LIB_INCLUDE := $(srctree)/tools/lib/ LIB_INCLUDE := $(srctree)/tools/lib/
CFLAGS := $(EXTRA_CFLAGS) $(EXTRA_WARNINGS) CFLAGS := $(EXTRA_CFLAGS) $(EXTRA_WARNINGS)
include $(src-perf)/config/Makefile.arch include $(src-perf)/config/Makefile.arch
$(call detected_var,ARCH)
NO_PERF_REGS := 1 NO_PERF_REGS := 1
# Additional ARCH settings for x86 # Additional ARCH settings for x86
ifeq ($(ARCH),x86) ifeq ($(ARCH),x86)
$(call detected,CONFIG_X86)
ifeq (${IS_64_BIT}, 1) ifeq (${IS_64_BIT}, 1)
CFLAGS += -DHAVE_ARCH_X86_64_SUPPORT CFLAGS += -DHAVE_ARCH_X86_64_SUPPORT
ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memset_64.S ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memset_64.S
LIBUNWIND_LIBS = -lunwind -lunwind-x86_64 LIBUNWIND_LIBS = -lunwind -lunwind-x86_64
$(call detected,CONFIG_X86_64)
else else
LIBUNWIND_LIBS = -lunwind -lunwind-x86 LIBUNWIND_LIBS = -lunwind -lunwind-x86
endif endif
...@@ -40,6 +48,10 @@ ifeq ($(ARCH),arm64) ...@@ -40,6 +48,10 @@ ifeq ($(ARCH),arm64)
LIBUNWIND_LIBS = -lunwind -lunwind-aarch64 LIBUNWIND_LIBS = -lunwind -lunwind-aarch64
endif endif
ifeq ($(NO_PERF_REGS),0)
$(call detected,CONFIG_PERF_REGS)
endif
# So far there's only x86 and arm libdw unwind support merged in perf. # So far there's only x86 and arm libdw unwind support merged in perf.
# Disable it on all other architectures in case libdw unwind # Disable it on all other architectures in case libdw unwind
# support is detected in system. Add supported architectures # support is detected in system. Add supported architectures
...@@ -114,6 +126,8 @@ ifdef PARSER_DEBUG ...@@ -114,6 +126,8 @@ ifdef PARSER_DEBUG
PARSER_DEBUG_BISON := -t PARSER_DEBUG_BISON := -t
PARSER_DEBUG_FLEX := -d PARSER_DEBUG_FLEX := -d
CFLAGS += -DPARSER_DEBUG CFLAGS += -DPARSER_DEBUG
$(call detected_var,PARSER_DEBUG_BISON)
$(call detected_var,PARSER_DEBUG_FLEX)
endif endif
ifndef NO_LIBPYTHON ifndef NO_LIBPYTHON
...@@ -361,6 +375,7 @@ endif # NO_LIBELF ...@@ -361,6 +375,7 @@ endif # NO_LIBELF
ifndef NO_LIBELF ifndef NO_LIBELF
CFLAGS += -DHAVE_LIBELF_SUPPORT CFLAGS += -DHAVE_LIBELF_SUPPORT
EXTLIBS += -lelf EXTLIBS += -lelf
$(call detected,CONFIG_LIBELF)
ifeq ($(feature-libelf-mmap), 1) ifeq ($(feature-libelf-mmap), 1)
CFLAGS += -DHAVE_LIBELF_MMAP_SUPPORT CFLAGS += -DHAVE_LIBELF_MMAP_SUPPORT
...@@ -381,6 +396,7 @@ ifndef NO_LIBELF ...@@ -381,6 +396,7 @@ ifndef NO_LIBELF
CFLAGS += -DHAVE_DWARF_SUPPORT $(LIBDW_CFLAGS) CFLAGS += -DHAVE_DWARF_SUPPORT $(LIBDW_CFLAGS)
LDFLAGS += $(LIBDW_LDFLAGS) LDFLAGS += $(LIBDW_LDFLAGS)
EXTLIBS += -ldw EXTLIBS += -ldw
$(call detected,CONFIG_DWARF)
endif # PERF_HAVE_DWARF_REGS endif # PERF_HAVE_DWARF_REGS
endif # NO_DWARF endif # NO_DWARF
endif # NO_LIBELF endif # NO_LIBELF
...@@ -408,9 +424,11 @@ ifdef NO_LIBUNWIND ...@@ -408,9 +424,11 @@ ifdef NO_LIBUNWIND
dwarf-post-unwind := 0 dwarf-post-unwind := 0
else else
dwarf-post-unwind-text := libdw dwarf-post-unwind-text := libdw
$(call detected,CONFIG_LIBDW_DWARF_UNWIND)
endif endif
else else
dwarf-post-unwind-text := libunwind dwarf-post-unwind-text := libunwind
$(call detected,CONFIG_LIBUNWIND)
# Enable libunwind support by default. # Enable libunwind support by default.
ifndef NO_LIBDW_DWARF_UNWIND ifndef NO_LIBDW_DWARF_UNWIND
NO_LIBDW_DWARF_UNWIND := 1 NO_LIBDW_DWARF_UNWIND := 1
...@@ -419,6 +437,7 @@ endif ...@@ -419,6 +437,7 @@ endif
ifeq ($(dwarf-post-unwind),1) ifeq ($(dwarf-post-unwind),1)
CFLAGS += -DHAVE_DWARF_UNWIND_SUPPORT CFLAGS += -DHAVE_DWARF_UNWIND_SUPPORT
$(call detected,CONFIG_DWARF_UNWIND)
else else
NO_DWARF_UNWIND := 1 NO_DWARF_UNWIND := 1
endif endif
...@@ -447,6 +466,7 @@ ifndef NO_LIBAUDIT ...@@ -447,6 +466,7 @@ ifndef NO_LIBAUDIT
else else
CFLAGS += -DHAVE_LIBAUDIT_SUPPORT CFLAGS += -DHAVE_LIBAUDIT_SUPPORT
EXTLIBS += -laudit EXTLIBS += -laudit
$(call detected,CONFIG_AUDIT)
endif endif
endif endif
...@@ -463,6 +483,7 @@ ifndef NO_SLANG ...@@ -463,6 +483,7 @@ ifndef NO_SLANG
CFLAGS += -I/usr/include/slang CFLAGS += -I/usr/include/slang
CFLAGS += -DHAVE_SLANG_SUPPORT CFLAGS += -DHAVE_SLANG_SUPPORT
EXTLIBS += -lslang EXTLIBS += -lslang
$(call detected,CONFIG_SLANG)
endif endif
endif endif
...@@ -501,6 +522,7 @@ else ...@@ -501,6 +522,7 @@ else
else else
LDFLAGS += $(PERL_EMBED_LDFLAGS) LDFLAGS += $(PERL_EMBED_LDFLAGS)
EXTLIBS += $(PERL_EMBED_LIBADD) EXTLIBS += $(PERL_EMBED_LIBADD)
$(call detected,CONFIG_LIBPERL)
endif endif
endif endif
...@@ -560,6 +582,7 @@ else ...@@ -560,6 +582,7 @@ else
LDFLAGS += $(PYTHON_EMBED_LDFLAGS) LDFLAGS += $(PYTHON_EMBED_LDFLAGS)
EXTLIBS += $(PYTHON_EMBED_LIBADD) EXTLIBS += $(PYTHON_EMBED_LIBADD)
LANG_BINDINGS += $(obj-perf)python/perf.so LANG_BINDINGS += $(obj-perf)python/perf.so
$(call detected,CONFIG_LIBPYTHON)
endif endif
endif endif
endif endif
...@@ -617,6 +640,7 @@ ifndef NO_ZLIB ...@@ -617,6 +640,7 @@ ifndef NO_ZLIB
ifeq ($(feature-zlib), 1) ifeq ($(feature-zlib), 1)
CFLAGS += -DHAVE_ZLIB_SUPPORT CFLAGS += -DHAVE_ZLIB_SUPPORT
EXTLIBS += -lz EXTLIBS += -lz
$(call detected,CONFIG_ZLIB)
else else
NO_ZLIB := 1 NO_ZLIB := 1
endif endif
...@@ -635,6 +659,7 @@ ifndef NO_LIBNUMA ...@@ -635,6 +659,7 @@ ifndef NO_LIBNUMA
else else
CFLAGS += -DHAVE_LIBNUMA_SUPPORT CFLAGS += -DHAVE_LIBNUMA_SUPPORT
EXTLIBS += -lnuma EXTLIBS += -lnuma
$(call detected,CONFIG_NUMA)
endif endif
endif endif
...@@ -815,3 +840,19 @@ endif ...@@ -815,3 +840,19 @@ endif
ifeq ($(display_lib),1) ifeq ($(display_lib),1)
$(info ) $(info )
endif endif
$(call detected_var,bindir_SQ)
$(call detected_var,PYTHON_WORD)
ifneq ($(OUTPUT),)
$(call detected_var,OUTPUT)
endif
$(call detected_var,htmldir_SQ)
$(call detected_var,infodir_SQ)
$(call detected_var,mandir_SQ)
$(call detected_var,ETC_PERFCONFIG_SQ)
$(call detected_var,prefix_SQ)
$(call detected_var,perfexecdir_SQ)
$(call detected_var,LIBDIR)
$(call detected_var,GTK_CFLAGS)
$(call detected_var,PERL_EMBED_CCOPTS)
$(call detected_var,PYTHON_EMBED_CCOPTS)
...@@ -49,7 +49,7 @@ test-hello.bin: ...@@ -49,7 +49,7 @@ test-hello.bin:
$(BUILD) $(BUILD)
test-pthread-attr-setaffinity-np.bin: test-pthread-attr-setaffinity-np.bin:
$(BUILD) -Werror -lpthread $(BUILD) -D_GNU_SOURCE -Werror -lpthread
test-stackprotector-all.bin: test-stackprotector-all.bin:
$(BUILD) -Werror -fstack-protector-all $(BUILD) -Werror -fstack-protector-all
......
libperf-$(CONFIG_LIBPERL) += perl/Perf-Trace-Util/
libperf-$(CONFIG_LIBPYTHON) += python/Perf-Trace-Util/
libperf-y += Context.o
CFLAGS_Context.o += $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs -Wno-undef -Wno-switch-default
libperf-y += Context.o
CFLAGS_Context.o += $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs
perf-y += builtin-test.o
perf-y += parse-events.o
perf-y += dso-data.o
perf-y += attr.o
perf-y += vmlinux-kallsyms.o
perf-y += open-syscall.o
perf-y += open-syscall-all-cpus.o
perf-y += open-syscall-tp-fields.o
perf-y += mmap-basic.o
perf-y += perf-record.o
perf-y += rdpmc.o
perf-y += evsel-roundtrip-name.o
perf-y += evsel-tp-sched.o
perf-y += fdarray.o
perf-y += pmu.o
perf-y += hists_common.o
perf-y += hists_link.o
perf-y += hists_filter.o
perf-y += hists_output.o
perf-y += hists_cumulate.o
perf-y += python-use.o
perf-y += bp_signal.o
perf-y += bp_signal_overflow.o
perf-y += task-exit.o
perf-y += sw-clock.o
perf-y += mmap-thread-lookup.o
perf-y += thread-mg-share.o
perf-y += switch-tracking.o
perf-y += keep-tracking.o
perf-y += code-reading.o
perf-y += sample-parsing.o
perf-y += parse-no-sample-id-all.o
perf-$(CONFIG_X86) += perf-time-to-tsc.o
ifeq ($(ARCH),$(filter $(ARCH),x86 arm))
perf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o
endif
CFLAGS_attr.o += -DBINDIR="BUILD_STR($(bindir_SQ))" -DPYTHON="BUILD_STR($(PYTHON_WORD))"
CFLAGS_python-use.o += -DPYTHONPATH="BUILD_STR($(OUTPUT)python)" -DPYTHON="BUILD_STR($(PYTHON_WORD))"
CFLAGS_dwarf-unwind.o += -fno-optimize-sibling-calls
...@@ -112,6 +112,9 @@ int test__dso_data(void) ...@@ -112,6 +112,9 @@ int test__dso_data(void)
dso = dso__new((const char *)file); dso = dso__new((const char *)file);
TEST_ASSERT_VAL("Failed to access to dso",
dso__data_fd(dso, &machine) >= 0);
/* Basic 10 bytes tests. */ /* Basic 10 bytes tests. */
for (i = 0; i < ARRAY_SIZE(offsets); i++) { for (i = 0; i < ARRAY_SIZE(offsets); i++) {
struct test_data_offset *data = &offsets[i]; struct test_data_offset *data = &offsets[i];
...@@ -243,8 +246,8 @@ int test__dso_data_cache(void) ...@@ -243,8 +246,8 @@ int test__dso_data_cache(void)
limit = nr * 4; limit = nr * 4;
TEST_ASSERT_VAL("failed to set file limit", !set_fd_limit(limit)); TEST_ASSERT_VAL("failed to set file limit", !set_fd_limit(limit));
/* and this is now our dso open FDs limit + 1 extra */ /* and this is now our dso open FDs limit */
dso_cnt = limit / 2 + 1; dso_cnt = limit / 2;
TEST_ASSERT_VAL("failed to create dsos\n", TEST_ASSERT_VAL("failed to create dsos\n",
!dsos__create(dso_cnt, TEST_FILE_SIZE)); !dsos__create(dso_cnt, TEST_FILE_SIZE));
...@@ -252,13 +255,13 @@ int test__dso_data_cache(void) ...@@ -252,13 +255,13 @@ int test__dso_data_cache(void)
struct dso *dso = dsos[i]; struct dso *dso = dsos[i];
/* /*
* Open dsos via dso__data_fd or dso__data_read_offset. * Open dsos via dso__data_fd(), it opens the data
* Both opens the data file and keep it open. * file and keep it open (unless open file limit).
*/ */
fd = dso__data_fd(dso, &machine);
TEST_ASSERT_VAL("failed to get fd", fd > 0);
if (i % 2) { if (i % 2) {
fd = dso__data_fd(dso, &machine);
TEST_ASSERT_VAL("failed to get fd", fd > 0);
} else {
#define BUFSIZE 10 #define BUFSIZE 10
u8 buf[BUFSIZE]; u8 buf[BUFSIZE];
ssize_t n; ssize_t n;
...@@ -268,7 +271,10 @@ int test__dso_data_cache(void) ...@@ -268,7 +271,10 @@ int test__dso_data_cache(void)
} }
} }
/* open +1 dso over the allowed limit */ /* verify the first one is already open */
TEST_ASSERT_VAL("dsos[0] is not open", dsos[0]->data.fd != -1);
/* open +1 dso to reach the allowed limit */
fd = dso__data_fd(dsos[i], &machine); fd = dso__data_fd(dsos[i], &machine);
TEST_ASSERT_VAL("failed to get fd", fd > 0); TEST_ASSERT_VAL("failed to get fd", fd > 0);
......
...@@ -29,7 +29,12 @@ int test__open_syscall_event_on_all_cpus(void) ...@@ -29,7 +29,12 @@ int test__open_syscall_event_on_all_cpus(void)
evsel = perf_evsel__newtp("syscalls", "sys_enter_open"); evsel = perf_evsel__newtp("syscalls", "sys_enter_open");
if (evsel == NULL) { if (evsel == NULL) {
pr_debug("is debugfs mounted on /sys/kernel/debug?\n"); if (tracefs_configured())
pr_debug("is tracefs mounted on /sys/kernel/tracing?\n");
else if (debugfs_configured())
pr_debug("is debugfs mounted on /sys/kernel/debug?\n");
else
pr_debug("Neither tracefs or debugfs is enabled in this kernel\n");
goto out_thread_map_delete; goto out_thread_map_delete;
} }
......
...@@ -18,7 +18,12 @@ int test__open_syscall_event(void) ...@@ -18,7 +18,12 @@ int test__open_syscall_event(void)
evsel = perf_evsel__newtp("syscalls", "sys_enter_open"); evsel = perf_evsel__newtp("syscalls", "sys_enter_open");
if (evsel == NULL) { if (evsel == NULL) {
pr_debug("is debugfs mounted on /sys/kernel/debug?\n"); if (tracefs_configured())
pr_debug("is tracefs mounted on /sys/kernel/tracing?\n");
else if (debugfs_configured())
pr_debug("is debugfs mounted on /sys/kernel/debug?\n");
else
pr_debug("Neither tracefs or debugfs is enabled in this kernel\n");
goto out_thread_map_delete; goto out_thread_map_delete;
} }
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#include "evsel.h" #include "evsel.h"
#include "evlist.h" #include "evlist.h"
#include <api/fs/fs.h> #include <api/fs/fs.h>
#include <api/fs/tracefs.h>
#include <api/fs/debugfs.h> #include <api/fs/debugfs.h>
#include "tests.h" #include "tests.h"
#include "debug.h" #include "debug.h"
...@@ -1192,11 +1193,19 @@ static int count_tracepoints(void) ...@@ -1192,11 +1193,19 @@ static int count_tracepoints(void)
{ {
char events_path[PATH_MAX]; char events_path[PATH_MAX];
struct dirent *events_ent; struct dirent *events_ent;
const char *mountpoint;
DIR *events_dir; DIR *events_dir;
int cnt = 0; int cnt = 0;
scnprintf(events_path, PATH_MAX, "%s/tracing/events", mountpoint = tracefs_find_mountpoint();
debugfs_find_mountpoint()); if (mountpoint) {
scnprintf(events_path, PATH_MAX, "%s/events",
mountpoint);
} else {
mountpoint = debugfs_find_mountpoint();
scnprintf(events_path, PATH_MAX, "%s/tracing/events",
mountpoint);
}
events_dir = opendir(events_path); events_dir = opendir(events_path);
......
libperf-y += setup.o
libperf-y += helpline.o
libperf-y += progress.o
libperf-y += util.o
libperf-y += hist.o
libperf-y += stdio/hist.o
CFLAGS_setup.o += -DLIBDIR="BUILD_STR($(LIBDIR))"
libperf-$(CONFIG_SLANG) += browser.o
libperf-$(CONFIG_SLANG) += browsers/
libperf-$(CONFIG_SLANG) += tui/
CFLAGS_browser.o += -DENABLE_SLFUTURE_CONST
libperf-y += annotate.o
libperf-y += hists.o
libperf-y += map.o
libperf-y += scripts.o
libperf-y += header.o
CFLAGS_annotate.o += -DENABLE_SLFUTURE_CONST
CFLAGS_hists.o += -DENABLE_SLFUTURE_CONST
CFLAGS_map.o += -DENABLE_SLFUTURE_CONST
CFLAGS_scripts.o += -DENABLE_SLFUTURE_CONST
CFLAGS_gtk += -fPIC $(GTK_CFLAGS)
gtk-y += browser.o
gtk-y += hists.o
gtk-y += setup.o
gtk-y += util.o
gtk-y += helpline.o
gtk-y += progress.o
gtk-y += annotate.o
libperf-y += setup.o
libperf-y += util.o
libperf-y += helpline.o
libperf-y += progress.o
libperf-y += abspath.o
libperf-y += alias.o
libperf-y += annotate.o
libperf-y += build-id.o
libperf-y += config.o
libperf-y += ctype.o
libperf-y += db-export.o
libperf-y += environment.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 += parse-options.o
libperf-y += parse-events.o
libperf-y += path.o
libperf-y += rbtree.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
libperf-y += strlist.o
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
libperf-y += debug.o
libperf-y += machine.o
libperf-y += map.o
libperf-y += pstack.o
libperf-y += session.o
libperf-y += ordered-events.o
libperf-y += comm.o
libperf-y += thread.o
libperf-y += thread_map.o
libperf-y += trace-event-parse.o
libperf-y += parse-events-flex.o
libperf-y += parse-events-bison.o
libperf-y += pmu.o
libperf-y += pmu-flex.o
libperf-y += pmu-bison.o
libperf-y += trace-event-read.o
libperf-y += trace-event-info.o
libperf-y += trace-event-scripting.o
libperf-y += trace-event.o
libperf-y += svghelper.o
libperf-y += sort.o
libperf-y += hist.o
libperf-y += util.o
libperf-y += xyarray.o
libperf-y += cpumap.o
libperf-y += cgroup.o
libperf-y += target.o
libperf-y += rblist.o
libperf-y += intlist.o
libperf-y += vdso.o
libperf-y += stat.o
libperf-y += record.o
libperf-y += srcline.o
libperf-y += data.o
libperf-y += tsc.o
libperf-y += cloexec.o
libperf-y += thread-stack.o
libperf-$(CONFIG_LIBELF) += symbol-elf.o
libperf-$(CONFIG_LIBELF) += probe-event.o
ifndef CONFIG_LIBELF
libperf-y += symbol-minimal.o
endif
libperf-$(CONFIG_DWARF) += probe-finder.o
libperf-$(CONFIG_DWARF) += dwarf-aux.o
libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o
libperf-y += scripting-engines/
libperf-$(CONFIG_PERF_REGS) += perf_regs.o
libperf-$(CONFIG_ZLIB) += zlib.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)
@$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/parse-events-flex.h $(PARSER_DEBUG_FLEX) util/parse-events.l
$(OUTPUT)util/parse-events-bison.c: util/parse-events.y
$(call rule_mkdir)
@$(call echo-cmd,bison)$(BISON) -v util/parse-events.y -d $(PARSER_DEBUG_BISON) -o $@ -p parse_events_
$(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c
$(call rule_mkdir)
@$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/pmu-flex.h util/pmu.l
$(OUTPUT)util/pmu-bison.c: util/pmu.y
$(call rule_mkdir)
@$(call echo-cmd,bison)$(BISON) -v util/pmu.y -d -o $@ -p perf_pmu_
CFLAGS_parse-events-flex.o += -w
CFLAGS_pmu-flex.o += -w
CFLAGS_parse-events-bison.o += -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -w
CFLAGS_pmu-bison.o += -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -w
$(OUTPUT)util/parse-events.o: $(OUTPUT)util/parse-events-flex.c $(OUTPUT)util/parse-events-bison.c
$(OUTPUT)util/pmu.o: $(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-bison.c
CFLAGS_find_next_bit.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))"
CFLAGS_rbtree.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))"
CFLAGS_hweight.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))"
CFLAGS_parse-events.o += -Wno-redundant-decls
$(OUTPUT)util/kallsyms.o: ../lib/symbol/kallsyms.c FORCE
$(call rule_mkdir)
$(call if_changed_dep,cc_o_c)
$(OUTPUT)util/find_next_bit.o: ../lib/util/find_next_bit.c FORCE
$(call rule_mkdir)
$(call if_changed_dep,cc_o_c)
$(OUTPUT)util/rbtree.o: ../../lib/rbtree.c FORCE
$(call rule_mkdir)
$(call if_changed_dep,cc_o_c)
$(OUTPUT)util/hweight.o: ../../lib/hweight.c FORCE
$(call rule_mkdir)
$(call if_changed_dep,cc_o_c)
...@@ -93,6 +93,35 @@ int build_id__sprintf(const u8 *build_id, int len, char *bf) ...@@ -93,6 +93,35 @@ int build_id__sprintf(const u8 *build_id, int len, char *bf)
return raw - build_id; return raw - build_id;
} }
/* asnprintf consolidates asprintf and snprintf */
static int asnprintf(char **strp, size_t size, const char *fmt, ...)
{
va_list ap;
int ret;
if (!strp)
return -EINVAL;
va_start(ap, fmt);
if (*strp)
ret = vsnprintf(*strp, size, fmt, ap);
else
ret = vasprintf(strp, fmt, ap);
va_end(ap);
return ret;
}
static char *build_id__filename(const char *sbuild_id, char *bf, size_t size)
{
char *tmp = bf;
int ret = asnprintf(&bf, size, "%s/.build-id/%.2s/%s", buildid_dir,
sbuild_id, sbuild_id + 2);
if (ret < 0 || (tmp && size < (unsigned int)ret))
return NULL;
return bf;
}
char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size) char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size)
{ {
char build_id_hex[BUILD_ID_SIZE * 2 + 1]; char build_id_hex[BUILD_ID_SIZE * 2 + 1];
...@@ -101,14 +130,7 @@ char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size) ...@@ -101,14 +130,7 @@ char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size)
return NULL; return NULL;
build_id__sprintf(dso->build_id, sizeof(dso->build_id), build_id_hex); build_id__sprintf(dso->build_id, sizeof(dso->build_id), build_id_hex);
if (bf == NULL) { return build_id__filename(build_id_hex, bf, size);
if (asprintf(&bf, "%s/.build-id/%.2s/%s", buildid_dir,
build_id_hex, build_id_hex + 2) < 0)
return NULL;
} else
snprintf(bf, size, "%s/.build-id/%.2s/%s", buildid_dir,
build_id_hex, build_id_hex + 2);
return bf;
} }
#define dsos__for_each_with_build_id(pos, head) \ #define dsos__for_each_with_build_id(pos, head) \
...@@ -259,12 +281,12 @@ void disable_buildid_cache(void) ...@@ -259,12 +281,12 @@ void disable_buildid_cache(void)
no_buildid_cache = true; no_buildid_cache = true;
} }
int build_id_cache__add_s(const char *sbuild_id, const char *debugdir, int build_id_cache__add_s(const char *sbuild_id, const char *name,
const char *name, bool is_kallsyms, bool is_vdso) bool is_kallsyms, bool is_vdso)
{ {
const size_t size = PATH_MAX; const size_t size = PATH_MAX;
char *realname, *filename = zalloc(size), char *realname, *filename = zalloc(size),
*linkname = zalloc(size), *targetname; *linkname = zalloc(size), *targetname, *tmp;
int len, err = -1; int len, err = -1;
bool slash = is_kallsyms || is_vdso; bool slash = is_kallsyms || is_vdso;
...@@ -282,7 +304,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir, ...@@ -282,7 +304,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
goto out_free; goto out_free;
len = scnprintf(filename, size, "%s%s%s", len = scnprintf(filename, size, "%s%s%s",
debugdir, slash ? "/" : "", buildid_dir, slash ? "/" : "",
is_vdso ? DSO__NAME_VDSO : realname); is_vdso ? DSO__NAME_VDSO : realname);
if (mkdir_p(filename, 0755)) if (mkdir_p(filename, 0755))
goto out_free; goto out_free;
...@@ -297,14 +319,16 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir, ...@@ -297,14 +319,16 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
goto out_free; goto out_free;
} }
len = scnprintf(linkname, size, "%s/.build-id/%.2s", if (!build_id__filename(sbuild_id, linkname, size))
debugdir, sbuild_id); goto out_free;
tmp = strrchr(linkname, '/');
*tmp = '\0';
if (access(linkname, X_OK) && mkdir_p(linkname, 0755)) if (access(linkname, X_OK) && mkdir_p(linkname, 0755))
goto out_free; goto out_free;
snprintf(linkname + len, size - len, "/%s", sbuild_id + 2); *tmp = '/';
targetname = filename + strlen(debugdir) - 5; targetname = filename + strlen(buildid_dir) - 5;
memcpy(targetname, "../..", 5); memcpy(targetname, "../..", 5);
if (symlink(targetname, linkname) == 0) if (symlink(targetname, linkname) == 0)
...@@ -318,29 +342,28 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir, ...@@ -318,29 +342,28 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
} }
static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size, static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size,
const char *name, const char *debugdir, const char *name, bool is_kallsyms,
bool is_kallsyms, bool is_vdso) bool is_vdso)
{ {
char sbuild_id[BUILD_ID_SIZE * 2 + 1]; char sbuild_id[BUILD_ID_SIZE * 2 + 1];
build_id__sprintf(build_id, build_id_size, sbuild_id); build_id__sprintf(build_id, build_id_size, sbuild_id);
return build_id_cache__add_s(sbuild_id, debugdir, name, return build_id_cache__add_s(sbuild_id, name, is_kallsyms, is_vdso);
is_kallsyms, is_vdso);
} }
int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir) int build_id_cache__remove_s(const char *sbuild_id)
{ {
const size_t size = PATH_MAX; const size_t size = PATH_MAX;
char *filename = zalloc(size), char *filename = zalloc(size),
*linkname = zalloc(size); *linkname = zalloc(size), *tmp;
int err = -1; int err = -1;
if (filename == NULL || linkname == NULL) if (filename == NULL || linkname == NULL)
goto out_free; goto out_free;
snprintf(linkname, size, "%s/.build-id/%.2s/%s", if (!build_id__filename(sbuild_id, linkname, size))
debugdir, sbuild_id, sbuild_id + 2); goto out_free;
if (access(linkname, F_OK)) if (access(linkname, F_OK))
goto out_free; goto out_free;
...@@ -354,8 +377,8 @@ int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir) ...@@ -354,8 +377,8 @@ int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir)
/* /*
* Since the link is relative, we must make it absolute: * Since the link is relative, we must make it absolute:
*/ */
snprintf(linkname, size, "%s/.build-id/%.2s/%s", tmp = strrchr(linkname, '/') + 1;
debugdir, sbuild_id, filename); snprintf(tmp, size - (tmp - linkname), "%s", filename);
if (unlink(linkname)) if (unlink(linkname))
goto out_free; goto out_free;
...@@ -367,8 +390,7 @@ int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir) ...@@ -367,8 +390,7 @@ int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir)
return err; return err;
} }
static int dso__cache_build_id(struct dso *dso, struct machine *machine, static int dso__cache_build_id(struct dso *dso, struct machine *machine)
const char *debugdir)
{ {
bool is_kallsyms = dso->kernel && dso->long_name[0] != '/'; bool is_kallsyms = dso->kernel && dso->long_name[0] != '/';
bool is_vdso = dso__is_vdso(dso); bool is_vdso = dso__is_vdso(dso);
...@@ -381,28 +403,26 @@ static int dso__cache_build_id(struct dso *dso, struct machine *machine, ...@@ -381,28 +403,26 @@ static int dso__cache_build_id(struct dso *dso, struct machine *machine,
name = nm; name = nm;
} }
return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id), name, return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id), name,
debugdir, is_kallsyms, is_vdso); is_kallsyms, is_vdso);
} }
static int __dsos__cache_build_ids(struct list_head *head, static int __dsos__cache_build_ids(struct list_head *head,
struct machine *machine, const char *debugdir) struct machine *machine)
{ {
struct dso *pos; struct dso *pos;
int err = 0; int err = 0;
dsos__for_each_with_build_id(pos, head) dsos__for_each_with_build_id(pos, head)
if (dso__cache_build_id(pos, machine, debugdir)) if (dso__cache_build_id(pos, machine))
err = -1; err = -1;
return err; return err;
} }
static int machine__cache_build_ids(struct machine *machine, const char *debugdir) static int machine__cache_build_ids(struct machine *machine)
{ {
int ret = __dsos__cache_build_ids(&machine->kernel_dsos.head, machine, int ret = __dsos__cache_build_ids(&machine->kernel_dsos.head, machine);
debugdir); ret |= __dsos__cache_build_ids(&machine->user_dsos.head, machine);
ret |= __dsos__cache_build_ids(&machine->user_dsos.head, machine,
debugdir);
return ret; return ret;
} }
...@@ -417,11 +437,11 @@ int perf_session__cache_build_ids(struct perf_session *session) ...@@ -417,11 +437,11 @@ int perf_session__cache_build_ids(struct perf_session *session)
if (mkdir(buildid_dir, 0755) != 0 && errno != EEXIST) if (mkdir(buildid_dir, 0755) != 0 && errno != EEXIST)
return -1; return -1;
ret = machine__cache_build_ids(&session->machines.host, buildid_dir); ret = machine__cache_build_ids(&session->machines.host);
for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) { for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) {
struct machine *pos = rb_entry(nd, struct machine, rb_node); struct machine *pos = rb_entry(nd, struct machine, rb_node);
ret |= machine__cache_build_ids(pos, buildid_dir); ret |= machine__cache_build_ids(pos);
} }
return ret ? -1 : 0; return ret ? -1 : 0;
} }
......
...@@ -22,9 +22,9 @@ bool perf_session__read_build_ids(struct perf_session *session, bool with_hits); ...@@ -22,9 +22,9 @@ bool perf_session__read_build_ids(struct perf_session *session, bool with_hits);
int perf_session__write_buildid_table(struct perf_session *session, int fd); int perf_session__write_buildid_table(struct perf_session *session, int fd);
int perf_session__cache_build_ids(struct perf_session *session); int perf_session__cache_build_ids(struct perf_session *session);
int build_id_cache__add_s(const char *sbuild_id, const char *debugdir, int build_id_cache__add_s(const char *sbuild_id,
const char *name, bool is_kallsyms, bool is_vdso); const char *name, bool is_kallsyms, bool is_vdso);
int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir); int build_id_cache__remove_s(const char *sbuild_id);
void disable_buildid_cache(void); void disable_buildid_cache(void);
#endif #endif
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#define EXEC_PATH_ENVIRONMENT "PERF_EXEC_PATH" #define EXEC_PATH_ENVIRONMENT "PERF_EXEC_PATH"
#define DEFAULT_PERF_DIR_ENVIRONMENT ".perf" #define DEFAULT_PERF_DIR_ENVIRONMENT ".perf"
#define PERF_DEBUGFS_ENVIRONMENT "PERF_DEBUGFS_DIR" #define PERF_DEBUGFS_ENVIRONMENT "PERF_DEBUGFS_DIR"
#define PERF_TRACEFS_ENVIRONMENT "PERF_TRACEFS_DIR"
typedef int (*config_fn_t)(const char *, const char *, void *); typedef int (*config_fn_t)(const char *, const char *, void *);
extern int perf_default_config(const char *, const char *, void *); extern int perf_default_config(const char *, const char *, void *);
......
...@@ -45,13 +45,13 @@ int dso__read_binary_type_filename(const struct dso *dso, ...@@ -45,13 +45,13 @@ int dso__read_binary_type_filename(const struct dso *dso,
case DSO_BINARY_TYPE__DEBUGLINK: { case DSO_BINARY_TYPE__DEBUGLINK: {
char *debuglink; char *debuglink;
strncpy(filename, dso->long_name, size); len = __symbol__join_symfs(filename, size, dso->long_name);
debuglink = filename + dso->long_name_len; debuglink = filename + len;
while (debuglink != filename && *debuglink != '/') while (debuglink != filename && *debuglink != '/')
debuglink--; debuglink--;
if (*debuglink == '/') if (*debuglink == '/')
debuglink++; debuglink++;
ret = filename__read_debuglink(dso->long_name, debuglink, ret = filename__read_debuglink(filename, debuglink,
size - (debuglink - filename)); size - (debuglink - filename));
} }
break; break;
...@@ -240,7 +240,7 @@ static int do_open(char *name) ...@@ -240,7 +240,7 @@ static int do_open(char *name)
if (fd >= 0) if (fd >= 0)
return fd; return fd;
pr_debug("dso open failed, mmap: %s\n", pr_debug("dso open failed: %s\n",
strerror_r(errno, sbuf, sizeof(sbuf))); strerror_r(errno, sbuf, sizeof(sbuf)));
if (!dso__data_open_cnt || errno != EMFILE) if (!dso__data_open_cnt || errno != EMFILE)
break; break;
......
...@@ -277,6 +277,21 @@ bool die_is_func_def(Dwarf_Die *dw_die) ...@@ -277,6 +277,21 @@ bool die_is_func_def(Dwarf_Die *dw_die)
dwarf_attr(dw_die, DW_AT_declaration, &attr) == NULL); dwarf_attr(dw_die, DW_AT_declaration, &attr) == NULL);
} }
/**
* die_is_func_instance - Ensure that this DIE is an instance of a subprogram
* @dw_die: a DIE
*
* Ensure that this DIE is an instance (which has an entry address).
* This returns true if @dw_die is a function instance. If not, you need to
* call die_walk_instances() to find actual instances.
**/
bool die_is_func_instance(Dwarf_Die *dw_die)
{
Dwarf_Addr tmp;
/* Actually gcc optimizes non-inline as like as inlined */
return !dwarf_func_inline(dw_die) && dwarf_entrypc(dw_die, &tmp) == 0;
}
/** /**
* die_get_data_member_location - Get the data-member offset * die_get_data_member_location - Get the data-member offset
* @mb_die: a DIE of a member of a data structure * @mb_die: a DIE of a member of a data structure
......
...@@ -41,6 +41,9 @@ extern int cu_walk_functions_at(Dwarf_Die *cu_die, Dwarf_Addr addr, ...@@ -41,6 +41,9 @@ extern int cu_walk_functions_at(Dwarf_Die *cu_die, Dwarf_Addr addr,
/* Ensure that this DIE is a subprogram and definition (not declaration) */ /* Ensure that this DIE is a subprogram and definition (not declaration) */
extern bool die_is_func_def(Dwarf_Die *dw_die); extern bool die_is_func_def(Dwarf_Die *dw_die);
/* Ensure that this DIE is an instance of a subprogram */
extern bool die_is_func_instance(Dwarf_Die *dw_die);
/* Compare diename and tname */ /* Compare diename and tname */
extern bool die_compare_name(Dwarf_Die *dw_die, const char *tname); extern bool die_compare_name(Dwarf_Die *dw_die, const char *tname);
......
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
* Released under the GPL v2. (and only v2, not any later version) * Released under the GPL v2. (and only v2, not any later version)
*/ */
#include "util.h" #include "util.h"
#include <api/fs/debugfs.h>
#include <api/fs/fs.h> #include <api/fs/fs.h>
#include <poll.h> #include <poll.h>
#include "cpumap.h" #include "cpumap.h"
...@@ -1329,7 +1328,7 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *tar ...@@ -1329,7 +1328,7 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *tar
* writing exactly one byte, in workload.cork_fd, usually via * writing exactly one byte, in workload.cork_fd, usually via
* perf_evlist__start_workload(). * perf_evlist__start_workload().
* *
* For cancelling the workload without actuallin running it, * For cancelling the workload without actually running it,
* the parent will just close workload.cork_fd, without writing * the parent will just close workload.cork_fd, without writing
* anything, i.e. read will return zero and we just exit() * anything, i.e. read will return zero and we just exit()
* here. * here.
......
...@@ -175,9 +175,6 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config) ...@@ -175,9 +175,6 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config)
char evt_path[MAXPATHLEN]; char evt_path[MAXPATHLEN];
char dir_path[MAXPATHLEN]; char dir_path[MAXPATHLEN];
if (debugfs_valid_mountpoint(tracing_events_path))
return NULL;
sys_dir = opendir(tracing_events_path); sys_dir = opendir(tracing_events_path);
if (!sys_dir) if (!sys_dir)
return NULL; return NULL;
...@@ -473,12 +470,6 @@ static int add_tracepoint_multi_sys(struct list_head *list, int *idx, ...@@ -473,12 +470,6 @@ static int add_tracepoint_multi_sys(struct list_head *list, int *idx,
int parse_events_add_tracepoint(struct list_head *list, int *idx, int parse_events_add_tracepoint(struct list_head *list, int *idx,
char *sys, char *event) char *sys, char *event)
{ {
int ret;
ret = debugfs_valid_mountpoint(tracing_events_path);
if (ret)
return ret;
if (strpbrk(sys, "*?")) if (strpbrk(sys, "*?"))
return add_tracepoint_multi_sys(list, idx, sys, event); return add_tracepoint_multi_sys(list, idx, sys, event);
else else
...@@ -1109,13 +1100,6 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob, ...@@ -1109,13 +1100,6 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
char evt_path[MAXPATHLEN]; char evt_path[MAXPATHLEN];
char dir_path[MAXPATHLEN]; char dir_path[MAXPATHLEN];
char sbuf[STRERR_BUFSIZE];
if (debugfs_valid_mountpoint(tracing_events_path)) {
printf(" [ Tracepoints not available: %s ]\n",
strerror_r(errno, sbuf, sizeof(sbuf)));
return;
}
sys_dir = opendir(tracing_events_path); sys_dir = opendir(tracing_events_path);
if (!sys_dir) if (!sys_dir)
...@@ -1163,9 +1147,6 @@ int is_valid_tracepoint(const char *event_string) ...@@ -1163,9 +1147,6 @@ int is_valid_tracepoint(const char *event_string)
char evt_path[MAXPATHLEN]; char evt_path[MAXPATHLEN];
char dir_path[MAXPATHLEN]; char dir_path[MAXPATHLEN];
if (debugfs_valid_mountpoint(tracing_events_path))
return 0;
sys_dir = opendir(tracing_events_path); sys_dir = opendir(tracing_events_path);
if (!sys_dir) if (!sys_dir)
return 0; return 0;
...@@ -1338,11 +1319,6 @@ static void print_symbol_events(const char *event_glob, unsigned type, ...@@ -1338,11 +1319,6 @@ static void print_symbol_events(const char *event_glob, unsigned type,
*/ */
void print_events(const char *event_glob, bool name_only) void print_events(const char *event_glob, bool name_only)
{ {
if (!name_only) {
printf("\n");
printf("List of pre-defined events (to be used in -e):\n");
}
print_symbol_events(event_glob, PERF_TYPE_HARDWARE, print_symbol_events(event_glob, PERF_TYPE_HARDWARE,
event_symbols_hw, PERF_COUNT_HW_MAX, name_only); event_symbols_hw, PERF_COUNT_HW_MAX, name_only);
......
...@@ -122,6 +122,6 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob, ...@@ -122,6 +122,6 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
int print_hwcache_events(const char *event_glob, bool name_only); int print_hwcache_events(const char *event_glob, bool name_only);
extern int is_valid_tracepoint(const char *event_string); extern int is_valid_tracepoint(const char *event_string);
extern int valid_debugfs_mount(const char *debugfs); int valid_event_mount(const char *eventfs);
#endif /* __PERF_PARSE_EVENTS_H */ #endif /* __PERF_PARSE_EVENTS_H */
...@@ -510,8 +510,10 @@ int parse_options_subcommand(int argc, const char **argv, const struct option *o ...@@ -510,8 +510,10 @@ int parse_options_subcommand(int argc, const char **argv, const struct option *o
} }
exit(130); exit(130);
case PARSE_OPT_LIST_SUBCMDS: case PARSE_OPT_LIST_SUBCMDS:
for (int i = 0; subcommands[i]; i++) if (subcommands) {
printf("%s ", subcommands[i]); for (int i = 0; subcommands[i]; i++)
printf("%s ", subcommands[i]);
}
exit(130); exit(130);
default: /* PARSE_OPT_UNKNOWN */ default: /* PARSE_OPT_UNKNOWN */
if (ctx.argv[0][1] == '-') { if (ctx.argv[0][1] == '-') {
......
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#include "symbol.h" #include "symbol.h"
#include "thread.h" #include "thread.h"
#include <api/fs/debugfs.h> #include <api/fs/debugfs.h>
#include <api/fs/tracefs.h>
#include "trace-event.h" /* For __maybe_unused */ #include "trace-event.h" /* For __maybe_unused */
#include "probe-event.h" #include "probe-event.h"
#include "probe-finder.h" #include "probe-finder.h"
...@@ -1805,7 +1806,7 @@ static void print_open_warning(int err, bool is_kprobe) ...@@ -1805,7 +1806,7 @@ static void print_open_warning(int err, bool is_kprobe)
" - please rebuild kernel with %s.\n", " - please rebuild kernel with %s.\n",
is_kprobe ? 'k' : 'u', config); is_kprobe ? 'k' : 'u', config);
} else if (err == -ENOTSUP) } else if (err == -ENOTSUP)
pr_warning("Debugfs is not mounted.\n"); pr_warning("Tracefs or debugfs is not mounted.\n");
else else
pr_warning("Failed to open %cprobe_events: %s\n", pr_warning("Failed to open %cprobe_events: %s\n",
is_kprobe ? 'k' : 'u', is_kprobe ? 'k' : 'u',
...@@ -1816,7 +1817,7 @@ static void print_both_open_warning(int kerr, int uerr) ...@@ -1816,7 +1817,7 @@ static void print_both_open_warning(int kerr, int uerr)
{ {
/* Both kprobes and uprobes are disabled, warn it. */ /* Both kprobes and uprobes are disabled, warn it. */
if (kerr == -ENOTSUP && uerr == -ENOTSUP) if (kerr == -ENOTSUP && uerr == -ENOTSUP)
pr_warning("Debugfs is not mounted.\n"); pr_warning("Tracefs or debugfs is not mounted.\n");
else if (kerr == -ENOENT && uerr == -ENOENT) else if (kerr == -ENOENT && uerr == -ENOENT)
pr_warning("Please rebuild kernel with CONFIG_KPROBE_EVENTS " pr_warning("Please rebuild kernel with CONFIG_KPROBE_EVENTS "
"or/and CONFIG_UPROBE_EVENTS.\n"); "or/and CONFIG_UPROBE_EVENTS.\n");
...@@ -1833,13 +1834,20 @@ static int open_probe_events(const char *trace_file, bool readwrite) ...@@ -1833,13 +1834,20 @@ static int open_probe_events(const char *trace_file, bool readwrite)
{ {
char buf[PATH_MAX]; char buf[PATH_MAX];
const char *__debugfs; const char *__debugfs;
const char *tracing_dir = "";
int ret; int ret;
__debugfs = debugfs_find_mountpoint(); __debugfs = tracefs_find_mountpoint();
if (__debugfs == NULL) if (__debugfs == NULL) {
return -ENOTSUP; tracing_dir = "tracing/";
ret = e_snprintf(buf, PATH_MAX, "%s/%s", __debugfs, trace_file); __debugfs = debugfs_find_mountpoint();
if (__debugfs == NULL)
return -ENOTSUP;
}
ret = e_snprintf(buf, PATH_MAX, "%s/%s%s",
__debugfs, tracing_dir, trace_file);
if (ret >= 0) { if (ret >= 0) {
pr_debug("Opening %s write=%d\n", buf, readwrite); pr_debug("Opening %s write=%d\n", buf, readwrite);
if (readwrite && !probe_event_dry_run) if (readwrite && !probe_event_dry_run)
...@@ -1855,12 +1863,12 @@ static int open_probe_events(const char *trace_file, bool readwrite) ...@@ -1855,12 +1863,12 @@ static int open_probe_events(const char *trace_file, bool readwrite)
static int open_kprobe_events(bool readwrite) static int open_kprobe_events(bool readwrite)
{ {
return open_probe_events("tracing/kprobe_events", readwrite); return open_probe_events("kprobe_events", readwrite);
} }
static int open_uprobe_events(bool readwrite) static int open_uprobe_events(bool readwrite)
{ {
return open_probe_events("tracing/uprobe_events", readwrite); return open_probe_events("uprobe_events", readwrite);
} }
/* Get raw string list of current kprobe_events or uprobe_events */ /* Get raw string list of current kprobe_events or uprobe_events */
......
...@@ -915,17 +915,13 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data) ...@@ -915,17 +915,13 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
dwarf_decl_line(sp_die, &pf->lno); dwarf_decl_line(sp_die, &pf->lno);
pf->lno += pp->line; pf->lno += pp->line;
param->retval = find_probe_point_by_line(pf); param->retval = find_probe_point_by_line(pf);
} else if (!dwarf_func_inline(sp_die)) { } else if (die_is_func_instance(sp_die)) {
/* Instances always have the entry address */
dwarf_entrypc(sp_die, &pf->addr);
/* Real function */ /* Real function */
if (pp->lazy_line) if (pp->lazy_line)
param->retval = find_probe_point_lazy(sp_die, pf); param->retval = find_probe_point_lazy(sp_die, pf);
else { else {
if (dwarf_entrypc(sp_die, &pf->addr) != 0) {
pr_warning("Failed to get entry address of "
"%s.\n", dwarf_diename(sp_die));
param->retval = -ENOENT;
return DWARF_CB_ABORT;
}
pf->addr += pp->offset; pf->addr += pp->offset;
/* TODO: Check the address in this function */ /* TODO: Check the address in this function */
param->retval = call_probe_finder(sp_die, pf); param->retval = call_probe_finder(sp_die, pf);
...@@ -1536,7 +1532,7 @@ static int line_range_search_cb(Dwarf_Die *sp_die, void *data) ...@@ -1536,7 +1532,7 @@ static int line_range_search_cb(Dwarf_Die *sp_die, void *data)
pr_debug("New line range: %d to %d\n", lf->lno_s, lf->lno_e); pr_debug("New line range: %d to %d\n", lf->lno_s, lf->lno_e);
lr->start = lf->lno_s; lr->start = lf->lno_s;
lr->end = lf->lno_e; lr->end = lf->lno_e;
if (dwarf_func_inline(sp_die)) if (!die_is_func_instance(sp_die))
param->retval = die_walk_instances(sp_die, param->retval = die_walk_instances(sp_die,
line_range_inline_cb, lf); line_range_inline_cb, lf);
else else
......
...@@ -17,6 +17,5 @@ util/xyarray.c ...@@ -17,6 +17,5 @@ util/xyarray.c
util/cgroup.c util/cgroup.c
util/rblist.c util/rblist.c
util/strlist.c util/strlist.c
../lib/api/fs/fs.c
util/trace-event.c util/trace-event.c
../../lib/rbtree.c ../../lib/rbtree.c
libperf-$(CONFIG_LIBPERL) += trace-event-perl.o
libperf-$(CONFIG_LIBPYTHON) += trace-event-python.o
CFLAGS_trace-event-perl.o += $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow -Wno-undef -Wno-switch-default
CFLAGS_trace-event-python.o += $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow
...@@ -25,7 +25,7 @@ cflags += ['-fno-strict-aliasing', '-Wno-write-strings', '-Wno-unused-parameter' ...@@ -25,7 +25,7 @@ cflags += ['-fno-strict-aliasing', '-Wno-write-strings', '-Wno-unused-parameter'
build_lib = getenv('PYTHON_EXTBUILD_LIB') build_lib = getenv('PYTHON_EXTBUILD_LIB')
build_tmp = getenv('PYTHON_EXTBUILD_TMP') build_tmp = getenv('PYTHON_EXTBUILD_TMP')
libtraceevent = getenv('LIBTRACEEVENT') libtraceevent = getenv('LIBTRACEEVENT')
libapikfs = getenv('LIBAPIKFS') libapikfs = getenv('LIBAPI')
ext_sources = [f.strip() for f in file('util/python-ext-sources') ext_sources = [f.strip() for f in file('util/python-ext-sources')
if len(f.strip()) > 0 and f[0] != '#'] if len(f.strip()) > 0 and f[0] != '#']
......
...@@ -69,6 +69,10 @@ static inline uint8_t elf_sym__type(const GElf_Sym *sym) ...@@ -69,6 +69,10 @@ static inline uint8_t elf_sym__type(const GElf_Sym *sym)
return GELF_ST_TYPE(sym->st_info); return GELF_ST_TYPE(sym->st_info);
} }
#ifndef STT_GNU_IFUNC
#define STT_GNU_IFUNC 10
#endif
static inline int elf_sym__is_function(const GElf_Sym *sym) static inline int elf_sym__is_function(const GElf_Sym *sym)
{ {
return (elf_sym__type(sym) == STT_FUNC || return (elf_sym__type(sym) == STT_FUNC ||
...@@ -859,10 +863,9 @@ int dso__load_sym(struct dso *dso, struct map *map, ...@@ -859,10 +863,9 @@ int dso__load_sym(struct dso *dso, struct map *map,
/* Reject ARM ELF "mapping symbols": these aren't unique and /* Reject ARM ELF "mapping symbols": these aren't unique and
* don't identify functions, so will confuse the profile * don't identify functions, so will confuse the profile
* output: */ * output: */
if (ehdr.e_machine == EM_ARM) { if (ehdr.e_machine == EM_ARM || ehdr.e_machine == EM_AARCH64) {
if (!strcmp(elf_name, "$a") || if (elf_name[0] == '$' && strchr("adtx", elf_name[1])
!strcmp(elf_name, "$d") || && (elf_name[2] == '\0' || elf_name[2] == '.'))
!strcmp(elf_name, "$t"))
continue; continue;
} }
......
...@@ -112,8 +112,8 @@ unsigned long long read_size(struct event_format *event, void *ptr, int size) ...@@ -112,8 +112,8 @@ unsigned long long read_size(struct event_format *event, void *ptr, int size)
return pevent_read_number(event->pevent, ptr, size); return pevent_read_number(event->pevent, ptr, size);
} }
void event_format__print(struct event_format *event, void event_format__fprintf(struct event_format *event,
int cpu, void *data, int size) int cpu, void *data, int size, FILE *fp)
{ {
struct pevent_record record; struct pevent_record record;
struct trace_seq s; struct trace_seq s;
...@@ -125,10 +125,16 @@ void event_format__print(struct event_format *event, ...@@ -125,10 +125,16 @@ void event_format__print(struct event_format *event,
trace_seq_init(&s); trace_seq_init(&s);
pevent_event_info(&s, event, &record); pevent_event_info(&s, event, &record);
trace_seq_do_printf(&s); trace_seq_do_fprintf(&s, fp);
trace_seq_destroy(&s); trace_seq_destroy(&s);
} }
void event_format__print(struct event_format *event,
int cpu, void *data, int size)
{
return event_format__fprintf(event, cpu, data, size, stdout);
}
void parse_proc_kallsyms(struct pevent *pevent, void parse_proc_kallsyms(struct pevent *pevent,
char *file, unsigned int size __maybe_unused) char *file, unsigned int size __maybe_unused)
{ {
......
...@@ -23,6 +23,9 @@ trace_event__tp_format(const char *sys, const char *name); ...@@ -23,6 +23,9 @@ trace_event__tp_format(const char *sys, const char *name);
int bigendian(void); int bigendian(void);
void event_format__fprintf(struct event_format *event,
int cpu, void *data, int size, FILE *fp);
void event_format__print(struct event_format *event, void event_format__print(struct event_format *event,
int cpu, void *data, int size); int cpu, void *data, int size);
......
...@@ -303,13 +303,26 @@ void set_term_quiet_input(struct termios *old) ...@@ -303,13 +303,26 @@ void set_term_quiet_input(struct termios *old)
tcsetattr(0, TCSANOW, &tc); tcsetattr(0, TCSANOW, &tc);
} }
static void set_tracing_events_path(const char *mountpoint) static void set_tracing_events_path(const char *tracing, const char *mountpoint)
{ {
snprintf(tracing_events_path, sizeof(tracing_events_path), "%s/%s", snprintf(tracing_events_path, sizeof(tracing_events_path), "%s/%s%s",
mountpoint, "tracing/events"); mountpoint, tracing, "events");
} }
const char *perf_debugfs_mount(const char *mountpoint) static const char *__perf_tracefs_mount(const char *mountpoint)
{
const char *mnt;
mnt = tracefs_mount(mountpoint);
if (!mnt)
return NULL;
set_tracing_events_path("", mnt);
return mnt;
}
static const char *__perf_debugfs_mount(const char *mountpoint)
{ {
const char *mnt; const char *mnt;
...@@ -317,7 +330,20 @@ const char *perf_debugfs_mount(const char *mountpoint) ...@@ -317,7 +330,20 @@ const char *perf_debugfs_mount(const char *mountpoint)
if (!mnt) if (!mnt)
return NULL; return NULL;
set_tracing_events_path(mnt); set_tracing_events_path("tracing/", mnt);
return mnt;
}
const char *perf_debugfs_mount(const char *mountpoint)
{
const char *mnt;
mnt = __perf_tracefs_mount(mountpoint);
if (mnt)
return mnt;
mnt = __perf_debugfs_mount(mountpoint);
return mnt; return mnt;
} }
...@@ -325,12 +351,19 @@ const char *perf_debugfs_mount(const char *mountpoint) ...@@ -325,12 +351,19 @@ const char *perf_debugfs_mount(const char *mountpoint)
void perf_debugfs_set_path(const char *mntpt) void perf_debugfs_set_path(const char *mntpt)
{ {
snprintf(debugfs_mountpoint, strlen(debugfs_mountpoint), "%s", mntpt); snprintf(debugfs_mountpoint, strlen(debugfs_mountpoint), "%s", mntpt);
set_tracing_events_path(mntpt); set_tracing_events_path("tracing/", mntpt);
}
static const char *find_tracefs(void)
{
const char *path = __perf_tracefs_mount(NULL);
return path;
} }
static const char *find_debugfs(void) static const char *find_debugfs(void)
{ {
const char *path = perf_debugfs_mount(NULL); const char *path = __perf_debugfs_mount(NULL);
if (!path) if (!path)
fprintf(stderr, "Your kernel does not support the debugfs filesystem"); fprintf(stderr, "Your kernel does not support the debugfs filesystem");
...@@ -344,6 +377,7 @@ static const char *find_debugfs(void) ...@@ -344,6 +377,7 @@ static const char *find_debugfs(void)
*/ */
const char *find_tracing_dir(void) const char *find_tracing_dir(void)
{ {
const char *tracing_dir = "";
static char *tracing; static char *tracing;
static int tracing_found; static int tracing_found;
const char *debugfs; const char *debugfs;
...@@ -351,11 +385,15 @@ const char *find_tracing_dir(void) ...@@ -351,11 +385,15 @@ const char *find_tracing_dir(void)
if (tracing_found) if (tracing_found)
return tracing; return tracing;
debugfs = find_debugfs(); debugfs = find_tracefs();
if (!debugfs) if (!debugfs) {
return NULL; tracing_dir = "/tracing";
debugfs = find_debugfs();
if (!debugfs)
return NULL;
}
if (asprintf(&tracing, "%s/tracing", debugfs) < 0) if (asprintf(&tracing, "%s%s", debugfs, tracing_dir) < 0)
return NULL; return NULL;
tracing_found = 1; tracing_found = 1;
......
...@@ -75,6 +75,7 @@ ...@@ -75,6 +75,7 @@
#include <linux/types.h> #include <linux/types.h>
#include <sys/ttydefaults.h> #include <sys/ttydefaults.h>
#include <api/fs/debugfs.h> #include <api/fs/debugfs.h>
#include <api/fs/tracefs.h>
#include <termios.h> #include <termios.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <termios.h> #include <termios.h>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment