Subject: Re: [PATCH perf/core 1/2] [BUGFIX] perf-probe: Fix to handle optimized not-inlined but has no instance

(2015/01/30 23:32), Arnaldo Carvalho de Melo wrote:
> Em Fri, Jan 30, 2015 at 11:21:35AM -0300, Arnaldo Carvalho de Melo escreveu:
>> Em Fri, Jan 30, 2015 at 06:37:44PM +0900, Masami Hiramatsu escreveu:
>>> Fix to handle optimized no-inline functions which have
>>> only function definition but no actual instance at
>>> that point. To fix this problem, we need to find actual
>>> instance of the function.
>>>
>>> Without this patch:
>>> ----
>>> # perf probe -a __up
>>> Failed to get entry address of __up.
>>> Error: Failed to add events.
>>> # perf probe -L __up
>>> Specified source line is not found.
>>> Error: Failed to show lines.
>>> ----
>>>
>>> With this patch:
>>> ----
>>> # perf probe -a __up
>>> Added new event:
>>> probe:__up (on __up)
>>>
>>> You can now use it in all perf tools, such as:
>>>
>>> perf record -e probe:__up -aR sleep 1
>>>
>>> # perf probe -L __up
>>> <__up@/home/fedora/ksrc/linux-3/kernel/locking/semaphore.c:0>
>>> 0 static noinline void __sched __up(struct semaphore *sem)
>>> {
>>> struct semaphore_waiter *waiter = list_first_entry(&sem->wait_
>>> struct semaphore_waite
>>> 4 list_del(&waiter->list);
>>> 5 waiter->up = true;
>>> 6 wake_up_process(waiter->task);
>>> 7 }
>>> ----
>>
>> Since __up here was built in some other way, I looked for another
>
> Nah, I saw you trying to add "perf probe -a __up" and stopped there,
> hadn't seen that it fails _as well_ for just listing the source code...
>
> Yes, I managed to reproduce the problem and test your fix, it works:

Thanks for testing!

>
> [root@zoo ~]# perf probe --del __up
> Removed event: probe:__up
> [root@zoo ~]# perf probe -L __up
> Specified source line is not found.
> Error: Failed to show lines.
>
> ---->>>>>> APPLY THE PATCH, rebuild and try again:
>
> [root@zoo ~]#
> [root@zoo ~]# perf probe -L __up
> <__up@/home/git/linux/kernel/locking/semaphore.c:0>
> 0 static noinline void __sched __up(struct semaphore *sem)
> {
> struct semaphore_waiter *waiter = list_first_entry(&sem->wait_list,
> struct semaphore_waiter, list);
> 4 list_del(&waiter->list);
> 5 waiter->up = true;
> 6 wake_up_process(waiter->task);
> 7 }
> [root@zoo ~]#
>
> --------------------------------------------------------------
>
> So its just this other case that fails, vmalloc_fault, can you check
> this one? Does it happen in your machine as well?

OK, I'll try reproducing this and dig deeper.

>
> Applying your patch, thanks,

Thank you!

>
> - Arnaldo
>
>> 'noinline' function to try, and it failed here:
>>
>> [root@zoo ~]# perf probe -L vmalloc_fault | head -5
>> <vmalloc_fault@/home/git/linux/arch/x86/mm/fault.c:0>
>> 0 static noinline int vmalloc_fault(unsigned long address)
>> 1 {
>> pgd_t *pgd, *pgd_ref;
>> pud_t *pud, *pud_ref;
>> [root@zoo ~]# perf probe vmalloc_fault
>> Added new event:
>> Failed to write event: Invalid argument
>> Error: Failed to add events.
>>
>> ---->>>>>> APPLY THE PATCH, rebuild and try again:
>>
>> [root@zoo ~]# perf probe vmalloc_fault
>> Added new event:
>> Failed to write event: Invalid argument
>> Error: Failed to add events.
>> [root@zoo ~]# perf probe -v vmalloc_fault
>> probe-definition(0): vmalloc_fault
>> symbol:vmalloc_fault file:(null) line:0 offset:0 return:0 lazy:(null)
>> 0 arguments
>> Looking at the vmlinux_path (7 entries long)
>> Using /lib/modules/3.19.0-rc6+/build/vmlinux for symbols
>> Open Debuginfo file: /lib/modules/3.19.0-rc6+/build/vmlinux
>> Try to find probe point from debuginfo.
>> Probe point found: vmalloc_fault+0
>> Found 1 probe_trace_events.
>> Opening /sys/kernel/debug/tracing/kprobe_events write=1
>> Added new event:
>> Writing event: p:probe/vmalloc_fault _text+289600
>> Failed to write event: Invalid argument
>> Error: Failed to add events. Reason: Invalid argument (Code: -22)
>> [root@zoo ~]# grep -w vmalloc_fault /proc/kallsyms
>> ffffffff81046b40 t vmalloc_fault
>> [root@zoo ~]# grep -w _text /proc/kallsyms
>> ffffffff81000000 T _text
>> [root@zoo ~]# python
>> Python 2.7.5 (default, Nov 3 2014, 14:26:24)
>> [GCC 4.8.3 20140911 (Red Hat 4.8.3-7)] on linux2
>> Type "help", "copyright", "credits" or "license" for more information.
>> >>> 0xffffffff81046b40 - 0xffffffff81000000
>> 289600L
>> >>>
>> [root@zoo ~]# readelf -s /lib/modules/3.19.0-rc6+/build/vmlinux | egrep -w _text\|vmalloc_fault
>> 3499: ffffffff81046b40 410 FUNC LOCAL DEFAULT 1 vmalloc_fault
>> 48873: ffffffff81000000 0 NOTYPE GLOBAL DEFAULT 1 _text
>> [root@zoo ~]#
>>
>> ---------------------------------------------------------------------------
>>
>> So perhaps I need a 'noinline' _and_ '__sched', so that I have a "optimized
>> no-inline functions which have only function definition but no actual instance
>> at that point"?
>>
>> Looking for one, will post here after objdump -dS finishes...
>>
>> - Arnaldo
>


--
Masami HIRAMATSU
Software Platform Research Dept. Linux Technology Research Center
Hitachi, Ltd., Yokohama Research Laboratory
E-mail: [email protected]


Subject: Re: Re: [PATCH perf/core 1/2] [BUGFIX] perf-probe: Fix to handle optimized not-inlined but has no instance

(2015/01/30 23:21), Arnaldo Carvalho de Melo wrote:
> Em Fri, Jan 30, 2015 at 06:37:44PM +0900, Masami Hiramatsu escreveu:
>> Fix to handle optimized no-inline functions which have
>> only function definition but no actual instance at
>> that point. To fix this problem, we need to find actual
>> instance of the function.
>>
>> Without this patch:
>> ----
>> # perf probe -a __up
>> Failed to get entry address of __up.
>> Error: Failed to add events.
>> # perf probe -L __up
>> Specified source line is not found.
>> Error: Failed to show lines.
>> ----
>>
>> With this patch:
>> ----
>> # perf probe -a __up
>> Added new event:
>> probe:__up (on __up)
>>
>> You can now use it in all perf tools, such as:
>>
>> perf record -e probe:__up -aR sleep 1
>>
>> # perf probe -L __up
>> <__up@/home/fedora/ksrc/linux-3/kernel/locking/semaphore.c:0>
>> 0 static noinline void __sched __up(struct semaphore *sem)
>> {
>> struct semaphore_waiter *waiter = list_first_entry(&sem->wait_
>> struct semaphore_waite
>> 4 list_del(&waiter->list);
>> 5 waiter->up = true;
>> 6 wake_up_process(waiter->task);
>> 7 }
>> ----
>
> Since __up here was built in some other way, I looked for another
> 'noinline' function to try, and it failed here:
>
> [root@zoo ~]# perf probe -L vmalloc_fault | head -5
> <vmalloc_fault@/home/git/linux/arch/x86/mm/fault.c:0>
> 0 static noinline int vmalloc_fault(unsigned long address)
> 1 {
> pgd_t *pgd, *pgd_ref;
> pud_t *pud, *pud_ref;
> [root@zoo ~]# perf probe vmalloc_fault
> Added new event:
> Failed to write event: Invalid argument
> Error: Failed to add events.
>
> ---->>>>>> APPLY THE PATCH, rebuild and try again:
>
> [root@zoo ~]# perf probe vmalloc_fault
> Added new event:
> Failed to write event: Invalid argument
> Error: Failed to add events.
> [root@zoo ~]# perf probe -v vmalloc_fault
> probe-definition(0): vmalloc_fault
> symbol:vmalloc_fault file:(null) line:0 offset:0 return:0 lazy:(null)
> 0 arguments
> Looking at the vmlinux_path (7 entries long)
> Using /lib/modules/3.19.0-rc6+/build/vmlinux for symbols
> Open Debuginfo file: /lib/modules/3.19.0-rc6+/build/vmlinux
> Try to find probe point from debuginfo.
> Probe point found: vmalloc_fault+0
> Found 1 probe_trace_events.
> Opening /sys/kernel/debug/tracing/kprobe_events write=1
> Added new event:
> Writing event: p:probe/vmalloc_fault _text+289600
> Failed to write event: Invalid argument
> Error: Failed to add events. Reason: Invalid argument (Code: -22)
> [root@zoo ~]# grep -w vmalloc_fault /proc/kallsyms
> ffffffff81046b40 t vmalloc_fault
> [root@zoo ~]# grep -w _text /proc/kallsyms
> ffffffff81000000 T _text
> [root@zoo ~]# python
> Python 2.7.5 (default, Nov 3 2014, 14:26:24)
> [GCC 4.8.3 20140911 (Red Hat 4.8.3-7)] on linux2
> Type "help", "copyright", "credits" or "license" for more information.
> >>> 0xffffffff81046b40 - 0xffffffff81000000
> 289600L
> >>>
> [root@zoo ~]# readelf -s /lib/modules/3.19.0-rc6+/build/vmlinux | egrep -w _text\|vmalloc_fault
> 3499: ffffffff81046b40 410 FUNC LOCAL DEFAULT 1 vmalloc_fault
> 48873: ffffffff81000000 0 NOTYPE GLOBAL DEFAULT 1 _text
> [root@zoo ~]#
>
> ---------------------------------------------------------------------------
>
> So perhaps I need a 'noinline' _and_ '__sched', so that I have a "optimized
> no-inline functions which have only function definition but no actual instance
> at that point"?

Ok, actually vmalloc_fault is marked as a nokprobe symbol.

$ grep vmalloc_fault -r arch/x86/
arch/x86/mm/fault.c:static noinline int vmalloc_fault(unsigned long address)
arch/x86/mm/fault.c:NOKPROBE_SYMBOL(vmalloc_fault);
arch/x86/mm/fault.c:static noinline int vmalloc_fault(unsigned long address)
arch/x86/mm/fault.c:NOKPROBE_SYMBOL(vmalloc_fault);
arch/x86/mm/fault.c: if (vmalloc_fault(address) >= 0)

All the symbols which marked by NOKPROBE_SYMBOL macro can not be
kprobed. And we now have <debugfs>/kprobes/blacklist special file
to get all nokprobe symbols.
I'll make another perf-probe patch which looks the blacklist before
trying define new events.

Thank you,

>
> Looking for one, will post here after objdump -dS finishes...
>
> - Arnaldo
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
>


--
Masami HIRAMATSU
Software Platform Research Dept. Linux Technology Research Center
Hitachi, Ltd., Yokohama Research Laboratory
E-mail: [email protected]

2015-02-11 20:41:58

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: Re: Re: [PATCH perf/core 1/2] [BUGFIX] perf-probe: Fix to handle optimized not-inlined but has no instance

Em Sun, Feb 08, 2015 at 05:37:08PM +0900, Masami Hiramatsu escreveu:
> (2015/01/30 23:21), Arnaldo Carvalho de Melo wrote:
> > So perhaps I need a 'noinline' _and_ '__sched', so that I have a "optimized
> > no-inline functions which have only function definition but no actual instance
> > at that point"?
>
> Ok, actually vmalloc_fault is marked as a nokprobe symbol.
>
> $ grep vmalloc_fault -r arch/x86/
> arch/x86/mm/fault.c:static noinline int vmalloc_fault(unsigned long address)
> arch/x86/mm/fault.c:NOKPROBE_SYMBOL(vmalloc_fault);
> arch/x86/mm/fault.c:static noinline int vmalloc_fault(unsigned long address)
> arch/x86/mm/fault.c:NOKPROBE_SYMBOL(vmalloc_fault);
> arch/x86/mm/fault.c: if (vmalloc_fault(address) >= 0)
>
> All the symbols which marked by NOKPROBE_SYMBOL macro can not be
> kprobed. And we now have <debugfs>/kprobes/blacklist special file

Ok!

> to get all nokprobe symbols.

> I'll make another perf-probe patch which looks the blacklist before
> trying define new events.

Ok, that will help, improving the error messages is a big priority.

- Arnaldo

Subject: [PATCH perf/core ] perf-probe: Check kprobes blacklist when adding new events

Recent linux kernel provides a blacklist of the functions which
can not be probed. perf probe can now check this blacklist before
setting new events and indicate better error message for users.

Without this patch,
----
# perf probe --add vmalloc_fault
Added new event:
Failed to write event: Invalid argument
Error: Failed to add events.
----
With this patch
----
# perf probe --add vmalloc_fault
Added new event:
Warning: Skipped probing on blacklisted function: vmalloc_fault
----

Signed-off-by: Masami Hiramatsu <[email protected]>
Reported-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/util/probe-event.c | 109 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 108 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 9dfbed9..662d454 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -1903,6 +1903,95 @@ static struct strlist *get_probe_trace_command_rawlist(int fd)
return sl;
}

+struct kprobe_blacklist_node {
+ struct list_head list;
+ unsigned long start;
+ unsigned long end;
+ char *symbol;
+};
+
+static void kprobe_blacklist__delete(struct list_head *blacklist)
+{
+ struct kprobe_blacklist_node *node;
+
+ while (!list_empty(blacklist)) {
+ node = list_first_entry(blacklist,
+ struct kprobe_blacklist_node, list);
+ list_del(&node->list);
+ free(node->symbol);
+ free(node);
+ }
+}
+
+static int kprobe_blacklist__load(struct list_head *blacklist)
+{
+ struct kprobe_blacklist_node *node;
+ const char *__debugfs = debugfs_find_mountpoint();
+ char buf[PATH_MAX], *p;
+ FILE *fp;
+ int ret;
+
+ if (__debugfs == NULL)
+ return -ENOTSUP;
+
+ ret = e_snprintf(buf, PATH_MAX, "%s/kprobes/blacklist", __debugfs);
+ if (ret < 0)
+ return ret;
+
+ fp = fopen(buf, "r");
+ if (!fp)
+ return -errno;
+
+ ret = 0;
+ while (fgets(buf, PATH_MAX, fp)) {
+ node = zalloc(sizeof(*node));
+ if (!node) {
+ ret = -ENOMEM;
+ break;
+ }
+ INIT_LIST_HEAD(&node->list);
+ list_add_tail(&node->list, blacklist);
+ if (sscanf(buf, "0x%lx-0x%lx", &node->start, &node->end) != 2) {
+ ret = -EINVAL;
+ break;
+ }
+ p = strchr(buf, '\t');
+ if (p) {
+ p++;
+ if (p[strlen(p) - 1] == '\n')
+ p[strlen(p) - 1] = '\0';
+ } else
+ p = (char *)"unknown";
+ node->symbol = strdup(p);
+ if (!node->symbol) {
+ ret = -ENOMEM;
+ break;
+ }
+ pr_debug2("Blacklist: 0x%lx-0x%lx, %s\n",
+ node->start, node->end, node->symbol);
+ ret++;
+ }
+ if (ret < 0)
+ kprobe_blacklist__delete(blacklist);
+ fclose(fp);
+
+ return ret;
+}
+
+static struct kprobe_blacklist_node *
+kprobe_blacklist__find_by_address(struct list_head *blacklist,
+ unsigned long address)
+{
+ struct kprobe_blacklist_node *node;
+
+ list_for_each_entry(node, blacklist, list) {
+ if (node->start <= address && address <= node->end)
+ return node;
+ }
+
+ return NULL;
+}
+
/* Show an event */
static int show_perf_probe_event(struct perf_probe_event *pev,
const char *module)
@@ -2117,6 +2206,8 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
char buf[64];
const char *event, *group;
struct strlist *namelist;
+ LIST_HEAD(blacklist);
+ struct kprobe_blacklist_node *node;

if (pev->uprobes)
fd = open_uprobe_events(true);
@@ -2134,11 +2225,25 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
pr_debug("Failed to get current event list.\n");
return -EIO;
}
+ /* Get kprobe blacklist if exists */
+ if (!pev->uprobes) {
+ ret = kprobe_blacklist__load(&blacklist);
+ if (ret < 0)
+ pr_debug("No kprobe blacklist support, ignored\n");
+ }

ret = 0;
pr_info("Added new event%s\n", (ntevs > 1) ? "s:" : ":");
for (i = 0; i < ntevs; i++) {
tev = &tevs[i];
+ /* Ensure that the address is NOT blacklisted */
+ node = kprobe_blacklist__find_by_address(&blacklist,
+ tev->point.address);
+ if (node) {
+ pr_warning("Warning: Skipped probing on blacklisted function: %s\n", node->symbol);
+ continue;
+ }
+
if (pev->event)
event = pev->event;
else
@@ -2189,13 +2294,15 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
allow_suffix = true;
}

- if (ret >= 0) {
+ /* Note that it is possible to skip all events because of blacklist */
+ if (ret >= 0 && tev->event) {
/* Show how to use the event. */
pr_info("\nYou can now use it in all perf tools, such as:\n\n");
pr_info("\tperf record -e %s:%s -aR sleep 1\n\n", tev->group,
tev->event);
}

+ kprobe_blacklist__delete(&blacklist);
strlist__delete(namelist);
close(fd);
return ret;

2015-02-25 21:50:17

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: Re: [PATCH perf/core ] perf-probe: Check kprobes blacklist when adding new events

Em Thu, Feb 19, 2015 at 11:31:13PM +0900, Masami Hiramatsu escreveu:
> Recent linux kernel provides a blacklist of the functions which
> can not be probed. perf probe can now check this blacklist before
> setting new events and indicate better error message for users.
>
> Without this patch,
> ----
> # perf probe --add vmalloc_fault
> Added new event:
> Failed to write event: Invalid argument
> Error: Failed to add events.
> ----
> With this patch
> ----
> # perf probe --add vmalloc_fault
> Added new event:
> Warning: Skipped probing on blacklisted function: vmalloc_fault
> ----
>
> Signed-off-by: Masami Hiramatsu <[email protected]>
> Reported-by: Arnaldo Carvalho de Melo <[email protected]>

Ok, I really need to use a newer kernel on this RHEL7 box, a 4.0-rc one,
as when trying this I saw no difference, but probably that is because it
didn't find the kprobes blacklist, tried inserting the probe and then
failed with the exact previous message...

A follow up patch could try to improve the situation by saying something
like:

"Failed to insert the probe, maybe this is a blacklisted function and
you're running an old kernel?

Please check the function definition, it should not be marked as, for
instance:

NOKPROBE_SYMBOL(vmalloc_fault);"

Anyway, applying your patch, clearly an improvement when the blacklist
is available.

Thanks,

- Arnaldo

Subject: [tip:perf/core] perf probe: Check kprobes blacklist when adding new events

Commit-ID: 9aaf5a5f479bd68699f2e6f6e5e5f1253377b6da
Gitweb: http://git.kernel.org/tip/9aaf5a5f479bd68699f2e6f6e5e5f1253377b6da
Author: Masami Hiramatsu <[email protected]>
AuthorDate: Thu, 19 Feb 2015 23:31:13 +0900
Committer: Arnaldo Carvalho de Melo <[email protected]>
CommitDate: Thu, 26 Feb 2015 11:59:05 -0300

perf probe: Check kprobes blacklist when adding new events

Recent linux kernel provides a blacklist of the functions which can not
be probed. perf probe can now check this blacklist before setting new
events and indicate better error message for users.

Without this patch,
----
# perf probe --add vmalloc_fault
Added new event:
Failed to write event: Invalid argument
Error: Failed to add events.
----
With this patch
----
# perf probe --add vmalloc_fault
Added new event:
Warning: Skipped probing on blacklisted function: vmalloc_fault
----

Reported-by: Arnaldo Carvalho de Melo <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Masami Hiramatsu <[email protected]>
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/util/probe-event.c | 109 +++++++++++++++++++++++++++++++++++++++++-
1 file changed, 108 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 9dfbed9..662d454 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -1903,6 +1903,95 @@ static struct strlist *get_probe_trace_command_rawlist(int fd)
return sl;
}

+struct kprobe_blacklist_node {
+ struct list_head list;
+ unsigned long start;
+ unsigned long end;
+ char *symbol;
+};
+
+static void kprobe_blacklist__delete(struct list_head *blacklist)
+{
+ struct kprobe_blacklist_node *node;
+
+ while (!list_empty(blacklist)) {
+ node = list_first_entry(blacklist,
+ struct kprobe_blacklist_node, list);
+ list_del(&node->list);
+ free(node->symbol);
+ free(node);
+ }
+}
+
+static int kprobe_blacklist__load(struct list_head *blacklist)
+{
+ struct kprobe_blacklist_node *node;
+ const char *__debugfs = debugfs_find_mountpoint();
+ char buf[PATH_MAX], *p;
+ FILE *fp;
+ int ret;
+
+ if (__debugfs == NULL)
+ return -ENOTSUP;
+
+ ret = e_snprintf(buf, PATH_MAX, "%s/kprobes/blacklist", __debugfs);
+ if (ret < 0)
+ return ret;
+
+ fp = fopen(buf, "r");
+ if (!fp)
+ return -errno;
+
+ ret = 0;
+ while (fgets(buf, PATH_MAX, fp)) {
+ node = zalloc(sizeof(*node));
+ if (!node) {
+ ret = -ENOMEM;
+ break;
+ }
+ INIT_LIST_HEAD(&node->list);
+ list_add_tail(&node->list, blacklist);
+ if (sscanf(buf, "0x%lx-0x%lx", &node->start, &node->end) != 2) {
+ ret = -EINVAL;
+ break;
+ }
+ p = strchr(buf, '\t');
+ if (p) {
+ p++;
+ if (p[strlen(p) - 1] == '\n')
+ p[strlen(p) - 1] = '\0';
+ } else
+ p = (char *)"unknown";
+ node->symbol = strdup(p);
+ if (!node->symbol) {
+ ret = -ENOMEM;
+ break;
+ }
+ pr_debug2("Blacklist: 0x%lx-0x%lx, %s\n",
+ node->start, node->end, node->symbol);
+ ret++;
+ }
+ if (ret < 0)
+ kprobe_blacklist__delete(blacklist);
+ fclose(fp);
+
+ return ret;
+}
+
+static struct kprobe_blacklist_node *
+kprobe_blacklist__find_by_address(struct list_head *blacklist,
+ unsigned long address)
+{
+ struct kprobe_blacklist_node *node;
+
+ list_for_each_entry(node, blacklist, list) {
+ if (node->start <= address && address <= node->end)
+ return node;
+ }
+
+ return NULL;
+}
+
/* Show an event */
static int show_perf_probe_event(struct perf_probe_event *pev,
const char *module)
@@ -2117,6 +2206,8 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
char buf[64];
const char *event, *group;
struct strlist *namelist;
+ LIST_HEAD(blacklist);
+ struct kprobe_blacklist_node *node;

if (pev->uprobes)
fd = open_uprobe_events(true);
@@ -2134,11 +2225,25 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
pr_debug("Failed to get current event list.\n");
return -EIO;
}
+ /* Get kprobe blacklist if exists */
+ if (!pev->uprobes) {
+ ret = kprobe_blacklist__load(&blacklist);
+ if (ret < 0)
+ pr_debug("No kprobe blacklist support, ignored\n");
+ }

ret = 0;
pr_info("Added new event%s\n", (ntevs > 1) ? "s:" : ":");
for (i = 0; i < ntevs; i++) {
tev = &tevs[i];
+ /* Ensure that the address is NOT blacklisted */
+ node = kprobe_blacklist__find_by_address(&blacklist,
+ tev->point.address);
+ if (node) {
+ pr_warning("Warning: Skipped probing on blacklisted function: %s\n", node->symbol);
+ continue;
+ }
+
if (pev->event)
event = pev->event;
else
@@ -2189,13 +2294,15 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
allow_suffix = true;
}

- if (ret >= 0) {
+ /* Note that it is possible to skip all events because of blacklist */
+ if (ret >= 0 && tev->event) {
/* Show how to use the event. */
pr_info("\nYou can now use it in all perf tools, such as:\n\n");
pr_info("\tperf record -e %s:%s -aR sleep 1\n\n", tev->group,
tev->event);
}

+ kprobe_blacklist__delete(&blacklist);
strlist__delete(namelist);
close(fd);
return ret;