aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/perf/Documentation/perf-record.txt55
-rw-r--r--tools/perf/builtin-record.c14
-rw-r--r--tools/perf/util/auxtrace.c737
-rw-r--r--tools/perf/util/auxtrace.h54
4 files changed, 857 insertions, 3 deletions
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index babbb63e6d9d..92335193dc33 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -89,9 +89,62 @@ OPTIONS
89 89
90--filter=<filter>:: 90--filter=<filter>::
91 Event filter. This option should follow a event selector (-e) which 91 Event filter. This option should follow a event selector (-e) which
92 selects tracepoint event(s). Multiple '--filter' options are combined 92 selects either tracepoint event(s) or a hardware trace PMU
93 (e.g. Intel PT or CoreSight).
94
95 - tracepoint filters
96
97 In the case of tracepoints, multiple '--filter' options are combined
93 using '&&'. 98 using '&&'.
94 99
100 - address filters
101
102 A hardware trace PMU advertises its ability to accept a number of
103 address filters by specifying a non-zero value in
104 /sys/bus/event_source/devices/<pmu>/nr_addr_filters.
105
106 Address filters have the format:
107
108 filter|start|stop|tracestop <start> [/ <size>] [@<file name>]
109
110 Where:
111 - 'filter': defines a region that will be traced.
112 - 'start': defines an address at which tracing will begin.
113 - 'stop': defines an address at which tracing will stop.
114 - 'tracestop': defines a region in which tracing will stop.
115
116 <file name> is the name of the object file, <start> is the offset to the
117 code to trace in that file, and <size> is the size of the region to
118 trace. 'start' and 'stop' filters need not specify a <size>.
119
120 If no object file is specified then the kernel is assumed, in which case
121 the start address must be a current kernel memory address.
122
123 <start> can also be specified by providing the name of a symbol. If the
124 symbol name is not unique, it can be disambiguated by inserting #n where
125 'n' selects the n'th symbol in address order. Alternately #0, #g or #G
126 select only a global symbol. <size> can also be specified by providing
127 the name of a symbol, in which case the size is calculated to the end
128 of that symbol. For 'filter' and 'tracestop' filters, if <size> is
129 omitted and <start> is a symbol, then the size is calculated to the end
130 of that symbol.
131
132 If <size> is omitted and <start> is '*', then the start and size will
133 be calculated from the first and last symbols, i.e. to trace the whole
134 file.
135
136 If symbol names (or '*') are provided, they must be surrounded by white
137 space.
138
139 The filter passed to the kernel is not necessarily the same as entered.
140 To see the filter that is passed, use the -v option.
141
142 The kernel may not be able to configure a trace region if it is not
143 within a single mapping. MMAP events (or /proc/<pid>/maps) can be
144 examined to determine if that is a possibility.
145
146 Multiple filters can be separated with space or comma.
147
95--exclude-perf:: 148--exclude-perf::
96 Don't record events issued by perf itself. This option should follow 149 Don't record events issued by perf itself. This option should follow
97 a event selector (-e) which selects tracepoint event(s). It adds a 150 a event selector (-e) which selects tracepoint event(s). It adds a
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 962adcfc43a5..67d2a9003294 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -1581,6 +1581,18 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
1581 if (err) 1581 if (err)
1582 goto out; 1582 goto out;
1583 1583
1584 /*
1585 * Allow aliases to facilitate the lookup of symbols for address
1586 * filters. Refer to auxtrace_parse_filters().
1587 */
1588 symbol_conf.allow_aliases = true;
1589
1590 symbol__init(NULL);
1591
1592 err = auxtrace_parse_filters(rec->evlist);
1593 if (err)
1594 goto out;
1595
1584 if (dry_run) 1596 if (dry_run)
1585 goto out; 1597 goto out;
1586 1598
@@ -1594,8 +1606,6 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
1594 1606
1595 err = -ENOMEM; 1607 err = -ENOMEM;
1596 1608
1597 symbol__init(NULL);
1598
1599 if (symbol_conf.kptr_restrict) 1609 if (symbol_conf.kptr_restrict)
1600 pr_warning( 1610 pr_warning(
1601"WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n" 1611"WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
index c0aba8e839aa..c5a6e0b12452 100644
--- a/tools/perf/util/auxtrace.c
+++ b/tools/perf/util/auxtrace.c
@@ -16,6 +16,10 @@
16#include <sys/types.h> 16#include <sys/types.h>
17#include <sys/mman.h> 17#include <sys/mman.h>
18#include <stdbool.h> 18#include <stdbool.h>
19#include <ctype.h>
20#include <string.h>
21#include <limits.h>
22#include <errno.h>
19 23
20#include <linux/kernel.h> 24#include <linux/kernel.h>
21#include <linux/perf_event.h> 25#include <linux/perf_event.h>
@@ -35,9 +39,14 @@
35#include "../perf.h" 39#include "../perf.h"
36#include "util.h" 40#include "util.h"
37#include "evlist.h" 41#include "evlist.h"
42#include "dso.h"
43#include "map.h"
44#include "pmu.h"
45#include "evsel.h"
38#include "cpumap.h" 46#include "cpumap.h"
39#include "thread_map.h" 47#include "thread_map.h"
40#include "asm/bug.h" 48#include "asm/bug.h"
49#include "symbol/kallsyms.h"
41#include "auxtrace.h" 50#include "auxtrace.h"
42 51
43#include <linux/hash.h> 52#include <linux/hash.h>
@@ -1399,3 +1408,731 @@ void *auxtrace_cache__lookup(struct auxtrace_cache *c, u32 key)
1399 1408
1400 return NULL; 1409 return NULL;
1401} 1410}
1411
1412static void addr_filter__free_str(struct addr_filter *filt)
1413{
1414 free(filt->str);
1415 filt->action = NULL;
1416 filt->sym_from = NULL;
1417 filt->sym_to = NULL;
1418 filt->filename = NULL;
1419 filt->str = NULL;
1420}
1421
1422static struct addr_filter *addr_filter__new(void)
1423{
1424 struct addr_filter *filt = zalloc(sizeof(*filt));
1425
1426 if (filt)
1427 INIT_LIST_HEAD(&filt->list);
1428
1429 return filt;
1430}
1431
1432static void addr_filter__free(struct addr_filter *filt)
1433{
1434 if (filt)
1435 addr_filter__free_str(filt);
1436 free(filt);
1437}
1438
1439static void addr_filters__add(struct addr_filters *filts,
1440 struct addr_filter *filt)
1441{
1442 list_add_tail(&filt->list, &filts->head);
1443 filts->cnt += 1;
1444}
1445
1446static void addr_filters__del(struct addr_filters *filts,
1447 struct addr_filter *filt)
1448{
1449 list_del_init(&filt->list);
1450 filts->cnt -= 1;
1451}
1452
1453void addr_filters__init(struct addr_filters *filts)
1454{
1455 INIT_LIST_HEAD(&filts->head);
1456 filts->cnt = 0;
1457}
1458
1459void addr_filters__exit(struct addr_filters *filts)
1460{
1461 struct addr_filter *filt, *n;
1462
1463 list_for_each_entry_safe(filt, n, &filts->head, list) {
1464 addr_filters__del(filts, filt);
1465 addr_filter__free(filt);
1466 }
1467}
1468
1469static int parse_num_or_str(char **inp, u64 *num, const char **str,
1470 const char *str_delim)
1471{
1472 *inp += strspn(*inp, " ");
1473
1474 if (isdigit(**inp)) {
1475 char *endptr;
1476
1477 if (!num)
1478 return -EINVAL;
1479 errno = 0;
1480 *num = strtoull(*inp, &endptr, 0);
1481 if (errno)
1482 return -errno;
1483 if (endptr == *inp)
1484 return -EINVAL;
1485 *inp = endptr;
1486 } else {
1487 size_t n;
1488
1489 if (!str)
1490 return -EINVAL;
1491 *inp += strspn(*inp, " ");
1492 *str = *inp;
1493 n = strcspn(*inp, str_delim);
1494 if (!n)
1495 return -EINVAL;
1496 *inp += n;
1497 if (**inp) {
1498 **inp = '\0';
1499 *inp += 1;
1500 }
1501 }
1502 return 0;
1503}
1504
1505static int parse_action(struct addr_filter *filt)
1506{
1507 if (!strcmp(filt->action, "filter")) {
1508 filt->start = true;
1509 filt->range = true;
1510 } else if (!strcmp(filt->action, "start")) {
1511 filt->start = true;
1512 } else if (!strcmp(filt->action, "stop")) {
1513 filt->start = false;
1514 } else if (!strcmp(filt->action, "tracestop")) {
1515 filt->start = false;
1516 filt->range = true;
1517 filt->action += 5; /* Change 'tracestop' to 'stop' */
1518 } else {
1519 return -EINVAL;
1520 }
1521 return 0;
1522}
1523
1524static int parse_sym_idx(char **inp, int *idx)
1525{
1526 *idx = -1;
1527
1528 *inp += strspn(*inp, " ");
1529
1530 if (**inp != '#')
1531 return 0;
1532
1533 *inp += 1;
1534
1535 if (**inp == 'g' || **inp == 'G') {
1536 *inp += 1;
1537 *idx = 0;
1538 } else {
1539 unsigned long num;
1540 char *endptr;
1541
1542 errno = 0;
1543 num = strtoul(*inp, &endptr, 0);
1544 if (errno)
1545 return -errno;
1546 if (endptr == *inp || num > INT_MAX)
1547 return -EINVAL;
1548 *inp = endptr;
1549 *idx = num;
1550 }
1551
1552 return 0;
1553}
1554
1555static int parse_addr_size(char **inp, u64 *num, const char **str, int *idx)
1556{
1557 int err = parse_num_or_str(inp, num, str, " ");
1558
1559 if (!err && *str)
1560 err = parse_sym_idx(inp, idx);
1561
1562 return err;
1563}
1564
1565static int parse_one_filter(struct addr_filter *filt, const char **filter_inp)
1566{
1567 char *fstr;
1568 int err;
1569
1570 filt->str = fstr = strdup(*filter_inp);
1571 if (!fstr)
1572 return -ENOMEM;
1573
1574 err = parse_num_or_str(&fstr, NULL, &filt->action, " ");
1575 if (err)
1576 goto out_err;
1577
1578 err = parse_action(filt);
1579 if (err)
1580 goto out_err;
1581
1582 err = parse_addr_size(&fstr, &filt->addr, &filt->sym_from,
1583 &filt->sym_from_idx);
1584 if (err)
1585 goto out_err;
1586
1587 fstr += strspn(fstr, " ");
1588
1589 if (*fstr == '/') {
1590 fstr += 1;
1591 err = parse_addr_size(&fstr, &filt->size, &filt->sym_to,
1592 &filt->sym_to_idx);
1593 if (err)
1594 goto out_err;
1595 filt->range = true;
1596 }
1597
1598 fstr += strspn(fstr, " ");
1599
1600 if (*fstr == '@') {
1601 fstr += 1;
1602 err = parse_num_or_str(&fstr, NULL, &filt->filename, " ,");
1603 if (err)
1604 goto out_err;
1605 }
1606
1607 fstr += strspn(fstr, " ,");
1608
1609 *filter_inp += fstr - filt->str;
1610
1611 return 0;
1612
1613out_err:
1614 addr_filter__free_str(filt);
1615
1616 return err;
1617}
1618
1619int addr_filters__parse_bare_filter(struct addr_filters *filts,
1620 const char *filter)
1621{
1622 struct addr_filter *filt;
1623 const char *fstr = filter;
1624 int err;
1625
1626 while (*fstr) {
1627 filt = addr_filter__new();
1628 err = parse_one_filter(filt, &fstr);
1629 if (err) {
1630 addr_filter__free(filt);
1631 addr_filters__exit(filts);
1632 return err;
1633 }
1634 addr_filters__add(filts, filt);
1635 }
1636
1637 return 0;
1638}
1639
1640struct sym_args {
1641 const char *name;
1642 u64 start;
1643 u64 size;
1644 int idx;
1645 int cnt;
1646 bool started;
1647 bool global;
1648 bool selected;
1649 bool duplicate;
1650 bool near;
1651};
1652
1653static bool kern_sym_match(struct sym_args *args, const char *name, char type)
1654{
1655 /* A function with the same name, and global or the n'th found or any */
1656 return symbol_type__is_a(type, MAP__FUNCTION) &&
1657 !strcmp(name, args->name) &&
1658 ((args->global && isupper(type)) ||
1659 (args->selected && ++(args->cnt) == args->idx) ||
1660 (!args->global && !args->selected));
1661}
1662
1663static int find_kern_sym_cb(void *arg, const char *name, char type, u64 start)
1664{
1665 struct sym_args *args = arg;
1666
1667 if (args->started) {
1668 if (!args->size)
1669 args->size = start - args->start;
1670 if (args->selected) {
1671 if (args->size)
1672 return 1;
1673 } else if (kern_sym_match(args, name, type)) {
1674 args->duplicate = true;
1675 return 1;
1676 }
1677 } else if (kern_sym_match(args, name, type)) {
1678 args->started = true;
1679 args->start = start;
1680 }
1681
1682 return 0;
1683}
1684
1685static int print_kern_sym_cb(void *arg, const char *name, char type, u64 start)
1686{
1687 struct sym_args *args = arg;
1688
1689 if (kern_sym_match(args, name, type)) {
1690 pr_err("#%d\t0x%"PRIx64"\t%c\t%s\n",
1691 ++args->cnt, start, type, name);
1692 args->near = true;
1693 } else if (args->near) {
1694 args->near = false;
1695 pr_err("\t\twhich is near\t\t%s\n", name);
1696 }
1697
1698 return 0;
1699}
1700
1701static int sym_not_found_error(const char *sym_name, int idx)
1702{
1703 if (idx > 0) {
1704 pr_err("N'th occurrence (N=%d) of symbol '%s' not found.\n",
1705 idx, sym_name);
1706 } else if (!idx) {
1707 pr_err("Global symbol '%s' not found.\n", sym_name);
1708 } else {
1709 pr_err("Symbol '%s' not found.\n", sym_name);
1710 }
1711 pr_err("Note that symbols must be functions.\n");
1712
1713 return -EINVAL;
1714}
1715
1716static int find_kern_sym(const char *sym_name, u64 *start, u64 *size, int idx)
1717{
1718 struct sym_args args = {
1719 .name = sym_name,
1720 .idx = idx,
1721 .global = !idx,
1722 .selected = idx > 0,
1723 };
1724 int err;
1725
1726 *start = 0;
1727 *size = 0;
1728
1729 err = kallsyms__parse("/proc/kallsyms", &args, find_kern_sym_cb);
1730 if (err < 0) {
1731 pr_err("Failed to parse /proc/kallsyms\n");
1732 return err;
1733 }
1734
1735 if (args.duplicate) {
1736 pr_err("Multiple kernel symbols with name '%s'\n", sym_name);
1737 args.cnt = 0;
1738 kallsyms__parse("/proc/kallsyms", &args, print_kern_sym_cb);
1739 pr_err("Disambiguate symbol name by inserting #n after the name e.g. %s #2\n",
1740 sym_name);
1741 pr_err("Or select a global symbol by inserting #0 or #g or #G\n");
1742 return -EINVAL;
1743 }
1744
1745 if (!args.started) {
1746 pr_err("Kernel symbol lookup: ");
1747 return sym_not_found_error(sym_name, idx);
1748 }
1749
1750 *start = args.start;
1751 *size = args.size;
1752
1753 return 0;
1754}
1755
1756static int find_entire_kern_cb(void *arg, const char *name __maybe_unused,
1757 char type, u64 start)
1758{
1759 struct sym_args *args = arg;
1760
1761 if (!symbol_type__is_a(type, MAP__FUNCTION))
1762 return 0;
1763
1764 if (!args->started) {
1765 args->started = true;
1766 args->start = start;
1767 }
1768 /* Don't know exactly where the kernel ends, so we add a page */
1769 args->size = round_up(start, page_size) + page_size - args->start;
1770
1771 return 0;
1772}
1773
1774static int addr_filter__entire_kernel(struct addr_filter *filt)
1775{
1776 struct sym_args args = { .started = false };
1777 int err;
1778
1779 err = kallsyms__parse("/proc/kallsyms", &args, find_entire_kern_cb);
1780 if (err < 0 || !args.started) {
1781 pr_err("Failed to parse /proc/kallsyms\n");
1782 return err;
1783 }
1784
1785 filt->addr = args.start;
1786 filt->size = args.size;
1787
1788 return 0;
1789}
1790
1791static int check_end_after_start(struct addr_filter *filt, u64 start, u64 size)
1792{
1793 if (start + size >= filt->addr)
1794 return 0;
1795
1796 if (filt->sym_from) {
1797 pr_err("Symbol '%s' (0x%"PRIx64") comes before '%s' (0x%"PRIx64")\n",
1798 filt->sym_to, start, filt->sym_from, filt->addr);
1799 } else {
1800 pr_err("Symbol '%s' (0x%"PRIx64") comes before address 0x%"PRIx64")\n",
1801 filt->sym_to, start, filt->addr);
1802 }
1803
1804 return -EINVAL;
1805}
1806
1807static int addr_filter__resolve_kernel_syms(struct addr_filter *filt)
1808{
1809 bool no_size = false;
1810 u64 start, size;
1811 int err;
1812
1813 if (symbol_conf.kptr_restrict) {
1814 pr_err("Kernel addresses are restricted. Unable to resolve kernel symbols.\n");
1815 return -EINVAL;
1816 }
1817
1818 if (filt->sym_from && !strcmp(filt->sym_from, "*"))
1819 return addr_filter__entire_kernel(filt);
1820
1821 if (filt->sym_from) {
1822 err = find_kern_sym(filt->sym_from, &start, &size,
1823 filt->sym_from_idx);
1824 if (err)
1825 return err;
1826 filt->addr = start;
1827 if (filt->range && !filt->size && !filt->sym_to) {
1828 filt->size = size;
1829 no_size = !!size;
1830 }
1831 }
1832
1833 if (filt->sym_to) {
1834 err = find_kern_sym(filt->sym_to, &start, &size,
1835 filt->sym_to_idx);
1836 if (err)
1837 return err;
1838
1839 err = check_end_after_start(filt, start, size);
1840 if (err)
1841 return err;
1842 filt->size = start + size - filt->addr;
1843 no_size = !!size;
1844 }
1845
1846 /* The very last symbol in kallsyms does not imply a particular size */
1847 if (no_size) {
1848 pr_err("Cannot determine size of symbol '%s'\n",
1849 filt->sym_to ? filt->sym_to : filt->sym_from);
1850 return -EINVAL;
1851 }
1852
1853 return 0;
1854}
1855
1856static struct dso *load_dso(const char *name)
1857{
1858 struct map *map;
1859 struct dso *dso;
1860
1861 map = dso__new_map(name);
1862 if (!map)
1863 return NULL;
1864
1865 map__load(map);
1866
1867 dso = dso__get(map->dso);
1868
1869 map__put(map);
1870
1871 return dso;
1872}
1873
1874static bool dso_sym_match(struct symbol *sym, const char *name, int *cnt,
1875 int idx)
1876{
1877 /* Same name, and global or the n'th found or any */
1878 return !arch__compare_symbol_names(name, sym->name) &&
1879 ((!idx && sym->binding == STB_GLOBAL) ||
1880 (idx > 0 && ++*cnt == idx) ||
1881 idx < 0);
1882}
1883
1884static void print_duplicate_syms(struct dso *dso, const char *sym_name)
1885{
1886 struct symbol *sym;
1887 bool near = false;
1888 int cnt = 0;
1889
1890 pr_err("Multiple symbols with name '%s'\n", sym_name);
1891
1892 sym = dso__first_symbol(dso, MAP__FUNCTION);
1893 while (sym) {
1894 if (dso_sym_match(sym, sym_name, &cnt, -1)) {
1895 pr_err("#%d\t0x%"PRIx64"\t%c\t%s\n",
1896 ++cnt, sym->start,
1897 sym->binding == STB_GLOBAL ? 'g' :
1898 sym->binding == STB_LOCAL ? 'l' : 'w',
1899 sym->name);
1900 near = true;
1901 } else if (near) {
1902 near = false;
1903 pr_err("\t\twhich is near\t\t%s\n", sym->name);
1904 }
1905 sym = dso__next_symbol(sym);
1906 }
1907
1908 pr_err("Disambiguate symbol name by inserting #n after the name e.g. %s #2\n",
1909 sym_name);
1910 pr_err("Or select a global symbol by inserting #0 or #g or #G\n");
1911}
1912
1913static int find_dso_sym(struct dso *dso, const char *sym_name, u64 *start,
1914 u64 *size, int idx)
1915{
1916 struct symbol *sym;
1917 int cnt = 0;
1918
1919 *start = 0;
1920 *size = 0;
1921
1922 sym = dso__first_symbol(dso, MAP__FUNCTION);
1923 while (sym) {
1924 if (*start) {
1925 if (!*size)
1926 *size = sym->start - *start;
1927 if (idx > 0) {
1928 if (*size)
1929 return 1;
1930 } else if (dso_sym_match(sym, sym_name, &cnt, idx)) {
1931 print_duplicate_syms(dso, sym_name);
1932 return -EINVAL;
1933 }
1934 } else if (dso_sym_match(sym, sym_name, &cnt, idx)) {
1935 *start = sym->start;
1936 *size = sym->end - sym->start;
1937 }
1938 sym = dso__next_symbol(sym);
1939 }
1940
1941 if (!*start)
1942 return sym_not_found_error(sym_name, idx);
1943
1944 return 0;
1945}
1946
1947static int addr_filter__entire_dso(struct addr_filter *filt, struct dso *dso)
1948{
1949 struct symbol *first_sym = dso__first_symbol(dso, MAP__FUNCTION);
1950 struct symbol *last_sym = dso__last_symbol(dso, MAP__FUNCTION);
1951
1952 if (!first_sym || !last_sym) {
1953 pr_err("Failed to determine filter for %s\nNo symbols found.\n",
1954 filt->filename);
1955 return -EINVAL;
1956 }
1957
1958 filt->addr = first_sym->start;
1959 filt->size = last_sym->end - first_sym->start;
1960
1961 return 0;
1962}
1963
1964static int addr_filter__resolve_syms(struct addr_filter *filt)
1965{
1966 u64 start, size;
1967 struct dso *dso;
1968 int err = 0;
1969
1970 if (!filt->sym_from && !filt->sym_to)
1971 return 0;
1972
1973 if (!filt->filename)
1974 return addr_filter__resolve_kernel_syms(filt);
1975
1976 dso = load_dso(filt->filename);
1977 if (!dso) {
1978 pr_err("Failed to load symbols from: %s\n", filt->filename);
1979 return -EINVAL;
1980 }
1981
1982 if (filt->sym_from && !strcmp(filt->sym_from, "*")) {
1983 err = addr_filter__entire_dso(filt, dso);
1984 goto put_dso;
1985 }
1986
1987 if (filt->sym_from) {
1988 err = find_dso_sym(dso, filt->sym_from, &start, &size,
1989 filt->sym_from_idx);
1990 if (err)
1991 goto put_dso;
1992 filt->addr = start;
1993 if (filt->range && !filt->size && !filt->sym_to)
1994 filt->size = size;
1995 }
1996
1997 if (filt->sym_to) {
1998 err = find_dso_sym(dso, filt->sym_to, &start, &size,
1999 filt->sym_to_idx);
2000 if (err)
2001 goto put_dso;
2002
2003 err = check_end_after_start(filt, start, size);
2004 if (err)
2005 return err;
2006
2007 filt->size = start + size - filt->addr;
2008 }
2009
2010put_dso:
2011 dso__put(dso);
2012
2013 return err;
2014}
2015
2016static char *addr_filter__to_str(struct addr_filter *filt)
2017{
2018 char filename_buf[PATH_MAX];
2019 const char *at = "";
2020 const char *fn = "";
2021 char *filter;
2022 int err;
2023
2024 if (filt->filename) {
2025 at = "@";
2026 fn = realpath(filt->filename, filename_buf);
2027 if (!fn)
2028 return NULL;
2029 }
2030
2031 if (filt->range) {
2032 err = asprintf(&filter, "%s 0x%"PRIx64"/0x%"PRIx64"%s%s",
2033 filt->action, filt->addr, filt->size, at, fn);
2034 } else {
2035 err = asprintf(&filter, "%s 0x%"PRIx64"%s%s",
2036 filt->action, filt->addr, at, fn);
2037 }
2038
2039 return err < 0 ? NULL : filter;
2040}
2041
2042static int parse_addr_filter(struct perf_evsel *evsel, const char *filter,
2043 int max_nr)
2044{
2045 struct addr_filters filts;
2046 struct addr_filter *filt;
2047 int err;
2048
2049 addr_filters__init(&filts);
2050
2051 err = addr_filters__parse_bare_filter(&filts, filter);
2052 if (err)
2053 goto out_exit;
2054
2055 if (filts.cnt > max_nr) {
2056 pr_err("Error: number of address filters (%d) exceeds maximum (%d)\n",
2057 filts.cnt, max_nr);
2058 err = -EINVAL;
2059 goto out_exit;
2060 }
2061
2062 list_for_each_entry(filt, &filts.head, list) {
2063 char *new_filter;
2064
2065 err = addr_filter__resolve_syms(filt);
2066 if (err)
2067 goto out_exit;
2068
2069 new_filter = addr_filter__to_str(filt);
2070 if (!new_filter) {
2071 err = -ENOMEM;
2072 goto out_exit;
2073 }
2074
2075 if (perf_evsel__append_addr_filter(evsel, new_filter)) {
2076 err = -ENOMEM;
2077 goto out_exit;
2078 }
2079 }
2080
2081out_exit:
2082 addr_filters__exit(&filts);
2083
2084 if (err) {
2085 pr_err("Failed to parse address filter: '%s'\n", filter);
2086 pr_err("Filter format is: filter|start|stop|tracestop <start symbol or address> [/ <end symbol or size>] [@<file name>]\n");
2087 pr_err("Where multiple filters are separated by space or comma.\n");
2088 }
2089
2090 return err;
2091}
2092
2093static struct perf_pmu *perf_evsel__find_pmu(struct perf_evsel *evsel)
2094{
2095 struct perf_pmu *pmu = NULL;
2096
2097 while ((pmu = perf_pmu__scan(pmu)) != NULL) {
2098 if (pmu->type == evsel->attr.type)
2099 break;
2100 }
2101
2102 return pmu;
2103}
2104
2105static int perf_evsel__nr_addr_filter(struct perf_evsel *evsel)
2106{
2107 struct perf_pmu *pmu = perf_evsel__find_pmu(evsel);
2108 int nr_addr_filters = 0;
2109
2110 if (!pmu)
2111 return 0;
2112
2113 perf_pmu__scan_file(pmu, "nr_addr_filters", "%d", &nr_addr_filters);
2114
2115 return nr_addr_filters;
2116}
2117
2118int auxtrace_parse_filters(struct perf_evlist *evlist)
2119{
2120 struct perf_evsel *evsel;
2121 char *filter;
2122 int err, max_nr;
2123
2124 evlist__for_each_entry(evlist, evsel) {
2125 filter = evsel->filter;
2126 max_nr = perf_evsel__nr_addr_filter(evsel);
2127 if (!filter || !max_nr)
2128 continue;
2129 evsel->filter = NULL;
2130 err = parse_addr_filter(evsel, filter, max_nr);
2131 free(filter);
2132 if (err)
2133 return err;
2134 pr_debug("Address filter: %s\n", evsel->filter);
2135 }
2136
2137 return 0;
2138}
diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h
index 09286f193532..26fb1ee5746a 100644
--- a/tools/perf/util/auxtrace.h
+++ b/tools/perf/util/auxtrace.h
@@ -318,6 +318,48 @@ struct auxtrace_record {
318 unsigned int alignment; 318 unsigned int alignment;
319}; 319};
320 320
321/**
322 * struct addr_filter - address filter.
323 * @list: list node
324 * @range: true if it is a range filter
325 * @start: true if action is 'filter' or 'start'
326 * @action: 'filter', 'start' or 'stop' ('tracestop' is accepted but converted
327 * to 'stop')
328 * @sym_from: symbol name for the filter address
329 * @sym_to: symbol name that determines the filter size
330 * @sym_from_idx: selects n'th from symbols with the same name (0 means global
331 * and less than 0 means symbol must be unique)
332 * @sym_to_idx: same as @sym_from_idx but for @sym_to
333 * @addr: filter address
334 * @size: filter region size (for range filters)
335 * @filename: DSO file name or NULL for the kernel
336 * @str: allocated string that contains the other string members
337 */
338struct addr_filter {
339 struct list_head list;
340 bool range;
341 bool start;
342 const char *action;
343 const char *sym_from;
344 const char *sym_to;
345 int sym_from_idx;
346 int sym_to_idx;
347 u64 addr;
348 u64 size;
349 const char *filename;
350 char *str;
351};
352
353/**
354 * struct addr_filters - list of address filters.
355 * @head: list of address filters
356 * @cnt: number of address filters
357 */
358struct addr_filters {
359 struct list_head head;
360 int cnt;
361};
362
321#ifdef HAVE_AUXTRACE_SUPPORT 363#ifdef HAVE_AUXTRACE_SUPPORT
322 364
323/* 365/*
@@ -482,6 +524,12 @@ void perf_session__auxtrace_error_inc(struct perf_session *session,
482 union perf_event *event); 524 union perf_event *event);
483void events_stats__auxtrace_error_warn(const struct events_stats *stats); 525void events_stats__auxtrace_error_warn(const struct events_stats *stats);
484 526
527void addr_filters__init(struct addr_filters *filts);
528void addr_filters__exit(struct addr_filters *filts);
529int addr_filters__parse_bare_filter(struct addr_filters *filts,
530 const char *filter);
531int auxtrace_parse_filters(struct perf_evlist *evlist);
532
485static inline int auxtrace__process_event(struct perf_session *session, 533static inline int auxtrace__process_event(struct perf_session *session,
486 union perf_event *event, 534 union perf_event *event,
487 struct perf_sample *sample, 535 struct perf_sample *sample,
@@ -640,6 +688,12 @@ void auxtrace_index__free(struct list_head *head __maybe_unused)
640{ 688{
641} 689}
642 690
691static inline
692int auxtrace_parse_filters(struct perf_evlist *evlist __maybe_unused)
693{
694 return 0;
695}
696
643int auxtrace_mmap__mmap(struct auxtrace_mmap *mm, 697int auxtrace_mmap__mmap(struct auxtrace_mmap *mm,
644 struct auxtrace_mmap_params *mp, 698 struct auxtrace_mmap_params *mp,
645 void *userpg, int fd); 699 void *userpg, int fd);