Coverage for /Syzygy/pe/decomposer.h

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
100.0%220.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    :  // Declares the decomposer, which decomposes a PE file into an ImageLayout and
  16    :  // its corresponding BlockGraph.
  17    :  
  18    :  #ifndef SYZYGY_PE_DECOMPOSER_H_
  19    :  #define SYZYGY_PE_DECOMPOSER_H_
  20    :  
  21    :  #include <windows.h>  // NOLINT
  22    :  #include <dia2.h>
  23    :  #include <vector>
  24    :  
  25    :  #include "syzygy/common/binary_stream.h"
  26    :  #include "syzygy/pdb/pdb_file.h"
  27    :  #include "syzygy/pdb/pdb_stream.h"
  28    :  #include "syzygy/pe/dia_browser.h"
  29    :  #include "syzygy/pe/image_layout.h"
  30    :  #include "syzygy/pe/pe_file.h"
  31    :  
  32    :  namespace pe {
  33    :  
  34    :  // Forward declaration of a helper class where we hide our implementation
  35    :  // details.
  36    :  class DecomposerImpl;
  37    :  
  38    :  class Decomposer {
  39    :   public:
  40    :    struct IntermediateReference;
  41    :    typedef std::vector<IntermediateReference> IntermediateReferences;
  42    :  
  43    :    // The separator that is used between the multiple symbol names that can be
  44    :    // associated with a single label.
  45    :    static const char kLabelNameSep[];
  46    :  
  47    :    // Initialize the decomposer for a given image file.
  48    :    // @param image_file the image file to decompose. This must outlive the
  49    :    //     instance of the decomposer.
  50    :    explicit Decomposer(const PEFile& image_file);
  51    :  
  52    :    // Decomposes the image file into a BlockGraph and an ImageLayout, which
  53    :    // have the breakdown of code and data blocks with typed references and
  54    :    // information on where the blocks resided in the original image,
  55    :    // respectively.
  56    :    // @returns true on success, false on failure.
  57    :    bool Decompose(ImageLayout* image_layout);
  58    :  
  59    :    // @name Mutators.
  60    :    // @{
  61    :    // Sets the PDB path to be used. If this is not called it will be inferred
  62    :    // using the information in the module, and searched for using the OS
  63    :    // search functionality.
  64    :    // @param pdb_path the path to the PDB file to be used in decomposing the
  65    :    //     image.
  66  E :    void set_pdb_path(const base::FilePath& pdb_path) { pdb_path_ = pdb_path; }
  67    :    // @}
  68    :  
  69    :    // @name Accessors
  70    :    // @{
  71    :    // Accessor to the PDB path. If Decompose has been called successfully this
  72    :    // will reflect the path of the PDB file that was used to perform the
  73    :    // decomposition.
  74    :    // @returns the PDB path.
  75  E :    const base::FilePath& pdb_path() const { return pdb_path_; }
  76    :    // @}
  77    :  
  78    :   protected:
  79    :    typedef block_graph::BlockGraph BlockGraph;
  80    :    typedef core::RelativeAddress RelativeAddress;
  81    :  
  82    :    // Searches for (if necessary) the PDB file to be used in the decomposition,
  83    :    // and validates that the file exists and matches the module.
  84    :    bool FindAndValidatePdbPath();
  85    :  
  86    :    // @name Used for round-trip decomposition when a serialized block graph is
  87    :    //     in the PDB. Exposed here for unittesting.
  88    :    // @{
  89    :    static bool LoadBlockGraphFromPdbStream(const PEFile& image_file,
  90    :                                            pdb::PdbStream* block_graph_stream,
  91    :                                            ImageLayout* image_layout);
  92    :    static bool LoadBlockGraphFromPdb(const base::FilePath& pdb_path,
  93    :                                      const PEFile& image_file,
  94    :                                      ImageLayout* image_layout,
  95    :                                      bool* stream_exists);
  96    :    // @}
  97    :  
  98    :    // @name Decomposition steps, in order.
  99    :    // @{
 100    :    // Performs the actual decomposition.
 101    :    bool DecomposeImpl();
 102    :    // Parses PE-related blocks and references.
 103    :    bool CreatePEImageBlocksAndReferences(IntermediateReferences* references);
 104    :    // Creates blocks from the COFF group symbols in the linker symbol stream.
 105    :    bool CreateBlocksFromCoffGroups();
 106    :    // Processes the SectionContribution table, creating code/data blocks from it.
 107    :    bool CreateBlocksFromSectionContribs(IDiaSession* session);
 108    :   // Processes the Compiland table and finds cold blocks.
 109    :    bool FindColdBlocksFromCompilands(IDiaSession* session);
 110    :    // Creates gap blocks to flesh out the image. After this has been run all
 111    :    // references should be resolvable.
 112    :    bool CreateGapBlocks();
 113    :    // Finalizes the given vector of intermediate references.
 114    :    bool FinalizeIntermediateReferences(const IntermediateReferences& references);
 115    :    // Creates inter-block references from fixups.
 116    :    bool CreateReferencesFromFixups(IDiaSession* session);
 117    :    // Processes symbols from the PDB, setting block names and labels. This
 118    :    // step is purely optional and only necessary to provide debug information.
 119    :    // This adds names to blocks, adds code labels and their names, and adds
 120    :    // more informative names to data labels.
 121    :    bool ProcessSymbols(IDiaSymbol* root);
 122    :    // @}
 123    :  
 124    :    // @{
 125    :    // @name Callbacks and context structures used by the COFF group parsing
 126    :    //     mechanism.
 127    :    struct VisitLinkerSymbolContext;
 128    :    bool VisitLinkerSymbol(VisitLinkerSymbolContext* context,
 129    :                           uint16_t symbol_length,
 130    :                           uint16_t symbol_type,
 131    :                           common::BinaryStreamReader* reader);
 132    :    // @}
 133    :  
 134    :    // @{
 135    :    // @name Callbacks used when parsing DIA symbols. Symbols only need to be
 136    :    //     parsed for debug information and can be completely ignored otherwise.
 137    :    DiaBrowser::BrowserDirective OnPushFunctionOrThunkSymbol(
 138    :        const DiaBrowser& dia_browser,
 139    :        const DiaBrowser::SymTagVector& sym_tags,
 140    :        const DiaBrowser::SymbolPtrVector& symbols);
 141    :    DiaBrowser::BrowserDirective OnPopFunctionOrThunkSymbol(
 142    :        const DiaBrowser& dia_browser,
 143    :        const DiaBrowser::SymTagVector& sym_tags,
 144    :        const DiaBrowser::SymbolPtrVector& symbols);
 145    :    DiaBrowser::BrowserDirective OnFunctionChildSymbol(
 146    :        const DiaBrowser& dia_browser,
 147    :        const DiaBrowser::SymTagVector& sym_tags,
 148    :        const DiaBrowser::SymbolPtrVector& symbols);
 149    :    DiaBrowser::BrowserDirective OnDataSymbol(
 150    :        const DiaBrowser& dia_browser,
 151    :        const DiaBrowser::SymTagVector& sym_tags,
 152    :        const DiaBrowser::SymbolPtrVector& symbols);
 153    :    DiaBrowser::BrowserDirective OnPublicSymbol(
 154    :        const DiaBrowser& dia_browser,
 155    :        const DiaBrowser::SymTagVector& sym_tags,
 156    :        const DiaBrowser::SymbolPtrVector& symbols);
 157    :    DiaBrowser::BrowserDirective OnLabelSymbol(
 158    :        const DiaBrowser& dia_browser,
 159    :        const DiaBrowser::SymTagVector& sym_tags,
 160    :        const DiaBrowser::SymbolPtrVector& symbols);
 161    :    // @}
 162    :  
 163    :    // @name These are called within the scope of OnFunctionChildSymbol, during
 164    :    //     which current_block_ is always set.
 165    :    // @{
 166    :    DiaBrowser::BrowserDirective OnScopeSymbol(enum SymTagEnum type,
 167    :                                               DiaBrowser::SymbolPtr symbol);
 168    :    DiaBrowser::BrowserDirective OnCallSiteSymbol(DiaBrowser::SymbolPtr symbol);
 169    :    // @}
 170    :  
 171    :    // @name Block creation members.
 172    :    // @{
 173    :    // Creates a new block with the given properties, and attaches the
 174    :    // data to it. This assumes that no conflicting block exists.
 175    :    BlockGraph::Block* CreateBlock(BlockGraph::BlockType type,
 176    :                                   RelativeAddress address,
 177    :                                   BlockGraph::Size size,
 178    :                                   const base::StringPiece& name);
 179    :    // Creates a new block with the given properties, or finds an existing PE
 180    :    // parsed block that subsumes it.
 181    :    BlockGraph::Block* CreateBlockOrFindCoveringPeBlock(
 182    :        BlockGraph::BlockType type,
 183    :        RelativeAddress address,
 184    :        BlockGraph::Size size,
 185    :        const base::StringPiece& name);
 186    :    // Creates a gap block of type @p block_type for the given range. For use by
 187    :    // CreateSectionGapBlocks.
 188    :    bool CreateGapBlock(BlockGraph::BlockType block_type,
 189    :                        RelativeAddress address,
 190    :                        BlockGraph::Size size);
 191    :    // Create blocks of type @p block_type for any gaps in the image
 192    :    // section represented by @p header.
 193    :    bool CreateSectionGapBlocks(const IMAGE_SECTION_HEADER* header,
 194    :                                BlockGraph::BlockType block_type);
 195    :    // @}
 196    :  
 197    :    // The PEFile that is being decomposed.
 198    :    const PEFile& image_file_;
 199    :    // The path to corresponding PDB file.
 200    :    base::FilePath pdb_path_;
 201    :  
 202    :    // @name Temporaries that are only valid while inside DecomposeImpl.
 203    :    //     Prevents us from having to pass these around everywhere.
 204    :    // @{
 205    :    // The image layout we're building.
 206    :    ImageLayout* image_layout_;
 207    :    // The image address space we're decomposing to.
 208    :    BlockGraph::AddressSpace* image_;
 209    :    // @}
 210    :  
 211    :    // Data structures holding the relation between functions and their cold
 212    :    // blocks outside of the function address space.
 213    :    // @{
 214    :    typedef std::map<core::RelativeAddress, BlockGraph::Block*> ColdBlocks;
 215    :    typedef std::map<BlockGraph::Block*, ColdBlocks> ColdBlocksMap;
 216    :    typedef std::map<BlockGraph::Block*, BlockGraph::Block*> ColdBlocksParent;
 217    :    ColdBlocksMap cold_blocks_;
 218    :    ColdBlocksParent cold_blocks_parent_;
 219    :    // @}
 220    :  
 221    :    // @name Temporaries that are only valid while in DiaBrowser.
 222    :    // @{
 223    :    BlockGraph::Block* current_block_;
 224    :    RelativeAddress current_address_;
 225    :    size_t current_scope_count_;
 226    :    // @}
 227    :  };
 228    :  
 229    :  }  // namespace pe
 230    :  
 231    :  #endif  // SYZYGY_PE_DECOMPOSER_H_

Coverage information generated Fri Jul 29 11:00:21 2016.