11bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata/*
21bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata * This file is part of ltrace.
31bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata * Copyright (C) 2012 Petr Machata, Red Hat Inc.
41bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata *
51bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata * This program is free software; you can redistribute it and/or
61bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata * modify it under the terms of the GNU General Public License as
71bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata * published by the Free Software Foundation; either version 2 of the
81bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata * License, or (at your option) any later version.
91bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata *
101bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata * This program is distributed in the hope that it will be useful, but
111bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata * WITHOUT ANY WARRANTY; without even the implied warranty of
121bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
131bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata * General Public License for more details.
141bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata *
151bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata * You should have received a copy of the GNU General Public License
161bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata * along with this program; if not, write to the Free Software
171bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
181bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata * 02110-1301 USA
191bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata */
201bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata
210b55b5852b9fe2ed6cceada004db303fe6efe6cePetr Machata#include <stdlib.h>
221bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata#include <assert.h>
23cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata#include <stdio.h>
24cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata#include <string.h>
251bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata
261bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata#include "filter.h"
271bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata#include "library.h"
28a24021c5abfa8c2482e3224f14ac191cd0826a8fPetr Machata#include "callback.h"
291bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata
301bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machatavoid
311bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machatafilter_init(struct filter *filt)
321bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata{
331bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	filt->rules = NULL;
3435c8814db9e7d41811cc4620c1bda084f4ff4c7bPetr Machata	filt->next = NULL;
351bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata}
361bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata
371bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machatavoid
381bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machatafilter_destroy(struct filter *filt)
391bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata{
401bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	struct filter_rule *it;
411bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	for (it = filt->rules; it != NULL; ) {
421bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata		struct filter_rule *next = it->next;
431bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata		filter_rule_destroy(it);
441bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata		it = next;
451bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	}
461bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata}
471bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata
481bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machatavoid
491bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machatafilter_rule_init(struct filter_rule *rule, enum filter_rule_type type,
501bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata		 struct filter_lib_matcher *matcher,
511bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata		 regex_t symbol_re)
521bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata{
531bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	rule->type = type;
541bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	rule->lib_matcher = matcher;
551bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	rule->symbol_re = symbol_re;
561bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	rule->next = NULL;
571bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata}
581bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata
591bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machatavoid
601bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machatafilter_rule_destroy(struct filter_rule *rule)
611bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata{
621bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	filter_lib_matcher_destroy(rule->lib_matcher);
631bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	regfree(&rule->symbol_re);
641bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata}
651bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata
661bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machatavoid
671bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machatafilter_add_rule(struct filter *filt, struct filter_rule *rule)
681bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata{
690e44da35a9d783318f936cce8a4f81f18193ab23Petr Machata	struct filter_rule **rulep;
700e44da35a9d783318f936cce8a4f81f18193ab23Petr Machata	for (rulep = &filt->rules; *rulep != NULL; rulep = &(*rulep)->next)
710e44da35a9d783318f936cce8a4f81f18193ab23Petr Machata		;
720e44da35a9d783318f936cce8a4f81f18193ab23Petr Machata	*rulep = rule;
731bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata}
741bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata
751bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machatavoid
761bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machatafilter_lib_matcher_name_init(struct filter_lib_matcher *matcher,
770b55b5852b9fe2ed6cceada004db303fe6efe6cePetr Machata			     enum filter_lib_matcher_type type,
781bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata			     regex_t libname_re)
791bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata{
800b55b5852b9fe2ed6cceada004db303fe6efe6cePetr Machata	switch (type) {
810b55b5852b9fe2ed6cceada004db303fe6efe6cePetr Machata	case FLM_MAIN:
820b55b5852b9fe2ed6cceada004db303fe6efe6cePetr Machata		assert(type != type);
830b55b5852b9fe2ed6cceada004db303fe6efe6cePetr Machata		abort();
840b55b5852b9fe2ed6cceada004db303fe6efe6cePetr Machata
850b55b5852b9fe2ed6cceada004db303fe6efe6cePetr Machata	case FLM_SONAME:
860b55b5852b9fe2ed6cceada004db303fe6efe6cePetr Machata	case FLM_PATHNAME:
870b55b5852b9fe2ed6cceada004db303fe6efe6cePetr Machata		matcher->type = type;
880b55b5852b9fe2ed6cceada004db303fe6efe6cePetr Machata		matcher->libname_re = libname_re;
890b55b5852b9fe2ed6cceada004db303fe6efe6cePetr Machata	}
901bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata}
911bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata
921bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machatavoid
931bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machatafilter_lib_matcher_main_init(struct filter_lib_matcher *matcher)
941bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata{
951bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	matcher->type = FLM_MAIN;
961bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata}
971bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata
981bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machatavoid
991bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machatafilter_lib_matcher_destroy(struct filter_lib_matcher *matcher)
1001bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata{
1011bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	switch (matcher->type) {
1020b55b5852b9fe2ed6cceada004db303fe6efe6cePetr Machata	case FLM_SONAME:
1030b55b5852b9fe2ed6cceada004db303fe6efe6cePetr Machata	case FLM_PATHNAME:
1041bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata		regfree(&matcher->libname_re);
1051bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata		break;
1061bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	case FLM_MAIN:
1071bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata		break;
1081bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	}
1091bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata}
1101bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata
1111bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machatastatic int
1121bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machatare_match_or_error(regex_t *re, const char *name, const char *what)
1131bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata{
1141bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	int status = regexec(re, name, 0, NULL, 0);
1151bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	if (status == 0)
1161bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata		return 1;
1171bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	if (status == REG_NOMATCH)
1181bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata		return 0;
1191bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata
1201bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	char buf[200];
1211bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	regerror(status, re, buf, sizeof buf);
122cc0e1e4b83d69441cc5f61ea87eda5458ee9fae3Petr Machata	fprintf(stderr, "Error when matching %s: %s\n", name, buf);
1231bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata
1241bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	return 0;
1251bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata}
1261bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata
1271bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machatastatic int
1281bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machatamatcher_matches_library(struct filter_lib_matcher *matcher, struct library *lib)
1291bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata{
1301bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	switch (matcher->type) {
1310b55b5852b9fe2ed6cceada004db303fe6efe6cePetr Machata	case FLM_SONAME:
1320b55b5852b9fe2ed6cceada004db303fe6efe6cePetr Machata		return re_match_or_error(&matcher->libname_re, lib->soname,
1330b55b5852b9fe2ed6cceada004db303fe6efe6cePetr Machata					 "library soname");
1340b55b5852b9fe2ed6cceada004db303fe6efe6cePetr Machata	case FLM_PATHNAME:
1350b55b5852b9fe2ed6cceada004db303fe6efe6cePetr Machata		return re_match_or_error(&matcher->libname_re, lib->pathname,
1360b55b5852b9fe2ed6cceada004db303fe6efe6cePetr Machata					 "library pathname");
1371bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	case FLM_MAIN:
138b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata		return lib->type == LT_LIBTYPE_MAIN;
1391bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	}
1401bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	assert(matcher->type != matcher->type);
1411bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	abort();
1421bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata}
1431bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata
1441bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machataint
1451bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machatafilter_matches_library(struct filter *filt, struct library *lib)
1461bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata{
14735c8814db9e7d41811cc4620c1bda084f4ff4c7bPetr Machata	if (filt == NULL)
14835c8814db9e7d41811cc4620c1bda084f4ff4c7bPetr Machata		return 0;
14935c8814db9e7d41811cc4620c1bda084f4ff4c7bPetr Machata
1501054c90aa71875610fda43365a8e74086eb2bd66Petr Machata	for (; filt != NULL; filt = filt->next) {
1511054c90aa71875610fda43365a8e74086eb2bd66Petr Machata		struct filter_rule *it;
1521054c90aa71875610fda43365a8e74086eb2bd66Petr Machata		for (it = filt->rules; it != NULL; it = it->next)
1531054c90aa71875610fda43365a8e74086eb2bd66Petr Machata			switch (it->type) {
1541054c90aa71875610fda43365a8e74086eb2bd66Petr Machata			case FR_ADD:
1551054c90aa71875610fda43365a8e74086eb2bd66Petr Machata				if (matcher_matches_library(it->lib_matcher, lib))
1561054c90aa71875610fda43365a8e74086eb2bd66Petr Machata					return 1;
1571054c90aa71875610fda43365a8e74086eb2bd66Petr Machata			case FR_SUBTRACT:
1581054c90aa71875610fda43365a8e74086eb2bd66Petr Machata				continue;
1591054c90aa71875610fda43365a8e74086eb2bd66Petr Machata			};
1601054c90aa71875610fda43365a8e74086eb2bd66Petr Machata	}
1611bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	return 0;
1621bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata}
1631bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata
1641bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machataint
165b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machatafilter_matches_symbol(struct filter *filt,
166b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata		      const char *sym_name, struct library *lib)
1671bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata{
168391318fb9b1f0f0f67b642309f5c9e94557f8568Petr Machata	for (; filt != NULL; filt = filt->next) {
169c631abfeeb063952f63533fd2c261567a297eeb1Petr Machata		int matches = 0;
170391318fb9b1f0f0f67b642309f5c9e94557f8568Petr Machata		struct filter_rule *it;
171391318fb9b1f0f0f67b642309f5c9e94557f8568Petr Machata		for (it = filt->rules; it != NULL; it = it->next) {
172391318fb9b1f0f0f67b642309f5c9e94557f8568Petr Machata			switch (it->type) {
173391318fb9b1f0f0f67b642309f5c9e94557f8568Petr Machata			case FR_ADD:
174391318fb9b1f0f0f67b642309f5c9e94557f8568Petr Machata				if (matches)
175391318fb9b1f0f0f67b642309f5c9e94557f8568Petr Machata					continue;
176391318fb9b1f0f0f67b642309f5c9e94557f8568Petr Machata				break;
177391318fb9b1f0f0f67b642309f5c9e94557f8568Petr Machata			case FR_SUBTRACT:
178391318fb9b1f0f0f67b642309f5c9e94557f8568Petr Machata				if (!matches)
179391318fb9b1f0f0f67b642309f5c9e94557f8568Petr Machata					continue;
180391318fb9b1f0f0f67b642309f5c9e94557f8568Petr Machata			}
181391318fb9b1f0f0f67b642309f5c9e94557f8568Petr Machata
182391318fb9b1f0f0f67b642309f5c9e94557f8568Petr Machata			if (matcher_matches_library(it->lib_matcher, lib)
183391318fb9b1f0f0f67b642309f5c9e94557f8568Petr Machata			    && re_match_or_error(&it->symbol_re, sym_name,
184391318fb9b1f0f0f67b642309f5c9e94557f8568Petr Machata						 "symbol name"))
185391318fb9b1f0f0f67b642309f5c9e94557f8568Petr Machata				matches = !matches;
1861bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata		}
187c631abfeeb063952f63533fd2c261567a297eeb1Petr Machata		if (matches)
188c631abfeeb063952f63533fd2c261567a297eeb1Petr Machata			return 1;
1891bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	}
190c631abfeeb063952f63533fd2c261567a297eeb1Petr Machata	return 0;
1911bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata}
192