Coverage for /Syzygy/pe/pe_coff_file.h

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

Line-by-line coverage:

   1    :  // Copyright 2013 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    :  // Common definitions and helper routines for reading both PE and COFF
  16    :  // file formats.
  17    :  
  18    :  #ifndef SYZYGY_PE_PE_COFF_FILE_H_
  19    :  #define SYZYGY_PE_PE_COFF_FILE_H_
  20    :  
  21    :  #include <windows.h>
  22    :  #include <winnt.h>
  23    :  #include <map>
  24    :  #include <string>
  25    :  #include <vector>
  26    :  
  27    :  #include "base/files/file_path.h"
  28    :  #include "syzygy/common/buffer_parser.h"
  29    :  #include "syzygy/core/address.h"
  30    :  #include "syzygy/core/address_space.h"
  31    :  #include "syzygy/core/serialization.h"
  32    :  
  33    :  namespace pe {
  34    :  
  35    :  // These duplicate similar constants in the block_graph namespace, declared by
  36    :  // block_graph.h. We duplicate it here so as not to add an uneccessary
  37    :  // dependency.
  38    :  // Header data and other data not from a regular section is considered as
  39    :  // being from an invalid section.
  40    :  const size_t kInvalidSection = SIZE_MAX;
  41    :  const size_t kPointerSize = sizeof(void*);
  42    :  
  43    :  // Base class for PE and COFF file readers, parameterized with an
  44    :  // address and a size type, wrapped in a traits class. The base class
  45    :  // defines an address space, in which data ranges from the input file
  46    :  // should be mapped. The template address and size types define the
  47    :  // resulting address space.
  48    :  //
  49    :  // PECoffFile observes the following address range separation rules:
  50    :  // - All headers live in a single range.
  51    :  // - Each section lives in its own data range.
  52    :  // - Other data may be added by child classes, and live in ranges
  53    :  //   different from the above.
  54    :  //
  55    :  // The address traits class @p AddressSpaceTraits should define the
  56    :  // following members:
  57    :  //
  58    :  // @code
  59    :  // struct AddressSpaceTraits {
  60    :  //   // The type of addresses native to the address space of the reader.
  61    :  //   typedef ... AddressType;
  62    :  //   // The type of sizes native to the address space of the reader.
  63    :  //   typedef ... SizeType;
  64    :  //
  65    :  //   // Return an address different from all valid addresses for the
  66    :  //   // specified address type.
  67    :  //   static const AddressType invalid_address();
  68    :  //
  69    :  //   // Return the address at which to insert global headers.
  70    :  //   static const AddressType header_address();
  71    :  //
  72    :  //   // Return the address where the corresponding section should be
  73    :  //   // mapped, or invalid_address() if the section should not be mapped.
  74    :  //   static AddressType GetSectionAddress(const IMAGE_SECTION_HEADER& header);
  75    :  //
  76    :  //   // Return the number of bytes of the corresponding section to map
  77    :  //   // to the resulting address space.
  78    :  //   static SizeType GetSectionSize(const IMAGE_SECTION_HEADER& header);
  79    :  // };
  80    :  // @endcode
  81    :  //
  82    :  // @tparam AddressSpaceTraits traits describing the types of the
  83    :  // resulting address map.
  84    :  // address map.
  85    :  template <typename AddressSpaceTraits>
  86    :  class PECoffFile {
  87    :   public:
  88    :    // The type of addresses native to this reader.
  89    :    typedef typename AddressSpaceTraits::AddressType AddressType;
  90    :  
  91    :    // The type of sizes native to this reader.
  92    :    typedef typename AddressSpaceTraits::SizeType SizeType;
  93    :  
  94    :    // The type of addresses referring to the on-disk file.
  95    :    typedef core::FileOffsetAddress FileOffsetAddress;
  96    :  
  97    :    // Return the address where the header is expected to be found,
  98    :    // after a successful call to Init().
  99    :    //
 100    :    // @returns the address of the header range.
 101  E :    static AddressType header_address() {
 102  E :      return AddressSpaceTraits::header_address();
 103  E :    }
 104    :  
 105    :    // @returns the path of the input file read, if any.
 106  E :    const base::FilePath& path() const { return path_; }
 107    :  
 108    :    // Copy mapped data to buffer. The specified range to read must be
 109    :    // contained within the image, and cannot cross data ranges from the
 110    :    // original file; in particular, sections with no gaps between them
 111    :    // must still be read separately.
 112    :    //
 113    :    // @param addr the address where the data is mapped.
 114    :    // @param data the buffer to write the data to.
 115    :    // @param len the number of bytes to copy.
 116    :    // @returns true on success, false on error.
 117    :    bool ReadImage(AddressType addr, void* data, SizeType len) const;
 118    :  
 119    :    // Copy mapped zero-terminated string data to string object.
 120    :    //
 121    :    // @param addr the address where the data is mapped.
 122    :    // @param str the string to write the data to.
 123    :    // @returns true on success, false on error.
 124    :    bool ReadImageString(AddressType addr, std::string* str) const;
 125    :  
 126    :    // Retrieve a pointer to the internal buffer containing image data. If the
 127    :    // specified range to read is not wholly contained within the image this will
 128    :    // return nullptr. This allows reading across arbitrary section boundaries,
 129    :    // and also allows reading "unmapped" data.
 130    :    //
 131    :    // @param addr the address of the data.
 132    :    // @param len the number of bytes that will be accessed through the
 133    :    //     returned pointer.
 134    :    // @returns a pointer into the internal buffer for the data, nullptr on
 135    :    //     failure.
 136    :    const uint8_t* GetImageDataByFileOffset(FileOffsetAddress addr,
 137    :                                            SizeType len) const;
 138    :  
 139    :    // Retrieve a pointer to the internal buffer containing mapped
 140    :    // data. The specified range to read must be contained within the
 141    :    // image, and cannot cross data ranges from the original file; in
 142    :    // particular, sections with no gaps between them must still be read
 143    :    // separately.
 144    :    //
 145    :    // @param addr the address where the data is mapped.
 146    :    // @param len the number of bytes that will be accessed through the
 147    :    // returned pointer.
 148    :    // @returns a pointer into the internal buffer for the data.
 149    :    const uint8_t* GetImageData(AddressType addr, SizeType len) const;
 150    :  
 151    :    // @copydoc GetImageData(AddressType,SizeType)
 152    :    // The resulting buffer is mutable.
 153    :    uint8_t* GetImageData(AddressType addr, SizeType len);
 154    :  
 155    :    // Retrieve a pointer to the internal buffer containing mapped
 156    :    // data assumed to be of type @p ItemType.
 157    :    //
 158    :    // @tparam ItemType the type of items to cast to.
 159    :    // @param addr the address where the data is mapped.
 160    :    // @param len the number of bytes that will be accessed through the
 161    :    // returned pointer.
 162    :    // @param item_ptr a pointer to the retrieved result.
 163    :    // @returns true on success, false on error.
 164    :    // @see GetImageData(AddressType,SizeType)
 165    :    template <typename ItemType> bool GetImageData(
 166    :        AddressType addr, SizeType len, const ItemType** item_ptr) const;
 167    :  
 168    :    // @copydoc GetImageData()
 169    :    // The resulting buffer is mutable.
 170    :    template <typename ItemType> bool GetImageData(
 171    :        AddressType addr, SizeType len, ItemType** item_ptr);
 172    :  
 173    :    // Test whether an address range is entirely mapped.
 174    :    //
 175    :    // @param addr the start of the address range.
 176    :    // @param len the length of the address range.
 177    :    // @returns true if the range is mapped, false otherwise.
 178    :    bool Contains(AddressType addr, SizeType len) const;
 179    :  
 180    :    // Retrieve the index of the section containing the specified range.
 181    :    //
 182    :    // @param addr the start of the address range.
 183    :    // @param len the length of the address range.
 184    :    // @returns the section index, or kInvalidSection if none is found.
 185    :    size_t GetSectionIndex(AddressType addr, SizeType len) const;
 186    :  
 187    :    // Retrieve the section header structure of the section containing
 188    :    // the specified range.
 189    :    //
 190    :    // @param addr the start of the address range.
 191    :    // @param len the length of the address range.
 192    :    // @returns the section header, or NULL if none is found.
 193    :    const IMAGE_SECTION_HEADER* GetSectionHeader(AddressType addr,
 194    :                                                 SizeType len) const;
 195    :  
 196    :    // Retrieve the short name of a section from its index.
 197    :    //
 198    :    // @param section_index the index of the section.
 199    :    // @returns the name of the section.
 200    :    std::string GetSectionName(size_t section_index) const;
 201    :  
 202    :    // Read the short name embedded in @p section.
 203    :    //
 204    :    // @param section the section header to read.
 205    :    // @returns the short name of the section.
 206    :    static std::string GetSectionName(const IMAGE_SECTION_HEADER& section);
 207    :  
 208    :    // @returns the COFF file header.
 209  E :    const IMAGE_FILE_HEADER* file_header() const {
 210  E :      return file_header_;
 211  E :    }
 212    :  
 213    :    // @returns an array of all section headers.
 214    :    // @note Use in combination with the NumberOfSections field of the
 215    :    // COFF file header.
 216  E :    const IMAGE_SECTION_HEADER* section_headers() const {
 217  E :      return section_headers_;
 218  E :    }
 219    :  
 220    :    // Retrieve the section header structure of a section from its index.
 221    :    //
 222    :    // @param num_section the index of the section.
 223    :    // @returns a pointer to the header structure.
 224  E :    const IMAGE_SECTION_HEADER* section_header(size_t num_section) const {
 225  E :      if (file_header_ != NULL && num_section < file_header_->NumberOfSections)
 226  E :        return section_headers_ + num_section;
 227  E :      return NULL;
 228  E :    }
 229    :  
 230    :   protected:
 231    :    struct SectionInfo {
 232    :      SectionInfo() : id(kInvalidSection), parser(nullptr, 0) {}
 233    :      SectionInfo(size_t id, const void* data, size_t length)
 234  E :          : id(id), parser(data, length) {}
 235    :      size_t id;
 236    :      common::BinaryBufferParser parser;
 237    :    };
 238    :  
 239    :    typedef core::AddressSpace<AddressType, SizeType, SectionInfo>
 240    :        ImageAddressSpace;
 241    :  
 242    :    // Protected constructor, for derived classes only.
 243    :    PECoffFile()
 244  E :        : file_header_(NULL),
 245  E :          section_headers_(NULL) {
 246  E :    }
 247    :  
 248  E :    ~PECoffFile() {
 249  E :    }
 250    :  
 251    :    // Set the file path and read all of its data.
 252    :    //
 253    :    // @param path the path to the input file.
 254    :    // @returns true on success, false on failure.
 255    :    bool Init(const base::FilePath& path);
 256    :  
 257    :    // Read headers common to both PE and COFF. Insert a range covering
 258    :    // all headers, including unread headers; the range spans from the
 259    :    // beginning of the file to the end of the known fixed headers (the
 260    :    // section table).
 261    :    //
 262    :    // @param file_header_start the offset where the COFF file header
 263    :    // (IMAGE_FILE_HEADER) starts.
 264    :    // @returns true on success, false on error.
 265    :    bool ReadCommonHeaders(FileOffsetAddress file_header_start);
 266    :  
 267    :    // Read section headers and insert a range for each section.
 268    :    //
 269    :    // @returns true on success, false on error.
 270    :    bool ReadSections();
 271    :  
 272    :    // Insert a section into the address map, backed by data in image_data_.
 273    :    //
 274    :    // @param id the id of the section.
 275    :    // @param start the file offset to start reading at.
 276    :    // @param size the number of bytes to read.
 277    :    // @param range the range to insert.
 278    :    // @returns true on success, false on error.
 279    :    bool InsertSection(size_t id,
 280    :                       FileOffsetAddress start,
 281    :                       size_t size,
 282    :                       const typename ImageAddressSpace::Range& range);
 283    :  
 284    :    // Reads data from the file at the given offset.
 285    :    //
 286    :    // @param offset the offset to read.
 287    :    // @param destination the variable to be populated with the result.
 288    :    // @param size the number of bytes to read.
 289    :    // @returns true on success, false otherwise.
 290    :    bool ReadAt(size_t offset, void* destination, size_t size) const;
 291    :  
 292    :    base::FilePath path_;
 293    :    const IMAGE_FILE_HEADER* file_header_;
 294    :    const IMAGE_SECTION_HEADER* section_headers_;
 295    :  
 296    :    // Contains all of the data in the image, as a single contiguous buffer.
 297    :    std::string image_data_;
 298    :  
 299    :    // A parser for the image data. This takes care of bounds and alignment
 300    :    // checking.
 301    :    common::BinaryBufferParser parser_;
 302    :  
 303    :    // Contains all addressable data in the image. The address space has a range
 304    :    // defined for the header and each section in the image, backed by data in
 305    :    // |image_data_|.
 306    :    ImageAddressSpace address_space_;
 307    :  
 308    :   private:
 309    :    DISALLOW_COPY_AND_ASSIGN(PECoffFile);
 310    :  };
 311    :  
 312    :  }  // namespace pe
 313    :  
 314    :  #include "syzygy/pe/pe_coff_file_impl.h"
 315    :  
 316    :  #endif  // SYZYGY_PE_PE_COFF_FILE_H_

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