aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/annotate.c
diff options
context:
space:
mode:
authorRavi Bangoria <ravi.bangoria@linux.vnet.ibm.com>2016-12-05 10:56:47 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2016-12-15 14:25:46 -0500
commite216874cc1946d28084fa90e495e02725a29e25f (patch)
tree3a1b44e133677030fa4370460c43b0f8c88c9759 /tools/perf/util/annotate.c
parent3ee2eb6da20db1edad31070da38996e8e0f8adfa (diff)
perf annotate: Fix jump target outside of function address range
If jump target is outside of function range, perf is not handling it correctly. Especially when target address is lesser than function start address, target offset will be negative. But, target address declared to be unsigned, converts negative number into 2's complement. See below example. Here target of 'jumpq' instruction at 34cf8 is 34ac0 which is lesser than function start address(34cf0). 34ac0 - 34cf0 = -0x230 = 0xfffffffffffffdd0 Objdump output: 0000000000034cf0 <__sigaction>: __GI___sigaction(): 34cf0: lea -0x20(%rdi),%eax 34cf3: cmp -bashx1,%eax 34cf6: jbe 34d00 <__sigaction+0x10> 34cf8: jmpq 34ac0 <__GI___libc_sigaction> 34cfd: nopl (%rax) 34d00: mov 0x386161(%rip),%rax # 3bae68 <_DYNAMIC+0x2e8> 34d07: movl -bashx16,%fs:(%rax) 34d0e: mov -bashxffffffff,%eax 34d13: retq perf annotate before applying patch: __GI___sigaction /usr/lib64/libc-2.22.so lea -0x20(%rdi),%eax cmp -bashx1,%eax v jbe 10 v jmpq fffffffffffffdd0 nop 10: mov _DYNAMIC+0x2e8,%rax movl -bashx16,%fs:(%rax) mov -bashxffffffff,%eax retq perf annotate after applying patch: __GI___sigaction /usr/lib64/libc-2.22.so lea -0x20(%rdi),%eax cmp -bashx1,%eax v jbe 10 ^ jmpq 34ac0 <__GI___libc_sigaction> nop 10: mov _DYNAMIC+0x2e8,%rax movl -bashx16,%fs:(%rax) mov -bashxffffffff,%eax retq Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Chris Riyder <chris.ryder@arm.com> Cc: Kim Phillips <kim.phillips@arm.com> Cc: Markus Trippelsdorf <markus@trippelsdorf.de> Cc: Masami Hiramatsu <mhiramat@kernel.org> Cc: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Taeung Song <treeze.taeung@gmail.com> Cc: linuxppc-dev@lists.ozlabs.org Link: http://lkml.kernel.org/r/1480953407-7605-3-git-send-email-ravi.bangoria@linux.vnet.ibm.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util/annotate.c')
-rw-r--r--tools/perf/util/annotate.c14
1 files changed, 9 insertions, 5 deletions
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 590244e5781e..c81a3950a7fe 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -230,10 +230,12 @@ static int jump__parse(struct arch *arch __maybe_unused, struct ins_operands *op
230 else 230 else
231 ops->target.addr = strtoull(ops->raw, NULL, 16); 231 ops->target.addr = strtoull(ops->raw, NULL, 16);
232 232
233 if (s++ != NULL) 233 if (s++ != NULL) {
234 ops->target.offset = strtoull(s, NULL, 16); 234 ops->target.offset = strtoull(s, NULL, 16);
235 else 235 ops->target.offset_avail = true;
236 ops->target.offset = UINT64_MAX; 236 } else {
237 ops->target.offset_avail = false;
238 }
237 239
238 return 0; 240 return 0;
239} 241}
@@ -241,7 +243,7 @@ static int jump__parse(struct arch *arch __maybe_unused, struct ins_operands *op
241static int jump__scnprintf(struct ins *ins, char *bf, size_t size, 243static int jump__scnprintf(struct ins *ins, char *bf, size_t size,
242 struct ins_operands *ops) 244 struct ins_operands *ops)
243{ 245{
244 if (!ops->target.addr) 246 if (!ops->target.addr || ops->target.offset < 0)
245 return ins__raw_scnprintf(ins, bf, size, ops); 247 return ins__raw_scnprintf(ins, bf, size, ops);
246 248
247 return scnprintf(bf, size, "%-6.6s %" PRIx64, ins->name, ops->target.offset); 249 return scnprintf(bf, size, "%-6.6s %" PRIx64, ins->name, ops->target.offset);
@@ -1209,9 +1211,11 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
1209 if (dl == NULL) 1211 if (dl == NULL)
1210 return -1; 1212 return -1;
1211 1213
1212 if (dl->ops.target.offset == UINT64_MAX) 1214 if (!disasm_line__has_offset(dl)) {
1213 dl->ops.target.offset = dl->ops.target.addr - 1215 dl->ops.target.offset = dl->ops.target.addr -
1214 map__rip_2objdump(map, sym->start); 1216 map__rip_2objdump(map, sym->start);
1217 dl->ops.target.offset_avail = true;
1218 }
1215 1219
1216 /* kcore has no symbols, so add the call target name */ 1220 /* kcore has no symbols, so add the call target name */
1217 if (dl->ins.ops && ins__is_call(&dl->ins) && !dl->ops.target.name) { 1221 if (dl->ins.ops && ins__is_call(&dl->ins) && !dl->ops.target.name) {