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

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