perf probe: Support SDT markers having reference counter (semaphore)

With this, perf buildid-cache will save SDT markers with reference
counter in probe cache. Perf probe will be able to probe markers
having reference counter. Ex,

  # readelf -n /tmp/tick | grep -A1 loop2
    Name: loop2
    ... Semaphore: 0x0000000010020036

  # ./perf buildid-cache --add /tmp/tick
  # ./perf probe sdt_tick:loop2
  # ./perf stat -e sdt_tick:loop2 /tmp/tick
    hi: 0
    hi: 1
    hi: 2
    ^C
     Performance counter stats for '/tmp/tick':
                 3      sdt_tick:loop2
       2.561851452 seconds time elapsed

Link: http://lkml.kernel.org/r/20180820044250.11659-5-ravi.bangoria@linux.ibm.com

Acked-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Acked-by: Masami Hiramatsu <mhiramat@kernel.org>
Acked-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Reviewed-by: Song Liu <songliubraving@fb.com>
Tested-by: Song Liu <songliubraving@fb.com>
Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.ibm.com>
Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
This commit is contained in:
Ravi Bangoria
2018-08-20 10:12:50 +05:30
committed by Steven Rostedt (VMware)
parent ccea8727dc
commit 5a5e3d3cea
6 changed files with 106 additions and 22 deletions

View File

@@ -1947,6 +1947,34 @@ void kcore_extract__delete(struct kcore_extract *kce)
}
#ifdef HAVE_GELF_GETNOTE_SUPPORT
static void sdt_adjust_loc(struct sdt_note *tmp, GElf_Addr base_off)
{
if (!base_off)
return;
if (tmp->bit32)
tmp->addr.a32[SDT_NOTE_IDX_LOC] =
tmp->addr.a32[SDT_NOTE_IDX_LOC] + base_off -
tmp->addr.a32[SDT_NOTE_IDX_BASE];
else
tmp->addr.a64[SDT_NOTE_IDX_LOC] =
tmp->addr.a64[SDT_NOTE_IDX_LOC] + base_off -
tmp->addr.a64[SDT_NOTE_IDX_BASE];
}
static void sdt_adjust_refctr(struct sdt_note *tmp, GElf_Addr base_addr,
GElf_Addr base_off)
{
if (!base_off)
return;
if (tmp->bit32 && tmp->addr.a32[SDT_NOTE_IDX_REFCTR])
tmp->addr.a32[SDT_NOTE_IDX_REFCTR] -= (base_addr - base_off);
else if (tmp->addr.a64[SDT_NOTE_IDX_REFCTR])
tmp->addr.a64[SDT_NOTE_IDX_REFCTR] -= (base_addr - base_off);
}
/**
* populate_sdt_note : Parse raw data and identify SDT note
* @elf: elf of the opened file
@@ -1964,7 +1992,6 @@ static int populate_sdt_note(Elf **elf, const char *data, size_t len,
const char *provider, *name, *args;
struct sdt_note *tmp = NULL;
GElf_Ehdr ehdr;
GElf_Addr base_off = 0;
GElf_Shdr shdr;
int ret = -EINVAL;
@@ -2060,17 +2087,12 @@ static int populate_sdt_note(Elf **elf, const char *data, size_t len,
* base address in the description of the SDT note. If its different,
* then accordingly, adjust the note location.
*/
if (elf_section_by_name(*elf, &ehdr, &shdr, SDT_BASE_SCN, NULL)) {
base_off = shdr.sh_offset;
if (base_off) {
if (tmp->bit32)
tmp->addr.a32[0] = tmp->addr.a32[0] + base_off -
tmp->addr.a32[1];
else
tmp->addr.a64[0] = tmp->addr.a64[0] + base_off -
tmp->addr.a64[1];
}
}
if (elf_section_by_name(*elf, &ehdr, &shdr, SDT_BASE_SCN, NULL))
sdt_adjust_loc(tmp, shdr.sh_offset);
/* Adjust reference counter offset */
if (elf_section_by_name(*elf, &ehdr, &shdr, SDT_PROBES_SCN, NULL))
sdt_adjust_refctr(tmp, shdr.sh_addr, shdr.sh_offset);
list_add_tail(&tmp->note_list, sdt_notes);
return 0;