perf probe: Fix wrong address verification
Since there are some DIE which has only ranges instead of the
combination of entrypc/highpc, address verification must use
dwarf_haspc() instead of dwarf_entrypc/dwarf_highpc.
Also, the ranges only DIE will have a partial code in different section
(e.g. unlikely code will be in text.unlikely as "FUNC.cold" symbol). In
that case, we can not use dwarf_entrypc() or die_entrypc(), because the
offset from original DIE can be a minus value.
Instead, this simply gets the symbol and offset from symtab.
Without this patch;
  # perf probe -D clear_tasks_mm_cpumask:1
  Failed to get entry address of clear_tasks_mm_cpumask
    Error: Failed to add events.
And with this patch:
  # perf probe -D clear_tasks_mm_cpumask:1
  p:probe/clear_tasks_mm_cpumask clear_tasks_mm_cpumask+0
  p:probe/clear_tasks_mm_cpumask_1 clear_tasks_mm_cpumask+5
  p:probe/clear_tasks_mm_cpumask_2 clear_tasks_mm_cpumask+8
  p:probe/clear_tasks_mm_cpumask_3 clear_tasks_mm_cpumask+16
  p:probe/clear_tasks_mm_cpumask_4 clear_tasks_mm_cpumask+82
Committer testing:
I managed to reproduce the above:
  [root@quaco ~]# perf probe -D clear_tasks_mm_cpumask:1
  p:probe/clear_tasks_mm_cpumask _text+919968
  p:probe/clear_tasks_mm_cpumask_1 _text+919973
  p:probe/clear_tasks_mm_cpumask_2 _text+919976
  [root@quaco ~]#
But then when trying to actually put the probe in place, it fails if I
use :0 as the offset:
  [root@quaco ~]# perf probe -L clear_tasks_mm_cpumask | head -5
  <clear_tasks_mm_cpumask@/usr/src/debug/kernel-5.2.fc30/linux-5.2.18-200.fc30.x86_64/kernel/cpu.c:0>
        0  void clear_tasks_mm_cpumask(int cpu)
        1  {
        2  	struct task_struct *p;
  [root@quaco ~]# perf probe clear_tasks_mm_cpumask:0
  Probe point 'clear_tasks_mm_cpumask' not found.
    Error: Failed to add events.
  [root@quaco
The next patch is needed to fix this case.
Fixes: 576b523721 ("perf probe: Fix probing symbols with optimization suffix")
Reported-by: Arnaldo Carvalho de Melo <acme@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Link: http://lore.kernel.org/lkml/157199318513.8075.10463906803299647907.stgit@devnote2
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
			
			
This commit is contained in:
		
							parent
							
								
									1785fbb738
								
							
						
					
					
						commit
						07d3698578
					
				| @ -604,38 +604,26 @@ static int convert_to_trace_point(Dwarf_Die *sp_die, Dwfl_Module *mod, | ||||
| 				  const char *function, | ||||
| 				  struct probe_trace_point *tp) | ||||
| { | ||||
| 	Dwarf_Addr eaddr, highaddr; | ||||
| 	Dwarf_Addr eaddr; | ||||
| 	GElf_Sym sym; | ||||
| 	const char *symbol; | ||||
| 
 | ||||
| 	/* Verify the address is correct */ | ||||
| 	if (dwarf_entrypc(sp_die, &eaddr) != 0) { | ||||
| 		pr_warning("Failed to get entry address of %s\n", | ||||
| 			   dwarf_diename(sp_die)); | ||||
| 		return -ENOENT; | ||||
| 	} | ||||
| 	if (dwarf_highpc(sp_die, &highaddr) != 0) { | ||||
| 		pr_warning("Failed to get end address of %s\n", | ||||
| 			   dwarf_diename(sp_die)); | ||||
| 		return -ENOENT; | ||||
| 	} | ||||
| 	if (paddr > highaddr) { | ||||
| 		pr_warning("Offset specified is greater than size of %s\n", | ||||
| 	if (!dwarf_haspc(sp_die, paddr)) { | ||||
| 		pr_warning("Specified offset is out of %s\n", | ||||
| 			   dwarf_diename(sp_die)); | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
| 
 | ||||
| 	symbol = dwarf_diename(sp_die); | ||||
| 	/* Try to get actual symbol name from symtab */ | ||||
| 	symbol = dwfl_module_addrsym(mod, paddr, &sym, NULL); | ||||
| 	if (!symbol) { | ||||
| 		/* Try to get the symbol name from symtab */ | ||||
| 		symbol = dwfl_module_addrsym(mod, paddr, &sym, NULL); | ||||
| 		if (!symbol) { | ||||
| 			pr_warning("Failed to find symbol at 0x%lx\n", | ||||
| 				   (unsigned long)paddr); | ||||
| 			return -ENOENT; | ||||
| 		} | ||||
| 		eaddr = sym.st_value; | ||||
| 		pr_warning("Failed to find symbol at 0x%lx\n", | ||||
| 			   (unsigned long)paddr); | ||||
| 		return -ENOENT; | ||||
| 	} | ||||
| 	eaddr = sym.st_value; | ||||
| 
 | ||||
| 	tp->offset = (unsigned long)(paddr - eaddr); | ||||
| 	tp->address = (unsigned long)paddr; | ||||
| 	tp->symbol = strdup(symbol); | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user