Coverage for /Syzygy/pe/pe_relinker.h

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
100.0%36360.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 PERelinker. Relinking can be seen as decomposing an input image,
  16    :  // applying a sequence of block-graph transforms (some applied implicitly, and
  17    :  // others provided by the user), followed by a sequence of orderers (again, some
  18    :  // implicit, some provided by the user), laying-out, finalizing and finally
  19    :  // writing a new image. After writing the image a similar transformation
  20    :  // workflow is applied to the corresponding PDB file, consisting of applying
  21    :  // any user defined PDB mutations, followed by 2-3 (depending on PeRelinker
  22    :  // configuration) internal mutations (updating the GUID/age, adding the history
  23    :  // stream and adding the serialized block-graph stream). PERelinker encapsulates
  24    :  // this workflow.
  25    :  //
  26    :  // It is intended to be used as follows:
  27    :  //
  28    :  //   PERelinker relinker;
  29    :  //   relinker.set_input_path(...);  // Required.
  30    :  //   relinker.set_output_path(...);  // Required.
  31    :  //   relinker.set_input_pdb_path(...);  // Optional.
  32    :  //   relinker.set_output_pdb_path(...);  // Optional.
  33    :  //   relinker.Init();  // Check the return value!
  34    :  //
  35    :  //   // At this point, the following accessors are valid:
  36    :  //   relinker.input_pe_file();
  37    :  //   relinker.input_image_layout();
  38    :  //   relinker.block_graph();
  39    :  //   relinker.dos_header_block();
  40    :  //   relinker.output_guid();
  41    :  //
  42    :  //   relinker.AppendTransform(...);  // May be called repeatedly.
  43    :  //   relinker.AppendOrderer(...);  // May be called repeatedly.
  44    :  //   relinker.AppendPdbMutator(...);  // May be called repeatedly.
  45    :  //
  46    :  //   relinker.Relink();  // Check the return value!
  47    :  //
  48    :  // NOTE: This split workflow is only necessary as a workaround to deal with
  49    :  //     transforms and orderers built around legacy code. Intermediate
  50    :  //     representations of serialized data-structures should be stored in such
  51    :  //     a way so as not to explicitly require access to the untransformed image.
  52    :  //     Additionally, for checking validity a transform or orderer should require
  53    :  //     no more than the PESignature associated with the original module, and/or
  54    :  //     the toolchain metadata present in the module, if there was any.
  55    :  //
  56    :  // TODO(chrisha): Resimplify this API once Reorderer has been reworked to move
  57    :  //     away from Block pointers.
  58    :  
  59    :  #ifndef SYZYGY_PE_PE_RELINKER_H_
  60    :  #define SYZYGY_PE_PE_RELINKER_H_
  61    :  
  62    :  #include <vector>
  63    :  
  64    :  #include "base/files/file_path.h"
  65    :  #include "syzygy/block_graph/orderer.h"
  66    :  #include "syzygy/block_graph/transform.h"
  67    :  #include "syzygy/pdb/pdb_mutator.h"
  68    :  #include "syzygy/pe/image_layout.h"
  69    :  #include "syzygy/pe/pe_coff_relinker.h"
  70    :  #include "syzygy/pe/pe_file.h"
  71    :  #include "syzygy/pe/pe_transform_policy.h"
  72    :  
  73    :  namespace pe {
  74    :  
  75    :  // Embodies a transformation on a PE image, from decomposing an original image
  76    :  // to applying some transform(s) to it, to generating the layout and finally
  77    :  // writing the image and accompanying PDB to disk.
  78    :  //
  79    :  // Creating a PERelinker and not changing its default configuration yields
  80    :  // an identity relinker that will produce an identical (nearly, except for
  81    :  // cosmetic differences in some headers) image to the input. If no orderers
  82    :  // are specified the default original orderer will be applied. If, in
  83    :  // addition, no transforms have been added this effectively makes the entire
  84    :  // relinker an identity relinker.
  85    :  //
  86    :  // The workflow is as follows:
  87    :  //
  88    :  // 1. Relinker created with an input image. The PDB file is found automatically
  89    :  //    and the image is decomposed. Optionally the PDB may be directly specified.
  90    :  // 2. The image is transformed:
  91    :  //    a) Transforms provided by the user are applied.
  92    :  //    b) AddMetadataTransform is conditionally applied.
  93    :  //    c) AddPdbInfoTransform is applied.
  94    :  //    d) PrepareHeadersTransform is applied.
  95    :  // 3. The image is ordered:
  96    :  //    a) Orderers provided by the user are applied.
  97    :  //    b) PEOrderer is applied.
  98    :  // 4. PEImageLayoutBuilder is used to convert the OrderedBlockGraph to an
  99    :  //    ImageLayout.
 100    :  // 5. Image and accompanying PDB file are written. (Filenames are inferred from
 101    :  //    input filenames or directly specified.)
 102    :  class PERelinker : public PECoffRelinker {
 103    :   public:
 104    :    // Constructor.
 105    :    // @param pe_transform_policy The policy that dictates how to apply
 106    :    //     transforms.
 107    :    explicit PERelinker(const PETransformPolicy* pe_transform_policy);
 108    :  
 109    :    // @see RelinkerInterface::image_format()
 110  E :    virtual ImageFormat image_format() const override {
 111  E :      return BlockGraph::PE_IMAGE;
 112  E :    }
 113    :  
 114    :    // @name Accessors.
 115    :    // @{
 116  E :    const base::FilePath& input_pdb_path() const { return input_pdb_path_; }
 117  E :    const base::FilePath& output_pdb_path() const { return output_pdb_path_; }
 118  E :    bool add_metadata() const { return add_metadata_; }
 119  E :    bool augment_pdb() const { return augment_pdb_; }
 120  E :    bool compress_pdb() const { return compress_pdb_; }
 121  E :    bool strip_strings() const { return strip_strings_; }
 122  E :    size_t padding() const { return padding_; }
 123  E :    size_t code_alignment() const { return code_alignment_; }
 124    :    // @}
 125    :  
 126    :    // @name Mutators for controlling relinker behaviour.
 127    :    // @{
 128  E :    void set_input_pdb_path(const base::FilePath& input_pdb_path) {
 129  E :      input_pdb_path_ = input_pdb_path;
 130  E :    }
 131  E :    void set_output_pdb_path(const base::FilePath& output_pdb_path) {
 132  E :      output_pdb_path_ = output_pdb_path;
 133  E :    }
 134  E :    void set_add_metadata(bool add_metadata) {
 135  E :      add_metadata_ = add_metadata;
 136  E :    }
 137  E :    void set_augment_pdb(bool augment_pdb) {
 138  E :      augment_pdb_ = augment_pdb;
 139  E :    }
 140  E :    void set_compress_pdb(bool compress_pdb) {
 141  E :      compress_pdb_ = compress_pdb;
 142  E :    }
 143  E :    void set_strip_strings(bool strip_strings) {
 144  E :      strip_strings_ = strip_strings;
 145  E :    }
 146  E :    void set_padding(size_t padding) {
 147  E :      padding_ = padding;
 148  E :    }
 149  E :    void set_code_alignment(size_t alignment) {
 150  E :      code_alignment_ = alignment;
 151  E :    }
 152    :    // @}
 153    :  
 154    :    // @see RelinkerInterface::AppendPdbMutator()
 155    :    virtual bool AppendPdbMutator(pdb::PdbMutatorInterface* pdb_mutator) override;
 156    :  
 157    :    // @see RelinkerInterface::AppendPdbMutators()
 158    :    virtual bool AppendPdbMutators(
 159    :        const std::vector<pdb::PdbMutatorInterface*>& pdb_mutators) override;
 160    :  
 161    :    // Runs the initialization phase of the relinker. This consists of decomposing
 162    :    // the input image, after which the intermediate data accessors declared below
 163    :    // become valid. This should typically be followed by a call to Relink.
 164    :    //
 165    :    // @returns true on success, false otherwise.
 166    :    // @pre input_path and output_path must be set prior to calling this.
 167    :    //     input_pdb_path and output_pdb_path may optionally have been set prior
 168    :    //     to calling this.
 169    :    // @post input_pe_file and input_image_layout may be called after this.
 170    :    // @note This entrypoint is virtual for unittest/mocking purposes.
 171    :    virtual bool Init() override;
 172    :  
 173    :    // Runs the relinker, generating an output image and PDB.
 174    :    //
 175    :    // @returns true on success, false otherwise.
 176    :    // @pre Init must have been called successfully.
 177    :    // @note This entrypoint is virtual for unittest/mocking purposes.
 178    :    virtual bool Relink() override;
 179    :  
 180    :    // @name Intermediate data accessors.
 181    :    // @{
 182    :    // These accessors only return meaningful data after Init has been called. By
 183    :    // the time any transforms or orderers are being called, these will contain
 184    :    // valid data.
 185    :    //
 186    :    // TODO(chrisha): Clean these up as part of the API simplification after
 187    :    //     all legacy code has been refactored.
 188    :    //
 189    :    // @pre Init has been successfully called.
 190  E :    const PEFile& input_pe_file() const { return input_pe_file_; }
 191    :    const GUID& output_guid() const { return output_guid_; }
 192    :    // @}
 193    :  
 194    :   protected:
 195    :    // The transform policy used by this relinker.
 196    :    const PETransformPolicy* pe_transform_policy_;
 197    :  
 198    :    base::FilePath input_pdb_path_;
 199    :    base::FilePath output_pdb_path_;
 200    :  
 201    :    // If true, metadata will be added to the output image. Defaults to true.
 202    :    bool add_metadata_;
 203    :    // If true, the PDB will be augmented with a serialized block-graph and
 204    :    // image layout. Defaults to true.
 205    :    bool augment_pdb_;
 206    :    // If true, then the augmented PDB stream will be compressed as it is written.
 207    :    // Defaults to false.
 208    :    bool compress_pdb_;
 209    :    // If true, strings associated with a block-graph will not be serialized into
 210    :    // the PDB. Defaults to false.
 211    :    bool strip_strings_;
 212    :    // Indicates the amount of padding to be added between blocks. Zero is the
 213    :    // default value and indicates no padding will be added.
 214    :    size_t padding_;
 215    :    // Minimal code block alignment.
 216    :    size_t code_alignment_;
 217    :  
 218    :    // The vectors of user supplied transforms, orderers and mutators to be
 219    :    // applied.
 220    :    std::vector<pdb::PdbMutatorInterface*> pdb_mutators_;
 221    :  
 222    :    // Intermediate variables that are initialized and used by Relink. They are
 223    :    // made externally accessible so that transforms and orderers may make use
 224    :    // of them if necessary.
 225    :  
 226    :    // These refer to the original image, and don't change after init.
 227    :    PEFile input_pe_file_;
 228    :  
 229    :    // These are for the new image that will be produced at the end of Relink.
 230    :    GUID output_guid_;
 231    :  };
 232    :  
 233    :  }  // namespace pe
 234    :  
 235    :  #endif  // SYZYGY_PE_PE_RELINKER_H_

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