Commit e7c632fc 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 fixes from Thomas Gleixner:

 - plug a memory leak in the intel pmu init code

 - clang fixes

 - tooling fix to avoid including kernel headers

 - a fix for jvmti to generate correct debug information for inlined
   code

 - replace backtick with a regular shell function

 - fix the build in hardened environments

* 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  perf/x86/intel: Plug memory leak in intel_pmu_init()
  x86/asm: Allow again using asm.h when building for the 'bpf' clang target
  tools arch s390: Do not include header files from the kernel sources
  perf jvmti: Generate correct debug information for inlined code
  perf tools: Fix up build in hardened environments
  perf tools: Use shell function for perl cflags retrieval
parents 88fa025d 7ad1437d
...@@ -3847,6 +3847,8 @@ static struct attribute *intel_pmu_attrs[] = { ...@@ -3847,6 +3847,8 @@ static struct attribute *intel_pmu_attrs[] = {
__init int intel_pmu_init(void) __init int intel_pmu_init(void)
{ {
struct attribute **extra_attr = NULL;
struct attribute **to_free = NULL;
union cpuid10_edx edx; union cpuid10_edx edx;
union cpuid10_eax eax; union cpuid10_eax eax;
union cpuid10_ebx ebx; union cpuid10_ebx ebx;
...@@ -3854,7 +3856,6 @@ __init int intel_pmu_init(void) ...@@ -3854,7 +3856,6 @@ __init int intel_pmu_init(void)
unsigned int unused; unsigned int unused;
struct extra_reg *er; struct extra_reg *er;
int version, i; int version, i;
struct attribute **extra_attr = NULL;
char *name; char *name;
if (!cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) { if (!cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) {
...@@ -4294,6 +4295,7 @@ __init int intel_pmu_init(void) ...@@ -4294,6 +4295,7 @@ __init int intel_pmu_init(void)
extra_attr = boot_cpu_has(X86_FEATURE_RTM) ? extra_attr = boot_cpu_has(X86_FEATURE_RTM) ?
hsw_format_attr : nhm_format_attr; hsw_format_attr : nhm_format_attr;
extra_attr = merge_attr(extra_attr, skl_format_attr); extra_attr = merge_attr(extra_attr, skl_format_attr);
to_free = extra_attr;
x86_pmu.cpu_events = get_hsw_events_attrs(); x86_pmu.cpu_events = get_hsw_events_attrs();
intel_pmu_pebs_data_source_skl( intel_pmu_pebs_data_source_skl(
boot_cpu_data.x86_model == INTEL_FAM6_SKYLAKE_X); boot_cpu_data.x86_model == INTEL_FAM6_SKYLAKE_X);
...@@ -4401,6 +4403,7 @@ __init int intel_pmu_init(void) ...@@ -4401,6 +4403,7 @@ __init int intel_pmu_init(void)
pr_cont("full-width counters, "); pr_cont("full-width counters, ");
} }
kfree(to_free);
return 0; return 0;
} }
......
...@@ -136,6 +136,7 @@ ...@@ -136,6 +136,7 @@
#endif #endif
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#ifndef __BPF__
/* /*
* This output constraint should be used for any inline asm which has a "call" * This output constraint should be used for any inline asm which has a "call"
* instruction. Otherwise the asm may be inserted before the frame pointer * instruction. Otherwise the asm may be inserted before the frame pointer
...@@ -145,5 +146,6 @@ ...@@ -145,5 +146,6 @@
register unsigned long current_stack_pointer asm(_ASM_SP); register unsigned long current_stack_pointer asm(_ASM_SP);
#define ASM_CALL_CONSTRAINT "+r" (current_stack_pointer) #define ASM_CALL_CONSTRAINT "+r" (current_stack_pointer)
#endif #endif
#endif
#endif /* _ASM_X86_ASM_H */ #endif /* _ASM_X86_ASM_H */
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef _ASM_S390_PERF_REGS_H
#define _ASM_S390_PERF_REGS_H
enum perf_event_s390_regs {
PERF_REG_S390_R0,
PERF_REG_S390_R1,
PERF_REG_S390_R2,
PERF_REG_S390_R3,
PERF_REG_S390_R4,
PERF_REG_S390_R5,
PERF_REG_S390_R6,
PERF_REG_S390_R7,
PERF_REG_S390_R8,
PERF_REG_S390_R9,
PERF_REG_S390_R10,
PERF_REG_S390_R11,
PERF_REG_S390_R12,
PERF_REG_S390_R13,
PERF_REG_S390_R14,
PERF_REG_S390_R15,
PERF_REG_S390_FP0,
PERF_REG_S390_FP1,
PERF_REG_S390_FP2,
PERF_REG_S390_FP3,
PERF_REG_S390_FP4,
PERF_REG_S390_FP5,
PERF_REG_S390_FP6,
PERF_REG_S390_FP7,
PERF_REG_S390_FP8,
PERF_REG_S390_FP9,
PERF_REG_S390_FP10,
PERF_REG_S390_FP11,
PERF_REG_S390_FP12,
PERF_REG_S390_FP13,
PERF_REG_S390_FP14,
PERF_REG_S390_FP15,
PERF_REG_S390_MASK,
PERF_REG_S390_PC,
PERF_REG_S390_MAX
};
#endif /* _ASM_S390_PERF_REGS_H */
...@@ -188,9 +188,7 @@ ifdef PYTHON_CONFIG ...@@ -188,9 +188,7 @@ ifdef PYTHON_CONFIG
PYTHON_EMBED_LDFLAGS := $(call strip-libs,$(PYTHON_EMBED_LDOPTS)) PYTHON_EMBED_LDFLAGS := $(call strip-libs,$(PYTHON_EMBED_LDOPTS))
PYTHON_EMBED_LIBADD := $(call grep-libs,$(PYTHON_EMBED_LDOPTS)) -lutil PYTHON_EMBED_LIBADD := $(call grep-libs,$(PYTHON_EMBED_LDOPTS)) -lutil
PYTHON_EMBED_CCOPTS := $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null) PYTHON_EMBED_CCOPTS := $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null)
ifeq ($(CC_NO_CLANG), 1)
PYTHON_EMBED_CCOPTS := $(filter-out -specs=%,$(PYTHON_EMBED_CCOPTS)) PYTHON_EMBED_CCOPTS := $(filter-out -specs=%,$(PYTHON_EMBED_CCOPTS))
endif
FLAGS_PYTHON_EMBED := $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS) FLAGS_PYTHON_EMBED := $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS)
endif endif
...@@ -576,14 +574,15 @@ ifndef NO_GTK2 ...@@ -576,14 +574,15 @@ ifndef NO_GTK2
endif endif
endif endif
ifdef NO_LIBPERL ifdef NO_LIBPERL
CFLAGS += -DNO_LIBPERL CFLAGS += -DNO_LIBPERL
else else
PERL_EMBED_LDOPTS = $(shell perl -MExtUtils::Embed -e ldopts 2>/dev/null) PERL_EMBED_LDOPTS = $(shell perl -MExtUtils::Embed -e ldopts 2>/dev/null)
PERL_EMBED_LDFLAGS = $(call strip-libs,$(PERL_EMBED_LDOPTS)) PERL_EMBED_LDFLAGS = $(call strip-libs,$(PERL_EMBED_LDOPTS))
PERL_EMBED_LIBADD = $(call grep-libs,$(PERL_EMBED_LDOPTS)) PERL_EMBED_LIBADD = $(call grep-libs,$(PERL_EMBED_LDOPTS))
PERL_EMBED_CCOPTS = `perl -MExtUtils::Embed -e ccopts 2>/dev/null` PERL_EMBED_CCOPTS = $(shell perl -MExtUtils::Embed -e ccopts 2>/dev/null)
PERL_EMBED_CCOPTS := $(filter-out -specs=%,$(PERL_EMBED_CCOPTS))
PERL_EMBED_LDOPTS := $(filter-out -specs=%,$(PERL_EMBED_LDOPTS))
FLAGS_PERL_EMBED=$(PERL_EMBED_CCOPTS) $(PERL_EMBED_LDOPTS) FLAGS_PERL_EMBED=$(PERL_EMBED_CCOPTS) $(PERL_EMBED_LDOPTS)
ifneq ($(feature-libperl), 1) ifneq ($(feature-libperl), 1)
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <linux/types.h> #include <linux/types.h>
#include <../../../../arch/s390/include/uapi/asm/perf_regs.h> #include <asm/perf_regs.h>
void perf_regs_load(u64 *regs); void perf_regs_load(u64 *regs);
......
...@@ -21,6 +21,7 @@ arch/x86/include/asm/cpufeatures.h ...@@ -21,6 +21,7 @@ arch/x86/include/asm/cpufeatures.h
arch/arm/include/uapi/asm/perf_regs.h arch/arm/include/uapi/asm/perf_regs.h
arch/arm64/include/uapi/asm/perf_regs.h arch/arm64/include/uapi/asm/perf_regs.h
arch/powerpc/include/uapi/asm/perf_regs.h arch/powerpc/include/uapi/asm/perf_regs.h
arch/s390/include/uapi/asm/perf_regs.h
arch/x86/include/uapi/asm/perf_regs.h arch/x86/include/uapi/asm/perf_regs.h
arch/x86/include/uapi/asm/kvm.h arch/x86/include/uapi/asm/kvm.h
arch/x86/include/uapi/asm/kvm_perf.h arch/x86/include/uapi/asm/kvm_perf.h
......
...@@ -384,13 +384,13 @@ jvmti_write_code(void *agent, char const *sym, ...@@ -384,13 +384,13 @@ jvmti_write_code(void *agent, char const *sym,
} }
int int
jvmti_write_debug_info(void *agent, uint64_t code, const char *file, jvmti_write_debug_info(void *agent, uint64_t code,
jvmti_line_info_t *li, int nr_lines) int nr_lines, jvmti_line_info_t *li,
const char * const * file_names)
{ {
struct jr_code_debug_info rec; struct jr_code_debug_info rec;
size_t sret, len, size, flen; size_t sret, len, size, flen = 0;
uint64_t addr; uint64_t addr;
const char *fn = file;
FILE *fp = agent; FILE *fp = agent;
int i; int i;
...@@ -405,7 +405,9 @@ jvmti_write_debug_info(void *agent, uint64_t code, const char *file, ...@@ -405,7 +405,9 @@ jvmti_write_debug_info(void *agent, uint64_t code, const char *file,
return -1; return -1;
} }
flen = strlen(file) + 1; for (i = 0; i < nr_lines; ++i) {
flen += strlen(file_names[i]) + 1;
}
rec.p.id = JIT_CODE_DEBUG_INFO; rec.p.id = JIT_CODE_DEBUG_INFO;
size = sizeof(rec); size = sizeof(rec);
...@@ -421,7 +423,7 @@ jvmti_write_debug_info(void *agent, uint64_t code, const char *file, ...@@ -421,7 +423,7 @@ jvmti_write_debug_info(void *agent, uint64_t code, const char *file,
* file[] : source file name * file[] : source file name
*/ */
size += nr_lines * sizeof(struct debug_entry); size += nr_lines * sizeof(struct debug_entry);
size += flen * nr_lines; size += flen;
rec.p.total_size = size; rec.p.total_size = size;
/* /*
...@@ -452,7 +454,7 @@ jvmti_write_debug_info(void *agent, uint64_t code, const char *file, ...@@ -452,7 +454,7 @@ jvmti_write_debug_info(void *agent, uint64_t code, const char *file,
if (sret != 1) if (sret != 1)
goto error; goto error;
sret = fwrite_unlocked(fn, flen, 1, fp); sret = fwrite_unlocked(file_names[i], strlen(file_names[i]) + 1, 1, fp);
if (sret != 1) if (sret != 1)
goto error; goto error;
} }
......
...@@ -14,6 +14,7 @@ typedef struct { ...@@ -14,6 +14,7 @@ typedef struct {
unsigned long pc; unsigned long pc;
int line_number; int line_number;
int discrim; /* discriminator -- 0 for now */ int discrim; /* discriminator -- 0 for now */
jmethodID methodID;
} jvmti_line_info_t; } jvmti_line_info_t;
void *jvmti_open(void); void *jvmti_open(void);
...@@ -22,11 +23,9 @@ int jvmti_write_code(void *agent, char const *symbol_name, ...@@ -22,11 +23,9 @@ int jvmti_write_code(void *agent, char const *symbol_name,
uint64_t vma, void const *code, uint64_t vma, void const *code,
const unsigned int code_size); const unsigned int code_size);
int jvmti_write_debug_info(void *agent, int jvmti_write_debug_info(void *agent, uint64_t code, int nr_lines,
uint64_t code,
const char *file,
jvmti_line_info_t *li, jvmti_line_info_t *li,
int nr_lines); const char * const * file_names);
#if defined(__cplusplus) #if defined(__cplusplus)
} }
......
...@@ -47,6 +47,7 @@ do_get_line_numbers(jvmtiEnv *jvmti, void *pc, jmethodID m, jint bci, ...@@ -47,6 +47,7 @@ do_get_line_numbers(jvmtiEnv *jvmti, void *pc, jmethodID m, jint bci,
tab[lines].pc = (unsigned long)pc; tab[lines].pc = (unsigned long)pc;
tab[lines].line_number = loc_tab[i].line_number; tab[lines].line_number = loc_tab[i].line_number;
tab[lines].discrim = 0; /* not yet used */ tab[lines].discrim = 0; /* not yet used */
tab[lines].methodID = m;
lines++; lines++;
} else { } else {
break; break;
...@@ -125,6 +126,99 @@ get_line_numbers(jvmtiEnv *jvmti, const void *compile_info, jvmti_line_info_t ** ...@@ -125,6 +126,99 @@ get_line_numbers(jvmtiEnv *jvmti, const void *compile_info, jvmti_line_info_t **
return JVMTI_ERROR_NONE; return JVMTI_ERROR_NONE;
} }
static void
copy_class_filename(const char * class_sign, const char * file_name, char * result, size_t max_length)
{
/*
* Assume path name is class hierarchy, this is a common practice with Java programs
*/
if (*class_sign == 'L') {
int j, i = 0;
char *p = strrchr(class_sign, '/');
if (p) {
/* drop the 'L' prefix and copy up to the final '/' */
for (i = 0; i < (p - class_sign); i++)
result[i] = class_sign[i+1];
}
/*
* append file name, we use loops and not string ops to avoid modifying
* class_sign which is used later for the symbol name
*/
for (j = 0; i < (max_length - 1) && file_name && j < strlen(file_name); j++, i++)
result[i] = file_name[j];
result[i] = '\0';
} else {
/* fallback case */
size_t file_name_len = strlen(file_name);
strncpy(result, file_name, file_name_len < max_length ? file_name_len : max_length);
}
}
static jvmtiError
get_source_filename(jvmtiEnv *jvmti, jmethodID methodID, char ** buffer)
{
jvmtiError ret;
jclass decl_class;
char *file_name = NULL;
char *class_sign = NULL;
char fn[PATH_MAX];
size_t len;
ret = (*jvmti)->GetMethodDeclaringClass(jvmti, methodID, &decl_class);
if (ret != JVMTI_ERROR_NONE) {
print_error(jvmti, "GetMethodDeclaringClass", ret);
return ret;
}
ret = (*jvmti)->GetSourceFileName(jvmti, decl_class, &file_name);
if (ret != JVMTI_ERROR_NONE) {
print_error(jvmti, "GetSourceFileName", ret);
return ret;
}
ret = (*jvmti)->GetClassSignature(jvmti, decl_class, &class_sign, NULL);
if (ret != JVMTI_ERROR_NONE) {
print_error(jvmti, "GetClassSignature", ret);
goto free_file_name_error;
}
copy_class_filename(class_sign, file_name, fn, PATH_MAX);
len = strlen(fn);
*buffer = malloc((len + 1) * sizeof(char));
if (!*buffer) {
print_error(jvmti, "GetClassSignature", ret);
ret = JVMTI_ERROR_OUT_OF_MEMORY;
goto free_class_sign_error;
}
strcpy(*buffer, fn);
ret = JVMTI_ERROR_NONE;
free_class_sign_error:
(*jvmti)->Deallocate(jvmti, (unsigned char *)class_sign);
free_file_name_error:
(*jvmti)->Deallocate(jvmti, (unsigned char *)file_name);
return ret;
}
static jvmtiError
fill_source_filenames(jvmtiEnv *jvmti, int nr_lines,
const jvmti_line_info_t * line_tab,
char ** file_names)
{
int index;
jvmtiError ret;
for (index = 0; index < nr_lines; ++index) {
ret = get_source_filename(jvmti, line_tab[index].methodID, &(file_names[index]));
if (ret != JVMTI_ERROR_NONE)
return ret;
}
return JVMTI_ERROR_NONE;
}
static void JNICALL static void JNICALL
compiled_method_load_cb(jvmtiEnv *jvmti, compiled_method_load_cb(jvmtiEnv *jvmti,
jmethodID method, jmethodID method,
...@@ -135,16 +229,18 @@ compiled_method_load_cb(jvmtiEnv *jvmti, ...@@ -135,16 +229,18 @@ compiled_method_load_cb(jvmtiEnv *jvmti,
const void *compile_info) const void *compile_info)
{ {
jvmti_line_info_t *line_tab = NULL; jvmti_line_info_t *line_tab = NULL;
char ** line_file_names = NULL;
jclass decl_class; jclass decl_class;
char *class_sign = NULL; char *class_sign = NULL;
char *func_name = NULL; char *func_name = NULL;
char *func_sign = NULL; char *func_sign = NULL;
char *file_name= NULL; char *file_name = NULL;
char fn[PATH_MAX]; char fn[PATH_MAX];
uint64_t addr = (uint64_t)(uintptr_t)code_addr; uint64_t addr = (uint64_t)(uintptr_t)code_addr;
jvmtiError ret; jvmtiError ret;
int nr_lines = 0; /* in line_tab[] */ int nr_lines = 0; /* in line_tab[] */
size_t len; size_t len;
int output_debug_info = 0;
ret = (*jvmti)->GetMethodDeclaringClass(jvmti, method, ret = (*jvmti)->GetMethodDeclaringClass(jvmti, method,
&decl_class); &decl_class);
...@@ -158,6 +254,19 @@ compiled_method_load_cb(jvmtiEnv *jvmti, ...@@ -158,6 +254,19 @@ compiled_method_load_cb(jvmtiEnv *jvmti,
if (ret != JVMTI_ERROR_NONE) { if (ret != JVMTI_ERROR_NONE) {
warnx("jvmti: cannot get line table for method"); warnx("jvmti: cannot get line table for method");
nr_lines = 0; nr_lines = 0;
} else if (nr_lines > 0) {
line_file_names = malloc(sizeof(char*) * nr_lines);
if (!line_file_names) {
warnx("jvmti: cannot allocate space for line table method names");
} else {
memset(line_file_names, 0, sizeof(char*) * nr_lines);
ret = fill_source_filenames(jvmti, nr_lines, line_tab, line_file_names);
if (ret != JVMTI_ERROR_NONE) {
warnx("jvmti: fill_source_filenames failed");
} else {
output_debug_info = 1;
}
}
} }
} }
...@@ -181,32 +290,13 @@ compiled_method_load_cb(jvmtiEnv *jvmti, ...@@ -181,32 +290,13 @@ compiled_method_load_cb(jvmtiEnv *jvmti,
goto error; goto error;
} }
/* copy_class_filename(class_sign, file_name, fn, PATH_MAX);
* Assume path name is class hierarchy, this is a common practice with Java programs
*/
if (*class_sign == 'L') {
int j, i = 0;
char *p = strrchr(class_sign, '/');
if (p) {
/* drop the 'L' prefix and copy up to the final '/' */
for (i = 0; i < (p - class_sign); i++)
fn[i] = class_sign[i+1];
}
/*
* append file name, we use loops and not string ops to avoid modifying
* class_sign which is used later for the symbol name
*/
for (j = 0; i < (PATH_MAX - 1) && file_name && j < strlen(file_name); j++, i++)
fn[i] = file_name[j];
fn[i] = '\0';
} else {
/* fallback case */
strcpy(fn, file_name);
}
/* /*
* write source line info record if we have it * write source line info record if we have it
*/ */
if (jvmti_write_debug_info(jvmti_agent, addr, fn, line_tab, nr_lines)) if (output_debug_info)
if (jvmti_write_debug_info(jvmti_agent, addr, nr_lines, line_tab, (const char * const *) line_file_names))
warnx("jvmti: write_debug_info() failed"); warnx("jvmti: write_debug_info() failed");
len = strlen(func_name) + strlen(class_sign) + strlen(func_sign) + 2; len = strlen(func_name) + strlen(class_sign) + strlen(func_sign) + 2;
...@@ -223,6 +313,13 @@ compiled_method_load_cb(jvmtiEnv *jvmti, ...@@ -223,6 +313,13 @@ compiled_method_load_cb(jvmtiEnv *jvmti,
(*jvmti)->Deallocate(jvmti, (unsigned char *)class_sign); (*jvmti)->Deallocate(jvmti, (unsigned char *)class_sign);
(*jvmti)->Deallocate(jvmti, (unsigned char *)file_name); (*jvmti)->Deallocate(jvmti, (unsigned char *)file_name);
free(line_tab); free(line_tab);
while (line_file_names && (nr_lines > 0)) {
if (line_file_names[nr_lines - 1]) {
free(line_file_names[nr_lines - 1]);
}
nr_lines -= 1;
}
free(line_file_names);
} }
static void JNICALL static void JNICALL
......
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