Merge branch 'perf-probes-for-linus-2' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'perf-probes-for-linus-2' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: x86: Issue at least one memory barrier in stop_machine_text_poke() perf probe: Correct probe syntax on command line help perf probe: Add lazy line matching support perf probe: Show more lines after last line perf probe: Check function address range strictly in line finder perf probe: Use libdw callback routines perf probe: Use elfutils-libdw for analyzing debuginfo perf probe: Rename probe finder functions perf probe: Fix bugs in line range finder perf probe: Update perf probe document perf probe: Do not show --line option without dwarf support kprobes: Add documents of jump optimization kprobes/x86: Support kprobes jump optimization on x86 x86: Add text_poke_smp for SMP cross modifying code kprobes/x86: Cleanup save/restore registers kprobes/x86: Boost probes when reentering kprobes: Jump optimization sysctl interface kprobes: Introduce kprobes jump optimization kprobes: Introduce generic insn_slot framework kprobes/x86: Cleanup RELATIVEJUMP_INSTRUCTION to RELATIVEJUMP_OPCODE
This commit is contained in:
@@ -41,7 +41,8 @@ OPTIONS
|
||||
|
||||
-d::
|
||||
--del=::
|
||||
Delete a probe event.
|
||||
Delete probe events. This accepts glob wildcards('*', '?') and character
|
||||
classes(e.g. [a-z], [!A-Z]).
|
||||
|
||||
-l::
|
||||
--list::
|
||||
@@ -50,17 +51,29 @@ OPTIONS
|
||||
-L::
|
||||
--line=::
|
||||
Show source code lines which can be probed. This needs an argument
|
||||
which specifies a range of the source code.
|
||||
which specifies a range of the source code. (see LINE SYNTAX for detail)
|
||||
|
||||
-f::
|
||||
--force::
|
||||
Forcibly add events with existing name.
|
||||
|
||||
PROBE SYNTAX
|
||||
------------
|
||||
Probe points are defined by following syntax.
|
||||
|
||||
"[EVENT=]FUNC[+OFFS|:RLN|%return][@SRC]|SRC:ALN [ARG ...]"
|
||||
1) Define event based on function name
|
||||
[EVENT=]FUNC[@SRC][:RLN|+OFFS|%return|;PTN] [ARG ...]
|
||||
|
||||
2) Define event based on source file with line number
|
||||
[EVENT=]SRC:ALN [ARG ...]
|
||||
|
||||
3) Define event based on source file with lazy pattern
|
||||
[EVENT=]SRC;PTN [ARG ...]
|
||||
|
||||
|
||||
'EVENT' specifies the name of new event, if omitted, it will be set the name of the probed function. Currently, event group name is set as 'probe'.
|
||||
'FUNC' specifies a probed function name, and it may have one of the following options; '+OFFS' is the offset from function entry address in bytes, 'RLN' is the relative-line number from function entry line, and '%return' means that it probes function return. In addition, 'SRC' specifies a source file which has that function.
|
||||
It is also possible to specify a probe point by the source line number by using 'SRC:ALN' syntax, where 'SRC' is the source file path and 'ALN' is the line number.
|
||||
'FUNC' specifies a probed function name, and it may have one of the following options; '+OFFS' is the offset from function entry address in bytes, ':RLN' is the relative-line number from function entry line, and '%return' means that it probes function return. And ';PTN' means lazy matching pattern (see LAZY MATCHING). Note that ';PTN' must be the end of the probe point definition. In addition, '@SRC' specifies a source file which has that function.
|
||||
It is also possible to specify a probe point by the source line number or lazy matching by using 'SRC:ALN' or 'SRC;PTN' syntax, where 'SRC' is the source file path, ':ALN' is the line number and ';PTN' is the lazy matching pattern.
|
||||
'ARG' specifies the arguments of this probe point. You can use the name of local variable, or kprobe-tracer argument format (e.g. $retval, %ax, etc).
|
||||
|
||||
LINE SYNTAX
|
||||
@@ -76,6 +89,41 @@ and 'ALN2' is end line number in the file. It is also possible to specify how
|
||||
many lines to show by using 'NUM'.
|
||||
So, "source.c:100-120" shows lines between 100th to l20th in source.c file. And "func:10+20" shows 20 lines from 10th line of func function.
|
||||
|
||||
LAZY MATCHING
|
||||
-------------
|
||||
The lazy line matching is similar to glob matching but ignoring spaces in both of pattern and target. So this accepts wildcards('*', '?') and character classes(e.g. [a-z], [!A-Z]).
|
||||
|
||||
e.g.
|
||||
'a=*' can matches 'a=b', 'a = b', 'a == b' and so on.
|
||||
|
||||
This provides some sort of flexibility and robustness to probe point definitions against minor code changes. For example, actual 10th line of schedule() can be moved easily by modifying schedule(), but the same line matching 'rq=cpu_rq*' may still exist in the function.)
|
||||
|
||||
|
||||
EXAMPLES
|
||||
--------
|
||||
Display which lines in schedule() can be probed:
|
||||
|
||||
./perf probe --line schedule
|
||||
|
||||
Add a probe on schedule() function 12th line with recording cpu local variable:
|
||||
|
||||
./perf probe schedule:12 cpu
|
||||
or
|
||||
./perf probe --add='schedule:12 cpu'
|
||||
|
||||
this will add one or more probes which has the name start with "schedule".
|
||||
|
||||
Add probes on lines in schedule() function which calls update_rq_clock().
|
||||
|
||||
./perf probe 'schedule;update_rq_clock*'
|
||||
or
|
||||
./perf probe --add='schedule;update_rq_clock*'
|
||||
|
||||
Delete all probes on schedule().
|
||||
|
||||
./perf probe --del='schedule*'
|
||||
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
linkperf:perf-trace[1], linkperf:perf-record[1]
|
||||
|
||||
@@ -500,12 +500,12 @@ else
|
||||
msg := $(error No libelf.h/libelf found, please install libelf-dev/elfutils-libelf-devel and glibc-dev[el]);
|
||||
endif
|
||||
|
||||
ifneq ($(shell sh -c "(echo '\#ifndef _MIPS_SZLONG'; echo '\#define _MIPS_SZLONG 0'; echo '\#endif'; echo '\#include <dwarf.h>'; echo '\#include <libdwarf.h>'; echo 'int main(void) { Dwarf_Debug dbg; Dwarf_Error err; Dwarf_Ranges *rng; dwarf_init(0, DW_DLC_READ, 0, 0, &dbg, &err); dwarf_get_ranges(dbg, 0, &rng, 0, 0, &err); return (long)dbg; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/libdwarf -ldwarf -lelf -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y)
|
||||
msg := $(warning No libdwarf.h found or old libdwarf.h found, disables dwarf support. Please install libdwarf-dev/libdwarf-devel >= 20081231);
|
||||
BASIC_CFLAGS += -DNO_LIBDWARF
|
||||
ifneq ($(shell sh -c "(echo '\#include <dwarf.h>'; echo '\#include <libdw.h>'; echo 'int main(void) { Dwarf *dbg; dbg = dwarf_begin(0, DWARF_C_READ); return (long)dbg; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/elfutils -ldw -lelf -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y)
|
||||
msg := $(warning No libdw.h found or old libdw.h found, disables dwarf support. Please install elfutils-devel/elfutils-dev);
|
||||
BASIC_CFLAGS += -DNO_DWARF_SUPPORT
|
||||
else
|
||||
BASIC_CFLAGS += -I/usr/include/libdwarf
|
||||
EXTLIBS += -lelf -ldwarf
|
||||
BASIC_CFLAGS += -I/usr/include/elfutils
|
||||
EXTLIBS += -lelf -ldw
|
||||
LIB_OBJS += util/probe-finder.o
|
||||
endif
|
||||
|
||||
|
||||
@@ -128,7 +128,7 @@ static void evaluate_probe_point(struct probe_point *pp)
|
||||
pp->function);
|
||||
}
|
||||
|
||||
#ifndef NO_LIBDWARF
|
||||
#ifndef NO_DWARF_SUPPORT
|
||||
static int open_vmlinux(void)
|
||||
{
|
||||
if (map__load(session.kmaps[MAP__FUNCTION], NULL) < 0) {
|
||||
@@ -156,14 +156,16 @@ static const char * const probe_usage[] = {
|
||||
"perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]",
|
||||
"perf probe [<options>] --del '[GROUP:]EVENT' ...",
|
||||
"perf probe --list",
|
||||
#ifndef NO_DWARF_SUPPORT
|
||||
"perf probe --line 'LINEDESC'",
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct option options[] = {
|
||||
OPT_BOOLEAN('v', "verbose", &verbose,
|
||||
"be more verbose (show parsed arguments, etc)"),
|
||||
#ifndef NO_LIBDWARF
|
||||
#ifndef NO_DWARF_SUPPORT
|
||||
OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
|
||||
"file", "vmlinux pathname"),
|
||||
#endif
|
||||
@@ -172,30 +174,32 @@ static const struct option options[] = {
|
||||
OPT_CALLBACK('d', "del", NULL, "[GROUP:]EVENT", "delete a probe event.",
|
||||
opt_del_probe_event),
|
||||
OPT_CALLBACK('a', "add", NULL,
|
||||
#ifdef NO_LIBDWARF
|
||||
"[EVENT=]FUNC[+OFFS|%return] [ARG ...]",
|
||||
#ifdef NO_DWARF_SUPPORT
|
||||
"[EVENT=]FUNC[+OFF|%return] [ARG ...]",
|
||||
#else
|
||||
"[EVENT=]FUNC[+OFFS|%return|:RLN][@SRC]|SRC:ALN [ARG ...]",
|
||||
"[EVENT=]FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT"
|
||||
" [ARG ...]",
|
||||
#endif
|
||||
"probe point definition, where\n"
|
||||
"\t\tGROUP:\tGroup name (optional)\n"
|
||||
"\t\tEVENT:\tEvent name\n"
|
||||
"\t\tFUNC:\tFunction name\n"
|
||||
"\t\tOFFS:\tOffset from function entry (in byte)\n"
|
||||
"\t\tOFF:\tOffset from function entry (in byte)\n"
|
||||
"\t\t%return:\tPut the probe at function return\n"
|
||||
#ifdef NO_LIBDWARF
|
||||
#ifdef NO_DWARF_SUPPORT
|
||||
"\t\tARG:\tProbe argument (only \n"
|
||||
#else
|
||||
"\t\tSRC:\tSource code path\n"
|
||||
"\t\tRLN:\tRelative line number from function entry.\n"
|
||||
"\t\tALN:\tAbsolute line number in file.\n"
|
||||
"\t\tRL:\tRelative line number from function entry.\n"
|
||||
"\t\tAL:\tAbsolute line number in file.\n"
|
||||
"\t\tPT:\tLazy expression of line code.\n"
|
||||
"\t\tARG:\tProbe argument (local variable name or\n"
|
||||
#endif
|
||||
"\t\t\tkprobe-tracer argument format.)\n",
|
||||
opt_add_probe_event),
|
||||
OPT_BOOLEAN('f', "force", &session.force_add, "forcibly add events"
|
||||
" with existing name"),
|
||||
#ifndef NO_LIBDWARF
|
||||
#ifndef NO_DWARF_SUPPORT
|
||||
OPT_CALLBACK('L', "line", NULL,
|
||||
"FUNC[:RLN[+NUM|:RLN2]]|SRC:ALN[+NUM|:ALN2]",
|
||||
"Show source code lines.", opt_show_lines),
|
||||
@@ -223,7 +227,7 @@ static void init_vmlinux(void)
|
||||
int cmd_probe(int argc, const char **argv, const char *prefix __used)
|
||||
{
|
||||
int i, ret;
|
||||
#ifndef NO_LIBDWARF
|
||||
#ifndef NO_DWARF_SUPPORT
|
||||
int fd;
|
||||
#endif
|
||||
struct probe_point *pp;
|
||||
@@ -259,7 +263,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef NO_LIBDWARF
|
||||
#ifndef NO_DWARF_SUPPORT
|
||||
if (session.show_lines) {
|
||||
if (session.nr_probe != 0 || session.dellist) {
|
||||
pr_warning(" Error: Don't use --line with"
|
||||
@@ -290,9 +294,9 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
|
||||
init_vmlinux();
|
||||
|
||||
if (session.need_dwarf)
|
||||
#ifdef NO_LIBDWARF
|
||||
#ifdef NO_DWARF_SUPPORT
|
||||
die("Debuginfo-analysis is not supported");
|
||||
#else /* !NO_LIBDWARF */
|
||||
#else /* !NO_DWARF_SUPPORT */
|
||||
pr_debug("Some probes require debuginfo.\n");
|
||||
|
||||
fd = open_vmlinux();
|
||||
@@ -312,7 +316,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
|
||||
continue;
|
||||
|
||||
lseek(fd, SEEK_SET, 0);
|
||||
ret = find_probepoint(fd, pp);
|
||||
ret = find_probe_point(fd, pp);
|
||||
if (ret > 0)
|
||||
continue;
|
||||
if (ret == 0) { /* No error but failed to find probe point. */
|
||||
@@ -333,7 +337,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
|
||||
close(fd);
|
||||
|
||||
end_dwarf:
|
||||
#endif /* !NO_LIBDWARF */
|
||||
#endif /* !NO_DWARF_SUPPORT */
|
||||
|
||||
/* Synthesize probes without dwarf */
|
||||
for (i = 0; i < session.nr_probe; i++) {
|
||||
|
||||
@@ -119,14 +119,14 @@ static void parse_perf_probe_probepoint(char *arg, struct probe_point *pp)
|
||||
char c, nc = 0;
|
||||
/*
|
||||
* <Syntax>
|
||||
* perf probe [EVENT=]SRC:LN
|
||||
* perf probe [EVENT=]FUNC[+OFFS|%return][@SRC]
|
||||
* perf probe [EVENT=]SRC[:LN|;PTN]
|
||||
* perf probe [EVENT=]FUNC[@SRC][+OFFS|%return|:LN|;PAT]
|
||||
*
|
||||
* TODO:Group name support
|
||||
*/
|
||||
|
||||
ptr = strchr(arg, '=');
|
||||
if (ptr) { /* Event name */
|
||||
ptr = strpbrk(arg, ";=@+%");
|
||||
if (ptr && *ptr == '=') { /* Event name */
|
||||
*ptr = '\0';
|
||||
tmp = ptr + 1;
|
||||
ptr = strchr(arg, ':');
|
||||
@@ -139,7 +139,7 @@ static void parse_perf_probe_probepoint(char *arg, struct probe_point *pp)
|
||||
arg = tmp;
|
||||
}
|
||||
|
||||
ptr = strpbrk(arg, ":+@%");
|
||||
ptr = strpbrk(arg, ";:+@%");
|
||||
if (ptr) {
|
||||
nc = *ptr;
|
||||
*ptr++ = '\0';
|
||||
@@ -156,7 +156,11 @@ static void parse_perf_probe_probepoint(char *arg, struct probe_point *pp)
|
||||
while (ptr) {
|
||||
arg = ptr;
|
||||
c = nc;
|
||||
ptr = strpbrk(arg, ":+@%");
|
||||
if (c == ';') { /* Lazy pattern must be the last part */
|
||||
pp->lazy_line = strdup(arg);
|
||||
break;
|
||||
}
|
||||
ptr = strpbrk(arg, ";:+@%");
|
||||
if (ptr) {
|
||||
nc = *ptr;
|
||||
*ptr++ = '\0';
|
||||
@@ -165,13 +169,13 @@ static void parse_perf_probe_probepoint(char *arg, struct probe_point *pp)
|
||||
case ':': /* Line number */
|
||||
pp->line = strtoul(arg, &tmp, 0);
|
||||
if (*tmp != '\0')
|
||||
semantic_error("There is non-digit charactor"
|
||||
" in line number.");
|
||||
semantic_error("There is non-digit char"
|
||||
" in line number.");
|
||||
break;
|
||||
case '+': /* Byte offset from a symbol */
|
||||
pp->offset = strtoul(arg, &tmp, 0);
|
||||
if (*tmp != '\0')
|
||||
semantic_error("There is non-digit charactor"
|
||||
semantic_error("There is non-digit character"
|
||||
" in offset.");
|
||||
break;
|
||||
case '@': /* File name */
|
||||
@@ -179,9 +183,6 @@ static void parse_perf_probe_probepoint(char *arg, struct probe_point *pp)
|
||||
semantic_error("SRC@SRC is not allowed.");
|
||||
pp->file = strdup(arg);
|
||||
DIE_IF(pp->file == NULL);
|
||||
if (ptr)
|
||||
semantic_error("@SRC must be the last "
|
||||
"option.");
|
||||
break;
|
||||
case '%': /* Probe places */
|
||||
if (strcmp(arg, "return") == 0) {
|
||||
@@ -196,11 +197,18 @@ static void parse_perf_probe_probepoint(char *arg, struct probe_point *pp)
|
||||
}
|
||||
|
||||
/* Exclusion check */
|
||||
if (pp->lazy_line && pp->line)
|
||||
semantic_error("Lazy pattern can't be used with line number.");
|
||||
|
||||
if (pp->lazy_line && pp->offset)
|
||||
semantic_error("Lazy pattern can't be used with offset.");
|
||||
|
||||
if (pp->line && pp->offset)
|
||||
semantic_error("Offset can't be used with line number.");
|
||||
|
||||
if (!pp->line && pp->file && !pp->function)
|
||||
semantic_error("File always requires line number.");
|
||||
if (!pp->line && !pp->lazy_line && pp->file && !pp->function)
|
||||
semantic_error("File always requires line number or "
|
||||
"lazy pattern.");
|
||||
|
||||
if (pp->offset && !pp->function)
|
||||
semantic_error("Offset requires an entry function.");
|
||||
@@ -208,11 +216,13 @@ static void parse_perf_probe_probepoint(char *arg, struct probe_point *pp)
|
||||
if (pp->retprobe && !pp->function)
|
||||
semantic_error("Return probe requires an entry function.");
|
||||
|
||||
if ((pp->offset || pp->line) && pp->retprobe)
|
||||
semantic_error("Offset/Line can't be used with return probe.");
|
||||
if ((pp->offset || pp->line || pp->lazy_line) && pp->retprobe)
|
||||
semantic_error("Offset/Line/Lazy pattern can't be used with "
|
||||
"return probe.");
|
||||
|
||||
pr_debug("symbol:%s file:%s line:%d offset:%d, return:%d\n",
|
||||
pp->function, pp->file, pp->line, pp->offset, pp->retprobe);
|
||||
pr_debug("symbol:%s file:%s line:%d offset:%d return:%d lazy:%s\n",
|
||||
pp->function, pp->file, pp->line, pp->offset, pp->retprobe,
|
||||
pp->lazy_line);
|
||||
}
|
||||
|
||||
/* Parse perf-probe event definition */
|
||||
@@ -458,6 +468,8 @@ static void clear_probe_point(struct probe_point *pp)
|
||||
free(pp->function);
|
||||
if (pp->file)
|
||||
free(pp->file);
|
||||
if (pp->lazy_line)
|
||||
free(pp->lazy_line);
|
||||
for (i = 0; i < pp->nr_args; i++)
|
||||
free(pp->args[i]);
|
||||
if (pp->args)
|
||||
@@ -719,6 +731,7 @@ void del_trace_kprobe_events(struct strlist *dellist)
|
||||
}
|
||||
|
||||
#define LINEBUF_SIZE 256
|
||||
#define NR_ADDITIONAL_LINES 2
|
||||
|
||||
static void show_one_line(FILE *fp, unsigned int l, bool skip, bool show_num)
|
||||
{
|
||||
@@ -779,5 +792,11 @@ void show_line_range(struct line_range *lr)
|
||||
show_one_line(fp, (l++) - lr->offset, false, false);
|
||||
show_one_line(fp, (l++) - lr->offset, false, true);
|
||||
}
|
||||
|
||||
if (lr->end == INT_MAX)
|
||||
lr->end = l + NR_ADDITIONAL_LINES;
|
||||
while (l < lr->end && !feof(fp))
|
||||
show_one_line(fp, (l++) - lr->offset, false, false);
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,7 @@
|
||||
#ifndef _PROBE_FINDER_H
|
||||
#define _PROBE_FINDER_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "util.h"
|
||||
|
||||
#define MAX_PATH_LEN 256
|
||||
@@ -20,6 +21,7 @@ struct probe_point {
|
||||
/* Inputs */
|
||||
char *file; /* File name */
|
||||
int line; /* Line number */
|
||||
char *lazy_line; /* Lazy line pattern */
|
||||
|
||||
char *function; /* Function name */
|
||||
int offset; /* Offset bytes */
|
||||
@@ -46,53 +48,46 @@ struct line_range {
|
||||
char *function; /* Function name */
|
||||
unsigned int start; /* Start line number */
|
||||
unsigned int end; /* End line number */
|
||||
unsigned int offset; /* Start line offset */
|
||||
int offset; /* Start line offset */
|
||||
char *path; /* Real path name */
|
||||
struct list_head line_list; /* Visible lines */
|
||||
};
|
||||
|
||||
#ifndef NO_LIBDWARF
|
||||
extern int find_probepoint(int fd, struct probe_point *pp);
|
||||
#ifndef NO_DWARF_SUPPORT
|
||||
extern int find_probe_point(int fd, struct probe_point *pp);
|
||||
extern int find_line_range(int fd, struct line_range *lr);
|
||||
|
||||
/* Workaround for undefined _MIPS_SZLONG bug in libdwarf.h: */
|
||||
#ifndef _MIPS_SZLONG
|
||||
# define _MIPS_SZLONG 0
|
||||
#endif
|
||||
|
||||
#include <dwarf.h>
|
||||
#include <libdwarf.h>
|
||||
#include <libdw.h>
|
||||
|
||||
struct probe_finder {
|
||||
struct probe_point *pp; /* Target probe point */
|
||||
struct probe_point *pp; /* Target probe point */
|
||||
|
||||
/* For function searching */
|
||||
Dwarf_Addr addr; /* Address */
|
||||
Dwarf_Unsigned fno; /* File number */
|
||||
Dwarf_Unsigned lno; /* Line number */
|
||||
Dwarf_Off inl_offs; /* Inline offset */
|
||||
Dwarf_Die cu_die; /* Current CU */
|
||||
Dwarf_Addr addr; /* Address */
|
||||
const char *fname; /* File name */
|
||||
int lno; /* Line number */
|
||||
Dwarf_Die cu_die; /* Current CU */
|
||||
|
||||
/* For variable searching */
|
||||
Dwarf_Addr cu_base; /* Current CU base address */
|
||||
Dwarf_Locdesc fbloc; /* Location of Current Frame Base */
|
||||
const char *var; /* Current variable name */
|
||||
char *buf; /* Current output buffer */
|
||||
int len; /* Length of output buffer */
|
||||
Dwarf_Op *fb_ops; /* Frame base attribute */
|
||||
Dwarf_Addr cu_base; /* Current CU base address */
|
||||
const char *var; /* Current variable name */
|
||||
char *buf; /* Current output buffer */
|
||||
int len; /* Length of output buffer */
|
||||
struct list_head lcache; /* Line cache for lazy match */
|
||||
};
|
||||
|
||||
struct line_finder {
|
||||
struct line_range *lr; /* Target line range */
|
||||
struct line_range *lr; /* Target line range */
|
||||
|
||||
Dwarf_Unsigned fno; /* File number */
|
||||
Dwarf_Unsigned lno_s; /* Start line number */
|
||||
Dwarf_Unsigned lno_e; /* End line number */
|
||||
Dwarf_Addr addr_s; /* Start address */
|
||||
Dwarf_Addr addr_e; /* End address */
|
||||
Dwarf_Die cu_die; /* Current CU */
|
||||
const char *fname; /* File name */
|
||||
int lno_s; /* Start line number */
|
||||
int lno_e; /* End line number */
|
||||
Dwarf_Die cu_die; /* Current CU */
|
||||
int found;
|
||||
};
|
||||
|
||||
#endif /* NO_LIBDWARF */
|
||||
#endif /* NO_DWARF_SUPPORT */
|
||||
|
||||
#endif /*_PROBE_FINDER_H */
|
||||
|
||||
@@ -265,21 +265,21 @@ error:
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* strglobmatch - glob expression pattern matching
|
||||
* @str: the target string to match
|
||||
* @pat: the pattern string to match
|
||||
*
|
||||
* This returns true if the @str matches @pat. @pat can includes wildcards
|
||||
* ('*','?') and character classes ([CHARS], complementation and ranges are
|
||||
* also supported). Also, this supports escape character ('\') to use special
|
||||
* characters as normal character.
|
||||
*
|
||||
* Note: if @pat syntax is broken, this always returns false.
|
||||
*/
|
||||
bool strglobmatch(const char *str, const char *pat)
|
||||
/* Glob/lazy pattern matching */
|
||||
static bool __match_glob(const char *str, const char *pat, bool ignore_space)
|
||||
{
|
||||
while (*str && *pat && *pat != '*') {
|
||||
if (ignore_space) {
|
||||
/* Ignore spaces for lazy matching */
|
||||
if (isspace(*str)) {
|
||||
str++;
|
||||
continue;
|
||||
}
|
||||
if (isspace(*pat)) {
|
||||
pat++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (*pat == '?') { /* Matches any single character */
|
||||
str++;
|
||||
pat++;
|
||||
@@ -308,3 +308,32 @@ bool strglobmatch(const char *str, const char *pat)
|
||||
return !*str && !*pat;
|
||||
}
|
||||
|
||||
/**
|
||||
* strglobmatch - glob expression pattern matching
|
||||
* @str: the target string to match
|
||||
* @pat: the pattern string to match
|
||||
*
|
||||
* This returns true if the @str matches @pat. @pat can includes wildcards
|
||||
* ('*','?') and character classes ([CHARS], complementation and ranges are
|
||||
* also supported). Also, this supports escape character ('\') to use special
|
||||
* characters as normal character.
|
||||
*
|
||||
* Note: if @pat syntax is broken, this always returns false.
|
||||
*/
|
||||
bool strglobmatch(const char *str, const char *pat)
|
||||
{
|
||||
return __match_glob(str, pat, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* strlazymatch - matching pattern strings lazily with glob pattern
|
||||
* @str: the target string to match
|
||||
* @pat: the pattern string to match
|
||||
*
|
||||
* This is similar to strglobmatch, except this ignores spaces in
|
||||
* the target string.
|
||||
*/
|
||||
bool strlazymatch(const char *str, const char *pat)
|
||||
{
|
||||
return __match_glob(str, pat, true);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ s64 perf_atoll(const char *str);
|
||||
char **argv_split(const char *str, int *argcp);
|
||||
void argv_free(char **argv);
|
||||
bool strglobmatch(const char *str, const char *pat);
|
||||
bool strlazymatch(const char *str, const char *pat);
|
||||
|
||||
#define _STR(x) #x
|
||||
#define STR(x) _STR(x)
|
||||
|
||||
Reference in New Issue
Block a user