aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorAndi Kleen <ak@linux.intel.com>2019-09-27 19:35:44 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2019-09-30 16:29:52 -0400
commite98df280bc2a499fd41d7f9e2d6733884de69902 (patch)
treea8d0d0604f6737168e3792fe31eb92e9746df14a /tools
parent2657983b4c0d81632c6a73bae469951b0d341251 (diff)
perf script brstackinsn: Fix recovery from LBR/binary mismatch
When the LBR data and the instructions in a binary do not match the loop printing instructions could get confused and print a long stream of bogus <bad> instructions. The problem was that if the instruction decoder cannot decode an instruction it ilen wasn't initialized, so the loop going through the basic block would continue with the previous value. Harden the code to avoid such problems: - Make sure ilen is always freshly initialized and is 0 for bad instructions. - Do not overrun the code buffer while printing instructions - Print a warning message if the final jump is not on an instruction boundary. Signed-off-by: Andi Kleen <ak@linux.intel.com> Cc: Jiri Olsa <jolsa@kernel.org> Link: http://lore.kernel.org/lkml/20190927233546.11533-1-andi@firstfloor.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/builtin-script.c6
1 files changed, 5 insertions, 1 deletions
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 286fc70d7402..67be8d31afab 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -1063,7 +1063,7 @@ static int perf_sample__fprintf_brstackinsn(struct perf_sample *sample,
1063 continue; 1063 continue;
1064 1064
1065 insn = 0; 1065 insn = 0;
1066 for (off = 0;; off += ilen) { 1066 for (off = 0; off < (unsigned)len; off += ilen) {
1067 uint64_t ip = start + off; 1067 uint64_t ip = start + off;
1068 1068
1069 printed += ip__fprintf_sym(ip, thread, x.cpumode, x.cpu, &lastsym, attr, fp); 1069 printed += ip__fprintf_sym(ip, thread, x.cpumode, x.cpu, &lastsym, attr, fp);
@@ -1074,6 +1074,7 @@ static int perf_sample__fprintf_brstackinsn(struct perf_sample *sample,
1074 printed += print_srccode(thread, x.cpumode, ip); 1074 printed += print_srccode(thread, x.cpumode, ip);
1075 break; 1075 break;
1076 } else { 1076 } else {
1077 ilen = 0;
1077 printed += fprintf(fp, "\t%016" PRIx64 "\t%s\n", ip, 1078 printed += fprintf(fp, "\t%016" PRIx64 "\t%s\n", ip,
1078 dump_insn(&x, ip, buffer + off, len - off, &ilen)); 1079 dump_insn(&x, ip, buffer + off, len - off, &ilen));
1079 if (ilen == 0) 1080 if (ilen == 0)
@@ -1083,6 +1084,8 @@ static int perf_sample__fprintf_brstackinsn(struct perf_sample *sample,
1083 insn++; 1084 insn++;
1084 } 1085 }
1085 } 1086 }
1087 if (off != (unsigned)len)
1088 printed += fprintf(fp, "\tmismatch of LBR data and executable\n");
1086 } 1089 }
1087 1090
1088 /* 1091 /*
@@ -1123,6 +1126,7 @@ static int perf_sample__fprintf_brstackinsn(struct perf_sample *sample,
1123 goto out; 1126 goto out;
1124 } 1127 }
1125 for (off = 0; off <= end - start; off += ilen) { 1128 for (off = 0; off <= end - start; off += ilen) {
1129 ilen = 0;
1126 printed += fprintf(fp, "\t%016" PRIx64 "\t%s\n", start + off, 1130 printed += fprintf(fp, "\t%016" PRIx64 "\t%s\n", start + off,
1127 dump_insn(&x, start + off, buffer + off, len - off, &ilen)); 1131 dump_insn(&x, start + off, buffer + off, len - off, &ilen));
1128 if (ilen == 0) 1132 if (ilen == 0)