This series is a set of backports to enhance the JVMTI plugin support in Linux perf tool. It allows one to use perf to profile Java applications and attain clearer symbols output.
Nick Gasson (6): perf jvmti: Fix jitdump for methods without debug info perf jvmti: Do not report error when missing debug information perf tests: Add test for the java demangler perf jvmti: Fix demangling Java symbols perf jvmti: Remove redundant jitdump line table entries perf jit: Fix inaccurate DWARF line table
tools/perf/jvmti/libjvmti.c | 92 ++++++++++++--------------- tools/perf/tests/Build | 1 + tools/perf/tests/builtin-test.c | 4 ++ tools/perf/tests/demangle-java-test.c | 42 ++++++++++++ tools/perf/tests/tests.h | 1 + tools/perf/util/demangle-java.c | 13 ++-- tools/perf/util/genelf_debug.c | 4 +- 7 files changed, 96 insertions(+), 61 deletions(-) create mode 100644 tools/perf/tests/demangle-java-test.c
From: Nick Gasson nick.gasson@arm.com
mainline inclusion from mainline-v5.7 commit 953e92402a523102899d15f0083a508006220859 category: bugfix bugzilla: NA CVE: NA
---------------------------
If a Java class is compiled with -g:none to omit debug information, the JVMTI plugin won't write jitdump entries for any method in this class and prints a lot of errors like:
java: GetSourceFileName failed with JVMTI_ERROR_ABSENT_INFORMATION
The call to GetSourceFileName is used to derive the file name `fn`, but this value is not actually used since commit ca58d7e64bdf ("perf jvmti: Generate correct debug information for inlined code") which moved the file name lookup into fill_source_filenames(). So the call to GetSourceFileName and related code can be safely removed.
Signed-off-by: Nick Gasson nick.gasson@arm.com Reviewed-by: Ian Rogers irogers@google.com Tested-by: Ian Rogers irogers@google.com Cc: Alexander Shishkin alexander.shishkin@linux.intel.com Cc: Jiri Olsa jolsa@redhat.com Cc: Mark Rutland mark.rutland@arm.com Cc: Namhyung Kim namhyung@kernel.org Cc: Peter Zijlstra peterz@infradead.org Link: http://lore.kernel.org/lkml/20200427061520.24905-2-nick.gasson@arm.com Signed-off-by: Arnaldo Carvalho de Melo acme@redhat.com Signed-off-by: Zhichang Yuan erik.yuan@arm.com --- tools/perf/jvmti/libjvmti.c | 11 ----------- 1 file changed, 11 deletions(-)
diff --git a/tools/perf/jvmti/libjvmti.c b/tools/perf/jvmti/libjvmti.c index 3361d98a4edd..eb798511e368 100644 --- a/tools/perf/jvmti/libjvmti.c +++ b/tools/perf/jvmti/libjvmti.c @@ -234,8 +234,6 @@ compiled_method_load_cb(jvmtiEnv *jvmti, char *class_sign = NULL; char *func_name = NULL; char *func_sign = NULL; - char *file_name = NULL; - char fn[PATH_MAX]; uint64_t addr = (uint64_t)(uintptr_t)code_addr; jvmtiError ret; int nr_lines = 0; /* in line_tab[] */ @@ -270,12 +268,6 @@ compiled_method_load_cb(jvmtiEnv *jvmti, } }
- ret = (*jvmti)->GetSourceFileName(jvmti, decl_class, &file_name); - if (ret != JVMTI_ERROR_NONE) { - print_error(jvmti, "GetSourceFileName", ret); - goto error; - } - ret = (*jvmti)->GetClassSignature(jvmti, decl_class, &class_sign, NULL); if (ret != JVMTI_ERROR_NONE) { @@ -290,8 +282,6 @@ compiled_method_load_cb(jvmtiEnv *jvmti, goto error; }
- copy_class_filename(class_sign, file_name, fn, PATH_MAX); - /* * write source line info record if we have it */ @@ -311,7 +301,6 @@ compiled_method_load_cb(jvmtiEnv *jvmti, (*jvmti)->Deallocate(jvmti, (unsigned char *)func_name); (*jvmti)->Deallocate(jvmti, (unsigned char *)func_sign); (*jvmti)->Deallocate(jvmti, (unsigned char *)class_sign); - (*jvmti)->Deallocate(jvmti, (unsigned char *)file_name); free(line_tab); while (line_file_names && (nr_lines > 0)) { if (line_file_names[nr_lines - 1]) {
From: Nick Gasson nick.gasson@arm.com
mainline inclusion from mainline-v5.7 commit 959f8ed4c1a82acf0b339f1509686ddfe2e48e29 category: bugfix bugzilla: NA CVE: NA
-------------------------------------------------
If the Java sources are compiled with -g:none to disable debug information the perf JVMTI plugin reports a lot of errors like:
java: GetLineNumberTable failed with JVMTI_ERROR_ABSENT_INFORMATION java: GetLineNumberTable failed with JVMTI_ERROR_ABSENT_INFORMATION java: GetLineNumberTable failed with JVMTI_ERROR_ABSENT_INFORMATION java: GetLineNumberTable failed with JVMTI_ERROR_ABSENT_INFORMATION java: GetLineNumberTable failed with JVMTI_ERROR_ABSENT_INFORMATION
Instead if GetLineNumberTable returns JVMTI_ERROR_ABSENT_INFORMATION simply skip emitting line number information for that method. Unlike the previous patch these errors don't affect the jitdump generation, they just generate a lot of noise.
Similarly for native methods which also don't have line tables.
Signed-off-by: Nick Gasson nick.gasson@arm.com Reviewed-by: Ian Rogers irogers@google.com Tested-by: Ian Rogers irogers@google.com Cc: Alexander Shishkin alexander.shishkin@linux.intel.com Cc: Jiri Olsa jolsa@redhat.com Cc: Mark Rutland mark.rutland@arm.com Cc: Namhyung Kim namhyung@kernel.org Cc: Peter Zijlstra peterz@infradead.org Link: http://lore.kernel.org/lkml/20200427061520.24905-3-nick.gasson@arm.com [ Moved || operator to the end of the line, not at the start of 2nd if condition ] Signed-off-by: Arnaldo Carvalho de Melo acme@redhat.com Signed-off-by: Zhichang Yuan erik.yuan@arm.com --- tools/perf/jvmti/libjvmti.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/tools/perf/jvmti/libjvmti.c b/tools/perf/jvmti/libjvmti.c index eb798511e368..199fb53a332c 100644 --- a/tools/perf/jvmti/libjvmti.c +++ b/tools/perf/jvmti/libjvmti.c @@ -38,7 +38,11 @@ do_get_line_numbers(jvmtiEnv *jvmti, void *pc, jmethodID m, jint bci, jvmtiError ret;
ret = (*jvmti)->GetLineNumberTable(jvmti, m, &nr_lines, &loc_tab); - if (ret != JVMTI_ERROR_NONE) { + if (ret == JVMTI_ERROR_ABSENT_INFORMATION || ret == JVMTI_ERROR_NATIVE_METHOD) { + /* No debug information for this method */ + *nr = 0; + return JVMTI_ERROR_NONE; + } else if (ret != JVMTI_ERROR_NONE) { print_error(jvmti, "GetLineNumberTable", ret); return ret; } @@ -90,6 +94,9 @@ get_line_numbers(jvmtiEnv *jvmti, const void *compile_info, jvmti_line_info_t ** /* free what was allocated for nothing */ (*jvmti)->Deallocate(jvmti, (unsigned char *)lne); nr_total += (int)nr; + } else if (ret == JVMTI_ERROR_ABSENT_INFORMATION || + ret == JVMTI_ERROR_NATIVE_METHOD) { + /* No debug information for this method */ } else { print_error(jvmti, "GetLineNumberTable", ret); } @@ -250,7 +257,9 @@ compiled_method_load_cb(jvmtiEnv *jvmti, if (has_line_numbers && map && map_length) { ret = get_line_numbers(jvmti, compile_info, &line_tab, &nr_lines); if (ret != JVMTI_ERROR_NONE) { - warnx("jvmti: cannot get line table for method"); + if (ret != JVMTI_ERROR_NOT_FOUND) { + warnx("jvmti: cannot get line table for method"); + } nr_lines = 0; } else if (nr_lines > 0) { line_file_names = malloc(sizeof(char*) * nr_lines);
From: Nick Gasson nick.gasson@arm.com
mainline inclusion from mainline-v5.7 commit 525c821de0a6e45dc31cd5313555df628d80b2a4 category: bugfix bugzilla: NA CVE: NA
-------------------------------------------------
Split from a larger patch that was also fixing a problem with the java demangler, so, before applying that patch we see:
$ perf test java 65: Demangle Java : FAILED! $ perf test -v java 65: Demangle Java : --- start --- test child forked, pid 307264 FAILED: Ljava/lang/StringLatin1;equals([B[B)Z: bool class java.lang.StringLatin1.equals(byte[], byte[]) != boolean java.lang.StringLatin1.equals(byte[], byte[]) FAILED: Ljava/util/zip/ZipUtils;CENSIZ([BI)J: long class java.util.zip.ZipUtils.CENSIZ(byte[], int) != long java.util.zip.ZipUtils.CENSIZ(byte[], int) FAILED: Ljava/util/regex/Pattern$BmpCharProperty;match(Ljava/util/regex/Matcher;ILjava/lang/CharSequence;)Z: bool class java.util.regex.Pattern$BmpCharProperty.match(class java.util.regex.Matcher., int, class java.lang., charhar, shortequence) != boolean java.util.regex.Pattern$BmpCharProperty.match(java.util.regex.Matcher, int, java.lang.CharSequence) FAILED: Ljava/lang/AbstractStringBuilder;appendChars(Ljava/lang/String;II)V: void class java.lang.AbstractStringBuilder.appendChars(class java.lang., shorttring., int, int) != void java.lang.AbstractStringBuilder.appendChars(java.lang.String, int, int) FAILED: Ljava/lang/Object;<init>()V: void class java.lang.Object<init>() != void java.lang.Object<init>() test child finished with -1 ---- end ---- Demangle Java: FAILED! $
Next patch should fix this.
Signed-off-by: Nick Gasson nick.gasson@arm.com Reviewed-by: Ian Rogers irogers@google.com Tested-by: Arnaldo Carvalho de Melo acme@redhat.com Tested-by: Ian Rogers irogers@google.com Cc: Alexander Shishkin alexander.shishkin@linux.intel.com Cc: Jiri Olsa jolsa@redhat.com Cc: Mark Rutland mark.rutland@arm.com Cc: Namhyung Kim namhyung@kernel.org Cc: Peter Zijlstra peterz@infradead.org Link: http://lore.kernel.org/lkml/20200427061520.24905-4-nick.gasson@arm.com Signed-off-by: Arnaldo Carvalho de Melo acme@redhat.com Signed-off-by: Zhichang Yuan erik.yuan@arm.com --- tools/perf/tests/Build | 1 + tools/perf/tests/builtin-test.c | 4 +++ tools/perf/tests/demangle-java-test.c | 42 +++++++++++++++++++++++++++ tools/perf/tests/tests.h | 1 + 4 files changed, 48 insertions(+) create mode 100644 tools/perf/tests/demangle-java-test.c
diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build index 6c108fa79ae3..e8fc36ed0979 100644 --- a/tools/perf/tests/Build +++ b/tools/perf/tests/Build @@ -49,6 +49,7 @@ perf-y += perf-hooks.o perf-y += clang.o perf-y += unit_number__scnprintf.o perf-y += mem2node.o +perf-y += demangle-java-test.o
$(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build $(call rule_mkdir) diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index d7a5e1b9aa6f..c71d19185ab3 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c @@ -279,6 +279,10 @@ static struct test generic_tests[] = { .desc = "mem2node", .func = test__mem2node, }, + { + .desc = "Demangle Java", + .func = test__demangle_java, + }, { .func = NULL, }, diff --git a/tools/perf/tests/demangle-java-test.c b/tools/perf/tests/demangle-java-test.c new file mode 100644 index 000000000000..8f3b90832fb0 --- /dev/null +++ b/tools/perf/tests/demangle-java-test.c @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: GPL-2.0 +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include "tests.h" +#include "session.h" +#include "debug.h" +#include "demangle-java.h" + +int test__demangle_java(struct test *test __maybe_unused, int subtest __maybe_unused) +{ + int ret = TEST_OK; + char *buf = NULL; + size_t i; + + struct { + const char *mangled, *demangled; + } test_cases[] = { + { "Ljava/lang/StringLatin1;equals([B[B)Z", + "boolean java.lang.StringLatin1.equals(byte[], byte[])" }, + { "Ljava/util/zip/ZipUtils;CENSIZ([BI)J", + "long java.util.zip.ZipUtils.CENSIZ(byte[], int)" }, + { "Ljava/util/regex/Pattern$BmpCharProperty;match(Ljava/util/regex/Matcher;ILjava/lang/CharSequence;)Z", + "boolean java.util.regex.Pattern$BmpCharProperty.match(java.util.regex.Matcher, int, java.lang.CharSequence)" }, + { "Ljava/lang/AbstractStringBuilder;appendChars(Ljava/lang/String;II)V", + "void java.lang.AbstractStringBuilder.appendChars(java.lang.String, int, int)" }, + { "Ljava/lang/Object;<init>()V", + "void java.lang.Object<init>()" }, + }; + + for (i = 0; i < sizeof(test_cases) / sizeof(test_cases[0]); i++) { + buf = java_demangle_sym(test_cases[i].mangled, 0); + if (strcmp(buf, test_cases[i].demangled)) { + pr_debug("FAILED: %s: %s != %s\n", test_cases[i].mangled, + buf, test_cases[i].demangled); + ret = TEST_FAIL; + } + free(buf); + } + + return ret; +} diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h index a9760e790563..591621b4d564 100644 --- a/tools/perf/tests/tests.h +++ b/tools/perf/tests/tests.h @@ -104,6 +104,7 @@ const char *test__clang_subtest_get_desc(int subtest); int test__clang_subtest_get_nr(void); int test__unit_number__scnprint(struct test *test, int subtest); int test__mem2node(struct test *t, int subtest); +int test__demangle_java(struct test *test, int subtest);
bool test__bp_signal_is_supported(void);
From: Nick Gasson nick.gasson@arm.com
mainline inclusion from mainline-v5.7 commit 0bdf31811be08f93a4bea015d6666df4455c5180 category: bugfix bugzilla: NA CVE: NA
-------------------------------------------------
For a Java method signature like:
Ljava/lang/AbstractStringBuilder;appendChars(Ljava/lang/String;II)V
The demangler produces:
void class java.lang.AbstractStringBuilder.appendChars(class java.lang., shorttring., int, int)
The arguments should be (java.lang.String, int, int) but the demangler interprets the "S" in String as the type code for "short". Correct this and two other minor things:
- There is no "bool" type in Java, should be "boolean".
- The demangler prepends "class" to every Java class name. This is not standard Java syntax and it wastes a lot of horizontal space if the signature is long. Remove this as there isn't any ambiguity between class names and primitives.
Committer notes:
This was split from a larger patch that also added a java demangler 'perf test' entry, that, before this patch shows the error being fixed by it:
$ perf test java 65: Demangle Java : FAILED! $ perf test -v java Couldn't bump rlimit(MEMLOCK), failures may take place when creating BPF maps, etc 65: Demangle Java : --- start --- test child forked, pid 307264 FAILED: Ljava/lang/StringLatin1;equals([B[B)Z: bool class java.lang.StringLatin1.equals(byte[], byte[]) != boolean java.lang.StringLatin1.equals(byte[], byte[]) FAILED: Ljava/util/zip/ZipUtils;CENSIZ([BI)J: long class java.util.zip.ZipUtils.CENSIZ(byte[], int) != long java.util.zip.ZipUtils.CENSIZ(byte[], int) FAILED: Ljava/util/regex/Pattern$BmpCharProperty;match(Ljava/util/regex/Matcher;ILjava/lang/CharSequence;)Z: bool class java.util.regex.Pattern$BmpCharProperty.match(class java.util.regex.Matcher., int, class java.lang., charhar, shortequence) != boolean java.util.regex.Pattern$BmpCharProperty.match(java.util.regex.Matcher, int, java.lang.CharSequence) FAILED: Ljava/lang/AbstractStringBuilder;appendChars(Ljava/lang/String;II)V: void class java.lang.AbstractStringBuilder.appendChars(class java.lang., shorttring., int, int) != void java.lang.AbstractStringBuilder.appendChars(java.lang.String, int, int) FAILED: Ljava/lang/Object;<init>()V: void class java.lang.Object<init>() != void java.lang.Object<init>() test child finished with -1 ---- end ---- Demangle Java: FAILED! $
After applying this patch:
$ perf test java 65: Demangle Java : Ok $
Signed-off-by: Nick Gasson nick.gasson@arm.com Reviewed-by: Ian Rogers irogers@google.com Tested-by: Arnaldo Carvalho de Melo acme@redhat.com Tested-by: Ian Rogers irogers@google.com Cc: Alexander Shishkin alexander.shishkin@linux.intel.com Cc: Jiri Olsa jolsa@redhat.com Cc: Mark Rutland mark.rutland@arm.com Cc: Namhyung Kim namhyung@kernel.org Cc: Peter Zijlstra peterz@infradead.org Link: http://lore.kernel.org/lkml/20200427061520.24905-4-nick.gasson@arm.com Signed-off-by: Arnaldo Carvalho de Melo acme@redhat.com Signed-off-by: Zhichang Yuan erik.yuan@arm.com --- tools/perf/util/demangle-java.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/tools/perf/util/demangle-java.c b/tools/perf/util/demangle-java.c index e4c486756053..c384f66a77fe 100644 --- a/tools/perf/util/demangle-java.c +++ b/tools/perf/util/demangle-java.c @@ -15,7 +15,7 @@ enum { MODE_CLASS = 1, MODE_FUNC = 2, MODE_TYPE = 3, - MODE_CTYPE = 3, /* class arg */ + MODE_CTYPE = 4, /* class arg */ };
#define BASE_ENT(c, n) [c - 'A']=n @@ -27,7 +27,7 @@ static const char *base_types['Z' - 'A' + 1] = { BASE_ENT('I', "int" ), BASE_ENT('J', "long" ), BASE_ENT('S', "short" ), - BASE_ENT('Z', "bool" ), + BASE_ENT('Z', "boolean" ), };
/* @@ -59,15 +59,16 @@ __demangle_java_sym(const char *str, const char *end, char *buf, int maxlen, int
switch (*q) { case 'L': - if (mode == MODE_PREFIX || mode == MODE_CTYPE) { - if (mode == MODE_CTYPE) { + if (mode == MODE_PREFIX || mode == MODE_TYPE) { + if (mode == MODE_TYPE) { if (narg) rlen += scnprintf(buf + rlen, maxlen - rlen, ", "); narg++; } - rlen += scnprintf(buf + rlen, maxlen - rlen, "class "); if (mode == MODE_PREFIX) mode = MODE_CLASS; + else + mode = MODE_CTYPE; } else buf[rlen++] = *q; break; @@ -120,7 +121,7 @@ __demangle_java_sym(const char *str, const char *end, char *buf, int maxlen, int if (mode != MODE_CLASS && mode != MODE_CTYPE) goto error; /* safe because at least one other char to process */ - if (isalpha(*(q + 1))) + if (isalpha(*(q + 1)) && mode == MODE_CLASS) rlen += scnprintf(buf + rlen, maxlen - rlen, "."); if (mode == MODE_CLASS) mode = MODE_FUNC;
From: Nick Gasson nick.gasson@arm.com
mainline inclusion from mainline-v5.7 commit 7d7e503cac31541e52ee4adb0185391ef74e1636 category: bugfix bugzilla: NA CVE: NA
-------------------------------------------------
For each PC/BCI pair in the JVMTI compiler inlining record table, the jitdump plugin emits debug line table entries for every source line in the method preceding that BCI. Instead only emit one source line per PC/BCI pair. Reported by Ian Rogers. This reduces the .dump size for SPECjbb from ~230MB to ~40MB.
Signed-off-by: Nick Gasson nick.gasson@arm.com Acked-by: Ian Rogers irogers@google.com Cc: Jiri Olsa jolsa@redhat.com Cc: Peter Zijlstra peterz@infradead.org Cc: Stephane Eranian eranian@google.com Link: http://lore.kernel.org/lkml/20200528054049.13662-1-nick.gasson@arm.com Signed-off-by: Arnaldo Carvalho de Melo acme@redhat.com Signed-off-by: Zhichang Yuan erik.yuan@arm.com --- tools/perf/jvmti/libjvmti.c | 78 ++++++++++++++++--------------------- 1 file changed, 33 insertions(+), 45 deletions(-)
diff --git a/tools/perf/jvmti/libjvmti.c b/tools/perf/jvmti/libjvmti.c index 199fb53a332c..9a546592e22f 100644 --- a/tools/perf/jvmti/libjvmti.c +++ b/tools/perf/jvmti/libjvmti.c @@ -29,38 +29,41 @@ static void print_error(jvmtiEnv *jvmti, const char *msg, jvmtiError ret) }
static jvmtiError -do_get_line_numbers(jvmtiEnv *jvmti, void *pc, jmethodID m, jint bci, - jvmti_line_info_t *tab, jint *nr) +do_get_line_number(jvmtiEnv *jvmti, void *pc, jmethodID m, jint bci, + jvmti_line_info_t *tab) { - jint i, lines = 0; - jint nr_lines = 0; + jint i, nr_lines = 0; jvmtiLineNumberEntry *loc_tab = NULL; jvmtiError ret; + jint src_line = -1;
ret = (*jvmti)->GetLineNumberTable(jvmti, m, &nr_lines, &loc_tab); if (ret == JVMTI_ERROR_ABSENT_INFORMATION || ret == JVMTI_ERROR_NATIVE_METHOD) { /* No debug information for this method */ - *nr = 0; - return JVMTI_ERROR_NONE; + return ret; } else if (ret != JVMTI_ERROR_NONE) { print_error(jvmti, "GetLineNumberTable", ret); return ret; }
- for (i = 0; i < nr_lines; i++) { - if (loc_tab[i].start_location < bci) { - tab[lines].pc = (unsigned long)pc; - tab[lines].line_number = loc_tab[i].line_number; - tab[lines].discrim = 0; /* not yet used */ - tab[lines].methodID = m; - lines++; - } else { - break; - } + for (i = 0; i < nr_lines && loc_tab[i].start_location <= bci; i++) { + src_line = i; } + + if (src_line != -1) { + tab->pc = (unsigned long)pc; + tab->line_number = loc_tab[src_line].line_number; + tab->discrim = 0; /* not yet used */ + tab->methodID = m; + + ret = JVMTI_ERROR_NONE; + } else { + ret = JVMTI_ERROR_ABSENT_INFORMATION; + } + (*jvmti)->Deallocate(jvmti, (unsigned char *)loc_tab); - *nr = lines; - return JVMTI_ERROR_NONE; + + return ret; }
static jvmtiError @@ -68,9 +71,8 @@ get_line_numbers(jvmtiEnv *jvmti, const void *compile_info, jvmti_line_info_t ** { const jvmtiCompiledMethodLoadRecordHeader *hdr; jvmtiCompiledMethodLoadInlineRecord *rec; - jvmtiLineNumberEntry *lne = NULL; PCStackInfo *c; - jint nr, ret; + jint ret; int nr_total = 0; int i, lines_total = 0;
@@ -83,24 +85,7 @@ get_line_numbers(jvmtiEnv *jvmti, const void *compile_info, jvmti_line_info_t ** for (hdr = compile_info; hdr != NULL; hdr = hdr->next) { if (hdr->kind == JVMTI_CMLR_INLINE_INFO) { rec = (jvmtiCompiledMethodLoadInlineRecord *)hdr; - for (i = 0; i < rec->numpcs; i++) { - c = rec->pcinfo + i; - nr = 0; - /* - * unfortunately, need a tab to get the number of lines! - */ - ret = (*jvmti)->GetLineNumberTable(jvmti, c->methods[0], &nr, &lne); - if (ret == JVMTI_ERROR_NONE) { - /* free what was allocated for nothing */ - (*jvmti)->Deallocate(jvmti, (unsigned char *)lne); - nr_total += (int)nr; - } else if (ret == JVMTI_ERROR_ABSENT_INFORMATION || - ret == JVMTI_ERROR_NATIVE_METHOD) { - /* No debug information for this method */ - } else { - print_error(jvmti, "GetLineNumberTable", ret); - } - } + nr_total += rec->numpcs; } }
@@ -119,14 +104,17 @@ get_line_numbers(jvmtiEnv *jvmti, const void *compile_info, jvmti_line_info_t ** rec = (jvmtiCompiledMethodLoadInlineRecord *)hdr; for (i = 0; i < rec->numpcs; i++) { c = rec->pcinfo + i; - nr = 0; - ret = do_get_line_numbers(jvmti, c->pc, - c->methods[0], - c->bcis[0], - *tab + lines_total, - &nr); + /* + * c->methods is the stack of inlined method calls + * at c->pc. [0] is the leaf method. Caller frames + * are ignored at the moment. + */ + ret = do_get_line_number(jvmti, c->pc, + c->methods[0], + c->bcis[0], + *tab + lines_total); if (ret == JVMTI_ERROR_NONE) - lines_total += nr; + lines_total++; } } }
From: Nick Gasson nick.gasson@arm.com
mainline inclusion from mainline-v5.7 commit 1e4bd2ae4564adbf9f9b6d26fad65ddabd0147fc category: bugfix bugzilla: NA CVE: NA
-------------------------------------------------
Fix an issue where addresses in the DWARF line table are offset by -0x40 (GEN_ELF_TEXT_OFFSET). This can be seen with `objdump -S` on the ELF files after perf inject.
Committer notes:
Ian added this in his Acked-by reply:
--- Without too much knowledge this looks good to me. The original code came from oprofile's jit support:
https://sourceforge.net/p/oprofile/oprofile/ci/master/tree/opjitconv/debug_l... ---
Signed-off-by: Nick Gasson nick.gasson@arm.com Acked-by: Ian Rogers irogers@google.com Cc: Jiri Olsa jolsa@redhat.com Cc: Peter Zijlstra peterz@infradead.org Cc: Stephane Eranian eranian@google.com Link: http://lore.kernel.org/lkml/20200528051916.6722-1-nick.gasson@arm.com Signed-off-by: Arnaldo Carvalho de Melo acme@redhat.com Signed-off-by: Zhichang Yuan erik.yuan@arm.com --- tools/perf/util/genelf_debug.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tools/perf/util/genelf_debug.c b/tools/perf/util/genelf_debug.c index 40789d8603d0..0b6d4fd8e1cb 100644 --- a/tools/perf/util/genelf_debug.c +++ b/tools/perf/util/genelf_debug.c @@ -344,7 +344,7 @@ static void emit_lineno_info(struct buffer_ext *be, */
/* start state of the state machine we take care of */ - unsigned long last_vma = code_addr; + unsigned long last_vma = 0; char const *cur_filename = NULL; unsigned long cur_file_idx = 0; int last_line = 1; @@ -475,7 +475,7 @@ jit_process_debug_info(uint64_t code_addr, ent = debug_entry_next(ent); } add_compilation_unit(di, buffer_ext_size(dl)); - add_debug_line(dl, debug, nr_debug_entries, 0); + add_debug_line(dl, debug, nr_debug_entries, GEN_ELF_TEXT_OFFSET); add_debug_abbrev(da); if (0) buffer_ext_dump(da, "abbrev");