Commit e0c4a5fc authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull perf updates/fixes from Ingo Molnar:
 "Mostly tooling updates, but also two kernel fixes: a call chain
  handling robustness fix and an x86 PMU driver event definition fix"

* 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  perf/callchain: Force USER_DS when invoking perf_callchain_user()
  tools build: Fixup sched_getcpu feature test
  perf tests kmod-path: Don't fail if compressed modules aren't supported
  perf annotate: Fix AArch64 comment char
  perf tools: Fix spelling mistakes
  perf/x86: Fix Broadwell-EP DRAM RAPL events
  perf config: Refactor a duplicated code for obtaining config file name
  perf symbols: Allow user probes on versioned symbols
  perf symbols: Accept symbols starting at address 0
  tools lib string: Adopt prefixcmp() from perf and subcmd
  perf units: Move parse_tag_value() to units.[ch]
  perf ui gtk: Move gtk .so name to the only place where it is used
  perf tools: Move HAS_BOOL define to where perl headers are used
  perf memswap: Split the byteswap memory range wrappers from util.[ch]
  perf tools: Move event prototypes from util.h to event.h
  perf buildid: Move prototypes from util.h to build-id.h
parents dfcb7b23 88b0193d
...@@ -761,7 +761,7 @@ static const struct x86_cpu_id rapl_cpu_match[] __initconst = { ...@@ -761,7 +761,7 @@ static const struct x86_cpu_id rapl_cpu_match[] __initconst = {
X86_RAPL_MODEL_MATCH(INTEL_FAM6_BROADWELL_CORE, hsw_rapl_init), X86_RAPL_MODEL_MATCH(INTEL_FAM6_BROADWELL_CORE, hsw_rapl_init),
X86_RAPL_MODEL_MATCH(INTEL_FAM6_BROADWELL_GT3E, hsw_rapl_init), X86_RAPL_MODEL_MATCH(INTEL_FAM6_BROADWELL_GT3E, hsw_rapl_init),
X86_RAPL_MODEL_MATCH(INTEL_FAM6_BROADWELL_X, hsw_rapl_init), X86_RAPL_MODEL_MATCH(INTEL_FAM6_BROADWELL_X, hsx_rapl_init),
X86_RAPL_MODEL_MATCH(INTEL_FAM6_BROADWELL_XEON_D, hsw_rapl_init), X86_RAPL_MODEL_MATCH(INTEL_FAM6_BROADWELL_XEON_D, hsw_rapl_init),
X86_RAPL_MODEL_MATCH(INTEL_FAM6_XEON_PHI_KNL, knl_rapl_init), X86_RAPL_MODEL_MATCH(INTEL_FAM6_XEON_PHI_KNL, knl_rapl_init),
......
...@@ -229,12 +229,18 @@ get_perf_callchain(struct pt_regs *regs, u32 init_nr, bool kernel, bool user, ...@@ -229,12 +229,18 @@ get_perf_callchain(struct pt_regs *regs, u32 init_nr, bool kernel, bool user,
} }
if (regs) { if (regs) {
mm_segment_t fs;
if (crosstask) if (crosstask)
goto exit_put; goto exit_put;
if (add_mark) if (add_mark)
perf_callchain_store_context(&ctx, PERF_CONTEXT_USER); perf_callchain_store_context(&ctx, PERF_CONTEXT_USER);
fs = get_fs();
set_fs(USER_DS);
perf_callchain_user(&ctx, regs); perf_callchain_user(&ctx, regs);
set_fs(fs);
} }
} }
......
#ifndef _GNU_SOURCE
#define _GNU_SOURCE #define _GNU_SOURCE
#endif
#include <sched.h> #include <sched.h>
int main(void) int main(void)
......
...@@ -18,4 +18,6 @@ extern size_t strlcpy(char *dest, const char *src, size_t size); ...@@ -18,4 +18,6 @@ extern size_t strlcpy(char *dest, const char *src, size_t size);
char *str_error_r(int errnum, char *buf, size_t buflen); char *str_error_r(int errnum, char *buf, size_t buflen);
int prefixcmp(const char *str, const char *prefix);
#endif /* _LINUX_STRING_H_ */ #endif /* _LINUX_STRING_H_ */
...@@ -87,3 +87,12 @@ size_t __weak strlcpy(char *dest, const char *src, size_t size) ...@@ -87,3 +87,12 @@ size_t __weak strlcpy(char *dest, const char *src, size_t size)
} }
return ret; return ret;
} }
int prefixcmp(const char *str, const char *prefix)
{
for (; ; str++, prefix++)
if (!*prefix)
return 0;
else if (*str != *prefix)
return (unsigned char)*prefix - (unsigned char)*str;
}
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <linux/string.h>
#include <termios.h> #include <termios.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/types.h> #include <sys/types.h>
......
#include <linux/compiler.h> #include <linux/compiler.h>
#include <linux/string.h>
#include <linux/types.h> #include <linux/types.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
......
...@@ -79,13 +79,4 @@ static inline void astrcat(char **out, const char *add) ...@@ -79,13 +79,4 @@ static inline void astrcat(char **out, const char *add)
free(tmp); free(tmp);
} }
static inline int prefixcmp(const char *str, const char *prefix)
{
for (; ; str++, prefix++)
if (!*prefix)
return 0;
else if (*str != *prefix)
return (unsigned char)*prefix - (unsigned char)*str;
}
#endif /* __SUBCMD_UTIL_H */ #endif /* __SUBCMD_UTIL_H */
...@@ -76,7 +76,7 @@ REPORT OPTIONS ...@@ -76,7 +76,7 @@ REPORT OPTIONS
-c:: -c::
--coalesce:: --coalesce::
Specify sorintg fields for single cacheline display. Specify sorting fields for single cacheline display.
Following fields are available: tid,pid,iaddr,dso Following fields are available: tid,pid,iaddr,dso
(see COALESCE) (see COALESCE)
...@@ -106,7 +106,7 @@ REPORT OPTIONS ...@@ -106,7 +106,7 @@ REPORT OPTIONS
-d:: -d::
--display:: --display::
Siwtch to HITM type (rmt, lcl) to display and sort on. Total HITMs as default. Switch to HITM type (rmt, lcl) to display and sort on. Total HITMs as default.
C2C RECORD C2C RECORD
---------- ----------
......
...@@ -225,7 +225,7 @@ OPTIONS ...@@ -225,7 +225,7 @@ OPTIONS
the libunwind or libdw library) should be used instead. the libunwind or libdw library) should be used instead.
Using the "lbr" method doesn't require any compiler options. It Using the "lbr" method doesn't require any compiler options. It
will produce call graphs from the hardware LBR registers. The will produce call graphs from the hardware LBR registers. The
main limition is that it is only available on new Intel main limitation is that it is only available on new Intel
platforms, such as Haswell. It can only get user call chain. It platforms, such as Haswell. It can only get user call chain. It
doesn't work with branch stack sampling at the same time. doesn't work with branch stack sampling at the same time.
......
...@@ -182,7 +182,7 @@ OPTIONS ...@@ -182,7 +182,7 @@ OPTIONS
--parent=<regex>:: --parent=<regex>::
A regex filter to identify parent. The parent is a caller of this A regex filter to identify parent. The parent is a caller of this
function and searched through the callchain, thus it requires callchain function and searched through the callchain, thus it requires callchain
information recorded. The pattern is in the exteneded regex format and information recorded. The pattern is in the extended regex format and
defaults to "\^sys_|^do_page_fault", see '--sort parent'. defaults to "\^sys_|^do_page_fault", see '--sort parent'.
-x:: -x::
...@@ -207,8 +207,8 @@ OPTIONS ...@@ -207,8 +207,8 @@ OPTIONS
-g:: -g::
--call-graph=<print_type,threshold[,print_limit],order,sort_key[,branch],value>:: --call-graph=<print_type,threshold[,print_limit],order,sort_key[,branch],value>::
Display call chains using type, min percent threshold, print limit, Display call chains using type, min percent threshold, print limit,
call order, sort key, optional branch and value. Note that ordering of call order, sort key, optional branch and value. Note that ordering
parameters is not fixed so any parement can be given in an arbitraty order. is not fixed so any parameter can be given in an arbitrary order.
One exception is the print_limit which should be preceded by threshold. One exception is the print_limit which should be preceded by threshold.
print_type can be either: print_type can be either:
......
...@@ -270,7 +270,7 @@ When the event stream contains multiple events each event is identified ...@@ -270,7 +270,7 @@ When the event stream contains multiple events each event is identified
by an ID. This can be either through the PERF_SAMPLE_ID or the by an ID. This can be either through the PERF_SAMPLE_ID or the
PERF_SAMPLE_IDENTIFIER header. The PERF_SAMPLE_IDENTIFIER header is PERF_SAMPLE_IDENTIFIER header. The PERF_SAMPLE_IDENTIFIER header is
at a fixed offset from the event header, which allows reliable at a fixed offset from the event header, which allows reliable
parsing of the header. Relying on ID may be ambigious. parsing of the header. Relying on ID may be ambiguous.
IDENTIFIER is only supported by newer Linux kernels. IDENTIFIER is only supported by newer Linux kernels.
Perf record specific events: Perf record specific events:
...@@ -288,7 +288,7 @@ struct attr_event { ...@@ -288,7 +288,7 @@ struct attr_event {
uint64_t id[]; uint64_t id[];
}; };
PERF_RECORD_HEADER_EVENT_TYPE = 65, /* depreceated */ PERF_RECORD_HEADER_EVENT_TYPE = 65, /* deprecated */
#define MAX_EVENT_NAME 64 #define MAX_EVENT_NAME 64
......
...@@ -23,7 +23,7 @@ For memory address profiling, try: perf mem record / perf mem report ...@@ -23,7 +23,7 @@ For memory address profiling, try: perf mem record / perf mem report
For tracepoint events, try: perf report -s trace_fields For tracepoint events, try: perf report -s trace_fields
To record callchains for each sample: perf record -g To record callchains for each sample: perf record -g
To record every process run by a user: perf record -u <user> To record every process run by a user: perf record -u <user>
Skip collecing build-id when recording: perf record -B Skip collecting build-id when recording: perf record -B
To change sampling frequency to 100 Hz: perf record -F 100 To change sampling frequency to 100 Hz: perf record -F 100
See assembly instructions with percentage: perf annotate <symbol> See assembly instructions with percentage: perf annotate <symbol>
If you prefer Intel style assembly, try: perf annotate -M intel If you prefer Intel style assembly, try: perf annotate -M intel
......
...@@ -50,7 +50,7 @@ static int arm64__annotate_init(struct arch *arch) ...@@ -50,7 +50,7 @@ static int arm64__annotate_init(struct arch *arch)
arch->initialized = true; arch->initialized = true;
arch->priv = arm; arch->priv = arm;
arch->associate_instruction_ops = arm64__associate_instruction_ops; arch->associate_instruction_ops = arm64__associate_instruction_ops;
arch->objdump.comment_char = ';'; arch->objdump.comment_char = '/';
arch->objdump.skip_functions_char = '+'; arch->objdump.skip_functions_char = '+';
return 0; return 0;
......
...@@ -52,6 +52,18 @@ int arch__compare_symbol_names(const char *namea, const char *nameb) ...@@ -52,6 +52,18 @@ int arch__compare_symbol_names(const char *namea, const char *nameb)
return strcmp(namea, nameb); return strcmp(namea, nameb);
} }
int arch__compare_symbol_names_n(const char *namea, const char *nameb,
unsigned int n)
{
/* Skip over initial dot */
if (*namea == '.')
namea++;
if (*nameb == '.')
nameb++;
return strncmp(namea, nameb, n);
}
#endif #endif
#if defined(_CALL_ELF) && _CALL_ELF == 2 #if defined(_CALL_ELF) && _CALL_ELF == 2
......
...@@ -49,19 +49,22 @@ static bool same_kallsyms_reloc(const char *from_dir, char *to_dir) ...@@ -49,19 +49,22 @@ static bool same_kallsyms_reloc(const char *from_dir, char *to_dir)
char to[PATH_MAX]; char to[PATH_MAX];
const char *name; const char *name;
u64 addr1 = 0, addr2 = 0; u64 addr1 = 0, addr2 = 0;
int i; int i, err = -1;
scnprintf(from, sizeof(from), "%s/kallsyms", from_dir); scnprintf(from, sizeof(from), "%s/kallsyms", from_dir);
scnprintf(to, sizeof(to), "%s/kallsyms", to_dir); scnprintf(to, sizeof(to), "%s/kallsyms", to_dir);
for (i = 0; (name = ref_reloc_sym_names[i]) != NULL; i++) { for (i = 0; (name = ref_reloc_sym_names[i]) != NULL; i++) {
addr1 = kallsyms__get_function_start(from, name); err = kallsyms__get_function_start(from, name, &addr1);
if (addr1) if (!err)
break; break;
} }
if (name) if (err)
addr2 = kallsyms__get_function_start(to, name); return false;
if (kallsyms__get_function_start(to, name, &addr2))
return false;
return addr1 == addr2; return addr1 == addr2;
} }
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "tool.h" #include "tool.h"
#include "data.h" #include "data.h"
#include "sort.h" #include "sort.h"
#include "event.h"
#include "evlist.h" #include "evlist.h"
#include "evsel.h" #include "evsel.h"
#include <asm/bug.h> #include <asm/bug.h>
......
...@@ -159,6 +159,7 @@ int cmd_config(int argc, const char **argv) ...@@ -159,6 +159,7 @@ int cmd_config(int argc, const char **argv)
int i, ret = 0; int i, ret = 0;
struct perf_config_set *set; struct perf_config_set *set;
char *user_config = mkpath("%s/.perfconfig", getenv("HOME")); char *user_config = mkpath("%s/.perfconfig", getenv("HOME"));
const char *config_filename;
argc = parse_options(argc, argv, config_options, config_usage, argc = parse_options(argc, argv, config_options, config_usage,
PARSE_OPT_STOP_AT_NON_OPTION); PARSE_OPT_STOP_AT_NON_OPTION);
...@@ -175,6 +176,11 @@ int cmd_config(int argc, const char **argv) ...@@ -175,6 +176,11 @@ int cmd_config(int argc, const char **argv)
else if (use_user_config) else if (use_user_config)
config_exclusive_filename = user_config; config_exclusive_filename = user_config;
if (!config_exclusive_filename)
config_filename = user_config;
else
config_filename = config_exclusive_filename;
/* /*
* At only 'config' sub-command, individually use the config set * At only 'config' sub-command, individually use the config set
* because of reinitializing with options config file location. * because of reinitializing with options config file location.
...@@ -192,14 +198,10 @@ int cmd_config(int argc, const char **argv) ...@@ -192,14 +198,10 @@ int cmd_config(int argc, const char **argv)
parse_options_usage(config_usage, config_options, "l", 1); parse_options_usage(config_usage, config_options, "l", 1);
} else { } else {
ret = show_config(set); ret = show_config(set);
if (ret < 0) { if (ret < 0)
const char * config_filename = config_exclusive_filename;
if (!config_exclusive_filename)
config_filename = user_config;
pr_err("Nothing configured, " pr_err("Nothing configured, "
"please check your %s \n", config_filename); "please check your %s \n", config_filename);
} }
}
break; break;
default: default:
if (argc) { if (argc) {
...@@ -221,13 +223,8 @@ int cmd_config(int argc, const char **argv) ...@@ -221,13 +223,8 @@ int cmd_config(int argc, const char **argv)
if (value == NULL) if (value == NULL)
ret = show_spec_config(set, var); ret = show_spec_config(set, var);
else { else
const char *config_filename = config_exclusive_filename;
if (!config_exclusive_filename)
config_filename = user_config;
ret = set_config(set, config_filename, var, value); ret = set_config(set, config_filename, var, value);
}
free(arg); free(arg);
} }
} else } else
......
...@@ -27,13 +27,13 @@ ...@@ -27,13 +27,13 @@
#include "util/drv_configs.h" #include "util/drv_configs.h"
#include "util/evlist.h" #include "util/evlist.h"
#include "util/evsel.h" #include "util/evsel.h"
#include "util/event.h"
#include "util/machine.h" #include "util/machine.h"
#include "util/session.h" #include "util/session.h"
#include "util/symbol.h" #include "util/symbol.h"
#include "util/thread.h" #include "util/thread.h"
#include "util/thread_map.h" #include "util/thread_map.h"
#include "util/top.h" #include "util/top.h"
#include "util/util.h"
#include <linux/rbtree.h> #include <linux/rbtree.h>
#include <subcmd/parse-options.h> #include <subcmd/parse-options.h>
#include "util/parse-events.h" #include "util/parse-events.h"
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "builtin.h" #include "builtin.h"
#include "util/color.h" #include "util/color.h"
#include "util/debug.h" #include "util/debug.h"
#include "util/event.h"
#include "util/evlist.h" #include "util/evlist.h"
#include <subcmd/exec-cmd.h> #include <subcmd/exec-cmd.h>
#include "util/machine.h" #include "util/machine.h"
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <subcmd/parse-options.h> #include <subcmd/parse-options.h>
#include "util/bpf-loader.h" #include "util/bpf-loader.h"
#include "util/debug.h" #include "util/debug.h"
#include "util/event.h"
#include <api/fs/fs.h> #include <api/fs/fs.h>
#include <api/fs/tracing_path.h> #include <api/fs/tracing_path.h>
#include <errno.h> #include <errno.h>
......
#include "perf.h" #include "perf.h"
#include "util/debug.h" #include "util/debug.h"
#include "util/event.h"
#include "util/symbol.h" #include "util/symbol.h"
#include "util/sort.h" #include "util/sort.h"
#include "util/evsel.h" #include "util/evsel.h"
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#include "util/symbol.h" #include "util/symbol.h"
#include "util/sort.h" #include "util/sort.h"
#include "util/evsel.h" #include "util/evsel.h"
#include "util/event.h"
#include "util/evlist.h" #include "util/evlist.h"
#include "util/machine.h" #include "util/machine.h"
#include "util/thread.h" #include "util/thread.h"
......
#include "perf.h" #include "perf.h"
#include "util/debug.h" #include "util/debug.h"
#include "util/event.h"
#include "util/symbol.h" #include "util/symbol.h"
#include "util/sort.h" #include "util/sort.h"
#include "util/evsel.h" #include "util/evsel.h"
......
...@@ -61,6 +61,7 @@ int test__kmod_path__parse(int subtest __maybe_unused) ...@@ -61,6 +61,7 @@ int test__kmod_path__parse(int subtest __maybe_unused)
M("/xxxx/xxxx/x-x.ko", PERF_RECORD_MISC_KERNEL, true); M("/xxxx/xxxx/x-x.ko", PERF_RECORD_MISC_KERNEL, true);
M("/xxxx/xxxx/x-x.ko", PERF_RECORD_MISC_USER, false); M("/xxxx/xxxx/x-x.ko", PERF_RECORD_MISC_USER, false);
#ifdef HAVE_ZLIB_SUPPORT
/* path alloc_name alloc_ext kmod comp name ext */ /* path alloc_name alloc_ext kmod comp name ext */
T("/xxxx/xxxx/x.ko.gz", true , true , true, true, "[x]", "gz"); T("/xxxx/xxxx/x.ko.gz", true , true , true, true, "[x]", "gz");
T("/xxxx/xxxx/x.ko.gz", false , true , true, true, NULL , "gz"); T("/xxxx/xxxx/x.ko.gz", false , true , true, true, NULL , "gz");
...@@ -96,6 +97,7 @@ int test__kmod_path__parse(int subtest __maybe_unused) ...@@ -96,6 +97,7 @@ int test__kmod_path__parse(int subtest __maybe_unused)
M("x.ko.gz", PERF_RECORD_MISC_CPUMODE_UNKNOWN, true); M("x.ko.gz", PERF_RECORD_MISC_CPUMODE_UNKNOWN, true);
M("x.ko.gz", PERF_RECORD_MISC_KERNEL, true); M("x.ko.gz", PERF_RECORD_MISC_KERNEL, true);
M("x.ko.gz", PERF_RECORD_MISC_USER, false); M("x.ko.gz", PERF_RECORD_MISC_USER, false);
#endif
/* path alloc_name alloc_ext kmod comp name ext */ /* path alloc_name alloc_ext kmod comp name ext */
T("[test_module]", true , true , true, false, "[test_module]", NULL); T("[test_module]", true , true , true, false, "[test_module]", NULL);
......
#include <errno.h> #include <errno.h>
#include <stdio.h> #include <stdio.h>
#include <sys/epoll.h> #include <sys/epoll.h>
#include <util/util.h>
#include <util/evlist.h> #include <util/evlist.h>
#include <linux/filter.h> #include <linux/filter.h>
#include "tests.h" #include "tests.h"
......
...@@ -10,7 +10,10 @@ pthread_mutex_t ui__lock = PTHREAD_MUTEX_INITIALIZER; ...@@ -10,7 +10,10 @@ pthread_mutex_t ui__lock = PTHREAD_MUTEX_INITIALIZER;
void *perf_gtk_handle; void *perf_gtk_handle;
int use_browser = -1; int use_browser = -1;
#define PERF_GTK_DSO "libperf-gtk.so"
#ifdef HAVE_GTK2_SUPPORT #ifdef HAVE_GTK2_SUPPORT
static int setup_gtk_browser(void) static int setup_gtk_browser(void)
{ {
int (*perf_ui_init)(void); int (*perf_ui_init)(void);
......
...@@ -13,6 +13,7 @@ libperf-y += find_bit.o ...@@ -13,6 +13,7 @@ libperf-y += find_bit.o
libperf-y += kallsyms.o libperf-y += kallsyms.o
libperf-y += levenshtein.o libperf-y += levenshtein.o
libperf-y += llvm-utils.o libperf-y += llvm-utils.o
libperf-y += memswap.o
libperf-y += parse-events.o libperf-y += parse-events.o
libperf-y += perf_regs.o libperf-y += perf_regs.o
libperf-y += path.o libperf-y += path.o
......
...@@ -44,6 +44,10 @@ bool build_id_cache__cached(const char *sbuild_id); ...@@ -44,6 +44,10 @@ bool build_id_cache__cached(const char *sbuild_id);
int build_id_cache__add_s(const char *sbuild_id, 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); int build_id_cache__remove_s(const char *sbuild_id);
extern char buildid_dir[];
void set_buildid_dir(const char *dir);
void disable_buildid_cache(void); void disable_buildid_cache(void);
#endif #endif
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <unistd.h> #include <unistd.h>
#include <uapi/linux/mman.h> /* To get things like MAP_HUGETLB even on older libc headers */ #include <uapi/linux/mman.h> /* To get things like MAP_HUGETLB even on older libc headers */
#include <api/fs/fs.h> #include <api/fs/fs.h>
#include <linux/perf_event.h>
#include "event.h" #include "event.h"
#include "debug.h" #include "debug.h"
#include "hist.h" #include "hist.h"
...@@ -767,15 +768,16 @@ static int find_symbol_cb(void *arg, const char *name, char type, ...@@ -767,15 +768,16 @@ static int find_symbol_cb(void *arg, const char *name, char type,
return 1; return 1;
} }
u64 kallsyms__get_function_start(const char *kallsyms_filename, int kallsyms__get_function_start(const char *kallsyms_filename,
const char *symbol_name) const char *symbol_name, u64 *addr)
{ {
struct process_symbol_args args = { .name = symbol_name, }; struct process_symbol_args args = { .name = symbol_name, };
if (kallsyms__parse(kallsyms_filename, &args, find_symbol_cb) <= 0) if (kallsyms__parse(kallsyms_filename, &args, find_symbol_cb) <= 0)
return 0; return -1;
return args.start; *addr = args.start;
return 0;
} }
int perf_event__synthesize_kernel_mmap(struct perf_tool *tool, int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
......
...@@ -229,7 +229,7 @@ struct build_id_event { ...@@ -229,7 +229,7 @@ struct build_id_event {
enum perf_user_event_type { /* above any possible kernel type */ enum perf_user_event_type { /* above any possible kernel type */
PERF_RECORD_USER_TYPE_START = 64, PERF_RECORD_USER_TYPE_START = 64,
PERF_RECORD_HEADER_ATTR = 64, PERF_RECORD_HEADER_ATTR = 64,
PERF_RECORD_HEADER_EVENT_TYPE = 65, /* depreceated */ PERF_RECORD_HEADER_EVENT_TYPE = 65, /* deprecated */
PERF_RECORD_HEADER_TRACING_DATA = 66, PERF_RECORD_HEADER_TRACING_DATA = 66,
PERF_RECORD_HEADER_BUILD_ID = 67, PERF_RECORD_HEADER_BUILD_ID = 67,
PERF_RECORD_FINISHED_ROUND = 68, PERF_RECORD_FINISHED_ROUND = 68,
...@@ -675,10 +675,18 @@ size_t perf_event__fprintf_cpu_map(union perf_event *event, FILE *fp); ...@@ -675,10 +675,18 @@ size_t perf_event__fprintf_cpu_map(union perf_event *event, FILE *fp);
size_t perf_event__fprintf_namespaces(union perf_event *event, FILE *fp); size_t perf_event__fprintf_namespaces(union perf_event *event, FILE *fp);
size_t perf_event__fprintf(union perf_event *event, FILE *fp); size_t perf_event__fprintf(union perf_event *event, FILE *fp);
u64 kallsyms__get_function_start(const char *kallsyms_filename, int kallsyms__get_function_start(const char *kallsyms_filename,
const char *symbol_name); const char *symbol_name, u64 *addr);
void *cpu_map_data__alloc(struct cpu_map *map, size_t *size, u16 *type, int *max); void *cpu_map_data__alloc(struct cpu_map *map, size_t *size, u16 *type, int *max);
void cpu_map_data__synthesize(struct cpu_map_data *data, struct cpu_map *map, void cpu_map_data__synthesize(struct cpu_map_data *data, struct cpu_map *map,
u16 type, int max); u16 type, int max);
void event_attr_init(struct perf_event_attr *attr);
int perf_event_paranoid(void);
extern int sysctl_perf_event_max_stack;
extern int sysctl_perf_event_max_contexts_per_stack;
#endif /* __PERF_RECORD_H */ #endif /* __PERF_RECORD_H */
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "asm/bug.h" #include "asm/bug.h"
#include "callchain.h" #include "callchain.h"
#include "cgroup.h" #include "cgroup.h"
#include "event.h"
#include "evsel.h" #include "evsel.h"
#include "evlist.h" #include "evlist.h"
#include "util.h" #include "util.h"
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "evlist.h" #include "evlist.h"
#include "evsel.h" #include "evsel.h"
#include "header.h" #include "header.h"
#include "memswap.h"
#include "../perf.h" #include "../perf.h"
#include "trace-event.h" #include "trace-event.h"
#include "session.h" #include "session.h"
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "../perf.h" #include "../perf.h"
#include "session.h" #include "session.h"
#include "machine.h" #include "machine.h"
#include "memswap.h"
#include "sort.h" #include "sort.h"
#include "tool.h" #include "tool.h"
#include "event.h" #include "event.h"
......
...@@ -796,11 +796,11 @@ const char *ref_reloc_sym_names[] = {"_text", "_stext", NULL}; ...@@ -796,11 +796,11 @@ const char *ref_reloc_sym_names[] = {"_text", "_stext", NULL};
* Returns the name of the start symbol in *symbol_name. Pass in NULL as * Returns the name of the start symbol in *symbol_name. Pass in NULL as
* symbol_name if it's not that important. * symbol_name if it's not that important.
*/ */
static u64 machine__get_running_kernel_start(struct machine *machine, static int machine__get_running_kernel_start(struct machine *machine,
const char **symbol_name) const char **symbol_name, u64 *start)
{ {
char filename[PATH_MAX]; char filename[PATH_MAX];
int i; int i, err = -1;
const char *name; const char *name;
u64 addr = 0; u64 addr = 0;
...@@ -810,21 +810,28 @@ static u64 machine__get_running_kernel_start(struct machine *machine, ...@@ -810,21 +810,28 @@ static u64 machine__get_running_kernel_start(struct machine *machine,
return 0; return 0;
for (i = 0; (name = ref_reloc_sym_names[i]) != NULL; i++) { for (i = 0; (name = ref_reloc_sym_names[i]) != NULL; i++) {
addr = kallsyms__get_function_start(filename, name); err = kallsyms__get_function_start(filename, name, &addr);
if (addr) if (!err)
break; break;
} }
if (err)
return -1;
if (symbol_name) if (symbol_name)
*symbol_name = name; *symbol_name = name;
return addr; *start = addr;
return 0;
} }
int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel) int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel)
{ {
int type; int type;
u64 start = machine__get_running_kernel_start(machine, NULL); u64 start = 0;
if (machine__get_running_kernel_start(machine, NULL, &start))
return -1;
/* In case of renewal the kernel map, destroy previous one */ /* In case of renewal the kernel map, destroy previous one */
machine__destroy_kernel_maps(machine); machine__destroy_kernel_maps(machine);
...@@ -1185,8 +1192,8 @@ static int machine__create_modules(struct machine *machine) ...@@ -1185,8 +1192,8 @@ static int machine__create_modules(struct machine *machine)
int machine__create_kernel_maps(struct machine *machine) int machine__create_kernel_maps(struct machine *machine)
{ {
struct dso *kernel = machine__get_kernel(machine); struct dso *kernel = machine__get_kernel(machine);
const char *name; const char *name = NULL;
u64 addr; u64 addr = 0;
int ret; int ret;
if (kernel == NULL) if (kernel == NULL)
...@@ -1211,8 +1218,7 @@ int machine__create_kernel_maps(struct machine *machine) ...@@ -1211,8 +1218,7 @@ int machine__create_kernel_maps(struct machine *machine)
*/ */
map_groups__fixup_end(&machine->kmaps); map_groups__fixup_end(&machine->kmaps);
addr = machine__get_running_kernel_start(machine, &name); if (machine__get_running_kernel_start(machine, &name, &addr)) {
if (!addr) {
} else if (maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, name, addr)) { } else if (maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, name, addr)) {
machine__destroy_kernel_maps(machine); machine__destroy_kernel_maps(machine);
return -1; return -1;
......
...@@ -325,11 +325,6 @@ int map__load(struct map *map) ...@@ -325,11 +325,6 @@ int map__load(struct map *map)
return 0; return 0;
} }
int __weak arch__compare_symbol_names(const char *namea, const char *nameb)
{
return strcmp(namea, nameb);
}
struct symbol *map__find_symbol(struct map *map, u64 addr) struct symbol *map__find_symbol(struct map *map, u64 addr)
{ {
if (map__load(map) < 0) if (map__load(map) < 0)
......
...@@ -130,13 +130,14 @@ struct thread; ...@@ -130,13 +130,14 @@ struct thread;
*/ */
#define __map__for_each_symbol_by_name(map, sym_name, pos) \ #define __map__for_each_symbol_by_name(map, sym_name, pos) \
for (pos = map__find_symbol_by_name(map, sym_name); \ for (pos = map__find_symbol_by_name(map, sym_name); \
pos && arch__compare_symbol_names(pos->name, sym_name) == 0; \ pos && \
!symbol__match_symbol_name(pos->name, sym_name, \
SYMBOL_TAG_INCLUDE__DEFAULT_ONLY); \
pos = symbol__next_by_name(pos)) pos = symbol__next_by_name(pos))
#define map__for_each_symbol_by_name(map, sym_name, pos) \ #define map__for_each_symbol_by_name(map, sym_name, pos) \
__map__for_each_symbol_by_name(map, sym_name, (pos)) __map__for_each_symbol_by_name(map, sym_name, (pos))
int arch__compare_symbol_names(const char *namea, const char *nameb);
void map__init(struct map *map, enum map_type type, void map__init(struct map *map, enum map_type type,
u64 start, u64 end, u64 pgoff, struct dso *dso); u64 start, u64 end, u64 pgoff, struct dso *dso);
struct map *map__new(struct machine *machine, u64 start, u64 len, struct map *map__new(struct machine *machine, u64 start, u64 len,
......
#include <byteswap.h>
#include "memswap.h"
#include <linux/types.h>
void mem_bswap_32(void *src, int byte_size)
{
u32 *m = src;
while (byte_size > 0) {
*m = bswap_32(*m);
byte_size -= sizeof(u32);
++m;
}
}
void mem_bswap_64(void *src, int byte_size)
{
u64 *m = src;
while (byte_size > 0) {
*m = bswap_64(*m);
byte_size -= sizeof(u64);
++m;
}
}
#ifndef PERF_MEMSWAP_H_
#define PERF_MEMSWAP_H_
void mem_bswap_64(void *src, int byte_size);
void mem_bswap_32(void *src, int byte_size);
#endif /* PERF_MEMSWAP_H_ */
...@@ -28,7 +28,9 @@ ...@@ -28,7 +28,9 @@
#include <linux/bitmap.h> #include <linux/bitmap.h>
#include <linux/time64.h> #include <linux/time64.h>
#include "../util.h" #include <stdbool.h>
/* perl needs the following define, right after including stdbool.h */
#define HAS_BOOL
#include <EXTERN.h> #include <EXTERN.h>
#include <perl.h> #include <perl.h>
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "evlist.h" #include "evlist.h"
#include "evsel.h" #include "evsel.h"
#include "memswap.h"
#include "session.h" #include "session.h"
#include "tool.h" #include "tool.h"
#include "sort.h" #include "sort.h"
......
...@@ -3,15 +3,6 @@ ...@@ -3,15 +3,6 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <errno.h> #include <errno.h>
int prefixcmp(const char *str, const char *prefix)
{
for (; ; str++, prefix++)
if (!*prefix)
return 0;
else if (*str != *prefix)
return (unsigned char)*prefix - (unsigned char)*str;
}
/* /*
* Used as the default ->buf value, so that people can always assume * Used as the default ->buf value, so that people can always assume
* buf is non NULL and ->buf is NUL terminated even for a freshly * buf is non NULL and ->buf is NUL terminated even for a freshly
......
...@@ -90,6 +90,17 @@ static int prefix_underscores_count(const char *str) ...@@ -90,6 +90,17 @@ static int prefix_underscores_count(const char *str)
return tail - str; return tail - str;
} }
int __weak arch__compare_symbol_names(const char *namea, const char *nameb)
{
return strcmp(namea, nameb);
}
int __weak arch__compare_symbol_names_n(const char *namea, const char *nameb,
unsigned int n)
{
return strncmp(namea, nameb, n);
}
int __weak arch__choose_best_symbol(struct symbol *syma, int __weak arch__choose_best_symbol(struct symbol *syma,
struct symbol *symb __maybe_unused) struct symbol *symb __maybe_unused)
{ {
...@@ -399,8 +410,26 @@ static void symbols__sort_by_name(struct rb_root *symbols, ...@@ -399,8 +410,26 @@ static void symbols__sort_by_name(struct rb_root *symbols,
} }
} }
int symbol__match_symbol_name(const char *name, const char *str,
enum symbol_tag_include includes)
{
const char *versioning;
if (includes == SYMBOL_TAG_INCLUDE__DEFAULT_ONLY &&
(versioning = strstr(name, "@@"))) {
int len = strlen(str);
if (len < versioning - name)
len = versioning - name;
return arch__compare_symbol_names_n(name, str, len);
} else
return arch__compare_symbol_names(name, str);
}
static struct symbol *symbols__find_by_name(struct rb_root *symbols, static struct symbol *symbols__find_by_name(struct rb_root *symbols,
const char *name) const char *name,
enum symbol_tag_include includes)
{ {
struct rb_node *n; struct rb_node *n;
struct symbol_name_rb_node *s = NULL; struct symbol_name_rb_node *s = NULL;
...@@ -414,11 +443,11 @@ static struct symbol *symbols__find_by_name(struct rb_root *symbols, ...@@ -414,11 +443,11 @@ static struct symbol *symbols__find_by_name(struct rb_root *symbols,
int cmp; int cmp;
s = rb_entry(n, struct symbol_name_rb_node, rb_node); s = rb_entry(n, struct symbol_name_rb_node, rb_node);
cmp = arch__compare_symbol_names(name, s->sym.name); cmp = symbol__match_symbol_name(s->sym.name, name, includes);
if (cmp < 0) if (cmp > 0)
n = n->rb_left; n = n->rb_left;
else if (cmp > 0) else if (cmp < 0)
n = n->rb_right; n = n->rb_right;
else else
break; break;
...@@ -427,6 +456,7 @@ static struct symbol *symbols__find_by_name(struct rb_root *symbols, ...@@ -427,6 +456,7 @@ static struct symbol *symbols__find_by_name(struct rb_root *symbols,
if (n == NULL) if (n == NULL)
return NULL; return NULL;
if (includes != SYMBOL_TAG_INCLUDE__DEFAULT_ONLY)
/* return first symbol that has same name (if any) */ /* return first symbol that has same name (if any) */
for (n = rb_prev(n); n; n = rb_prev(n)) { for (n = rb_prev(n); n; n = rb_prev(n)) {
struct symbol_name_rb_node *tmp; struct symbol_name_rb_node *tmp;
...@@ -466,7 +496,7 @@ void dso__insert_symbol(struct dso *dso, enum map_type type, struct symbol *sym) ...@@ -466,7 +496,7 @@ void dso__insert_symbol(struct dso *dso, enum map_type type, struct symbol *sym)
struct symbol *dso__find_symbol(struct dso *dso, struct symbol *dso__find_symbol(struct dso *dso,
enum map_type type, u64 addr) enum map_type type, u64 addr)
{ {
if (dso->last_find_result[type].addr != addr) { if (dso->last_find_result[type].addr != addr || dso->last_find_result[type].symbol == NULL) {
dso->last_find_result[type].addr = addr; dso->last_find_result[type].addr = addr;
dso->last_find_result[type].symbol = symbols__find(&dso->symbols[type], addr); dso->last_find_result[type].symbol = symbols__find(&dso->symbols[type], addr);
} }
...@@ -503,7 +533,12 @@ struct symbol *symbol__next_by_name(struct symbol *sym) ...@@ -503,7 +533,12 @@ struct symbol *symbol__next_by_name(struct symbol *sym)
struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type, struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type,
const char *name) const char *name)
{ {
return symbols__find_by_name(&dso->symbol_names[type], name); struct symbol *s = symbols__find_by_name(&dso->symbol_names[type], name,
SYMBOL_TAG_INCLUDE__NONE);
if (!s)
s = symbols__find_by_name(&dso->symbol_names[type], name,
SYMBOL_TAG_INCLUDE__DEFAULT_ONLY);
return s;
} }
void dso__sort_by_name(struct dso *dso, enum map_type type) void dso__sort_by_name(struct dso *dso, enum map_type type)
...@@ -1075,8 +1110,9 @@ static int validate_kcore_addresses(const char *kallsyms_filename, ...@@ -1075,8 +1110,9 @@ static int validate_kcore_addresses(const char *kallsyms_filename,
if (kmap->ref_reloc_sym && kmap->ref_reloc_sym->name) { if (kmap->ref_reloc_sym && kmap->ref_reloc_sym->name) {
u64 start; u64 start;
start = kallsyms__get_function_start(kallsyms_filename, if (kallsyms__get_function_start(kallsyms_filename,
kmap->ref_reloc_sym->name); kmap->ref_reloc_sym->name, &start))
return -ENOENT;
if (start != kmap->ref_reloc_sym->addr) if (start != kmap->ref_reloc_sym->addr)
return -EINVAL; return -EINVAL;
} }
...@@ -1248,9 +1284,7 @@ static int kallsyms__delta(struct map *map, const char *filename, u64 *delta) ...@@ -1248,9 +1284,7 @@ static int kallsyms__delta(struct map *map, const char *filename, u64 *delta)
if (!kmap->ref_reloc_sym || !kmap->ref_reloc_sym->name) if (!kmap->ref_reloc_sym || !kmap->ref_reloc_sym->name)
return 0; return 0;
addr = kallsyms__get_function_start(filename, if (kallsyms__get_function_start(filename, kmap->ref_reloc_sym->name, &addr))
kmap->ref_reloc_sym->name);
if (!addr)
return -1; return -1;
*delta = addr - kmap->ref_reloc_sym->addr; *delta = addr - kmap->ref_reloc_sym->addr;
......
...@@ -348,8 +348,19 @@ void arch__sym_update(struct symbol *s, GElf_Sym *sym); ...@@ -348,8 +348,19 @@ void arch__sym_update(struct symbol *s, GElf_Sym *sym);
#define SYMBOL_A 0 #define SYMBOL_A 0
#define SYMBOL_B 1 #define SYMBOL_B 1
int arch__compare_symbol_names(const char *namea, const char *nameb);
int arch__compare_symbol_names_n(const char *namea, const char *nameb,
unsigned int n);
int arch__choose_best_symbol(struct symbol *syma, struct symbol *symb); int arch__choose_best_symbol(struct symbol *syma, struct symbol *symb);
enum symbol_tag_include {
SYMBOL_TAG_INCLUDE__NONE = 0,
SYMBOL_TAG_INCLUDE__DEFAULT_ONLY
};
int symbol__match_symbol_name(const char *namea, const char *nameb,
enum symbol_tag_include includes);
/* structure containing an SDT note's info */ /* structure containing an SDT note's info */
struct sdt_note { struct sdt_note {
char *name; /* name of the note*/ char *name; /* name of the note*/
......
#include "units.h" #include "units.h"
#include <inttypes.h> #include <inttypes.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/time64.h> #include <linux/time64.h>
unsigned long parse_tag_value(const char *str, struct parse_tag *tags)
{
struct parse_tag *i = tags;
while (i->tag) {
char *s = strchr(str, i->tag);
if (s) {
unsigned long int value;
char *endptr;
value = strtoul(str, &endptr, 10);
if (s != endptr)
break;
if (value > ULONG_MAX / i->mult)
break;
value *= i->mult;
return value;
}
i++;
}
return (unsigned long) -1;
}
unsigned long convert_unit(unsigned long value, char *unit) unsigned long convert_unit(unsigned long value, char *unit)
{ {
*unit = ' '; *unit = ' ';
......
...@@ -4,6 +4,13 @@ ...@@ -4,6 +4,13 @@
#include <stddef.h> #include <stddef.h>
#include <linux/types.h> #include <linux/types.h>
struct parse_tag {
char tag;
int mult;
};
unsigned long parse_tag_value(const char *str, struct parse_tag *tags);
unsigned long convert_unit(unsigned long value, char *unit); unsigned long convert_unit(unsigned long value, char *unit);
int unit_number__scnprintf(char *buf, size_t size, u64 n); int unit_number__scnprintf(char *buf, size_t size, u64 n);
......
...@@ -13,7 +13,6 @@ ...@@ -13,7 +13,6 @@
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include <limits.h> #include <limits.h>
#include <byteswap.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/log2.h> #include <linux/log2.h>
#include <linux/time64.h> #include <linux/time64.h>
...@@ -335,33 +334,6 @@ int hex2u64(const char *ptr, u64 *long_val) ...@@ -335,33 +334,6 @@ int hex2u64(const char *ptr, u64 *long_val)
return p - ptr; return p - ptr;
} }
unsigned long parse_tag_value(const char *str, struct parse_tag *tags)
{
struct parse_tag *i = tags;
while (i->tag) {
char *s;
s = strchr(str, i->tag);
if (s) {
unsigned long int value;
char *endptr;
value = strtoul(str, &endptr, 10);
if (s != endptr)
break;
if (value > ULONG_MAX / i->mult)
break;
value *= i->mult;
return value;
}
i++;
}
return (unsigned long) -1;
}
int perf_event_paranoid(void) int perf_event_paranoid(void)
{ {
int value; int value;
...@@ -372,27 +344,6 @@ int perf_event_paranoid(void) ...@@ -372,27 +344,6 @@ int perf_event_paranoid(void)
return value; return value;
} }
void mem_bswap_32(void *src, int byte_size)
{
u32 *m = src;
while (byte_size > 0) {
*m = bswap_32(*m);
byte_size -= sizeof(u32);
++m;
}
}
void mem_bswap_64(void *src, int byte_size)
{
u64 *m = src;
while (byte_size > 0) {
*m = bswap_64(*m);
byte_size -= sizeof(u64);
++m;
}
}
bool find_process(const char *name) bool find_process(const char *name)
{ {
size_t len = strlen(name); size_t len = strlen(name);
......
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
#define _BSD_SOURCE 1 #define _BSD_SOURCE 1
/* glibc 2.20 deprecates _BSD_SOURCE in favour of _DEFAULT_SOURCE */ /* glibc 2.20 deprecates _BSD_SOURCE in favour of _DEFAULT_SOURCE */
#define _DEFAULT_SOURCE 1 #define _DEFAULT_SOURCE 1
#define HAS_BOOL
#include <fcntl.h> #include <fcntl.h>
#include <stdbool.h> #include <stdbool.h>
...@@ -14,8 +13,6 @@ ...@@ -14,8 +13,6 @@
#include <stdarg.h> #include <stdarg.h>
#include <linux/types.h> #include <linux/types.h>
extern char buildid_dir[];
#ifdef __GNUC__ #ifdef __GNUC__
#define NORETURN __attribute__((__noreturn__)) #define NORETURN __attribute__((__noreturn__))
#else #else
...@@ -25,8 +22,6 @@ extern char buildid_dir[]; ...@@ -25,8 +22,6 @@ extern char buildid_dir[];
#endif #endif
#endif #endif
#define PERF_GTK_DSO "libperf-gtk.so"
/* General helper functions */ /* General helper functions */
void usage(const char *err) NORETURN; void usage(const char *err) NORETURN;
void die(const char *err, ...) NORETURN __attribute__((format (printf, 1, 2))); void die(const char *err, ...) NORETURN __attribute__((format (printf, 1, 2)));
...@@ -35,9 +30,6 @@ void warning(const char *err, ...) __attribute__((format (printf, 1, 2))); ...@@ -35,9 +30,6 @@ void warning(const char *err, ...) __attribute__((format (printf, 1, 2)));
void set_warning_routine(void (*routine)(const char *err, va_list params)); void set_warning_routine(void (*routine)(const char *err, va_list params));
int prefixcmp(const char *str, const char *prefix);
void set_buildid_dir(const char *dir);
static inline void *zalloc(size_t size) static inline void *zalloc(size_t size)
{ {
return calloc(1, size); return calloc(1, size);
...@@ -59,29 +51,11 @@ int copyfile_offset(int fromfd, loff_t from_ofs, int tofd, loff_t to_ofs, u64 si ...@@ -59,29 +51,11 @@ int copyfile_offset(int fromfd, loff_t from_ofs, int tofd, loff_t to_ofs, u64 si
ssize_t readn(int fd, void *buf, size_t n); ssize_t readn(int fd, void *buf, size_t n);
ssize_t writen(int fd, void *buf, size_t n); ssize_t writen(int fd, void *buf, size_t n);
struct perf_event_attr;
void event_attr_init(struct perf_event_attr *attr);
size_t hex_width(u64 v); size_t hex_width(u64 v);
int hex2u64(const char *ptr, u64 *val); int hex2u64(const char *ptr, u64 *val);
extern unsigned int page_size; extern unsigned int page_size;
extern int cacheline_size; extern int cacheline_size;
extern int sysctl_perf_event_max_stack;
extern int sysctl_perf_event_max_contexts_per_stack;
struct parse_tag {
char tag;
int mult;
};
unsigned long parse_tag_value(const char *str, struct parse_tag *tags);
int perf_event_paranoid(void);
void mem_bswap_64(void *src, int byte_size);
void mem_bswap_32(void *src, int byte_size);
bool find_process(const char *name); bool find_process(const char *name);
......
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