blob: 2d5e109e8a11ff864b1b23851d4c0f49a68f6076 [file] [log] [blame]
// Copyright 2013 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Declares FilterCompiler, a utility class for converting textual descriptions
// of symbols/compilands/etc into address-space filters for a given image.
//
// A filter description consists of a series of rules of the form:
//
// [+ or -][type]:[description]
//
// A line with a leading '+' means that any address ranges matching the rule
// will be added to the filter. A line with a leading '-' means that the
// corresponding address ranges will be removed from the filter. Lines will be
// processed in the order that they are provided in the file.
//
// The types that are currently recognized are:
//
// function Matches undecorated function names. The description is a
// regex that will be matched against the symbol name,
// including its full namespace.
// public_symbol Allows matching of public symbols. The description is a
// regex that will be matched against the decorated symbol
// name.
//
// Comments may be specified using the '#' character.
#ifndef SYZYGY_GENFILTER_FILTER_COMPILER_H_
#define SYZYGY_GENFILTER_FILTER_COMPILER_H_
#include <dia2.h>
#include <map>
#include "pcrecpp.h" // NOLINT
#include "syzygy/pe/image_filter.h"
namespace genfilter {
class FilterCompiler {
public:
typedef core::RelativeAddress RelativeAddress;
typedef pe::ImageFilter ImageFilter;
typedef ImageFilter::RelativeAddressFilter RelativeAddressFilter;
typedef RelativeAddressFilter::Range Range;
// Possible modification types.
enum ModificationType {
// The bytes matching the rule will be added to the filter.
kAddToFilter,
// The bytes matching the rule will be subtracted from the filter.
kSubtractFromFilter,
};
// Possible filter rule types.
enum RuleType{
kFunctionRule,
kPublicSymbolRule,
// This must be last.
kRuleTypeCount,
};
// Constructor.
FilterCompiler() { }
// @name Accessors.
// @{
const base::FilePath& image_path() const { return image_path_; }
const base::FilePath& pdb_path() const { return pdb_path_; }
// @}
// Initializes this filter generator. Logs verbosely on failure.
// @param image_path The path to the image for which a filter is being
// generated.
// @param pdb_path The path of the corresponding PDB. If this is empty it
// will be searched for.
// @returns true on success, false otherwise.
// @note Init must be called before calling any other member functions.
bool Init(const base::FilePath& image_path);
bool Init(const base::FilePath& image_path, const base::FilePath& pdb_path);
// Adds a rule to this filter compiler.
// @param modification_type The way the filter is modifed upon successful
// matching of this rule.
// @param rule_type The type of the rule to add.
// @param description The rule description. This must be a valid Perl regex
// pattern.
// @returns true on success, false otherwise.
bool AddRule(ModificationType modification_type,
RuleType rule_type,
const base::StringPiece& description);
// Parses a filter description file, adding its contents to this compiler.
// Logs verbosely on failure.
// @param path The path of the filter description file to parse.
// @returns true on success, false otherwise.
bool ParseFilterDescriptionFile(const base::FilePath& path);
// Compiles a filter using the current rules. This logs a warning for any
// filter rules that were not successfully matched.
// @param filter The filter to be populated.
// @returns true on success, false otherwise.
bool Compile(ImageFilter* filter);
protected:
// Forward declaration.
struct Rule;
typedef pcrecpp::RE RE;
typedef std::map<size_t, Rule> RuleMap;
typedef std::vector<Rule*> RulePointers;
// Adds a rule with explicit source information to this filter compiler.
// @param modification_type The way the filter is modified upon successful
// matching of this rule.
// @param rule_type The type of the rule to add.
// @param description The rule description. This must be a valid Perl regex
// pattern.
// @param source_info A description of the source file, line number and
// content. This is only used during error reporting.
// @returns true on success, false otherwise.
bool AddRule(ModificationType modification_type,
RuleType rule_type,
const base::StringPiece& description,
const base::StringPiece& source_info);
// Crawls the symbols matching rules. Delegates to the various symbol
// visitors.
// @returns true on success, false otherwise.
bool CrawlSymbols();
// Fills in the filter using cached symbol match data in the rules.
// @param filter The filter to be filled in.
bool FillFilter(ImageFilter* filter);
// @name Symbol visitors.
// @{
bool OnCompiland(IDiaSymbol* compiland);
bool OnFunction(IDiaSymbol* function);
bool OnPublicSymbol(IDiaSymbol* public_symbol);
// @}
// Matches a symbol by name against rules in the given vector. Called by
// OnPublicSymbol and OnFunction.
// @param rules The vector of rules to be inspected for a symbol match.
// @param symbol The symbol to inspect.
bool MatchRulesBySymbolName(const RulePointers& rules, IDiaSymbol* symbol);
base::FilePath image_path_;
base::FilePath pdb_path_;
pe::PEFile::Signature image_signature_;
// Stores the filter lines in a map, keyed by their index. We use a map so
// that pointers are stable.
RuleMap rule_map_;
// Rule pointers stored by type. This allows efficient access while crawling
// symbols
RulePointers rules_by_type_[kRuleTypeCount];
DISALLOW_COPY_AND_ASSIGN(FilterCompiler);
};
struct FilterCompiler::Rule {
// Constructor.
Rule(size_t index,
ModificationType modification_type,
RuleType rule_type,
const pe::PEFile::Signature& image_signature,
const base::StringPiece& regex,
const base::StringPiece& source_info)
: index(index),
modification_type(modification_type),
rule_type(rule_type),
ranges(Range(RelativeAddress(0), image_signature.module_size)),
regex(regex.as_string()),
source_info(source_info.as_string()) {
}
// The index of the filter. This reflects the order in which it was added to
// the compiler.
size_t index;
// The type of modification that this rule will enact.
ModificationType modification_type;
// The type of filter rule.
RuleType rule_type;
// The ranges of the image covered by this filter line. The rules may be
// matched and satisfied in an arbitrary order while crawling the symbols and
// this is used to persist the filter information so that it may be applied in
// the intended order once symbol resolution is complete.
RelativeAddressFilter ranges;
// The regex pattern associated with this filter line.
RE regex;
// The source information associated with the rule. This is for debugging.
std::string source_info;
};
} // namespace genfilter
#endif // SYZYGY_GENFILTER_FILTER_COMPILER_H_