Coverage for /Syzygy/pe/pe_file.h

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
100.0%39390.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    :  #ifndef SYZYGY_PE_PE_FILE_H_
  16    :  #define SYZYGY_PE_PE_FILE_H_
  17    :  
  18    :  #include <windows.h>
  19    :  #include <winnt.h>
  20    :  #include <map>
  21    :  #include <set>
  22    :  #include <string>
  23    :  #include <vector>
  24    :  
  25    :  #include "base/files/file_path.h"
  26    :  #include "sawbuck/sym_util/types.h"
  27    :  #include "syzygy/core/address.h"
  28    :  #include "syzygy/core/address_space.h"
  29    :  #include "syzygy/core/serialization.h"
  30    :  #include "syzygy/pe/pe_coff_file.h"
  31    :  
  32    :  namespace pe {
  33    :  
  34    :  // Traits of the PE address space.
  35    :  struct PEAddressSpaceTraits {
  36    :    // Native addresses for PE files: relative virtual addresses (RVAs).
  37    :    typedef core::RelativeAddress AddressType;
  38    :  
  39    :    // Native sizes for PE files.
  40    :    typedef size_t SizeType;
  41    :  
  42    :    // @returns an address different from all valid addresses for the
  43    :    // specified address type.
  44  E :    static const AddressType invalid_address() {
  45  E :      return AddressType::kInvalidAddress;
  46  E :    }
  47    :  
  48    :    // @returns the address at which to insert global headers.
  49  E :    static const AddressType header_address() {
  50  E :      return AddressType(0);
  51  E :    }
  52    :  
  53    :    // Return the RVA to which the section will be mapped when the
  54    :    // program is loaded.
  55    :    //
  56    :    // @param header the section header.
  57    :    // @returns the RVA of the section.
  58  E :    static AddressType GetSectionAddress(const IMAGE_SECTION_HEADER& header) {
  59  E :      return AddressType(header.VirtualAddress);
  60  E :    }
  61    :  
  62    :    // Return the number of bytes that will be occupied by the section
  63    :    // when the program is loaded, including any run-time padding.
  64    :    //
  65    :    // @param header the section header.
  66    :    // @returns the run-time size of the section.
  67  E :    static SizeType GetSectionSize(const IMAGE_SECTION_HEADER& header) {
  68  E :      return SizeType(header.Misc.VirtualSize);
  69  E :    }
  70    :  };
  71    :  
  72    :  // A raw, sparse, representation of a PE file. It offers a view of the
  73    :  // contents of the file as would be mapped into memory, if the program
  74    :  // were loaded.
  75    :  class PEFile : public PECoffFile<PEAddressSpaceTraits> {
  76    :   public:
  77    :    struct Signature;
  78    :  
  79    :    typedef core::AbsoluteAddress AbsoluteAddress;
  80    :    typedef core::FileOffsetAddress FileOffsetAddress;
  81    :    typedef core::RelativeAddress RelativeAddress;
  82    :  
  83    :    // A set of locations in the RVA address space where an address is
  84    :    // present and needs to be relocated.
  85    :    typedef std::set<RelativeAddress> RelocSet;
  86    :  
  87    :    // A map from locations in the RVA address space where an address is
  88    :    // present and needs to be relocated, to the absolute addresses they
  89    :    // refer to.
  90    :    typedef std::map<RelativeAddress, AbsoluteAddress> RelocMap;
  91    :  
  92    :    // Information about a single export.
  93    :    struct ExportInfo;
  94    :    typedef std::vector<ExportInfo> ExportInfoVector;
  95    :  
  96    :    // Information about a single import.
  97    :    struct ImportInfo;
  98    :    typedef std::vector<ImportInfo> ImportInfoVector;
  99    :  
 100    :    // Information about all imports for a given DLL.
 101    :    struct ImportDll;
 102    :    typedef std::vector<ImportDll> ImportDllVector;
 103    :  
 104    :    // Allow overloading of the following functions inherited from
 105    :    // PECoffFile.
 106    :    using PECoffFile<PEAddressSpaceTraits>::ReadImage;
 107    :    using PECoffFile<PEAddressSpaceTraits>::ReadImageString;
 108    :    using PECoffFile<PEAddressSpaceTraits>::GetImageData;
 109    :    using PECoffFile<PEAddressSpaceTraits>::Contains;
 110    :    using PECoffFile<PEAddressSpaceTraits>::GetSectionIndex;
 111    :    using PECoffFile<PEAddressSpaceTraits>::GetSectionHeader;
 112    :  
 113    :    // Construct a PEFile object not yet bound to any file.
 114    :    PEFile();
 115    :  
 116    :    // Destroy this PEFile object, invalidating all pointers obtained
 117    :    // through GetImageData(), or headers returned by corresponding
 118    :    // accessor methods.
 119    :    ~PEFile();
 120    :  
 121    :    // Read in the image file at @p path, making its data
 122    :    // available. A PE file reader may only read a single file.
 123    :    //
 124    :    // @param path the path to the file to read.
 125    :    // @returns true on success, false on error.
 126    :    bool Init(const base::FilePath& path);
 127    :  
 128    :    // Retrieve the signature of this PE file. May only be called after
 129    :    // a file has been read with Init().
 130    :    //
 131    :    // @param signature the object to copy the signature to.
 132    :    void GetSignature(Signature* signature) const;
 133    :  
 134    :    // Decode relocation information from the image, inserting the
 135    :    // results into @p relocs.
 136    :    //
 137    :    // TODO(siggi): Consider folding this member into ReadRelocs.
 138    :    //
 139    :    // @param relocs the set to which relocations are to be added.
 140    :    // @returns true on success, false on error.
 141    :    bool DecodeRelocs(RelocSet* relocs) const;
 142    :  
 143    :    // Retrieve relocation target addresses for the specified set of
 144    :    // relocations.
 145    :    //
 146    :    // @param relocs the set of relocations to look up.
 147    :    // @param reloc_values the map to which relocation--target pairs are
 148    :    // to be added.
 149    :    // @returns true on success, false on error.
 150    :    bool ReadRelocs(const RelocSet& relocs, RelocMap* reloc_values) const;
 151    :  
 152    :    // Decode import information from the image.
 153    :    //
 154    :    // @param imports where to place the decoded imports.
 155    :    // @returns true on success, false on error.
 156    :    bool DecodeImports(ImportDllVector* imports) const;
 157    :  
 158    :    // Decode export information from the image.
 159    :    //
 160    :    // @param exports where to place the decoded exports.
 161    :    // @returns true on success, false on error.
 162    :    bool DecodeExports(ExportInfoVector* exports) const;
 163    :  
 164    :    // Translate a relative address to an absolute address, based on the
 165    :    // preferred loading address of this PE file.
 166    :    //
 167    :    // @param rel the address to translate.
 168    :    // @param abs where to place the resulting address.
 169    :    // @returns true on success, false on error.
 170    :    bool Translate(RelativeAddress rel, AbsoluteAddress* abs) const;
 171    :  
 172    :    // Translate an absolute address to a relative address, based on the
 173    :    // preferred loading address of this PE file.
 174    :    //
 175    :    // @param abs the address to translate.
 176    :    // @param rel where to place the resulting address.
 177    :    // @returns true on success, false on error.
 178    :    bool Translate(AbsoluteAddress abs, RelativeAddress* rel) const;
 179    :  
 180    :    // Translate a file offset present in the on-disk file to the
 181    :    // relative address it maps to at run-time.
 182    :    //
 183    :    // @param offs the file offset to translate.
 184    :    // @param rel where to place the resulting address.
 185    :    // @returns true on success, false on error.
 186    :    bool Translate(FileOffsetAddress offs, RelativeAddress* rel) const;
 187    :  
 188    :    // Translate a relative address to the file offset it is mapped from
 189    :    // in the on-disk file.
 190    :    //
 191    :    // @param rel the address to translate.
 192    :    // @param offs where to place the resulting address.
 193    :    // @returns true on success, false on error.
 194    :    bool Translate(RelativeAddress rel, FileOffsetAddress* offs) const;
 195    :  
 196    :    // Absolute address wrappers around the same-named methods from
 197    :    // PECoffFile, which deal with relative addresses. Each of the
 198    :    // following method is equivalent to applying Translate() to the
 199    :    // absolute address then calling the corresponding RVA-based method.
 200    :    //
 201    :    // @see pe::PECoffFile @{
 202    :    bool ReadImage(AbsoluteAddress addr, void* data, size_t len) const;
 203    :    bool ReadImageString(AbsoluteAddress addr, std::string* str) const;
 204    :    const uint8* GetImageData(AbsoluteAddress addr, size_t len) const;
 205    :    uint8* GetImageData(AbsoluteAddress addr, size_t len);
 206    :    bool Contains(AbsoluteAddress addr, size_t len) const;
 207    :    size_t GetSectionIndex(AbsoluteAddress addr, size_t len) const;
 208    :    const IMAGE_SECTION_HEADER* GetSectionHeader(AbsoluteAddress addr,
 209    :                                                 size_t len) const;
 210    :    // @}
 211    :  
 212    :    // Retrieve the index of the first section with the specified name.
 213    :    //
 214    :    // @param name the name of the section to look up.
 215    :    // @returns the index of the section, or kInvalidSection if none is
 216    :    // found.
 217    :    size_t GetSectionIndex(const char* name) const;
 218    :  
 219    :    // Retrieve a pointer to the header structure of the first section
 220    :    // with the specified name.
 221    :    //
 222    :    // @param name the name of the section to look up.
 223    :    // @returns a pointer to the header structure of the section, or
 224    :    // NULL if none is found.
 225    :    const IMAGE_SECTION_HEADER* GetSectionHeader(const char* name) const;
 226    :  
 227    :    // @returns a pointer to the DOS header structure of this PE file.
 228  E :    const IMAGE_DOS_HEADER* dos_header() const {
 229  E :      return dos_header_;
 230  E :    }
 231    :  
 232    :    // @returns a pointer to the NT headers structure of this PE file.
 233  E :    const IMAGE_NT_HEADERS* nt_headers() const {
 234  E :      return nt_headers_;
 235  E :    }
 236    :  
 237    :    // Subtract the preferred loading address of this PE file from the
 238    :    // specified displacement.
 239    :    //
 240    :    // @param abs_disp the value to translate.
 241    :    // @returns the new offset, relative to the preferred loading
 242    :    // address.
 243  E :    uint32 PEFile::AbsToRelDisplacement(uint32 abs_disp) const {
 244  E :      return abs_disp - nt_headers_->OptionalHeader.ImageBase;
 245  E :    }
 246    :  
 247    :   private:
 248    :    // Read all NT headers, including common COFF headers. Insert
 249    :    // a range covering all headers.
 250    :    //
 251    :    // @param file the input file stream.
 252    :    // @returns true on success, false on error.
 253    :    bool ReadHeaders(FILE* file);
 254    :  
 255    :    const IMAGE_DOS_HEADER* dos_header_;
 256    :    const IMAGE_NT_HEADERS* nt_headers_;
 257    :  
 258    :    DISALLOW_COPY_AND_ASSIGN(PEFile);
 259    :  };
 260    :  
 261    :  // A parsed PE file signature; a signature describes some module. It
 262    :  // offers access to the exploded components of the PE signature,
 263    :  // comparison, and serialization.
 264    :  struct PEFile::Signature {
 265    :    // Construct a default all-zero signature.
 266  E :    Signature() : module_size(0), module_time_date_stamp(0), module_checksum(0) {
 267  E :    }
 268    :  
 269    :    // Construct a signature from the specified module information.
 270    :    //
 271    :    // @param module_info the module information from which to extract
 272    :    // signature data.
 273    :    explicit Signature(const sym_util::ModuleInformation& module_info)
 274    :        : path(module_info.image_file_name),
 275    :          base_address(module_info.base_address),
 276    :          module_size(module_info.module_size),
 277    :          module_time_date_stamp(module_info.time_date_stamp),
 278  E :          module_checksum(module_info.image_checksum) {
 279  E :    }
 280    :  
 281    :    // The original module path, kept for convenience. This should
 282    :    // always be an absolute path.
 283    :    //
 284    :    // TODO(chrisha): Check that the path is absolute at all sites where this
 285    :    //     path is used.
 286    :    std::wstring path;
 287    :  
 288    :    // The four signature components.
 289    :    // @{
 290    :    // The preferred loading address of the module.
 291    :    AbsoluteAddress base_address;
 292    :  
 293    :    // The on-disk size in bytes of the module file.
 294    :    size_t module_size;
 295    :  
 296    :    // The on-disk modification time of the module file.
 297    :    uint32 module_time_date_stamp;
 298    :  
 299    :    // A 32-bit checksum of the module file.
 300    :    uint32 module_checksum;
 301    :    // @}
 302    :  
 303    :    // Compare the specified signature with this one. Signatures are
 304    :    // consistent with one another if their four components match; paths
 305    :    // may differ.
 306    :    //
 307    :    // @param signature the signature to compare to.
 308    :    // @returns true if the signatures are consistent, false otherwise.
 309    :    bool IsConsistent(const Signature& signature) const;
 310    :  
 311    :    // Compare the specified signature with this one in the same way as
 312    :    // IsConsistent(), except that in addition signatures may differ.
 313    :    //
 314    :    // @param signature the signature to compare to.
 315    :    // @returns true if the signatures are consistent except possibly
 316    :    // for the signature, false otherwise.
 317    :    bool IsConsistentExceptForChecksum(const Signature& signature) const;
 318    :  
 319    :    // Compare the specified signature with this one. Signatures are
 320    :    // equal if their paths are the same and they are consistent.
 321    :    //
 322    :    // @param signature the signature to compare to.
 323    :    // @returns true if the signatures are equal, false otherwise.
 324    :    // @note We need an equality operator for serialization unittests.
 325  E :    bool operator==(const Signature& signature) const {
 326  E :      return path == signature.path && IsConsistent(signature);
 327  E :    }
 328    :  
 329    :    // Serialize this signature to @p out_archive.
 330    :    //
 331    :    // @param out_archive the archive to serialize to.
 332    :    // @returns true on success, false on error.
 333    :    bool Save(core::OutArchive* out_archive) const;
 334    :  
 335    :    // Deserializea a signature from @p in_archive, replacing the
 336    :    // contents of this structure.
 337    :    //
 338    :    // @param in_archive the archive to deserialize from.
 339    :    // @returns true on success, false on error.
 340    :    bool Load(core::InArchive* in_archive);
 341    :  };
 342    :  
 343    :  // A structure exposing information about a single export.
 344    :  struct PEFile::ExportInfo {
 345    :    // The address of the exported function.
 346    :    RelativeAddress function;
 347    :  
 348    :    // The name of the export, if any.
 349    :    std::string name;
 350    :  
 351    :    // The export forward string, if any.
 352    :    std::string forward;
 353    :  
 354    :    // The export ordinal.
 355    :    uint16 ordinal;
 356    :  };
 357    :  
 358    :  // A structure exposing information about a single import.
 359    :  struct PEFile::ImportInfo {
 360    :    // Construct an ImportInfo structure from its components.
 361    :    //
 362    :    // @param h the ordinal hint.
 363    :    // @param o the function ordinal.
 364    :    // @param n the function name.
 365    :    ImportInfo(uint16 h, uint16 o, const char* n)
 366    :        : hint(h),
 367    :          ordinal(o),
 368  E :          function(n) {
 369  E :    }
 370    :  
 371    :    // Construct an ImportInfo structure for a named function with no
 372    :    // ordinal information.
 373    :    //
 374    :    // @param function_name the function name.
 375    :    explicit ImportInfo(const char* function_name)
 376    :        : hint(0),
 377    :          ordinal(0),
 378    :          function(function_name) {
 379    :    }
 380    :  
 381    :    // Construct an ImportInfo structure for a function referenced by
 382    :    // ordinal.
 383    :    //
 384    :    // @param function_ordinal the function ordinal.
 385    :    explicit ImportInfo(uint16 function_ordinal)
 386    :        : hint(0),
 387    :          ordinal(function_ordinal) {
 388    :    }
 389    :  
 390    :    // Construct a default all-zero ImportInfo structure.
 391  E :    ImportInfo() : hint(0), ordinal(0) {
 392  E :    }
 393    :  
 394    :    // Compare the specified structure with this one. ImportInfo
 395    :    // structures are equal if their components are equal.
 396    :    //
 397    :    // @param o the structure to compare to.
 398    :    // @returns true if the signatures are equal, false otherwise.
 399  E :    bool operator==(const ImportInfo& o) const {
 400  E :      return hint == o.hint && ordinal == o.ordinal && function == o.function;
 401  E :    }
 402    :  
 403    :    // The loader ordinal hint for this import.
 404    :    uint16 hint;
 405    :  
 406    :    // The ordinal of the function if the function field is empty.
 407    :    uint16 ordinal;
 408    :  
 409    :    // The name of the function, or the empty string for imports by
 410    :    // ordinal.
 411    :    std::string function;
 412    :  };
 413    :  
 414    :  // A structure holding information about all imports from a given DLL.
 415    :  struct PEFile::ImportDll {
 416    :    // Construct a default empty ImportDll structure.
 417  E :    ImportDll() {
 418  E :      memset(&desc, 0, sizeof(desc));
 419  E :      desc.ForwarderChain = -1;
 420  E :    }
 421    :  
 422    :    // The import descriptor.
 423    :    IMAGE_IMPORT_DESCRIPTOR desc;
 424    :  
 425    :    // Name of the DLL imported.
 426    :    std::string name;
 427    :  
 428    :    // A vector of ImportInfo structures, one for each imported
 429    :    // function.
 430    :    ImportInfoVector functions;
 431    :  };
 432    :  
 433    :  }  // namespace pe
 434    :  
 435    :  #endif  // SYZYGY_PE_PE_FILE_H_

Coverage information generated Wed Dec 11 11:34:16 2013.