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

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
100.0%28280.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    :  // Declaration of the entry thunk instrumentation transform. This instruments
  16    :  // module entry points (DLL and EXE) and individual functions with different
  17    :  // hook functions (provided to the transform). The details as to which
  18    :  // entry points and functions are hooked (and how) can be individually
  19    :  // controlled.
  20    :  //
  21    :  // A generic hook (without a parameter) redirects a call to a thunk of the
  22    :  // form:
  23    :  //
  24    :  //   0x68 0x44 0x33 0x22 0x11       push 0x11223344
  25    :  //   0xff 0x25 0x88 0x77 0x66 0x55  jmp [0x55667788]
  26    :  //
  27    :  // Where 0x11223344 is the address of the original function to be invoked,
  28    :  // and 0x55667788 is the address of the import pointing at the hook to be
  29    :  // invoked. The hook is responsible for cleaning up the stack with a 'ret' so
  30    :  // that 0x11223344 is popped, and control is transferred to the original
  31    :  // function.
  32    :  //
  33    :  // A parameterized hook redirects a call to a thunk of the form:
  34    :  //
  35    :  //   0x68 0xdd 0xcc 0xbb 0xaa       push 0xaabbccdd  ; must be a 32 bit value.
  36    :  //   0x68 0x44 0x33 0x22 0x11       push 0x11223344
  37    :  //   0xff 0x25 0x88 0x77 0x66 0x55  jmp [0x55667788]
  38    :  //
  39    :  // Where 0xaabbccdd is an additional immediate value, the semantics of which
  40    :  // are known to the hook function. The hook is responsible for cleaning up
  41    :  // the stack with a 'ret 4' so that both 0xaabbccdd and 0x11223344 are popped
  42    :  // and control is returned to the original function.
  43    :  //
  44    :  // Prior to executing the thunk the stack is set up as if the call was going to
  45    :  // be directly to the original function.
  46    :  
  47    :  #ifndef SYZYGY_INSTRUMENT_TRANSFORMS_ENTRY_THUNK_TRANSFORM_H_
  48    :  #define SYZYGY_INSTRUMENT_TRANSFORMS_ENTRY_THUNK_TRANSFORM_H_
  49    :  
  50    :  #include <set>
  51    :  #include <string>
  52    :  
  53    :  #include "base/strings/string_piece.h"
  54    :  #include "syzygy/block_graph/basic_block_assembler.h"
  55    :  #include "syzygy/block_graph/iterate.h"
  56    :  #include "syzygy/block_graph/transforms/iterative_transform.h"
  57    :  #include "syzygy/pe/pe_utils.h"
  58    :  
  59    :  namespace instrument {
  60    :  namespace transforms {
  61    :  
  62    :  class EntryThunkTransform
  63    :      : public block_graph::transforms::IterativeTransformImpl<
  64    :          EntryThunkTransform> {
  65    :   public:
  66    :    typedef block_graph::BasicBlockAssembler::Immediate ImmediateType;
  67    :    typedef block_graph::BlockGraph BlockGraph;
  68    :    typedef block_graph::TransformPolicyInterface TransformPolicyInterface;
  69    :  
  70    :    EntryThunkTransform();
  71    :  
  72    :    // @name Accessors.
  73    :    // @{
  74  E :    void set_instrument_unsafe_references(bool instrument) {
  75  E :      instrument_unsafe_references_ = instrument;
  76  E :    }
  77  E :    bool instrument_unsafe_references() const {
  78  E :      return instrument_unsafe_references_;
  79  E :    }
  80    :  
  81  E :    void set_src_ranges_for_thunks(bool src_ranges_for_thunks) {
  82  E :      src_ranges_for_thunks_ = src_ranges_for_thunks;
  83  E :    }
  84  E :    bool src_ranges_for_thunks() const {
  85  E :      return src_ranges_for_thunks_;
  86  E :    }
  87    :  
  88  E :    void set_only_instrument_module_entry(bool only_instrument_module_entry) {
  89  E :      only_instrument_module_entry_ = only_instrument_module_entry;
  90  E :    }
  91    :  
  92  E :    bool only_instrument_module_entry() const {
  93  E :      return only_instrument_module_entry_;
  94  E :    }
  95    :  
  96  E :    void set_instrument_dll_name(const base::StringPiece& instrument_dll_name) {
  97  E :      instrument_dll_name.CopyToString(&instrument_dll_name_);
  98  E :    }
  99    :    const char* instrument_dll_name() const {
 100    :      return instrument_dll_name_.c_str();
 101    :    }
 102    :  
 103  E :    const ImmediateType& entry_thunk_parameter() const {
 104  E :      return entry_thunk_parameter_;
 105  E :    }
 106  E :    const ImmediateType& function_thunk_parameter() const {
 107  E :      return function_thunk_parameter_;
 108  E :    }
 109    :  
 110  E :    BlockGraph::Section* thunk_section() const { return thunk_section_; }
 111    :    // @}
 112    :  
 113    :    // @{
 114    :    // Sets the parameter to be used by entry/function thunks. Only 32-bit
 115    :    // parameters may be used. Set to an invalid parameter (default constructed)
 116    :    // with a size of core::kSizeNone in order to disable parameterized thunks.
 117    :    // @param ImmediateType the parameter to be used.
 118    :    // @returns true if the parameter was accepted, false otherwise.
 119    :    bool SetEntryThunkParameter(const ImmediateType& ImmediateType);
 120    :    bool SetFunctionThunkParameter(const ImmediateType& ImmediateType);
 121    :    // @}
 122    :  
 123    :    // @{
 124    :    // @returns true if the thunk type will be parameterized.
 125    :    bool EntryThunkIsParameterized() const;
 126    :    bool FunctionThunkIsParameterized() const;
 127    :    // @}
 128    :  
 129    :    // The name of the import for general entry hooks.
 130    :    static const char kEntryHookName[];
 131    :    // The name of the import for DllMain-like function entry hooks.
 132    :    static const char kDllMainEntryHookName[];
 133    :    // The name of the import for EXE entry point hook.
 134    :    static const char kExeMainEntryHookName[];
 135    :  
 136    :    // The name of the DLL imported default.
 137    :    static const char kDefaultInstrumentDll[];
 138    :  
 139    :   protected:
 140    :    typedef std::map<BlockGraph::Offset, BlockGraph::Block*> ThunkBlockMap;
 141    :  
 142    :    // @name IterativeTransformImpl implementation.
 143    :    // @{
 144    :    bool PreBlockGraphIteration(const TransformPolicyInterface* policy,
 145    :                                BlockGraph* block_graph,
 146    :                                BlockGraph::Block* header_block);
 147    :    bool OnBlock(const TransformPolicyInterface* policy,
 148    :                 BlockGraph* block_graph,
 149    :                 BlockGraph::Block* block);
 150    :    // @}
 151    :  
 152    :    // Instrument a single block.
 153    :    bool InstrumentCodeBlock(BlockGraph* block_graph, BlockGraph::Block* block);
 154    :  
 155    :    // Instruments a single referrer to a code block.
 156    :    bool InstrumentCodeBlockReferrer(const BlockGraph::Block::Referrer& referrer,
 157    :                                     BlockGraph* block_graph,
 158    :                                     BlockGraph::Block* block,
 159    :                                     ThunkBlockMap* thunk_block_map);
 160    :  
 161    :    // Create a single thunk to destination.
 162    :    // @param block_graph the block-graph being instrumented.
 163    :    // @param destination the destination reference.
 164    :    // @param hook a reference to the hook to use.
 165    :    // @param parameter the parameter to be passed to the thunk. If this is NULL
 166    :    //     then an unparameterized thunk will be created.
 167    :    BlockGraph::Block* CreateOneThunk(BlockGraph* block_graph,
 168    :                                      const BlockGraph::Reference& destination,
 169    :                                      const BlockGraph::Reference& hook,
 170    :                                      const ImmediateType* parameter);
 171    :  
 172    :   private:
 173    :    friend IterativeTransformImpl<EntryThunkTransform>;
 174    :    friend NamedBlockGraphTransformImpl<EntryThunkTransform>;
 175    :  
 176    :    bool GetEntryPoints(BlockGraph::Block* header_block);
 177    :  
 178    :    // For NamedBlockGraphTransformImpl.
 179    :    static const char kTransformName[];
 180    :  
 181    :    // The section we put our thunks in. Valid after successful
 182    :    // PreBlockGraphIteration.
 183    :    BlockGraph::Section* thunk_section_;
 184    :  
 185    :    // References to _indirect_penter and _indirect_penter_dllmain import
 186    :    // entries. Valid after successful PreBlockGraphIteration.
 187    :    BlockGraph::Reference hook_ref_;
 188    :    BlockGraph::Reference hook_dllmain_ref_;
 189    :    BlockGraph::Reference hook_exe_entry_ref_;
 190    :  
 191    :    // Iff true, instrument references with a non-zero offset into the
 192    :    // destination block.
 193    :    bool instrument_unsafe_references_;
 194    :  
 195    :    // Iff true, thunks will be adorned with a source range identifying them
 196    :    // with the function they address. This makes the output more debugging
 197    :    // friendly, at the cost of the uniqueness of address->name resolution.
 198    :    bool src_ranges_for_thunks_;
 199    :  
 200    :    // If true, only instrument DLL entry points.
 201    :    bool only_instrument_module_entry_;
 202    :  
 203    :    // If has a size of 32 bits, then entry thunks will be set up with an extra
 204    :    // parameter on the stack prior to the address of the original function.
 205    :    ImmediateType entry_thunk_parameter_;
 206    :  
 207    :    // If has a size of 32 bits, then function hook thunks will be set up with an
 208    :    // extra parameter on the stack prior to the address of the original function.
 209    :    ImmediateType function_thunk_parameter_;
 210    :  
 211    :    // Name of the instrumentation DLL we import.
 212    :    // Defaults to "call_trace_client.dll".
 213    :    std::string instrument_dll_name_;
 214    :  
 215    :    // This contains the set of entrypoints that have DllMain calling conventions.
 216    :    // These are thunked to the dllmain hook import, instead of the generic
 217    :    // hook import. Valid after successful call to GetEntryPoints.
 218    :    pe::EntryPointSet dllmain_entrypoints_;
 219    :    // If the module being instrumented is an executable, this will hold the
 220    :    // EXE main entry point. Valid after successful call to GetEntryPoints.
 221    :    pe::EntryPoint exe_entry_point_;
 222    :  
 223    :    DISALLOW_COPY_AND_ASSIGN(EntryThunkTransform);
 224    :  };
 225    :  
 226    :  }  // namespace transforms
 227    :  }  // namespace instrument
 228    :  
 229    :  #endif  // SYZYGY_INSTRUMENT_TRANSFORMS_ENTRY_THUNK_TRANSFORM_H_

Coverage information generated Thu Jan 14 17:40:38 2016.