mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-16 18:26:42 +00:00
ftrace: add module globbing
Extend module command for function filter selection with globbing. It uses the same globbing as function filter. sh# echo '*alloc*:mod:*' > set_ftrace_filter Will trace any function with the letters 'alloc' in the name in any module but not in kernel. sh# echo '!*alloc*:mod:ipv6' >> set_ftrace_filter Will prevent from tracing functions with 'alloc' in the name from module ipv6 (do not forget to append to set_ftrace_filter file). sh# echo '*alloc*:mod:!ipv6' > set_ftrace_filter Will trace functions with 'alloc' in the name from kernel and any module except ipv6. sh# echo '*alloc*:mod:!*' > set_ftrace_filter Will trace any function with the letters 'alloc' in the name only from kernel, but not from any module. sh# echo '*:mod:!*' > set_ftrace_filter or sh# echo ':mod:!' > set_ftrace_filter Will trace every function in the kernel, but will not trace functions from any module. sh# echo '*:mod:*' > set_ftrace_filter or sh# echo ':mod:' > set_ftrace_filter As the opposite will trace all functions from all modules, but not from kernel. sh# echo '*:mod:*snd*' > set_ftrace_filter Will trace your sound drivers only (if any). Link: http://lkml.kernel.org/r/1443545176-3215-4-git-send-email-0x7f454c46@gmail.com Signed-off-by: Dmitry Safonov <0x7f454c46@gmail.com> [ Made format changes ] Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
This commit is contained in:
parent
3ba0092971
commit
0b507e1ed1
@ -3485,19 +3485,37 @@ enter_record(struct ftrace_hash *hash, struct dyn_ftrace *rec, int clear_filter)
|
||||
}
|
||||
|
||||
static int
|
||||
ftrace_match_record(struct dyn_ftrace *rec,
|
||||
char *mod, struct ftrace_glob *func_g)
|
||||
ftrace_match_record(struct dyn_ftrace *rec, struct ftrace_glob *func_g,
|
||||
struct ftrace_glob *mod_g, int exclude_mod)
|
||||
{
|
||||
char str[KSYM_SYMBOL_LEN];
|
||||
char *modname;
|
||||
|
||||
kallsyms_lookup(rec->ip, NULL, NULL, &modname, str);
|
||||
|
||||
if (mod) {
|
||||
/* module lookup requires matching the module */
|
||||
if (!modname || strcmp(modname, mod))
|
||||
if (mod_g) {
|
||||
int mod_matches = (modname) ? ftrace_match(modname, mod_g) : 0;
|
||||
|
||||
/* blank module name to match all modules */
|
||||
if (!mod_g->len) {
|
||||
/* blank module globbing: modname xor exclude_mod */
|
||||
if ((!exclude_mod) != (!modname))
|
||||
goto func_match;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* not matching the module */
|
||||
if (!modname || !mod_matches) {
|
||||
if (exclude_mod)
|
||||
goto func_match;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mod_matches && exclude_mod)
|
||||
return 0;
|
||||
|
||||
func_match:
|
||||
/* blank search means to match all funcs in the mod */
|
||||
if (!func_g->len)
|
||||
return 1;
|
||||
@ -3512,23 +3530,32 @@ match_records(struct ftrace_hash *hash, char *func, int len, char *mod)
|
||||
struct ftrace_page *pg;
|
||||
struct dyn_ftrace *rec;
|
||||
struct ftrace_glob func_g = { .type = MATCH_FULL };
|
||||
struct ftrace_glob mod_g = { .type = MATCH_FULL };
|
||||
struct ftrace_glob *mod_match = (mod) ? &mod_g : NULL;
|
||||
int exclude_mod = 0;
|
||||
int found = 0;
|
||||
int ret;
|
||||
int clear_filter;
|
||||
|
||||
if (len) {
|
||||
if (func) {
|
||||
func_g.type = filter_parse_regex(func, len, &func_g.search,
|
||||
&clear_filter);
|
||||
func_g.len = strlen(func_g.search);
|
||||
}
|
||||
|
||||
if (mod) {
|
||||
mod_g.type = filter_parse_regex(mod, strlen(mod),
|
||||
&mod_g.search, &exclude_mod);
|
||||
mod_g.len = strlen(mod_g.search);
|
||||
}
|
||||
|
||||
mutex_lock(&ftrace_lock);
|
||||
|
||||
if (unlikely(ftrace_disabled))
|
||||
goto out_unlock;
|
||||
|
||||
do_for_each_ftrace_rec(pg, rec) {
|
||||
if (ftrace_match_record(rec, mod, &func_g)) {
|
||||
if (ftrace_match_record(rec, &func_g, mod_match, exclude_mod)) {
|
||||
ret = enter_record(hash, rec, clear_filter);
|
||||
if (ret < 0) {
|
||||
found = ret;
|
||||
@ -3568,17 +3595,11 @@ ftrace_mod_callback(struct ftrace_hash *hash,
|
||||
* you can tell which command was used by the cmd
|
||||
* parameter.
|
||||
*/
|
||||
|
||||
/* we must have a module name */
|
||||
if (!module || !strlen(module))
|
||||
return -EINVAL;
|
||||
|
||||
ret = match_records(hash, func, strlen(func), module);
|
||||
if (!ret)
|
||||
return -EINVAL;
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -3729,7 +3750,7 @@ register_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
|
||||
|
||||
do_for_each_ftrace_rec(pg, rec) {
|
||||
|
||||
if (!ftrace_match_record(rec, NULL, &func_g))
|
||||
if (!ftrace_match_record(rec, &func_g, NULL, 0))
|
||||
continue;
|
||||
|
||||
entry = kmalloc(sizeof(*entry), GFP_KERNEL);
|
||||
@ -4621,7 +4642,7 @@ ftrace_set_func(unsigned long *array, int *idx, int size, char *buffer)
|
||||
|
||||
do_for_each_ftrace_rec(pg, rec) {
|
||||
|
||||
if (ftrace_match_record(rec, NULL, &func_g)) {
|
||||
if (ftrace_match_record(rec, &func_g, NULL, 0)) {
|
||||
/* if it is in the array */
|
||||
exists = false;
|
||||
for (i = 0; i < *idx; i++) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user