diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-12-31 14:47:24 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-12-31 14:47:24 -0500 |
| commit | e7c632fc479a8ac28da19252d44b0bd90a2638f6 (patch) | |
| tree | a3c53ae200192b6931e00a52127afdd49c84a6a5 | |
| parent | 88fa025d30ea97a2aae6394794bdfc31dc9423b7 (diff) | |
| parent | 7ad1437d6ace0e450a6c1167720608ad660b191d (diff) | |
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
| -rw-r--r-- | arch/x86/events/intel/core.c | 5 | ||||
| -rw-r--r-- | arch/x86/include/asm/asm.h | 2 | ||||
| -rw-r--r-- | tools/arch/s390/include/uapi/asm/perf_regs.h | 44 | ||||
| -rw-r--r-- | tools/perf/Makefile.config | 9 | ||||
| -rw-r--r-- | tools/perf/arch/s390/include/perf_regs.h | 2 | ||||
| -rwxr-xr-x | tools/perf/check-headers.sh | 1 | ||||
| -rw-r--r-- | tools/perf/jvmti/jvmti_agent.c | 16 | ||||
| -rw-r--r-- | tools/perf/jvmti/jvmti_agent.h | 7 | ||||
| -rw-r--r-- | tools/perf/jvmti/libjvmti.c | 147 |
9 files changed, 190 insertions, 43 deletions
diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c index 09c26a4f139c..731153a4681e 100644 --- a/arch/x86/events/intel/core.c +++ b/arch/x86/events/intel/core.c | |||
| @@ -3847,6 +3847,8 @@ static struct attribute *intel_pmu_attrs[] = { | |||
| 3847 | 3847 | ||
| 3848 | __init int intel_pmu_init(void) | 3848 | __init int intel_pmu_init(void) |
| 3849 | { | 3849 | { |
| 3850 | struct attribute **extra_attr = NULL; | ||
| 3851 | struct attribute **to_free = NULL; | ||
| 3850 | union cpuid10_edx edx; | 3852 | union cpuid10_edx edx; |
| 3851 | union cpuid10_eax eax; | 3853 | union cpuid10_eax eax; |
| 3852 | union cpuid10_ebx ebx; | 3854 | union cpuid10_ebx ebx; |
| @@ -3854,7 +3856,6 @@ __init int intel_pmu_init(void) | |||
| 3854 | unsigned int unused; | 3856 | unsigned int unused; |
| 3855 | struct extra_reg *er; | 3857 | struct extra_reg *er; |
| 3856 | int version, i; | 3858 | int version, i; |
| 3857 | struct attribute **extra_attr = NULL; | ||
| 3858 | char *name; | 3859 | char *name; |
| 3859 | 3860 | ||
| 3860 | if (!cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) { | 3861 | if (!cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) { |
| @@ -4294,6 +4295,7 @@ __init int intel_pmu_init(void) | |||
| 4294 | extra_attr = boot_cpu_has(X86_FEATURE_RTM) ? | 4295 | extra_attr = boot_cpu_has(X86_FEATURE_RTM) ? |
| 4295 | hsw_format_attr : nhm_format_attr; | 4296 | hsw_format_attr : nhm_format_attr; |
| 4296 | extra_attr = merge_attr(extra_attr, skl_format_attr); | 4297 | extra_attr = merge_attr(extra_attr, skl_format_attr); |
| 4298 | to_free = extra_attr; | ||
| 4297 | x86_pmu.cpu_events = get_hsw_events_attrs(); | 4299 | x86_pmu.cpu_events = get_hsw_events_attrs(); |
| 4298 | intel_pmu_pebs_data_source_skl( | 4300 | intel_pmu_pebs_data_source_skl( |
| 4299 | boot_cpu_data.x86_model == INTEL_FAM6_SKYLAKE_X); | 4301 | boot_cpu_data.x86_model == INTEL_FAM6_SKYLAKE_X); |
| @@ -4401,6 +4403,7 @@ __init int intel_pmu_init(void) | |||
| 4401 | pr_cont("full-width counters, "); | 4403 | pr_cont("full-width counters, "); |
| 4402 | } | 4404 | } |
| 4403 | 4405 | ||
| 4406 | kfree(to_free); | ||
| 4404 | return 0; | 4407 | return 0; |
| 4405 | } | 4408 | } |
| 4406 | 4409 | ||
diff --git a/arch/x86/include/asm/asm.h b/arch/x86/include/asm/asm.h index 219faaec51df..386a6900e206 100644 --- a/arch/x86/include/asm/asm.h +++ b/arch/x86/include/asm/asm.h | |||
| @@ -136,6 +136,7 @@ | |||
| 136 | #endif | 136 | #endif |
| 137 | 137 | ||
| 138 | #ifndef __ASSEMBLY__ | 138 | #ifndef __ASSEMBLY__ |
| 139 | #ifndef __BPF__ | ||
| 139 | /* | 140 | /* |
| 140 | * This output constraint should be used for any inline asm which has a "call" | 141 | * This output constraint should be used for any inline asm which has a "call" |
| 141 | * instruction. Otherwise the asm may be inserted before the frame pointer | 142 | * instruction. Otherwise the asm may be inserted before the frame pointer |
| @@ -145,5 +146,6 @@ | |||
| 145 | register unsigned long current_stack_pointer asm(_ASM_SP); | 146 | register unsigned long current_stack_pointer asm(_ASM_SP); |
| 146 | #define ASM_CALL_CONSTRAINT "+r" (current_stack_pointer) | 147 | #define ASM_CALL_CONSTRAINT "+r" (current_stack_pointer) |
| 147 | #endif | 148 | #endif |
| 149 | #endif | ||
| 148 | 150 | ||
| 149 | #endif /* _ASM_X86_ASM_H */ | 151 | #endif /* _ASM_X86_ASM_H */ |
diff --git a/tools/arch/s390/include/uapi/asm/perf_regs.h b/tools/arch/s390/include/uapi/asm/perf_regs.h new file mode 100644 index 000000000000..d17dd9e5d516 --- /dev/null +++ b/tools/arch/s390/include/uapi/asm/perf_regs.h | |||
| @@ -0,0 +1,44 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ | ||
| 2 | #ifndef _ASM_S390_PERF_REGS_H | ||
| 3 | #define _ASM_S390_PERF_REGS_H | ||
| 4 | |||
| 5 | enum perf_event_s390_regs { | ||
| 6 | PERF_REG_S390_R0, | ||
| 7 | PERF_REG_S390_R1, | ||
| 8 | PERF_REG_S390_R2, | ||
| 9 | PERF_REG_S390_R3, | ||
| 10 | PERF_REG_S390_R4, | ||
| 11 | PERF_REG_S390_R5, | ||
| 12 | PERF_REG_S390_R6, | ||
| 13 | PERF_REG_S390_R7, | ||
| 14 | PERF_REG_S390_R8, | ||
| 15 | PERF_REG_S390_R9, | ||
| 16 | PERF_REG_S390_R10, | ||
| 17 | PERF_REG_S390_R11, | ||
| 18 | PERF_REG_S390_R12, | ||
| 19 | PERF_REG_S390_R13, | ||
| 20 | PERF_REG_S390_R14, | ||
| 21 | PERF_REG_S390_R15, | ||
| 22 | PERF_REG_S390_FP0, | ||
| 23 | PERF_REG_S390_FP1, | ||
| 24 | PERF_REG_S390_FP2, | ||
| 25 | PERF_REG_S390_FP3, | ||
| 26 | PERF_REG_S390_FP4, | ||
| 27 | PERF_REG_S390_FP5, | ||
| 28 | PERF_REG_S390_FP6, | ||
| 29 | PERF_REG_S390_FP7, | ||
| 30 | PERF_REG_S390_FP8, | ||
| 31 | PERF_REG_S390_FP9, | ||
| 32 | PERF_REG_S390_FP10, | ||
| 33 | PERF_REG_S390_FP11, | ||
| 34 | PERF_REG_S390_FP12, | ||
| 35 | PERF_REG_S390_FP13, | ||
| 36 | PERF_REG_S390_FP14, | ||
| 37 | PERF_REG_S390_FP15, | ||
| 38 | PERF_REG_S390_MASK, | ||
| 39 | PERF_REG_S390_PC, | ||
| 40 | |||
| 41 | PERF_REG_S390_MAX | ||
| 42 | }; | ||
| 43 | |||
| 44 | #endif /* _ASM_S390_PERF_REGS_H */ | ||
diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config index ed65e82f034e..0294bfb6c5f8 100644 --- a/tools/perf/Makefile.config +++ b/tools/perf/Makefile.config | |||
| @@ -188,9 +188,7 @@ ifdef PYTHON_CONFIG | |||
| 188 | PYTHON_EMBED_LDFLAGS := $(call strip-libs,$(PYTHON_EMBED_LDOPTS)) | 188 | PYTHON_EMBED_LDFLAGS := $(call strip-libs,$(PYTHON_EMBED_LDOPTS)) |
| 189 | PYTHON_EMBED_LIBADD := $(call grep-libs,$(PYTHON_EMBED_LDOPTS)) -lutil | 189 | PYTHON_EMBED_LIBADD := $(call grep-libs,$(PYTHON_EMBED_LDOPTS)) -lutil |
| 190 | PYTHON_EMBED_CCOPTS := $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null) | 190 | PYTHON_EMBED_CCOPTS := $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null) |
| 191 | ifeq ($(CC_NO_CLANG), 1) | 191 | PYTHON_EMBED_CCOPTS := $(filter-out -specs=%,$(PYTHON_EMBED_CCOPTS)) |
| 192 | PYTHON_EMBED_CCOPTS := $(filter-out -specs=%,$(PYTHON_EMBED_CCOPTS)) | ||
| 193 | endif | ||
| 194 | FLAGS_PYTHON_EMBED := $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS) | 192 | FLAGS_PYTHON_EMBED := $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS) |
| 195 | endif | 193 | endif |
| 196 | 194 | ||
| @@ -576,14 +574,15 @@ ifndef NO_GTK2 | |||
| 576 | endif | 574 | endif |
| 577 | endif | 575 | endif |
| 578 | 576 | ||
| 579 | |||
| 580 | ifdef NO_LIBPERL | 577 | ifdef NO_LIBPERL |
| 581 | CFLAGS += -DNO_LIBPERL | 578 | CFLAGS += -DNO_LIBPERL |
| 582 | else | 579 | else |
| 583 | PERL_EMBED_LDOPTS = $(shell perl -MExtUtils::Embed -e ldopts 2>/dev/null) | 580 | PERL_EMBED_LDOPTS = $(shell perl -MExtUtils::Embed -e ldopts 2>/dev/null) |
| 584 | PERL_EMBED_LDFLAGS = $(call strip-libs,$(PERL_EMBED_LDOPTS)) | 581 | PERL_EMBED_LDFLAGS = $(call strip-libs,$(PERL_EMBED_LDOPTS)) |
| 585 | PERL_EMBED_LIBADD = $(call grep-libs,$(PERL_EMBED_LDOPTS)) | 582 | PERL_EMBED_LIBADD = $(call grep-libs,$(PERL_EMBED_LDOPTS)) |
| 586 | PERL_EMBED_CCOPTS = `perl -MExtUtils::Embed -e ccopts 2>/dev/null` | 583 | PERL_EMBED_CCOPTS = $(shell perl -MExtUtils::Embed -e ccopts 2>/dev/null) |
| 584 | PERL_EMBED_CCOPTS := $(filter-out -specs=%,$(PERL_EMBED_CCOPTS)) | ||
| 585 | PERL_EMBED_LDOPTS := $(filter-out -specs=%,$(PERL_EMBED_LDOPTS)) | ||
| 587 | FLAGS_PERL_EMBED=$(PERL_EMBED_CCOPTS) $(PERL_EMBED_LDOPTS) | 586 | FLAGS_PERL_EMBED=$(PERL_EMBED_CCOPTS) $(PERL_EMBED_LDOPTS) |
| 588 | 587 | ||
| 589 | ifneq ($(feature-libperl), 1) | 588 | ifneq ($(feature-libperl), 1) |
diff --git a/tools/perf/arch/s390/include/perf_regs.h b/tools/perf/arch/s390/include/perf_regs.h index d2df54a6bc5a..bcfbaed78cc2 100644 --- a/tools/perf/arch/s390/include/perf_regs.h +++ b/tools/perf/arch/s390/include/perf_regs.h | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | #include <stdlib.h> | 4 | #include <stdlib.h> |
| 5 | #include <linux/types.h> | 5 | #include <linux/types.h> |
| 6 | #include <../../../../arch/s390/include/uapi/asm/perf_regs.h> | 6 | #include <asm/perf_regs.h> |
| 7 | 7 | ||
| 8 | void perf_regs_load(u64 *regs); | 8 | void perf_regs_load(u64 *regs); |
| 9 | 9 | ||
diff --git a/tools/perf/check-headers.sh b/tools/perf/check-headers.sh index 6db9d809fe97..3e64f10b6d66 100755 --- a/tools/perf/check-headers.sh +++ b/tools/perf/check-headers.sh | |||
| @@ -21,6 +21,7 @@ arch/x86/include/asm/cpufeatures.h | |||
| 21 | arch/arm/include/uapi/asm/perf_regs.h | 21 | arch/arm/include/uapi/asm/perf_regs.h |
| 22 | arch/arm64/include/uapi/asm/perf_regs.h | 22 | arch/arm64/include/uapi/asm/perf_regs.h |
| 23 | arch/powerpc/include/uapi/asm/perf_regs.h | 23 | arch/powerpc/include/uapi/asm/perf_regs.h |
| 24 | arch/s390/include/uapi/asm/perf_regs.h | ||
| 24 | arch/x86/include/uapi/asm/perf_regs.h | 25 | arch/x86/include/uapi/asm/perf_regs.h |
| 25 | arch/x86/include/uapi/asm/kvm.h | 26 | arch/x86/include/uapi/asm/kvm.h |
| 26 | arch/x86/include/uapi/asm/kvm_perf.h | 27 | arch/x86/include/uapi/asm/kvm_perf.h |
diff --git a/tools/perf/jvmti/jvmti_agent.c b/tools/perf/jvmti/jvmti_agent.c index cf36de7ea255..0c6d1002b524 100644 --- a/tools/perf/jvmti/jvmti_agent.c +++ b/tools/perf/jvmti/jvmti_agent.c | |||
| @@ -384,13 +384,13 @@ jvmti_write_code(void *agent, char const *sym, | |||
| 384 | } | 384 | } |
| 385 | 385 | ||
| 386 | int | 386 | int |
| 387 | jvmti_write_debug_info(void *agent, uint64_t code, const char *file, | 387 | jvmti_write_debug_info(void *agent, uint64_t code, |
| 388 | jvmti_line_info_t *li, int nr_lines) | 388 | int nr_lines, jvmti_line_info_t *li, |
| 389 | const char * const * file_names) | ||
| 389 | { | 390 | { |
| 390 | struct jr_code_debug_info rec; | 391 | struct jr_code_debug_info rec; |
| 391 | size_t sret, len, size, flen; | 392 | size_t sret, len, size, flen = 0; |
| 392 | uint64_t addr; | 393 | uint64_t addr; |
| 393 | const char *fn = file; | ||
| 394 | FILE *fp = agent; | 394 | FILE *fp = agent; |
| 395 | int i; | 395 | int i; |
| 396 | 396 | ||
| @@ -405,7 +405,9 @@ jvmti_write_debug_info(void *agent, uint64_t code, const char *file, | |||
| 405 | return -1; | 405 | return -1; |
| 406 | } | 406 | } |
| 407 | 407 | ||
| 408 | flen = strlen(file) + 1; | 408 | for (i = 0; i < nr_lines; ++i) { |
| 409 | flen += strlen(file_names[i]) + 1; | ||
| 410 | } | ||
| 409 | 411 | ||
| 410 | rec.p.id = JIT_CODE_DEBUG_INFO; | 412 | rec.p.id = JIT_CODE_DEBUG_INFO; |
| 411 | size = sizeof(rec); | 413 | size = sizeof(rec); |
| @@ -421,7 +423,7 @@ jvmti_write_debug_info(void *agent, uint64_t code, const char *file, | |||
| 421 | * file[] : source file name | 423 | * file[] : source file name |
| 422 | */ | 424 | */ |
| 423 | size += nr_lines * sizeof(struct debug_entry); | 425 | size += nr_lines * sizeof(struct debug_entry); |
| 424 | size += flen * nr_lines; | 426 | size += flen; |
| 425 | rec.p.total_size = size; | 427 | rec.p.total_size = size; |
| 426 | 428 | ||
| 427 | /* | 429 | /* |
| @@ -452,7 +454,7 @@ jvmti_write_debug_info(void *agent, uint64_t code, const char *file, | |||
| 452 | if (sret != 1) | 454 | if (sret != 1) |
| 453 | goto error; | 455 | goto error; |
| 454 | 456 | ||
| 455 | sret = fwrite_unlocked(fn, flen, 1, fp); | 457 | sret = fwrite_unlocked(file_names[i], strlen(file_names[i]) + 1, 1, fp); |
| 456 | if (sret != 1) | 458 | if (sret != 1) |
| 457 | goto error; | 459 | goto error; |
| 458 | } | 460 | } |
diff --git a/tools/perf/jvmti/jvmti_agent.h b/tools/perf/jvmti/jvmti_agent.h index fe32d8344a82..6ed82f6c06dd 100644 --- a/tools/perf/jvmti/jvmti_agent.h +++ b/tools/perf/jvmti/jvmti_agent.h | |||
| @@ -14,6 +14,7 @@ typedef struct { | |||
| 14 | unsigned long pc; | 14 | unsigned long pc; |
| 15 | int line_number; | 15 | int line_number; |
| 16 | int discrim; /* discriminator -- 0 for now */ | 16 | int discrim; /* discriminator -- 0 for now */ |
| 17 | jmethodID methodID; | ||
| 17 | } jvmti_line_info_t; | 18 | } jvmti_line_info_t; |
| 18 | 19 | ||
| 19 | void *jvmti_open(void); | 20 | void *jvmti_open(void); |
| @@ -22,11 +23,9 @@ int jvmti_write_code(void *agent, char const *symbol_name, | |||
| 22 | uint64_t vma, void const *code, | 23 | uint64_t vma, void const *code, |
| 23 | const unsigned int code_size); | 24 | const unsigned int code_size); |
| 24 | 25 | ||
| 25 | int jvmti_write_debug_info(void *agent, | 26 | int jvmti_write_debug_info(void *agent, uint64_t code, int nr_lines, |
| 26 | uint64_t code, | ||
| 27 | const char *file, | ||
| 28 | jvmti_line_info_t *li, | 27 | jvmti_line_info_t *li, |
| 29 | int nr_lines); | 28 | const char * const * file_names); |
| 30 | 29 | ||
| 31 | #if defined(__cplusplus) | 30 | #if defined(__cplusplus) |
| 32 | } | 31 | } |
diff --git a/tools/perf/jvmti/libjvmti.c b/tools/perf/jvmti/libjvmti.c index c62c9fc9a525..6add3e982614 100644 --- a/tools/perf/jvmti/libjvmti.c +++ b/tools/perf/jvmti/libjvmti.c | |||
| @@ -47,6 +47,7 @@ do_get_line_numbers(jvmtiEnv *jvmti, void *pc, jmethodID m, jint bci, | |||
| 47 | tab[lines].pc = (unsigned long)pc; | 47 | tab[lines].pc = (unsigned long)pc; |
| 48 | tab[lines].line_number = loc_tab[i].line_number; | 48 | tab[lines].line_number = loc_tab[i].line_number; |
| 49 | tab[lines].discrim = 0; /* not yet used */ | 49 | tab[lines].discrim = 0; /* not yet used */ |
| 50 | tab[lines].methodID = m; | ||
| 50 | lines++; | 51 | lines++; |
| 51 | } else { | 52 | } else { |
| 52 | break; | 53 | break; |
| @@ -125,6 +126,99 @@ get_line_numbers(jvmtiEnv *jvmti, const void *compile_info, jvmti_line_info_t ** | |||
| 125 | return JVMTI_ERROR_NONE; | 126 | return JVMTI_ERROR_NONE; |
| 126 | } | 127 | } |
| 127 | 128 | ||
| 129 | static void | ||
| 130 | copy_class_filename(const char * class_sign, const char * file_name, char * result, size_t max_length) | ||
| 131 | { | ||
| 132 | /* | ||
| 133 | * Assume path name is class hierarchy, this is a common practice with Java programs | ||
| 134 | */ | ||
| 135 | if (*class_sign == 'L') { | ||
| 136 | int j, i = 0; | ||
| 137 | char *p = strrchr(class_sign, '/'); | ||
| 138 | if (p) { | ||
| 139 | /* drop the 'L' prefix and copy up to the final '/' */ | ||
| 140 | for (i = 0; i < (p - class_sign); i++) | ||
| 141 | result[i] = class_sign[i+1]; | ||
| 142 | } | ||
| 143 | /* | ||
| 144 | * append file name, we use loops and not string ops to avoid modifying | ||
| 145 | * class_sign which is used later for the symbol name | ||
| 146 | */ | ||
| 147 | for (j = 0; i < (max_length - 1) && file_name && j < strlen(file_name); j++, i++) | ||
| 148 | result[i] = file_name[j]; | ||
| 149 | |||
| 150 | result[i] = '\0'; | ||
| 151 | } else { | ||
| 152 | /* fallback case */ | ||
| 153 | size_t file_name_len = strlen(file_name); | ||
| 154 | strncpy(result, file_name, file_name_len < max_length ? file_name_len : max_length); | ||
| 155 | } | ||
| 156 | } | ||
| 157 | |||
| 158 | static jvmtiError | ||
| 159 | get_source_filename(jvmtiEnv *jvmti, jmethodID methodID, char ** buffer) | ||
| 160 | { | ||
| 161 | jvmtiError ret; | ||
| 162 | jclass decl_class; | ||
| 163 | char *file_name = NULL; | ||
| 164 | char *class_sign = NULL; | ||
| 165 | char fn[PATH_MAX]; | ||
| 166 | size_t len; | ||
| 167 | |||
| 168 | ret = (*jvmti)->GetMethodDeclaringClass(jvmti, methodID, &decl_class); | ||
| 169 | if (ret != JVMTI_ERROR_NONE) { | ||
| 170 | print_error(jvmti, "GetMethodDeclaringClass", ret); | ||
| 171 | return ret; | ||
| 172 | } | ||
| 173 | |||
| 174 | ret = (*jvmti)->GetSourceFileName(jvmti, decl_class, &file_name); | ||
| 175 | if (ret != JVMTI_ERROR_NONE) { | ||
| 176 | print_error(jvmti, "GetSourceFileName", ret); | ||
| 177 | return ret; | ||
| 178 | } | ||
| 179 | |||
| 180 | ret = (*jvmti)->GetClassSignature(jvmti, decl_class, &class_sign, NULL); | ||
| 181 | if (ret != JVMTI_ERROR_NONE) { | ||
| 182 | print_error(jvmti, "GetClassSignature", ret); | ||
| 183 | goto free_file_name_error; | ||
| 184 | } | ||
| 185 | |||
| 186 | copy_class_filename(class_sign, file_name, fn, PATH_MAX); | ||
| 187 | len = strlen(fn); | ||
| 188 | *buffer = malloc((len + 1) * sizeof(char)); | ||
| 189 | if (!*buffer) { | ||
| 190 | print_error(jvmti, "GetClassSignature", ret); | ||
| 191 | ret = JVMTI_ERROR_OUT_OF_MEMORY; | ||
| 192 | goto free_class_sign_error; | ||
| 193 | } | ||
| 194 | strcpy(*buffer, fn); | ||
| 195 | ret = JVMTI_ERROR_NONE; | ||
| 196 | |||
| 197 | free_class_sign_error: | ||
| 198 | (*jvmti)->Deallocate(jvmti, (unsigned char *)class_sign); | ||
| 199 | free_file_name_error: | ||
| 200 | (*jvmti)->Deallocate(jvmti, (unsigned char *)file_name); | ||
| 201 | |||
| 202 | return ret; | ||
| 203 | } | ||
| 204 | |||
| 205 | static jvmtiError | ||
| 206 | fill_source_filenames(jvmtiEnv *jvmti, int nr_lines, | ||
| 207 | const jvmti_line_info_t * line_tab, | ||
| 208 | char ** file_names) | ||
| 209 | { | ||
| 210 | int index; | ||
| 211 | jvmtiError ret; | ||
| 212 | |||
| 213 | for (index = 0; index < nr_lines; ++index) { | ||
| 214 | ret = get_source_filename(jvmti, line_tab[index].methodID, &(file_names[index])); | ||
| 215 | if (ret != JVMTI_ERROR_NONE) | ||
| 216 | return ret; | ||
| 217 | } | ||
| 218 | |||
| 219 | return JVMTI_ERROR_NONE; | ||
| 220 | } | ||
| 221 | |||
| 128 | static void JNICALL | 222 | static void JNICALL |
| 129 | compiled_method_load_cb(jvmtiEnv *jvmti, | 223 | compiled_method_load_cb(jvmtiEnv *jvmti, |
| 130 | jmethodID method, | 224 | jmethodID method, |
| @@ -135,16 +229,18 @@ compiled_method_load_cb(jvmtiEnv *jvmti, | |||
| 135 | const void *compile_info) | 229 | const void *compile_info) |
| 136 | { | 230 | { |
| 137 | jvmti_line_info_t *line_tab = NULL; | 231 | jvmti_line_info_t *line_tab = NULL; |
| 232 | char ** line_file_names = NULL; | ||
| 138 | jclass decl_class; | 233 | jclass decl_class; |
| 139 | char *class_sign = NULL; | 234 | char *class_sign = NULL; |
| 140 | char *func_name = NULL; | 235 | char *func_name = NULL; |
| 141 | char *func_sign = NULL; | 236 | char *func_sign = NULL; |
| 142 | char *file_name= NULL; | 237 | char *file_name = NULL; |
| 143 | char fn[PATH_MAX]; | 238 | char fn[PATH_MAX]; |
| 144 | uint64_t addr = (uint64_t)(uintptr_t)code_addr; | 239 | uint64_t addr = (uint64_t)(uintptr_t)code_addr; |
| 145 | jvmtiError ret; | 240 | jvmtiError ret; |
| 146 | int nr_lines = 0; /* in line_tab[] */ | 241 | int nr_lines = 0; /* in line_tab[] */ |
| 147 | size_t len; | 242 | size_t len; |
| 243 | int output_debug_info = 0; | ||
| 148 | 244 | ||
| 149 | ret = (*jvmti)->GetMethodDeclaringClass(jvmti, method, | 245 | ret = (*jvmti)->GetMethodDeclaringClass(jvmti, method, |
| 150 | &decl_class); | 246 | &decl_class); |
| @@ -158,6 +254,19 @@ compiled_method_load_cb(jvmtiEnv *jvmti, | |||
| 158 | if (ret != JVMTI_ERROR_NONE) { | 254 | if (ret != JVMTI_ERROR_NONE) { |
| 159 | warnx("jvmti: cannot get line table for method"); | 255 | warnx("jvmti: cannot get line table for method"); |
| 160 | nr_lines = 0; | 256 | nr_lines = 0; |
| 257 | } else if (nr_lines > 0) { | ||
| 258 | line_file_names = malloc(sizeof(char*) * nr_lines); | ||
| 259 | if (!line_file_names) { | ||
| 260 | warnx("jvmti: cannot allocate space for line table method names"); | ||
| 261 | } else { | ||
| 262 | memset(line_file_names, 0, sizeof(char*) * nr_lines); | ||
| 263 | ret = fill_source_filenames(jvmti, nr_lines, line_tab, line_file_names); | ||
| 264 | if (ret != JVMTI_ERROR_NONE) { | ||
| 265 | warnx("jvmti: fill_source_filenames failed"); | ||
| 266 | } else { | ||
| 267 | output_debug_info = 1; | ||
| 268 | } | ||
| 269 | } | ||
| 161 | } | 270 | } |
| 162 | } | 271 | } |
| 163 | 272 | ||
| @@ -181,33 +290,14 @@ compiled_method_load_cb(jvmtiEnv *jvmti, | |||
| 181 | goto error; | 290 | goto error; |
| 182 | } | 291 | } |
| 183 | 292 | ||
| 184 | /* | 293 | copy_class_filename(class_sign, file_name, fn, PATH_MAX); |
| 185 | * Assume path name is class hierarchy, this is a common practice with Java programs | 294 | |
| 186 | */ | ||
| 187 | if (*class_sign == 'L') { | ||
| 188 | int j, i = 0; | ||
| 189 | char *p = strrchr(class_sign, '/'); | ||
| 190 | if (p) { | ||
| 191 | /* drop the 'L' prefix and copy up to the final '/' */ | ||
| 192 | for (i = 0; i < (p - class_sign); i++) | ||
| 193 | fn[i] = class_sign[i+1]; | ||
| 194 | } | ||
| 195 | /* | ||
| 196 | * append file name, we use loops and not string ops to avoid modifying | ||
| 197 | * class_sign which is used later for the symbol name | ||
| 198 | */ | ||
| 199 | for (j = 0; i < (PATH_MAX - 1) && file_name && j < strlen(file_name); j++, i++) | ||
| 200 | fn[i] = file_name[j]; | ||
| 201 | fn[i] = '\0'; | ||
| 202 | } else { | ||
| 203 | /* fallback case */ | ||
| 204 | strcpy(fn, file_name); | ||
| 205 | } | ||
| 206 | /* | 295 | /* |
| 207 | * write source line info record if we have it | 296 | * write source line info record if we have it |
| 208 | */ | 297 | */ |
| 209 | if (jvmti_write_debug_info(jvmti_agent, addr, fn, line_tab, nr_lines)) | 298 | if (output_debug_info) |
| 210 | warnx("jvmti: write_debug_info() failed"); | 299 | if (jvmti_write_debug_info(jvmti_agent, addr, nr_lines, line_tab, (const char * const *) line_file_names)) |
| 300 | warnx("jvmti: write_debug_info() failed"); | ||
| 211 | 301 | ||
| 212 | len = strlen(func_name) + strlen(class_sign) + strlen(func_sign) + 2; | 302 | len = strlen(func_name) + strlen(class_sign) + strlen(func_sign) + 2; |
| 213 | { | 303 | { |
| @@ -223,6 +313,13 @@ error: | |||
| 223 | (*jvmti)->Deallocate(jvmti, (unsigned char *)class_sign); | 313 | (*jvmti)->Deallocate(jvmti, (unsigned char *)class_sign); |
| 224 | (*jvmti)->Deallocate(jvmti, (unsigned char *)file_name); | 314 | (*jvmti)->Deallocate(jvmti, (unsigned char *)file_name); |
| 225 | free(line_tab); | 315 | free(line_tab); |
| 316 | while (line_file_names && (nr_lines > 0)) { | ||
| 317 | if (line_file_names[nr_lines - 1]) { | ||
| 318 | free(line_file_names[nr_lines - 1]); | ||
| 319 | } | ||
| 320 | nr_lines -= 1; | ||
| 321 | } | ||
| 322 | free(line_file_names); | ||
| 226 | } | 323 | } |
| 227 | 324 | ||
| 228 | static void JNICALL | 325 | static void JNICALL |
