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