diff options
Diffstat (limited to 'tools/perf/builtin-script.c')
-rw-r--r-- | tools/perf/builtin-script.c | 21 |
1 files changed, 18 insertions, 3 deletions
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 3728b50e52e2..d079f36d342d 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c | |||
@@ -1073,9 +1073,18 @@ static int perf_sample__fprintf_brstackinsn(struct perf_sample *sample, | |||
1073 | 1073 | ||
1074 | /* | 1074 | /* |
1075 | * Print final block upto sample | 1075 | * Print final block upto sample |
1076 | * | ||
1077 | * Due to pipeline delays the LBRs might be missing a branch | ||
1078 | * or two, which can result in very large or negative blocks | ||
1079 | * between final branch and sample. When this happens just | ||
1080 | * continue walking after the last TO until we hit a branch. | ||
1076 | */ | 1081 | */ |
1077 | start = br->entries[0].to; | 1082 | start = br->entries[0].to; |
1078 | end = sample->ip; | 1083 | end = sample->ip; |
1084 | if (end < start) { | ||
1085 | /* Missing jump. Scan 128 bytes for the next branch */ | ||
1086 | end = start + 128; | ||
1087 | } | ||
1079 | len = grab_bb(buffer, start, end, machine, thread, &x.is64bit, &x.cpumode, true); | 1088 | len = grab_bb(buffer, start, end, machine, thread, &x.is64bit, &x.cpumode, true); |
1080 | printed += ip__fprintf_sym(start, thread, x.cpumode, x.cpu, &lastsym, attr, fp); | 1089 | printed += ip__fprintf_sym(start, thread, x.cpumode, x.cpu, &lastsym, attr, fp); |
1081 | if (len <= 0) { | 1090 | if (len <= 0) { |
@@ -1084,7 +1093,6 @@ static int perf_sample__fprintf_brstackinsn(struct perf_sample *sample, | |||
1084 | machine, thread, &x.is64bit, &x.cpumode, false); | 1093 | machine, thread, &x.is64bit, &x.cpumode, false); |
1085 | if (len <= 0) | 1094 | if (len <= 0) |
1086 | goto out; | 1095 | goto out; |
1087 | |||
1088 | printed += fprintf(fp, "\t%016" PRIx64 "\t%s\n", sample->ip, | 1096 | printed += fprintf(fp, "\t%016" PRIx64 "\t%s\n", sample->ip, |
1089 | dump_insn(&x, sample->ip, buffer, len, NULL)); | 1097 | dump_insn(&x, sample->ip, buffer, len, NULL)); |
1090 | if (PRINT_FIELD(SRCCODE)) | 1098 | if (PRINT_FIELD(SRCCODE)) |
@@ -1096,6 +1104,13 @@ static int perf_sample__fprintf_brstackinsn(struct perf_sample *sample, | |||
1096 | dump_insn(&x, start + off, buffer + off, len - off, &ilen)); | 1104 | dump_insn(&x, start + off, buffer + off, len - off, &ilen)); |
1097 | if (ilen == 0) | 1105 | if (ilen == 0) |
1098 | break; | 1106 | break; |
1107 | if (arch_is_branch(buffer + off, len - off, x.is64bit) && start + off != sample->ip) { | ||
1108 | /* | ||
1109 | * Hit a missing branch. Just stop. | ||
1110 | */ | ||
1111 | printed += fprintf(fp, "\t... not reaching sample ...\n"); | ||
1112 | break; | ||
1113 | } | ||
1099 | if (PRINT_FIELD(SRCCODE)) | 1114 | if (PRINT_FIELD(SRCCODE)) |
1100 | print_srccode(thread, x.cpumode, start + off); | 1115 | print_srccode(thread, x.cpumode, start + off); |
1101 | } | 1116 | } |
@@ -1167,7 +1182,7 @@ static int perf_sample__fprintf_callindent(struct perf_sample *sample, | |||
1167 | struct addr_location *al, FILE *fp) | 1182 | struct addr_location *al, FILE *fp) |
1168 | { | 1183 | { |
1169 | struct perf_event_attr *attr = &evsel->attr; | 1184 | struct perf_event_attr *attr = &evsel->attr; |
1170 | size_t depth = thread_stack__depth(thread); | 1185 | size_t depth = thread_stack__depth(thread, sample->cpu); |
1171 | const char *name = NULL; | 1186 | const char *name = NULL; |
1172 | static int spacing; | 1187 | static int spacing; |
1173 | int len = 0; | 1188 | int len = 0; |
@@ -1701,7 +1716,7 @@ static bool show_event(struct perf_sample *sample, | |||
1701 | struct thread *thread, | 1716 | struct thread *thread, |
1702 | struct addr_location *al) | 1717 | struct addr_location *al) |
1703 | { | 1718 | { |
1704 | int depth = thread_stack__depth(thread); | 1719 | int depth = thread_stack__depth(thread, sample->cpu); |
1705 | 1720 | ||
1706 | if (!symbol_conf.graph_function) | 1721 | if (!symbol_conf.graph_function) |
1707 | return true; | 1722 | return true; |