Coverage for /Syzygy/instrument/transforms/asan_transform.h

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
100.0%43430.C++source

Line-by-line coverage:

   1    :  // Copyright 2012 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    :  // Implementation of the SyzyAsan instrumentation transform.
  16    :  
  17    :  #ifndef SYZYGY_INSTRUMENT_TRANSFORMS_ASAN_TRANSFORM_H_
  18    :  #define SYZYGY_INSTRUMENT_TRANSFORMS_ASAN_TRANSFORM_H_
  19    :  
  20    :  #include <map>
  21    :  #include <set>
  22    :  #include <string>
  23    :  #include <utility>
  24    :  
  25    :  #include "base/strings/string_piece.h"
  26    :  #include "syzygy/block_graph/filterable.h"
  27    :  #include "syzygy/block_graph/iterate.h"
  28    :  #include "syzygy/block_graph/analysis/liveness_analysis.h"
  29    :  #include "syzygy/block_graph/analysis/memory_access_analysis.h"
  30    :  #include "syzygy/block_graph/transforms/iterative_transform.h"
  31    :  #include "syzygy/block_graph/transforms/named_transform.h"
  32    :  #include "syzygy/common/asan_parameters.h"
  33    :  #include "syzygy/instrument/transforms/asan_interceptor_filter.h"
  34    :  #include "syzygy/instrument/transforms/asan_intercepts.h"
  35    :  
  36    :  namespace instrument {
  37    :  namespace transforms {
  38    :  
  39    :  // This class implements the transformation applied to each basic block.
  40    :  class AsanBasicBlockTransform
  41    :      : public block_graph::transforms::NamedBasicBlockSubGraphTransformImpl<
  42    :            AsanBasicBlockTransform>,
  43    :        public block_graph::Filterable {
  44    :   public:
  45    :    // Represent the different kind of access to the memory.
  46    :    enum MemoryAccessMode {
  47    :      kNoAccess,
  48    :      kReadAccess,
  49    :      kWriteAccess,
  50    :      kInstrAccess,
  51    :      kRepzAccess,
  52    :      kRepnzAccess,
  53    :    };
  54    :  
  55    :    enum StackAccessMode {
  56    :      kUnsafeStackAccess,
  57    :      kSafeStackAccess,
  58    :    };
  59    :  
  60    :    // Contains memory access information.
  61    :    struct MemoryAccessInfo {
  62    :      MemoryAccessMode mode;
  63    :      uint8_t size;
  64    :      uint16_t opcode;
  65    :      // True iff we need to save the flags for this access.
  66    :      bool save_flags;
  67    :    };
  68    :  
  69    :    typedef block_graph::BlockGraph BlockGraph;
  70    :    typedef block_graph::BasicBlockSubGraph BasicBlockSubGraph;
  71    :    typedef block_graph::TransformPolicyInterface TransformPolicyInterface;
  72    :    typedef MemoryAccessInfo AsanHookMapEntryKey;
  73    :    // Map of hooks to Asan check access functions.
  74    :    typedef std::map<AsanHookMapEntryKey, BlockGraph::Reference> AsanHookMap;
  75    :    typedef std::map<MemoryAccessMode, BlockGraph::Reference> AsanDefaultHookMap;
  76    :  
  77    :    // Constructor.
  78    :    // @param check_access_hooks References to the various check access functions.
  79    :    //     The hooks are assumed to be direct references for COFF images, and
  80    :    //     indirect references for PE images.
  81    :    explicit AsanBasicBlockTransform(AsanHookMap* check_access_hooks) :
  82    :        check_access_hooks_(check_access_hooks),
  83    :        debug_friendly_(false),
  84    :        dry_run_(false),
  85    :        instrumentation_happened_(false),
  86    :        instrumentation_rate_(1.0),
  87    :        remove_redundant_checks_(false),
  88  E :        use_liveness_analysis_(false) {
  89  E :      DCHECK(check_access_hooks != NULL);
  90  E :    }
  91    :  
  92    :    // @name Accessors and mutators.
  93    :    // @{
  94    :    bool debug_friendly() const { return debug_friendly_; }
  95  E :    void set_debug_friendly(bool flag) { debug_friendly_ = flag; }
  96    :  
  97  E :    bool use_liveness_analysis() { return use_liveness_analysis_; }
  98  E :    void set_use_liveness_analysis(bool use_liveness_analysis) {
  99  E :      use_liveness_analysis_ = use_liveness_analysis;
 100  E :    }
 101    :  
 102  E :    bool remove_redundant_checks() const { return remove_redundant_checks_; }
 103  E :    void set_remove_redundant_checks(bool remove_redundant_checks) {
 104  E :      remove_redundant_checks_ = remove_redundant_checks;
 105  E :    }
 106    :  
 107    :    // The instrumentation rate must be in the range [0, 1], inclusive.
 108  E :    double instrumentation_rate() const { return instrumentation_rate_; }
 109    :    void set_instrumentation_rate(double instrumentation_rate);
 110    :  
 111    :    // Instead of instrumenting the basic blocks, in dry run mode the instrumenter
 112    :    // only signals if any instrumentation would have happened on the block.
 113    :    // @returns true iff the instrumenter is in dry run mode.
 114  E :    bool dry_run() const { return dry_run_; }
 115    :    // Instead of instrumenting the basic blocks, in dry run mode the instrumenter
 116    :    // only signals if any instrumentation would have happened on the block.
 117    :    // @param dry_run true iff dry run mode is on.
 118  E :    void set_dry_run(bool dry_run) { dry_run_ = dry_run; }
 119    :  
 120    :    // If at least one instrumentation happened during a transform, or would have
 121    :    // happened during a dry run transform, this returns true.
 122    :    // @returns true iff an instrumentation happened (or would have happened, in
 123    :    //     case of a dry run).
 124  E :    bool instrumentation_happened() const { return instrumentation_happened_; }
 125    :    // @}
 126    :  
 127    :    // The transform name.
 128    :    static const char kTransformName[];
 129    :  
 130    :   protected:
 131    :    // @name BasicBlockSubGraphTransformInterface method.
 132    :    virtual bool TransformBasicBlockSubGraph(
 133    :        const TransformPolicyInterface* policy,
 134    :        BlockGraph* block_graph,
 135    :        BasicBlockSubGraph* basic_block_subgraph) OVERRIDE;
 136    :  
 137    :    // Instruments the memory accesses in a basic block.
 138    :    // @param basic_block The basic block to be instrumented.
 139    :    // @param stack_mode Give some assumptions to the transformation on stack
 140    :    //     frame manipulations inside @p basic_block. The transformation assume a
 141    :    //     standard calling convention, unless specified by this parameter.
 142    :    //     (note: Unsafe blocks may be produced with the compiler flag
 143    :    //     frame-pointer-omission).
 144    :    // @param image_format The format of the image being instrumented. The details
 145    :    //     of how we invoke the hooks vary depending on this.
 146    :    // @returns true on success, false otherwise.
 147    :    bool InstrumentBasicBlock(block_graph::BasicCodeBlock* basic_block,
 148    :                              StackAccessMode stack_mode,
 149    :                              BlockGraph::ImageFormat image_format);
 150    :  
 151    :   private:
 152    :    // Liveness analysis and liveness information for this subgraph.
 153    :    block_graph::analysis::LivenessAnalysis liveness_;
 154    :  
 155    :    // Memory accesses value numbering.
 156    :    block_graph::analysis::MemoryAccessAnalysis memory_accesses_;
 157    :  
 158    :    // The references to the Asan access check import entries.
 159    :    AsanHookMap* check_access_hooks_;
 160    :  
 161    :    // Activate the overwriting of source range for created instructions.
 162    :    bool debug_friendly_;
 163    :  
 164    :    // Instead of instrumenting the basic blocks, run in dry run mode and just
 165    :    // signal whether there would be an instrumenation in the block.
 166    :    bool dry_run_;
 167    :  
 168    :    // Controls the rate at which reads/writes are instrumented. This is
 169    :    // implemented using random sampling.
 170    :    double instrumentation_rate_;
 171    :  
 172    :    // If any instrumentation happened during a transform, or would have happened
 173    :    // during a dry run transform, this member is set to true.
 174    :    bool instrumentation_happened_;
 175    :  
 176    :    // When activated, a redundancy elimination is performed to minimize the
 177    :    // memory checks added by this transform.
 178    :    bool remove_redundant_checks_;
 179    :  
 180    :    // Set iff we should use the liveness analysis to do smarter instrumentation.
 181    :    bool use_liveness_analysis_;
 182    :  
 183    :    DISALLOW_COPY_AND_ASSIGN(AsanBasicBlockTransform);
 184    :  };
 185    :  
 186    :  class AsanTransform
 187    :      : public block_graph::transforms::IterativeTransformImpl<AsanTransform>,
 188    :        public block_graph::Filterable {
 189    :   public:
 190    :    typedef block_graph::BlockGraph BlockGraph;
 191    :    typedef block_graph::TransformPolicyInterface TransformPolicyInterface;
 192    :    typedef AsanBasicBlockTransform::MemoryAccessInfo MemoryAccessInfo;
 193    :    typedef AsanBasicBlockTransform::MemoryAccessMode MemoryAccessMode;
 194    :  
 195    :    // Initialize a new AsanTransform instance.
 196    :    AsanTransform();
 197    :  
 198    :    // @name IterativeTransformImpl implementation.
 199    :    // @{
 200    :    bool PreBlockGraphIteration(const TransformPolicyInterface* policy,
 201    :                                BlockGraph* block_graph,
 202    :                                BlockGraph::Block* header_block);
 203    :    bool OnBlock(const TransformPolicyInterface* policy,
 204    :                 BlockGraph* block_graph,
 205    :                 BlockGraph::Block* block);
 206    :    bool PostBlockGraphIteration(const TransformPolicyInterface* policy,
 207    :                                 BlockGraph* block_graph,
 208    :                                 BlockGraph::Block* header_block);
 209    :    // @}
 210    :  
 211    :    // @name Accessors and mutators.
 212    :    // @{
 213  E :    void set_instrument_dll_name(const base::StringPiece& instrument_dll_name) {
 214  E :      instrument_dll_name.CopyToString(&asan_dll_name_);
 215  E :    }
 216  E :    const char* instrument_dll_name() const {
 217  E :      return asan_dll_name_.c_str();
 218  E :    }
 219    :  
 220  E :    bool debug_friendly() const { return debug_friendly_; }
 221  E :    void set_debug_friendly(bool flag) { debug_friendly_ = flag; }
 222    :  
 223  E :    bool use_interceptors() const { return use_interceptors_; }
 224  E :    void set_use_interceptors(bool use_interceptors) {
 225  E :      use_interceptors_ = use_interceptors;
 226  E :    }
 227    :  
 228  E :    bool use_liveness_analysis() const { return use_liveness_analysis_; }
 229  E :    void set_use_liveness_analysis(bool use_liveness_analysis) {
 230  E :      use_liveness_analysis_ = use_liveness_analysis;
 231  E :    }
 232    :  
 233  E :    bool remove_redundant_checks() const { return remove_redundant_checks_; }
 234  E :    void set_remove_redundant_checks(bool remove_redundant_checks) {
 235  E :      remove_redundant_checks_ = remove_redundant_checks;
 236  E :    }
 237    :  
 238    :    // The instrumentation rate must be in the range [0, 1], inclusive.
 239  E :    double instrumentation_rate() const { return instrumentation_rate_; }
 240    :    void set_instrumentation_rate(double instrumentation_rate);
 241    :  
 242    :    // Asan RTL parameters.
 243  E :    const common::InflatedAsanParameters* asan_parameters() const {
 244  E :      return asan_parameters_;
 245  E :    }
 246    :    void set_asan_parameters(
 247  E :        const common::InflatedAsanParameters* asan_parameters) {
 248  E :      asan_parameters_ = asan_parameters;
 249  E :    }
 250    :    // @}
 251    :  
 252    :    // The name of the DLL that is imported by default.
 253    :    static const char kSyzyAsanDll[];
 254    :  
 255    :    // The transform name.
 256    :    static const char kTransformName[];
 257    :  
 258    :    // The hooks stub name.
 259    :    static const char kAsanHookStubName[];
 260    :  
 261    :   protected:
 262    :    // @name PE-specific methods.
 263    :    // @{
 264    :    // Invoked when instrumenting a PE image. Intercepts all relevant import
 265    :    // and statically linked functions found in the image. The intercepts to be
 266    :    // used are exposed for unittesting.
 267    :    bool PeInterceptFunctions(const AsanIntercept* intercepts,
 268    :                              const TransformPolicyInterface* policy,
 269    :                              BlockGraph* block_graph,
 270    :                              BlockGraph::Block* header_block);
 271    :  
 272    :    // Injects runtime parameters into the image.
 273    :    bool PeInjectAsanParameters(const TransformPolicyInterface* policy,
 274    :                                BlockGraph* block_graph,
 275    :                                BlockGraph::Block* header_block);
 276    :    // @}
 277    :  
 278    :    // @name COFF-specific methods.
 279    :    // @{
 280    :    // Invoked when instrumenting a COFF image. Intercepts all relevant functions
 281    :    // via symbol renaming, redirecting to Asan instrumented versions. The
 282    :    // intercepts to be used are exposed for unittesting.
 283    :    bool CoffInterceptFunctions(const AsanIntercept* intercepts,
 284    :                                const TransformPolicyInterface* policy,
 285    :                                BlockGraph* block_graph,
 286    :                                BlockGraph::Block* header_block);
 287    :    // @}
 288    :  
 289    :    // Name of the asan_rtl DLL we import. Defaults to "syzyasan_rtl.dll".
 290    :    std::string asan_dll_name_;
 291    :  
 292    :    // Activate the overwriting of source range for created instructions.
 293    :    bool debug_friendly_;
 294    :  
 295    :    // Set iff we should use the liveness analysis to do smarter instrumentation.
 296    :    bool use_liveness_analysis_;
 297    :  
 298    :    // When activated, a redundancy elimination is performed to minimize the
 299    :    // memory checks added by this transform.
 300    :    bool remove_redundant_checks_;
 301    :  
 302    :    // Set iff we should use the functions interceptors.
 303    :    bool use_interceptors_;
 304    :  
 305    :    // Controls the rate at which reads/writes are instrumented. This is
 306    :    // implemented using random sampling.
 307    :    double instrumentation_rate_;
 308    :  
 309    :    // Asan RTL parameters that will be injected into the instrumented image.
 310    :    // These will be found by the RTL and used to control its behaviour. Allows
 311    :    // for setting parameters at instrumentation time that vary from the defaults.
 312    :    // These can still be overridden by configuring the RTL via an environment
 313    :    // variable.
 314    :    const common::InflatedAsanParameters* asan_parameters_;
 315    :  
 316    :    // References to the different Asan check access import entries. Valid after
 317    :    // successful PreBlockGraphIteration.
 318    :    AsanBasicBlockTransform::AsanHookMap check_access_hooks_ref_;
 319    :  
 320    :    // Block containing any injected runtime parameters. Valid in PE mode after
 321    :    // a successful PostBlockGraphIteration. This is a unittesting seam.
 322    :    block_graph::BlockGraph::Block* asan_parameters_block_;
 323    :  
 324    :   private:
 325    :    DISALLOW_COPY_AND_ASSIGN(AsanTransform);
 326    :  };
 327    :  
 328    :  bool operator<(const AsanBasicBlockTransform::MemoryAccessInfo& left,
 329    :                 const AsanBasicBlockTransform::MemoryAccessInfo& right);
 330    :  
 331    :  }  // namespace transforms
 332    :  }  // namespace instrument
 333    :  
 334    :  #endif  // SYZYGY_INSTRUMENT_TRANSFORMS_ASAN_TRANSFORM_H_

Coverage information generated Thu Mar 26 16:15:41 2015.