blob: ba50c40fb99781f59773e5a392b568a4242089ec [file] [log] [blame]
Petr Machata1bbfbc62012-03-31 02:00:00 +02001/*
2 * This file is part of ltrace.
3 * Copyright (C) 2012 Petr Machata, Red Hat Inc.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18 * 02110-1301 USA
19 */
20
Petr Machata0b55b582012-04-02 00:38:46 +020021#include <stdlib.h>
Petr Machata1bbfbc62012-03-31 02:00:00 +020022#include <assert.h>
Petr Machatacc0e1e42012-04-25 13:42:07 +020023#include <stdio.h>
24#include <string.h>
Petr Machata1bbfbc62012-03-31 02:00:00 +020025
26#include "filter.h"
27#include "library.h"
Petr Machataa24021c2012-09-25 14:46:44 +020028#include "callback.h"
Petr Machata1bbfbc62012-03-31 02:00:00 +020029
Petr Machata1bbfbc62012-03-31 02:00:00 +020030void
31filter_init(struct filter *filt)
32{
33 filt->rules = NULL;
Petr Machata35c88142012-04-04 00:54:43 +020034 filt->next = NULL;
Petr Machata1bbfbc62012-03-31 02:00:00 +020035}
36
37void
38filter_destroy(struct filter *filt)
39{
40 struct filter_rule *it;
41 for (it = filt->rules; it != NULL; ) {
42 struct filter_rule *next = it->next;
43 filter_rule_destroy(it);
44 it = next;
45 }
46}
47
48void
49filter_rule_init(struct filter_rule *rule, enum filter_rule_type type,
50 struct filter_lib_matcher *matcher,
51 regex_t symbol_re)
52{
53 rule->type = type;
54 rule->lib_matcher = matcher;
55 rule->symbol_re = symbol_re;
56 rule->next = NULL;
57}
58
59void
60filter_rule_destroy(struct filter_rule *rule)
61{
62 filter_lib_matcher_destroy(rule->lib_matcher);
63 regfree(&rule->symbol_re);
64}
65
66void
67filter_add_rule(struct filter *filt, struct filter_rule *rule)
68{
Petr Machata0e44da32012-04-23 23:33:31 +020069 struct filter_rule **rulep;
70 for (rulep = &filt->rules; *rulep != NULL; rulep = &(*rulep)->next)
71 ;
72 *rulep = rule;
Petr Machata1bbfbc62012-03-31 02:00:00 +020073}
74
75void
76filter_lib_matcher_name_init(struct filter_lib_matcher *matcher,
Petr Machata0b55b582012-04-02 00:38:46 +020077 enum filter_lib_matcher_type type,
Petr Machata1bbfbc62012-03-31 02:00:00 +020078 regex_t libname_re)
79{
Petr Machata0b55b582012-04-02 00:38:46 +020080 switch (type) {
81 case FLM_MAIN:
82 assert(type != type);
83 abort();
84
85 case FLM_SONAME:
86 case FLM_PATHNAME:
87 matcher->type = type;
88 matcher->libname_re = libname_re;
89 }
Petr Machata1bbfbc62012-03-31 02:00:00 +020090}
91
92void
93filter_lib_matcher_main_init(struct filter_lib_matcher *matcher)
94{
95 matcher->type = FLM_MAIN;
96}
97
98void
99filter_lib_matcher_destroy(struct filter_lib_matcher *matcher)
100{
101 switch (matcher->type) {
Petr Machata0b55b582012-04-02 00:38:46 +0200102 case FLM_SONAME:
103 case FLM_PATHNAME:
Petr Machata1bbfbc62012-03-31 02:00:00 +0200104 regfree(&matcher->libname_re);
105 break;
106 case FLM_MAIN:
107 break;
108 }
109}
110
111static int
112re_match_or_error(regex_t *re, const char *name, const char *what)
113{
114 int status = regexec(re, name, 0, NULL, 0);
115 if (status == 0)
116 return 1;
117 if (status == REG_NOMATCH)
118 return 0;
119
120 char buf[200];
121 regerror(status, re, buf, sizeof buf);
Petr Machatacc0e1e42012-04-25 13:42:07 +0200122 fprintf(stderr, "Error when matching %s: %s\n", name, buf);
Petr Machata1bbfbc62012-03-31 02:00:00 +0200123
124 return 0;
125}
126
127static int
128matcher_matches_library(struct filter_lib_matcher *matcher, struct library *lib)
129{
130 switch (matcher->type) {
Petr Machata0b55b582012-04-02 00:38:46 +0200131 case FLM_SONAME:
132 return re_match_or_error(&matcher->libname_re, lib->soname,
133 "library soname");
134 case FLM_PATHNAME:
135 return re_match_or_error(&matcher->libname_re, lib->pathname,
136 "library pathname");
Petr Machata1bbfbc62012-03-31 02:00:00 +0200137 case FLM_MAIN:
Petr Machatab5f80ac2012-04-04 01:46:18 +0200138 return lib->type == LT_LIBTYPE_MAIN;
Petr Machata1bbfbc62012-03-31 02:00:00 +0200139 }
140 assert(matcher->type != matcher->type);
141 abort();
142}
143
144int
145filter_matches_library(struct filter *filt, struct library *lib)
146{
Petr Machata35c88142012-04-04 00:54:43 +0200147 if (filt == NULL)
148 return 0;
149
Petr Machata1054c902012-09-27 22:46:16 +0200150 for (; filt != NULL; filt = filt->next) {
151 struct filter_rule *it;
152 for (it = filt->rules; it != NULL; it = it->next)
153 switch (it->type) {
154 case FR_ADD:
155 if (matcher_matches_library(it->lib_matcher, lib))
156 return 1;
157 case FR_SUBTRACT:
158 continue;
159 };
160 }
Petr Machata1bbfbc62012-03-31 02:00:00 +0200161 return 0;
162}
163
164int
Petr Machatab5f80ac2012-04-04 01:46:18 +0200165filter_matches_symbol(struct filter *filt,
166 const char *sym_name, struct library *lib)
Petr Machata1bbfbc62012-03-31 02:00:00 +0200167{
Petr Machata391318f2012-04-19 02:28:13 +0200168 for (; filt != NULL; filt = filt->next) {
Petr Machatac631abf2012-04-23 23:39:04 +0200169 int matches = 0;
Petr Machata391318f2012-04-19 02:28:13 +0200170 struct filter_rule *it;
171 for (it = filt->rules; it != NULL; it = it->next) {
172 switch (it->type) {
173 case FR_ADD:
174 if (matches)
175 continue;
176 break;
177 case FR_SUBTRACT:
178 if (!matches)
179 continue;
180 }
Petr Machata1bbfbc62012-03-31 02:00:00 +0200181
Petr Machata391318f2012-04-19 02:28:13 +0200182 if (matcher_matches_library(it->lib_matcher, lib)
183 && re_match_or_error(&it->symbol_re, sym_name,
184 "symbol name"))
185 matches = !matches;
186 }
Petr Machatac631abf2012-04-23 23:39:04 +0200187 if (matches)
188 return 1;
Petr Machata1bbfbc62012-03-31 02:00:00 +0200189 }
Petr Machatac631abf2012-04-23 23:39:04 +0200190 return 0;
Petr Machata1bbfbc62012-03-31 02:00:00 +0200191}