filter.c revision 1bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bd
1/*
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
21#include <stddef.h>
22#include <error.h>
23#include <assert.h>
24
25#include "filter.h"
26#include "library.h"
27
28void abort(void); //xxx
29
30void
31filter_init(struct filter *filt)
32{
33	filt->rules = NULL;
34}
35
36void
37filter_destroy(struct filter *filt)
38{
39	struct filter_rule *it;
40	for (it = filt->rules; it != NULL; ) {
41		struct filter_rule *next = it->next;
42		filter_rule_destroy(it);
43		it = next;
44	}
45}
46
47void
48filter_rule_init(struct filter_rule *rule, enum filter_rule_type type,
49		 struct filter_lib_matcher *matcher,
50		 regex_t symbol_re)
51{
52	rule->type = type;
53	rule->lib_matcher = matcher;
54	rule->symbol_re = symbol_re;
55	rule->next = NULL;
56}
57
58void
59filter_rule_destroy(struct filter_rule *rule)
60{
61	filter_lib_matcher_destroy(rule->lib_matcher);
62	regfree(&rule->symbol_re);
63}
64
65void
66filter_add_rule(struct filter *filt, struct filter_rule *rule)
67{
68	rule->next = filt->rules;
69	filt->rules = rule;
70}
71
72void
73filter_lib_matcher_name_init(struct filter_lib_matcher *matcher,
74			     regex_t libname_re)
75{
76	matcher->type = FLM_NAME;
77	matcher->libname_re = libname_re;
78}
79
80void
81filter_lib_matcher_main_init(struct filter_lib_matcher *matcher)
82{
83	matcher->type = FLM_MAIN;
84}
85
86void
87filter_lib_matcher_destroy(struct filter_lib_matcher *matcher)
88{
89	switch (matcher->type) {
90	case FLM_NAME:
91		regfree(&matcher->libname_re);
92		break;
93	case FLM_MAIN:
94		break;
95	}
96}
97
98static int
99re_match_or_error(regex_t *re, const char *name, const char *what)
100{
101	int status = regexec(re, name, 0, NULL, 0);
102	if (status == 0)
103		return 1;
104	if (status == REG_NOMATCH)
105		return 0;
106
107	char buf[200];
108	regerror(status, re, buf, sizeof buf);
109	error(0, 0, "Error when matching %s: %s", name, buf);
110
111	return 0;
112}
113
114static int
115matcher_matches_library(struct filter_lib_matcher *matcher, struct library *lib)
116{
117	switch (matcher->type) {
118	case FLM_NAME:
119		return re_match_or_error(&matcher->libname_re, lib->name,
120					 "library name");
121	case FLM_MAIN:
122		assert(!"FLM_MAIN not implemented yet!");
123		abort();
124	}
125	assert(matcher->type != matcher->type);
126	abort();
127}
128
129int
130filter_matches_library(struct filter *filt, struct library *lib)
131{
132	struct filter_rule *it;
133	for (it = filt->rules; it != NULL; it = it->next)
134		switch (it->type) {
135		case FR_ADD:
136			if (matcher_matches_library(it->lib_matcher, lib))
137				return 1;
138		case FR_SUBTRACT:
139			continue;
140		};
141	return 0;
142}
143
144int
145filter_matches_symbol(struct filter *filt, struct library_symbol *sym)
146{
147	int matches = 0;
148	struct filter_rule *it;
149	for (it = filt->rules; it != NULL; it = it->next) {
150		switch (it->type) {
151		case FR_ADD:
152			if (matches)
153				continue;
154			break;
155		case FR_SUBTRACT:
156			if (!matches)
157				continue;
158		}
159
160		if (matcher_matches_library(it->lib_matcher, sym->lib)
161		    && re_match_or_error(&it->symbol_re, sym->name,
162					 "symbol name"))
163			matches = !matches;
164	}
165	return matches;
166}
167