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:

committed by
Steven Rostedt (VMware)

parent
ccea8727dc
commit
5a5e3d3cea
@@ -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;
|
||||
|
Reference in New Issue
Block a user