1 : // Copyright 2013 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 : //
15 : // Declares FilterCompiler, a utility class for converting textual descriptions
16 : // of symbols/compilands/etc into address-space filters for a given image.
17 : //
18 : // A filter description consists of a series of rules of the form:
19 : //
20 : // [+ or -][type]:[description]
21 : //
22 : // A line with a leading '+' means that any address ranges matching the rule
23 : // will be added to the filter. A line with a leading '-' means that the
24 : // corresponding address ranges will be removed from the filter. Lines will be
25 : // processed in the order that they are provided in the file.
26 : //
27 : // The types that are currently recognized are:
28 : //
29 : // function Matches undecorated function names. The description is a
30 : // regex that will be matched against the symbol name,
31 : // including its full namespace.
32 : // public_symbol Allows matching of public symbols. The description is a
33 : // regex that will be matched against the decorated symbol
34 : // name.
35 : //
36 : // Comments may be specified using the '#' character.
37 :
38 : #ifndef SYZYGY_GENFILTER_FILTER_COMPILER_H_
39 : #define SYZYGY_GENFILTER_FILTER_COMPILER_H_
40 :
41 : #include <dia2.h>
42 : #include <map>
43 :
44 : #include "pcrecpp.h" // NOLINT
45 : #include "syzygy/pe/image_filter.h"
46 :
47 : namespace genfilter {
48 :
49 : class FilterCompiler {
50 : public:
51 : typedef core::RelativeAddress RelativeAddress;
52 : typedef pe::ImageFilter ImageFilter;
53 : typedef ImageFilter::RelativeAddressFilter RelativeAddressFilter;
54 : typedef RelativeAddressFilter::Range Range;
55 :
56 : // Possible modification types.
57 : enum ModificationType {
58 : // The bytes matching the rule will be added to the filter.
59 : kAddToFilter,
60 : // The bytes matching the rule will be subtracted from the filter.
61 : kSubtractFromFilter,
62 : };
63 :
64 : // Possible filter rule types.
65 : enum RuleType{
66 : kFunctionRule,
67 : kPublicSymbolRule,
68 :
69 : // This must be last.
70 : kRuleTypeCount,
71 : };
72 :
73 : // Constructor.
74 E : FilterCompiler() { }
75 :
76 : // @name Accessors.
77 : // @{
78 E : const base::FilePath& image_path() const { return image_path_; }
79 E : const base::FilePath& pdb_path() const { return pdb_path_; }
80 : // @}
81 :
82 : // Initializes this filter generator. Logs verbosely on failure.
83 : // @param image_path The path to the image for which a filter is being
84 : // generated.
85 : // @param pdb_path The path of the corresponding PDB. If this is empty it
86 : // will be searched for.
87 : // @returns true on success, false otherwise.
88 : // @note Init must be called before calling any other member functions.
89 : bool Init(const base::FilePath& image_path);
90 : bool Init(const base::FilePath& image_path, const base::FilePath& pdb_path);
91 :
92 : // Adds a rule to this filter compiler.
93 : // @param modification_type The way the filter is modifed upon successful
94 : // matching of this rule.
95 : // @param rule_type The type of the rule to add.
96 : // @param description The rule description. This must be a valid Perl regex
97 : // pattern.
98 : // @returns true on success, false otherwise.
99 : bool AddRule(ModificationType modification_type,
100 : RuleType rule_type,
101 : const base::StringPiece& description);
102 :
103 : // Parses a filter description file, adding its contents to this compiler.
104 : // Logs verbosely on failure.
105 : // @param path The path of the filter description file to parse.
106 : // @returns true on success, false otherwise.
107 : bool ParseFilterDescriptionFile(const base::FilePath& path);
108 :
109 : // Compiles a filter using the current rules. This logs a warning for any
110 : // filter rules that were not successfully matched.
111 : // @param filter The filter to be populated.
112 : // @returns true on success, false otherwise.
113 : bool Compile(ImageFilter* filter);
114 :
115 : protected:
116 : // Forward declaration.
117 : struct Rule;
118 :
119 : typedef pcrecpp::RE RE;
120 : typedef std::map<size_t, Rule> RuleMap;
121 : typedef std::vector<Rule*> RulePointers;
122 :
123 : // Adds a rule with explicit source information to this filter compiler.
124 : // @param modification_type The way the filter is modified upon successful
125 : // matching of this rule.
126 : // @param rule_type The type of the rule to add.
127 : // @param description The rule description. This must be a valid Perl regex
128 : // pattern.
129 : // @param source_info A description of the source file, line number and
130 : // content. This is only used during error reporting.
131 : // @returns true on success, false otherwise.
132 : bool AddRule(ModificationType modification_type,
133 : RuleType rule_type,
134 : const base::StringPiece& description,
135 : const base::StringPiece& source_info);
136 :
137 : // Crawls the symbols matching rules. Delegates to the various symbol
138 : // visitors.
139 : // @returns true on success, false otherwise.
140 : bool CrawlSymbols();
141 :
142 : // Fills in the filter using cached symbol match data in the rules.
143 : // @param filter The filter to be filled in.
144 : bool FillFilter(ImageFilter* filter);
145 :
146 : // @name Symbol visitors.
147 : // @{
148 : bool OnCompiland(IDiaSymbol* compiland);
149 : bool OnFunction(IDiaSymbol* function);
150 : bool OnPublicSymbol(IDiaSymbol* public_symbol);
151 : // @}
152 :
153 : // Matches a symbol by name against rules in the given vector. Called by
154 : // OnPublicSymbol and OnFunction.
155 : // @param rules The vector of rules to be inspected for a symbol match.
156 : // @param symbol The symbol to inspect.
157 : bool MatchRulesBySymbolName(const RulePointers& rules, IDiaSymbol* symbol);
158 :
159 : base::FilePath image_path_;
160 : base::FilePath pdb_path_;
161 : pe::PEFile::Signature image_signature_;
162 :
163 : // Stores the filter lines in a map, keyed by their index. We use a map so
164 : // that pointers are stable.
165 : RuleMap rule_map_;
166 :
167 : // Rule pointers stored by type. This allows efficient access while crawling
168 : // symbols
169 : RulePointers rules_by_type_[kRuleTypeCount];
170 :
171 : DISALLOW_COPY_AND_ASSIGN(FilterCompiler);
172 : };
173 :
174 : struct FilterCompiler::Rule {
175 : // Constructor.
176 : Rule(size_t index,
177 : ModificationType modification_type,
178 : RuleType rule_type,
179 : const pe::PEFile::Signature& image_signature,
180 : const base::StringPiece& regex,
181 : const base::StringPiece& source_info)
182 : : index(index),
183 : modification_type(modification_type),
184 : rule_type(rule_type),
185 : ranges(Range(RelativeAddress(0), image_signature.module_size)),
186 : regex(regex.as_string()),
187 E : source_info(source_info.as_string()) {
188 E : }
189 :
190 : // The index of the filter. This reflects the order in which it was added to
191 : // the compiler.
192 : size_t index;
193 :
194 : // The type of modification that this rule will enact.
195 : ModificationType modification_type;
196 :
197 : // The type of filter rule.
198 : RuleType rule_type;
199 :
200 : // The ranges of the image covered by this filter line. The rules may be
201 : // matched and satisfied in an arbitrary order while crawling the symbols and
202 : // this is used to persist the filter information so that it may be applied in
203 : // the intended order once symbol resolution is complete.
204 : RelativeAddressFilter ranges;
205 :
206 : // The regex pattern associated with this filter line.
207 : RE regex;
208 :
209 : // The source information associated with the rule. This is for debugging.
210 : std::string source_info;
211 : };
212 :
213 : } // namespace genfilter
214 :
215 : #endif // SYZYGY_GENFILTER_FILTER_COMPILER_H_
|